Incorporate rosapps. 0.3.15 was branched somewhat incorrectly so rosapps is not synce...
[reactos.git] / modules / rosapps / applications / net / tsclient / porting-tools / rdesktop-core-tester / rdesktop-core-tester.cpp
1 #include "stdafx.h"
2
3 #include <zmouse.h>
4
5 #include "rdesktop/rdesktop.h"
6 #include "rdesktop/proto.h"
7
8 extern "C"
9 {
10 /* ==== BEGIN POOP ==== */
11 // Temporary implementations of stuff we totally positively need to make the Real Thing happy
12 /* produce a hex dump */
13 void
14 hexdump(unsigned char *p, unsigned int len)
15 {
16 unsigned char *line = p;
17 int i, thisline;
18 unsigned int offset = 0;
19
20 while (offset < len)
21 {
22 printf("%04x ", offset);
23 thisline = len - offset;
24 if (thisline > 16)
25 thisline = 16;
26
27 for (i = 0; i < thisline; i++)
28 printf("%02x ", line[i]);
29
30 for (; i < 16; i++)
31 printf(" ");
32
33 for (i = 0; i < thisline; i++)
34 printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
35
36 printf("\n");
37 offset += thisline;
38 line += thisline;
39 }
40 }
41
42 void generate_random(uint8 * random)
43 {
44 memcpy(random, "12345678901234567890123456789012", 32);
45 }
46
47 /* report an error */
48 void
49 error(char *format, ...)
50 {
51 va_list ap;
52
53 fprintf(stderr, "ERROR: ");
54
55 va_start(ap, format);
56 vfprintf(stderr, format, ap);
57 va_end(ap);
58 }
59
60 /* report a warning */
61 void
62 warning(char *format, ...)
63 {
64 va_list ap;
65
66 fprintf(stderr, "WARNING: ");
67
68 va_start(ap, format);
69 vfprintf(stderr, format, ap);
70 va_end(ap);
71 }
72
73 /* report an unimplemented protocol feature */
74 void
75 unimpl(char *format, ...)
76 {
77 va_list ap;
78
79 fprintf(stderr, "NOT IMPLEMENTED: ");
80
81 va_start(ap, format);
82 vfprintf(stderr, format, ap);
83 va_end(ap);
84 }
85
86 /* Create the bitmap cache directory */
87 BOOL
88 rd_pstcache_mkdir(void)
89 {
90 char *home;
91 char bmpcache_dir[256];
92
93 home = getenv("HOME");
94
95 if (home == NULL)
96 return False;
97
98 sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop");
99
100 if ((_mkdir(bmpcache_dir) == -1) && errno != EEXIST)
101 {
102 perror(bmpcache_dir);
103 return False;
104 }
105
106 sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop/cache");
107
108 if ((_mkdir(bmpcache_dir) == -1) && errno != EEXIST)
109 {
110 perror(bmpcache_dir);
111 return False;
112 }
113
114 return True;
115 }
116
117 /* open a file in the .rdesktop directory */
118 int
119 rd_open_file(char *filename)
120 {
121 char *home;
122 char fn[256];
123 int fd;
124
125 home = getenv("HOME");
126 if (home == NULL)
127 return -1;
128 sprintf(fn, "%s/.rdesktop/%s", home, filename);
129 fd = _open(fn, _O_RDWR | _O_CREAT, 0);
130 if (fd == -1)
131 perror(fn);
132 return fd;
133 }
134
135 /* close file */
136 void
137 rd_close_file(int fd)
138 {
139 _close(fd);
140 }
141
142 /* read from file*/
143 int
144 rd_read_file(int fd, void *ptr, int len)
145 {
146 return _read(fd, ptr, len);
147 }
148
149 /* write to file */
150 int
151 rd_write_file(int fd, void *ptr, int len)
152 {
153 return _write(fd, ptr, len);
154 }
155
156 /* move file pointer */
157 int
158 rd_lseek_file(int fd, int offset)
159 {
160 return _lseek(fd, offset, SEEK_SET);
161 }
162
163 /* do a write lock on a file */
164 BOOL
165 rd_lock_file(int fd, int start, int len)
166 {
167 // TODOOO...
168 return False;
169 }
170
171 int
172 load_licence(RDPCLIENT * This, unsigned char **data)
173 {
174 return -1;
175 }
176
177 void
178 save_licence(RDPCLIENT * This, unsigned char *data, int length)
179 {
180 }
181
182 /* ==== END POOP ==== */
183
184 /* ==== UI ==== */
185 // Globals are totally teh evil, but cut me some slack here
186 HWND hwnd;
187 HBITMAP hbmBuffer;
188 PVOID pBuffer;
189 HDC hdcBuffer;
190 UINT wmZMouseWheel;
191
192 };
193
194 static
195 void
196 mstsc_mousewheel(RDPCLIENT * This, int value, LPARAM lparam)
197 {
198 uint16 button;
199
200 if(value < 0)
201 button = MOUSE_FLAG_BUTTON5;
202 else
203 button = MOUSE_FLAG_BUTTON4;
204
205 if(value < 0)
206 value = - value;
207
208 for(int click = 0; click < value; click += WHEEL_DELTA)
209 rdp_send_input(This, GetTickCount(), RDP_INPUT_MOUSE, button | MOUSE_FLAG_DOWN, LOWORD(lparam), HIWORD(lparam));
210 }
211
212 static
213 LRESULT
214 CALLBACK
215 mstsc_WndProc(HWND hwnd, UINT uMsg, WPARAM wparam, LPARAM lparam)
216 {
217 // BUGBUG: LongToPtr & PtrToLong will break on Win64
218
219 RDPCLIENT * This = reinterpret_cast<RDPCLIENT *>(LongToPtr(GetWindowLongPtr(hwnd, GWLP_USERDATA)));
220
221 switch(uMsg)
222 {
223 case WM_CLOSE:
224 DestroyWindow(hwnd);
225 break;
226
227 // FIXME: temporary
228 case WM_DESTROY:
229 PostQuitMessage(0);
230 break;
231
232 /* Initialization */
233 case WM_CREATE:
234 This = static_cast<RDPCLIENT *>(reinterpret_cast<LPCREATESTRUCT>(lparam)->lpCreateParams);
235 SetWindowLongPtr(hwnd, GWLP_USERDATA, PtrToLong(This));
236 break;
237
238 /* Painting */
239 case WM_PRINTCLIENT:
240 if(wparam == 0)
241 break;
242
243 case WM_PAINT:
244 {
245 HDC hdc = (HDC)wparam;
246
247 // A DC was provided: print the whole client area into it
248 if(hdc)
249 {
250 RECT rc;
251 GetClientRect(hwnd, &rc);
252 BitBlt(hdc, 0, 0, rc.right, rc.bottom, hdcBuffer, 0, 0, SRCCOPY);
253 }
254 // Otherwise, we're refreshing to screen
255 else
256 {
257 PAINTSTRUCT ps;
258 hdc = BeginPaint(hwnd, &ps);
259
260 BitBlt
261 (
262 hdc,
263 ps.rcPaint.left,
264 ps.rcPaint.top,
265 ps.rcPaint.right - ps.rcPaint.left,
266 ps.rcPaint.bottom - ps.rcPaint.top,
267 hdcBuffer,
268 ps.rcPaint.left,
269 ps.rcPaint.top,
270 SRCCOPY
271 );
272
273 EndPaint(hwnd, &ps);
274 }
275 }
276
277 break;
278
279 /* Keyboard stuff */
280 case WM_SYSKEYDOWN:
281 case WM_KEYDOWN:
282 rdp_send_input(This, GetMessageTime(), RDP_INPUT_SCANCODE, RDP_KEYPRESS | (lparam & 0x1000000 ? KBD_FLAG_EXT : 0), LOBYTE(HIWORD(lparam)), 0);
283 break;
284
285 case WM_SYSKEYUP:
286 case WM_KEYUP:
287 rdp_send_input(This, GetMessageTime(), RDP_INPUT_SCANCODE, RDP_KEYRELEASE | (lparam & 0x1000000 ? KBD_FLAG_EXT : 0), LOBYTE(HIWORD(lparam)), 0);
288 break;
289
290 /* Mouse stuff */
291 // Cursor shape
292 case WM_SETCURSOR:
293 if(LOWORD(lparam) == HTCLIENT)
294 {
295 //SetCursor(hcursor);
296 return TRUE;
297 }
298
299 break;
300
301 // Movement
302 case WM_MOUSEMOVE:
303 //if(This->sendmotion || wparam & (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON | MK_XBUTTON1 | MK_XBUTTON2))
304 rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_MOVE, LOWORD(lparam), HIWORD(lparam));
305
306 break;
307
308 // Buttons
309 // TODO: X buttons
310 case WM_LBUTTONDOWN:
311 rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1 | MOUSE_FLAG_DOWN, LOWORD(lparam), HIWORD(lparam));
312 break;
313
314 case WM_RBUTTONDOWN:
315 rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON2 | MOUSE_FLAG_DOWN, LOWORD(lparam), HIWORD(lparam));
316 break;
317
318 case WM_MBUTTONDOWN:
319 rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON3 | MOUSE_FLAG_DOWN, LOWORD(lparam), HIWORD(lparam));
320 break;
321
322 case WM_LBUTTONUP:
323 rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON1, LOWORD(lparam), HIWORD(lparam));
324 break;
325
326 case WM_RBUTTONUP:
327 rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON2, LOWORD(lparam), HIWORD(lparam));
328 break;
329
330 case WM_MBUTTONUP:
331 rdp_send_input(This, GetMessageTime(), RDP_INPUT_MOUSE, MOUSE_FLAG_BUTTON3, LOWORD(lparam), HIWORD(lparam));
332 break;
333
334 // Wheel
335 case WM_MOUSEWHEEL:
336 mstsc_mousewheel(This, (SHORT)HIWORD(wparam), lparam);
337 break;
338
339 default:
340 /* Registered messages */
341 // Z-Mouse wheel support - you know, just in case
342 if(uMsg == wmZMouseWheel)
343 {
344 mstsc_mousewheel(This, (int)wparam, lparam);
345 break;
346 }
347
348 /* Unhandled messages */
349 return DefWindowProc(hwnd, uMsg, wparam, lparam);
350 }
351
352 return 0;
353 }
354
355 static
356 DWORD
357 WINAPI
358 mstsc_ProtocolIOThread
359 (
360 LPVOID lpArgument
361 )
362 {
363 RDPCLIENT * This = static_cast<RDPCLIENT *>(lpArgument);
364
365 WCHAR hostname[MAX_COMPUTERNAME_LENGTH + 1];
366 DWORD dw = ARRAYSIZE(hostname);
367 GetComputerNameW(hostname, &dw);
368
369 uint32 flags = RDP_LOGON_NORMAL | RDP_LOGON_COMPRESSION | RDP_LOGON_COMPRESSION2;
370
371 rdp_connect(This, "10.0.0.3", flags, L"Administrator", L"", L"", L"", L"", hostname, "");
372 //rdp_connect(This, "192.168.7.232", flags, "", "", "", "");
373
374 hdcBuffer = CreateCompatibleDC(NULL);
375
376 BITMAPINFO bmi;
377 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
378 bmi.bmiHeader.biWidth = This->width;
379 bmi.bmiHeader.biHeight = This->height;
380 bmi.bmiHeader.biPlanes = 1;
381 bmi.bmiHeader.biBitCount = This->server_depth;
382 bmi.bmiHeader.biCompression = BI_RGB;
383 bmi.bmiHeader.biSizeImage = 0;
384 bmi.bmiHeader.biXPelsPerMeter = 0;
385 bmi.bmiHeader.biYPelsPerMeter = 0;
386 bmi.bmiHeader.biClrUsed = 0; // TODO! palette displays
387 bmi.bmiHeader.biClrImportant = 0; // TODO! palette displays
388
389 hbmBuffer = CreateDIBSection(hdcBuffer, &bmi, DIB_RGB_COLORS, &pBuffer, NULL, 0);
390
391 SelectObject(hdcBuffer, hbmBuffer);
392
393 #if 0
394 rcClip.left = 0;
395 rcClip.top = 0;
396 rcClip.right = This->width + 1;
397 rcClip.bottom = This->height + 1;
398 #endif
399
400 BOOL deactivated;
401 uint32 ext_disc_reason;
402
403 rdp_main_loop(This, &deactivated, &ext_disc_reason);
404 // TODO: handle redirection
405 // EVENT: OnDisconnect
406
407 SendMessage(hwnd, WM_CLOSE, 0, 0);
408
409 return 0;
410 }
411
412 /* Virtual channel stuff */
413 extern "C" void channel_process(RDPCLIENT * This, STREAM s, uint16 mcs_channel)
414 {
415 }
416
417 DWORD tlsIndex;
418
419 typedef struct CHANNEL_HANDLE_
420 {
421 RDPCLIENT * client;
422 int channel;
423 }
424 CHANNEL_HANDLE;
425
426 static
427 UINT
428 VCAPITYPE
429 VirtualChannelInit
430 (
431 LPVOID * ppInitHandle,
432 PCHANNEL_DEF pChannel,
433 INT channelCount,
434 ULONG versionRequested,
435 PCHANNEL_INIT_EVENT_FN pChannelInitEventProc
436 )
437 {
438 if(channelCount <= 0)
439 return CHANNEL_RC_BAD_CHANNEL;
440
441 if(ppInitHandle == NULL)
442 return CHANNEL_RC_BAD_INIT_HANDLE;
443
444 if(pChannel == NULL)
445 return CHANNEL_RC_BAD_CHANNEL;
446
447 if(pChannelInitEventProc == NULL)
448 return CHANNEL_RC_BAD_PROC;
449
450 RDPCLIENT * This = (RDPCLIENT *)TlsGetValue(tlsIndex);
451
452 if(This == NULL)
453 return CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY;
454
455 if(This->num_channels + channelCount > CHANNEL_MAX_COUNT)
456 return CHANNEL_RC_TOO_MANY_CHANNELS;
457
458 for(INT i = 0; i < channelCount; ++ i)
459 {
460 if(strlen(pChannel[i].name) > CHANNEL_NAME_LEN)
461 return CHANNEL_RC_BAD_CHANNEL;
462 }
463
464 memcpy(This->channel_defs + This->num_channels, pChannel, sizeof(*pChannel) * channelCount);
465
466 #if 0 // TODO
467 for(INT i = 0; i < channelCount; ++ i)
468 {
469 pChannel[i].options |= CHANNEL_OPTION_INITIALIZED;
470
471 int j = This->num_channels + i;
472 This->channel_data[j].opened = 0;
473 This->channel_data[j].pChannelInitEventProc = pChannelInitEventProc;
474 This->channel_data[j].pChannelOpenEventProc = NULL;
475 }
476 #endif
477
478 This->num_channels += channelCount;
479
480 *ppInitHandle = This;
481
482 return CHANNEL_RC_OK;
483 }
484
485 UINT
486 VCAPITYPE
487 VirtualChannelOpen
488 (
489 LPVOID pInitHandle,
490 LPDWORD pOpenHandle,
491 PCHAR pChannelName,
492 PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc
493 )
494 {
495 if(pInitHandle == NULL)
496 return CHANNEL_RC_BAD_INIT_HANDLE;
497
498 if(pOpenHandle == NULL)
499 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
500
501 if(pChannelName == NULL)
502 return CHANNEL_RC_UNKNOWN_CHANNEL_NAME;
503
504 if(pChannelOpenEventProc == NULL)
505 return CHANNEL_RC_BAD_PROC;
506
507 RDPCLIENT * This = (RDPCLIENT *)pInitHandle;
508
509 #if 0 // TODO
510 for(unsigned i = 0; i < This->num_channels; ++ i)
511 {
512 if(strcmp(pChannelName, This->channel_defs[i].name) == 0)
513 {
514 if(This->channel_data[i].opened)
515 return CHANNEL_RC_ALREADY_OPEN;
516
517 This->channel_data[i].opened = 1;
518 This->channel_data[i].pChannelOpenEventProc = pChannelOpenEventProc;
519
520 // TODO: allocate a handle here
521 *pOpenHandle = 0;
522
523 break;
524 }
525 }
526 #endif
527
528 return CHANNEL_RC_OK;
529 }
530
531 UINT VCAPITYPE VirtualChannelClose
532 (
533 DWORD openHandle
534 )
535 {
536 // TODO: channel handle management
537 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
538 }
539
540 UINT VCAPITYPE VirtualChannelWrite
541 (
542 DWORD openHandle,
543 LPVOID pData,
544 ULONG dataLength,
545 LPVOID pUserData
546 )
547 {
548 // TODO
549 return CHANNEL_RC_BAD_CHANNEL_HANDLE;
550 }
551
552 int wmain()
553 {
554 WSADATA wsd;
555 WSAStartup(MAKEWORD(2, 2), &wsd);
556
557 static RDPCLIENT This_; // NOTE: this is HUGE and would overflow the stack!
558 ZeroMemory(&This_, sizeof(This_));
559
560 RDPCLIENT * This = &This_;
561
562 /*
563 Threading model for MissTosca:
564 - main thread is the GUI thread. Message loop maintained by caller
565 - protocol I/O is handled in an I/O thread (or thread pool)
566 - extra threads maintained by virtual channel handlers. Virtual channel writes are thread-neutral
567
568 How we handle drawing: at the moment just an off-screen buffer we dump on-screen when asked to.
569 Still considering how to draw on-screen directly and *then* buffering off-screen (for example,
570 when running inside another remote session)
571 */
572
573 // FIXME: keyboard mess
574 This->keylayout = 0x409;
575 This->keyboard_type = 0x4;
576 This->keyboard_subtype = 0x0;
577 This->keyboard_functionkeys = 0xc;
578 This->width = 800;
579 This->height = 600;
580 This->server_depth = 24;
581 This->bitmap_compression = True;
582 //This->sendmotion = True;
583 This->bitmap_cache = True;
584 This->bitmap_cache_persist_enable = False;
585 This->bitmap_cache_precache = True;
586 This->encryption = True;
587 This->packet_encryption = True;
588 This->desktop_save = True;
589 This->polygon_ellipse_orders = False; // = True;
590 //This->fullscreen = False;
591 //This->grab_keyboard = True;
592 //This->hide_decorations = False;
593 This->use_rdp5 = True;
594 //This->rdpclip = True;
595 This->console_session = False;
596 //This->numlock_sync = False;
597 //This->seamless_rdp = False;
598 This->rdp5_performanceflags = RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS;
599 This->tcp_port_rdp = TCP_PORT_RDP;
600
601 #define NOT_SET -1
602 This->cache.bmpcache_lru[0] = NOT_SET;
603 This->cache.bmpcache_lru[1] = NOT_SET;
604 This->cache.bmpcache_lru[2] = NOT_SET;
605 This->cache.bmpcache_mru[0] = NOT_SET;
606 This->cache.bmpcache_mru[1] = NOT_SET;
607 This->cache.bmpcache_mru[2] = NOT_SET;
608
609 This->rdp.current_status = 1;
610
611 //hcursor = NULL;
612
613 WNDCLASS wc;
614 ZeroMemory(&wc, sizeof(wc));
615
616 wc.lpfnWndProc = mstsc_WndProc;
617 wc.hbrBackground = static_cast<HBRUSH>(GetStockObject(HOLLOW_BRUSH));
618 wc.lpszClassName = TEXT("MissTosca_Desktop");
619
620 wmZMouseWheel = RegisterWindowMessage(MSH_MOUSEWHEEL);
621
622 ATOM a = RegisterClass(&wc);
623
624 hwnd = CreateWindow
625 (
626 MAKEINTATOM(a),
627 NULL,
628 WS_POPUP | WS_VISIBLE,
629 CW_USEDEFAULT,
630 CW_USEDEFAULT,
631 This->width,
632 This->height,
633 NULL,
634 NULL,
635 NULL,
636 This
637 );
638
639 // The righ time to start the protocol thread
640 DWORD dwThreadId;
641 HANDLE hThread = CreateThread(NULL, 0, mstsc_ProtocolIOThread, This, 0, &dwThreadId);
642
643 // Your standard, garden variety message loop
644 MSG msg;
645
646 while(GetMessage(&msg, NULL, 0, 0))
647 {
648 TranslateMessage(&msg);
649 DispatchMessage(&msg);
650 }
651 }
652
653 // EOF