/[rdesktop]/sourceforge.net/trunk/seamlessrdp/ServerExe/HookDll/hookdll.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /sourceforge.net/trunk/seamlessrdp/ServerExe/HookDll/hookdll.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1186 - (hide annotations)
Wed Mar 22 11:56:46 2006 UTC (18 years, 2 months ago) by ossman_
File MIME type: text/plain
File size: 13294 byte(s)
Avoid %p since it's implementation defined.

1 ossman_ 1071 /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.
3     Seamless windows - Remote server hook DLL
4 ossman_ 1069
5 ossman_ 1071 Based on code copyright (C) 2004-2005 Martin Wickett
6    
7     Copyright (C) Peter Åstrand <astrand@cendio.se> 2005-2006
8     Copyright (C) Pierre Ossman <ossman@cendio.se> 2006
9    
10     This program is free software; you can redistribute it and/or modify
11     it under the terms of the GNU General Public License as published by
12     the Free Software Foundation; either version 2 of the License, or
13     (at your option) any later version.
14    
15     This program is distributed in the hope that it will be useful,
16     but WITHOUT ANY WARRANTY; without even the implied warranty of
17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18     GNU General Public License for more details.
19    
20     You should have received a copy of the GNU General Public License
21     along with this program; if not, write to the Free Software
22     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23     */
24    
25 ossman_ 1069 #include <stdio.h>
26     #include <stdarg.h>
27    
28 ossman_ 1071 #include <windows.h>
29     #include <winuser.h>
30 ossman_ 1069
31 ossman_ 1073 #include "../vchannel.h"
32 ossman_ 1071
33 ossman_ 1069 #define DLL_EXPORT __declspec(dllexport)
34    
35 ossman_ 1145 #ifdef __GNUC__
36     #define SHARED __attribute__((section ("SHAREDDATA"), shared))
37     #else
38     #define SHARED
39     #endif
40    
41 ossman_ 1069 // Shared DATA
42     #pragma data_seg ( "SHAREDDATA" )
43    
44     // this is the total number of processes this dll is currently attached to
45 ossman_ 1145 int g_instance_count SHARED = 0;
46 ossman_ 1069
47 ossman_ 1145 // blocks for locally generated events
48 ossman_ 1161 HWND g_block_move_hwnd SHARED = NULL;
49 ossman_ 1165 unsigned int g_block_move_serial SHARED = 0;
50 ossman_ 1145 RECT g_block_move SHARED = { 0, 0, 0, 0 };
51 ossman_ 1165
52     unsigned int g_blocked_zchange_serial SHARED = 0;
53 ossman_ 1158 HWND g_blocked_zchange[2] SHARED = { NULL, NULL };
54 ossman_ 1165
55     unsigned int g_blocked_focus_serial SHARED = 0;
56 ossman_ 1158 HWND g_blocked_focus SHARED = NULL;
57 ossman_ 1165
58     unsigned int g_blocked_state_serial SHARED = 0;
59 ossman_ 1161 HWND g_blocked_state_hwnd SHARED = NULL;
60 ossman_ 1160 int g_blocked_state SHARED = -1;
61 ossman_ 1145
62 ossman_ 1069 #pragma data_seg ()
63    
64     #pragma comment(linker, "/section:SHAREDDATA,rws")
65    
66 ossman_ 1153 #define FOCUS_MSG_NAME "WM_SEAMLESS_FOCUS"
67     static UINT g_wm_seamless_focus;
68    
69 ossman_ 1071 static HHOOK g_cbt_hook = NULL;
70     static HHOOK g_wndproc_hook = NULL;
71 ossman_ 1134 static HHOOK g_wndprocret_hook = NULL;
72 ossman_ 1069
73 ossman_ 1071 static HINSTANCE g_instance = NULL;
74 ossman_ 1069
75 ossman_ 1071 static HANDLE g_mutex = NULL;
76 ossman_ 1069
77 ossman_ 1081 static void
78     update_position(HWND hwnd)
79     {
80 ossman_ 1145 RECT rect, blocked;
81 ossman_ 1161 HWND blocked_hwnd;
82 ossman_ 1165 unsigned int serial;
83 ossman_ 1081
84 ossman_ 1145 WaitForSingleObject(g_mutex, INFINITE);
85 ossman_ 1165 blocked_hwnd = g_block_move_hwnd;
86     serial = g_block_move_serial;
87 ossman_ 1145 memcpy(&blocked, &g_block_move, sizeof(RECT));
88     ReleaseMutex(g_mutex);
89    
90 ossman_ 1167 vchannel_block();
91    
92     if (!GetWindowRect(hwnd, &rect))
93     {
94     debug("GetWindowRect failed!\n");
95     goto end;
96     }
97    
98 ossman_ 1161 if ((hwnd == blocked_hwnd) && (rect.left == blocked.left) && (rect.top == blocked.top)
99 ossman_ 1145 && (rect.right == blocked.right) && (rect.bottom == blocked.bottom))
100 ossman_ 1167 goto end;
101    
102 ossman_ 1186 vchannel_write("POSITION", "0x%08lx,%d,%d,%d,%d,0x%08x",
103 ossman_ 1167 hwnd,
104     rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 0);
105    
106     end:
107     vchannel_unblock();
108 ossman_ 1081 }
109    
110 ossman_ 1162 static void
111     update_zorder(HWND hwnd)
112     {
113     HWND behind;
114     HWND block_hwnd, block_behind;
115 ossman_ 1165 unsigned int serial;
116 ossman_ 1162
117     WaitForSingleObject(g_mutex, INFINITE);
118 ossman_ 1165 serial = g_blocked_zchange_serial;
119 ossman_ 1162 block_hwnd = g_blocked_zchange[0];
120     block_behind = g_blocked_zchange[1];
121     ReleaseMutex(g_mutex);
122    
123 ossman_ 1167 vchannel_block();
124    
125 ossman_ 1162 behind = GetNextWindow(hwnd, GW_HWNDPREV);
126     while (behind)
127     {
128     LONG style;
129    
130     style = GetWindowLong(behind, GWL_STYLE);
131    
132     if ((!(style & WS_CHILD) || (style & WS_POPUP)) && (style & WS_VISIBLE))
133     break;
134    
135     behind = GetNextWindow(behind, GW_HWNDPREV);
136     }
137    
138     if ((hwnd == block_hwnd) && (behind == block_behind))
139 ossman_ 1165 vchannel_write("ACK", "%u", serial);
140     else
141 ossman_ 1186 vchannel_write("ZCHANGE", "0x%08lx,0x%08lx,0x%08x", hwnd, behind, 0);
142 ossman_ 1167
143     vchannel_unblock();
144 ossman_ 1162 }
145    
146 ossman_ 1179 static HWND
147     get_parent(HWND hwnd)
148     {
149     LONG style;
150     HWND parent;
151    
152     style = GetWindowLong(hwnd, GWL_STYLE);
153    
154     if (style & (WS_POPUP | DS_MODALFRAME))
155     {
156     parent = (HWND) GetWindowLong(hwnd, GWL_HWNDPARENT);
157    
158     if (parent)
159     {
160     style = GetWindowLong(parent, GWL_STYLE);
161     if (((style & WS_CHILD) && !(style & WS_POPUP)) || !(style & WS_VISIBLE))
162     parent = NULL;
163     }
164    
165     if (!parent)
166     parent = GetWindow(hwnd, GW_OWNER);
167    
168     if (parent)
169     {
170     style = GetWindowLong(parent, GWL_STYLE);
171     if (((style & WS_CHILD) && !(style & WS_POPUP)) || !(style & WS_VISIBLE))
172     parent = NULL;
173     }
174    
175     if (!parent)
176     parent = (HWND) - 1;
177     }
178     else
179     parent = NULL;
180    
181     return parent;
182     }
183    
184 ossman_ 1071 static LRESULT CALLBACK
185     wndproc_hook_proc(int code, WPARAM cur_thread, LPARAM details)
186 ossman_ 1069 {
187 ossman_ 1097 HWND hwnd, parent;
188 ossman_ 1079 UINT msg;
189     WPARAM wparam;
190     LPARAM lparam;
191 ossman_ 1069
192 ossman_ 1079 LONG style;
193 ossman_ 1069
194 ossman_ 1071 if (code < 0)
195     goto end;
196 ossman_ 1069
197 ossman_ 1079 hwnd = ((CWPSTRUCT *) details)->hwnd;
198     msg = ((CWPSTRUCT *) details)->message;
199     wparam = ((CWPSTRUCT *) details)->wParam;
200     lparam = ((CWPSTRUCT *) details)->lParam;
201    
202     style = GetWindowLong(hwnd, GWL_STYLE);
203    
204 ossman_ 1082 /* Docs say that WS_CHILD and WS_POPUP is an illegal combination,
205     but they exist nonetheless. */
206     if ((style & WS_CHILD) && !(style & WS_POPUP))
207 ossman_ 1079 goto end;
208    
209 ossman_ 1179 parent = get_parent(hwnd);
210 ossman_ 1097
211 ossman_ 1071 switch (msg)
212     {
213     case WM_WINDOWPOSCHANGED:
214 ossman_ 1079 {
215     WINDOWPOS *wp = (WINDOWPOS *) lparam;
216 ossman_ 1069
217 ossman_ 1079 if (wp->flags & SWP_SHOWWINDOW)
218     {
219 ossman_ 1134 unsigned short title[150];
220 ossman_ 1099 int state;
221 ossman_ 1177 DWORD pid;
222     int flags;
223 ossman_ 1099
224 ossman_ 1177 GetWindowThreadProcessId(hwnd, &pid);
225 ossman_ 1069
226 ossman_ 1177 flags = 0;
227     if (style & DS_MODALFRAME)
228     flags |= SEAMLESS_CREATE_MODAL;
229    
230     vchannel_write("CREATE", "0x%08lx,0x%08lx,0x%08lx,0x%08x",
231     (long) hwnd, (long) pid, (long) parent,
232     flags);
233    
234 ossman_ 1134 GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
235 ossman_ 1069
236 ossman_ 1186 vchannel_write("TITLE", "0x%08lx,%s,0x%08x", hwnd,
237 ossman_ 1134 vchannel_strfilter_unicode(title), 0);
238 ossman_ 1099
239     if (style & WS_MAXIMIZE)
240     state = 2;
241     else if (style & WS_MINIMIZE)
242     state = 1;
243     else
244     state = 0;
245    
246 ossman_ 1081 update_position(hwnd);
247 ossman_ 1099
248 ossman_ 1186 vchannel_write("STATE", "0x%08lx,0x%08x,0x%08x", hwnd,
249     state, 0);
250 ossman_ 1079 }
251 ossman_ 1069
252 ossman_ 1079 if (wp->flags & SWP_HIDEWINDOW)
253 ossman_ 1186 vchannel_write("DESTROY", "0x%08lx,0x%08x", hwnd, 0);
254 ossman_ 1079
255 ossman_ 1108 if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
256 ossman_ 1079 break;
257    
258 ossman_ 1080 if (!(wp->flags & SWP_NOMOVE && wp->flags & SWP_NOSIZE))
259 ossman_ 1081 update_position(hwnd);
260 ossman_ 1079
261 ossman_ 1071 break;
262 ossman_ 1079 }
263 ossman_ 1069
264 ossman_ 1081 case WM_SIZE:
265 ossman_ 1108 if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
266 ossman_ 1083 break;
267 ossman_ 1081 update_position(hwnd);
268     break;
269    
270     case WM_MOVE:
271 ossman_ 1108 if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
272 ossman_ 1083 break;
273 ossman_ 1081 update_position(hwnd);
274     break;
275    
276 ossman_ 1134 case WM_DESTROY:
277     if (!(style & WS_VISIBLE))
278     break;
279 ossman_ 1186 vchannel_write("DESTROY", "0x%08lx,0x%08x", hwnd, 0);
280 ossman_ 1134 break;
281    
282     default:
283     break;
284     }
285    
286     end:
287     return CallNextHookEx(g_wndproc_hook, code, cur_thread, details);
288     }
289    
290     static LRESULT CALLBACK
291     wndprocret_hook_proc(int code, WPARAM cur_thread, LPARAM details)
292     {
293     HWND hwnd, parent;
294     UINT msg;
295     WPARAM wparam;
296     LPARAM lparam;
297    
298     LONG style;
299    
300     if (code < 0)
301     goto end;
302    
303     hwnd = ((CWPRETSTRUCT *) details)->hwnd;
304     msg = ((CWPRETSTRUCT *) details)->message;
305     wparam = ((CWPRETSTRUCT *) details)->wParam;
306     lparam = ((CWPRETSTRUCT *) details)->lParam;
307    
308     style = GetWindowLong(hwnd, GWL_STYLE);
309    
310     /* Docs say that WS_CHILD and WS_POPUP is an illegal combination,
311     but they exist nonetheless. */
312     if ((style & WS_CHILD) && !(style & WS_POPUP))
313     goto end;
314    
315 ossman_ 1179 parent = get_parent(hwnd);
316 ossman_ 1158
317 ossman_ 1134 switch (msg)
318     {
319 ossman_ 1162 case WM_WINDOWPOSCHANGED:
320     {
321     WINDOWPOS *wp = (WINDOWPOS *) lparam;
322    
323     if (!(style & WS_VISIBLE) || (style & WS_MINIMIZE))
324     break;
325    
326     if (!(wp->flags & SWP_NOZORDER))
327     update_zorder(hwnd);
328    
329     break;
330     }
331    
332    
333 ossman_ 1102 case WM_SETTEXT:
334 ossman_ 1113 {
335 ossman_ 1134 unsigned short title[150];
336 ossman_ 1113 if (!(style & WS_VISIBLE))
337     break;
338 ossman_ 1134 /* We cannot use the string in lparam because
339     we need unicode. */
340     GetWindowTextW(hwnd, title, sizeof(title) / sizeof(*title));
341 ossman_ 1186 vchannel_write("TITLE", "0x%08lx,%s,0x%08x", hwnd,
342 ossman_ 1134 vchannel_strfilter_unicode(title), 0);
343 ossman_ 1102 break;
344 ossman_ 1113 }
345 ossman_ 1102
346 ossman_ 1071 default:
347     break;
348     }
349    
350 ossman_ 1153 if (msg == g_wm_seamless_focus)
351 ossman_ 1158 {
352 ossman_ 1185 /* FIXME: SetForegroundWindow() kills menus. Need to find a
353     clean way to solve this. */
354     if ((GetForegroundWindow() != hwnd) && !parent)
355     SetForegroundWindow(hwnd);
356 ossman_ 1165
357     vchannel_write("ACK", "%u", g_blocked_focus_serial);
358 ossman_ 1158 }
359 ossman_ 1153
360 ossman_ 1071 end:
361 ossman_ 1134 return CallNextHookEx(g_wndprocret_hook, code, cur_thread, details);
362 ossman_ 1069 }
363    
364 ossman_ 1071 static LRESULT CALLBACK
365     cbt_hook_proc(int code, WPARAM wparam, LPARAM lparam)
366 ossman_ 1069 {
367 ossman_ 1071 if (code < 0)
368     goto end;
369 ossman_ 1069
370 ossman_ 1071 switch (code)
371     {
372     case HCBT_MINMAX:
373     {
374 ossman_ 1160 int show, state, blocked;
375 ossman_ 1161 HWND blocked_hwnd;
376 ossman_ 1165 unsigned int serial;
377 ossman_ 1069
378 ossman_ 1160 WaitForSingleObject(g_mutex, INFINITE);
379 ossman_ 1161 blocked_hwnd = g_blocked_state_hwnd;
380 ossman_ 1165 serial = g_blocked_state_serial;
381 ossman_ 1160 blocked = g_blocked_state;
382     ReleaseMutex(g_mutex);
383    
384 ossman_ 1071 show = LOWORD(lparam);
385 ossman_ 1069
386 ossman_ 1128 if ((show == SW_NORMAL) || (show == SW_SHOWNORMAL)
387     || (show == SW_RESTORE))
388 ossman_ 1079 state = 0;
389 ossman_ 1106 else if ((show == SW_MINIMIZE) || (show == SW_SHOWMINIMIZED))
390 ossman_ 1079 state = 1;
391 ossman_ 1106 else if ((show == SW_MAXIMIZE) || (show == SW_SHOWMAXIMIZED))
392 ossman_ 1079 state = 2;
393 ossman_ 1100 else
394 ossman_ 1106 {
395     debug("Unexpected show: %d", show);
396 ossman_ 1100 break;
397 ossman_ 1106 }
398 ossman_ 1160
399 ossman_ 1165 if ((blocked_hwnd == (HWND) wparam) && (blocked == state))
400     vchannel_write("ACK", "%u", serial);
401     else
402 ossman_ 1186 vchannel_write("STATE", "0x%08lx,0x%08x,0x%08x",
403     (HWND) wparam, state, 0);
404 ossman_ 1160
405 ossman_ 1071 break;
406     }
407 ossman_ 1069
408 ossman_ 1071 default:
409     break;
410     }
411 ossman_ 1069
412 ossman_ 1071 end:
413     return CallNextHookEx(g_cbt_hook, code, wparam, lparam);
414 ossman_ 1069 }
415    
416 ossman_ 1071 DLL_EXPORT void
417     SetHooks(void)
418 ossman_ 1069 {
419 ossman_ 1071 if (!g_cbt_hook)
420     g_cbt_hook = SetWindowsHookEx(WH_CBT, cbt_hook_proc, g_instance, 0);
421 ossman_ 1069
422 ossman_ 1071 if (!g_wndproc_hook)
423     g_wndproc_hook = SetWindowsHookEx(WH_CALLWNDPROC, wndproc_hook_proc, g_instance, 0);
424 ossman_ 1134
425     if (!g_wndprocret_hook)
426     g_wndprocret_hook =
427     SetWindowsHookEx(WH_CALLWNDPROCRET, wndprocret_hook_proc, g_instance, 0);
428 ossman_ 1069 }
429    
430 ossman_ 1071 DLL_EXPORT void
431     RemoveHooks(void)
432 ossman_ 1069 {
433 ossman_ 1071 if (g_cbt_hook)
434     UnhookWindowsHookEx(g_cbt_hook);
435 ossman_ 1069
436 ossman_ 1071 if (g_wndproc_hook)
437     UnhookWindowsHookEx(g_wndproc_hook);
438 ossman_ 1134
439     if (g_wndprocret_hook)
440     UnhookWindowsHookEx(g_wndprocret_hook);
441 ossman_ 1069 }
442    
443 ossman_ 1145 DLL_EXPORT void
444 ossman_ 1165 SafeMoveWindow(unsigned int serial, HWND hwnd, int x, int y, int width, int height)
445 ossman_ 1145 {
446 ossman_ 1165 RECT rect;
447    
448 ossman_ 1145 WaitForSingleObject(g_mutex, INFINITE);
449 ossman_ 1161 g_block_move_hwnd = hwnd;
450 ossman_ 1165 g_block_move_serial = serial;
451 ossman_ 1145 g_block_move.left = x;
452     g_block_move.top = y;
453     g_block_move.right = x + width;
454     g_block_move.bottom = y + height;
455     ReleaseMutex(g_mutex);
456    
457     SetWindowPos(hwnd, NULL, x, y, width, height, SWP_NOACTIVATE | SWP_NOZORDER);
458    
459 ossman_ 1167 vchannel_write("ACK", "%u", serial);
460    
461     if (!GetWindowRect(hwnd, &rect))
462     debug("GetWindowRect failed!\n");
463     else if ((rect.left != x) || (rect.top != y) || (rect.right != x + width)
464     || (rect.bottom != y + height))
465     update_position(hwnd);
466    
467 ossman_ 1145 WaitForSingleObject(g_mutex, INFINITE);
468 ossman_ 1161 g_block_move_hwnd = NULL;
469 ossman_ 1145 memset(&g_block_move, 0, sizeof(RECT));
470     ReleaseMutex(g_mutex);
471     }
472    
473 ossman_ 1158 DLL_EXPORT void
474 ossman_ 1165 SafeZChange(unsigned int serial, HWND hwnd, HWND behind)
475 ossman_ 1158 {
476     WaitForSingleObject(g_mutex, INFINITE);
477 ossman_ 1165 g_blocked_zchange_serial = serial;
478 ossman_ 1158 g_blocked_zchange[0] = hwnd;
479     g_blocked_zchange[1] = behind;
480     ReleaseMutex(g_mutex);
481    
482 ossman_ 1162 if (behind == NULL)
483     behind = HWND_TOP;
484    
485 ossman_ 1158 SetWindowPos(hwnd, behind, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
486    
487     WaitForSingleObject(g_mutex, INFINITE);
488     g_blocked_zchange[0] = NULL;
489     g_blocked_zchange[1] = NULL;
490     ReleaseMutex(g_mutex);
491     }
492    
493     DLL_EXPORT void
494 ossman_ 1165 SafeFocus(unsigned int serial, HWND hwnd)
495 ossman_ 1158 {
496     WaitForSingleObject(g_mutex, INFINITE);
497 ossman_ 1165 g_blocked_focus_serial = serial;
498 ossman_ 1158 g_blocked_focus = hwnd;
499     ReleaseMutex(g_mutex);
500    
501     SendMessage(hwnd, g_wm_seamless_focus, 0, 0);
502    
503     WaitForSingleObject(g_mutex, INFINITE);
504     g_blocked_focus = NULL;
505     ReleaseMutex(g_mutex);
506     }
507    
508 ossman_ 1160 DLL_EXPORT void
509 ossman_ 1165 SafeSetState(unsigned int serial, HWND hwnd, int state)
510 ossman_ 1160 {
511 ossman_ 1165 LONG style;
512     int curstate;
513    
514     vchannel_block();
515    
516     style = GetWindowLong(hwnd, GWL_STYLE);
517    
518     if (style & WS_MAXIMIZE)
519     curstate = 2;
520     else if (style & WS_MINIMIZE)
521     curstate = 1;
522     else
523     curstate = 0;
524    
525     if (state == curstate)
526     {
527     vchannel_write("ACK", "%u", serial);
528     vchannel_unblock();
529 ossman_ 1167 return;
530 ossman_ 1165 }
531    
532 ossman_ 1160 WaitForSingleObject(g_mutex, INFINITE);
533 ossman_ 1161 g_blocked_state_hwnd = hwnd;
534 ossman_ 1165 g_blocked_state_serial = serial;
535 ossman_ 1160 g_blocked_state = state;
536     ReleaseMutex(g_mutex);
537    
538 ossman_ 1165 vchannel_unblock();
539    
540 ossman_ 1160 if (state == 0)
541     ShowWindow(hwnd, SW_RESTORE);
542     else if (state == 1)
543     ShowWindow(hwnd, SW_MINIMIZE);
544     else if (state == 2)
545     ShowWindow(hwnd, SW_MAXIMIZE);
546     else
547     debug("Invalid state %d sent.", state);
548    
549     WaitForSingleObject(g_mutex, INFINITE);
550 ossman_ 1161 g_blocked_state_hwnd = NULL;
551 ossman_ 1160 g_blocked_state = -1;
552     ReleaseMutex(g_mutex);
553     }
554    
555 ossman_ 1071 DLL_EXPORT int
556     GetInstanceCount()
557 ossman_ 1069 {
558 ossman_ 1071 return g_instance_count;
559 ossman_ 1069 }
560    
561 ossman_ 1071 BOOL APIENTRY
562     DllMain(HINSTANCE hinstDLL, DWORD ul_reason_for_call, LPVOID lpReserved)
563 ossman_ 1069 {
564 ossman_ 1071 switch (ul_reason_for_call)
565     {
566     case DLL_PROCESS_ATTACH:
567     // remember our instance handle
568     g_instance = hinstDLL;
569 ossman_ 1069
570 ossman_ 1073 g_mutex = CreateMutex(NULL, FALSE, "Local\\SeamlessDLL");
571 ossman_ 1071 if (!g_mutex)
572     return FALSE;
573 ossman_ 1069
574 ossman_ 1071 WaitForSingleObject(g_mutex, INFINITE);
575     ++g_instance_count;
576     ReleaseMutex(g_mutex);
577 ossman_ 1069
578 ossman_ 1153 g_wm_seamless_focus = RegisterWindowMessage(FOCUS_MSG_NAME);
579    
580 ossman_ 1071 vchannel_open();
581 ossman_ 1069
582 ossman_ 1071 break;
583 ossman_ 1069
584 ossman_ 1071 case DLL_THREAD_ATTACH:
585     break;
586 ossman_ 1069
587 ossman_ 1071 case DLL_THREAD_DETACH:
588     break;
589 ossman_ 1069
590 ossman_ 1071 case DLL_PROCESS_DETACH:
591     WaitForSingleObject(g_mutex, INFINITE);
592     --g_instance_count;
593     ReleaseMutex(g_mutex);
594 ossman_ 1069
595 ossman_ 1071 vchannel_close();
596 ossman_ 1069
597 ossman_ 1071 CloseHandle(g_mutex);
598 ossman_ 1069
599 ossman_ 1071 break;
600     }
601 ossman_ 1069
602 ossman_ 1071 return TRUE;
603 ossman_ 1069 }

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26