Flavio
Flavio

Reputation: 461

ERROR_INVALID_HANDLE when calling GetModuleFileNameEx after CreateProcess

After a successful call to CreateProcess, I am trying to get the path of the created process using GetModuleFileNameEx (lpApplicationName and lpCommandLine parameters can vary or be null so they aren't reliable in this case). The problem is that GetModuleFileNameEx fails with error 6 (ERROR_INVALID_HANDLE), leaving its buffer with invalid data. I cannot understand the reason, since CreateProcess succeeds and process handle should have been saved correctly in pi.hProcess.

Hope you can shed some light, thanks in advance!

EDIT: An update: I noticed that removing the CREATE_SUSPENDED removes this problem too, but I need that flag set. How can I do?

// Defining GetModuleFileNameExA function
typedef DWORD (WINAPI *fGetModuleFileNameExA)
(
    HANDLE hProcess,
    HMODULE hModule,
    LPSTR lpFilename,
    DWORD nSize
);
//Load dinamically DLL function on program startup:
fGetModuleFileNameExA _GetModuleFileNameExA = (fGetModuleFileNameExA) GetProcAddress( LoadLibraryA("Psapi.dll"), "GetModuleFileNameExA");

// **** OTHER UNRELATED CODE HERE ****


PROCESS_INFORMATION pi;

//This call succeeds
if (!CreateProcessW( ApplicationName, 
                    CommandLine, 
                    NewProcess.lpProcessAttributes, 
                    NewProcess.lpThreadAttributes,
                    NewProcess.bInheritHandles,
                    CREATE_SUSPENDED | CREATE_NEW_CONSOLE,
                    NULL,
                    CurrentDirectory,
                    &NewProcess.bufStartupInfo,
                    &pi)
       ) MessageBoxA(0, "Error creating process", "", 0);

    char ProcessPath[MAX_PATH];

//Problem here: call fails with error 6
if (!_GetModuleFileNameExA(pi.hProcess, NULL, ProcessPath, MAX_PATH)) {GetLastError();}

//Invalid data is displayed
MessageBoxA(0, ProcessPath, "GetModuleFileNameEx",0);

Upvotes: 1

Views: 2031

Answers (1)

axnsan
axnsan

Reputation: 917

From the CreateProcess documentation on MSDN:

Note that the function returns before the process has finished initialization. If a required DLL cannot be located or fails to initialize, the process is terminated. To get the termination status of a process, call GetExitCodeProcess.

...

The calling thread can use the WaitForInputIdle function to wait until the new process has finished its initialization and is waiting for user input with no input pending. This can be useful for synchronization between parent and child processes, because CreateProcess returns without waiting for the new process to finish its initialization. For example, the creating process would use WaitForInputIdle before trying to find a window associated with the new process.

Similar question

Upvotes: 3

Related Questions