GetDesktopWindow from non-interactive service...
From: Robb Shearer (robert.shearer_at_citicorp.com)
Date: 09/13/03
- Next message: Ohaya: "Re: Possible to override CDP in Certificate?"
- Previous message: Ohaya: "Re: Possible to override CDP in Certificate?"
- Next in thread: Eric Perlin [MS]: "Re: GetDesktopWindow from non-interactive service..."
- Reply: Eric Perlin [MS]: "Re: GetDesktopWindow from non-interactive service..."
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]
Date: Fri, 12 Sep 2003 15:23:33 -0700
We have a service that is monitoring production desktop.
It can determine when something bad has happend on the
production desktop, and generate an e-mail notification to
a 'OnCall' e-mail box.
I have cobbled together some examples from MSDN and other
places, and added the ability for the service to take a
snapshot of the desktop, and include it as an attachment.
This works GREAT on my workstation -- running as a
service. But on a test machine (and in production) it will
receive an ACCESS DENIED error with the BitBlt.
Here is the code I am using to do the snapshot -- minus
all the AddTheAceWindowStation -- which are from MSDN.
I have tried it w/ and w/o the #define
TRY_USING_MS_ADDACE_EXAMPLE. Which AddTheAceWindowStation
fails.
Any idea / help would be GREATLY appreciated.
Thank you.
PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp)
{
BITMAP bmp;
PBITMAPINFO pbmi;
WORD cClrBits;
// Retrieve the bitmap color format, width, and
height.
if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp))
return NULL;
// Convert the color format to a count of bits.
cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
if (cClrBits == 1)
cClrBits = 1;
else if (cClrBits <= 4)
cClrBits = 4;
else if (cClrBits <= 8)
cClrBits = 8;
else if (cClrBits <= 16)
cClrBits = 16;
else if (cClrBits <= 24)
cClrBits = 24;
else cClrBits = 32;
// Allocate memory for the BITMAPINFO structure. (This
structure
// contains a BITMAPINFOHEADER structure and an array
of RGBQUAD
// data structures.)
if (cClrBits != 24)
pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * (1<< cClrBits));
// There is no RGBQUAD array for the 24-bit-per-pixel
format.
else
pbmi = (PBITMAPINFO) LocalAlloc(LPTR,
sizeof(BITMAPINFOHEADER));
// Initialize the fields in the BITMAPINFO structure.
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmi->bmiHeader.biWidth = bmp.bmWidth;
pbmi->bmiHeader.biHeight = bmp.bmHeight;
pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
if (cClrBits < 24)
pbmi->bmiHeader.biClrUsed = (1<<cClrBits);
// If the bitmap is not compressed, set the BI_RGB
flag.
pbmi->bmiHeader.biCompression = BI_RGB;
// Compute the number of bytes in the array of color
// indices and store the result in biSizeImage.
// For Windows NT, the width must be DWORD aligned
unless
// the bitmap is RLE compressed. This example shows
this.
// For Windows 95/98/Me, the width must be WORD
aligned unless the
// bitmap is RLE compressed.
pbmi->bmiHeader.biSizeImage = ((pbmi-
>bmiHeader.biWidth * cClrBits +31) & ~31) /8
* pbmi-
>bmiHeader.biHeight;
// Set biClrImportant to 0, indicating that all of the
// device colors are important.
pbmi->bmiHeader.biClrImportant = 0;
return pbmi;
}
HBITMAP CreateBitmapOfDesktop(HWND desktopWindow)
{
HWND hwnd = desktopWindow;
HDC hScreenDC = GetDC(hwnd);
int ScreenWidth = GetDeviceCaps(hScreenDC,
HORZRES);
int ScreenHeight = GetDeviceCaps(hScreenDC,
VERTRES);
HBITMAP bitmap = CreateCompatibleBitmap(hScreenDC,
ScreenWidth, ScreenHeight);
HDC bitmapDC = CreateCompatibleDC(hScreenDC);
HBITMAP oldBitmap = (HBITMAP)SelectObject
(bitmapDC, bitmap);
if ( BitBlt(bitmapDC, 0, 0, ScreenWidth,
ScreenHeight, hScreenDC, 0, 0, SRCCOPY | CAPTUREBLT) == 0 )
return NULL;
SelectObject(bitmapDC, oldBitmap);
DeleteObject(bitmapDC);
ReleaseDC(hwnd, hScreenDC);
return bitmap;
}
void SaveBitmapToFile(LPTSTR pszFile, PBITMAPINFO pbi,
HBITMAP hBMP, HWND desktopWindow)
{
HANDLE hf; // file handle
BITMAPFILEHEADER hdr; // bitmap file-header
PBITMAPINFOHEADER pbih; // bitmap info-header
LPBYTE lpBits; // memory pointer
DWORD dwTotal; // total count of
bytes
DWORD cb; // incremental count
of bytes
BYTE *hp; // byte pointer
DWORD dwTmp;
pbih = (PBITMAPINFOHEADER) pbi;
lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih-
>biSizeImage);
if (!lpBits)
return;
HWND hwnd = desktopWindow;
HDC hScreenDC = GetDC(hwnd);
// Retrieve the color table (RGBQUAD array) and the
bits
// (array of palette indices) from the DIB.
if (!GetDIBits(hScreenDC, hBMP, 0, (WORD) pbih-
>biHeight, lpBits, pbi, DIB_RGB_COLORS))
{
ReleaseDC(hwnd, hScreenDC);
return;
}
ReleaseDC(hwnd, hScreenDC);
// Create the .BMP file.
hf = CreateFile(pszFile,
GENERIC_READ | GENERIC_WRITE,
(DWORD) 0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
if (hf == INVALID_HANDLE_VALUE)
return;
hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M"
// Compute the size of the entire file.
hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + pbih-
>biSize + pbih->biClrUsed * sizeof(RGBQUAD) + pbih-
>biSizeImage);
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;
// Compute the offset to the array of color indices.
hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) +
pbih->biSize + pbih->biClrUsed * sizeof (RGBQUAD);
// Copy the BITMAPFILEHEADER into the .BMP file.
if (!WriteFile(hf, (LPVOID) &hdr, sizeof
(BITMAPFILEHEADER), (LPDWORD) &dwTmp, NULL))
return;
// Copy the BITMAPINFOHEADER and RGBQUAD array into
the file.
if (!WriteFile(hf, (LPVOID) pbih, sizeof
(BITMAPINFOHEADER) + pbih->biClrUsed * sizeof (RGBQUAD),
(LPDWORD) &dwTmp, ( NULL)) )
return;
// Copy the array of color indices into the .BMP file.
dwTotal = cb = pbih->biSizeImage;
hp = lpBits;
if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD)
&dwTmp,NULL))
return;
// Close the .BMP file.
if (!CloseHandle(hf))
return;
// Free memory.
GlobalFree((HGLOBAL)lpBits);
}
BOOL CALLBACK FindDesktopWindow(HWND hwnd, LPARAM p)
{
char winName[256];
char className[256];
className[0] = 0;
GetClassName(hwnd, className, 255);
if ( stricmp(className, "#32769") == 0 )
{
DWORD* desktopWindow = (DWORD*)p;
*desktopWindow = (long)hwnd;
return FALSE;
}
HWND parent= hwnd;
do {
className[0] = 0;
parent = GetParent(parent);
GetClassName(parent, className, 255);
if ( stricmp(className, "#32769") == 0 )
{
DWORD* desktopWindow = (DWORD*)p;
*desktopWindow = (long)parent;
return FALSE;
}
} while ( parent != NULL );
return TRUE;
}
// called with "winsta0, default"
STDMETHODIMP GrabDesktopSnapshot(char* UserWinStaName,
char* UserDesktopName)
{
HDESK hdesk;
HDESK hdeskold;
HWINSTA hwinsta;
hwinsta = OpenWindowStation(UserWinStaName, FALSE,
READ_CONTROL);
if (hwinsta == NULL)
return E_FAIL;
HWINSTA hwinstaold = GetProcessWindowStation();
if (hwinstaold == NULL)
return E_FAIL;
hdeskold = GetThreadDesktop(GetCurrentThreadId());
//
// set the windowstation to winsta0 so that you
obtain the
// correct default desktop
//
if (!SetProcessWindowStation(hwinsta))
return E_FAIL;
//
// obtain a handle to the user desktop
//
hdesk = OpenDesktop(UserDesktopName, 0, FALSE,
READ_CONTROL | WRITE_DAC | DESKTOP_WRITEOBJECTS |
DESKTOP_READOBJECTS );
if (hdesk == NULL)
return E_FAIL;
SetThreadDesktop(hdesk);
#ifdef TRY_USING_MS_ADDACE_EXAMPLE
HANDLE hToken;
PSID psid;
if (!LogonUser("Foo", "DomainLab", "Bar",
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
&hToken))
return E_FAIL;
// example function form MSDN
if (!GetLogonSID(hToken, &psid))
return E_FAIL;
//
// add the user to interactive windowstation ---
sample function from MSDN
//
if (!AddTheAceWindowStation(hwinsta, psid))
return E_FAIL;
//
// add user to "default" desktop --
sample function from MSDN
//
if (!AddTheAceDesktop(hdesk, psid))
return E_FAIL;
//
// free the buffer for the logon sid
//
RemoveSid(&psid);
#endif
// Don't want to use GetDesktopWindow().. This
might eventually be used
// in a TerminalServer environment.
//
// Or -- is that a totally mute point? --- Will
GetDesktopWindow() work if the
// SetProcessWindowStation() and SetThreadDesktop
() are set correctly?
//
HWND DesktopWindow = 0;
EnumDesktopWindows(hdesk, FindDesktopWindow, (long)
&DesktopWindow);
if ( DesktopWindow == 0 )
return E_FAIL;
HBITMAP bitmap = CreateBitmapOfDesktop
(DesktopWindow);
if ( bitmap == NULL )
return E_FAIL;
PBITMAPINFO bitmapInfo = CreateBitmapInfoStruct
(bitmap);
char filename[256];
SYSTEMTIME st;
GetSystemTime(&st);
SystemTimeToTzSpecificLocalTime(NULL, &st, &st);
sprintf(filename, "c:\\temp\\Snapshot_%04.04d%
02.02d%02.02d_%02.02d%02.02d%02.02d.bmp", st.wYear,
st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
SaveBitmapToFile(filename, bitmapInfo, bitmap,
DesktopWindow);
DeleteObject(bitmap);
SetThreadDesktop(hdeskold);
if (!SetProcessWindowStation(hwinstaold))
return E_FAIL;
// we will continue even if this fails
int closeRes = CloseWindowStation(hwinsta);
if (!CloseDesktop(hdesk))
return E_FAIL;
CloseHandle(hToken);
return S_OK;
}
- Next message: Ohaya: "Re: Possible to override CDP in Certificate?"
- Previous message: Ohaya: "Re: Possible to override CDP in Certificate?"
- Next in thread: Eric Perlin [MS]: "Re: GetDesktopWindow from non-interactive service..."
- Reply: Eric Perlin [MS]: "Re: GetDesktopWindow from non-interactive service..."
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ] [ attachment ]