737 lines
17 KiB
C
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;
|
|
}
|