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