SymEnumSourceFiles get incomplete file names - c++

I was tring to use SymEnumSourceFiles to get the file name within the debugging module.But the file name as a parameter in the callback function seems incomplete. e.g. A file named"c:\program files\test\test.cpp" only showed "c:\program fi" in the FileName part of the PSOURCEFILE type parameter, and that's very wired.
Here is my code:
struct foo
{
static BOOL CALLBACK run( PSOURCEFILE pSourceFile, PVOID UserContext)
{
static TCHAR szFileName[MAX_PATH] = _T("");
if (_tcscmp(szFileName, pSourceFile->FileName))
{
_tcscpy(szFileName, pSourceFile->FileName);
}
return TRUE;
}
};
HANDLE hCurrentProcess = GetCurrentProcess();
SymInitialize(hCurrentProcess, NULL, FALSE);
DWORD64 BaseOfDll = SymLoadModule64(hCurrentProcess,
NULL,
(LPCSTR)_bstr_t(lpszFile),
NULL,0,0);
if(!SymEnumSourceFiles(hCurrentProcess, BaseOfDll, NULL, foo::run, (PVOID)pCallBack))
{
ATLTRACE(_T(__FUNCTION__) _T(" error:0x%x\n"), GetLastError());
}
SymUnloadModule64(hCurrentProcess, BaseOfDll);
SymCleanup(hCurrentProcess);
Can anyone tell me where I go wrong please?
PS. When I simply replace SymEnumSourceFiles with SymEnumLines and change the callback function, the file name I got is correct.

There used to be a bug with SymEnumSymbols where symbol name was not zero terminated, maybe this one is related. Try zeroing out the filename after copying it (pSourceFile->FileName[0] = 0;).

Try ANSI version of SymEnumSourceFiles. There seems to be a bug in SymEnumSourceFilesW function.

Related

How can i create a dir in Documents folder? [C++]

Im trying to create a directory , or a subdirectory in the Documents folder.
PWSTR ppszPath; // variable to receive the path memory block pointer.
HRESULT hr = SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &ppszPath);
std::wstring myPath;
if (SUCCEEDED(hr)) {
myPath = ppszPath; // make a local copy of the path
}
const wchar_t* str = myPath.c_str();
_bstr_t b(str);
int status = _mkdir(b+"\\New");
As you can see , I'm trying to create a new folder named "New" in Documents Folder.
The path to the documents is correct but the dir is not created.
This is using _bstr_t to avoid using Unicode, the new path is converted to ANSI and will be invalid unless the original path was ANSI, (or ASCII to be guaranteed)
Just pad L"\\New" and wide string functions to solve the problem.
You also have to free ppszPath as stated in documentation
std::wstring myPath;
wchar_t *ppszPath;
HRESULT hr = SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &ppszPath);
if (SUCCEEDED(hr))
{
myPath = ppszPath;
CoTaskMemFree(ppszPath);
}//error checking?
myPath += L"\\New";
std::filesystem::create_directory(myPath)
//or _wmkdir(myPath.c_str());
The std::filesystem::path class understands Unicode just fine, so you don’t need to mess with any helpers there. Also, you need to check both function results to determine success or failure:
bool success = false;
PWSTR documents_path = nullptr;
if (SUCCEEDED( SHGetKnownFolderPath( FOLDERID_Documents, 0, NULL, &documents_path ) ))
{
using namespace std::filesystem;
success = create_directory( path{ documents_path } / "new_folder" );
CoTaskMemFree( documents_path );
documents_path = nullptr;
}
The result of the operation is indicated in the variable success.
I would personally separate the functions of obtaining the user’s Documents folder and the directory creation into two separate functions, but the above will do just fine.

How can I give an old ActiveX control new GUIDs?

I am trying to modify an ActiveX control developed in Visual Studio 2008 to use it for a purpose for which it was not originally designed. I will be reusing at least 90% of its code. Therefore, I would like to begin by creating an identical control that uses different GUIDs. I tried to follow instructions I found here (a very old link, written in 2004), but when I tried to build my project, I got an assertion failure in ctlreg.cpp line 113. Then, I restored all my changed files back to their original states, and for each GUID is the .odl file, I searched for the GUID in my .cpp and .h files and changed it wherever I found it. I also made sure to change my major version number. I still get the assertion failure. What else should I be doing?
Here's the code from ctlreg.cpp from the start of the method containing the assertion to the assertion itself:
BOOL AFXAPI AfxOleRegisterTypeLib(HINSTANCE hInstance, REFGUID tlid,
LPCTSTR pszFileName, LPCTSTR pszHelpDir)
{
BOOL bSuccess = FALSE;
CStringW strPathNameW;
wchar_t *szPathNameW = strPathNameW.GetBuffer(_MAX_PATH);
::GetModuleFileNameW(hInstance, szPathNameW, _MAX_PATH);
strPathNameW.ReleaseBuffer();
LPTYPELIB ptlib = NULL;
// If a filename was specified, replace final component of path with it.
if (pszFileName != NULL)
{
int iBackslash = strPathNameW.ReverseFind('\\');
if (iBackslash != -1)
strPathNameW = strPathNameW.Left(iBackslash+1);
strPathNameW += pszFileName;
}
if (SUCCEEDED(LoadTypeLib(strPathNameW.GetString(), &ptlib)))
{
ASSERT_POINTER(ptlib, ITypeLib);
LPTLIBATTR pAttr;
GUID tlidActual = GUID_NULL;
if (SUCCEEDED(ptlib->GetLibAttr(&pAttr)))
{
ASSERT_POINTER(pAttr, TLIBATTR);
tlidActual = pAttr->guid;
ptlib->ReleaseTLibAttr(pAttr);
}
// Check that the guid of the loaded type library matches
// the tlid parameter.
ASSERT(IsEqualGUID(tlid, tlidActual));

Using GetFunctionInfo to get the name of a function from a FunctionID

I am writing a CLR profiler using the ICorProfilerInfo interface.
When using SetEnterLeaveFunctionHooks, the callback methods are passed a FunctionID.
How do I get the metadata (I am after the name in particular), of a function given this FunctionID?
An MSDN article suggests that the first call should be to GetFunctionInfo. The documentation for this function states:
The profiler code can call ICorProfilerInfo::GetModuleMetaData to obtain a metadata interface for a given module. The metadata token that is returned to the location referenced by pToken can then be used to access the metadata for the function.
It does not elaborate on the last sentence ('the metadata token ... can be used to access metadata for the function').
How does this work?
So far, I am doing the following:
void MyProfiler::EnterMethod(FunctionID functionID)
{
ClassID classId = 0;
ModuleID moduleId = 0;
mdToken metaDataToken = 0;
IMetaDataImport* metaDataImport = NULL;
// (m_info is ICorProfilerInfo3)
m_info->GetFunctionInfo(functionID, &classId, &moduleId, &metaDataToken);
m_info->GetModuleMetaData(moduleId, ofRead, IID_IMetaDataImport, (IUnknown**)&metaDataImport);
// What goes here?
}
I have tried to call GetTypeRefProps like this:
mdToken ptkResolutionScope;
WCHAR szName[1024];
ULONG cchName = 1024;
ULONG pchName;
HRESULT result = MetaDataImport->GetTypeRefProps(pToken, &ptkResolutionScope, szName, cchName, &pchName);
The final call returns S_FALSE, and does not populate szName.
GetTypeRefProps is only applicable when your token is a TypeRef token, GetFunctionInfo will give you a MethodDef token which requires you to use the GetMethodProps method.
metaDataImport->GetMethodProps(metaDataToken, NULL, szName, cchName, &pchName, NULL, NULL, NULL, NULL, NULL);

How to convert UnicodeString to BSTR?

I'm having a problem when calling OpenDatabase function (DAO). It's prototipe is:
virtual HRESULT STDMETHODCALLTYPE OpenDatabase(BSTR Name/*[in]*/, VARIANT Options/*[in,opt]*/,
VARIANT ReadOnly/*[in,opt]*/,
VARIANT Connect/*[in,opt]*/,
Dao_tlb::Database** ppDb/*[out,retval]*/) = 0; // [-1]
So, when I do this:
if(OpenDialog1->Execute() != true) return;
The selected filename is saved in OpenDialog1->FileName. Then I call the function above:
pDatabasePtr = pDBEngine->OpenDatabase(WideString(OpenDialog1->FileName).c_bstr(), myOpts, myRead, myCon);
and this works! But, the problem is when I try to set the filename to something else:
OpenDialog1->FileName = ParamStr(1); // OpenDatabase don't work in runtime - file not recognised!
or even set the filename inside a function:
pDatabasePtr = pDBEngine->OpenDatabase(WideString(L"SomeDB.mdb").c_bstr(), myOpts, myRead, myCon);
In both cases I get strange errors and never able to open a database. So, I probably convert UnicodeString/WideString to BSTR incorrectly.
So, why this function (OpenDatabase) works with
if(OpenDialog1->Execute() != true) return;
and does not work with
OpenDialog1->FileName = ParamStr(1);
How do I set the conversion correctly?
I found answer in here if anyone else needs it:
https://forums.embarcadero.com/thread.jspa?messageID=498776

How to display absolute path with device name of currently opened file

The first two lines of this code showing file name excluding device name like /Document/temp but I want
to show also device name like L"\Device\Harddisk0\DR0\Document\temp. I am using this code to call ObQueryNameString routine but it is showing NULL.
Please tell me what is wrong with code. I think memory is not allocating
properly.
PFILE_OBJECT pFileObject = IoGetCurrentIrpStackLocation(Irp)->FileObject;
if (pFileObject)
{
DbgPrint("FileName : %wZ\n", pFileObject->FileName);
}
NTSTATUS status = STATUS_UNSUCCESSFUL;
OBJECT_NAME_INFORMATION objName = {0};
ULONG ReturnLength = 1024;
ObQueryNameString(DeviceObject, objName, sizeof(objName), ReturnLength);
DbgPrint("FileName : %wZ\n", &objName);
Have you considered using GetFullPathName function?
Refer to http://msdn.microsoft.com/en-us/library/aa364963%28VS.85%29.aspx for more accurate explanation what it does.