diff --git a/Library/x64/msdia140.dll b/Library/x64/msdia140.dll new file mode 100644 index 0000000..a465051 Binary files /dev/null and b/Library/x64/msdia140.dll differ diff --git a/Library/x64/symsrv.dll b/Library/x64/symsrv.dll new file mode 100644 index 0000000..5e3b5ad Binary files /dev/null and b/Library/x64/symsrv.dll differ diff --git a/Library/x86/msdia140.dll b/Library/x86/msdia140.dll new file mode 100644 index 0000000..adfd67f Binary files /dev/null and b/Library/x86/msdia140.dll differ diff --git a/Library/x86/symsrv.dll b/Library/x86/symsrv.dll new file mode 100644 index 0000000..4d83891 Binary files /dev/null and b/Library/x86/symsrv.dll differ diff --git a/Source/PDB.cpp b/Source/PDB.cpp index 0c34f61..1448160 100644 --- a/Source/PDB.cpp +++ b/Source/PDB.cpp @@ -1,6 +1,8 @@ #include "PDB.h" +#include "PDBCallback.h" #include // IDia* interfaces +#include #include @@ -54,7 +56,7 @@ SymbolModuleBase::SymbolModuleBase() , m_Session(nullptr) , m_GlobalSymbol(nullptr) { - HRESULT hr = CoInitialize(NULL); + HRESULT hr = CoInitialize(nullptr); assert(hr == S_OK); } @@ -68,24 +70,69 @@ SymbolModuleBase::Open( // Obtain access to the provider // - HRESULT HResult; + HRESULT HResult = S_OK; + auto PDBSearchPath = L"Srv*.\\Symbols*https://msdl.microsoft.com/download/symbols"; + char FileExt[MAX_PATH] = { 0 }; HResult = CoCreateInstance( __uuidof(DiaSource), - NULL, + nullptr, CLSCTX_INPROC_SERVER, __uuidof(IDiaDataSource), (void**)&m_DataSource ); + // Retry with direct export call + if (HResult == REGDB_E_CLASSNOTREG) + { + HMODULE HMod = LoadLibraryW(L"msdia140.dll"); + + if (!HMod) + { + HResult = HRESULT_FROM_WIN32(GetLastError()); + return FALSE; + } + + auto DllGetClassObject = reinterpret_cast(GetProcAddress(HMod, "DllGetClassObject")); + + if (!DllGetClassObject) + { + HResult = HRESULT_FROM_WIN32(GetLastError()); + return FALSE; + } + + CComPtr ClassFactory; + HResult = DllGetClassObject(__uuidof(DiaSource), __uuidof(IClassFactory), &ClassFactory); + + if (FAILED(HResult)) + { + return FALSE; + } + + HResult = ClassFactory->CreateInstance(nullptr, __uuidof(IDiaDataSource), (void**)&m_DataSource); + } + if (FAILED(HResult)) { return FALSE; } - HResult = m_DataSource->loadDataFromPdb( - string_converter.from_bytes(Path).c_str() + _splitpath_s(Path, nullptr, 0, nullptr, 0, nullptr, 0, FileExt, _countof(FileExt)); + + if (_stricmp(FileExt, ".pdb") == 0) + { + HResult = m_DataSource->loadDataFromPdb( + string_converter.from_bytes(Path).c_str() ); + } + else + { + PDBCallback Callback; + Callback.AddRef(); + + HResult = m_DataSource->loadDataForExe( + string_converter.from_bytes(Path).c_str(), PDBSearchPath, &Callback); + } if (FAILED(HResult)) { @@ -499,16 +546,17 @@ SymbolModule::BuildSymbolMap() { IDiaEnumSymbols* DiaSymbolEnumerator; - m_GlobalSymbol->findChildren(SymTagPublicSymbol, NULL, nsNone, &DiaSymbolEnumerator); - BuildFunctionSetFromEnumerator(DiaSymbolEnumerator); + if (SUCCEEDED(m_GlobalSymbol->findChildren(SymTagPublicSymbol, nullptr, nsNone, &DiaSymbolEnumerator))) + BuildFunctionSetFromEnumerator(DiaSymbolEnumerator); - m_GlobalSymbol->findChildren(SymTagEnum, NULL, nsNone, &DiaSymbolEnumerator); - BuildSymbolMapFromEnumerator(DiaSymbolEnumerator); + if (SUCCEEDED(m_GlobalSymbol->findChildren(SymTagEnum, nullptr, nsNone, &DiaSymbolEnumerator))) + BuildSymbolMapFromEnumerator(DiaSymbolEnumerator); - m_GlobalSymbol->findChildren(SymTagUDT, NULL, nsNone, &DiaSymbolEnumerator); - BuildSymbolMapFromEnumerator(DiaSymbolEnumerator); + if (SUCCEEDED(m_GlobalSymbol->findChildren(SymTagUDT, nullptr, nsNone, &DiaSymbolEnumerator))) + BuildSymbolMapFromEnumerator(DiaSymbolEnumerator); - DiaSymbolEnumerator->Release(); + if (DiaSymbolEnumerator) + DiaSymbolEnumerator->Release(); } const SymbolMap& @@ -590,7 +638,7 @@ SymbolModule::ProcessSymbolEnum( { IDiaEnumSymbols* DiaSymbolEnumerator; - if (FAILED(DiaSymbol->findChildren(SymTagNull, NULL, nsNone, &DiaSymbolEnumerator))) + if (FAILED(DiaSymbol->findChildren(SymTagNull, nullptr, nsNone, &DiaSymbolEnumerator))) { return; } @@ -605,8 +653,8 @@ SymbolModule::ProcessSymbolEnum( ULONG FetchedSymbolCount = 0; for (DWORD Index = 0; - SUCCEEDED(DiaSymbolEnumerator->Next(1, &DiaChildSymbol, &FetchedSymbolCount)) && (FetchedSymbolCount == 1); - Index++) + SUCCEEDED(DiaSymbolEnumerator->Next(1, &DiaChildSymbol, &FetchedSymbolCount)) && (FetchedSymbolCount == 1); + Index++) { SYMBOL_ENUM_FIELD* EnumValue = &Symbol->u.Enum.Fields[Index]; @@ -718,7 +766,7 @@ SymbolModule::ProcessSymbolFunction( IDiaEnumSymbols* DiaSymbolEnumerator; - if (FAILED(DiaSymbol->findChildren(SymTagNull, NULL, nsNone, &DiaSymbolEnumerator))) + if (FAILED(DiaSymbol->findChildren(SymTagNull, nullptr, nsNone, &DiaSymbolEnumerator))) { return; } @@ -734,8 +782,8 @@ SymbolModule::ProcessSymbolFunction( ULONG FetchedSymbolCount = 0; for (DWORD Index = 0; - SUCCEEDED(DiaSymbolEnumerator->Next(1, &DiaChildSymbol, &FetchedSymbolCount)) && (FetchedSymbolCount == 1); - Index++) + SUCCEEDED(DiaSymbolEnumerator->Next(1, &DiaChildSymbol, &FetchedSymbolCount)) && (FetchedSymbolCount == 1); + Index++) { SYMBOL* Argument; Argument = GetSymbol(DiaChildSymbol); @@ -773,7 +821,7 @@ SymbolModule::ProcessSymbolUdt( IDiaEnumSymbols* DiaSymbolEnumerator; - if (FAILED(DiaSymbol->findChildren(SymTagData, NULL, nsNone, &DiaSymbolEnumerator))) + if (FAILED(DiaSymbol->findChildren(SymTagData, nullptr, nsNone, &DiaSymbolEnumerator))) { return; } @@ -789,8 +837,8 @@ SymbolModule::ProcessSymbolUdt( ULONG FetchedSymbolCount = 0; for (DWORD Index = 0; - SUCCEEDED(DiaSymbolEnumerator->Next(1, &DiaChildSymbol, &FetchedSymbolCount)) && (FetchedSymbolCount == 1); - Index++) + SUCCEEDED(DiaSymbolEnumerator->Next(1, &DiaChildSymbol, &FetchedSymbolCount)) && (FetchedSymbolCount == 1); + Index++) { SYMBOL_UDT_FIELD* Member = &Symbol->u.Udt.Fields[Index]; @@ -1076,7 +1124,7 @@ PDB::GetBasicTypeString( if (TypeMap[n].BaseType == BaseType) { if (TypeMap[n].Length == Size || - TypeMap[n].Length == 0) + TypeMap[n].Length == 0) { return TypeMap[n].TypeString; } diff --git a/Source/PDBCallback.h b/Source/PDBCallback.h new file mode 100644 index 0000000..0123fb5 --- /dev/null +++ b/Source/PDBCallback.h @@ -0,0 +1,112 @@ +#pragma once + +#include // IDia* interfaces + +////////////////////////////////////////////////////////////////////////// +// PDBCallback +// + +class PDBCallback : public IDiaLoadCallback2 +{ + volatile unsigned long m_RefCount = 0; + +public: + + //IUnknown + ULONG STDMETHODCALLTYPE AddRef() override + { + return m_RefCount++; + } + ULONG STDMETHODCALLTYPE Release() override + { + if ((--m_RefCount) == 0) + { + delete this; + } + + return m_RefCount; + } + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID Rid, void **Interface) override + { + if (Interface == nullptr) + { + return E_INVALIDARG; + } + + if (Rid == __uuidof(IDiaLoadCallback2)) + { + *Interface = (IDiaLoadCallback2 *)this; + } + else if (Rid == __uuidof(IDiaLoadCallback)) + { + *Interface = (IDiaLoadCallback *)this; + } + else if (Rid == __uuidof(IUnknown)) + { + *Interface = (IUnknown *)this; + } + else + { + *Interface = nullptr; + } + + if (*Interface != nullptr) + { + AddRef(); + return S_OK; + } + + return E_NOINTERFACE; + } + + HRESULT STDMETHODCALLTYPE NotifyDebugDir( + BOOL fExecutable, + DWORD cbData, + BYTE data[]) override // really a const struct _IMAGE_DEBUG_DIRECTORY * + { + return S_OK; + } + HRESULT STDMETHODCALLTYPE NotifyOpenDBG( + LPCOLESTR dbgPath, + HRESULT resultCode) override + { + // wprintf(L"opening %s...\n", dbgPath); + return S_OK; + } + + HRESULT STDMETHODCALLTYPE NotifyOpenPDB( + LPCOLESTR pdbPath, + HRESULT resultCode) override + { + // wprintf(L"opening %s...\n", pdbPath); + return S_OK; + } + HRESULT STDMETHODCALLTYPE RestrictRegistryAccess() override + { + // return hr != S_OK to prevent querying the registry for symbol search paths + return S_OK; + } + HRESULT STDMETHODCALLTYPE RestrictSymbolServerAccess() override + { + // return hr != S_OK to prevent accessing a symbol server + return S_OK; + } + HRESULT STDMETHODCALLTYPE RestrictOriginalPathAccess() override + { + // return hr != S_OK to prevent querying the registry for symbol search paths + return S_OK; + } + HRESULT STDMETHODCALLTYPE RestrictReferencePathAccess() override + { + // return hr != S_OK to prevent accessing a symbol server + return S_OK; + } + HRESULT STDMETHODCALLTYPE RestrictDBGAccess() override + { + return S_OK; + } + HRESULT STDMETHODCALLTYPE RestrictSystemRootAccess() override + { + return S_OK; + } +}; \ No newline at end of file diff --git a/Source/PDBExtractor.cpp b/Source/PDBExtractor.cpp index bc6a0bc..1d39926 100644 --- a/Source/PDBExtractor.cpp +++ b/Source/PDBExtractor.cpp @@ -236,6 +236,10 @@ PDBExtractor::ParseParameters( std::ios::out ); } + else + { + m_Settings.PdbHeaderReconstructorSettings.OutputFile = nullptr; + } break; case 't': @@ -681,11 +685,11 @@ PDBExtractor::CloseOpenedFiles() if (m_Settings.TestFilename) { - delete m_Settings.PdbHeaderReconstructorSettings.TestFile; + delete m_Settings.PdbHeaderReconstructorSettings.TestFile; } if (m_Settings.OutputFilename) { - delete m_Settings.PdbHeaderReconstructorSettings.OutputFile; + delete m_Settings.PdbHeaderReconstructorSettings.OutputFile; } } diff --git a/Source/PDBHeaderReconstructor.h b/Source/PDBHeaderReconstructor.h index 38e60a6..e94d182 100644 --- a/Source/PDBHeaderReconstructor.h +++ b/Source/PDBHeaderReconstructor.h @@ -133,7 +133,7 @@ class PDBHeaderReconstructor OnAnonymousUdtBegin( UdtKind Kind, const SYMBOL_UDT_FIELD* FirstUdtField - ); + ) override; void OnAnonymousUdtEnd( diff --git a/Source/UdtFieldDefinition.h b/Source/UdtFieldDefinition.h index 4b141ba..5b74f75 100644 --- a/Source/UdtFieldDefinition.h +++ b/Source/UdtFieldDefinition.h @@ -124,7 +124,7 @@ class UdtFieldDefinition void SetMemberName( const CHAR* MemberName - ) + ) override { m_MemberName = MemberName ? MemberName : std::string(); } diff --git a/Source/pdbex.vcxproj b/Source/pdbex.vcxproj index dc487be..fdeeb8b 100644 --- a/Source/pdbex.vcxproj +++ b/Source/pdbex.vcxproj @@ -103,6 +103,10 @@ Console true + + copy $(SolutionDir)Library\$(PlatformTarget)\msdia140.dll $(OutDir) +copy $(SolutionDir)Library\$(PlatformTarget)\symsrv.dll $(OutDir) + @@ -118,6 +122,10 @@ Console true + + copy $(SolutionDir)Library\$(PlatformTarget)\msdia140.dll $(OutDir) +copy $(SolutionDir)Library\$(PlatformTarget)\symsrv.dll $(OutDir) + @@ -138,6 +146,10 @@ true true + + copy $(SolutionDir)Library\$(PlatformTarget)\msdia140.dll $(OutDir) +copy $(SolutionDir)Library\$(PlatformTarget)\symsrv.dll $(OutDir) + @@ -158,6 +170,10 @@ true true + + copy $(SolutionDir)Library\$(PlatformTarget)\msdia140.dll $(OutDir) +copy $(SolutionDir)Library\$(PlatformTarget)\symsrv.dll $(OutDir) + @@ -167,6 +183,7 @@ + diff --git a/Source/pdbex.vcxproj.filters b/Source/pdbex.vcxproj.filters index 34c49a9..5293e19 100644 --- a/Source/pdbex.vcxproj.filters +++ b/Source/pdbex.vcxproj.filters @@ -62,6 +62,9 @@ Header Files + + Header Files +