There are three ways to share kernel objects across process boundaries:
- Inheritance of object handles
- Named objects
- Copy object handle
named Objects
The second way to share kernel objects that span process boundaries is to name the objects, and note that some kernel objects are not named, but most kernel objects can be named.
All of the following functions can create named Kernel objects:
HANDLECreateMutex(pslcurity_attributes PSA, BOOL binitialowner, PctstrPszname); HANDLECreateEvent(psecurity_attributes PSA, BOOL bManualReset, bool binitialstate, PCTSTRPszname); HANDLECreateSemaphore(psecurity_attributes PSA, Long linitialcount, long lMaximumCount, pctstrPszname); HANDLECreateWaitableTimer(pslcurity_attributes PSA, BOOL bmanualreset, PctstrPszname); HANDLEcreatefilemapping(HANDLE hfile, Psecurity_attributes PSA, DWORD Flprotect, DWORD Dwmaximumsizehigh, DWORD Dwmaximumsizelow, PC Tstr pszname); HANDLECreatejobobject(psecurity_attributes PSA, Pctstr pszname);
issues to be aware of using named Objects
All of these objects share a single name space. So the following usage is wrong.
HANDLE Hmutex=CreateMutex (NULL. FALSE,"Jeffobj"); HANDLE Hsem=CreateSemaphore (NULL,1, 1, "Jeffobj");D Word dwerrorcode=GetLastError ();
Therefore, to prevent name collisions, we recommend that you create a GUID and use the string expression of the GUID as the object name.
how to share objects with named Objects
Process A starts the run and calls the following function:
="jeffmutex");
When another process PROCESSB (not necessarily a subprocess of process A) starts the runtime, execute the following code:
="jeffmutex");
When process B calls CreateMutex, the system first checks to see if a kernel object with the name "Jeffmutex" already exists.
Because an object with that name does exist, the kernel checks the type of the object. Because an attempt was made to create a mutex object, and the object named "Jeffmutex" is also a mutex object,
As a result, the system performs a security check to determine whether the caller has complete access to the object.
If you have this access, the system finds an empty project in the handle table of the PROCESSB and initializes the project to point to the existing kernel object.
If the object type does not match, or if the caller is denied access, then CreateMutex will fail to run (return null).
When process B succeeds in making a call to CreateMutex, it does not actually create a mutex object. Instead, process B is given a procedure-related handle value that identifies the existing mutex object in the kernel . Of course, because a new item in the handle table of process B is referencing the object, the usage count of the mutex is incremented. The object is not undone until process a and process B close their object handles at the same time. Note that the handle values in both processes are likely to be different values. this is possible. Process a uses its handle value, and process B uses its own handle value to manipulate a mutually exclusive kernel object.
Note that when you have multiple kernel objects that have the same name, there is a very important detail to know. When process B calls CreateMutex, it passes the security property information and the second argument to the function. If an object with the specified name already exists, then these parameters are ignored.
Determine if it does create a new kernel object instead of opening an existing object
HANDLE Hmutex=CreateMutex (&SA, FALSE,"Jeffobj");if(GetLastError ()== error_already_exists) { //opened a handle to an existing object. //Sa.lpsecuritydescriptor and the second parameter//(FALSE) is ignored}Else{ //Created a brand new object. //Sa.lpsecuritydescriptor and the second parameter//(FALSE) is used to construct the object.}
Another way to share objects by name
Instead of calling the create* function, call the open* function:
handle OpenMutex (DWORD dwdesiredaccess, BOOL binherithandle, Pctstr pszname); HANDLE openevent (DWORD dwdesiredaccess, BOOL bInheritHandle, Pctstr pszname); HANDLE opensemaphore (DWORD dwdesiredaccess, BOOL bInheritHandle, Pctstr pszname), HANDLE (DWORD dwdesiredaccess, BOOL binherithandle, Pctstr pszname); HANDLE openfilemapping (DWORD dwdesiredaccess, BOOL bInheritHandle, Pctstr pszname); HANDLE openjob0bject (DWORD dwdesiredaccess, BOOL bInheritHandle, Pctstr pszname);
The last parameter, Pszname, is used to indicate the name of the kernel object. You cannot pass NULL for this parameter, you must pass an address ending with 0. These functions search for a single namespace of the kernel object to find the matching space. If a kernel object with the specified name does not exist, the function returns NULL.
If a kernel object with the specified name exists, and it is an object of the same type, then the system will see if it is allowed to perform the required access (accessed through the dwdesiredaccess parameter). If you have this access, the handle table of the calling process is updated and the usage count of the object is incremented. If true is passed for the bInheritHandle parameter, the returned handle will be inheritable.
The main difference between calling the Create * function and calling the open* function
If the object does not exist, then the create* function creates the object, and the open* function fails.
A small application
Named objects are often used to prevent multiple instances of an application from running. To do this, you only need to call the create* function in the main or WinMain function to create a named object (it doesn't matter what object is created). When the create* function returns, the GetLastError function is called. If the GetLastError function returns ERROR_ALREADY_EXISTS, then another instance of your application is running and the new instance can exit. Here are some of the code that explains this:
Intwinapi WinMain (hinstance hinstexe, hinstance, PSTR pszcmdline,intncmdshow) {HANDLE h=CreateMutex (NULL, FALSE,"{fa531cc1-0497-11d3-a180-00105a276c3e}"); LF (GetLastError ()==error_already_exists) { //There is already an instance//Of the application running return(0); } //This is the first instance of ThisApplication running. //before exiting, close the object.CloseHandle (h); return(0);}
the namespace of the Terminal ServerThe terminal server can slightly change the situation described above. Terminal Server has multiple namespaces for kernel objects. Above reproduced in http://www.cnblogs.com/fangyukuan/archive/2010/08/31/1813733.html
Self-Test code to build 2 console programs first process
#include <windows.h> #include <stdio.h> #include <tchar.h> #include <strsafe.h> #define Grs_ useprintf () TCHAR pbuf[1024] = {} #define GRS_PRINTF (...) stringcchprintf (pbuf,1024,__va_args__); Writeconsole (GetStdHandle (Std_output_handle), Pbuf,lstrlen (PBuf), null,null); int main () {grs_useprintf ();/*HANDLE Hmutex = CreateMutex (Null,false, _t ("Jeffobj")); HANDLE Hsem = CreateSemaphore (NULL, 1, 1, _t ("Jeffobj")); grs_printf (_t ("Pipeline creation failed, Error code:0x%08x\n"), GetLastError ()); */handle Hmutex = CreateMutex (NULL, FALSE, _t ("Mymutex") );//closehandle (Hmutex); grs_printf (_t ("Error code:0x%08x\n"), GetLastError ()); HANDLE hMutex1 = CreateSemaphore (NULL, _t ("Mymutex")); grs_printf (_t ("Error code:0x%08x\n"), GetLastError ()); _tsystem (_t ("PAUSE"));}
#include <Windows.h> #include <tchar.h> #include <stdio.h> #include <strsafe.h> #define Grs_ useprintf () TCHAR pbuf[1024] = {} #define GRS_PRINTF (...) stringcchprintf (pbuf,1024,__va_args__); Writeconsole (GetStdHandle (Std_output_handle), Pbuf,lstrlen (PBuf), null,null); int main () {grs_useprintf (); HANDLE h = CreateMutex (NULL, FALSE, _t ("Mymutex")); if (getlasterror () = = error_already_exists) {//there is already an Insta Nce//of the Application running_tprintf_s (_t ("There is already an instanceof the application Running")); CloseHandle (h); return (0);} This is the first instance of ThisApplication Running.//before exiting, close the object. CloseHandle (h); return (0);}
Second Process#include <Windows.h> #include <stdio.h> #include <tchar.h>int main () {HANDLE Hmutex;hmutex = OpenMutex (mutex_all_access,false,_t ("Mymutex")); if (Hmutex = = NULL) printf ("OpenMutex Error:%d\n", GetLastError ()); else printf ("OpenMutex successfully opened the mutex.\n");
use open* create* to refer to MSDN Dome
Locojyw
Email:[email protected]
you are welcome to communicate, what is wrong please point out
Reprint Annotated Source
Share Kernel objects "named objects" across process boundaries