/[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 930 - (show annotations)
Thu Jun 30 14:14:56 2005 UTC (18 years, 11 months ago) by astrand
File size: 14866 byte(s)
Should have UNIX LF linebreaks, when running CVS from UNIX.

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

  ViewVC Help
Powered by ViewVC 1.1.26