Leaked source code of windows server 2003
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.
 
 
 
 
 
 

274 lines
7.0 KiB

/****************************** Module Header ******************************\
* Module Name: snapshot.c
*
* Screen/Window SnapShotting Routines
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* History:
* 26-Nov-1991 DavidPe Ported from Win 3.1 sources
\***************************************************************************/
#include "precomp.h"
#pragma hdrstop
/***************************************************************************\
* xxxSnapWindow
*
* Effects: Snaps either the desktop hwnd or the active front most window. If
* any other window is specified, we will snap it but it will be clipped.
*
\***************************************************************************/
BOOL xxxSnapWindow(
PWND pwnd)
{
PTHREADINFO ptiCurrent;
RECT rc;
HDC hdcScr = NULL;
HDC hdcMem = NULL;
BOOL fRet;
HBITMAP hbmOld;
HBITMAP hbm;
HANDLE hPal;
LPLOGPALETTE lppal;
int palsize;
int iFixedPaletteEntries;
BOOL fSuccess;
PWND pwndT;
TL tlpwndT;
PWINDOWSTATION pwinsta;
TL tlpwinsta;
CheckLock(pwnd);
UserAssert(pwnd != NULL);
ptiCurrent = PtiCurrent();
/*
* If this is a thread of winlogon, don't do the snapshot.
*/
if (PsGetCurrentProcessId() == gpidLogon) {
return FALSE;
}
/*
* Get the affected windowstation
*/
if (!NT_SUCCESS(ReferenceWindowStation(
PsGetCurrentThread(),
NULL,
WINSTA_READSCREEN,
&pwinsta,
TRUE)) ||
pwinsta->dwWSF_Flags & WSF_NOIO) {
return FALSE;
}
/*
* If the window is on another windowstation, do nothing.
*/
if (pwnd->head.rpdesk->rpwinstaParent != pwinsta) {
return FALSE;
}
/*
* Get the parent of any child windows.
*/
while (TestWF(pwnd, WFCHILD)) {
pwnd = pwnd->spwndParent;
UserAssert(pwnd != NULL);
}
/*
* Lock the windowstation before we leave the critical section
*/
ThreadLockWinSta(ptiCurrent, pwinsta, &tlpwinsta);
/*
* Open the clipboard and empty it.
*
* pwndDesktop is made the owner of the clipboard, instead of the
* currently active window; -- SANKAR -- 20th July, 1989 --
*/
pwndT = ptiCurrent->rpdesk->pDeskInfo->spwnd;
ThreadLockWithPti(ptiCurrent, pwndT, &tlpwndT);
fSuccess = _OpenClipboard(pwndT, NULL);
ThreadUnlock(&tlpwndT);
if (!fSuccess) {
ThreadUnlockWinSta(ptiCurrent, &tlpwinsta);
return FALSE;
}
xxxEmptyClipboard(pwinsta);
/*
* Use the whole window.
*/
CopyRect(&rc, &pwnd->rcWindow);
/*
* Only snap what is on the screen.
*/
if (!IntersectRect(&rc, &rc, &gpDispInfo->rcScreen)) {
fRet = FALSE;
goto SnapExit;
}
rc.right -= rc.left;
rc.bottom -= rc.top;
/*
* Figure out how far offset from window origin visible part is
*/
if (pwnd != PWNDDESKTOP(pwnd)) {
rc.left -= pwnd->rcWindow.left;
rc.top -= pwnd->rcWindow.top;
}
/*
* Get the entire window's DC.
*/
hdcScr = _GetWindowDC(pwnd);
if (!hdcScr)
goto MemoryError;
/*
* Create the memory DC.
*/
hdcMem = GreCreateCompatibleDC(hdcScr);
if (!hdcMem)
goto MemoryError;
/*
* Create the destination bitmap. If it fails, then attempt
* to create a monochrome bitmap.
* Did we have enough memory?
*/
if (SYSMET(SAMEDISPLAYFORMAT)) {
hbm = GreCreateCompatibleBitmap(hdcScr, rc.right, rc.bottom);
} else {
hbm = GreCreateBitmap(rc.right, rc.bottom, 1, gpDispInfo->BitCountMax, NULL);
}
if (!hbm) {
hbm = GreCreateBitmap(rc.right, rc.bottom, 1, 1, NULL);
if (!hbm)
goto MemoryError;
}
/*
* Select the bitmap into the memory DC.
*/
hbmOld = GreSelectBitmap(hdcMem, hbm);
/*
* Snap!!!
* Check the return value because the process taking the snapshot
* may not have access to read the screen.
*/
fRet = GreBitBlt(hdcMem, 0, 0, rc.right, rc.bottom, hdcScr, rc.left, rc.top, SRCCOPY | CAPTUREBLT, 0);
/*
* Restore the old bitmap into the memory DC.
*/
GreSelectBitmap(hdcMem, hbmOld);
/*
* If the blt failed, leave now.
*/
if (!fRet) {
goto SnapExit;
}
_SetClipboardData(CF_BITMAP, hbm, FALSE, TRUE);
/*
* If this is a palette device, let's throw the current system palette
* into the clipboard also. Useful if the user just snapped a window
* containing palette colors...
*/
if (TEST_PUSIF(PUSIF_PALETTEDISPLAY)) {
int i;
int iPalSize;
palsize = GreGetDeviceCaps(hdcScr, SIZEPALETTE);
/*
* Determine the number of system colors.
*/
if (GreGetSystemPaletteUse(hdcScr) == SYSPAL_STATIC)
iFixedPaletteEntries = GreGetDeviceCaps(hdcScr, NUMRESERVED);
else
iFixedPaletteEntries = 2;
lppal = (LPLOGPALETTE)UserAllocPoolWithQuota(
(LONG)(sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * palsize),
TAG_CLIPBOARD);
if (lppal != NULL) {
lppal->palVersion = 0x300;
lppal->palNumEntries = (WORD)palsize;
if (GreGetSystemPaletteEntries(hdcScr,
0,
palsize,
lppal->palPalEntry)) {
iPalSize = palsize - iFixedPaletteEntries / 2;
for (i = iFixedPaletteEntries / 2; i < iPalSize; i++) {
/*
* Any non system palette enteries need to have the NOCOLLAPSE
* flag set otherwise bitmaps containing different palette
* indices but same colors get messed up.
*/
lppal->palPalEntry[i].peFlags = PC_NOCOLLAPSE;
}
if (hPal = GreCreatePalette(lppal))
_SetClipboardData(CF_PALETTE, hPal, FALSE, TRUE);
}
UserFreePool(lppal);
}
}
PlayEventSound(USER_SOUND_SNAPSHOT);
fRet = TRUE;
SnapExit:
/*
* Release the window/client DC.
*/
if (hdcScr) {
_ReleaseDC(hdcScr);
}
xxxCloseClipboard(pwinsta);
Unlock(&pwinsta->spwndClipOwner);
/*
* Delete the memory DC.
*/
if (hdcMem) {
GreDeleteDC(hdcMem);
}
ThreadUnlockWinSta(ptiCurrent, &tlpwinsta);
return fRet;
MemoryError:
/*
* Display an error message box.
*/
ClientNoMemoryPopup();
fRet = FALSE;
goto SnapExit;
}