CreateProcess # Unhandled exception when not using directly a string - c++

I'm trying to use CreateProcess to open a game .exe but I'm having the unhandled exception error. I already figured out the problem and the solution, but I need to get the path for the second parameter of CreateProcess from a file dialog box (that part is done and works). The problem is:
For the second parameter of CreateProcess, I need to declare a variable with the value to it (the 2nd param), but if I "point" it to the variable of the path to the file selected in the file dialog box, it doesn't work anymore.
I'm sorry if this is a really dumb question, but I'm starting in C++.
The code that works is here:
wchar_t szGameDir[] = L"PATH_TO_EXE";
if ( CreateProcess (
NULL,
szGameDir, NULL, NULL, FALSE,
CREATE_UNICODE_ENVIRONMENT,
NULL, NULL,
&pstStartupInfo, &pstProcInfo ) )
But when I set szGameDir to the value of 'pszGameDir' (path to the EXE selected by the user), it gives the unhandled exception error...
wchar_t* szGameDir = pszGameDir;
if ( CreateProcess (
NULL,
szGameDir, NULL, NULL, FALSE,
CREATE_UNICODE_ENVIRONMENT,
NULL, NULL,
&pstStartupInfo, &pstProcInfo ) )
And this is where I initialize 'pszGameDir':
OPENFILENAME DialogBox;
ZeroMemory ( &DialogBox, sizeof(DialogBox) );
DialogBox.lStructSize = sizeof(OPENFILENAME);
DialogBox.hwndOwner = NULL;
DialogBox.lpstrFilter = L"Grand Theft Auto: Vice City (*.exe)\0*.exe\0";
DialogBox.lpstrFile = (LPTSTR)this->pszGameDir;
DialogBox.nMaxFile = MAX_PATH;
DialogBox.nMaxFileTitle = sizeof ( L"gta-vc.exe" );
DialogBox.lpstrTitle = L"Please, select 'gta-vc.exe'";
DialogBox.Flags = 0x02000000 | 0x00001000 | 0x00000400 | 0x10000000 | 0x00020000 | 0x00000800 | 0x0000008;
DialogBox.nFileExtension = (WORD)"exe";
DialogBox.lpstrDefExt = L"exe";
return GetOpenFileName ( &DialogBox ) != 0 ? 1 : NULL;
Can someone help me? (Yes, I did search already, but honestly I haven't found about this specific thing, I wasn't able to fix it either..)

CreateProcess needs the command line parameter to be writeable. Read the description of the argument at MSDN:
The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.
It has to be writeable, I am afraid.

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.

winapi - GetServiceKeyName returns empty service name

I'm trying to get service name from display name using winapi function GetServiceKeyName in C++ with the following code:
SC_HANDLE hSCManager = OpenSCManager(NULL,
NULL, // service control manager database
SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE |SC_MANAGER_QUERY_LOCK_STATUS | STANDARD_RIGHTS_READ);
LPTSTR lpServiceName;
LPCTSTR lpDisplayName = L"My service";
DWORD dwSizeNeeded = sizeof(lpDisplayName);
GetServiceKeyName(hSCManager, lpDisplayName, lpServiceName, &dwSizeNeeded);
After finish, dwSizeNeeded have 15 as value and lpServiceName have "". Where I'm wrong calling to this function? Need any special right here? The inconvenience here is that this app doesn't have admin rights so I cannot (I guess) set SC_MANAGER_ALL_ACCESS. Of course, My service is up and running in system, so I have not bad display name.
Two lines needs to be modified:
...
TCHAR lpServiceName[512];
DWORD dwSizeNeeded = sizeof lpServcieName / sizeof lpServiceName[0]; // Number of elements in buffer
...
You should also see what GetServiceKeyName returns as that is the signal if it has succeeded or not. Checking the string is only valid if GetServiceKeyName returns TRUE.

Access violation reading from location in C++

Why is the last statement throwing Access Violation?
I wanted to write the status of a service into an XML file.
#define STR_SERVICE_STATUS_INPUT__XML_CONTENT _T("<SERVICE NAME = \"%s\" STARTUP_TYPE = \"0x%d\" />\r\n\r\n")
CString csWriteBufferTemp;
DWORD dwBufferSize;
DWORD dwBytesNeeded;
SC_HANDLE schHandle;
LPQUERY_SERVICE_CONFIG st_lpqscServiceInfo;
schHandle = OpenService(IN_schHandle, (CString)cArgentServices[i], SERVICE_QUERY_CONFIG);
bRC = QueryServiceConfig(schHandle, NULL, 0, &dwBytesNeeded);
dwBufferSize = dwBytesNeeded; //Size needed.
st_lpqscServiceInfo = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LMEM_FIXED, dwBufferSize);
bRC = QueryServiceConfig(schHandle, st_lpqscServiceInfo, dwBufferSize, &dwBytesNeeded);
csWriteBufferTemp.Format(STR_SERVICE_STATUS_INPUT__XML_CONTENT__,st_lpqscServiceInfo->lpDisplayName,0);
You are almost certainly using the wrong string format parameter in _T("<SERVICE NAME = \"%S\" STARTUP_TYPE = \"0x%d\" />\r\n\r\n"). The lpServiceStartName member of SERVICE_QUERY_CONFIG and CString are both TCHAR-based so they should have matching character types regardless of whether your compiling in Unicode mode or not. In that case, you should be using %s instead of %S.
Thanks for all your replies and suggestions, I found the answer on another site. I don't know if this is the correct way but it works!
LPQUERY_SERVICE_CONFIG
st_lpqscServiceInfo;
SC_HANDLE schHandle;
st_lpqscServiceInfo = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LPTR, 4096);
schHandle = OpenSCManager(IN_pszMachineName,SERVICES_ACTIVE_DATABASE, SERVICE_QUERY_CONFIG);
bRC = QueryServiceConfig(schHandle, st_lpqscServiceInfo, dwBufferSize, &dwBytesNeeded);
csWriteBufferTemp.Format(STR_SERVICE_STATUS_INPUT__XML_CONTENT__,st_lpqscServiceInfo->lpDisplayName,0);

SymEnumSourceFiles get incomplete file names

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.

Text from sysListView32 tree

Itrying to get a out of a string sysListView32 from another process.
The list is a tree. And for the first column returns an empty string.
Tell me where is the problem?
Image of tree:
tree
Code:
vProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ |
PROCESS_VM_WRITE, False, vProcessId);
vPointer = VirtualAllocEx(vProcess, NULL, 4096, MEM_RESERVE | MEM_COMMIT,
PAGE_READWRITE);
vItem.mask = LVIF_TEXT;
vItem.iItem = I;
vItem.iSubItem = J;
vItem.cchTextMax = sizeof(vBuffer);
vItem.pszText = (wchar_t*)vPointer +sizeof(TLVItem);
WriteProcessMemory(vProcess, vPointer, &vItem, sizeof(TLVItem),
&vNumberOfBytesRead);
SendMessageW(mHandle, LVM_GETITEMW, I, (LPARAM)vPointer);
ReadProcessMemory(vProcess, (wchar_t*)vPointer +sizeof(TLVItem),
vBuffer, sizeof(vBuffer), &vNumberOfBytesRead);
RESULT = UnicodeString(vBuffer);
VirtualFreeEx(vProcess, vPointer, 0, MEM_RELEASE); // free mem
CloseHandle(vProcess);
You didn't VirtualAlloc the memory block in the target process, so it isn't there.
Instead of using extreme hackery to try to get this, why not use one of the accessibility APIs to get this info cross-process. UIA, for example, goes down to XP and supports this:
http://msdn.microsoft.com/en-us/library/ms726294(VS.85).aspx
Martyn