diff --git a/ExpandCab.ps1 b/ExpandCab.ps1 new file mode 100644 index 0000000..99ae867 --- /dev/null +++ b/ExpandCab.ps1 @@ -0,0 +1,9 @@ +Param([string]$sSourcePath, [string]$sDestinationPath) + +$oShell = New-Object -Comobject "Shell.Application" +if (!$?) { + $(Throw "unable to create Shell.Application object") +} +$oCab = $oShell.Namespace($sSourcePath).items() +$oDestinationFolder = $oShell.Namespace($sDestinationPath) +$oDestinationFolder.CopyHere($oCab) diff --git a/PDBTypeCopy.py b/PDBTypeCopy.py new file mode 100644 index 0000000..4f3f00d --- /dev/null +++ b/PDBTypeCopy.py @@ -0,0 +1,22 @@ +import os, sys; +from fbDownloadPDB import fbDownloadPDB; +from fbCopyPDBTypeData import fbCopyPDBTypeData; + +if __name__ == "__main__": + if (len(sys.argv) != 5): + print "Usage: %s [file] [from hash] [to hash] [symbols folder path]" + sys.exit(1); + + sFileName, sFromHash, sToHash, sSymbolCacheFolderPath = sys.argv[1:]; + if (not fbDownloadPDB(sFileName, sFromHash, sSymbolCacheFolderPath)): + sys.exit(1); + if (not fbDownloadPDB(sFileName, sToHash, sSymbolCacheFolderPath)): + sys.exit(1); + + sPDBFromFilePath = os.path.join(sSymbolCacheFolderPath, sFileName, sFromHash, sFileName); + sPDBToFilePath = os.path.join(sSymbolCacheFolderPath, sFileName, sToHash, sFileName); + if (not fbCopyPDBTypeData(sPDBFromFilePath, sPDBToFilePath)): + sys.exit(1); + + print "+ PDB types copied successfully."; + diff --git a/fbCopyPDBTypeData.py b/fbCopyPDBTypeData.py new file mode 100644 index 0000000..58106d8 --- /dev/null +++ b/fbCopyPDBTypeData.py @@ -0,0 +1,22 @@ +import os; +from pdb_type_theft import PDB7, TPI_STREAM; + +def fbCopyPDBTypeData(sPDBFromFilePath, sPDBToFilePath): + print "* Copying PDB type data..."; + with open(sPDBFromFilePath, 'rb') as hPdbFromFile: + oFromPDB = PDB7(hPdbFromFile); + + with open(sPDBToFilePath, 'rb') as hPDBToFile: + oToPDB = PDB7(hPDBToFile); + uFromTPIHashStream = oFromPDB.streams[TPI_STREAM].stream; + uToTPIHashStream = oToPDB.streams[TPI_STREAM].stream; + + oToPDB.streams[TPI_STREAM] = oFromPDB.streams[TPI_STREAM]; + oToPDB.streams[TPI_STREAM].stream = uToTPIHashStream; + oToPDB.streams[TPI_STREAM]._update_data(); + oToPDB.streams[uToTPIHashStream] = oFromPDB.streams[uFromTPIHashStream]; + + print "* Saving updated PDB file..."; + with open(sPDBToFilePath, 'wb') as hPDBToFile: + oToPDB.dump(hPDBToFile) + print " * PDB file size: %d bytes." % (os.path.getsize(sPDBToFilePath)); diff --git a/fbDownloadPDB.py b/fbDownloadPDB.py new file mode 100644 index 0000000..d5bad90 --- /dev/null +++ b/fbDownloadPDB.py @@ -0,0 +1,64 @@ +import os, re, subprocess, sys, urllib, urllib2; + +sPowershellEXEPath = os.path.join(os.getenv("SystemRoot"), "System32", "Windowspowershell", "v1.0", "powershell.exe"); +sExpendsCabPS1Path = os.path.abspath(os.path.join(os.path.dirname("__file__"), "ExpandCab.ps1")); + +def fbDownloadPDB(sFileName, sHash, sSymbolCacheFolderPath): + sPDBFolderPath = os.path.join(sSymbolCacheFolderPath, sFileName, sHash); + sPDBFilePath = os.path.join(sPDBFolderPath, sFileName); +# if (os.path.isfile(sPDBFilePath)): +# print "* File already exists in local cache"; +# return True; + + print "* Downloading PDB Cab file for %s @ %s..." % (sFileName, sHash); + sCabFileURL = "http://msdl.microsoft.com/download/symbols/%s/%s/%s" % (sFileName, sHash, sFileName[:-1] + "_"); + oCabFileRequest = urllib2.Request(sCabFileURL, headers = {"User-Agent": "Microsoft-Symbol-Server/6.6.0007.5"}); + sTempCabFile = urllib2.urlopen(oCabFileRequest).read(); + print " * Cab file size: %d bytes." % (len(sTempCabFile)); + sTempCabFilePath = os.path.join(os.environ["TEMP"], "%s@%s.cab" % (sFileName, sHash)); + open(sTempCabFilePath, "wb").write(sTempCabFile); + + if (not os.path.isdir(sPDBFolderPath)): + os.makedirs(sPDBFolderPath); + + sPDBBackupFilePath = None; + # Back up current file if any + if (os.path.isfile(sPDBFilePath)): + sPDBBackupFilePath = os.path.join(sPDBFolderPath, "#old#%s" % sFileName); + # Delete existing back up if any + if (os.path.isfile(sPDBBackupFilePath)): + os.remove(sPDBBackupFilePath); + # Back up current file + os.rename(sPDBFilePath, sPDBBackupFilePath); + print "* Extracting PDB Cab file to %s..." % sPDBFolderPath; + if (subprocess.call([sPowershellEXEPath, sExpendsCabPS1Path, sTempCabFilePath, sPDBFolderPath])): + print "- Extraction failed."; + # Delete failed PDB file if any + if (os.path.isfile(sPDBFilePath)): + os.remove(sPDBFilePath); + # Restore back up if any + if (sPDBBackupFilePath and os.path.isfile(sPDBBackupFilePath)): + os.rename(sPDBBackupFilePath, sPDBFilePath); + return False; + + if (not os.path.isfile(sPDBFilePath)): + print "- Extraction did not reveal a %s file as expected." % sFileName; + # Restore back up if any + if (sPDBBackupFilePath and os.path.isfile(sPDBBackupFilePath)): + os.rename(sPDBBackupFilePath, sPDBFilePath); + return False; + + # Remove back up if any + if (sPDBBackupFilePath and os.path.isfile(sPDBBackupFilePath)): + os.remove(sPDBBackupFilePath); + + print " * PDB file size: %d bytes." % (os.path.getsize(sPDBFilePath)); + return True; + +if __name__ == "__main__": + if (len(sys.argv) != 4): + print "Usage: %s [file] [hash] [symbols folder path]" + sys.exit(1); + sFileName, sHash, sSymbolCacheFolderPath = sys.argv[1:]; + if (not fbDownloadPDB(sFileName, sHash, sSymbolCacheFolderPath)): + sys.exit(1); \ No newline at end of file