/[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 992 - (show annotations)
Sun Aug 28 12:56:38 2005 UTC (18 years, 10 months ago) by astrand
File size: 19654 byte(s)
Indenting with the CVS version of astyle

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