Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: ea9b06d4fc
Fetching contributors…

Cannot retrieve contributors at this time

572 lines (478 sloc) 19.865 kb
// This file is distributed under a BSD license. See LICENSE.txt for details.
#include "_types.hpp"
#include "debuginfo.hpp"
#include "pdbfile.hpp"
#include <malloc.h>
#include "windows.h"
#include "ole2.h"
/****************************************************************************/
// I don't want to use the complete huge dia2.h headers (>350k), so here
// goes the minimal version...
enum SymTagEnum
{
SymTagNull,
SymTagExe,
SymTagCompiland,
SymTagCompilandDetails,
SymTagCompilandEnv,
SymTagFunction,
SymTagBlock,
SymTagData,
SymTagAnnotation,
SymTagLabel,
SymTagPublicSymbol,
SymTagUDT,
SymTagEnum,
SymTagFunctionType,
SymTagPointerType,
SymTagArrayType,
SymTagBaseType,
SymTagTypedef,
SymTagBaseClass,
SymTagFriend,
SymTagFunctionArgType,
SymTagFuncDebugStart,
SymTagFuncDebugEnd,
SymTagUsingNamespace,
SymTagVTableShape,
SymTagVTable,
SymTagCustom,
SymTagThunk,
SymTagCustomType,
SymTagManagedType,
SymTagDimension,
SymTagMax
};
class IDiaEnumSymbols;
class IDiaEnumSymbolsByAddr;
class IDiaEnumTables;
class IDiaDataSource;
class IDiaSession;
class IDiaSymbol;
class IDiaSectionContrib;
class IDiaTable;
// not transcribed here:
class IDiaSourceFile;
class IDiaEnumSourceFiles;
class IDiaEnumLineNumbers;
class IDiaEnumDebugStreams;
class IDiaEnumInjectedSources;
class IDiaEnumSymbols : public IUnknown
{
public:
virtual HRESULT __stdcall get__NewEnum(IUnknown **ret) = 0;
virtual HRESULT __stdcall get_Count(LONG *ret) = 0;
virtual HRESULT __stdcall Item(DWORD index,IDiaSymbol **symbol) = 0;
virtual HRESULT __stdcall Next(ULONG celt,IDiaSymbol **rgelt,ULONG *pceltFetched) = 0;
virtual HRESULT __stdcall Skip(ULONG celt) = 0;
virtual HRESULT __stdcall Reset() = 0;
virtual HRESULT __stdcall Clone(IDiaEnumSymbols **penum) = 0;
};
class IDiaEnumSymbolsByAddr : public IUnknown
{
public:
virtual HRESULT __stdcall symbolByAddr(DWORD isect,DWORD offset,IDiaSymbol** ppSymbol) = 0;
virtual HRESULT __stdcall symbolByRVA(DWORD relativeVirtualAddress,IDiaSymbol** ppSymbol) = 0;
virtual HRESULT __stdcall symbolByVA(ULONGLONG virtualAddress,IDiaSymbol** ppSymbol) = 0;
virtual HRESULT __stdcall Next(ULONG celt,IDiaSymbol ** rgelt,ULONG* pceltFetched) = 0;
virtual HRESULT __stdcall Prev(ULONG celt,IDiaSymbol ** rgelt,ULONG * pceltFetched) = 0;
virtual HRESULT __stdcall Clone(IDiaEnumSymbolsByAddr **ppenum) = 0;
};
class IDiaEnumTables : public IUnknown
{
public:
virtual HRESULT __stdcall get__NewEnum(IUnknown **ret) = 0;
virtual HRESULT __stdcall get_Count(LONG *ret) = 0;
virtual HRESULT __stdcall Item(VARIANT index,IDiaTable **table) = 0;
virtual HRESULT __stdcall Next(ULONG celt,IDiaTable ** rgelt,ULONG *pceltFetched) = 0;
virtual HRESULT __stdcall Skip(ULONG celt) = 0;
virtual HRESULT __stdcall Reset() = 0;
virtual HRESULT __stdcall Clone(IDiaEnumTables **ppenum) = 0;
};
class IDiaDataSource : public IUnknown
{
public:
virtual HRESULT __stdcall get_lastError(BSTR *ret) = 0;
virtual HRESULT __stdcall loadDataFromPdb(LPCOLESTR pdbPath) = 0;
virtual HRESULT __stdcall loadAndValidateDataFromPdb(LPCOLESTR pdbPath,GUID *pcsig70,DWORD sig,DWORD age) = 0;
virtual HRESULT __stdcall loadDataForExe(LPCOLESTR executable,LPCOLESTR searchPath,IUnknown *pCallback) = 0;
virtual HRESULT __stdcall loadDataFromIStream(IStream *pIStream) = 0;
virtual HRESULT __stdcall openSession(IDiaSession **ppSession) = 0;
};
class IDiaSession : public IUnknown
{
public:
virtual HRESULT __stdcall get_loadAddress(ULONGLONG *ret) = 0;
virtual HRESULT __stdcall put_loadAddress(ULONGLONG val) = 0;
virtual HRESULT __stdcall get_globalScape(IDiaSymbol **sym) = 0;
virtual HRESULT __stdcall getEnumTables(IDiaEnumTables** ppEnumTables) = 0;
virtual HRESULT __stdcall getSymbolsByAddr(IDiaEnumSymbolsByAddr** ppEnumbyAddr) = 0;
virtual HRESULT __stdcall findChildren(IDiaSymbol* parent,enum SymTagEnum symtag,LPCOLESTR name,DWORD compareFlags,IDiaEnumSymbols** ppResult) = 0;
virtual HRESULT __stdcall findSymbolByAddr(DWORD isect,DWORD offset,enum SymTagEnum symtag,IDiaSymbol** ppSymbol) = 0;
virtual HRESULT __stdcall findSymbolByRVA(DWORD rva,enum SymTagEnum symtag,IDiaSymbol** ppSymbol) = 0;
virtual HRESULT __stdcall findSymbolByVA(ULONGLONG va,enum SymTagEnum symtag,IDiaSymbol** ppSymbol) = 0;
virtual HRESULT __stdcall findSymbolByToken(ULONG token,enum SymTagEnum symtag,IDiaSymbol** ppSymbol) = 0;
virtual HRESULT __stdcall symsAreEquiv(IDiaSymbol* symbolA,IDiaSymbol* symbolB) = 0;
virtual HRESULT __stdcall symbolById(DWORD id,IDiaSymbol** ppSymbol) = 0;
virtual HRESULT __stdcall findSymbolByRVAEx(DWORD rva,enum SymTagEnum symtag,IDiaSymbol** ppSymbol,long* displacement) = 0;
virtual HRESULT __stdcall findSymbolByVAEx(ULONGLONG va,enum SymTagEnum symtag,IDiaSymbol** ppSymbol,long* displacement) = 0;
virtual HRESULT __stdcall findFile(IDiaSymbol* pCompiland,LPCOLESTR name,DWORD compareFlags,IDiaEnumSourceFiles** ppResult) = 0;
virtual HRESULT __stdcall findFileById(DWORD uniqueId,IDiaSourceFile** ppResult) = 0;
virtual HRESULT __stdcall findLines(IDiaSymbol* compiland,IDiaSourceFile* file,IDiaEnumLineNumbers** ppResult) = 0;
virtual HRESULT __stdcall findLinesByAddr(DWORD seg,DWORD offset,DWORD length,IDiaEnumLineNumbers** ppResult) = 0;
virtual HRESULT __stdcall findLinesByRVA(DWORD rva,DWORD length,IDiaEnumLineNumbers** ppResult) = 0;
virtual HRESULT __stdcall findLinesByVA(ULONGLONG va,DWORD length,IDiaEnumLineNumbers** ppResult) = 0;
virtual HRESULT __stdcall findLinesByLinenum(IDiaSymbol* compiland,IDiaSourceFile* file,DWORD linenum,DWORD column,IDiaEnumLineNumbers** ppResult) = 0;
virtual HRESULT __stdcall findInjectedSource(LPCOLESTR srcFile,IDiaEnumInjectedSources** ppResult) = 0;
virtual HRESULT __stdcall getEnumDebugStreams(IDiaEnumDebugStreams** ppEnumDebugStreams) = 0;
};
class IDiaSymbol : public IUnknown
{
public:
virtual HRESULT __stdcall get_symIndexId(DWORD *ret) = 0;
virtual HRESULT __stdcall get_symTag(DWORD *ret) = 0;
virtual HRESULT __stdcall get_name(BSTR *ret) = 0;
virtual HRESULT __stdcall get_lexicalParent(IDiaSymbol **ret) = 0;
virtual HRESULT __stdcall get_classParent(IDiaSymbol **ret) = 0;
virtual HRESULT __stdcall get_type(IDiaSymbol **ret) = 0;
virtual HRESULT __stdcall get_dataKind(DWORD *ret) = 0;
virtual HRESULT __stdcall get_locationType(DWORD *ret) = 0;
virtual HRESULT __stdcall get_addressSection(DWORD *ret) = 0;
virtual HRESULT __stdcall get_addressOffset(DWORD *ret) = 0;
virtual HRESULT __stdcall get_relativeVirtualAddress(DWORD *ret) = 0;
virtual HRESULT __stdcall get_virtualAddress(ULONGLONG *ret) = 0;
virtual HRESULT __stdcall get_registerId(DWORD *ret) = 0;
virtual HRESULT __stdcall get_offset(LONG *ret) = 0;
virtual HRESULT __stdcall get_length(ULONGLONG *ret) = 0;
virtual HRESULT __stdcall get_slot(DWORD *ret) = 0;
virtual HRESULT __stdcall get_volatileType(BOOL *ret) = 0;
virtual HRESULT __stdcall get_constType(BOOL *ret) = 0;
virtual HRESULT __stdcall get_unalignedType(BOOL *ret) = 0;
virtual HRESULT __stdcall get_access(DWORD *ret) = 0;
virtual HRESULT __stdcall get_libraryName(BSTR *ret) = 0;
virtual HRESULT __stdcall get_platform(DWORD *ret) = 0;
virtual HRESULT __stdcall get_language(DWORD *ret) = 0;
virtual HRESULT __stdcall get_editAndContinueEnabled(BOOL *ret) = 0;
virtual HRESULT __stdcall get_frontEndMajor(DWORD *ret) = 0;
virtual HRESULT __stdcall get_frontEndMinor(DWORD *ret) = 0;
virtual HRESULT __stdcall get_frontEndBuild(DWORD *ret) = 0;
virtual HRESULT __stdcall get_backEndMajor(DWORD *ret) = 0;
virtual HRESULT __stdcall get_backEndMinor(DWORD *ret) = 0;
virtual HRESULT __stdcall get_backEndBuild(DWORD *ret) = 0;
virtual HRESULT __stdcall get_sourceFileName(BSTR *ret) = 0;
virtual HRESULT __stdcall get_unused(BSTR *ret) = 0;
virtual HRESULT __stdcall get_thunkOrdinal(DWORD *ret) = 0;
virtual HRESULT __stdcall get_thisAdjust(LONG *ret) = 0;
virtual HRESULT __stdcall get_virtualBaseOffset(DWORD *ret) = 0;
virtual HRESULT __stdcall get_virtual(BOOL *ret) = 0;
virtual HRESULT __stdcall get_intro(BOOL *ret) = 0;
virtual HRESULT __stdcall get_pure(BOOL *ret) = 0;
virtual HRESULT __stdcall get_callingConvention(DWORD *ret) = 0;
virtual HRESULT __stdcall get_value(VARIANT *ret) = 0;
virtual HRESULT __stdcall get_baseType(DWORD *ret) = 0;
virtual HRESULT __stdcall get_token(DWORD *ret) = 0;
virtual HRESULT __stdcall get_timeStamp(DWORD *ret) = 0;
virtual HRESULT __stdcall get_guid(GUID *ret) = 0;
virtual HRESULT __stdcall get_symbolsFileName(BSTR *ret) = 0;
virtual HRESULT __stdcall get_reference(BOOL *ret) = 0;
virtual HRESULT __stdcall get_count(DWORD *ret) = 0;
virtual HRESULT __stdcall get_bitPosition(DWORD *ret) = 0;
virtual HRESULT __stdcall get_arrayIndexType(IDiaSymbol **ret) = 0;
virtual HRESULT __stdcall get_packed(BOOL *ret) = 0;
virtual HRESULT __stdcall get_constructor(BOOL *ret) = 0;
virtual HRESULT __stdcall get_overloadedOperator(BOOL *ret) = 0;
virtual HRESULT __stdcall get_nested(BOOL *ret) = 0;
virtual HRESULT __stdcall get_hasNestedTypes(BOOL *ret) = 0;
virtual HRESULT __stdcall get_hasAssignmentOperator(BOOL *ret) = 0;
virtual HRESULT __stdcall get_hasCastOperator(BOOL *ret) = 0;
virtual HRESULT __stdcall get_scoped(BOOL *ret) = 0;
virtual HRESULT __stdcall get_virtualBaseClass(BOOL *ret) = 0;
virtual HRESULT __stdcall get_indirectVirtualBaseClass(BOOL *ret) = 0;
virtual HRESULT __stdcall get_virtualBasePointerOffset(LONG *ret) = 0;
virtual HRESULT __stdcall get_virtualTableShape(IDiaSymbol **ret) = 0;
virtual HRESULT __stdcall get_lexicalParentId(DWORD *ret) = 0;
virtual HRESULT __stdcall get_classParentId(DWORD *ret) = 0;
virtual HRESULT __stdcall get_typeId(DWORD *ret) = 0;
virtual HRESULT __stdcall get_arrayIndexTypeId(DWORD *ret) = 0;
virtual HRESULT __stdcall get_virtualTableShapeId(DWORD *ret) = 0;
virtual HRESULT __stdcall get_code(BOOL *ret) = 0;
virtual HRESULT __stdcall get_function(BOOL *ret) = 0;
virtual HRESULT __stdcall get_managed(BOOL *ret) = 0;
virtual HRESULT __stdcall get_msil(BOOL *ret) = 0;
virtual HRESULT __stdcall get_virtualBaseDispIndex(DWORD *ret) = 0;
virtual HRESULT __stdcall get_undecoratedName(BSTR *ret) = 0;
virtual HRESULT __stdcall get_age(DWORD *ret) = 0;
virtual HRESULT __stdcall get_signature(DWORD *ret) = 0;
virtual HRESULT __stdcall get_compilerGenerated(BOOL *ret) = 0;
virtual HRESULT __stdcall get_addressTaken(BOOL *ret) = 0;
virtual HRESULT __stdcall get_rank(DWORD *ret) = 0;
virtual HRESULT __stdcall get_lowerBound(IDiaSymbol **ret) = 0;
virtual HRESULT __stdcall get_upperBound(IDiaSymbol **ret) = 0;
virtual HRESULT __stdcall get_lowerBoundId(DWORD *ret) = 0;
virtual HRESULT __stdcall get_upperBoundId(DWORD *ret) = 0;
virtual HRESULT __stdcall get_dataBytes(DWORD cbData,DWORD *pcbData,BYTE data[]) = 0;
virtual HRESULT __stdcall findChildren(enum SymTagEnum symtag,LPCOLESTR name,DWORD compareFlags,IDiaEnumSymbols** ppResult) = 0;
virtual HRESULT __stdcall get_targetSection(DWORD *ret) = 0;
virtual HRESULT __stdcall get_targetOffset(DWORD *ret) = 0;
virtual HRESULT __stdcall get_targetRelativeVirtualAddress(DWORD *ret) = 0;
virtual HRESULT __stdcall get_targetVirtualAddress(ULONGLONG *ret) = 0;
virtual HRESULT __stdcall get_machineType(DWORD *ret) = 0;
virtual HRESULT __stdcall get_oemId(DWORD *ret) = 0;
virtual HRESULT __stdcall get_oemSymbolId(DWORD *ret) = 0;
virtual HRESULT __stdcall get_types(DWORD cTypes,DWORD *pcTypes,IDiaSymbol* types[]) = 0;
virtual HRESULT __stdcall get_typeIds(DWORD cTypes,DWORD *pcTypeIds,DWORD typeIds[]) = 0;
virtual HRESULT __stdcall get_objectPointerType(IDiaSymbol **ret) = 0;
virtual HRESULT __stdcall get_udtKind(DWORD *ret) = 0;
virtual HRESULT __stdcall get_undecoratedNameEx(DWORD undecorateOptions,BSTR *name) = 0;
};
class IDiaSectionContrib : public IUnknown
{
public:
virtual HRESULT __stdcall get_compiland(IDiaSymbol **ret) = 0;
virtual HRESULT __stdcall get_addressSection(DWORD *ret) = 0;
virtual HRESULT __stdcall get_addressOffset(DWORD *ret) = 0;
virtual HRESULT __stdcall get_relativeVirtualAddress(DWORD *ret) = 0;
virtual HRESULT __stdcall get_virtualAddress(ULONGLONG *ret) = 0;
virtual HRESULT __stdcall get_length(DWORD *ret) = 0;
virtual HRESULT __stdcall get_notPaged(BOOL *ret) = 0;
virtual HRESULT __stdcall get_code(BOOL *ret) = 0;
virtual HRESULT __stdcall get_initializedData(BOOL *ret) = 0;
virtual HRESULT __stdcall get_uninitializedData(BOOL *ret) = 0;
virtual HRESULT __stdcall get_remove(BOOL *ret) = 0;
virtual HRESULT __stdcall get_comdat(BOOL *ret) = 0;
virtual HRESULT __stdcall get_discardable(BOOL *ret) = 0;
virtual HRESULT __stdcall get_notCached(BOOL *ret) = 0;
virtual HRESULT __stdcall get_share(BOOL *ret) = 0;
virtual HRESULT __stdcall get_execute(BOOL *ret) = 0;
virtual HRESULT __stdcall get_read(BOOL *ret) = 0;
virtual HRESULT __stdcall get_write(BOOL *ret) = 0;
virtual HRESULT __stdcall get_dataCrc(DWORD *ret) = 0;
virtual HRESULT __stdcall get_relocationsaCrc(DWORD *ret) = 0;
virtual HRESULT __stdcall get_compilandId(DWORD *ret) = 0;
};
class IDiaTable : public IEnumUnknown
{
public:
virtual HRESULT __stdcall get__NewEnum(IUnknown **ret) = 0;
virtual HRESULT __stdcall get_name(BSTR *ret) = 0;
virtual HRESULT __stdcall get_Count(LONG *ret) = 0;
virtual HRESULT __stdcall Item(DWORD index,IUnknown **element) = 0;
};
class DECLSPEC_UUID("e60afbee-502d-46ae-858f-8272a09bd707") DiaSource;
class DECLSPEC_UUID("79f1bb5f-b66e-48e5-b6a9-1545c323ca3d") IDiaDataSource;
/****************************************************************************/
struct PDBFileReader::SectionContrib
{
DWORD Section;
DWORD Offset;
DWORD Length;
DWORD Compiland;
BOOL CodeFlag;
};
sU32 PDBFileReader::CompilandFromSectionOffset(sU32 sec,sU32 offs,sBool &codeFlag)
{
sInt l,r,x;
l = 0;
r = nContribs;
while(l < r)
{
x = (l + r) / 2;
const SectionContrib &cur = Contribs[x];
if(sec < cur.Section || sec == cur.Section && offs < cur.Offset)
r = x;
else if(sec > cur.Section || sec == cur.Section && offs >= cur.Offset + cur.Length)
l = x+1;
else // we got a winner
{
codeFlag = cur.CodeFlag;
return cur.Compiland;
}
}
// normally, this shouldn't happen!
return 0;
}
// helpers
static sChar *BStrToString(BSTR str,sChar *defString="")
{
if(!str)
{
sInt len = sGetStringLen(defString);
sChar *buffer = new sChar[len+1];
sCopyString(buffer,defString,len+1);
return buffer;
}
else
{
sInt len = SysStringLen(str);
sChar *buffer = new sChar[len+1];
for(sInt i=0;i<len;i++)
buffer[i] = (str[i] >= 32 && str[i] < 128) ? str[i] : '?';
buffer[len] = 0;
return buffer;
}
}
static sInt GetBStr(BSTR str,sChar *defString,DebugInfo &to)
{
sChar *normalStr = BStrToString(str);
sInt result = to.MakeString(normalStr);
delete[] normalStr;
return result;
}
void PDBFileReader::ProcessSymbol(IDiaSymbol *symbol,DebugInfo &to)
{
DWORD section,offset,rva;
enum SymTagEnum tag;
ULONGLONG length = 0;
sU32 compilandId;
IDiaSymbol *compiland = 0;
BSTR name = 0, sourceName = 0;
sBool codeFlag;
symbol->get_symTag((DWORD *) &tag);
symbol->get_relativeVirtualAddress(&rva);
symbol->get_length(&length);
symbol->get_addressSection(&section);
symbol->get_addressOffset(&offset);
// is the previous symbol desperately looking for a length? we can help!
if(DanglingLengthStart)
{
to.Symbols[to.Symbols.Count - 1].Size = rva - DanglingLengthStart;
DanglingLengthStart = 0;
}
// get length from type for data
if(tag == SymTagData)
{
IDiaSymbol *type;
if(symbol->get_type(&type) == S_OK)
{
type->get_length(&length);
type->Release();
}
// if length still zero, just guess and take number of bytes between
// this symbol and the next one.
if(!length)
DanglingLengthStart = rva;
}
compilandId = CompilandFromSectionOffset(section,offset,codeFlag);
Session->symbolById(compilandId,&compiland);
if(compiland)
compiland->get_name(&sourceName);
symbol->get_name(&name);
// fill out structure
sChar *nameStr = BStrToString(name,"<no name>");
sChar *sourceStr = BStrToString(sourceName,"<no source>");
if(tag == SymTagPublicSymbol)
{
length = 0;
DanglingLengthStart = rva;
}
DISymbol *outSym = to.Symbols.Add();
outSym->Name.Index = outSym->MangledName.Index = to.MakeString(nameStr);
outSym->FileNum = to.GetFileByName(sourceStr);
outSym->VA = rva;
outSym->Size = (sU32) length;
outSym->Class = codeFlag ? DIC_CODE : DIC_DATA;
outSym->NameSpNum = to.GetNameSpaceByName(nameStr);
// clean up
delete[] nameStr;
delete[] sourceStr;
if(compiland) compiland->Release();
if(sourceName) SysFreeString(sourceName);
if(name) SysFreeString(name);
}
void PDBFileReader::ReadEverything(DebugInfo &to)
{
ULONG celt;
Contribs = 0;
nContribs = 0;
DanglingLengthStart = 0;
// read section table
IDiaEnumTables *enumTables;
if(Session->getEnumTables(&enumTables) == S_OK)
{
VARIANT vIndex;
vIndex.vt = VT_BSTR;
vIndex.bstrVal = SysAllocString(L"Sections");
IDiaTable *secTable;
if(enumTables->Item(vIndex,&secTable) == S_OK)
{
LONG count;
secTable->get_Count(&count);
Contribs = new SectionContrib[count];
nContribs = 0;
IDiaSectionContrib *item;
while(SUCCEEDED(secTable->Next(1,(IUnknown **)&item,&celt)) && celt == 1)
{
SectionContrib &contrib = Contribs[nContribs++];
item->get_addressOffset(&contrib.Offset);
item->get_addressSection(&contrib.Section);
item->get_length(&contrib.Length);
item->get_compilandId(&contrib.Compiland);
item->get_execute(&contrib.CodeFlag);
item->Release();
}
secTable->Release();
}
SysFreeString(vIndex.bstrVal);
enumTables->Release();
}
// enumerate symbols by (virtual) address
IDiaEnumSymbolsByAddr *enumByAddr;
if(SUCCEEDED(Session->getSymbolsByAddr(&enumByAddr)))
{
IDiaSymbol *symbol;
// get first symbol to get first RVA (argh)
if(SUCCEEDED(enumByAddr->symbolByAddr(1,0,&symbol)))
{
DWORD rva;
if(symbol->get_relativeVirtualAddress(&rva) == S_OK)
{
symbol->Release();
// now, enumerate by rva.
if(SUCCEEDED(enumByAddr->symbolByRVA(rva,&symbol)))
{
do
{
ProcessSymbol(symbol,to);
symbol->Release();
if(FAILED(enumByAddr->Next(1,&symbol,&celt)))
break;
}
while(celt == 1);
}
}
else
symbol->Release();
}
enumByAddr->Release();
}
// clean up
delete[] Contribs;
}
/****************************************************************************/
sBool PDBFileReader::ReadDebugInfo(sChar *fileName,DebugInfo &to)
{
sBool readOk = sFALSE;
if(FAILED(CoInitialize(0)))
return sFALSE;
IDiaDataSource *source = 0;
CoCreateInstance(__uuidof(DiaSource),0,CLSCTX_INPROC_SERVER,
__uuidof(IDiaDataSource),(void**) &source);
if(source)
{
wchar_t wideFileName[260];
mbstowcs(wideFileName,fileName,260);
if(SUCCEEDED(source->loadDataForExe(wideFileName,0,0)))
{
if(SUCCEEDED(source->openSession(&Session)))
{
ReadEverything(to);
readOk = sTRUE;
Session->Release();
}
}
source->Release();
}
CoUninitialize();
return readOk;
}
/****************************************************************************/
Jump to Line
Something went wrong with that request. Please try again.