VOID DestroyThreadsHotKeys() { PHOTKEY *pphk; PHOTKEY phk; PTHREADINFO ptiCurrent = PtiCurrent(); pphk = &gphkFirst; while (*pphk) { if ((*pphk)->pti == ptiCurrent) { phk = *pphk; *pphk = (*pphk)->phkNext; /* * Unlock the object stored here. */ if ((phk->spwnd != PWND_FOCUS) && (phk->spwnd != PWND_INPUTOWNER)) { Unlock(&phk->spwnd); } UserFreePool(phk); } else { pphk = &((*pphk)->phkNext); } } }
/***************************************************************************\ * MNFreePopup * \***************************************************************************/ VOID MNFreePopup( PPOPUPMENU ppopupmenu) { PMENU pmenu; PMENU pmenuSys; #ifdef DEBUG Validateppopupmenu(ppopupmenu); #endif if (IsRootPopupMenu(ppopupmenu)) { MNFlushDestroyedPopups (ppopupmenu, TRUE); } /* * This app is finished using the global system menu: unlock any objects * it is using! * * NOTE: This global system menu thing doesn't work: two apps can use * it at the same time: which would be a disasterous bug! */ if (ppopupmenu->spwndNotify != NULL) { pmenuSys = ppopupmenu->spwndNotify->head.rpdesk->spmenuSys; if (pmenuSys != NULL) { Unlock(&pmenuSys->spwndNotify); if ((pmenu = _GetSubMenu(pmenuSys, 0)) != NULL) Unlock(&pmenu->spwndNotify); } Unlock(&ppopupmenu->spwndNotify); } Unlock(&ppopupmenu->spwndPopupMenu); Unlock(&ppopupmenu->spwndNextPopup); Unlock(&ppopupmenu->spwndPrevPopup); Unlock(&ppopupmenu->spmenu); Unlock(&ppopupmenu->spmenuAlternate); Unlock(&ppopupmenu->spwndActivePopup); #ifdef DEBUG ppopupmenu->fFreed = TRUE; #endif if (ppopupmenu == &gpopupMenu) { UserAssert(gfPopupInUse); gfPopupInUse = FALSE; } else { UserFreePool(ppopupmenu); } }
BOOL xxxRegisterUserHungAppHandlers( PFNW32ET pfnW32EndTask, HANDLE hEventWowExec) { BOOL bRetVal; PPROCESSINFO ppi; PWOWPROCESSINFO pwpi; // // Allocate the per wow process info stuff // ensuring the memory is Zero init. // pwpi = (PWOWPROCESSINFO) UserAllocPoolWithQuota(sizeof(WOWPROCESSINFO), TAG_WOW); if (!pwpi) return FALSE; RtlZeroMemory(pwpi, sizeof(*pwpi)); // // Reference the WowExec event for kernel access // bRetVal = NT_SUCCESS(ObReferenceObjectByHandle( hEventWowExec, EVENT_ALL_ACCESS, NULL, UserMode, &pwpi->pEventWowExec, NULL )); // // if sucess then intialize the pwpi, ppi structs // else free allocated memory // if (bRetVal) { pwpi->hEventWowExecClient = hEventWowExec; pwpi->lpfnWowExitTask = (DWORD)pfnW32EndTask; ppi = PpiCurrent(); ppi->pwpi = pwpi; // add to the list, order doesn't matter pwpi->pwpiNext = gpwpiFirstWow; gpwpiFirstWow = pwpi; } else { UserFreePool(pwpi); } return bRetVal; }
VOID DestroyWindowsHotKeys( PWND pwnd) { PHOTKEY *pphk; PHOTKEY phk; pphk = &gphkFirst; while (*pphk) { if ((*pphk)->spwnd == pwnd) { phk = *pphk; *pphk = (*pphk)->phkNext; Unlock(&phk->spwnd); UserFreePool(phk); } else { pphk = &((*pphk)->phkNext); } } }
BOOL _DestroyCursor( PCURSOR pcur, DWORD cmdDestroy) { PPROCESSINFO ppi; PPROCESSINFO ppiCursor; int i; extern BOOL DestroyAniIcon(PACON pacon); if (pcur == NULL) { UserAssert(FALSE); return(TRUE); } ppi = PpiCurrent(); ppiCursor = GETPPI(pcur); /* * Remove this icon from the caption icon cache. */ for (i = 0; i < CCACHEDCAPTIONS; i++) { if (cachedCaptions[i].spcursor == pcur) { Unlock( &(cachedCaptions[i].spcursor) ); } } /* * First step in destroying an cursor */ switch (cmdDestroy) { case CURSOR_ALWAYSDESTROY: /* * Always destroy? then don't do any checking... */ break; case CURSOR_CALLFROMCLIENT: /* * Can't destroy public cursors/icons. */ if (ppiCursor == NULL) /* * Fake success if its a resource loaded icon because * this is how win95 responded. */ return !!(pcur->CURSORF_flags & CURSORF_FROMRESOURCE); /* * If this cursor was loaded from a resource, don't free it till the * process exits. This is the way we stay compatible with win3.0's * cursors which were actually resources. Resources under win3 have * reference counting and other "features" like handle values that * never change. Read more in the comment in * ServerLoadCreateCursorIcon(). */ if (pcur->CURSORF_flags & (CURSORF_LRSHARED | CURSORF_SECRET)) { return TRUE; } /* * One thread can't destroy the objects created by another. */ if (ppiCursor != ppi) { RIPERR0(ERROR_DESTROY_OBJECT_OF_OTHER_THREAD, RIP_VERBOSE, ""); return FALSE; } /* * fall through. */ case CURSOR_THREADCLEANUP: /* * Don't destroy public objects either (pretend it worked though). */ if (ppiCursor == NULL) return TRUE; break; } /* * First mark the object for destruction. This tells the locking code that * we want to destroy this object when the lock count goes to 0. If this * returns FALSE, we can't destroy the object yet. */ if (!HMMarkObjectDestroy((PHEAD)pcur)) return FALSE; if (pcur->strName.Length != 0) { UserFreePool((LPSTR)pcur->strName.Buffer); } if (pcur->atomModName != 0) { DeleteAtom(pcur->atomModName); } /* * If this is an ACON call its special routine to destroy it. */ if (pcur->CURSORF_flags & CURSORF_ACON) { DestroyAniIcon((PACON)pcur); } else { if (pcur->hbmMask != NULL) { GreDeleteObject(pcur->hbmMask); } if (pcur->hbmColor != NULL) { GreDeleteObject(pcur->hbmColor); } } /* * Ok to destroy... Free the handle (which will free the object and the * handle). */ DestroyEmptyCursorObject(pcur); return TRUE; }
PHOTKEY FindHotKey( PTHREADINFO ptiCurrent, PWND pwnd, int id, UINT fsModifiers, UINT vk, BOOL fUnregister, PBOOL pfKeysExist) { PHOTKEY phk, phkRet, phkPrev; /* * Initialize out 'return' values. */ *pfKeysExist = FALSE; phkRet = NULL; phk = gphkFirst; while (phk) { /* * If all this matches up then we've found it. */ if ((phk->pti == ptiCurrent) && (phk->spwnd == pwnd) && (phk->id == id)) { if (fUnregister) { /* * Unlink the HOTKEY from the list. */ if (phk == gphkFirst) { gphkFirst = phk->phkNext; } else { phkPrev->phkNext = phk->phkNext; } if ((pwnd != PWND_FOCUS) && (pwnd != PWND_INPUTOWNER)) { Unlock(&phk->spwnd); } UserFreePool((PVOID)phk); return((PHOTKEY)1); } phkRet = phk; } /* * If the key is already registered, set the exists flag so * the app knows it can't use this hotkey sequence. */ if ((phk->fsModifiers == fsModifiers) && (phk->vk == vk)) { /* * In the case of PWND_FOCUS, we need to check that the queues * are the same since PWND_FOCUS is local to the queue it was * registered under. */ if (phk->spwnd == PWND_FOCUS) { if (phk->pti == ptiCurrent) { *pfKeysExist = TRUE; } } else { *pfKeysExist = TRUE; } } phkPrev = phk; phk = phk->phkNext; } return phkRet; }
/***************************************************************************\ * xxxCsEvent * * Description: * Handles broadcasting of all types of DDEML events. * * History: * 11-1-91 sanfords Created. * 10-28-97 FritzS added cbEventData as a passed-in parameter. This was done because the EVENT_PACKET may be client-side and we capture the count to keep a hostile app from changing the size after data probing. \***************************************************************************/ DWORD xxxCsEvent( PEVENT_PACKET pep, WORD cbEventData) { PSVR_INSTANCE_INFO psiiT; PEVENT_PACKET pep2; HWND *ahwndEvent = NULL; PWND pwnd; int cHwndAllocated, i, cTargets; TL tlpwnd; TL tlpep2; TL tlahwndEvent; ULONG cbEventPacket; PTHREADINFO pti = PtiCurrent(); CheckCritIn(); /* * Copy pep info to a server side stable area */ cbEventPacket = cbEventData + sizeof(EVENT_PACKET) - sizeof(DWORD); pep2 = (PEVENT_PACKET)UserAllocPoolWithQuota(cbEventPacket, TAG_DDE5); if (pep2 == NULL) { return DMLERR_MEMORY_ERROR; } try { RtlCopyMemory((LPSTR)pep2, (LPSTR)pep, cbEventPacket); } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { UserFreePool(pep2); return DMLERR_INVALIDPARAMETER; } pep2->cbEventData = cbEventData; cTargets = 0; cHwndAllocated = 0; for (psiiT = psiiList; psiiT != NULL; psiiT = psiiT->next) { // // Don't bother with event windows for instances who's flags // indicate they're not interrested in the event. // if (((psiiT->afCmd & pep2->EventType) && !pep2->fSense) || (!(psiiT->afCmd & pep2->EventType) && pep2->fSense)) { continue; } if (cTargets >= cHwndAllocated) { if (ahwndEvent == NULL) { cHwndAllocated = 8; ahwndEvent = (HWND *)UserAllocPoolWithQuota( sizeof(HWND) * cHwndAllocated, TAG_DDE6); } else { DWORD dwSize = cHwndAllocated * sizeof(HWND); HWND *ahwndEventT = ahwndEvent; cHwndAllocated += 8; ahwndEvent = (HWND *)UserReAllocPoolWithQuota(ahwndEvent, dwSize, sizeof(HWND) * cHwndAllocated, TAG_DDE7); if (ahwndEvent == NULL) { UserFreePool(ahwndEventT); } } if (ahwndEvent == NULL) { UserFreePool(pep2); return DMLERR_MEMORY_ERROR; } } ahwndEvent[cTargets++] = PtoH(psiiT->spwndEvent); } ThreadLockPool(pti, pep2, &tlpep2); if (ahwndEvent != NULL) { ThreadLockPool(pti, ahwndEvent, &tlahwndEvent); for (i = 0; i < cTargets; i++) { /* * We need to change contexts for the callback */ pwnd = ValidateHwnd(ahwndEvent[i]); if (pwnd != NULL) { ThreadLockAlwaysWithPti(pti, pwnd, &tlpwnd); xxxSendMessage(pwnd, WM_DDEMLEVENT, 0, (LPARAM)pep2); ThreadUnlock(&tlpwnd); } } ThreadUnlockAndFreePool(pti, &tlahwndEvent); } ThreadUnlockAndFreePool(pti, &tlpep2); return DMLERR_NO_ERROR; }
HPALETTE CreatePaletteFromBitmap( HBITMAP hbm) { HPALETTE hpal; LPLOGPALETTE ppal; HBITMAP hbmT; DWORD size; int i; /* * Make room for temp logical palette of max size. */ size = sizeof(LOGPALETTE) + (MAXPAL * sizeof(PALETTEENTRY)); ppal = (LPLOGPALETTE)UserAllocPool(size, TAG_SYSTEM); if (!ppal) return NULL; /* * Retrieve the palette from the DIB(Section). The method of calling * GreGetDIBColorTable() can only be done on sections or REAL-Dibs. */ hbmT = GreSelectBitmap(ghdcMem, hbm); ppal->palVersion = 0x300; ppal->palNumEntries = (WORD)GreGetDIBColorTable(ghdcMem, 0, MAXPAL, (LPRGBQUAD)ppal->palPalEntry); GreSelectBitmap(ghdcMem, hbmT); /* * Create a halftone-palette if their are no entries. Otherwise, * swap the RGB values to be palentry-compatible and create us a * palette. */ if (ppal->palNumEntries == 0) { hpal = GreCreateHalftonePalette(gpDispInfo->hdcScreen); } else { BYTE tmpR; /* * Swap red/blue because a RGBQUAD and PALETTEENTRY dont get along. */ for (i=0; i < (int)ppal->palNumEntries; i++) { tmpR = ppal->palPalEntry[i].peRed; ppal->palPalEntry[i].peRed = ppal->palPalEntry[i].peBlue; ppal->palPalEntry[i].peBlue = tmpR; ppal->palPalEntry[i].peFlags = 0; } /* * If the Bitmap only has VGA colors in it we dont want to * use a palette. It just causes unessesary palette flashes. */ hpal = TestVGAColors(ppal) ? NULL : GreCreatePalette(ppal); } UserFreePool(ppal); /* * Make this palette public. */ if (hpal) GreSetPaletteOwner(hpal, OBJECT_OWNER_PUBLIC); return hpal; }
LPWSTR GetDeskWallpaperName(PUNICODE_STRING pProfileUserName, LPWSTR lpszFile ) { WCHAR wszKey[GDWPN_KEYSIZE]; WCHAR wszNone[GDWPN_KEYSIZE]; LPWSTR lpszBitmap = NULL; /* * Load the none-string. This will be used for comparisons later. */ ServerLoadString(hModuleWin, STR_NONE, wszNone, ARRAY_SIZE(wszNone)); if ((lpszFile == NULL) || (lpszFile == SETWALLPAPER_DEFAULT) || (lpszFile == SETWALLPAPER_METRICS)) { /* * Allocate a buffer for the wallpaper. We will assume * a default-size in this case. */ lpszBitmap = UserAllocPool(GDWPN_BITSIZE * sizeof(WCHAR), TAG_SYSTEM); if (lpszBitmap == NULL) return NULL; /* * Get the "Wallpaper" string from WIN.INI's [Desktop] section. The * section name is not localized, so hard code it. If the string * returned is Empty, then set it up for a none-wallpaper. */ if (!FastGetProfileStringFromIDW(pProfileUserName, PMAP_DESKTOP, STR_DTBITMAP, wszNone, lpszBitmap, GDWPN_BITSIZE )) { wcscpy(lpszBitmap, wszNone); } } else { UINT uLen; uLen = wcslen(lpszFile) + 1; uLen = max(uLen, GDWPN_BITSIZE); /* * Allocate enough space to store the name passed in. Returning * NULL will allow the wallpaper to redraw. As well, if we're * out of memory, then no need to load a wallpaper anyway. */ lpszBitmap = UserAllocPool(uLen * sizeof(WCHAR), TAG_SYSTEM); if (lpszBitmap == NULL) return NULL; wcscpy(lpszBitmap, lpszFile); } /* * No bitmap if NULL passed in or if (NONE) in win.ini entry. We * return NULL to force the redraw of the wallpaper in the kernel. */ if ((*lpszBitmap == (WCHAR)0) || (_wcsicmp(lpszBitmap, wszNone) == 0)) { UserFreePool(lpszBitmap); return NULL; } /* * If bitmap name set to (DEFAULT) then set it to the system bitmap. */ ServerLoadString(hModuleWin, STR_DEFAULT, wszKey, ARRAY_SIZE(wszKey)); if (_wcsicmp(lpszBitmap, wszKey) == 0) { GetDefaultWallpaperName(lpszBitmap); } return lpszBitmap; }
BOOL xxxSetDeskWallpaper(PUNICODE_STRING pProfileUserName, LPWSTR lpszFile) { BITMAP bm; UINT WallpaperStyle2; PWND pwndShell; TL tl; PTHREADINFO ptiCurrent = PtiCurrent(); PDESKTOP pdesk; BOOL fRet = FALSE; HBITMAP hbmOld; PROFINTINFO apsi[] = { {PMAP_DESKTOP, (LPWSTR)STR_TILEWALL , 0, &gwWPStyle }, {PMAP_DESKTOP, (LPWSTR)STR_DTSTYLE , 0, &WallpaperStyle2 }, {PMAP_DESKTOP, (LPWSTR)STR_DTORIGINX, 0, &gsrcWallpaper.x }, {PMAP_DESKTOP, (LPWSTR)STR_DTORIGINY, 0, &gsrcWallpaper.y }, {0, NULL, 0, NULL } }; pdesk = ptiCurrent->rpdesk; hbmOld = ghbmWallpaper; /* * Get the shell-window. This could be NULL on system * initialization. We will use this to do palette realization. */ pwndShell = (pdesk ? pdesk->pDeskInfo->spwndShell : NULL); if ((lpszFile == SETWALLPAPER_METRICS) && !(gwWPStyle & DTF_STRETCH)) { gsrcWallpaper.x = 0; gsrcWallpaper.y = 0; if (ghbmWallpaper) goto CreateNewWallpaper; goto Metric_Change; } CreateNewWallpaper: /* * Delete the old wallpaper and palette if the exist. */ if (ghpalWallpaper) { GreDeleteObject(ghpalWallpaper); ghpalWallpaper = NULL; } if (ghbmWallpaper) { GreDeleteObject(ghbmWallpaper); ghbmWallpaper = NULL; } /* * Kill any SPBs no matter what. * Works if we're switching from/to palettized wallpaper. * Fixes a lot of problems because palette doesn't change, shell * paints funny on desktop, etc. */ FreeAllSpbs(); /* * If this is a metric-change (and stretched), then we need to * reload it. However, since we are called from the winlogon process * during a desktop-switch, we would be mapped to the wrong Luid * when we attempt to grab the name from GetDeskWallpaperName. This * would use the Luid from the DEFAULT user rather than the current * logged on user. In order to avoid this, we cache the wallpaer * name so that on METRIC-CHANGES we use the current-user's wallpaper. * * NOTE: we assume that prior to any METRIC change, we have already * setup the ghbmWallpaper and lpszCached. This is usually done * either on logon or during user desktop-changes through conrol-Panel. */ if (lpszFile == SETWALLPAPER_METRICS) { UserAssert(gpszWall != NULL); goto LoadWallpaper; } /* * Free the cached handle. */ if (gpszWall) { UserFreePool(gpszWall); gpszWall = NULL; } /* * Load the wallpaper-name. If this returns FALSE, then * the user specified (None). We will return true to force * the repainting of the desktop. */ gpszWall = GetDeskWallpaperName(pProfileUserName,lpszFile); if (!gpszWall) { fRet = TRUE; goto SDW_Exit; } /* * Retrieve the default settings from the registry. * * If tile is indicated, then normalize style to not include * FIT/STRETCH which are center-only styles. Likewise, if * we are centered, then normalize out the TILE bit. */ FastGetProfileIntsW(pProfileUserName, apsi); gwWPStyle &= DTF_TILE; if (!(gwWPStyle & DTF_TILE)) { gwWPStyle = WallpaperStyle2 & DTF_STRETCH; } /* * Load the wallpaper. This makes a callback to the client to * perform the bitmap-creation. */ LoadWallpaper: if (xxxLoadDesktopWallpaper(gpszWall) == FALSE) { gwWPStyle = 0; goto SDW_Exit; } /* * If we have a palette, then we need to do the correct realization and * notification. */ if (ghpalWallpaper != NULL) { PWND pwndSend; if (pwndShell) { pwndSend = pwndShell; } else { pwndSend = (pdesk ? pdesk->pDeskInfo->spwnd : NULL); } /* * Update the desktop with the new bitmap. This cleans * out the system-palette so colors can be realized. */ GreRealizeDefaultPalette(gpDispInfo->hdcScreen, TRUE); /* * Don't broadcast if system initialization is occuring. Otherwise * this gives the shell first-crack at realizing its colors * correctly. */ if (pwndSend) { HWND hwnd = HW(pwndSend); ThreadLockAlways(pwndSend, &tl); xxxSendNotifyMessage(pwndSend, WM_PALETTECHANGED, (WPARAM)hwnd, 0); ThreadUnlock(&tl); } } Metric_Change: if (fRet = GreExtGetObjectW(ghbmWallpaper, sizeof(bm), (PBITMAP)&bm)) { gsrcWallpaper.cx = bm.bmWidth; gsrcWallpaper.cy = bm.bmHeight; } // fall-through SDW_Exit: /* * Notify the shell-window that the wallpaper changed. */ if ((pwndShell != NULL) && ((hbmOld && !ghbmWallpaper) || (!hbmOld && ghbmWallpaper))) { ThreadLockAlways(pwndShell, &tl); xxxSendNotifyMessage(pwndShell, WM_SHELLNOTIFY, SHELLNOTIFY_WALLPAPERCHANGED, (LPARAM)ghbmWallpaper); ThreadUnlock(&tl); } return fRet; }
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); ptiCurrent = PtiCurrent(); /* * If this is a thread of winlogon, don't do the snapshot. */ if (GetCurrentProcessId() == 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 ((pwnd != NULL) && TestWF(pwnd, WFCHILD)) { pwnd = pwnd->spwndParent; } /* * 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 = xxxOpenClipboard(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; }
// // Insert/remove the specified IME hotkey into/from // the IME hotkey list (gpImeHotKeyListHeader). // BOOL SetImeHotKey( DWORD dwHotKeyID, UINT uModifiers, UINT uVKey, HKL hKL, DWORD dwAction ) { PIMEHOTKEYOBJ ph; switch ( dwAction ) { case ISHK_REMOVE: ph = FindImeHotKeyByID( gpImeHotKeyListHeader, dwHotKeyID ); if ( ph != NULL ) { if ( DeleteImeHotKey( &gpImeHotKeyListHeader, ph ) == ph ) { UserFreePool( ph ); return ( TRUE ); } else { RIPMSG0( RIP_ERROR, "IME hotkey list is messed up" ); return ( FALSE ); } } else { RIPERR0( ERROR_INVALID_PARAMETER, RIP_WARNING, "no such IME hotkey registered"); return ( FALSE ); } break; case ISHK_INITIALIZE: ph = gpImeHotKeyListHeader; while ( ph != NULL ) { PIMEHOTKEYOBJ phNext; phNext = ph->pNext; UserFreePool( ph ); ph = phNext; } gpImeHotKeyListHeader = NULL; return TRUE; case ISHK_ADD: ph = FindImeHotKeyByKey( gpImeHotKeyListHeader, uModifiers & MOD_MODIFY_KEYS, uModifiers & MOD_BOTH_SIDES, uVKey ); if ( ph != NULL ) { if ( ph->hk.dwHotKeyID != dwHotKeyID ) { RIPERR0( ERROR_HOTKEY_ALREADY_REGISTERED, RIP_WARNING, "There is an IME hotkey that has the same vkey/modifiers"); return ( FALSE ); } // So far we found a hotkey that has the // same vkey and same ID. // But because modifiers may be slightly // different, so go ahead and change it. } else { // // the specified vkey/modifiers combination cound not be found // in the hotkey list. The caller may want to change the key // assignment of an existing hotkey or add a new hotkey. // ph = FindImeHotKeyByID( gpImeHotKeyListHeader, dwHotKeyID ); } if ( ph == NULL ) { // // adding a new hotkey // ph = (PIMEHOTKEYOBJ)UserAllocPool( sizeof(IMEHOTKEY), TAG_IMEHOTKEY ); if ( ph == NULL ) { RIPERR0( ERROR_OUTOFMEMORY, RIP_WARNING, "Memory allocation failed in SetImeHotKey"); return ( FALSE ); } ph->hk.dwHotKeyID = dwHotKeyID; ph->hk.uModifiers = uModifiers; ph->hk.uVKey = uVKey; ph->hk.hKL = hKL; ph->pNext = NULL; AddImeHotKey( &gpImeHotKeyListHeader, ph ); } else { // // changing an existing hotkey // ph->hk.uModifiers = uModifiers; ph->hk.uVKey = uVKey; ph->hk.hKL = hKL; } return ( TRUE ); break; }; }
UINT DWP_SetHotKey( PWND pwnd, DWORD dwKey) { PHOTKEYSTRUCT phk; BOOL fKeyExists = FALSE; PWND pwndTemp; /* * Filter out invalid hotkeys */ if (LOBYTE(dwKey) == VK_ESCAPE || LOBYTE(dwKey) == VK_SPACE || LOBYTE(dwKey) == VK_TAB || LOBYTE(dwKey) == VK_PACKET) { return (UINT)-1; } /* * Don't allow hotkeys for children */ if (TestWF(pwnd, WFCHILD)) return 0; /* * Check if the hot key exists and is assigned to a different pwnd */ if (dwKey != 0) { pwndTemp = HotKeyToWindow(dwKey); if ((pwndTemp != NULL) && (pwndTemp != pwnd)) fKeyExists = TRUE; } /* * Get the hotkey assigned to the window, if any */ if ((phk = HotKeyHelper(pwnd)) == NULL) { /* * Window doesn't exist in the hotkey list and key is being set * to zero, so just return. */ if (dwKey == 0) return 1; /* * Allocate and point to a spot for the new hotkey */ if (gcHotKey >= gcHotKeyAlloc) { if (gcHotKeyAlloc) { phk = (PHOTKEYSTRUCT)UserReAllocPool( (HANDLE)gpHotKeyList, gcHotKeyAlloc * sizeof(HOTKEYSTRUCT), (gcHotKey + 1) * sizeof(HOTKEYSTRUCT), TAG_HOTKEY); if (phk != NULL) { gpHotKeyList = phk; phk = &gpHotKeyList[gcHotKey++]; gcHotKeyAlloc = gcHotKey; } else { return 0; } } else { UserAssert(gpHotKeyList == NULL); UserAssert(gcHotKey == 0); phk = (PHOTKEYSTRUCT)UserAllocPool(sizeof(HOTKEYSTRUCT), TAG_HOTKEY); if (phk != NULL) { gpHotKeyList = phk; gcHotKey = 1; gcHotKeyAlloc = 1; } else { return 0; } } } else { phk = &gpHotKeyList[gcHotKey++]; } } if (dwKey == 0) { /* * The hotkey for this window is being deleted. Copy the last item * on the list on top of the one being deleted. */ if (--gcHotKey) { Lock(&phk->spwnd, gpHotKeyList[gcHotKey].spwnd); Unlock(&gpHotKeyList[gcHotKey].spwnd); phk->key = gpHotKeyList[gcHotKey].key; phk = (PHOTKEYSTRUCT)UserReAllocPool((HANDLE)gpHotKeyList, gcHotKeyAlloc * sizeof(HOTKEYSTRUCT), gcHotKey * sizeof(HOTKEYSTRUCT), TAG_HOTKEY); if (phk != NULL) { gpHotKeyList = phk; gcHotKeyAlloc = gcHotKey; } } else { Unlock(&gpHotKeyList[gcHotKey].spwnd); UserFreePool((HANDLE)gpHotKeyList); gpHotKeyList = NULL; gcHotKeyAlloc = 0; } } else { /* * Add the window and key to the list */ phk->spwnd = NULL; Lock(&phk->spwnd, pwnd); phk->key = dwKey; } return fKeyExists ? 2 : 1; }