|
|
/*++
* File name: * glyphspy.c * Contents: * UI for spying and recording glyphs reveived by RDP client --*/
#include <windows.h>
#include <stdio.h>
#include <stdarg.h>
#include <malloc.h>
#include "..\lib\feedback.h"
#include "..\lib\bmpdb.h"
#include "resource.h"
#define CLIENT_EXE "mstsc.exe"
#define TRACE(_x_) {_MyPrintMessage _x_;}
// Dialog functions
VOID AddBitmapDialog(HINSTANCE hInst, HWND hWnd, PBMPENTRY pBitmap); VOID BrowseBitmapsDialog(HINSTANCE hInst, HWND hWnd);
/*
* Global data */ HWND g_hMainWindow; // Main window handle
HINSTANCE g_hInstance; // executable instance
HINSTANCE g_hPrevInstance; // previous instance
DWORD g_pidRDP = 0; // Process Id of the RDP client
HANDLE g_hRDP = NULL; // Process handle of the client
#define HISTSIZE 150 // Size of the history list
UINT g_nCurSize = 0; // Current size
UINT g_nScrollPos = 0; // Vertical scroll position
BMPENTRY g_Bmp[HISTSIZE]; // The history list
/*++
* Function: * _CompareBitmaps * Description: * Compares two bitmaps * Arguments: * pBmp - bitmap to compare to * pData - bits of the second bitmap * xSize - size of the second bitmap * ySize * bmiSize - BITMAPINFO size * nBytesLen - size of the second bitmap bits * Return value: * TRUE if equal * Called by: * _AddToHistList --*/ BOOL _CompareBitmaps( PBMPENTRY pBmp, PVOID pData, UINT xSize, UINT ySize, UINT bmiSize, UINT nBytesLen) { BOOL rv = FALSE;
if (xSize != pBmp->xSize || ySize != pBmp->ySize || bmiSize != pBmp->bmiSize || nBytesLen != pBmp->nDataSize)
goto exitpt;
if (!memcmp(pBmp->pData, pData, nBytesLen)) rv = TRUE; exitpt: return rv; }
/*++
* Function: * _AddToHistList * Description: * Adds a bitmap to the history list * Arguments: * pBmpFeed - bitmap to add * Called by: * _GetBitmap --*/ void _AddToHistList(PBMPFEEDBACK pBmpFeed) { PVOID pNewData, pBmpData; HBITMAP hBmp; UINT i, nTotalSize;
if (!pBmpFeed || !pBmpFeed->xSize || !pBmpFeed->ySize || !pBmpFeed->bmpsize) goto exitpt;
pBmpData = (BYTE *)(&(pBmpFeed->BitmapInfo)) + pBmpFeed->bmiSize; nTotalSize = pBmpFeed->bmpsize + pBmpFeed->bmiSize;
for (i = 0; i < g_nCurSize; i++) if (_CompareBitmaps(g_Bmp + i, &pBmpFeed->BitmapInfo, pBmpFeed->xSize, pBmpFeed->ySize, pBmpFeed->bmiSize, nTotalSize)) goto exitpt;
pNewData = malloc(nTotalSize); if (!pNewData) goto exitpt;
memcpy(pNewData, &pBmpFeed->BitmapInfo, nTotalSize); if (!pBmpFeed->bmiSize) hBmp = CreateBitmap(pBmpFeed->xSize, pBmpFeed->ySize, 1, 1, pBmpData); else { HDC hDC;
hDC = GetDC(g_hMainWindow); if ( hDC ) { hBmp = CreateDIBitmap(hDC, &(pBmpFeed->BitmapInfo.bmiHeader), CBM_INIT, pBmpData, &(pBmpFeed->BitmapInfo), DIB_PAL_COLORS); ReleaseDC(g_hMainWindow, hDC); } }
if (g_nCurSize == HISTSIZE) // Delete the last entry
{ DeleteObject(g_Bmp[g_nCurSize - 1].hBitmap); free(g_Bmp[g_nCurSize - 1].pData); } else { g_nCurSize++; } if (g_nCurSize) memmove(g_Bmp + 1, g_Bmp, (g_nCurSize - 1)*sizeof(g_Bmp[0]));
g_Bmp[0].hBitmap = hBmp; g_Bmp[0].xSize = pBmpFeed->xSize; g_Bmp[0].ySize = pBmpFeed->ySize; g_Bmp[0].nDataSize = pBmpFeed->bmpsize + pBmpFeed->bmiSize; g_Bmp[0].bmiSize = pBmpFeed->bmiSize; g_Bmp[0].bmpSize = pBmpFeed->bmpsize; g_Bmp[0].pData = pNewData;
exitpt: ; }
/*++
* Function: * _FreeHistList * Description: * Deletes and frees all resources allocated by history list * Called by: * _GlyphSpyWndProc on WM_CLOSE --*/ void _FreeHistList(void) { UINT i;
for(i = 0; i < g_nCurSize; i++) { DeleteObject(g_Bmp[i].hBitmap); free(g_Bmp[i].pData); } g_nCurSize = 0; }
/*++
* Function: * _MyPrintMessage * Description: * Print function for debugging purposes * Arguments: * format - message format * ... - format arguments * Called by: * TRACE macro --*/ void _MyPrintMessage(char *format, ...) { char szBuffer[256]; va_list arglist; int nchr;
va_start (arglist, format); nchr = _vsnprintf (szBuffer, sizeof(szBuffer), format, arglist); va_end (arglist); OutputDebugString(szBuffer);
}
/*++
* Function: * _StartClient * Description: * Starts an RDP client process * Return value: * TRUE on success * Called by: * _GlyphSpyWndProc on ID_YEAH_START --*/ BOOL _StartClient(VOID) { STARTUPINFO si; PROCESS_INFORMATION procinfo; BOOL rv = TRUE;
if (g_pidRDP) { rv = FALSE; goto exitpt; }
FillMemory(&si, sizeof(si), 0); si.cb = sizeof(si); si.wShowWindow = SW_SHOWMINIMIZED;
if (!CreateProcessA(CLIENT_EXE, " /CLXDLL=CLXTSHAR.DLL", // Command line
NULL, // Security attribute for process
NULL, // Security attribute for thread
FALSE, // Inheritance - no
0, // Creation flags
NULL, // Environment
NULL, // Current dir
&si, &procinfo)) { rv = FALSE; } else { g_pidRDP = procinfo.dwProcessId; g_hRDP = procinfo.hProcess; } CloseHandle(procinfo.hThread);
exitpt: return rv; }
/*++
* Function: * _CloseClient * Description: * Closes the handle to the client process * Called by: * _GlyphSpyWndProc on WM_FB_DISCONNECT and ID_YEAH_START --*/ VOID _CloseClient(VOID) { if (g_pidRDP) { g_pidRDP = 0; CloseHandle(g_hRDP); } }
/*++
* Function: * _GetBitmap * Description: * Opens the shared memory and retreives the bitmap * passed by clxtshar * Arguments: * dwProcessId - senders process Id * hMapF - handle to the shared memory * Called by: * _GlyphSpyWndProc on WM_FB_GLYPHOUT --*/ VOID _GetBitmap(DWORD dwProcessId, HANDLE hMapF) { PBMPFEEDBACK pView; HANDLE hDupMapF; UINT nSize;
if (dwProcessId != g_pidRDP) goto exitpt;
if (!DuplicateHandle( g_hRDP, hMapF, GetCurrentProcess(), &hDupMapF, FILE_MAP_READ, FALSE, 0)) { TRACE(("Can't dup file handle, GetLastError = %d\n", GetLastError())); goto exitpt; }
pView = MapViewOfFile(hDupMapF, FILE_MAP_READ, 0, 0, sizeof(*pView));
if (!pView) { TRACE(("Can't map a view, GetLastError = %d\n", GetLastError())); goto exitpt1; }
// Get size
nSize = pView->bmiSize + sizeof(*pView) + pView->bmpsize - sizeof(pView->BitmapInfo);
// unmap
UnmapViewOfFile(pView);
// remap the whole structure
pView = MapViewOfFile(hDupMapF, FILE_MAP_READ, 0, 0, nSize);
if (!pView) { TRACE(("Can't map a view, GetLastError = %d\n", GetLastError())); goto exitpt1; }
_AddToHistList(pView); UnmapViewOfFile(pView); CloseHandle(hDupMapF);
exitpt: return; exitpt1: UnmapViewOfFile(pView); CloseHandle(hDupMapF); }
/*++
* Function: * _RepaintWindow * Description: * Redraws the window client area * Arguments: * hWnd - window handle * Called by: * _GlyphSpyWndProc on WM_PAINT --*/ void _RepaintWindow(HWND hWnd) { HDC glyphDC = NULL; HDC theDC; HBITMAP hOldBmp; PAINTSTRUCT ps; UINT nBmpCntr, yPtr; RECT rcClient;
theDC = BeginPaint(hWnd, &ps); if (!theDC) goto exitpt;
GetClientRect(hWnd, &rcClient);
glyphDC = CreateCompatibleDC(theDC);
if (!g_nCurSize) goto exitpt;
if (!glyphDC) goto exitpt;
hOldBmp = SelectObject(glyphDC, g_Bmp[0].hBitmap);
nBmpCntr = g_nScrollPos; yPtr = 0; while (nBmpCntr < g_nCurSize && yPtr < (UINT)rcClient.bottom) { SelectObject(glyphDC, g_Bmp[nBmpCntr].hBitmap);
BitBlt(theDC, // Dest DC
0, // Dest x
yPtr, // Dest y
g_Bmp[nBmpCntr].xSize, // Width
g_Bmp[nBmpCntr].ySize, // Height
glyphDC, // Source
0, // Src x
0, // Src y
SRCCOPY); // Rop
yPtr += g_Bmp[nBmpCntr].ySize; nBmpCntr++; }
SelectObject(glyphDC, hOldBmp); EndPaint(hWnd, &ps); exitpt:
if ( glyphDC ) DeleteDC(glyphDC); }
/*++
* Function: * _SetVScroll * Description: * Changes the position of the vertical scroll * Arguments: * nScrollCode - Scroll action * nPos - argument * Called by: * _GlyphOutWndProc on WM_VSCROLL --*/ VOID _SetVScroll(int nScrollCode, short int nPos) { int nScrollPos = g_nScrollPos;
switch(nScrollCode) { case SB_BOTTOM: nScrollPos = g_nCurSize - 1; break; // case SB_ENDSCROLL:
case SB_LINEDOWN: nScrollPos++; break; case SB_LINEUP: nScrollPos--; break; case SB_PAGEDOWN: nScrollPos += 3; break; case SB_PAGEUP: nScrollPos -= 3; break; case SB_THUMBPOSITION: nScrollPos = nPos; break; case SB_THUMBTRACK: nScrollPos = nPos; break; case SB_TOP: nScrollPos = 0; break; }
g_nScrollPos = nScrollPos; if (nScrollPos < 0) g_nScrollPos = 0;
if (nScrollPos >= (int)g_nCurSize) g_nScrollPos = g_nCurSize - 1; }
/*++
* Function: * _ClickOnGlyph * Description: * When the mouse click on glyph a dialog * pops up offering adding the glyph to the database * Arguments: * hWnd - client window handle * xPos,yPos - location where the mouse was clicked * Called by: * _GlyphSpyWndProc on WM_LBUTTONDOWN --*/ VOID _ClickOnGlyph(HWND hWnd, UINT xPos, UINT yPos) { UINT X0 = 0; UINT nPointed; BMPENTRY Bitmap;
for(nPointed = g_nScrollPos; nPointed < g_nCurSize && X0 < yPos; nPointed++) X0 += g_Bmp[nPointed].ySize;
nPointed --; if (X0 > yPos && xPos <= (UINT)g_Bmp[nPointed].xSize) { memset(&Bitmap, 0, sizeof(Bitmap));
Bitmap.nDataSize = g_Bmp[nPointed].nDataSize; Bitmap.bmiSize = g_Bmp[nPointed].bmiSize; Bitmap.bmpSize = g_Bmp[nPointed].bmpSize; Bitmap.xSize = g_Bmp[nPointed].xSize; Bitmap.ySize = g_Bmp[nPointed].ySize; Bitmap.pData = malloc(Bitmap.nDataSize);
if (!Bitmap.pData) goto exitpt;
memcpy(Bitmap.pData, g_Bmp[nPointed].pData, Bitmap.nDataSize);
if (!Bitmap.bmiSize) // Monochrome bitmap
Bitmap.hBitmap = CreateBitmap( Bitmap.xSize, Bitmap.ySize, 1, 1, Bitmap.pData); else { HDC hDC = GetDC(g_hMainWindow);
if ( hDC ) { Bitmap.hBitmap = CreateDIBitmap(hDC, (BITMAPINFOHEADER *) Bitmap.pData, CBM_INIT, ((BYTE *)(Bitmap.pData)) + Bitmap.bmiSize, (BITMAPINFO *) Bitmap.pData, DIB_PAL_COLORS);
ReleaseDC(g_hMainWindow, hDC); } }
if (!Bitmap.hBitmap) { free(Bitmap.pData); goto exitpt; }
// Open dialog for adding
AddBitmapDialog(g_hInstance, hWnd, &Bitmap);
DeleteObject(Bitmap.hBitmap); free(Bitmap.pData); }
exitpt: ; }
/*++
* Function: * _GlyphSpyWndProc * Description: * Dispatches the messages for glyphspy window * Arguments: * hWnd - window handle * uiMessage - message id * wParam, lParam - parameters * Return value: * 0 - message is processed --*/ LRESULT CALLBACK _GlyphSpyWndProc( HWND hWnd, UINT uiMessage, WPARAM wParam, LPARAM lParam) { LRESULT rv = 0;
switch(uiMessage) { case WM_CREATE: OpenDB(TRUE); // Open glyph DB for Read/Write
break;
case WM_FB_GLYPHOUT: _GetBitmap((DWORD)wParam, (HANDLE)lParam);
// Set scroll range
if (g_nCurSize) SetScrollRange(hWnd, SB_VERT, 0, g_nCurSize - 1, TRUE); // Repaint the window
InvalidateRect(hWnd, NULL, TRUE); break;
case WM_FB_ACCEPTME: if ((DWORD)lParam == g_pidRDP) rv = 1; break; case WM_FB_DISCONNECT: _CloseClient(); break;
case WM_PAINT: _RepaintWindow(hWnd); break;
case WM_VSCROLL: _SetVScroll((int) LOWORD(wParam), (short int) HIWORD(wParam)); SetScrollPos(hWnd, SB_VERT, g_nScrollPos, TRUE); InvalidateRect(hWnd, NULL, TRUE); break;
case WM_LBUTTONDOWN: _ClickOnGlyph(hWnd, LOWORD(lParam), HIWORD(lParam)); break;
case WM_MOUSEWHEEL: if (((short)HIWORD(wParam)) > 0) _SetVScroll(SB_PAGEUP, 0); else _SetVScroll(SB_PAGEDOWN, 0);
SetScrollPos(hWnd, SB_VERT, g_nScrollPos, TRUE); InvalidateRect(hWnd, NULL, TRUE); break;
case WM_COMMAND: switch (wParam) { case ID_YEAH_START: if (!_StartClient()) { if (MessageBox(hWnd, "RDP Client is already started. " "Do you wish to start another ?", "Warning", MB_YESNO) == IDYES) { _CloseClient(); _StartClient(); } } break; case ID_YEAH_BROWSE: BrowseBitmapsDialog(g_hInstance, hWnd); break; } break;
case WM_CLOSE: _FreeHistList(); CloseDB(); // Close the glyph DB
PostQuitMessage(0); break;
default: rv = DefWindowProc(hWnd, uiMessage, wParam, lParam); }
return rv; }
/*++
* Function: * _CreateMYWindow * Description: * Creates glyphspy client window * Return value: * TRUE on success * Called by: * WinMain --*/ BOOL _CreateMYWindow(void) { WNDCLASS wc; BOOL rv = TRUE;
// if (!g_hPrevInstance)
{ memset(&wc, 0, sizeof(wc));
// Main window classname
wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = _GlyphSpyWndProc; wc.hInstance = g_hInstance; wc.lpszClassName = _TSTNAMEOFCLAS; wc.hIcon = LoadIcon(g_hInstance, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1); wc.hbrBackground = GetStockObject(WHITE_BRUSH);
if (!RegisterClass (&wc)) { rv = FALSE; goto exitpt; } } g_hMainWindow = CreateWindow( _TSTNAMEOFCLAS, "GlyphSpy", // Window name
WS_OVERLAPPEDWINDOW|WS_VSCROLL, // dwStyle
CW_USEDEFAULT, // x
CW_USEDEFAULT, // y
CW_USEDEFAULT, // nWidth
CW_USEDEFAULT, // nHeight
HWND_DESKTOP, // hWndParent
NULL, // hMenu
g_hInstance, NULL); // lpParam
if (!g_hMainWindow) rv = FALSE;
SetScrollRange(g_hMainWindow, SB_VERT, 0, 0, FALSE);
ShowWindow(g_hMainWindow, SW_SHOW); UpdateWindow(g_hMainWindow);
exitpt: return rv; }
/*++
* Function: * WinMain * Description: * Startup function --*/ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpszCmdLine, int nCmdShow) { MSG msg;
g_hInstance = hInstance; g_hPrevInstance = hInstance; if (!_CreateMYWindow()) goto exitpt;
while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage (&msg); DispatchMessage (&msg); }
exitpt: return 0; }
|