windows-nt/Source/XPSP1/NT/termsrv/reskit/smc/tclient/glyphspy/glyphspy.c
2020-09-26 16:20:57 +08:00

737 lines
17 KiB
C

/*++
* 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;
}