I\'m trying to pass a mutex handle, to a child process trough command line, or any other way.
How can I do that? How do I acess the mutex from the child?
Th
Either create the mutex before creating the child process and make it inheritable (set bInheritHandle to TRUE in the lpMutexAttributes parameter for CreateMutex). This way you can pass the handle in the command line.
Or use DuplicateHandle and pass the handle via some other mechanism (e.g. use a pipe as STDIN for the child process).
Two options:
You can use named objects. Process A creates the Mutex with a name and then spawns Process B. Process B then calls OpenMutex or CreateMutex with the same name, and it will get a handle to the same mutex.
Drawbacks are in name selection. If you have a name collision, you can get unpredictable results. An attacker could create a mutex with the same name and create a denial of service situation. One way to deal with this is to generate the name randomly. For example, Process A could generate a GUID for the name, and then pass that GUID (as a string) on the command line to Process B.
You can use inheritance. Child processes can inherit many types of handles from the parent process, including mutex handles. Set the bInheritHandles parameters in the CreateProcess command (which your sample is already doing), and pass the value of the handle (as a string) on the command line to the child process. The child process can then convert the command line string back to a value and simply start using it. The value is the same in both processes.
This technique doesn't have the same drawbacks as the named object technique.
A working example of inheritance (error checking elided):
#include <cstddef>
#include <iostream>
#include <string>
#include <sstream>
#include <windows.h>
void DoParentWork() {
std::wcout << L"Parent: Creating an inheritable event..." << std::endl;
SECURITY_ATTRIBUTES security = {
sizeof(security), nullptr, /* bInheritHandle = */ TRUE
};
HANDLE hEvent = ::CreateEventW(&security, /* bManualReset = */ TRUE,
/* bInitialState = */ FALSE, nullptr);
std::wstringstream ssCommand;
ssCommand << L"foo.exe " << reinterpret_cast<std::size_t>(hEvent);
std::wstring strCmd = ssCommand.str();;
std::wcout << L"Parent: Starting child process..." << std::endl;
STARTUPINFO start_info = {sizeof(start_info)};
PROCESS_INFORMATION proc_info = {0};
::CreateProcessW(L"foo.exe", &strCmd[0], nullptr, nullptr,
/* bInheritHandles = */ TRUE, 0, nullptr, nullptr,
&start_info, &proc_info);
::CloseHandle(proc_info.hThread);
::CloseHandle(proc_info.hProcess);
std::wcout << L"Parent: Waiting for the child to signal the event."
<< std::endl;
if (::WaitForSingleObject(hEvent, 10*1000) == WAIT_OBJECT_0) {
std::wcout << L"Parent: The event was signaled." << std::endl;
} else {
std::wcout << L"Parent: Timed out waiting for the event."
<< std::endl;
}
::CloseHandle(hEvent);
}
void DoChildWork(const char *pszEvent) {
std::stringstream ss(pszEvent);
UINT_PTR iEvent;
ss >> iEvent;
HANDLE hEvent = reinterpret_cast<HANDLE>(iEvent);
std::cout << "Child: Event handle "
<< reinterpret_cast<std::size_t>(hEvent) << std::endl;
::Sleep(2000);
std::cout << "Child: Signalling the event." << std::endl;
::SetEvent(hEvent);
}
int main(int cArgs, char *ppszArgs[]) {
if (cArgs > 1) DoChildWork(ppszArgs[1]);
else DoParentWork();
return 0;
}