[codeproject上的文章]Inside Windows Handles
|
| ||
IntroductionWhen Charles Petzold told window handles are system wide handles, many might not have got the real implication behind his statement. What he meant was, Process-A can find out what is its window handle and some how send the handle value to Process-B, Process-B once it receives that handle can do a Sharing HandlesHandles are 32 bit unsigned values that the Windows OS owns. It is usually the programmer who uses Windows native APIs to use these handles. This is one of the reasons why I am showing the second technique. If you were a nuts and bolts guy, you would want to see the handles being marshaled by your own eyes, and be sure that Windows does nothing on our backs. This doubt might arise when a beginner in Windows programming does a Marshaling the handlesLet us see how these handles make sense when sent from one process to another process. Thread handles and Event object handles, for instance, do not make sense in other processes when sent directly. We need to marshal them. We need to custom marshal them in particular. We will custom marshal some handles and write the marshaled handle value to a file/file mapping kernel object, and other processes can read from this file/ file mapping kernel object and operate on them. BOOL DuplicateHandle (
HANDLE hSourceProcessHandle, // handle to the source process
HANDLE hSourceHandle, // handle to duplicate
HANDLE hTargetProcessHandle, // handle to process to duplicate to
LPHANDLE lpTargetHandle, // pointer to duplicate handle
DWORD dwDesiredAccess, // access for duplicate handle
BOOL bInheritHandle, // handle inheritance flag
DWORD dwOptions // optional actions
);
That's the API for custom marshalling a handle to a target process, it is the Look at the Between a parent process and a child process, things get a little easier. You would need to pass BOOL CreateProcess ( PCTSTR pszApplicationName, PTSTR pszCommandLine, PSECURITY_ATTRIBUTES psaProcess, PSECURITY_ATTRIBUTES pszThread, BOOL bInheritHandles, DWORD dwCreationFlags, PVOID pvEnvironment, PCTSTR pszCurrentDirectory, LPSTARTUPINFO pStartupInfo, PPROCESS_INFORMATION pProcessInformation ); Note: The thread IDs and the process IDs are system wide. We cannot custom marshal all kinds of handles. For a complete list of handles that can be custom marshaled, click on this link. About the projectSendWindowHandle project has it all. Just run it and it will run the ReceiveWindowHandle EXE. First, click on any button in the One argument one can give is Event objects already have a built in mechanism for sharing them across processes, then why do we need to do this On Some MFC Internals used in the projectIt would be atrocious if I do not explain some of the Windows/MFC internals stuff used in the projects as they do occupy significant portion of the article. Beginners may find it useful. Allow me to cover them in the following appendices. Appendix (A)Towards the end in the SendWindowHandle project, I wrote a function HANDLE WINAPI CreateToolhelp32Snapshot (
DWORD dwFlags,
DWORD th32ProcessID
);
This API takes a snapshot of the processes, and the heaps, modules, and threads used by the processes. See MSDN for a complete documentation. It is a very useful API to scan for system wide threads, processes and modules. Note: Readers who do not like using CreateToolhelp32Snapshot can use their own ways of killing processes. Appendix (B)An insight into handling messages received from There is one function in SendWindowHandle project The above is straight out of Microsoft's web site. Since I do not want to use a hook for this purpose, I do as shown below: In the MFC architecture, the registered window procedure is always the LONG SetWindowLong (
HWND hWnd, // handle of window
int nIndex, // offset of value to set
LONG dwNewLong // new value
);
where the
LRESULT CallWindowProc (
WNDPROC lpPrevWndFunc, // pointer to previous procedure
HWND hWnd, // handle to window
UINT Msg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
Since thread messages do not get passed on to their window procedures, the onus is on us to do the same. Okay, so I write something like this to get messages sent by MSG msg; While (::GetMessage (&msg,0,0,0)) { if (msg.hWnd == NULL) { AfxCallWndProc (dlg,dlg->m_hWnd,WM_THRDMESSAGE,0,0); } DispatchMessage (&msg); } But there is one problem here, I can't enter the message loop, it has already come into existence once Luckily, MFC implements modal and modeless dialogs in almost the same way. In both the cases, it calls Still, I can't enter the message loop that is already running, and I do not want to use a hook, so I replace the original message loop itself. In the One thing to remember is once this message loop is terminated (when the user closes the dialog), the main message loop kicks in While I do all this, this very problem was addressed by the Microsoft team, and Microsoft being Microsoft presents a totally different solution to the problem in its help and support web site. The reader can also look into an article by me in CodeGuru for a better understanding of the message maps in MFC. ConclusionThough this article is about some inner workings and the behavior of handles, let us just see why we need to share handles between processes. Usually, when the main application is made up of many small executables, these small executables might need to get some handles residing in the main executable to operate on them. Like, a main application might be just a user interface, and the dependant small executables might be the ones that do some background processing. There was a case when I had an executable running just to ensure it cleans up (temporary files) properly in case the main executable exited abruptly or crashed. Once I had an executable monitoring one thread of the application; if the thread crashes, it will bring down the application; then this executable will bring up the application altogether from scratch. Else, say a large amount of data has to be passed from one exe to another for processing of data. We need the unnamed file-mapping object handle pointing to the data to be sent across processes. Dr_Sai
|
浙公网安备 33010602011771号