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

Contents of /sourceforge.net/trunk/seamlessrdp/ClientDLL/clipper.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 938 - (show annotations)
Fri Jul 1 07:01:00 2005 UTC (18 years, 11 months ago) by astrand
File size: 17952 byte(s)
Added proper copyright headers

1 //
2 // Copyright (C) 2004-2005 Martin Wickett
3 //
4
5 #define TSDLL
6
7 #include "clipper.h"
8
9 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
10 {
11 UNREFERENCED_PARAMETER(lpvReserved);
12 UNREFERENCED_PARAMETER(hinstDLL);
13
14 switch (fdwReason) {
15 case DLL_PROCESS_ATTACH:
16 break;
17
18 case DLL_THREAD_ATTACH:
19 break;
20
21 case DLL_THREAD_DETACH:
22 break;
23
24 case DLL_PROCESS_DETACH:
25 break;
26
27 default:
28 break;
29 }
30 return TRUE;
31 }
32
33 void WINAPI VirtualChannelOpenEvent(DWORD openHandle, UINT event,
34 LPVOID pdata, UINT32 dataLength,
35 UINT32 totalLength, UINT32 dataFlags)
36 {
37 LPDWORD pdwControlCode = (LPDWORD) pdata;
38 CHAR ourData[1600];
39 UINT ui = 0;
40
41 UNREFERENCED_PARAMETER(openHandle);
42 UNREFERENCED_PARAMETER(dataFlags);
43
44 ZeroMemory(ourData, sizeof(ourData));
45
46 //copy the send string (with the same lenth of the data)
47 strncpy(ourData, (LPSTR) pdata, dataLength / sizeof(char));
48
49 if (OUTPUT_DEBUG_INFO == 1) {
50 OutputDebugString
51 ("TS WINDOW CLIPPER :: CLIENT DLL :: Info --> Virtual channel data received");
52 OutputDebugString(ourData);
53 }
54
55 if (dataLength == totalLength) {
56 switch (event) {
57 case CHANNEL_EVENT_DATA_RECEIVED: {
58 CTokenizer tok(_T((LPSTR) ourData), _T(";"));
59 CStdString cs;
60
61 CWindowData *wid = new CWindowData("");
62 CStdString messageType;
63 int mixMaxType = 0;
64
65 while (tok.Next(cs)) {
66 CStdString msg;
67 CTokenizer msgTok(cs, _T("="));
68
69 msgTok.Next(msg);
70
71 if (strcmp(msg, "MSG") == 0) {
72 msgTok.Next(msg);
73 messageType = msg;
74 }
75
76 if (strcmp(msg, "ID") == 0) {
77 msgTok.Next(msg);
78 wid->SetId(msg);
79 } else if (strcmp(msg, "TITLE") == 0) {
80 msgTok.Next(msg);
81 wid->SetTitle(msg);
82 } else if (strcmp(msg, "POS") == 0) {
83 msgTok.Next(msg);
84
85 CStdString pos;
86 CTokenizer posTok(msg, _T("~"));
87
88 posTok.Next(pos);
89
90
91 // check bounds, coords can be negative if window top left point is moved off the screen.
92 // we don't care about that since the window can't be see so just use zero.
93
94 if (strchr(pos, '-') == NULL) {
95 wid->SetX1(atoi(pos));
96 } else {
97 wid->SetX1(0);
98 }
99
100 posTok.Next(pos);
101
102 if (strchr(pos, '-') == NULL) {
103 wid->SetY1(atoi(pos));
104 } else {
105 wid->SetY1(0);
106 }
107
108 posTok.Next(pos);
109
110 if (strchr(pos, '-') == NULL) {
111 wid->SetX2(atoi(pos));
112 } else {
113 wid->SetX2(0);
114 }
115
116 posTok.Next(pos);
117
118 if (strchr(pos, '-') == NULL) {
119 wid->SetY2(atoi(pos));
120 } else {
121 wid->SetY2(0);
122 }
123 } else if (strcmp(msg, "TYPE") == 0) {
124 msgTok.Next(msg);
125 mixMaxType = atoi(msg);
126 }
127 }
128
129 if (strcmp(messageType, "HSHELL_WINDOWCREATED") == 0) {
130 if (OUTPUT_DEBUG_INFO == 1) {
131 OutputDebugString
132 ("TS WINDOW CLIPPER :: CLIENT DLL :: Info --> Message was of type HSHELL_WINDOWCREATED window title is:");
133 OutputDebugString(wid->GetTitle());
134 }
135
136 CStdString s = wid->GetId();
137 char *ptr;
138 int length = s.GetLength();
139 ptr = s.GetBufferSetLength(length);
140
141 hash_insert(ptr, wid, &m_ht);
142
143 CreateAndShowWindow(wid);
144
145 DoClipping(1);
146 } else if (strcmp(messageType, "HSHELL_WINDOWDESTROYED") == 0) {
147 if (OUTPUT_DEBUG_INFO == 1) {
148 OutputDebugString
149 ("TS WINDOW CLIPPER :: CLIENT DLL :: Info --> Message was of type HSHELL_WINDOWDISTROYED window title is:");
150 OutputDebugString(wid->GetTitle());
151 }
152
153 CStdString s = wid->GetId();
154 char *ptr;
155 int length = s.GetLength();
156 ptr = s.GetBufferSetLength(length);
157
158 CWindowData *oldWinData =
159 (CWindowData *) hash_del(ptr, &m_ht);
160
161 DestroyTaskbarWindow(oldWinData);
162
163 delete oldWinData;
164
165 DoClipping(1);
166 } else if (strcmp(messageType, "HCBT_MINMAX") == 0) {
167 if (OUTPUT_DEBUG_INFO == 1) {
168 OutputDebugString
169 ("TS WINDOW CLIPPER :: CLIENT DLL :: Info --> Message was of type HCBT_MINMAX");
170 }
171
172
173 //TODO
174
175 } else if (strcmp(messageType, "HCBT_MOVESIZE") == 0) {
176 if (OUTPUT_DEBUG_INFO == 1) {
177 OutputDebugString
178 ("TS WINDOW CLIPPER :: CLIENT DLL :: Info --> Message was of type HCBT_MOVESIZE window title is:");
179 OutputDebugString(wid->GetTitle());
180 }
181
182 CStdString s = wid->GetId();
183 char *ptr;
184 int length = s.GetLength();
185 ptr = s.GetBufferSetLength(length);
186
187 CWindowData *movedWinData =
188 (CWindowData *) hash_lookup(ptr, &m_ht);
189
190 if (movedWinData != NULL) {
191 movedWinData->SetX1(wid->GetX1());
192 movedWinData->SetX2(wid->GetX2());
193 movedWinData->SetY1(wid->GetY1());
194 movedWinData->SetY2(wid->GetY2());
195
196 DoClipping(1);
197 }
198
199 delete wid;
200 } else if (strcmp(messageType, "CALLWNDPROC_WM_MOVING") == 0) {
201 if (OUTPUT_DEBUG_INFO == 1) {
202 OutputDebugString
203 ("TS WINDOW CLIPPER :: CLIENT DLL :: Info --> Message was of type CALLWNDPROC_WM_MOVING window title is:");
204 OutputDebugString(wid->GetTitle());
205 }
206
207 CStdString s = wid->GetId();
208 char *ptr;
209 int length = s.GetLength();
210 ptr = s.GetBufferSetLength(length);
211
212 CWindowData *movedWinData =
213 (CWindowData *) hash_lookup(ptr, &m_ht);
214
215 if (movedWinData != NULL) {
216 movedWinData->SetX1(wid->GetX1());
217 movedWinData->SetX2(wid->GetX2());
218 movedWinData->SetY1(wid->GetY1());
219 movedWinData->SetY2(wid->GetY2());
220
221 ////might be too much of an overhead forcing the redraw here. Might be better to do 'DoClipping(0)' instead?
222 DoClipping(1);
223 }
224
225 delete wid;
226 }
227 }
228 break;
229
230 case CHANNEL_EVENT_WRITE_COMPLETE: {}
231 break;
232
233 case CHANNEL_EVENT_WRITE_CANCELLED: {}
234 break;
235
236 default: {}
237 break;
238 }
239 } else {}
240 }
241
242
243 VOID VCAPITYPE VirtualChannelInitEventProc(LPVOID pInitHandle, UINT event,
244 LPVOID pData, UINT dataLength)
245 {
246 UINT ui;
247
248 UNREFERENCED_PARAMETER(pInitHandle);
249 UNREFERENCED_PARAMETER(dataLength);
250
251 switch (event) {
252 case CHANNEL_EVENT_INITIALIZED: {}
253 break;
254
255 case CHANNEL_EVENT_CONNECTED: {
256 //
257 // open channel
258 //
259 ui = gpEntryPoints->pVirtualChannelOpen(gphChannel,
260 &gdwOpenChannel,
261 CHANNELNAME,
262 (PCHANNEL_OPEN_EVENT_FN)
263 VirtualChannelOpenEvent);
264
265 if (ui == CHANNEL_RC_OK) {}
266 else {
267 MessageBox(NULL, TEXT("Open of RDP virtual channel failed"),
268 TEXT("TS Window Clipper"), MB_OK);
269 }
270
271 if (ui != CHANNEL_RC_OK) {
272 return;
273 }
274 }
275 break;
276
277 case CHANNEL_EVENT_V1_CONNECTED: {
278 MessageBox(NULL,
279 TEXT
280 ("Connecting to a non Windows 2000 Terminal Server"),
281 TEXT("TS Window Clipper"), MB_OK);
282 }
283 break;
284
285 case CHANNEL_EVENT_DISCONNECTED: {}
286 break;
287
288 case CHANNEL_EVENT_TERMINATED: {
289 //
290 // free the entry points table
291 //
292 LocalFree((HLOCAL) gpEntryPoints);
293 }
294 break;
295
296 default: {}
297 break;
298 }
299 }
300
301 BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
302 {
303 CHANNEL_DEF cd;
304 UINT uRet;
305
306 size_t s = 10;
307 hash_construct_table(&m_ht, s);
308
309 //
310 // allocate memory
311 //
312 gpEntryPoints =
313 (PCHANNEL_ENTRY_POINTS) LocalAlloc(LPTR, pEntryPoints->cbSize);
314
315 memcpy(gpEntryPoints, pEntryPoints, pEntryPoints->cbSize);
316
317 //
318 // initialize CHANNEL_DEF structure
319 //
320 ZeroMemory(&cd, sizeof(CHANNEL_DEF));
321 strcpy(cd.name, CHANNELNAME); // ANSI ONLY
322
323 //
324 // register channel
325 //
326 uRet =
327 gpEntryPoints->pVirtualChannelInit((LPVOID *) & gphChannel,
328 (PCHANNEL_DEF) & cd, 1,
329 VIRTUAL_CHANNEL_VERSION_WIN2000,
330 (PCHANNEL_INIT_EVENT_FN)
331 VirtualChannelInitEventProc);
332
333 if (uRet == CHANNEL_RC_OK) {
334 if (ALWAYS__CLIP) {
335 DoClipping(1);
336 }
337 } else {
338 MessageBox(NULL, TEXT("RDP Virtual channel Init Failed"),
339 TEXT("TS Window Clipper"), MB_OK);
340 }
341
342 if (uRet != CHANNEL_RC_OK) {
343 return FALSE;
344 }
345
346 //
347 // make sure channel was initialized
348 //
349 if (cd.options != CHANNEL_OPTION_INITIALIZED) {
350 return FALSE;
351 }
352
353 return TRUE;
354 }
355
356
357 // data structure to transfer informations
358 typedef struct _WindowFromProcessOrThreadID
359 {
360 union
361 {
362 DWORD procId;
363 DWORD threadId;
364 };
365 HWND hWnd;
366 }
367 Wnd4PTID;
368
369 // Callback procedure
370 BOOL CALLBACK PrivateEnumWindowsProc(HWND hwnd, LPARAM lParam)
371 {
372 DWORD procId;
373 DWORD threadId;
374 Wnd4PTID *tmp = (Wnd4PTID *) lParam;
375 // get the process/thread id of current window
376 threadId = GetWindowThreadProcessId(hwnd, &procId);
377 // check if the process/thread id equal to the one passed by lParam?
378 if (threadId == tmp->threadId || procId == tmp->procId) {
379 // check if the window is a main window
380 // because there lots of windows belong to the same process/thread
381 LONG dwStyle = GetWindowLong(hwnd, GWL_STYLE);
382 if (dwStyle & WS_SYSMENU) {
383 tmp->hWnd = hwnd;
384 return FALSE; // break the enumeration
385 }
386 }
387 return TRUE; // continue the enumeration
388 }
389
390 // Enumarate all the MainWindow of the system
391 HWND FindProcessMainWindow(DWORD procId)
392 {
393 Wnd4PTID tempWnd4ID;
394 tempWnd4ID.procId = procId;
395 if (!EnumWindows
396 ((WNDENUMPROC) PrivateEnumWindowsProc, (LPARAM) & tempWnd4ID)) {
397
398 if (OUTPUT_DEBUG_INFO == 1) {
399 OutputDebugString
400 ("TS WINDOW CLIPPER :: CLIENT DLL :: Info --> Found main process window");
401 }
402
403 return tempWnd4ID.hWnd;
404 }
405
406
407 if (OUTPUT_DEBUG_INFO == 1) {
408 OutputDebugString
409 ("TS WINDOW CLIPPER :: CLIENT DLL :: Info --> Could not find main process window");
410 }
411
412 return NULL;
413 }
414
415
416 void DoClipping(int forceRedraw)
417 {
418 //if main window handle is null, try to get it
419 if (m_mainWindowHandle == NULL) {
420 m_mainWindowHandle = FindProcessMainWindow(GetCurrentProcessId());
421
422 //hide the window from taskbar and put at the back of the z order
423 if (HIDE_TSAC_WINDOW == 1) {
424 ShowWindow(m_mainWindowHandle, SW_HIDE);
425 SetWindowLongPtr(m_mainWindowHandle, GWL_EXSTYLE,
426 GetWindowLong(m_mainWindowHandle,
427 GWL_EXSTYLE) | WS_EX_TOOLWINDOW);
428 ShowWindow(m_mainWindowHandle, SW_SHOW);
429 }
430
431 SetWindowPos(m_mainWindowHandle, HWND_NOTOPMOST, 0, 0, 0, 0,
432 SWP_NOMOVE | SWP_NOSIZE);
433 }
434
435 //if we have the handle, lets use it for the clipping
436 if (m_mainWindowHandle != NULL) {
437 RECT wRect;
438 GetWindowRect(m_mainWindowHandle, &wRect);
439
440 if (OUTPUT_DEBUG_INFO == 1) {
441 OutputDebugString
442 ("TS WINDOW CLIPPER :: CLIENT DLL :: Info --> Restarting clipping...");
443 }
444
445 m_regionResult = NULL;
446
447 if (OUTPUT_WINDOW_TABLE_DEBUG_INFO == 1) {
448 OutputDebugString
449 ("-----------------------------------------------------------------------------");
450 OutputDebugString
451 ("TS WINDOW CLIPPER :: CLIENT DLL :: Info --> starting printing of window table");
452 }
453
454 //enumerate though hashtable
455 if (&m_ht != NULL) {
456 hash_enumerate(&m_ht, CreateRegionFromWindowData);
457 }
458
459 if (OUTPUT_WINDOW_TABLE_DEBUG_INFO == 1) {
460 OutputDebugString
461 ("TS WINDOW CLIPPER :: CLIENT DLL :: Info --> finished printing of window table");
462 OutputDebugString
463 ("-----------------------------------------------------------------------------");
464 }
465
466 if (m_regionResult == NULL) {
467 if (ALWAYS__CLIP) {
468 m_regionResult = CreateRectRgn(0, 0, 0, 0);
469 } else {
470 m_regionResult =
471 CreateRectRgn(0, 0, wRect.right, wRect.bottom);
472 }
473 }
474
475 SetWindowRgn(m_mainWindowHandle, (HRGN__ *) m_regionResult, TRUE);
476
477 if (forceRedraw == 1) {
478 // invalidate the window and force it to redraw
479 RedrawWindow(m_mainWindowHandle, NULL, NULL,
480 RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
481 }
482 } else {
483 if (OUTPUT_DEBUG_INFO == 1) {
484 OutputDebugString
485 ("TS WINDOW CLIPPER :: CLIENT DLL :: Info --> Coulf not find window to clip");
486 }
487 }
488 }
489
490 void CreateRegionFromWindowData(char *key, void *value)
491 {
492 CWindowData *wd;
493 wd = (CWindowData *) value;
494 int x1 = 0, x2 = 0, y1 = 0, y2 = 0;
495
496 char strB[5];
497 char strT[5];
498 char strL[5];
499 char strR[5];
500
501 if (m_regionResult == NULL) {
502 m_regionResult = CreateRectRgn(0, 0, 0, 0);
503 }
504
505 if (OUTPUT_DEBUG_INFO == 1 && OUTPUT_WINDOW_TABLE_DEBUG_INFO != 1) {
506 OutputDebugString
507 ("TS WINDOW CLIPPER :: CLIENT DLL :: Info --> Adding this window to cliping region");
508 OutputDebugString(wd->GetTitle());
509 }
510 if (OUTPUT_WINDOW_TABLE_DEBUG_INFO == 1) {
511 ltoa(wd->GetY2(), strB, 10);
512 ltoa(wd->GetY1(), strT, 10);
513 ltoa(wd->GetX2(), strR, 10);
514 ltoa(wd->GetX1(), strL, 10);
515
516 OutputDebugString("This window is in the table:");
517 OutputDebugString(wd->GetTitle());
518 OutputDebugString(wd->GetId());
519 OutputDebugString(strL);
520 OutputDebugString(strT);
521 OutputDebugString(strR);
522 OutputDebugString(strB);
523 OutputDebugString("*******************");
524 }
525
526 HRGN newRegion =
527 CreateRectRgn(wd->GetX1(), wd->GetY1(), wd->GetX2(), wd->GetY2());
528
529 CombineRgn(m_regionResult, newRegion, m_regionResult, RGN_OR);
530 }
531
532 /*
533 Dummy procedure to catch when window is being maximised.
534
535 Need to tell the window on the server to do the same.
536 */
537 LRESULT CALLBACK DummyWindowCallbackProc(HWND hwnd, UINT uMsg, WPARAM wParam,
538 LPARAM lParam)
539 {
540 //TODO
541
542 return DefWindowProc(hwnd, uMsg, wParam, lParam);
543 }
544
545 void CreateAndShowWindow(CWindowData * wd)
546 {
547 if (classAlreadyRegistered == 0) {
548 static const char *szWndName = "WTSWinClipperDummy";
549 WNDCLASS wc;
550
551 wc.style = 0;
552 wc.lpfnWndProc = DummyWindowCallbackProc;
553 wc.cbClsExtra = 0;
554 wc.cbWndExtra = 0;
555 wc.hInstance = 0;
556 wc.hIcon = 0;
557 wc.hCursor = 0;
558 wc.hbrBackground = 0;
559 wc.lpszMenuName = 0;
560 wc.lpszClassName = szWndName;
561
562 if (RegisterClass(&wc)) {
563 classAlreadyRegistered = 1;
564 }
565 }
566
567 if (classAlreadyRegistered = 1) {
568 HWND hWnd =
569 CreateWindow(TEXT("WTSWinClipperDummy"), wd->GetTitle(), WS_POPUP,
570 0, 0, 0, 0, 0, 0, 0, 0);
571 ShowWindow(hWnd, 3);
572 SetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOREDRAW);
573 wd->TaskbarWindowHandle = hWnd;
574 SetFocus(m_mainWindowHandle);
575 }
576 }
577
578 void DestroyTaskbarWindow(CWindowData * wd)
579 {
580 if (wd->TaskbarWindowHandle != NULL) {
581 DestroyWindow(wd->TaskbarWindowHandle);
582 }
583 }

  ViewVC Help
Powered by ViewVC 1.1.26