/[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 933 - (show annotations)
Thu Jun 30 14:46:14 2005 UTC (19 years ago) by astrand
File size: 18714 byte(s)
Fixed indentation, by running indent-all.

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

  ViewVC Help
Powered by ViewVC 1.1.26