Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

736 lines
17 KiB

  1. /*++
  2. * File name:
  3. * glyphspy.c
  4. * Contents:
  5. * UI for spying and recording glyphs reveived by RDP client
  6. --*/
  7. #include <windows.h>
  8. #include <stdio.h>
  9. #include <stdarg.h>
  10. #include <malloc.h>
  11. #include "..\lib\feedback.h"
  12. #include "..\lib\bmpdb.h"
  13. #include "resource.h"
  14. #define CLIENT_EXE "mstsc.exe"
  15. #define TRACE(_x_) {_MyPrintMessage _x_;}
  16. // Dialog functions
  17. VOID AddBitmapDialog(HINSTANCE hInst, HWND hWnd, PBMPENTRY pBitmap);
  18. VOID BrowseBitmapsDialog(HINSTANCE hInst, HWND hWnd);
  19. /*
  20. * Global data
  21. */
  22. HWND g_hMainWindow; // Main window handle
  23. HINSTANCE g_hInstance; // executable instance
  24. HINSTANCE g_hPrevInstance; // previous instance
  25. DWORD g_pidRDP = 0; // Process Id of the RDP client
  26. HANDLE g_hRDP = NULL; // Process handle of the client
  27. #define HISTSIZE 150 // Size of the history list
  28. UINT g_nCurSize = 0; // Current size
  29. UINT g_nScrollPos = 0; // Vertical scroll position
  30. BMPENTRY g_Bmp[HISTSIZE]; // The history list
  31. /*++
  32. * Function:
  33. * _CompareBitmaps
  34. * Description:
  35. * Compares two bitmaps
  36. * Arguments:
  37. * pBmp - bitmap to compare to
  38. * pData - bits of the second bitmap
  39. * xSize - size of the second bitmap
  40. * ySize
  41. * bmiSize - BITMAPINFO size
  42. * nBytesLen - size of the second bitmap bits
  43. * Return value:
  44. * TRUE if equal
  45. * Called by:
  46. * _AddToHistList
  47. --*/
  48. BOOL _CompareBitmaps(
  49. PBMPENTRY pBmp,
  50. PVOID pData,
  51. UINT xSize,
  52. UINT ySize,
  53. UINT bmiSize,
  54. UINT nBytesLen)
  55. {
  56. BOOL rv = FALSE;
  57. if (xSize != pBmp->xSize || ySize != pBmp->ySize ||
  58. bmiSize != pBmp->bmiSize ||
  59. nBytesLen != pBmp->nDataSize)
  60. goto exitpt;
  61. if (!memcmp(pBmp->pData, pData, nBytesLen))
  62. rv = TRUE;
  63. exitpt:
  64. return rv;
  65. }
  66. /*++
  67. * Function:
  68. * _AddToHistList
  69. * Description:
  70. * Adds a bitmap to the history list
  71. * Arguments:
  72. * pBmpFeed - bitmap to add
  73. * Called by:
  74. * _GetBitmap
  75. --*/
  76. void _AddToHistList(PBMPFEEDBACK pBmpFeed)
  77. {
  78. PVOID pNewData, pBmpData;
  79. HBITMAP hBmp;
  80. UINT i, nTotalSize;
  81. if (!pBmpFeed || !pBmpFeed->xSize || !pBmpFeed->ySize ||
  82. !pBmpFeed->bmpsize)
  83. goto exitpt;
  84. pBmpData = (BYTE *)(&(pBmpFeed->BitmapInfo)) + pBmpFeed->bmiSize;
  85. nTotalSize = pBmpFeed->bmpsize + pBmpFeed->bmiSize;
  86. for (i = 0; i < g_nCurSize; i++)
  87. if (_CompareBitmaps(g_Bmp + i,
  88. &pBmpFeed->BitmapInfo,
  89. pBmpFeed->xSize,
  90. pBmpFeed->ySize,
  91. pBmpFeed->bmiSize,
  92. nTotalSize))
  93. goto exitpt;
  94. pNewData = malloc(nTotalSize);
  95. if (!pNewData)
  96. goto exitpt;
  97. memcpy(pNewData, &pBmpFeed->BitmapInfo, nTotalSize);
  98. if (!pBmpFeed->bmiSize)
  99. hBmp = CreateBitmap(pBmpFeed->xSize, pBmpFeed->ySize,
  100. 1, 1,
  101. pBmpData);
  102. else {
  103. HDC hDC;
  104. hDC = GetDC(g_hMainWindow);
  105. if ( hDC )
  106. {
  107. hBmp = CreateDIBitmap(hDC,
  108. &(pBmpFeed->BitmapInfo.bmiHeader),
  109. CBM_INIT,
  110. pBmpData,
  111. &(pBmpFeed->BitmapInfo),
  112. DIB_PAL_COLORS);
  113. ReleaseDC(g_hMainWindow, hDC);
  114. }
  115. }
  116. if (g_nCurSize == HISTSIZE)
  117. // Delete the last entry
  118. {
  119. DeleteObject(g_Bmp[g_nCurSize - 1].hBitmap);
  120. free(g_Bmp[g_nCurSize - 1].pData);
  121. } else {
  122. g_nCurSize++;
  123. }
  124. if (g_nCurSize)
  125. memmove(g_Bmp + 1, g_Bmp, (g_nCurSize - 1)*sizeof(g_Bmp[0]));
  126. g_Bmp[0].hBitmap = hBmp;
  127. g_Bmp[0].xSize = pBmpFeed->xSize;
  128. g_Bmp[0].ySize = pBmpFeed->ySize;
  129. g_Bmp[0].nDataSize = pBmpFeed->bmpsize + pBmpFeed->bmiSize;
  130. g_Bmp[0].bmiSize = pBmpFeed->bmiSize;
  131. g_Bmp[0].bmpSize = pBmpFeed->bmpsize;
  132. g_Bmp[0].pData = pNewData;
  133. exitpt:
  134. ;
  135. }
  136. /*++
  137. * Function:
  138. * _FreeHistList
  139. * Description:
  140. * Deletes and frees all resources allocated by history list
  141. * Called by:
  142. * _GlyphSpyWndProc on WM_CLOSE
  143. --*/
  144. void _FreeHistList(void)
  145. {
  146. UINT i;
  147. for(i = 0; i < g_nCurSize; i++)
  148. {
  149. DeleteObject(g_Bmp[i].hBitmap);
  150. free(g_Bmp[i].pData);
  151. }
  152. g_nCurSize = 0;
  153. }
  154. /*++
  155. * Function:
  156. * _MyPrintMessage
  157. * Description:
  158. * Print function for debugging purposes
  159. * Arguments:
  160. * format - message format
  161. * ... - format arguments
  162. * Called by:
  163. * TRACE macro
  164. --*/
  165. void _MyPrintMessage(char *format, ...)
  166. {
  167. char szBuffer[256];
  168. va_list arglist;
  169. int nchr;
  170. va_start (arglist, format);
  171. nchr = _vsnprintf (szBuffer, sizeof(szBuffer), format, arglist);
  172. va_end (arglist);
  173. OutputDebugString(szBuffer);
  174. }
  175. /*++
  176. * Function:
  177. * _StartClient
  178. * Description:
  179. * Starts an RDP client process
  180. * Return value:
  181. * TRUE on success
  182. * Called by:
  183. * _GlyphSpyWndProc on ID_YEAH_START
  184. --*/
  185. BOOL _StartClient(VOID)
  186. {
  187. STARTUPINFO si;
  188. PROCESS_INFORMATION procinfo;
  189. BOOL rv = TRUE;
  190. if (g_pidRDP)
  191. {
  192. rv = FALSE;
  193. goto exitpt;
  194. }
  195. FillMemory(&si, sizeof(si), 0);
  196. si.cb = sizeof(si);
  197. si.wShowWindow = SW_SHOWMINIMIZED;
  198. if (!CreateProcessA(CLIENT_EXE,
  199. " /CLXDLL=CLXTSHAR.DLL", // Command line
  200. NULL, // Security attribute for process
  201. NULL, // Security attribute for thread
  202. FALSE, // Inheritance - no
  203. 0, // Creation flags
  204. NULL, // Environment
  205. NULL, // Current dir
  206. &si,
  207. &procinfo))
  208. {
  209. rv = FALSE;
  210. } else {
  211. g_pidRDP = procinfo.dwProcessId;
  212. g_hRDP = procinfo.hProcess;
  213. }
  214. CloseHandle(procinfo.hThread);
  215. exitpt:
  216. return rv;
  217. }
  218. /*++
  219. * Function:
  220. * _CloseClient
  221. * Description:
  222. * Closes the handle to the client process
  223. * Called by:
  224. * _GlyphSpyWndProc on WM_FB_DISCONNECT and ID_YEAH_START
  225. --*/
  226. VOID _CloseClient(VOID)
  227. {
  228. if (g_pidRDP)
  229. {
  230. g_pidRDP = 0;
  231. CloseHandle(g_hRDP);
  232. }
  233. }
  234. /*++
  235. * Function:
  236. * _GetBitmap
  237. * Description:
  238. * Opens the shared memory and retreives the bitmap
  239. * passed by clxtshar
  240. * Arguments:
  241. * dwProcessId - senders process Id
  242. * hMapF - handle to the shared memory
  243. * Called by:
  244. * _GlyphSpyWndProc on WM_FB_GLYPHOUT
  245. --*/
  246. VOID _GetBitmap(DWORD dwProcessId, HANDLE hMapF)
  247. {
  248. PBMPFEEDBACK pView;
  249. HANDLE hDupMapF;
  250. UINT nSize;
  251. if (dwProcessId != g_pidRDP)
  252. goto exitpt;
  253. if (!DuplicateHandle( g_hRDP,
  254. hMapF,
  255. GetCurrentProcess(),
  256. &hDupMapF,
  257. FILE_MAP_READ,
  258. FALSE,
  259. 0))
  260. {
  261. TRACE(("Can't dup file handle, GetLastError = %d\n", GetLastError()));
  262. goto exitpt;
  263. }
  264. pView = MapViewOfFile(hDupMapF,
  265. FILE_MAP_READ,
  266. 0,
  267. 0,
  268. sizeof(*pView));
  269. if (!pView)
  270. {
  271. TRACE(("Can't map a view, GetLastError = %d\n", GetLastError()));
  272. goto exitpt1;
  273. }
  274. // Get size
  275. nSize = pView->bmiSize + sizeof(*pView) + pView->bmpsize - sizeof(pView->BitmapInfo);
  276. // unmap
  277. UnmapViewOfFile(pView);
  278. // remap the whole structure
  279. pView = MapViewOfFile(hDupMapF,
  280. FILE_MAP_READ,
  281. 0,
  282. 0,
  283. nSize);
  284. if (!pView)
  285. {
  286. TRACE(("Can't map a view, GetLastError = %d\n", GetLastError()));
  287. goto exitpt1;
  288. }
  289. _AddToHistList(pView);
  290. UnmapViewOfFile(pView);
  291. CloseHandle(hDupMapF);
  292. exitpt:
  293. return;
  294. exitpt1:
  295. UnmapViewOfFile(pView);
  296. CloseHandle(hDupMapF);
  297. }
  298. /*++
  299. * Function:
  300. * _RepaintWindow
  301. * Description:
  302. * Redraws the window client area
  303. * Arguments:
  304. * hWnd - window handle
  305. * Called by:
  306. * _GlyphSpyWndProc on WM_PAINT
  307. --*/
  308. void _RepaintWindow(HWND hWnd)
  309. {
  310. HDC glyphDC = NULL;
  311. HDC theDC;
  312. HBITMAP hOldBmp;
  313. PAINTSTRUCT ps;
  314. UINT nBmpCntr, yPtr;
  315. RECT rcClient;
  316. theDC = BeginPaint(hWnd, &ps);
  317. if (!theDC)
  318. goto exitpt;
  319. GetClientRect(hWnd, &rcClient);
  320. glyphDC = CreateCompatibleDC(theDC);
  321. if (!g_nCurSize)
  322. goto exitpt;
  323. if (!glyphDC)
  324. goto exitpt;
  325. hOldBmp = SelectObject(glyphDC, g_Bmp[0].hBitmap);
  326. nBmpCntr = g_nScrollPos;
  327. yPtr = 0;
  328. while (nBmpCntr < g_nCurSize && yPtr < (UINT)rcClient.bottom)
  329. {
  330. SelectObject(glyphDC, g_Bmp[nBmpCntr].hBitmap);
  331. BitBlt(theDC, // Dest DC
  332. 0, // Dest x
  333. yPtr, // Dest y
  334. g_Bmp[nBmpCntr].xSize, // Width
  335. g_Bmp[nBmpCntr].ySize, // Height
  336. glyphDC, // Source
  337. 0, // Src x
  338. 0, // Src y
  339. SRCCOPY); // Rop
  340. yPtr += g_Bmp[nBmpCntr].ySize;
  341. nBmpCntr++;
  342. }
  343. SelectObject(glyphDC, hOldBmp);
  344. EndPaint(hWnd, &ps);
  345. exitpt:
  346. if ( glyphDC )
  347. DeleteDC(glyphDC);
  348. }
  349. /*++
  350. * Function:
  351. * _SetVScroll
  352. * Description:
  353. * Changes the position of the vertical scroll
  354. * Arguments:
  355. * nScrollCode - Scroll action
  356. * nPos - argument
  357. * Called by:
  358. * _GlyphOutWndProc on WM_VSCROLL
  359. --*/
  360. VOID _SetVScroll(int nScrollCode, short int nPos)
  361. {
  362. int nScrollPos = g_nScrollPos;
  363. switch(nScrollCode)
  364. {
  365. case SB_BOTTOM:
  366. nScrollPos = g_nCurSize - 1;
  367. break;
  368. // case SB_ENDSCROLL:
  369. case SB_LINEDOWN:
  370. nScrollPos++;
  371. break;
  372. case SB_LINEUP:
  373. nScrollPos--;
  374. break;
  375. case SB_PAGEDOWN:
  376. nScrollPos += 3;
  377. break;
  378. case SB_PAGEUP:
  379. nScrollPos -= 3;
  380. break;
  381. case SB_THUMBPOSITION:
  382. nScrollPos = nPos;
  383. break;
  384. case SB_THUMBTRACK:
  385. nScrollPos = nPos;
  386. break;
  387. case SB_TOP:
  388. nScrollPos = 0;
  389. break;
  390. }
  391. g_nScrollPos = nScrollPos;
  392. if (nScrollPos < 0)
  393. g_nScrollPos = 0;
  394. if (nScrollPos >= (int)g_nCurSize)
  395. g_nScrollPos = g_nCurSize - 1;
  396. }
  397. /*++
  398. * Function:
  399. * _ClickOnGlyph
  400. * Description:
  401. * When the mouse click on glyph a dialog
  402. * pops up offering adding the glyph to the database
  403. * Arguments:
  404. * hWnd - client window handle
  405. * xPos,yPos - location where the mouse was clicked
  406. * Called by:
  407. * _GlyphSpyWndProc on WM_LBUTTONDOWN
  408. --*/
  409. VOID _ClickOnGlyph(HWND hWnd, UINT xPos, UINT yPos)
  410. {
  411. UINT X0 = 0;
  412. UINT nPointed;
  413. BMPENTRY Bitmap;
  414. for(nPointed = g_nScrollPos; nPointed < g_nCurSize && X0 < yPos; nPointed++)
  415. X0 += g_Bmp[nPointed].ySize;
  416. nPointed --;
  417. if (X0 > yPos && xPos <= (UINT)g_Bmp[nPointed].xSize)
  418. {
  419. memset(&Bitmap, 0, sizeof(Bitmap));
  420. Bitmap.nDataSize = g_Bmp[nPointed].nDataSize;
  421. Bitmap.bmiSize = g_Bmp[nPointed].bmiSize;
  422. Bitmap.bmpSize = g_Bmp[nPointed].bmpSize;
  423. Bitmap.xSize = g_Bmp[nPointed].xSize;
  424. Bitmap.ySize = g_Bmp[nPointed].ySize;
  425. Bitmap.pData = malloc(Bitmap.nDataSize);
  426. if (!Bitmap.pData)
  427. goto exitpt;
  428. memcpy(Bitmap.pData, g_Bmp[nPointed].pData, Bitmap.nDataSize);
  429. if (!Bitmap.bmiSize)
  430. // Monochrome bitmap
  431. Bitmap.hBitmap = CreateBitmap(
  432. Bitmap.xSize,
  433. Bitmap.ySize,
  434. 1, 1,
  435. Bitmap.pData);
  436. else {
  437. HDC hDC = GetDC(g_hMainWindow);
  438. if ( hDC )
  439. {
  440. Bitmap.hBitmap =
  441. CreateDIBitmap(hDC,
  442. (BITMAPINFOHEADER *)
  443. Bitmap.pData,
  444. CBM_INIT,
  445. ((BYTE *)(Bitmap.pData)) + Bitmap.bmiSize,
  446. (BITMAPINFO *)
  447. Bitmap.pData,
  448. DIB_PAL_COLORS);
  449. ReleaseDC(g_hMainWindow, hDC);
  450. }
  451. }
  452. if (!Bitmap.hBitmap)
  453. {
  454. free(Bitmap.pData);
  455. goto exitpt;
  456. }
  457. // Open dialog for adding
  458. AddBitmapDialog(g_hInstance, hWnd, &Bitmap);
  459. DeleteObject(Bitmap.hBitmap);
  460. free(Bitmap.pData);
  461. }
  462. exitpt:
  463. ;
  464. }
  465. /*++
  466. * Function:
  467. * _GlyphSpyWndProc
  468. * Description:
  469. * Dispatches the messages for glyphspy window
  470. * Arguments:
  471. * hWnd - window handle
  472. * uiMessage - message id
  473. * wParam, lParam - parameters
  474. * Return value:
  475. * 0 - message is processed
  476. --*/
  477. LRESULT CALLBACK _GlyphSpyWndProc( HWND hWnd,
  478. UINT uiMessage,
  479. WPARAM wParam,
  480. LPARAM lParam)
  481. {
  482. LRESULT rv = 0;
  483. switch(uiMessage)
  484. {
  485. case WM_CREATE:
  486. OpenDB(TRUE); // Open glyph DB for Read/Write
  487. break;
  488. case WM_FB_GLYPHOUT:
  489. _GetBitmap((DWORD)wParam, (HANDLE)lParam);
  490. // Set scroll range
  491. if (g_nCurSize)
  492. SetScrollRange(hWnd, SB_VERT, 0, g_nCurSize - 1, TRUE);
  493. // Repaint the window
  494. InvalidateRect(hWnd, NULL, TRUE);
  495. break;
  496. case WM_FB_ACCEPTME:
  497. if ((DWORD)lParam == g_pidRDP)
  498. rv = 1;
  499. break;
  500. case WM_FB_DISCONNECT:
  501. _CloseClient();
  502. break;
  503. case WM_PAINT:
  504. _RepaintWindow(hWnd);
  505. break;
  506. case WM_VSCROLL:
  507. _SetVScroll((int) LOWORD(wParam), (short int) HIWORD(wParam));
  508. SetScrollPos(hWnd, SB_VERT, g_nScrollPos, TRUE);
  509. InvalidateRect(hWnd, NULL, TRUE);
  510. break;
  511. case WM_LBUTTONDOWN:
  512. _ClickOnGlyph(hWnd, LOWORD(lParam), HIWORD(lParam));
  513. break;
  514. case WM_MOUSEWHEEL:
  515. if (((short)HIWORD(wParam)) > 0)
  516. _SetVScroll(SB_PAGEUP, 0);
  517. else
  518. _SetVScroll(SB_PAGEDOWN, 0);
  519. SetScrollPos(hWnd, SB_VERT, g_nScrollPos, TRUE);
  520. InvalidateRect(hWnd, NULL, TRUE);
  521. break;
  522. case WM_COMMAND:
  523. switch (wParam)
  524. {
  525. case ID_YEAH_START:
  526. if (!_StartClient())
  527. {
  528. if (MessageBox(hWnd,
  529. "RDP Client is already started. "
  530. "Do you wish to start another ?",
  531. "Warning", MB_YESNO) == IDYES)
  532. {
  533. _CloseClient();
  534. _StartClient();
  535. }
  536. }
  537. break;
  538. case ID_YEAH_BROWSE:
  539. BrowseBitmapsDialog(g_hInstance, hWnd);
  540. break;
  541. }
  542. break;
  543. case WM_CLOSE:
  544. _FreeHistList();
  545. CloseDB(); // Close the glyph DB
  546. PostQuitMessage(0);
  547. break;
  548. default:
  549. rv = DefWindowProc(hWnd, uiMessage, wParam, lParam);
  550. }
  551. return rv;
  552. }
  553. /*++
  554. * Function:
  555. * _CreateMYWindow
  556. * Description:
  557. * Creates glyphspy client window
  558. * Return value:
  559. * TRUE on success
  560. * Called by:
  561. * WinMain
  562. --*/
  563. BOOL _CreateMYWindow(void)
  564. {
  565. WNDCLASS wc;
  566. BOOL rv = TRUE;
  567. // if (!g_hPrevInstance)
  568. {
  569. memset(&wc, 0, sizeof(wc));
  570. // Main window classname
  571. wc.style = CS_HREDRAW | CS_VREDRAW;
  572. wc.lpfnWndProc = _GlyphSpyWndProc;
  573. wc.hInstance = g_hInstance;
  574. wc.lpszClassName = _TSTNAMEOFCLAS;
  575. wc.hIcon = LoadIcon(g_hInstance, IDI_APPLICATION);
  576. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  577. wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
  578. wc.hbrBackground = GetStockObject(WHITE_BRUSH);
  579. if (!RegisterClass (&wc))
  580. {
  581. rv = FALSE;
  582. goto exitpt;
  583. }
  584. }
  585. g_hMainWindow = CreateWindow(
  586. _TSTNAMEOFCLAS,
  587. "GlyphSpy", // Window name
  588. WS_OVERLAPPEDWINDOW|WS_VSCROLL, // dwStyle
  589. CW_USEDEFAULT, // x
  590. CW_USEDEFAULT, // y
  591. CW_USEDEFAULT, // nWidth
  592. CW_USEDEFAULT, // nHeight
  593. HWND_DESKTOP, // hWndParent
  594. NULL, // hMenu
  595. g_hInstance,
  596. NULL); // lpParam
  597. if (!g_hMainWindow)
  598. rv = FALSE;
  599. SetScrollRange(g_hMainWindow, SB_VERT, 0, 0, FALSE);
  600. ShowWindow(g_hMainWindow, SW_SHOW);
  601. UpdateWindow(g_hMainWindow);
  602. exitpt:
  603. return rv;
  604. }
  605. /*++
  606. * Function:
  607. * WinMain
  608. * Description:
  609. * Startup function
  610. --*/
  611. int
  612. WINAPI
  613. WinMain(HINSTANCE hInstance,
  614. HINSTANCE hPrevInst,
  615. LPSTR lpszCmdLine,
  616. int nCmdShow)
  617. {
  618. MSG msg;
  619. g_hInstance = hInstance;
  620. g_hPrevInstance = hInstance;
  621. if (!_CreateMYWindow())
  622. goto exitpt;
  623. while (GetMessage(&msg, NULL, 0, 0))
  624. {
  625. TranslateMessage (&msg);
  626. DispatchMessage (&msg);
  627. }
  628. exitpt:
  629. return 0;
  630. }