From the MS docs i read that you should call the func twice, first time is to get the token length and the second is getting its info. My problem is that it fails in the first call(error 122) but still writes a length of 32.
const char* CSystemHelper::ReturnUserByProcessHandle(const PROCESSENTRY32 &PENTRY) {
HANDLE hToken, tHandle;
DWORD ErrorCode;
if ((tHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, PENTRY.th32ProcessID)) == 0) {
ErrorCode = GetLastError();
CMessage::DEFAULT_MESSAGE(ErrorCode);
return "UNIDENTIFIED";
}
if (!OpenProcessToken(tHandle, TOKEN_QUERY, &hToken)) {
ErrorCode = GetLastError();
CMessage::DEFAULT_MESSAGE(ErrorCode);
return "UNIDENTIFIED";
}
DWORD len = 0;
// this call fails, but len is set to 32
if (!GetTokenInformation(hToken, TokenOwner, NULL, 0, &len)) {
ErrorCode = GetLastError();
CMessage::DEFAULT_MESSAGE(ErrorCode);
CloseHandle(hToken);
return "UNIDENTIFIED";
}
PTOKEN_OWNER TOKENOWNER = (PTOKEN_OWNER)LocalAlloc(LPTR, len);
if (!TOKENOWNER) {
LocalFree(TOKENOWNER);
CloseHandle(hToken);
return "UNIDENTIFIED";
}
if (!GetTokenInformation(hToken, TokenOwner, TOKENOWNER, len, &len)) {
LocalFree(TOKENOWNER);
CloseHandle(hToken);
return "UNIDENTIFIED";
}
char Username[256] = { 0 }, LocalDomain[256] = { 0 };
DWORD UsernameLength = 256, LocalDomainLength = 256;
SID_NAME_USE SIDNAMEUSE;
if (!LookupAccountSidA(NULL, TOKENOWNER->Owner, Username, &UsernameLength, LocalDomain, &LocalDomainLength, &SIDNAMEUSE)){
LocalFree(TOKENOWNER);
CloseHandle(hToken);
return "UNIDENTIFIED";
}
return Username;
}
if that matters handle is opened through a processentry which does not raise any errors
Yes. It is normal operation.
When TokenInformation parameter is null, GetTokenInformation function returns 122(ERROR_INSUFFICIENT_BUFFER).
So your code must be changed like this.
DWORD len = 0;
// this call fails, but len is set to 32
if (GetTokenInformation(hToken, TokenOwner, NULL, 0, &len)) {
ErrorCode = GetLastError();
if (ErrorCode != ERROR_INSUFFICIENT_BUFFER || len == 0)
{
CMessage::DEFAULT_MESSAGE(ErrorCode);
CloseHandle(hToken);
return "UNIDENTIFIED";
}
}
PTOKEN_OWNER TOKENOWNER = (PTOKEN_OWNER)LocalAlloc(LPTR, len);
if (!TOKENOWNER) {
LocalFree(TOKENOWNER);
CloseHandle(hToken);
return "UNIDENTIFIED";
}
Thanks for replying. Combining answers of Jack Lee and Karsten Loop i came to solution. I tried to omit error checking and return username but it was pure garbage so i decided to use std::string instead of c-style char arrays and everything is working.
I'm trying to open a file on windows and check that the magic bytes match a windows PE32. If I run the code below and return just before the ReadFile call in the function problemFunction the code works fine and it prints 5a4d at the end of the main function. However if I return after the ReadFile call in problemFunction then I exit in the dos->e_magic != PIMAGE_DOS_HEADER check.
#include <Windows.h>
#include <winternl.h>
void problemFunction(HANDLE *fh) {
DWORD fileSize = GetFileSize(fh, NULL);
if (!fileSize) { CloseHandle(fh); exit(1); }
BYTE* pByte = new BYTE[fileSize];
DWORD dw;
ReadFile(*fh, pByte, fileSize, &dw, NULL);
// could be wrong but i think i need to run SetFilePointer here but not sure on what to do.
return;
}
int main() {
const char* filepath = "C:\\windows\\file\\path\\to\\exe";
HANDLE fh = CreateFileA(filepath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(fh == INVALID_HANDLE_VALUE) { CloseHandle(fh); exit(1); }
problemFunction(&fh);
DWORD fileSize = GetFileSize(fh, NULL);
if (!fileSize) { CloseHandle(fh); exit(1); }
BYTE* pByte = new BYTE[fileSize];
DWORD dw;
ReadFile(fh, pByte, fileSize, &dw, NULL);
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)pByte;
if (dos->e_magic != IMAGE_DOS_SIGNATURE) { CloseHandle(fh); exit(1); }
// dos->e_magic should be 5a4d for MZ, windows PE
}
I assume i need to reset the file pointer after the problemFunction read call with something like
LONG reset = -sizeof(DWORD);
SetFilePointer(*fh, reset, NULL, FILE_END);
But i can't get it to work.
Thanks
There are a number of problems with your code.
problemFunction() is taking a HANDLE* pointer as input, but it is not dereferencing that pointer when passing it to GetFileSize() or CloseHandle(). But it is dereferencing the pointer when passing it to ReadFile().
You must be compiling your code with STRICT Type Checking turned off, otherwise your code would fail to compile. You should always compile with STRICT enabled.
HANDLE is a pointer type, so there is no need to pass it around by pointer, unless you are going to modify its value, which this code is not doing. So you should change problemFunction() to take a HANDLE as-is rather than taking a HANDLE* pointer.
Also, GetFileSize() does not return 0 on failure, like your code assumes. It actually returns INVALID_FILE_SIZE which is -1, ie 0XFFFFFFFF as a DWORD. This is clearly stated in the documentation:
If the function fails and lpFileSizeHigh is NULL, the return value is INVALID_FILE_SIZE. To get extended error information, call GetLastError.
But, most importantly, your 2nd call to ReadFile() inside of main() does not read what you are expecting because the 1st call to ReadFile() inside of problemFunction() has already read the data (and leaked it!), but you are not seeking the HANDLE back to the beginning of the file after that read so the 2nd call to ReadFile() can read it again. You are correct that you need to use SetFilePointer() for that.
With that said, try something more like this:
#include <Windows.h>
#include <winternl.h>
bool test(HANDLE fh) {
DWORD fileSize = GetFileSize(fh, NULL);
if (fileSize == INVALID_FILE_SIZE) {
return false;
}
BYTE* pByte = new BYTE[fileSize];
DWORD dw;
if (!ReadFile(fh, pByte, fileSize, &dw, NULL)) {
delete[] pByte;
return false;
}
// use pByte as needed...
delete[] pByte;
if (SetFilePointer(fh, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
return false;
}
return true;
}
int main() {
const char* filepath = "C:\\windows\\file\\path\\to\\exe";
HANDLE fh = CreateFileA(filepath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fh == INVALID_HANDLE_VALUE) {
return 1;
}
if (!test(fh)) {
CloseHandle(fh);
return 1;
}
DWORD fileSize = GetFileSize(fh, NULL);
if (fileSize == INVALID_FILE_SIZE) {
CloseHandle(fh);
return 1;
}
BYTE* pByte = new BYTE[fileSize];
DWORD dw;
if (!ReadFile(fh, pByte, fileSize, &dw, NULL) || dw < sizeof(IMAGE_DOS_HEADER)) {
CloseHandle(fh);
return 1;
}
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)pByte;
if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
delete[] pByte;
CloseHandle(fh);
return 1;
}
...
delete[] pByte;
CloseHandle(fh);
return 0;
}
I am learning C++ and I need help figuring out how to inject a DLL with ManualMap Injection from the C++ Projects resources.
I have a source for this in C#, but I am not sure how to convert it, and I don't want to try to convert about 5000 lines of code.
Here is a undetected DLL Injection using ManualMapping it's undetected by many GameGuard's for injecting DLL's into games.
#include <stdio.h>
#include <Windows.h>
#include <tlhelp32.h> /* PROCESSENTRY32 */
#include <conio.h> /* _getch() */
#include <shlwapi.h> /* StrStrI */
#pragma comment(lib, "shlwapi.lib") /* unresolved external symbol __imp__StrStrIW#8 */
typedef HMODULE (WINAPI *pLoadLibraryA)(LPCSTR);
typedef FARPROC (WINAPI *pGetProcAddress)(HMODULE,LPCSTR);
typedef BOOL (WINAPI *PDLL_MAIN)(HMODULE,DWORD,PVOID);
typedef struct _MANUAL_INJECT
{
PVOID ImageBase;
PIMAGE_NT_HEADERS NtHeaders;
PIMAGE_BASE_RELOCATION BaseRelocation;
PIMAGE_IMPORT_DESCRIPTOR ImportDirectory;
pLoadLibraryA fnLoadLibraryA;
pGetProcAddress fnGetProcAddress;
}MANUAL_INJECT,*PMANUAL_INJECT;
DWORD WINAPI LoadDll(PVOID p)
{
PMANUAL_INJECT ManualInject;
HMODULE hModule;
DWORD i,Function,count,delta;
PDWORD ptr;
PWORD list;
PIMAGE_BASE_RELOCATION pIBR;
PIMAGE_IMPORT_DESCRIPTOR pIID;
PIMAGE_IMPORT_BY_NAME pIBN;
PIMAGE_THUNK_DATA FirstThunk,OrigFirstThunk;
PDLL_MAIN EntryPoint;
ManualInject=(PMANUAL_INJECT)p;
pIBR=ManualInject->BaseRelocation;
delta=(DWORD)((LPBYTE)ManualInject->ImageBase-ManualInject->NtHeaders->OptionalHeader.ImageBase); // Calculate the delta
// Relocate the image
while(pIBR->VirtualAddress)
{
if(pIBR->SizeOfBlock>=sizeof(IMAGE_BASE_RELOCATION))
{
count=(pIBR->SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION))/sizeof(WORD);
list=(PWORD)(pIBR+1);
for(i=0;i<count;i++)
{
if(list[i])
{
ptr=(PDWORD)((LPBYTE)ManualInject->ImageBase+(pIBR->VirtualAddress+(list[i] & 0xFFF)));
*ptr+=delta;
}
}
}
pIBR=(PIMAGE_BASE_RELOCATION)((LPBYTE)pIBR+pIBR->SizeOfBlock);
}
pIID=ManualInject->ImportDirectory;
// Resolve DLL imports
while(pIID->Characteristics)
{
OrigFirstThunk=(PIMAGE_THUNK_DATA)((LPBYTE)ManualInject->ImageBase+pIID->OriginalFirstThunk);
FirstThunk=(PIMAGE_THUNK_DATA)((LPBYTE)ManualInject->ImageBase+pIID->FirstThunk);
hModule=ManualInject->fnLoadLibraryA((LPCSTR)ManualInject->ImageBase+pIID->Name);
if(!hModule)
{
return FALSE;
}
while(OrigFirstThunk->u1.AddressOfData)
{
if(OrigFirstThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)
{
// Import by ordinal
Function=(DWORD)ManualInject->fnGetProcAddress(hModule,(LPCSTR)(OrigFirstThunk->u1.Ordinal & 0xFFFF));
if(!Function)
{
return FALSE;
}
FirstThunk->u1.Function=Function;
}
else
{
// Import by name
pIBN=(PIMAGE_IMPORT_BY_NAME)((LPBYTE)ManualInject->ImageBase+OrigFirstThunk->u1.AddressOfData);
Function=(DWORD)ManualInject->fnGetProcAddress(hModule,(LPCSTR)pIBN->Name);
if(!Function)
{
return FALSE;
}
FirstThunk->u1.Function=Function;
}
OrigFirstThunk++;
FirstThunk++;
}
pIID++;
}
if(ManualInject->NtHeaders->OptionalHeader.AddressOfEntryPoint)
{
EntryPoint=(PDLL_MAIN)((LPBYTE)ManualInject->ImageBase+ManualInject->NtHeaders->OptionalHeader.AddressOfEntryPoint);
return EntryPoint((HMODULE)ManualInject->ImageBase,DLL_PROCESS_ATTACH,NULL); // Call the entry point
}
return TRUE;
}
DWORD WINAPI LoadDllEnd()
{
return 0;
}
DWORD GetTargetThreadIDFromProcName(const char * ProcName)
{
PROCESSENTRY32 pe;
HANDLE thSnapShot;
BOOL retval, ProcFound = false;
thSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (thSnapShot == INVALID_HANDLE_VALUE)
{
//MessageBox(NULL, "Error: Unable to create toolhelp snapshot!", "2MLoader", MB_OK);
printf("Error: Unable to create toolhelp snapshot!");
return false;
}
pe.dwSize = sizeof(PROCESSENTRY32);
retval = Process32First(thSnapShot, &pe);
while (retval)
{
if (StrStrI(pe.szExeFile, ProcName))
{
return pe.th32ProcessID;
}
retval = Process32Next(thSnapShot, &pe);
}
return 0;
}
void GetGamePath(char* buff) {
HKEY hKey = 0;
char path[255] = { 0 };
char filename[255] = { 0 };
DWORD dwType = 0;
DWORD dwBufSize = 255;
GetFullPathName("Game.exe", MAX_PATH, buff, NULL);
//If file exists, then just exit.
if (FILE *file = fopen(buff, "r")) {
fclose(file);
return;
}
if (RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\SomeGame\\Game", 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &hKey) == ERROR_SUCCESS)
{
bool failed = false;
dwType = REG_SZ;
if (RegQueryValueEx(hKey, "PATH", 0, &dwType, (BYTE*)&path, &dwBufSize) != ERROR_SUCCESS)
failed = true;
if (RegQueryValueEx(hKey, "FILENAME", 0, &dwType, (BYTE*)&filename, &dwBufSize) != ERROR_SUCCESS)
failed = true;
RegCloseKey(hKey);
sprintf(buff, "%s%s", path, filename);
if (failed) {
GetFullPathName("Game.exe", MAX_PATH, buff, NULL);
}
}
}
int wmain(int argc,wchar_t* argv[])
{
PIMAGE_DOS_HEADER pIDH;
PIMAGE_NT_HEADERS pINH;
PIMAGE_SECTION_HEADER pISH;
HANDLE hProcess,hThread,hFile,hToken;
PVOID /*buffer,*/image,mem;
DWORD i,FileSize,ProcessId,ExitCode,read;
TOKEN_PRIVILEGES tp;
MANUAL_INJECT ManualInject;
if(OpenProcessToken((HANDLE)-1,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
{
tp.PrivilegeCount=1;
tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
tp.Privileges[0].Luid.LowPart=20;
tp.Privileges[0].Luid.HighPart=0;
AdjustTokenPrivileges(hToken,FALSE,&tp,0,NULL,NULL);
CloseHandle(hToken);
}
printf("\nOpening the DLL.\n");
/*
hFile=CreateFile("AO.dll",GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL); // Open the DLL
if(hFile==INVALID_HANDLE_VALUE)
{
printf("\nError: Unable to open the DLL (%d)\n",GetLastError());
return -1;
}
FileSize=GetFileSize(hFile,NULL);
buffer=VirtualAlloc(NULL,FileSize,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
if(!buffer)
{
printf("\nError: Unable to allocate memory for DLL data (%d)\n",GetLastError());
CloseHandle(hFile);
return -1;
}
// Read the DLL
if(!ReadFile(hFile,buffer,FileSize,&read,NULL))
{
printf("\nError: Unable to read the DLL (%d)\n",GetLastError());
VirtualFree(buffer,0,MEM_RELEASE);
CloseHandle(hFile);
return -1;
}
CloseHandle(hFile);
*/
MODULE hModule = GetModuleHandle(NULL); // get the handle to the current module (the executable file)
HRSRC hResource = FindResource(hModule, MAKEINTRESOURCE(RESOURCE_ID), RESOURCE_TYPE); // substitute RESOURCE_ID and RESOURCE_TYPE.
HGLOBAL hMemory = LoadResource(hModule, hResource);
DWORD dwSize = SizeofResource(hModule, hResource);
LPVOID lpAddress = LockResource(hMemory);
unsigned char *buffer = new char[dwSize];
memcpy(buffer, lpAddress, dwSize);
pIDH=(PIMAGE_DOS_HEADER)buffer;
if(pIDH->e_magic!=IMAGE_DOS_SIGNATURE)
{
printf("\nError: Invalid executable image.\n");
VirtualFree(buffer,0,MEM_RELEASE);
return -1;
}
pINH=(PIMAGE_NT_HEADERS)((LPBYTE)buffer+pIDH->e_lfanew);
if(pINH->Signature!=IMAGE_NT_SIGNATURE)
{
printf("\nError: Invalid PE header.\n");
VirtualFree(buffer,0,MEM_RELEASE);
return -1;
}
if(!(pINH->FileHeader.Characteristics & IMAGE_FILE_DLL))
{
printf("\nError: The image is not DLL.\n");
VirtualFree(buffer,0,MEM_RELEASE);
return -1;
}
// Retrieve process ID
ProcessId = 0;
char buf[MAX_PATH] = { 0 };
//Game.exe not started, attempt to start Game.exe (same path as this tool).
if (ProcessId == 0) {
// Gets the exe's full path name.
GetGamePath(buf);
printf("GamePath: ");
printf(buf);
printf("\n");
LPCTSTR lpApplicationName = buf; /* The program to be executed */
STARTUPINFO lpStartupInfo;
PROCESS_INFORMATION lpProcessInfo;
memset(&lpStartupInfo, 0, sizeof(lpStartupInfo));
memset(&lpProcessInfo, 0, sizeof(lpProcessInfo));
/* Create the process */
if (!CreateProcess(lpApplicationName, NULL, NULL, NULL, FALSE, NULL, NULL, NULL, &lpStartupInfo, &lpProcessInfo)) {
printf("Uh-Oh! CreateProcess() failed to start program %s\n", lpApplicationName);
_getch();
return 0;
} else {
WaitForSingleObject(lpProcessInfo.hProcess, 2000);
CloseHandle(lpProcessInfo.hThread);
CloseHandle(lpProcessInfo.hProcess);
ProcessId = lpProcessInfo.dwProcessId;
}
}
printf("Game.exe ProcessId = %d\n", ProcessId);
printf("\nOpening target process.\n");
hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,ProcessId);
if(!hProcess)
{
printf("\nError: Unable to open target process (%d)\n",GetLastError());
VirtualFree(buffer,0,MEM_RELEASE);
CloseHandle(hProcess);
return -1;
}
printf("\nAllocating memory for the DLL.\n");
image=VirtualAllocEx(hProcess,NULL,pINH->OptionalHeader.SizeOfImage,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE); // Allocate memory for the DLL
if(!image)
{
printf("\nError: Unable to allocate memory for the DLL (%d)\n",GetLastError());
VirtualFree(buffer,0,MEM_RELEASE);
CloseHandle(hProcess);
return -1;
}
// Copy the header to target process
printf("\nCopying headers into target process.\n");
if(!WriteProcessMemory(hProcess,image,buffer,pINH->OptionalHeader.SizeOfHeaders,NULL))
{
printf("\nError: Unable to copy headers to target process (%d)\n",GetLastError());
VirtualFreeEx(hProcess,image,0,MEM_RELEASE);
CloseHandle(hProcess);
VirtualFree(buffer,0,MEM_RELEASE);
return -1;
}
pISH=(PIMAGE_SECTION_HEADER)(pINH+1);
// Copy the DLL to target process
printf("\nCopying sections to target process.\n");
for(i=0;i<pINH->FileHeader.NumberOfSections;i++)
{
WriteProcessMemory(hProcess,(PVOID)((LPBYTE)image+pISH[i].VirtualAddress),(PVOID)((LPBYTE)buffer+pISH[i].PointerToRawData),pISH[i].SizeOfRawData,NULL);
}
printf("\nAllocating memory for the loader code.\n");
mem=VirtualAllocEx(hProcess,NULL,4096,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE); // Allocate memory for the loader code
if(!mem)
{
printf("\nError: Unable to allocate memory for the loader code (%d)\n",GetLastError());
VirtualFreeEx(hProcess,image,0,MEM_RELEASE);
CloseHandle(hProcess);
VirtualFree(buffer,0,MEM_RELEASE);
return -1;
}
printf("\nLoader code allocated at %#x\n",mem);
memset(&ManualInject,0,sizeof(MANUAL_INJECT));
ManualInject.ImageBase=image;
ManualInject.NtHeaders=(PIMAGE_NT_HEADERS)((LPBYTE)image+pIDH->e_lfanew);
ManualInject.BaseRelocation=(PIMAGE_BASE_RELOCATION)((LPBYTE)image+pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
ManualInject.ImportDirectory=(PIMAGE_IMPORT_DESCRIPTOR)((LPBYTE)image+pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
ManualInject.fnLoadLibraryA=LoadLibraryA;
ManualInject.fnGetProcAddress=GetProcAddress;
printf("\nWriting loader code to target process.\n");
WriteProcessMemory(hProcess,mem,&ManualInject,sizeof(MANUAL_INJECT),NULL); // Write the loader information to target process
WriteProcessMemory(hProcess,(PVOID)((PMANUAL_INJECT)mem+1),LoadDll,(DWORD)LoadDllEnd-(DWORD)LoadDll,NULL); // Write the loader code to target process
printf("\nExecuting loader code.\n");
hThread=CreateRemoteThread(hProcess,NULL,0,(LPTHREAD_START_ROUTINE)((PMANUAL_INJECT)mem+1),mem,0,NULL); // Create a remote thread to execute the loader code
if(!hThread)
{
printf("\nError: Unable to execute loader code (%d)\n",GetLastError());
VirtualFreeEx(hProcess,mem,0,MEM_RELEASE);
VirtualFreeEx(hProcess,image,0,MEM_RELEASE);
CloseHandle(hProcess);
VirtualFree(buffer,0,MEM_RELEASE);
return -1;
}
WaitForSingleObject(hThread,INFINITE);
GetExitCodeThread(hThread,&ExitCode);
if(!ExitCode)
{
VirtualFreeEx(hProcess,mem,0,MEM_RELEASE);
VirtualFreeEx(hProcess,image,0,MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProcess);
VirtualFree(buffer,0,MEM_RELEASE);
return -1;
}
CloseHandle(hThread);
VirtualFreeEx(hProcess,mem,0,MEM_RELEASE);
CloseHandle(hProcess);
printf("\nDLL injected at %#x\n",image);
if(pINH->OptionalHeader.AddressOfEntryPoint)
{
printf("\nDLL entry point: %#x\n",(PVOID)((LPBYTE)image+pINH->OptionalHeader.AddressOfEntryPoint));
}
VirtualFree(buffer,0,MEM_RELEASE);
return 0;
}
I want to make my C++ program to start up automatically when the windows start up and run at the background. I searched something about it and find we can use register the C++ program to be a windows service so that when the windows start up, the program can automatically run.
So I copy this code in Add Application to Startup (Registry) , and run the code, but I cannot see any records in my computer management->services.
Here is the code:
#include "stdafx.h"
#include<Windows.h>
#include <Winbase.h>
BOOL RegisterMyProgramForStartup(PCWSTR pszAppName, PCWSTR pathToExe, PCWSTR args)
{
HKEY hKey = NULL;
LONG lResult = 0;
BOOL fSuccess = TRUE;
DWORD dwSize;
const size_t count = MAX_PATH * 2;
wchar_t szValue[count] = {};
wcscpy_s(szValue, count, L"\"");
wcscat_s(szValue, count, pathToExe);
wcscat_s(szValue, count, L"\" ");
if (args != NULL)
{
wcscat_s(szValue, count, args);
}
lResult = RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, NULL, 0, (KEY_WRITE | KEY_READ), NULL, &hKey, NULL);
fSuccess = (lResult == 0);
if (fSuccess)
{
dwSize = (wcslen(szValue) + 1) * 2;
lResult = RegSetValueExW(hKey, pszAppName, 0, REG_SZ, (BYTE*)szValue, dwSize);
fSuccess = (lResult == 0);
}
if (hKey != NULL)
{
RegCloseKey(hKey);
hKey = NULL;
}
return fSuccess;
}
void RegisterProgram()
{
wchar_t szPathToExe[MAX_PATH];
GetModuleFileNameW(NULL, szPathToExe, MAX_PATH);
RegisterMyProgramForStartup(L"ConsoleApplication7", szPathToExe, L"-foobar");
}
int _tmain(int argc, _TCHAR* argv[])
{
RegisterProgram();
return 0;
}
Similar to C++ Windows - How to get process path from its PID but the reverse: How can I get a pid from a given path?
I am trying to write an update tool, and I want to see if the exe is in use. Then if it is in use, I want to wait for the process to exit. Therefore, I want to get the process PID belonging to the file.
Here is a quick and simple way to do what you are looking for. By using the QueryFullProcessImageName, you can do a quick check.
Things that can cause the following code not to work as desired:
If you do not have permissions to view a process, you will not be
able to see the information.
If the process is 64bit and you are running your application as 32 bit, you will see the process ID, but you can not open a process handle to it.
Example:
BOOL GetProcessName(LPTSTR szFilename, DWORD dwSize, DWORD dwProcID)
{
BOOLEAN retVal = FALSE;
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcID);
DWORD dwPathSize = dwSize;
if (hProcess == 0)
return retVal; // You should check for error code, if you are concerned about this
retVal = QueryFullProcessImageName(hProcess, 0, szFilename, &dwPathSize);
CloseHandle(hProcess);
return retVal;
}
BOOL IsProcessInUse(LPCTSTR process_name)
{
DWORD* pProcs = NULL;
DWORD dwSize = 0;
DWORD dwRealSize = 0;
TCHAR szCompareName[MAX_PATH + 1];
int nCount = 0;
int nResult = 0;
dwSize = 1024;
pProcs = new DWORD[dwSize];
EnumProcesses(pProcs, dwSize*sizeof(DWORD), &dwRealSize);
dwSize = dwRealSize / sizeof(DWORD);
for (DWORD nCount = 0; nCount < dwSize; nCount++)
{
ZeroMemory(szCompareName, MAX_PATH + 1 * (sizeof(TCHAR)));
if (GetProcessName(szCompareName, MAX_PATH, pProcs[nCount]))
{
if (_tcscmp(process_name, szCompareName) == 0)
{
delete[] pProcs;
return true;
}
}
}
delete[] pProcs;
return FALSE;
}
You would then use something simple like the following to test it:
if (IsProcessInUse(your_file))
AfxMessageBox(_T("The process is still running"));
else
AfxMessageBox(_T("The process has been closed"));
The above answers your indirect question. To answer your literal question, you would change the IsProcessInUse as follows:
DWORD GetNamedProcessID(LPCTSTR process_name)
{
DWORD* pProcs = NULL;
DWORD retVal = 0;
DWORD dwSize = 0;
DWORD dwRealSize = 0;
TCHAR szCompareName[MAX_PATH + 1];
int nCount = 0;
int nResult = 0;
dwSize = 1024;
pProcs = new DWORD[dwSize];
EnumProcesses(pProcs, dwSize*sizeof(DWORD), &dwRealSize);
dwSize = dwRealSize / sizeof(DWORD);
for (DWORD nCount = 0; nCount < dwSize; nCount++)
{
ZeroMemory(szCompareName, MAX_PATH + 1 * (sizeof(TCHAR)));
if (GetProcessName(szCompareName, MAX_PATH, pProcs[nCount]))
{
if (_tcscmp(process_name, szCompareName) == 0)
{
retVal = pProcs[nCount];
delete[] pProcs;
return retVal;
}
}
}
delete[] pProcs;
return 0;
}
One last important thing to note is the fact that this will only return a single instance (or PID) for a file, and this does not look for Modules that are used by process (so any DLL in use by process will not be identified, however, from the link you provided, you can see ways of utilizing that to get that level of functionality.