/* * @implemented */ BOOL APIENTRY NtUserGetIconSize( HANDLE hCurIcon, UINT istepIfAniCur, PLONG plcx, // &size.cx PLONG plcy) // &size.cy { PCURICON_OBJECT CurIcon; NTSTATUS Status = STATUS_SUCCESS; BOOL bRet = FALSE; TRACE("Enter NtUserGetIconSize\n"); UserEnterExclusive(); if (!(CurIcon = UserGetCurIconObject(hCurIcon))) { goto cleanup; } if(CurIcon->CURSORF_flags & CURSORF_ACON) { /* Use first frame for animated cursors */ PACON AniCurIcon = (PACON)CurIcon; CurIcon = AniCurIcon->aspcur[0]; UserDereferenceObject(AniCurIcon); UserReferenceObject(CurIcon); } _SEH2_TRY { ProbeForWrite(plcx, sizeof(LONG), 1); *plcx = CurIcon->cx; ProbeForWrite(plcy, sizeof(LONG), 1); *plcy = CurIcon->cy; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END if (NT_SUCCESS(Status)) bRet = TRUE; else SetLastNtError(Status); // Maybe not, test this UserDereferenceObject(CurIcon); cleanup: TRACE("Leave NtUserGetIconSize, ret=%i\n", bRet); UserLeave(); return bRet; }
static BOOL FASTCALL RemoveTimer(PTIMER pTmr) { BOOL Ret = FALSE; if (pTmr) { /* Set the flag, it will be removed when ready */ RemoveEntryList(&pTmr->ptmrList); if ((pTmr->pWnd == NULL) && (!(pTmr->flags & TMRF_SYSTEM))) // System timers are reusable. { UINT_PTR IDEvent; IDEvent = NUM_WINDOW_LESS_TIMERS - pTmr->nID; IntLockWindowlessTimerBitmap(); RtlClearBit(&WindowLessTimersBitMap, IDEvent); IntUnlockWindowlessTimerBitmap(); } UserDereferenceObject(pTmr); Ret = UserDeleteObject( UserHMGetHandle(pTmr), otTimer); } if (!Ret) ERR("Warning: Unable to delete timer\n"); return Ret; }
/* * co_UserActivateKbl * * Activates given layout in specified thread */ static PKL co_UserActivateKbl(PTHREADINFO pti, PKL pKl, UINT Flags) { PKL pklPrev; pklPrev = pti->KeyboardLayout; if (pklPrev) UserDereferenceObject(pklPrev); pti->KeyboardLayout = pKl; pti->pClientInfo->hKL = pKl->hkl; UserReferenceObject(pKl); if (Flags & KLF_SETFORPROCESS) { // FIXME } // Send WM_INPUTLANGCHANGE to thread's focus window co_IntSendMessage(pti->MessageQueue->spwndFocus ? UserHMGetHandle(pti->MessageQueue->spwndFocus) : 0, WM_INPUTLANGCHANGE, (WPARAM)pKl->iBaseCharset, // FIXME: How to set it? (LPARAM)pKl->hkl); // hkl return pklPrev; }
/* IntDestroyMonitorObject * * Destroys a MONITOR * You have to be the owner of the monitors lock to safely destroy it. * * Arguments * * pMonitor * Pointer to the MONITOR which shall be deleted */ static void IntDestroyMonitorObject(IN PMONITOR pMonitor) { RtlFreeUnicodeString(&pMonitor->DeviceName); UserDereferenceObject(pMonitor); }
/* * UserLoadKbdLayout * * Loads keyboard layout and creates KL object */ static PKL UserLoadKbdLayout(PUNICODE_STRING pwszKLID, HKL hKL) { LCID lCid; CHARSETINFO cs; PKL pKl; /* Create keyboard layout object */ pKl = UserCreateObject(gHandleTable, NULL, NULL, NULL, TYPE_KBDLAYOUT, sizeof(KL)); if (!pKl) { ERR("Failed to create object!\n"); return NULL; } pKl->hkl = hKL; pKl->spkf = UserLoadKbdFile(pwszKLID); /* Dereference keyboard layout */ UserDereferenceObject(pKl); /* If we failed, remove KL object */ if (!pKl->spkf) { ERR("UserLoadKbdFile(%wZ) failed!\n", pwszKLID); UserDeleteObject(pKl->head.h, TYPE_KBDLAYOUT); return NULL; } // Up to Language Identifiers.. RtlUnicodeStringToInteger(pwszKLID, (ULONG)16, (PULONG)&lCid); TRACE("Language Identifiers %wZ LCID 0x%x\n", pwszKLID, lCid); if (co_IntGetCharsetInfo(lCid, &cs)) { pKl->iBaseCharset = cs.ciCharset; pKl->dwFontSigs = cs.fs.fsCsb[0]; pKl->CodePage = (USHORT)cs.ciACP; TRACE("Charset %u Font Sig %lu CodePage %u\n", pKl->iBaseCharset, pKl->dwFontSigs, pKl->CodePage); } else { pKl->iBaseCharset = ANSI_CHARSET; pKl->dwFontSigs = FS_LATIN1; pKl->CodePage = CP_ACP; } // Set initial system character set and font signature. if (gSystemFS == 0) { gSystemCPCharSet = pKl->iBaseCharset; gSystemFS = pKl->dwFontSigs; } return pKl; }
static VOID NTAPI IntAddSynthesizedFormats(PWINSTATION_OBJECT pWinStaObj) { PCLIP pTextEl, pUniTextEl, pOemTextEl, pLocaleEl, pBmEl, pDibEl; pTextEl = IntIsFormatAvailable(pWinStaObj, CF_TEXT); pOemTextEl = IntIsFormatAvailable(pWinStaObj, CF_OEMTEXT); pUniTextEl = IntIsFormatAvailable(pWinStaObj, CF_UNICODETEXT); pLocaleEl = IntIsFormatAvailable(pWinStaObj, CF_LOCALE); pBmEl = IntIsFormatAvailable(pWinStaObj, CF_BITMAP); pDibEl = IntIsFormatAvailable(pWinStaObj, CF_DIB); /* Add CF_LOCALE format if we have CF_TEXT */ if (!pLocaleEl && pTextEl) { PCLIPBOARDDATA pMemObj; HANDLE hMem; pMemObj = (PCLIPBOARDDATA)UserCreateObject(gHandleTable, NULL, NULL, &hMem, TYPE_CLIPDATA, sizeof(CLIPBOARDDATA) + sizeof(LCID)); if (pMemObj) { pMemObj->cbData = sizeof(LCID); *((LCID*)pMemObj->Data) = NtCurrentTeb()->CurrentLocale; IntAddFormatedData(pWinStaObj, CF_LOCALE, hMem, TRUE, TRUE); /* Release the extra reference (UserCreateObject added 2 references) */ UserDereferenceObject(pMemObj); } } /* Add CF_TEXT. Note: it is synthesized in user32.dll */ if (!pTextEl && (pUniTextEl || pOemTextEl)) IntAddFormatedData(pWinStaObj, CF_TEXT, DATA_SYNTH_USER, FALSE, TRUE); /* Add CF_OEMTEXT. Note: it is synthesized in user32.dll */ if (!pOemTextEl && (pUniTextEl || pTextEl)) IntAddFormatedData(pWinStaObj, CF_OEMTEXT, DATA_SYNTH_USER, FALSE, TRUE); /* Add CF_UNICODETEXT. Note: it is synthesized in user32.dll */ if (!pUniTextEl && (pTextEl || pOemTextEl)) IntAddFormatedData(pWinStaObj, CF_UNICODETEXT, DATA_SYNTH_USER, FALSE, TRUE); /* Add CF_BITMAP. Note: it is synthesized on demand */ if (!pBmEl && pDibEl) IntAddFormatedData(pWinStaObj, CF_BITMAP, DATA_SYNTH_KRNL, FALSE, TRUE); /* Note: We need to render the DIB or DIBV5 format as soon as possible because pallette information may change */ if (!pDibEl && pBmEl) IntSynthesizeDib(pWinStaObj, pBmEl->hData); }
/* IntAttachMonitor * * Creates a new MONITOR and appends it to the list of monitors. * * Arguments * * pGdiDevice Pointer to the PDEVOBJ onto which the monitor was attached * DisplayNumber Display Number (starting with 0) * * Return value * Returns a NTSTATUS */ NTSTATUS IntAttachMonitor(IN PDEVOBJ *pGdiDevice, IN ULONG DisplayNumber) { PMONITOR Monitor; WCHAR Buffer[CCHDEVICENAME]; TRACE("Attaching monitor...\n"); /* create new monitor object */ Monitor = IntCreateMonitorObject(); if (Monitor == NULL) { TRACE("Couldnt create monitor object\n"); return STATUS_INSUFFICIENT_RESOURCES; } _snwprintf(Buffer, CCHDEVICENAME, L"\\\\.\\DISPLAY%d", DisplayNumber + 1); if (!RtlCreateUnicodeString(&Monitor->DeviceName, Buffer)) { TRACE("Couldn't duplicate monitor name!\n"); UserDereferenceObject(Monitor); UserDeleteObject(UserHMGetHandle(Monitor), otMonitor); return STATUS_INSUFFICIENT_RESOURCES; } Monitor->GdiDevice = pGdiDevice; Monitor->cWndStack = 0; if (gMonitorList == NULL) { TRACE("Primary monitor is beeing attached\n"); Monitor->IsPrimary = TRUE; gMonitorList = Monitor; } else { PMONITOR p; TRACE("Additional monitor is beeing attached\n"); for (p = gMonitorList; p->Next != NULL; p = p->Next) { p->Next = Monitor; } Monitor->Prev = p; } IntUpdateMonitorSize(pGdiDevice); return STATUS_SUCCESS; }
/* IntDestroyMonitorObject * * Destroys a MONITOR * You have to be the owner of the monitors lock to safely destroy it. * * Arguments * * pMonitor * Pointer to the MONITOR which shall be deleted */ static void IntDestroyMonitorObject(IN PMONITOR pMonitor) { /* Remove monitor region */ if (pMonitor->hrgnMonitor) { GreSetObjectOwner(pMonitor->hrgnMonitor, GDI_OBJ_HMGR_POWNED); GreDeleteObject(pMonitor->hrgnMonitor); } /* Destroy monitor object */ UserDereferenceObject(pMonitor); UserDeleteObject(UserHMGetHandle(pMonitor), TYPE_MONITOR); }
/* * @implemented */ HCURSOR APIENTRY NtUserSetCursor( HCURSOR hCursor) { PCURICON_OBJECT pcurOld, pcurNew; HCURSOR hOldCursor = NULL; TRACE("Enter NtUserSetCursor\n"); UserEnterExclusive(); if (hCursor) { pcurNew = UserGetCurIconObject(hCursor); if (!pcurNew) { EngSetLastError(ERROR_INVALID_CURSOR_HANDLE); goto leave; } pcurNew->CURSORF_flags |= CURSORF_CURRENT; } else { pcurNew = NULL; } pcurOld = UserSetCursor(pcurNew, FALSE); if (pcurOld) { hOldCursor = pcurOld->head.h; pcurOld->CURSORF_flags &= ~CURSORF_CURRENT; if(UserObjectInDestroy(hOldCursor)) { /* Destroy it once and for all */ IntDestroyCurIconObject(pcurOld, TRUE); hOldCursor = NULL; } else { UserDereferenceObject(pcurOld); } } leave: UserLeave(); return hOldCursor; }
HANDLE APIENTRY NtUserConvertMemHandle( PVOID pData, DWORD cbData) { HANDLE hMem = NULL; PCLIPBOARDDATA pMemObj; UserEnterExclusive(); /* Create Clipboard data object */ pMemObj = UserCreateObject(gHandleTable, NULL, NULL, &hMem, TYPE_CLIPDATA, sizeof(CLIPBOARDDATA) + cbData); if (!pMemObj) goto cleanup; pMemObj->cbData = cbData; /* Copy data */ _SEH2_TRY { ProbeForRead(pData, cbData, 1); memcpy(pMemObj->Data, pData, cbData); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { pMemObj = NULL; } _SEH2_END; /* Release the extra reference (UserCreateObject added 2 references) */ UserDereferenceObject(pMemObj); /* If we failed to copy data, remove handle */ if (!pMemObj) { UserDeleteObject(hMem, TYPE_CLIPDATA); hMem = NULL; } cleanup: UserLeave(); return hMem; }
/* * @implemented */ BOOL APIENTRY NtUserDrawIconEx( HDC hdc, int xLeft, int yTop, HICON hIcon, int cxWidth, int cyHeight, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags, BOOL bMetaHDC, // When TRUE, GDI functions need to be handled in User32! PVOID pDIXData) { PCURICON_OBJECT pIcon; BOOL Ret; TRACE("Enter NtUserDrawIconEx\n"); UserEnterExclusive(); if (!(pIcon = UserGetCurIconObject(hIcon))) { ERR("UserGetCurIconObject(0x%08x) failed!\n", hIcon); UserLeave(); return FALSE; } Ret = UserDrawIconEx(hdc, xLeft, yTop, pIcon, cxWidth, cyHeight, istepIfAniCur, hbrFlickerFreeDraw, diFlags); UserDereferenceObject(pIcon); UserLeave(); return Ret; }
HANDLE IntCreateCurIconHandle(BOOLEAN Animated) { PCURICON_OBJECT CurIcon; HANDLE hCurIcon; CurIcon = UserCreateObject( gHandleTable, NULL, NULL, &hCurIcon, TYPE_CURSOR, Animated ? sizeof(ACON) : sizeof(CURICON_OBJECT)); if (!CurIcon) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } UserDereferenceObject(CurIcon); return hCurIcon; }
/* * UserLoadKbdFile * * Loads keyboard layout DLL and creates KBDFILE object */ static PKBDFILE UserLoadKbdFile(PUNICODE_STRING pwszKLID) { PKBDFILE pkf, pRet = NULL; NTSTATUS Status; ULONG cbSize; HKEY hKey = NULL; WCHAR wszLayoutPath[MAX_PATH] = L"\\SystemRoot\\System32\\"; WCHAR wszLayoutRegKey[256] = L"\\REGISTRY\\Machine\\SYSTEM\\CurrentControlSet\\" L"Control\\Keyboard Layouts\\"; /* Create keyboard layout file object */ pkf = UserCreateObject(gHandleTable, NULL, NULL, NULL, TYPE_KBDFILE, sizeof(KBDFILE)); if (!pkf) { ERR("Failed to create object!\n"); return NULL; } /* Set keyboard layout name */ swprintf(pkf->awchKF, L"%wZ", pwszKLID); /* Open layout registry key */ RtlStringCbCatW(wszLayoutRegKey, sizeof(wszLayoutRegKey), pkf->awchKF); Status = RegOpenKey(wszLayoutRegKey, &hKey); if (!NT_SUCCESS(Status)) { ERR("Failed to open keyboard layouts registry key %ws (%lx)\n", wszLayoutRegKey, Status); goto cleanup; } /* Read filename of layout DLL */ cbSize = sizeof(wszLayoutPath) - wcslen(wszLayoutPath)*sizeof(WCHAR); Status = RegQueryValue(hKey, L"Layout File", REG_SZ, wszLayoutPath + wcslen(wszLayoutPath), &cbSize); if (!NT_SUCCESS(Status)) { ERR("Can't get layout filename for %wZ (%lx)\n", pwszKLID, Status); goto cleanup; } /* Load keyboard file now */ if (!UserLoadKbdDll(wszLayoutPath, &pkf->hBase, &pkf->pKbdTbl)) { ERR("Failed to load %ws dll!\n", wszLayoutPath); goto cleanup; } /* Update next field */ pkf->pkfNext = gpkfList; gpkfList = pkf; /* Return keyboard file */ pRet = pkf; cleanup: if (hKey) ZwClose(hKey); if (pkf) UserDereferenceObject(pkf); // we dont need ptr anymore if (!pRet) { /* We have failed - destroy created object */ if (pkf) UserDeleteObject(pkf->head.h, TYPE_KBDFILE); } return pRet; }
static VOID NTAPI IntSynthesizeDib( PWINSTATION_OBJECT pWinStaObj, HBITMAP hbm) { HDC hdc; ULONG cjInfoSize, cjDataSize; PCLIPBOARDDATA pClipboardData; HANDLE hMem; INT iResult; struct { BITMAPINFOHEADER bmih; RGBQUAD rgbColors[256]; } bmiBuffer; PBITMAPINFO pbmi = (PBITMAPINFO)&bmiBuffer; /* Get the display DC */ hdc = UserGetDCEx(NULL, NULL, DCX_USESTYLE); if (!hdc) { return; } /* Get information about the bitmap format */ iResult = GreGetDIBitsInternal(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS, 0, sizeof(bmiBuffer)); if (iResult == 0) { goto cleanup; } /* Get the size for a full BITMAPINFO */ cjInfoSize = DIB_BitmapInfoSize(pbmi, DIB_RGB_COLORS); /* Calculate the size of the clipboard data, which is a packed DIB */ cjDataSize = cjInfoSize + pbmi->bmiHeader.biSizeImage; /* Create the clipboard data */ pClipboardData = (PCLIPBOARDDATA)UserCreateObject(gHandleTable, NULL, NULL, &hMem, TYPE_CLIPDATA, cjDataSize); if (!pClipboardData) { goto cleanup; } /* Set the data size */ pClipboardData->cbData = cjDataSize; /* Copy the BITMAPINFOHEADER */ memcpy(pClipboardData->Data, pbmi, sizeof(BITMAPINFOHEADER)); /* Get the bitmap bits and the color table */ iResult = GreGetDIBitsInternal(hdc, hbm, 0, abs(pbmi->bmiHeader.biHeight), (LPBYTE)pClipboardData->Data + cjInfoSize, (LPBITMAPINFO)pClipboardData->Data, DIB_RGB_COLORS, pbmi->bmiHeader.biSizeImage, cjInfoSize); /* Add the clipboard data */ IntAddFormatedData(pWinStaObj, CF_DIB, hMem, TRUE, TRUE); /* Release the extra reference (UserCreateObject added 2 references) */ UserDereferenceObject(pClipboardData); cleanup: UserReleaseDC(NULL, hdc, FALSE); }
HWINEVENTHOOK APIENTRY NtUserSetWinEventHook( UINT eventMin, UINT eventMax, HMODULE hmodWinEventProc, PUNICODE_STRING puString, WINEVENTPROC lpfnWinEventProc, DWORD idProcess, DWORD idThread, UINT dwflags) { PEVENTHOOK pEH; HWINEVENTHOOK Ret = NULL; NTSTATUS Status; HANDLE Handle; PETHREAD Thread = NULL; TRACE("NtUserSetWinEventHook hmod 0x%x, pfn 0x%x\n",hmodWinEventProc, lpfnWinEventProc); UserEnterExclusive(); if ( !GlobalEvents ) { GlobalEvents = ExAllocatePoolWithTag(PagedPool, sizeof(EVENTTABLE), TAG_HOOK); if (GlobalEvents == NULL) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); goto SetEventExit; } GlobalEvents->Counts = 0; InitializeListHead(&GlobalEvents->Events); } if (eventMin > eventMax) { EngSetLastError(ERROR_INVALID_HOOK_FILTER); goto SetEventExit; } if (!lpfnWinEventProc) { EngSetLastError(ERROR_INVALID_FILTER_PROC); goto SetEventExit; } if ((dwflags & WINEVENT_INCONTEXT) && !hmodWinEventProc) { EngSetLastError(ERROR_HOOK_NEEDS_HMOD); goto SetEventExit; } if (idThread) { Status = PsLookupThreadByThreadId((HANDLE)(DWORD_PTR)idThread, &Thread); if (!NT_SUCCESS(Status)) { EngSetLastError(ERROR_INVALID_THREAD_ID); goto SetEventExit; } } // Creator, pti is set here. pEH = UserCreateObject(gHandleTable, NULL, &Handle, otEvent, sizeof(EVENTHOOK)); if (pEH) { InsertTailList(&GlobalEvents->Events, &pEH->Chain); GlobalEvents->Counts++; UserHMGetHandle(pEH) = Handle; pEH->eventMin = eventMin; pEH->eventMax = eventMax; pEH->idProcess = idProcess; // These are cmp'ed pEH->idThread = idThread; // " pEH->Flags = dwflags; /* If WINEVENT_INCONTEXT, set offset from hmod and proc. Save ihmod from the atom index table where the hmod data is saved to be recalled later if fSync set by WINEVENT_INCONTEXT. If WINEVENT_OUTOFCONTEXT just use proc.. Do this instead.... */ if (NULL != hmodWinEventProc) { pEH->offPfn = (ULONG_PTR)((char *)lpfnWinEventProc - (char *)hmodWinEventProc); pEH->ihmod = (INT)hmodWinEventProc; pEH->Proc = lpfnWinEventProc; } else pEH->Proc = lpfnWinEventProc; UserDereferenceObject(pEH); Ret = Handle; IntSetSrvEventMask( eventMin, eventMax); } SetEventExit: if (Thread) ObDereferenceObject(Thread); UserLeave(); return Ret; }
VOID FASTCALL IntNotifyWinEvent( DWORD Event, PWND pWnd, LONG idObject, LONG idChild, DWORD flags) { PEVENTHOOK pEH; PLIST_ENTRY pLE; PTHREADINFO pti, ptiCurrent; TRACE("IntNotifyWinEvent GlobalEvents = 0x%x pWnd 0x%x\n",GlobalEvents, pWnd); if (!GlobalEvents || !GlobalEvents->Counts) return; if (pWnd && pWnd->state & WNDS_DESTROYED) return; ptiCurrent = PsGetCurrentThreadWin32Thread(); if (pWnd && flags & WEF_SETBYWNDPTI) pti = pWnd->head.pti; else pti = ptiCurrent; pLE = GlobalEvents->Events.Flink; pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain); do { if (!pEH) break; UserReferenceObject(pEH); // Must be inside the event window. if ( (pEH->eventMin <= Event) && (pEH->eventMax >= Event)) { // if all process || all thread || other thread same process // if ^skip own thread && ((Pid && CPid == Pid && ^skip own process) || all process) if ( (!pEH->idProcess || pEH->idProcess == PtrToUint(pti->pEThread->Cid.UniqueProcess)) && (!(pEH->Flags & WINEVENT_SKIPOWNPROCESS) || pEH->head.pti->ppi != pti->ppi) && (!pEH->idThread || pEH->idThread == PtrToUint(pti->pEThread->Cid.UniqueThread)) && (!(pEH->Flags & WINEVENT_SKIPOWNTHREAD) || pEH->head.pti != pti) && pEH->head.pti->rpdesk == ptiCurrent->rpdesk ) // Same as hooks. { // Send message to the thread if pEH is not current. if (pEH->head.pti != ptiCurrent) { ERR("Global Event 0x%x, idObject %d\n", Event, idObject); IntCallLowLevelEvent( pEH, Event, UserHMGetHandle(pWnd), idObject, idChild); } else { ERR("Local Event 0x%x, idObject %d\n", Event, idObject); co_IntCallEventProc( UserHMGetHandle(pEH), Event, UserHMGetHandle(pWnd), idObject, idChild, PtrToUint(NtCurrentTeb()->ClientId.UniqueThread), (DWORD)EngGetTickCount(), pEH->Proc); } } } UserDereferenceObject(pEH); pLE = pEH->Chain.Flink; pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain); } while (pLE != &GlobalEvents->Events); }
/* * @unimplemented */ HCURSOR NTAPI NtUserGetCursorFrameInfo( HCURSOR hCursor, DWORD istep, INT* rate_jiffies, DWORD* num_steps) { PCURICON_OBJECT CurIcon; HCURSOR ret; INT jiffies = 0; DWORD steps = 1; NTSTATUS Status = STATUS_SUCCESS; TRACE("Enter NtUserGetCursorFrameInfo\n"); UserEnterExclusive(); if (!(CurIcon = UserGetCurIconObject(hCursor))) { UserLeave(); return NULL; } ret = CurIcon->head.h; if(CurIcon->CURSORF_flags & CURSORF_ACON) { PACON AniCurIcon = (PACON)CurIcon; if(istep >= AniCurIcon->cicur) { UserDereferenceObject(CurIcon); UserLeave(); return NULL; } jiffies = AniCurIcon->ajifRate[istep]; steps = AniCurIcon->cicur; ret = AniCurIcon->aspcur[AniCurIcon->aicur[istep]]->head.h; } _SEH2_TRY { ProbeForWrite(rate_jiffies, sizeof(INT), 1); ProbeForWrite(num_steps, sizeof(DWORD), 1); *rate_jiffies = jiffies; *num_steps = steps; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END if (!NT_SUCCESS(Status)) { WARN("Status: 0x%08x.\n", Status); SetLastNtError(Status); ret = NULL; } UserDereferenceObject(CurIcon); UserLeave(); TRACE("Leaving NtUserGetCursorFrameInfo, ret = 0x%08x\n", ret); return ret; }
/* * @implemented */ DWORD_PTR APIENTRY NtUserCallOneParam( DWORD_PTR Param, DWORD Routine) { DECLARE_RETURN(DWORD_PTR); TRACE("Enter NtUserCallOneParam\n"); UserEnterExclusive(); switch(Routine) { case ONEPARAM_ROUTINE_POSTQUITMESSAGE: { PTHREADINFO pti; pti = PsGetCurrentThreadWin32Thread(); MsqPostQuitMessage(pti->MessageQueue, Param); RETURN(TRUE); } case ONEPARAM_ROUTINE_BEGINDEFERWNDPOS: { PSMWP psmwp; HDWP hDwp = NULL; INT count = (INT)Param; if (count < 0) { EngSetLastError(ERROR_INVALID_PARAMETER); RETURN(0); } /* Windows allows zero count, in which case it allocates context for 8 moves */ if (count == 0) count = 8; psmwp = (PSMWP) UserCreateObject( gHandleTable, NULL, (PHANDLE)&hDwp, otSMWP, sizeof(SMWP)); if (!psmwp) RETURN(0); psmwp->acvr = ExAllocatePoolWithTag(PagedPool, count * sizeof(CVR), USERTAG_SWP); if (!psmwp->acvr) { UserDeleteObject(hDwp, otSMWP); RETURN(0); } RtlZeroMemory(psmwp->acvr, count * sizeof(CVR)); psmwp->bHandle = TRUE; psmwp->ccvr = 0; // actualCount psmwp->ccvrAlloc = count; // suggestedCount RETURN((DWORD_PTR)hDwp); } case ONEPARAM_ROUTINE_SHOWCURSOR: RETURN( (DWORD_PTR)UserShowCursor((BOOL)Param) ); case ONEPARAM_ROUTINE_GETDESKTOPMAPPING: { PTHREADINFO ti; ti = GetW32ThreadInfo(); if (ti != NULL) { /* Try convert the pointer to a user mode pointer if the desktop is mapped into the process */ RETURN((DWORD_PTR)DesktopHeapAddressToUser((PVOID)Param)); } else { RETURN(0); } } case ONEPARAM_ROUTINE_WINDOWFROMDC: RETURN( (DWORD_PTR)IntWindowFromDC((HDC)Param)); case ONEPARAM_ROUTINE_SWAPMOUSEBUTTON: { DWORD_PTR Result; Result = gspv.bMouseBtnSwap; gspv.bMouseBtnSwap = Param ? TRUE : FALSE; gpsi->aiSysMet[SM_SWAPBUTTON] = gspv.bMouseBtnSwap; RETURN(Result); } case ONEPARAM_ROUTINE_SWITCHCARETSHOWING: RETURN( (DWORD_PTR)IntSwitchCaretShowing((PVOID)Param)); case ONEPARAM_ROUTINE_SETCARETBLINKTIME: RETURN( (DWORD_PTR)IntSetCaretBlinkTime((UINT)Param)); case ONEPARAM_ROUTINE_SETMESSAGEEXTRAINFO: RETURN( (DWORD_PTR)MsqSetMessageExtraInfo((LPARAM)Param)); case ONEPARAM_ROUTINE_CREATEEMPTYCUROBJECT: { PCURICON_OBJECT CurIcon; DWORD_PTR Result ; if (!(CurIcon = IntCreateCurIconHandle())) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); RETURN(0); } Result = (DWORD_PTR)CurIcon->Self; UserDereferenceObject(CurIcon); RETURN(Result); } case ONEPARAM_ROUTINE_GETCURSORPOSITION: { BOOL ret = TRUE; _SEH2_TRY { ProbeForWrite((POINT*)Param,sizeof(POINT),1); RtlCopyMemory((POINT*)Param,&gpsi->ptCursor,sizeof(POINT)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastNtError(_SEH2_GetExceptionCode()); ret = FALSE; } _SEH2_END; RETURN (ret); } case ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING: { BOOL Enable; PPROCESSINFO Process = PsGetCurrentProcessWin32Process(); if(Process != NULL) { Enable = (BOOL)(Param != 0); if(Enable) { Process->W32PF_flags &= ~W32PF_NOWINDOWGHOSTING; } else { Process->W32PF_flags |= W32PF_NOWINDOWGHOSTING; } RETURN( TRUE); } RETURN( FALSE); } case ONEPARAM_ROUTINE_GETINPUTEVENT: RETURN( (DWORD_PTR)IntMsqSetWakeMask(Param)); case ONEPARAM_ROUTINE_GETKEYBOARDTYPE: RETURN( UserGetKeyboardType(Param)); case ONEPARAM_ROUTINE_GETKEYBOARDLAYOUT: RETURN( (DWORD_PTR)UserGetKeyboardLayout(Param)); case ONEPARAM_ROUTINE_RELEASEDC: RETURN (UserReleaseDC(NULL, (HDC) Param, FALSE)); case ONEPARAM_ROUTINE_REALIZEPALETTE: RETURN (UserRealizePalette((HDC) Param)); case ONEPARAM_ROUTINE_GETQUEUESTATUS: { RETURN (IntGetQueueStatus((DWORD)Param)); } case ONEPARAM_ROUTINE_ENUMCLIPBOARDFORMATS: /* FIXME: Should use UserEnterShared */ RETURN(IntEnumClipboardFormats(Param)); case ONEPARAM_ROUTINE_CSRSS_GUICHECK: IntUserManualGuiCheck(Param); RETURN(TRUE); case ONEPARAM_ROUTINE_GETCURSORPOS: { BOOL Ret = TRUE; PPOINTL pptl; PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); if (pti->hdesk != InputDesktopHandle) RETURN(FALSE); _SEH2_TRY { pptl = (PPOINTL)Param; *pptl = gpsi->ptCursor; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Ret = FALSE; } _SEH2_END; RETURN(Ret); } case ONEPARAM_ROUTINE_SETPROCDEFLAYOUT: { PPROCESSINFO ppi; if (Param & LAYOUT_ORIENTATIONMASK) { ppi = PsGetCurrentProcessWin32Process(); ppi->dwLayout = Param; RETURN(TRUE); } EngSetLastError(ERROR_INVALID_PARAMETER); RETURN(FALSE); } case ONEPARAM_ROUTINE_GETPROCDEFLAYOUT: { BOOL Ret = TRUE; PPROCESSINFO ppi; PDWORD pdwLayout; if ( PsGetCurrentProcess() == CsrProcess) { EngSetLastError(ERROR_INVALID_ACCESS); RETURN(FALSE); } ppi = PsGetCurrentProcessWin32Process(); _SEH2_TRY { pdwLayout = (PDWORD)Param; *pdwLayout = ppi->dwLayout; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastNtError(_SEH2_GetExceptionCode()); Ret = FALSE; } _SEH2_END; RETURN(Ret); } case ONEPARAM_ROUTINE_REPLYMESSAGE: RETURN (co_MsqReplyMessage((LRESULT) Param)); case ONEPARAM_ROUTINE_MESSAGEBEEP: RETURN ( UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_MESSAGE_BEEP, Param) ); /* TODO: Implement sound sentry */ } ERR("Calling invalid routine number 0x%x in NtUserCallOneParam(), Param=0x%x\n", Routine, Param); EngSetLastError(ERROR_INVALID_PARAMETER); RETURN( 0); CLEANUP: TRACE("Leave NtUserCallOneParam, ret=%i\n",_ret_); UserLeave(); END_CLEANUP; }
BOOLEAN FASTCALL IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, BOOLEAN bForce) { if(CurIcon->CURSORF_flags & CURSORF_CURRENT) { /* Mark the object as destroyed, and fail, as per tests */ TRACE("Cursor is current, marking as destroyed.\n"); UserDeleteObject(CurIcon->head.h, TYPE_CURSOR); return FALSE; } if(CurIcon->head.ppi != PsGetCurrentProcessWin32Process()) { /* This object doesn't belong to the current process */ WARN("Trying to delete foreign cursor!\n"); UserDereferenceObject(CurIcon); EngSetLastError(ERROR_DESTROY_OBJECT_OF_OTHER_THREAD); return FALSE; } /* Do not destroy it if it is shared. (And we're not forced to) */ if((CurIcon->CURSORF_flags & CURSORF_LRSHARED) && !bForce) { /* Tests show this is a valid call */ WARN("Trying to destroy shared cursor!\n"); UserDereferenceObject(CurIcon); return TRUE; } if(!(CurIcon->CURSORF_flags & CURSORF_ACON)) { HBITMAP bmpMask = CurIcon->hbmMask; HBITMAP bmpColor = CurIcon->hbmColor; HBITMAP bmpAlpha = CurIcon->hbmAlpha; /* Delete bitmaps */ if (bmpMask) { GreSetObjectOwner(bmpMask, GDI_OBJ_HMGR_POWNED); GreDeleteObject(bmpMask); CurIcon->hbmMask = NULL; } if (bmpColor) { GreSetObjectOwner(bmpColor, GDI_OBJ_HMGR_POWNED); GreDeleteObject(bmpColor); CurIcon->hbmColor = NULL; } if (bmpAlpha) { GreSetObjectOwner(bmpAlpha, GDI_OBJ_HMGR_POWNED); GreDeleteObject(bmpAlpha); CurIcon->hbmAlpha = NULL; } } else { PACON AniCurIcon = (PACON)CurIcon; UINT i; for(i = 0; i < AniCurIcon->cpcur; i++) IntDestroyCurIconObject(AniCurIcon->aspcur[i], TRUE); ExFreePoolWithTag(AniCurIcon->aspcur, USERTAG_CURSOR); } if (CurIcon->CURSORF_flags & CURSORF_LRSHARED) { if (!IS_INTRESOURCE(CurIcon->strName.Buffer)) ExFreePoolWithTag(CurIcon->strName.Buffer, TAG_STRING); if (CurIcon->atomModName) RtlDeleteAtomFromAtomTable(gAtomTable, CurIcon->atomModName); CurIcon->strName.Buffer = NULL; CurIcon->atomModName = 0; } /* We were given a pointer, no need to keep the reference any longer! */ UserDereferenceObject(CurIcon); return UserDeleteObject(CurIcon->head.h, TYPE_CURSOR); }
/* * @implemented */ BOOL APIENTRY NtUserSetCursorIconData( _In_ HCURSOR Handle, _In_opt_ PUNICODE_STRING pustrModule, _In_opt_ PUNICODE_STRING pustrRsrc, _In_ const CURSORDATA* pCursorData) { PCURICON_OBJECT CurIcon; NTSTATUS Status = STATUS_SUCCESS; BOOLEAN Ret = FALSE; BOOLEAN IsShared = FALSE, IsAnim = FALSE; DWORD numFrames; UINT i = 0; TRACE("Enter NtUserSetCursorIconData\n"); UserEnterExclusive(); if (!(CurIcon = UserGetCurIconObject(Handle))) { UserLeave(); EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } _SEH2_TRY { ProbeForRead(pCursorData, sizeof(*pCursorData), 1); if(pCursorData->CURSORF_flags & CURSORF_ACON) { /* This is an animated cursor */ PACON AniCurIcon = (PACON)CurIcon; DWORD numSteps; numFrames = AniCurIcon->cpcur = pCursorData->cpcur; numSteps = AniCurIcon->cicur = pCursorData->cicur; AniCurIcon->iicur = pCursorData->iicur; AniCurIcon->rt = pCursorData->rt; /* Calculate size: one cursor object for each frame, and a frame index and jiffies for each "step" */ AniCurIcon->aspcur = ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, /* Let SEH catch allocation failures */ numFrames * sizeof(CURICON_OBJECT*) + numSteps * (sizeof(DWORD) + sizeof(INT)), USERTAG_CURSOR); AniCurIcon->aicur = (DWORD*)(AniCurIcon->aspcur + numFrames); AniCurIcon->ajifRate = (INT*)(AniCurIcon->aicur + numSteps); RtlZeroMemory(AniCurIcon->aspcur, numFrames * sizeof(CURICON_OBJECT*)); ProbeForRead(pCursorData->aicur, numSteps * sizeof(DWORD), 1); RtlCopyMemory(AniCurIcon->aicur, pCursorData->aicur, numSteps * sizeof(DWORD)); ProbeForRead(pCursorData->ajifRate, numSteps * sizeof(INT), 1); RtlCopyMemory(AniCurIcon->ajifRate, pCursorData->ajifRate, numSteps * sizeof(INT)); AniCurIcon->CURSORF_flags = pCursorData->CURSORF_flags; pCursorData = pCursorData->aspcur; IsAnim = TRUE; } else { CurIcon->xHotspot = pCursorData->xHotspot; CurIcon->yHotspot = pCursorData->yHotspot; CurIcon->cx = pCursorData->cx; CurIcon->cy = pCursorData->cy; CurIcon->rt = pCursorData->rt; CurIcon->bpp = pCursorData->bpp; CurIcon->hbmMask = pCursorData->hbmMask; CurIcon->hbmColor = pCursorData->hbmColor; CurIcon->hbmAlpha = pCursorData->hbmAlpha; CurIcon->CURSORF_flags = pCursorData->CURSORF_flags; } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END if (!NT_SUCCESS(Status)) { SetLastNtError(Status); goto done; } if(IsAnim) { PACON AniCurIcon = (PACON)CurIcon; /* This is an animated cursor. Create a cursor object for each frame and set up the data */ for(i = 0; i < numFrames; i++) { HANDLE hCurFrame = IntCreateCurIconHandle(FALSE); if(!NtUserSetCursorIconData(hCurFrame, NULL, NULL, pCursorData)) goto done; AniCurIcon->aspcur[i] = UserGetCurIconObject(hCurFrame); if(!AniCurIcon->aspcur[i]) goto done; pCursorData++; } } if(CurIcon->CURSORF_flags & CURSORF_LRSHARED) { IsShared = TRUE; if(pustrRsrc && pustrModule) { UNICODE_STRING ustrModuleSafe; /* We use this convenient function, because INTRESOURCEs and ATOMs are the same */ Status = ProbeAndCaptureUnicodeStringOrAtom(&CurIcon->strName, pustrRsrc); if(!NT_SUCCESS(Status)) goto done; Status = ProbeAndCaptureUnicodeString(&ustrModuleSafe, UserMode, pustrModule); if(!NT_SUCCESS(Status)) goto done; Status = RtlAddAtomToAtomTable(gAtomTable, ustrModuleSafe.Buffer, &CurIcon->atomModName); ReleaseCapturedUnicodeString(&ustrModuleSafe, UserMode); if(!NT_SUCCESS(Status)) goto done; } } if(!CurIcon->hbmMask) { ERR("NtUserSetCursorIconData was got no hbmMask.\n"); EngSetLastError(ERROR_INVALID_PARAMETER); goto done; } GreSetObjectOwner(CurIcon->hbmMask, GDI_OBJ_HMGR_PUBLIC); if(CurIcon->hbmColor) GreSetObjectOwner(CurIcon->hbmColor, GDI_OBJ_HMGR_PUBLIC); if(CurIcon->hbmAlpha) GreSetObjectOwner(CurIcon->hbmAlpha, GDI_OBJ_HMGR_PUBLIC); if(IsShared) { /* Update process cache in case of shared cursor */ PPROCESSINFO ppi = CurIcon->head.ppi; UserReferenceObject(CurIcon); CurIcon->pcurNext = ppi->pCursorCache; ppi->pCursorCache = CurIcon; } Ret = TRUE; done: if(!Ret && IsShared) { if(!IS_INTRESOURCE(CurIcon->strName.Buffer)) ExFreePoolWithTag(CurIcon->strName.Buffer, TAG_STRING); } if(!Ret && IsAnim) { PACON AniCurIcon = (PACON)CurIcon; for(i = 0; i < numFrames; i++) { if(AniCurIcon->aspcur[i]) IntDestroyCurIconObject(AniCurIcon->aspcur[i], TRUE); } AniCurIcon->cicur = 0; AniCurIcon->cpcur = 0; ExFreePoolWithTag(AniCurIcon->aspcur, USERTAG_CURSOR); AniCurIcon->aspcur = NULL; AniCurIcon->aicur = NULL; AniCurIcon->ajifRate = NULL; } UserDereferenceObject(CurIcon); TRACE("Leave NtUserSetCursorIconData, ret=%i\n",Ret); UserLeave(); return Ret; }
/* * @implemented */ BOOL APIENTRY NtUserGetIconInfo( _In_ HANDLE hCurIcon, _Out_opt_ PICONINFO IconInfo, _Out_opt_ PUNICODE_STRING lpModule, // Optional _Out_opt_ PUNICODE_STRING lpResName, // Optional _Out_opt_ LPDWORD pbpp, // Optional _In_ BOOL bInternal) { ICONINFO ii; PCURICON_OBJECT CurIcon; NTSTATUS Status = STATUS_SUCCESS; BOOL Ret = FALSE; DWORD colorBpp = 0; TRACE("Enter NtUserGetIconInfo\n"); /* Check if something was actually asked */ if (!IconInfo && !lpModule && !lpResName) { WARN("Nothing to fill.\n"); EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } UserEnterExclusive(); if (!(CurIcon = UserGetCurIconObject(hCurIcon))) { WARN("UserGetIconObject(0x%08x) Failed.\n", hCurIcon); UserLeave(); return FALSE; } /* Give back the icon information */ if(IconInfo) { PCURICON_OBJECT FrameCurIcon = CurIcon; if(CurIcon->CURSORF_flags & CURSORF_ACON) { /* Get information from first frame. */ FrameCurIcon = ((PACON)CurIcon)->aspcur[0]; } /* Fill data */ ii.fIcon = is_icon(FrameCurIcon); ii.xHotspot = FrameCurIcon->xHotspot; ii.yHotspot = FrameCurIcon->yHotspot; /* Copy bitmaps */ ii.hbmMask = BITMAP_CopyBitmap(FrameCurIcon->hbmMask); GreSetObjectOwner(ii.hbmMask, GDI_OBJ_HMGR_POWNED); ii.hbmColor = BITMAP_CopyBitmap(FrameCurIcon->hbmColor); GreSetObjectOwner(ii.hbmColor, GDI_OBJ_HMGR_POWNED); colorBpp = FrameCurIcon->bpp; /* Copy fields */ _SEH2_TRY { ProbeForWrite(IconInfo, sizeof(ICONINFO), 1); RtlCopyMemory(IconInfo, &ii, sizeof(ICONINFO)); if (pbpp) { ProbeForWrite(pbpp, sizeof(DWORD), 1); *pbpp = colorBpp; } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END if (!NT_SUCCESS(Status)) { WARN("Status: 0x%08x.\n", Status); SetLastNtError(Status); goto leave; } } /* Give back the module name */ if(lpModule) { ULONG BufLen = 0; if (!CurIcon->atomModName) goto leave; RtlQueryAtomInAtomTable(gAtomTable, CurIcon->atomModName, NULL, NULL, NULL, &BufLen); /* Get the module name from the atom table */ _SEH2_TRY { if (BufLen > (lpModule->MaximumLength * sizeof(WCHAR))) { lpModule->Length = 0; } else { ProbeForWrite(lpModule->Buffer, lpModule->MaximumLength, 1); BufLen = lpModule->MaximumLength * sizeof(WCHAR); RtlQueryAtomInAtomTable(gAtomTable, CurIcon->atomModName, NULL, NULL, lpModule->Buffer, &BufLen); lpModule->Length = BufLen/sizeof(WCHAR); } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END if (!NT_SUCCESS(Status)) { SetLastNtError(Status); goto leave; } } if (lpResName) { if (!CurIcon->strName.Buffer) goto leave; /* Copy it */ _SEH2_TRY { ProbeForWrite(lpResName, sizeof(UNICODE_STRING), 1); if (IS_INTRESOURCE(CurIcon->strName.Buffer)) { lpResName->Buffer = CurIcon->strName.Buffer; lpResName->Length = 0; } else if (lpResName->MaximumLength < CurIcon->strName.Length) { lpResName->Length = 0; } else { ProbeForWrite(lpResName->Buffer, lpResName->MaximumLength * sizeof(WCHAR), 1); RtlCopyMemory(lpResName->Buffer, CurIcon->strName.Buffer, lpResName->Length); } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END } if (!NT_SUCCESS(Status)) { SetLastNtError(Status); goto leave; } Ret = TRUE; leave: UserDereferenceObject(CurIcon); TRACE("Leave NtUserGetIconInfo, ret=%i\n", Ret); UserLeave(); return Ret; }
HACCEL APIENTRY NtUserCreateAcceleratorTable( LPACCEL Entries, ULONG EntriesCount) { PACCELERATOR_TABLE Accel; HACCEL hAccel; ULONG Index; NTSTATUS Status = STATUS_SUCCESS; DECLARE_RETURN(HACCEL); TRACE("Enter NtUserCreateAcceleratorTable(Entries %p, EntriesCount %u)\n", Entries, EntriesCount); UserEnterExclusive(); if (!Entries || EntriesCount <= 0) { SetLastNtError(STATUS_INVALID_PARAMETER); RETURN( (HACCEL) NULL ); } Accel = UserCreateObject(gHandleTable, NULL, NULL, (PHANDLE)&hAccel, TYPE_ACCELTABLE, sizeof(ACCELERATOR_TABLE)); if (Accel == NULL) { SetLastNtError(STATUS_NO_MEMORY); RETURN( (HACCEL) NULL ); } Accel->Count = EntriesCount; Accel->Table = ExAllocatePoolWithTag(PagedPool, EntriesCount * sizeof(ACCEL), USERTAG_ACCEL); if (Accel->Table == NULL) { UserDereferenceObject(Accel); UserDeleteObject(hAccel, TYPE_ACCELTABLE); SetLastNtError(STATUS_NO_MEMORY); RETURN( (HACCEL) NULL); } _SEH2_TRY { ProbeForRead(Entries, EntriesCount * sizeof(ACCEL), 4); for (Index = 0; Index < EntriesCount; Index++) { Accel->Table[Index].fVirt = Entries[Index].fVirt & FVIRT_MASK; if(Accel->Table[Index].fVirt & FVIRTKEY) { Accel->Table[Index].key = Entries[Index].key; } else { RtlMultiByteToUnicodeN(&Accel->Table[Index].key, sizeof(WCHAR), NULL, (PCSTR)&Entries[Index].key, sizeof(CHAR)); } Accel->Table[Index].cmd = Entries[Index].cmd; } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END; if (!NT_SUCCESS(Status)) { ExFreePoolWithTag(Accel->Table, USERTAG_ACCEL); UserDereferenceObject(Accel); UserDeleteObject(hAccel, TYPE_ACCELTABLE); SetLastNtError(Status); RETURN( (HACCEL) NULL); } /* FIXME: Save HandleTable in a list somewhere so we can clean it up again */ RETURN(hAccel); CLEANUP: TRACE("Leave NtUserCreateAcceleratorTable(Entries %p, EntriesCount %u) = %p\n", Entries, EntriesCount, _ret_); UserLeave(); END_CLEANUP; }
NTSTATUS NTAPI UserDestroyThreadInfo(struct _ETHREAD *Thread) { PTHREADINFO *ppti; PSINGLE_LIST_ENTRY psle; PPROCESSINFO ppiCurrent; struct _EPROCESS *Process; PTHREADINFO ptiCurrent; Process = Thread->ThreadsProcess; /* Get the Win32 Thread */ ptiCurrent = PsGetThreadWin32Thread(Thread); ASSERT(ptiCurrent); TRACE_CH(UserThread,"Destroying pti 0x%p eThread 0x%p\n", ptiCurrent, Thread); ptiCurrent->TIF_flags |= TIF_INCLEANUP; ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; ppiCurrent = ptiCurrent->ppi; ASSERT(ppiCurrent); IsRemoveAttachThread(ptiCurrent); ptiCurrent->TIF_flags |= TIF_DONTATTACHQUEUE; ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; /* Decrement thread count and check if its 0 */ ppiCurrent->cThreads--; if(ptiCurrent->TIF_flags & TIF_GUITHREADINITIALIZED) { /* Do now some process cleanup that requires a valid win32 thread */ if(ptiCurrent->ppi->cThreads == 0) { /* Check if we have registered the user api hook */ if(ptiCurrent->ppi == ppiUahServer) { /* Unregister the api hook */ UserUnregisterUserApiHook(); } /* Notify logon application to restart shell if needed */ if(ptiCurrent->pDeskInfo) { if(ptiCurrent->pDeskInfo->ppiShellProcess == ppiCurrent) { DWORD ExitCode = PsGetProcessExitStatus(Process); TRACE_CH(UserProcess, "Shell process is exiting (%lu)\n", ExitCode); UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_SHELL_EXITED, ExitCode); ptiCurrent->pDeskInfo->ppiShellProcess = NULL; } } } DceFreeThreadDCE(ptiCurrent); HOOK_DestroyThreadHooks(Thread); EVENT_DestroyThreadEvents(Thread); DestroyTimersForThread(ptiCurrent); KeSetEvent(ptiCurrent->pEventQueueServer, IO_NO_INCREMENT, FALSE); UnregisterThreadHotKeys(ptiCurrent); /* if (IsListEmpty(&ptiCurrent->WindowListHead)) { ERR_CH(UserThread,"Thread Window List is Empty!\n"); } */ co_DestroyThreadWindows(Thread); if (ppiCurrent && ppiCurrent->ptiList == ptiCurrent && !ptiCurrent->ptiSibling && ppiCurrent->W32PF_flags & W32PF_CLASSESREGISTERED) { TRACE_CH(UserThread,"DestroyProcessClasses\n"); /* no process windows should exist at this point, or the function will assert! */ DestroyProcessClasses(ppiCurrent); ppiCurrent->W32PF_flags &= ~W32PF_CLASSESREGISTERED; } IntBlockInput(ptiCurrent, FALSE); IntCleanupThreadCallbacks(ptiCurrent); /* cleanup user object references stack */ psle = PopEntryList(&ptiCurrent->ReferencesList); while (psle) { PUSER_REFERENCE_ENTRY ref = CONTAINING_RECORD(psle, USER_REFERENCE_ENTRY, Entry); TRACE_CH(UserThread,"thread clean: remove reference obj 0x%p\n",ref->obj); UserDereferenceObject(ref->obj); psle = PopEntryList(&ptiCurrent->ReferencesList); } } /* Find the THREADINFO in the PROCESSINFO's list */ ppti = &ppiCurrent->ptiList; while (*ppti != NULL && *ppti != ptiCurrent) { ppti = &((*ppti)->ptiSibling); } /* we must have found it */ ASSERT(*ppti == ptiCurrent); /* Remove it from the list */ *ppti = ptiCurrent->ptiSibling; if (ptiCurrent->KeyboardLayout) UserDereferenceObject(ptiCurrent->KeyboardLayout); if (gptiForeground == ptiCurrent) { // IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0); // IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, NULL, OBJID_WINDOW, CHILDID_SELF, 0); gptiForeground = NULL; } // Fixes CORE-6384 & CORE-7030. /* if (ptiLastInput == ptiCurrent) { if (!ppiCurrent->ptiList) ptiLastInput = gptiForeground; else ptiLastInput = ppiCurrent->ptiList; ERR_CH(UserThread,"DTI: ptiLastInput is Cleared!!\n"); } */ TRACE_CH(UserThread,"Freeing pti 0x%p\n", ptiCurrent); /* Free the THREADINFO */ IntDereferenceThreadInfo(ptiCurrent); return STATUS_SUCCESS; }