/[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 937 - (show annotations)
Fri Jul 1 06:50:52 2005 UTC (18 years, 10 months ago) by astrand
File size: 18164 byte(s)
Indenting with astyle instead of indent

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

  ViewVC Help
Powered by ViewVC 1.1.26