/****************************** Module Header ******************************\ * Module Name: init.c * * Copyright (c) 1985 - 1999, Microsoft Corporation * * This module contains all the init code for win32k.sys. * * History: * 18-Sep-1990 DarrinM Created. \***************************************************************************/ #include "precomp.h" #pragma hdrstop #if DBG LIST_ENTRY gDesktopList; #endif PVOID gpCountTable; // // External references // extern PVOID *apObjects; extern PKWAIT_BLOCK gWaitBlockArray; extern PVOID UserAtomTableHandle; extern PKTIMER gptmrWD; extern UNICODE_STRING* gpastrSetupExe; extern WCHAR* glpSetupPrograms; extern PHANDLEPAGE gpHandlePages; extern PBWL pbwlCache; // // Forward references // #if DBG VOID InitGlobalThreadLockArray( DWORD dwIndex); #endif VOID CheckLUIDDosDevicesEnabled( PBOOL result); /* * Local Constants. */ #define GRAY_STRLEN 40 /* * Globals local to this file only. */ BOOL bPermanentFontsLoaded; /* * Globals shared with W32 */ CONST ULONG W32ProcessSize = sizeof(PROCESSINFO); CONST ULONG W32ProcessTag = TAG_PROCESSINFO; CONST ULONG W32ThreadSize = sizeof(THREADINFO); CONST ULONG W32ThreadTag = TAG_THREADINFO; PFAST_MUTEX gpW32FastMutex; NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath); #pragma alloc_text(INIT, DriverEntry) NTSTATUS Win32UserInitialize(VOID); #if defined(_X86_) ULONG Win32UserProbeAddress; #endif /* * holds the result of "Are LUID DosDevices maps enabled?" * TRUE - LUID DosDevices are enabled * FALSE - LUID DosDevices are not enabled */ ULONG gLUIDDeviceMapsEnabled; VOID FreeSMS(PSMS psms); VOID FreeImeHotKeys(VOID); extern PPAGED_LOOKASIDE_LIST SMSLookaside; extern PPAGED_LOOKASIDE_LIST QEntryLookaside; /* * Max time is 10 minutes. The count is 10 min * 60 sec * 4 for 250 ms. */ #define MAX_TIME_OUT (10 * 60 * 4) /***************************************************************************\ * Win32kNtUserCleanup * * History: * 5-Jan-1997 CLupu Created. \***************************************************************************/ BOOL Win32kNtUserCleanup( VOID) { int i; TRACE_HYDAPI(("Win32kNtUserCleanup: Cleanup Resources\n")); if (gpresUser != NULL) { EnterCrit(); } DbgDumpTrackedDesktops(TRUE); /* * Anything in this list must be cleaned up when threads go away. */ UserAssert(gpbwlList == NULL); UserAssert(gpWinEventHooks == NULL); UserAssert(gpScancodeMap == NULL); /* * Free IME hotkeys. */ FreeImeHotKeys(); /* * Free the wallpaper name string. */ if (gpszWall != NULL) { UserFreePool(gpszWall); gpszWall = NULL; } /* * Free the hung redraw stuff. */ if (gpvwplHungRedraw != NULL) { UserFreePool(gpvwplHungRedraw); gpvwplHungRedraw = NULL; } /* * Free the arrary of setup app names. */ if (gpastrSetupExe) { UserFreePool(gpastrSetupExe); gpastrSetupExe = NULL; } if (glpSetupPrograms) { UserFreePool(glpSetupPrograms); glpSetupPrograms = NULL; } /* * Free the cached window list. */ if (pbwlCache != NULL) { UserFreePool(pbwlCache); pbwlCache = NULL; } /* * Free outstanding timers. */ while (gptmrFirst != NULL) { FreeTimer(gptmrFirst); } if (gptmrWD) { KeCancelTimer(gptmrWD); UserFreePool(gptmrWD); gptmrWD = NULL; } if (gptmrMaster) { KeCancelTimer(gptmrMaster); UserFreePool(gptmrMaster); gptmrMaster = NULL; } /* * Cleanup monitors and windows layout snapshots */ CleanupMonitorsAndWindowsSnapShot(); /* * Cleanup PnP input device synchronization event. */ if (gpEventPnPWainting != NULL) { FreeKernelEvent(&gpEventPnPWainting); } /* * Cleanup mouse & kbd change events */ for (i = 0; i <= DEVICE_TYPE_MAX; i++) { UserAssert(gptiRit == NULL); if (aDeviceTemplate[i].pkeHidChange) { FreeKernelEvent(&aDeviceTemplate[i].pkeHidChange); } } /* * Cleanup any system thread parameters. */ CSTCleanupStack(FALSE); CSTCleanupStack(TRUE); EnterDeviceInfoListCrit(); #ifdef GENERIC_INPUT CleanupHidRequestList(); #endif while (gpDeviceInfoList) { /* * Assert that there is no outstanding read or PnP thread waiting * in RequestDeviceChanges() for this device. * Clear these flags anyway, to force the free. */ UserAssert((gpDeviceInfoList->bFlags & GDIF_READING) == 0); UserAssert((gpDeviceInfoList->usActions & GDIAF_PNPWAITING) == 0); gpDeviceInfoList->bFlags &= ~GDIF_READING; gpDeviceInfoList->usActions &= ~GDIAF_PNPWAITING; FreeDeviceInfo(gpDeviceInfoList); } #ifdef TRACK_PNP_NOTIFICATION CleanupPnpNotificationRecord(); #endif LeaveDeviceInfoListCrit(); /* * Cleanup object references */ if (gThinwireFileObject) ObDereferenceObject(gThinwireFileObject); if (gVideoFileObject) ObDereferenceObject(gVideoFileObject); if (gpRemoteBeepDevice) ObDereferenceObject(gpRemoteBeepDevice); /* * Cleanup our resources. There should be no threads in here * when we get called. */ if (gpresMouseEventQueue) { ExDeleteResourceLite(gpresMouseEventQueue); ExFreePool(gpresMouseEventQueue); gpresMouseEventQueue = NULL; } if (gpresDeviceInfoList) { ExDeleteResourceLite(gpresDeviceInfoList); ExFreePool(gpresDeviceInfoList); gpresDeviceInfoList = NULL; } if (gpkeMouseData != NULL) { FreeKernelEvent(&gpkeMouseData); } if (apObjects) { UserFreePool(apObjects); apObjects = NULL; } if (gWaitBlockArray) { UserFreePool(gWaitBlockArray); gWaitBlockArray = NULL; } if (gpEventDiconnectDesktop != NULL) { FreeKernelEvent(&gpEventDiconnectDesktop); } if (gpevtDesktopDestroyed != NULL) { FreeKernelEvent(&gpevtDesktopDestroyed); } if (gpEventScanGhosts != NULL) { FreeKernelEvent(&gpEventScanGhosts); } if (gpevtVideoportCallout != NULL) { FreeKernelEvent(&gpevtVideoportCallout); } if (UserAtomTableHandle != NULL) { RtlDestroyAtomTable(UserAtomTableHandle); UserAtomTableHandle = NULL; } /* * cleanup the SMS lookaside buffer */ { PSMS psmsNext; while (gpsmsList != NULL) { psmsNext = gpsmsList->psmsNext; UserAssert(gpsmsList->spwnd == NULL); FreeSMS(gpsmsList); gpsmsList = psmsNext; } if (SMSLookaside != NULL) { ExDeletePagedLookasideList(SMSLookaside); UserFreePool(SMSLookaside); SMSLookaside = NULL; } } /* * Let go of the attached queue for hard error handling. * Do this before we free the Qlookaside ! */ if (gHardErrorHandler.pqAttach != NULL) { UserAssert(gHardErrorHandler.pqAttach > 0); UserAssert(gHardErrorHandler.pqAttach->QF_flags & QF_INDESTROY); FreeQueue(gHardErrorHandler.pqAttach); gHardErrorHandler.pqAttach = NULL; } /* * Free the cached array of queues */ FreeCachedQueues(); /* * cleanup the QEntry lookaside buffer */ if (QEntryLookaside != NULL) { ExDeletePagedLookasideList(QEntryLookaside); UserFreePool(QEntryLookaside); QEntryLookaside = NULL; } /* * Cleanup the keyboard layouts */ CleanupKeyboardLayouts(); { PWOWTHREADINFO pwti; /* * Cleanup gpwtiFirst list. This list is supposed to be empty * at this point. In one case during stress we hit the case where * it was not empty. The assert is to catch that case in * checked builds. */ while (gpwtiFirst != NULL) { pwti = gpwtiFirst; gpwtiFirst = pwti->pwtiNext; UserFreePool(pwti); } } /* * Cleanup cached SMWP array */ if (gSMWP.acvr != NULL) { UserFreePool(gSMWP.acvr); } /* * Free gpsdInitWinSta. This is != NULL only if the session didn't * make it to UserInitialize. */ if (gpsdInitWinSta != NULL) { UserFreePool(gpsdInitWinSta); gpsdInitWinSta = NULL; } if (gpHandleFlagsMutex != NULL) { ExFreePool(gpHandleFlagsMutex); gpHandleFlagsMutex = NULL; } /* * Delete the power request structures. */ DeletePowerRequestList(); if (gpresUser != NULL) { LeaveCrit(); ExDeleteResourceLite(gpresUser); ExFreePool(gpresUser); gpresUser = NULL; } #if DBG /* * Cleanup the global thread lock structures */ for (i = 0; i < gcThreadLocksArraysAllocated; i++) { UserFreePool(gpaThreadLocksArrays[i]); gpaThreadLocksArrays[i] = NULL; } #endif // DBG #ifdef GENERIC_INPUT #if DBG /* * Checkup the HID related memory leak. */ CheckupHidLeak(); #endif // DBG #endif // GENERIC_INPUT return TRUE; } #if DBG /***************************************************************************\ * TrackAddDesktop * * Track desktops for cleanup purposes * * History: * 04-Dec-1997 clupu Created. \***************************************************************************/ VOID TrackAddDesktop( PVOID pDesktop) { PLIST_ENTRY Entry; PVOID Atom; TRACE_HYDAPI(("TrackAddDesktop %#p\n", pDesktop)); Atom = (PVOID)UserAllocPool(sizeof(PVOID) + sizeof(LIST_ENTRY), TAG_TRACKDESKTOP); if (Atom) { *(PVOID*)Atom = pDesktop; Entry = (PLIST_ENTRY)(((PCHAR)Atom) + sizeof(PVOID)); InsertTailList(&gDesktopList, Entry); } } /***************************************************************************\ * TrackRemoveDesktop * * Track desktops for cleanup purposes * * History: * 04-Dec-1997 clupu Created. \***************************************************************************/ VOID TrackRemoveDesktop( PVOID pDesktop) { PLIST_ENTRY NextEntry; PVOID Atom; TRACE_HYDAPI(("TrackRemoveDesktop %#p\n", pDesktop)); NextEntry = gDesktopList.Flink; while (NextEntry != &gDesktopList) { Atom = (PVOID)(((PCHAR)NextEntry) - sizeof(PVOID)); if (pDesktop == *(PVOID*)Atom) { RemoveEntryList(NextEntry); UserFreePool(Atom); break; } NextEntry = NextEntry->Flink; } } /***************************************************************************\ * DumpTrackedDesktops * * Dumps the tracked desktops * * History: * 04-Dec-1997 clupu Created. \***************************************************************************/ VOID DumpTrackedDesktops( BOOL bBreak) { PLIST_ENTRY NextEntry; PVOID pdesk; PVOID Atom; int nAlive = 0; TRACE_HYDAPI(("DumpTrackedDesktops\n")); NextEntry = gDesktopList.Flink; while (NextEntry != &gDesktopList) { Atom = (PVOID)(((PCHAR)NextEntry) - sizeof(PVOID)); pdesk = *(PVOID*)Atom; KdPrint(("pdesk %#p\n", pdesk)); /* * Restart at the begining of the list since our * entry got deleted */ NextEntry = NextEntry->Flink; nAlive++; } if (bBreak && nAlive > 0) { RIPMSG0(RIP_ERROR, "Desktop objects still around\n"); } } #endif // DBG VOID DestroyRegion( HRGN* prgn) { if (*prgn != NULL) { GreSetRegionOwner(*prgn, OBJECT_OWNER_CURRENT); GreDeleteObject(*prgn); *prgn = NULL; } } VOID DestroyBrush( HBRUSH* pbr) { if (*pbr != NULL) { //GreSetBrushOwner(*pbr, OBJECT_OWNER_CURRENT); GreDeleteObject(*pbr); *pbr = NULL; } } VOID DestroyBitmap( HBITMAP* pbm) { if (*pbm != NULL) { GreSetBitmapOwner(*pbm, OBJECT_OWNER_CURRENT); GreDeleteObject(*pbm); *pbm = NULL; } } VOID DestroyDC( HDC* phdc) { if (*phdc != NULL) { GreSetDCOwner(*phdc, OBJECT_OWNER_CURRENT); GreDeleteDC(*phdc); *phdc = NULL; } } VOID DestroyFont( HFONT* pfnt) { if (*pfnt != NULL) { GreDeleteObject(*pfnt); *pfnt = NULL; } } /***************************************************************************\ * CleanupGDI * * Cleanup all the GDI global objects used in USERK * * History: * 29-Jan-1998 clupu Created. \***************************************************************************/ VOID CleanupGDI( VOID) { int i; /* * Free gpDispInfo stuff */ DestroyDC(&gpDispInfo->hdcScreen); DestroyDC(&gpDispInfo->hdcBits); DestroyDC(&gpDispInfo->hdcGray); DestroyDC(&ghdcMem); DestroyDC(&ghdcMem2); DestroyDC(&gfade.hdc); /* * Free the cache DC stuff before the GRE cleanup. * Also notice that we call DelayedDestroyCacheDC which * we usualy call from DestroyProcessInfo. We do it * here because this is the last WIN32 thread. */ DestroyCacheDCEntries(PtiCurrent()); DestroyCacheDCEntries(NULL); DelayedDestroyCacheDC(); UserAssert(gpDispInfo->pdceFirst == NULL); /* * Free bitmaps */ DestroyBitmap(&gpDispInfo->hbmGray); DestroyBitmap(&ghbmBits); DestroyBitmap(&ghbmCaption); /* * Cleanup brushes */ DestroyBrush(&ghbrHungApp); DestroyBrush(&gpsi->hbrGray); DestroyBrush(&ghbrWhite); DestroyBrush(&ghbrBlack); for (i = 0; i < COLOR_MAX; i++) { DestroyBrush(&(SYSHBRUSH(i))); } /* * Cleanup regions */ DestroyRegion(&gpDispInfo->hrgnScreen); DestroyRegion(&ghrgnInvalidSum); DestroyRegion(&ghrgnVisNew); DestroyRegion(&ghrgnSWP1); DestroyRegion(&ghrgnValid); DestroyRegion(&ghrgnValidSum); DestroyRegion(&ghrgnInvalid); DestroyRegion(&ghrgnInv0); DestroyRegion(&ghrgnInv1); DestroyRegion(&ghrgnInv2); DestroyRegion(&ghrgnGDC); DestroyRegion(&ghrgnSCR); DestroyRegion(&ghrgnSPB1); DestroyRegion(&ghrgnSPB2); DestroyRegion(&ghrgnSW); DestroyRegion(&ghrgnScrl1); DestroyRegion(&ghrgnScrl2); DestroyRegion(&ghrgnScrlVis); DestroyRegion(&ghrgnScrlSrc); DestroyRegion(&ghrgnScrlDst); DestroyRegion(&ghrgnScrlValid); /* * Cleanup fonts */ DestroyFont(&ghSmCaptionFont); DestroyFont(&ghMenuFont); DestroyFont(&ghMenuFontDef); DestroyFont(&ghStatusFont); DestroyFont(&ghIconFont); DestroyFont(&ghFontSys); #ifdef LAME_BUTTON DestroyFont(&ghLameFont); #endif // LAME_BUTTON /* * wallpaper stuff. */ if (ghpalWallpaper != NULL) { GreSetPaletteOwner(ghpalWallpaper, OBJECT_OWNER_CURRENT); GreDeleteObject(ghpalWallpaper); ghpalWallpaper = NULL; } DestroyBitmap(&ghbmWallpaper); /* * Unload the video driver */ if (gpDispInfo->pmdev) { DrvDestroyMDEV(gpDispInfo->pmdev); GreFreePool(gpDispInfo->pmdev); gpDispInfo->pmdev = NULL; gpDispInfo->hDev = NULL; } /* * Free the monitor stuff */ { PMONITOR pMonitor; PMONITOR pMonitorNext; pMonitor = gpDispInfo->pMonitorFirst; while (pMonitor != NULL) { pMonitorNext = pMonitor->pMonitorNext; DestroyMonitor(pMonitor); pMonitor = pMonitorNext; } UserAssert(gpDispInfo->pMonitorFirst == NULL); if (gpMonitorCached != NULL) { DestroyMonitor(gpMonitorCached); } } } /***************************************************************************\ * DestroyHandleTableObjects * * Destroy any object still in the handle table. * \***************************************************************************/ VOID DestroyHandleFirstPass(PHE phe) { /* * First pass for the handle object destruction. * Destroy the object, when we can. Otherwise, * links to the other handle object should be cleared * so that there will not be a dependency issues * in the final, second pass. */ if (phe->phead->cLockObj == 0) { HMDestroyObject(phe->phead); } else { /* * The object couldn't be destroyed. */ if (phe->bType == TYPE_KBDLAYOUT) { PKL pkl = (PKL)phe->phead; UINT i; /* * Clear out the pkf references (they will be * destroyed cleanly in the second run anyway) */ pkl->spkf = NULL; pkl->spkfPrimary = NULL; if (pkl->pspkfExtra) { for (i = 0; i < pkl->uNumTbl; ++i) { pkl->pspkfExtra[i] = NULL; } } pkl->uNumTbl = 0; } } } VOID DestroyHandleSecondPass(PHE phe) { /* * Destroy the object. */ if (phe->phead->cLockObj > 0) { RIPMSG2(RIP_WARNING, "DestroyHandleSecondPass: phe %#p still locked (%d)!", phe, phe->phead->cLockObj); /* * We're going to die, why bothered by the lock count? * We're forcing the lockcount to 0, and call the destroy routine. */ phe->phead->cLockObj = 0; } HMDestroyUnlockedObject(phe); UserAssert(phe->bType == TYPE_FREE); } VOID DestroyHandleTableObjects(VOID) { PHE pheT; DWORD i; VOID (*HandleDestroyer)(PHE); #if DBG DWORD nLeak; #endif /* * Make sure the handle table was created ! */ if (gSharedInfo.aheList == NULL) { return; } /* * Loop through the table destroying all remaining objects. */ #if DBG RIPMSG0(RIP_WARNING, "==== Start handle leak check\n"); nLeak = 0; for (i = 0; i <= giheLast; ++i) { pheT = gSharedInfo.aheList + i; if (pheT->bType != TYPE_FREE) { ++nLeak; RIPMSG3(RIP_WARNING, " LEAK -- Handle %p @%p type=%x\n", pheT->phead->h, pheT, pheT->bType); } } RIPMSG1(RIP_WARNING, "==== Handle leak check finished: 0n%d leaks detected.\n", nLeak); #endif /* * First pass: destroy it, or cut the link to other handle based object */ HandleDestroyer = DestroyHandleFirstPass; repeat: for (i = 0; i <= giheLast; ++i) { pheT = gSharedInfo.aheList + i; if (pheT->bType == TYPE_FREE) continue; UserAssert(!(gahti[pheT->bType].bObjectCreateFlags & OCF_PROCESSOWNED) && !(gahti[pheT->bType].bObjectCreateFlags & OCF_THREADOWNED)); UserAssert(!(pheT->bFlags & HANDLEF_DESTROY)); HandleDestroyer(pheT); } if (HandleDestroyer == DestroyHandleFirstPass) { /* * Go for the second pass. */ HandleDestroyer = DestroyHandleSecondPass; goto repeat; } } /***************************************************************************\ * Win32KDriverUnload * * Exit point for win32k.sys * \***************************************************************************/ #ifdef TRACE_MAP_VIEWS extern PWin32Section gpSections; #endif VOID Win32KDriverUnload( IN PDRIVER_OBJECT DriverObject) { TRACE_HYDAPI(("Win32KDriverUnload\n")); UNREFERENCED_PARAMETER(DriverObject); HYDRA_HINT(HH_DRIVERUNLOAD); /* * Cleanup all resources in GRE */ MultiUserNtGreCleanup(); HYDRA_HINT(HH_GRECLEANUP); /* * Cleanup CSRSS */ if (gpepCSRSS) { ObDereferenceObject(gpepCSRSS); gpepCSRSS = NULL; } /* * BUG 305965. There might be cases when we end up with DCEs still * in the list. Go ahead and clean it up here. */ if (gpDispInfo != NULL && gpDispInfo->pdceFirst != NULL) { PDCE pdce, pdceNext; RIPMSG0(RIP_ERROR, "Win32KDriverUnload: the DCE list is not empty"); pdce = gpDispInfo->pdceFirst; while (pdce != NULL) { pdceNext = pdce->pdceNext; UserFreePool(pdce); pdce = pdceNext; } gpDispInfo->pdceFirst = NULL; } /* * Cleanup all resources in ntuser */ Win32kNtUserCleanup(); /* * Cleanup the handle table for any object that is neither process * owned nor thread owned */ DestroyHandleTableObjects(); HYDRA_HINT(HH_USERKCLEANUP); #if DBG || FRE_LOCK_RECORD HMCleanUpHandleTable(); #endif /* * Free the handle page array */ if (gpHandlePages != NULL) { UserFreePool(gpHandlePages); gpHandlePages = NULL; } if (CsrApiPort != NULL) { ObDereferenceObject(CsrApiPort); CsrApiPort = NULL; } /* * Destroy the shared memory. */ if (ghSectionShared != NULL) { NTSTATUS Status; gpsi = NULL; if (gpvSharedBase != NULL) { Win32HeapDestroy(gpvSharedAlloc); Status = Win32UnmapViewInSessionSpace(gpvSharedBase); UserAssert(NT_SUCCESS(Status)); } Win32DestroySection(ghSectionShared); } CleanupWin32HeapStubs(); #ifdef TRACE_MAP_VIEWS if (gpSections != NULL) { FRE_RIPMSG3(RIP_ERROR, "Section being leaked; do \"d%cs 0x%p l%x\" to find stacktrace of the offender and triage against that", (sizeof(ULONG_PTR) == 8 ? 'q' : 'd'), (ULONG_PTR)gpSections + FIELD_OFFSET(Win32Section, trace), ARRAY_SIZE(gpSections->trace)); } #endif // TRACE_MAP_VIEWS /* * Cleanup all the user pool allocations by hand */ CleanupMediaChange(); CleanupPoolAllocations(); CleanUpPoolLimitations(); CleanUpSections(); /* * Cleanup W32 structures. */ if (gpW32FastMutex != NULL) { ExFreePool(gpW32FastMutex); gpW32FastMutex = NULL; } /* * Remove and free the service vector. */ if (!gbRemoteSession) { KeRemoveSystemServiceTable(W32_SERVICE_NUMBER); if (gpCountTable != NULL) { ExFreePool(gpCountTable); gpCountTable = NULL; } } } /***************************************************************************\ * DriverEntry * * Entry point needed to initialize win32k.sys. * \***************************************************************************/ NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { NTSTATUS Status; OBJECT_ATTRIBUTES obja; UNICODE_STRING strName; HANDLE hEventFirstSession; UNREFERENCED_PARAMETER(RegistryPath); HYDRA_HINT(HH_DRIVERENTRY); gpvWin32kImageBase = DriverObject->DriverStart; #if DBG /* * Initialize the desktop tracking list. */ InitializeListHead(&gDesktopList); #endif // DBG #ifdef GENERIC_INPUT /* * Initialize the global HID request list. */ InitializeHidRequestList(); #endif /* * Find out if this is a remote session. */ RtlInitUnicodeString(&strName, L"\\UniqueSessionIdEvent"); InitializeObjectAttributes(&obja, &strName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwCreateEvent(&hEventFirstSession, EVENT_ALL_ACCESS, &obja, SynchronizationEvent, FALSE); if (!NT_SUCCESS(Status)) { if (Status == STATUS_OBJECT_NAME_COLLISION) { gbRemoteSession = TRUE; } else { goto Failure; } } else { gbRemoteSession = FALSE; } /* * Set the unload address */ DriverObject->DriverUnload = Win32KDriverUnload; /* * Initialize data used for the timers. We want to do this really early, * before any Win32 Timer will be created. We need to be very careful to * not do anything that will need Win32 initialized yet. */ gcmsLastTimer = NtGetTickCount(); /* * Initialize the Win32 structures. We need to do this before we create * any threads. */ gpW32FastMutex = ExAllocatePoolWithTag(NonPagedPool, sizeof(FAST_MUTEX), TAG_SYSTEM); if (gpW32FastMutex == NULL) { Status = STATUS_NO_MEMORY; goto Failure; } ExInitializeFastMutex(gpW32FastMutex); if (!gbRemoteSession) { #if DBG /* * Allocate and zero the system service count table. Do not use * UserAllocPool for this allocation. */ gpCountTable = ExAllocatePoolWithTag(NonPagedPool, W32pServiceLimit * sizeof(ULONG), 'llac'); if (gpCountTable == NULL) { Status = STATUS_NO_MEMORY; goto Failure; } RtlZeroMemory(gpCountTable, W32pServiceLimit * sizeof(ULONG)); #endif /* * We only establish the system entry table once for the * whole system, even though WIN32K.SYS is instanced on a winstation * basis. This is because the VM changes assure that all loads of * WIN32K.SYS are at the exact same address, even if a fixup had * to occur. */ UserVerify(KeAddSystemServiceTable(W32pServiceTable, gpCountTable, W32pServiceLimit, W32pArgumentTable, W32_SERVICE_NUMBER)); } /* * Initialize the critical section before establishing the callouts so * we can assume that it's always valid. */ if (!InitCreateUserCrit()) { Status = STATUS_NO_MEMORY; goto Failure; } if (!gbRemoteSession) { WIN32_CALLOUTS_FPNS Win32Callouts; Win32Callouts.ProcessCallout = W32pProcessCallout; Win32Callouts.ThreadCallout = W32pThreadCallout; Win32Callouts.GlobalAtomTableCallout = UserGlobalAtomTableCallout; Win32Callouts.PowerEventCallout = UserPowerEventCallout; Win32Callouts.PowerStateCallout = UserPowerStateCallout; Win32Callouts.JobCallout = UserJobCallout; Win32Callouts.BatchFlushRoutine = (PVOID)NtGdiFlushUserBatch; Win32Callouts.DesktopOpenProcedure = (PKWIN32_OBJECT_CALLOUT)DesktopOpenProcedure; Win32Callouts.DesktopOkToCloseProcedure = (PKWIN32_OBJECT_CALLOUT)OkayToCloseDesktop; Win32Callouts.DesktopCloseProcedure = (PKWIN32_OBJECT_CALLOUT)UnmapDesktop; Win32Callouts.DesktopDeleteProcedure = (PKWIN32_OBJECT_CALLOUT)FreeDesktop; Win32Callouts.WindowStationOkToCloseProcedure = (PKWIN32_OBJECT_CALLOUT)OkayToCloseWindowStation; Win32Callouts.WindowStationCloseProcedure = (PKWIN32_OBJECT_CALLOUT)DestroyWindowStation; Win32Callouts.WindowStationDeleteProcedure = (PKWIN32_OBJECT_CALLOUT)FreeWindowStation; Win32Callouts.WindowStationParseProcedure = (PKWIN32_OBJECT_CALLOUT)ParseWindowStation; Win32Callouts.WindowStationOpenProcedure = (PKWIN32_OBJECT_CALLOUT)WindowStationOpenProcedure; PsEstablishWin32Callouts(&Win32Callouts); } Status = InitSectionTrace(); if (!NT_SUCCESS(Status)) { goto Failure; } if (!InitWin32HeapStubs()) { Status = STATUS_NO_MEMORY; goto Failure; } /* * Initialize pool limitation array. */ Status = InitPoolLimitations(); if (!NT_SUCCESS(Status)) { goto Failure; } /* * Create the event that is signaled when a desktop does away */ gpevtDesktopDestroyed = CreateKernelEvent(SynchronizationEvent, FALSE); if (gpevtDesktopDestroyed == NULL) { RIPMSG0(RIP_WARNING, "Couldn't create gpevtDesktopDestroyed"); Status = STATUS_NO_MEMORY; goto Failure; } /* * Create the event that is signaled when no disconnect/reconnect is pending */ gpevtVideoportCallout = CreateKernelEvent(NotificationEvent, FALSE); if (gpevtVideoportCallout == NULL) { RIPMSG0(RIP_WARNING, "Couldn't create gpevtVideoportCallout"); Status = STATUS_NO_MEMORY; goto Failure; } #if defined(_X86_) /* * Keep our own copy of this to avoid double indirections on probing */ Win32UserProbeAddress = *MmUserProbeAddress; #endif if ((hModuleWin = MmPageEntireDriver(DriverEntry)) == NULL) { RIPMSG0(RIP_WARNING, "MmPageEntireDriver failed"); Status = STATUS_NO_MEMORY; goto Failure; } #if DBG /* * Initialize the gpaThreadLocksArray mechanism */ gFreeTLList = gpaThreadLocksArrays[gcThreadLocksArraysAllocated] = UserAllocPoolZInit(sizeof(TL)*MAX_THREAD_LOCKS, TAG_GLOBALTHREADLOCK); if (gFreeTLList == NULL) { Status = STATUS_NO_MEMORY; goto Failure; } InitGlobalThreadLockArray(0); gcThreadLocksArraysAllocated = 1; #endif if (!InitializeGre()) { RIPMSG0(RIP_WARNING, "InitializeGre failed"); Status = STATUS_NO_MEMORY; goto Failure; } Status = Win32UserInitialize(); if (!NT_SUCCESS(Status)) { RIPMSG1(RIP_WARNING, "Win32UserInitialize failed with Status %x", Status); goto Failure; } /* * Remember Session Creation Time. This is used to decide if power * messages need to be sent. */ gSessionCreationTime = KeQueryInterruptTime(); // // Initialize rundown protection for WindowStation objects. // ExInitializeRundownProtection(&gWinstaRunRef); /* * Check if LUID DosDevices are enabled */ CheckLUIDDosDevicesEnabled(&gLUIDDeviceMapsEnabled); return STATUS_SUCCESS; Failure: RIPMSG1(RIP_WARNING, "Initialization of WIN32K.SYS failed with Status = 0x%x", Status); Win32KDriverUnload(NULL); return Status; } /***************************************************************************\ * xxxAddFontResourceW * * * History: \***************************************************************************/ int xxxAddFontResourceW( LPWSTR lpFile, FLONG flags, DESIGNVECTOR *pdv) { UNICODE_STRING strFile; RtlInitUnicodeString(&strFile, lpFile); return xxxClientAddFontResourceW(&strFile, flags, pdv); } /***************************************************************************\ * LW_DriversInit * * * History: \***************************************************************************/ VOID LW_DriversInit(VOID) { /* * Initialize the keyboard typematic rate. */ SetKeyboardRate((UINT)gnKeyboardSpeed); /* * Adjust VK modification table if not default (type 4) kbd. */ if (gKeyboardInfo.KeyboardIdentifier.Type == 3) gapulCvt_VK = gapulCvt_VK_84; /* * Adjust VK modification table for IBM 5576 002/003 keyboard. */ if (JAPANESE_KEYBOARD(gKeyboardInfo.KeyboardIdentifier) && (gKeyboardInfo.KeyboardIdentifier.Subtype == 3)) gapulCvt_VK = gapulCvt_VK_IBM02; /* * Initialize NLS keyboard globals. */ NlsKbdInitializePerSystem(); } /***************************************************************************\ * LoadCPUserPreferences * * 06/07/96 GerardoB Created \***************************************************************************/ BOOL LoadCPUserPreferences( PUNICODE_STRING pProfileUserName, DWORD dwPolicyOnly) { DWORD pdwValue[SPI_BOOLMASKDWORDSIZE], dw; PPROFILEVALUEINFO ppvi = gpviCPUserPreferences; UserAssert(1 + SPI_DWORDRANGECOUNT == ARRAY_SIZE(gpviCPUserPreferences)); /* * The first value in gpviCPUserPreferences corresponds to the bit mask */ dw = FastGetProfileValue(pProfileUserName, ppvi->uSection, ppvi->pwszKeyName, NULL, (LPBYTE)pdwValue, sizeof(*pdwValue), dwPolicyOnly); /* * Copy only the amount of data read and no more than what we expect. */ if (dw != 0) { if (dw > sizeof(gpdwCPUserPreferencesMask)) { dw = sizeof(gpdwCPUserPreferencesMask); } RtlCopyMemory(gpdwCPUserPreferencesMask, pdwValue, dw); } ppvi++; /* * DWORD values */ for (dw = 1; dw < 1 + SPI_DWORDRANGECOUNT; dw++, ppvi++) { if (FastGetProfileValue(pProfileUserName, ppvi->uSection, ppvi->pwszKeyName, NULL, (LPBYTE)pdwValue, sizeof(DWORD), dwPolicyOnly)) { ppvi->dwValue = *pdwValue; } } /* * Propagate gpsi flags */ PropagetUPBOOLTogpsi(COMBOBOXANIMATION); PropagetUPBOOLTogpsi(LISTBOXSMOOTHSCROLLING); PropagetUPBOOLTogpsi(KEYBOARDCUES); SET_OR_CLEAR_SRVIF(SRVIF_KEYBOARDPREF, TEST_BOOL_ACCF(ACCF_KEYBOARDPREF)); gpsi->uCaretWidth = UP(CARETWIDTH); SYSMET(CXFOCUSBORDER) = UP(FOCUSBORDERWIDTH); SYSMET(CYFOCUSBORDER) = UP(FOCUSBORDERHEIGHT); PropagetUPBOOLTogpsi(UIEFFECTS); EnforceColorDependentSettings(); return TRUE; } /***************************************************************************\ * LW_LoadProfileInitData * * Only stuff that gets initialized at boot should go here. Per user settings * should be initialized in xxxUpdatePerUserSystemParameters. \***************************************************************************/ VOID LW_LoadProfileInitData( PUNICODE_STRING pProfileUserName) { FastGetProfileIntFromID(pProfileUserName, PMAP_WINDOWSM, STR_DDESENDTIMEOUT, 0, &guDdeSendTimeout, 0); } /***************************************************************************\ * LW_LoadResources * * * History: \***************************************************************************/ VOID LW_LoadResources( PUNICODE_STRING pProfileUserName) { WCHAR rgch[4]; /* * See if the Mouse buttons need swapping. */ FastGetProfileStringFromIDW(pProfileUserName, PMAP_MOUSE, STR_SWAPBUTTONS, szN, rgch, ARRAY_SIZE(rgch), 0); SYSMET(SWAPBUTTON) = (*rgch == '1' || *rgch == *szY || *rgch == *szy); /* * See if we should beep. */ FastGetProfileStringFromIDW(pProfileUserName, PMAP_BEEP, STR_BEEP, szY, rgch, ARRAY_SIZE(rgch), 0); SET_OR_CLEAR_PUDF(PUDF_BEEP, (rgch[0] == *szY) || (rgch[0] == *szy)); /* * See if we should have extended sounds. */ FastGetProfileStringFromIDW(pProfileUserName, PMAP_BEEP, STR_EXTENDEDSOUNDS, szN, rgch, ARRAY_SIZE(rgch), 0); SET_OR_CLEAR_PUDF(PUDF_EXTENDEDSOUNDS, (rgch[0] == *szY || rgch[0] == *szy)); } /***************************************************************************\ * xxxLoadSomeStrings * * This function loads a bunch of strings from the user32 resource string * table * This is done to keep all the localizable strings in user side to be MUI * Manageable. * * History: * 4-Mar-2000 MHamid Created. \***************************************************************************/ VOID xxxLoadSomeStrings( VOID) { int i, str, id; /* * MessageBox strings. */ for (i = 0, str = STR_OK, id = IDOK; iMBStrings[i].uStr = str; gpsi->MBStrings[i].uID = id; xxxClientLoadStringW(str, gpsi->MBStrings[i].szName, ARRAY_SIZE(gpsi->MBStrings[i].szName)); } /* * Load ToolTip strings. */ xxxClientLoadStringW(STR_TT_MIN, gszMIN, ARRAY_SIZE(gszMIN)); xxxClientLoadStringW(STR_TT_MAX, gszMAX, ARRAY_SIZE(gszMAX)); xxxClientLoadStringW(STR_TT_RESUP, gszRESUP, ARRAY_SIZE(gszRESUP)); xxxClientLoadStringW(STR_TT_RESDOWN, gszRESDOWN, ARRAY_SIZE(gszRESDOWN)); xxxClientLoadStringW(STR_TT_SCLOSE, gszSCLOSE, ARRAY_SIZE(gszSCLOSE)); xxxClientLoadStringW(STR_TT_HELP, gszHELP, ARRAY_SIZE(gszHELP)); } /***************************************************************************\ * xxxInitWindowStation * * History: * 6-Sep-1996 CLupu Created. * 21-Jan-98 SamerA Renamed to xxxInitWindowStation since it may leave the * critical section. \***************************************************************************/ BOOL xxxInitWindowStation( VOID) { TL tlName; PUNICODE_STRING pProfileUserName = CreateProfileUserName(&tlName); BOOL fRet; /* * Load all profile data first */ LW_LoadProfileInitData(pProfileUserName); /* * Initialize User in a specific order. */ LW_DriversInit(); xxxLoadSomeStrings(); /* * This is the initialization from Chicago */ if (!(fRet = xxxSetWindowNCMetrics(pProfileUserName, NULL, TRUE, -1))) { RIPMSG0(RIP_WARNING, "xxxInitWindowStation failed in xxxSetWindowNCMetrics"); goto Exit; } SetMinMetrics(pProfileUserName, NULL); if (!(fRet = SetIconMetrics(pProfileUserName, NULL))) { RIPMSG0(RIP_WARNING, "xxxInitWindowStation failed in SetIconMetrics"); goto Exit; } if (!(fRet = FinalUserInit())) { RIPMSG0(RIP_WARNING, "xxxInitWindowStation failed in FinalUserInit"); goto Exit; } /* * Initialize the key cache index. */ gpsi->dwKeyCache = 1; Exit: FreeProfileUserName(pProfileUserName, &tlName); return fRet; } /***************************************************************************\ * CreateTerminalInput * * * History: * 6-Sep-1996 CLupu Created. \***************************************************************************/ BOOL CreateTerminalInput( PTERMINAL pTerm) { UserAssert(pTerm != NULL); /* * call to the client side to clean up the [Fonts] section * of the registry. This will only take significant chunk of time * if the [Fonts] key changed during since the last boot and if * there are lots of fonts loaded */ ClientFontSweep(); /* * Load the standard fonts before we create any DCs. At this time we can * only add the fonts that do not reside on the net. They may be needed * by winlogon. Our winlogon needs only ms sans serif, but private * winlogon's may need some other fonts as well. The fonts on the net * will be added later, right after all the net connections have been * restored. */ xxxLW_LoadFonts(FALSE); /* * Initialize the input system. */ if (!xxxInitInput(pTerm)) { return FALSE; } return TRUE; } /***************************************************************************\ * CI_GetClrVal * * Returns the RGB value of a color string from WIN.INI. * * History: \***************************************************************************/ DWORD CI_GetClrVal( LPWSTR p, DWORD clrDefval) { LPBYTE pl; BYTE val; int i; DWORD clrval; if (*p == UNICODE_NULL) { return clrDefval; } /* * Initialize the pointer to the LONG return value. Set to MSB. */ pl = (LPBYTE)&clrval; /* * Get three goups of numbers seprated by non-numeric characters. */ for (i = 0; i < 3; i++) { /* * Skip over any non-numeric characters within the string. */ while ((*p != UNICODE_NULL) && !(*p >= TEXT('0') && *p <= TEXT('9'))) { p++; } /* * Are we (prematurely) at the end of the string? */ if (*p == UNICODE_NULL) { RIPMSG0(RIP_WARNING, "CI_GetClrVal: Color string is corrupted"); return clrDefval; } /* * Get the next series of digits. */ val = 0; while (*p >= TEXT('0') && *p <= TEXT('9')) val = (BYTE)((int)val*10 + (int)*p++ - '0'); /* * HACK! Store the group in the LONG return value. */ *pl++ = val; } /* * Force the MSB to zero for GDI. */ *pl = 0; return clrval; } /***************************************************************************\ * xxxODI_ColorInit * * * History: \***************************************************************************/ VOID xxxODI_ColorInit(PUNICODE_STRING pProfileUserName) { int i; COLORREF colorVals[STR_COLOREND - STR_COLORSTART + 1]; INT colorIndex[STR_COLOREND - STR_COLORSTART + 1]; WCHAR rgchValue[25]; #if COLOR_MAX - (STR_COLOREND - STR_COLORSTART + 1) #error "COLOR_MAX value conflicts with STR_COLOREND - STR_COLORSTART" #endif /* * Now set up default color values. * These are not in display drivers anymore since we just want default. * The real values are stored in the profile. */ RtlCopyMemory(gpsi->argbSystem, gargbInitial, sizeof(COLORREF) * COLOR_MAX); RtlCopyMemory(gpsi->argbSystemUnmatched, gpsi->argbSystem, sizeof(COLORREF) * COLOR_MAX); for (i = 0; i < COLOR_MAX; i++) { LUID luidCaller; /* * Try to find a WIN.INI entry for this object. */ *rgchValue = 0; /* * Special case the background color. Try using Winlogon's value * if present. If the value doesn't exist then use USER's value. */ if ((COLOR_BACKGROUND == i) && NT_SUCCESS(GetProcessLuid(NULL, &luidCaller)) && RtlEqualLuid(&luidCaller, &luidSystem)) { FastGetProfileStringFromIDW(pProfileUserName, PMAP_WINLOGON, STR_COLORSTART + COLOR_BACKGROUND, szNull, rgchValue, ARRAY_SIZE(rgchValue), 0); } if (*rgchValue == 0) { FastGetProfileStringFromIDW(pProfileUserName, PMAP_COLORS, STR_COLORSTART + i, szNull, rgchValue, ARRAY_SIZE(rgchValue), 0); } /* * Convert the string into an RGB value and store. Use the * default RGB value if the profile value is missing. */ colorVals[i] = CI_GetClrVal(rgchValue, gpsi->argbSystem[i]); colorIndex[i] = i; } xxxSetSysColors(pProfileUserName, i, colorIndex, colorVals, SSCF_FORCESOLIDCOLOR | SSCF_SETMAGICCOLORS); } /***********************************************************************\ * _LoadIconsAndCursors * * Used in parallel with the client side - LoadIconsAndCursors. This * assumes that only the default configurable cursors and icons have * been loaded and searches the global icon cache for them to fixup * the default resource ids to standard ids. Also initializes the * rgsys arrays allowing SYSCUR and SYSICO macros to work. * * 14-Oct-1995 SanfordS created. \***********************************************************************/ VOID _LoadCursorsAndIcons( VOID) { PCURSOR pcur; int i; pcur = gpcurFirst; /* * Only CSR can call this (and only once). */ if (!ISCSRSS()) { return; } HYDRA_HINT(HH_LOADCURSORS); while (pcur) { UserAssert(!IS_PTR(pcur->strName.Buffer)); switch (pcur->rt) { case RT_ICON: UserAssert((LONG_PTR)pcur->strName.Buffer >= OIC_FIRST_DEFAULT); UserAssert((LONG_PTR)pcur->strName.Buffer < OIC_FIRST_DEFAULT + COIC_CONFIGURABLE); i = PTR_TO_ID(pcur->strName.Buffer) - OIC_FIRST_DEFAULT; pcur->strName.Buffer = (LPWSTR)gasysico[i].Id; if (pcur->CURSORF_flags & CURSORF_LRSHARED) { UserAssert(gasysico[i].spcur == NULL); Lock(&gasysico[i].spcur, pcur); } else { UserAssert(gpsi->hIconSmWindows == NULL); UserAssert((int)pcur->cx == SYSMET(CXSMICON)); /* * The special small winlogo icon is not shared. */ gpsi->hIconSmWindows = PtoH(pcur); } break; case RT_CURSOR: UserAssert((LONG_PTR)pcur->strName.Buffer >= OCR_FIRST_DEFAULT); UserAssert((LONG_PTR)pcur->strName.Buffer < OCR_FIRST_DEFAULT + COCR_CONFIGURABLE); i = PTR_TO_ID(pcur->strName.Buffer) - OCR_FIRST_DEFAULT; pcur->strName.Buffer = (LPWSTR)gasyscur[i].Id; Lock(&gasyscur[i].spcur, pcur); break; default: // Should be nothing in the cache but these! RIPMSG1(RIP_ERROR, "Bogus object in cursor list: 0x%p", pcur); } pcur = pcur->pcurNext; } /* * copy special icon handles to global spots for later use. */ gpsi->hIcoWindows = PtoH(SYSICO(WINLOGO)); } /***********************************************************************\ * UnloadCursorsAndIcons * * Used for cleanup of win32k. * * Dec-10-1997 clupu created. \***********************************************************************/ VOID UnloadCursorsAndIcons( VOID) { PCURSOR pcur; int ind; TRACE_HYDAPI(("UnloadCursorsAndIcons\n")); /* * Unlock the icons. */ for (ind = 0; ind < COIC_CONFIGURABLE; ind++) { pcur = gasysico[ind].spcur; if (pcur == NULL) { continue; } pcur->head.ppi = PpiCurrent(); Unlock(&gasysico[ind].spcur); } /* * Unlock the cursors. */ for (ind = 0; ind < COCR_CONFIGURABLE; ind++) { pcur = gasyscur[ind].spcur; if (pcur == NULL) { continue; } pcur->head.ppi = PpiCurrent(); Unlock(&gasyscur[ind].spcur); } } /***********************************************************************\ * xxxUpdateSystemCursorsFromRegistry * * Reloads all customizable cursors from the registry. * * 09-Oct-1995 SanfordS created. \***********************************************************************/ VOID xxxUpdateSystemCursorsFromRegistry( PUNICODE_STRING pProfileUserName) { int i; UNICODE_STRING strName; TCHAR szFilename[MAX_PATH]; PCURSOR pCursor; UINT LR_flags; for (i = 0; i < COCR_CONFIGURABLE; i++) { FastGetProfileStringFromIDW(pProfileUserName, PMAP_CURSORS, gasyscur[i].StrId, TEXT(""), szFilename, ARRAY_SIZE(szFilename), 0); if (*szFilename) { RtlInitUnicodeString(&strName, szFilename); LR_flags = LR_LOADFROMFILE | LR_ENVSUBST | LR_DEFAULTSIZE; } else { RtlInitUnicodeStringOrId(&strName, MAKEINTRESOURCE(i + OCR_FIRST_DEFAULT)); LR_flags = LR_ENVSUBST | LR_DEFAULTSIZE; } pCursor = xxxClientLoadImage(&strName, 0, IMAGE_CURSOR, 0, 0, LR_flags, FALSE); if (pCursor) { zzzSetSystemImage(pCursor, gasyscur[i].spcur); } else { RIPMSG1(RIP_WARNING, "Unable to update cursor. id=%x.", i + OCR_FIRST_DEFAULT); } } } /***********************************************************************\ * xxxUpdateSystemIconsFromRegistry * * Reloads all customizable icons from the registry. * * 09-Oct-1995 SanfordS created. \***********************************************************************/ VOID xxxUpdateSystemIconsFromRegistry( PUNICODE_STRING pProfileUserName) { int i; UNICODE_STRING strName; TCHAR szFilename[MAX_PATH]; PCURSOR pCursor; UINT LR_flags; for (i = 0; i < COIC_CONFIGURABLE; i++) { FastGetProfileStringFromIDW(pProfileUserName, PMAP_ICONS, gasysico[i].StrId, TEXT(""), szFilename, ARRAY_SIZE(szFilename), 0); if (*szFilename) { RtlInitUnicodeString(&strName, szFilename); LR_flags = LR_LOADFROMFILE | LR_ENVSUBST; } else { RtlInitUnicodeStringOrId(&strName, MAKEINTRESOURCE(i + OIC_FIRST_DEFAULT)); LR_flags = LR_ENVSUBST; } pCursor = xxxClientLoadImage(&strName, 0, IMAGE_ICON, 0, 0, LR_flags, FALSE); RIPMSG3(RIP_VERBOSE, (!IS_PTR(strName.Buffer)) ? "%#.8lx = Loaded id %ld" : "%#.8lx = Loaded file %ws for id %ld", PtoH(pCursor), strName.Buffer, i + OIC_FIRST_DEFAULT); if (pCursor) { zzzSetSystemImage(pCursor, gasysico[i].spcur); } else { RIPMSG1(RIP_WARNING, "Unable to update icon. id=%ld", i + OIC_FIRST_DEFAULT); } /* * update the small winlogo icon which is referenced by gpsi. * Seems like we should load the small version for all configurable * icons anyway. What is needed is for CopyImage to support * copying of images loaded from files with LR_COPYFROMRESOURCE * allowing a reaload of the bits. (SAS) */ if (i == OIC_WINLOGO_DEFAULT - OIC_FIRST_DEFAULT) { PCURSOR pCurSys = HtoP(gpsi->hIconSmWindows); if (pCurSys != NULL) { pCursor = xxxClientLoadImage(&strName, 0, IMAGE_ICON, SYSMET(CXSMICON), SYSMET(CYSMICON), LR_flags, FALSE); if (pCursor) { zzzSetSystemImage(pCursor, pCurSys); } else { RIPMSG0(RIP_WARNING, "Unable to update small winlogo icon."); } } } } } /***************************************************************************\ * LW_BrushInit * * * History: \***************************************************************************/ BOOL LW_BrushInit( VOID) { HBITMAP hbmGray; CONST static WORD patGray[8] = {0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa}; /* * Create a gray brush to be used with GrayString. */ hbmGray = GreCreateBitmap(8, 8, 1, 1, (LPBYTE)patGray); if (hbmGray == NULL) { return FALSE; } gpsi->hbrGray = GreCreatePatternBrush(hbmGray); ghbrWhite = GreGetStockObject(WHITE_BRUSH); ghbrBlack = GreGetStockObject(BLACK_BRUSH); UserAssert(ghbrWhite != NULL && ghbrBlack != NULL); if (gpsi->hbrGray == NULL) { return FALSE; } GreDeleteObject(hbmGray); GreSetBrushOwnerPublic(gpsi->hbrGray); ghbrHungApp = GreCreateSolidBrush(0); if (ghbrHungApp == NULL) { return FALSE; } GreSetBrushOwnerPublic(ghbrHungApp); return TRUE; } /***************************************************************************\ * LW_RegisterWindows * * * History: \***************************************************************************/ BOOL LW_RegisterWindows( VOID) { int i; WNDCLASSVEREX wndcls; PTHREADINFO ptiCurrent = PtiCurrent(); BOOL fSuccess = TRUE; BOOL fSystem = (ptiCurrent->TIF_flags & TIF_SYSTEMTHREAD) != 0; CONST static struct { BOOLEAN fSystem; BOOLEAN fGlobalClass; WORD fnid; UINT style; WNDPROC lpfnWndProc; int cbWndExtra; BOOL fNormalCursor : 1; HBRUSH hbrBackground; LPCTSTR lpszClassName; } rc[] = { { TRUE, TRUE, FNID_DESKTOP, CS_DBLCLKS, (WNDPROC)xxxDesktopWndProc, sizeof(DESKWND) - sizeof(WND), TRUE, (HBRUSH)(COLOR_BACKGROUND + 1), DESKTOPCLASS}, { TRUE, FALSE, FNID_SWITCH, CS_VREDRAW | CS_HREDRAW | CS_SAVEBITS, (WNDPROC)xxxSwitchWndProc, sizeof(SWITCHWND) - sizeof(WND), TRUE, NULL, SWITCHWNDCLASS}, { TRUE, FALSE, FNID_MENU, CS_DBLCLKS | CS_SAVEBITS | CS_DROPSHADOW, (WNDPROC)xxxMenuWindowProc, sizeof(PPOPUPMENU), FALSE, (HBRUSH)(COLOR_MENU + 1), MENUCLASS}, { FALSE, FALSE, FNID_SCROLLBAR, CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_PARENTDC, (WNDPROC)xxxSBWndProc, sizeof(SBWND) - sizeof(WND), TRUE, NULL, L"ScrollBar"}, { TRUE, FALSE, FNID_TOOLTIP, CS_DBLCLKS | CS_SAVEBITS, (WNDPROC)xxxTooltipWndProc, sizeof(TOOLTIPWND) - sizeof(WND), TRUE, NULL, TOOLTIPCLASS}, { TRUE, TRUE, FNID_ICONTITLE, 0, (WNDPROC)xxxDefWindowProc, 0, TRUE, NULL, ICONTITLECLASS}, { FALSE, FALSE, 0, 0, (WNDPROC)xxxEventWndProc, sizeof(PSVR_INSTANCE_INFO), FALSE, NULL, L"DDEMLEvent"}, #ifdef HUNGAPP_GHOSTING { TRUE, TRUE, FNID_GHOST, 0, (WNDPROC)xxxGhostWndProc, 0, TRUE, NULL, L"Ghost"}, #endif // HUNGAPP_GHOSTING { TRUE, TRUE, 0, 0, (WNDPROC)xxxDefWindowProc, 0, TRUE, NULL, L"SysShadow"}, { TRUE, TRUE, FNID_MESSAGEWND, 0, (WNDPROC)xxxDefWindowProc, 4, TRUE, NULL, szMESSAGE} }; /* * All other classes are registered via the table. */ wndcls.cbClsExtra = 0; wndcls.hInstance = hModuleWin; wndcls.hIcon = NULL; wndcls.hIconSm = NULL; wndcls.lpszMenuName = NULL; for (i = 0; i < ARRAY_SIZE(rc); i++) { if (fSystem && !rc[i].fSystem) { continue; } wndcls.style = rc[i].style; wndcls.lpfnWndProc = rc[i].lpfnWndProc; wndcls.cbWndExtra = rc[i].cbWndExtra; wndcls.hCursor = rc[i].fNormalCursor ? PtoH(SYSCUR(ARROW)) : NULL; wndcls.hbrBackground= rc[i].hbrBackground; wndcls.lpszClassName= rc[i].lpszClassName; wndcls.lpszClassNameVer= rc[i].lpszClassName; if (InternalRegisterClassEx(&wndcls, rc[i].fnid, CSF_SERVERSIDEPROC | CSF_WIN40COMPAT) == NULL) { RIPMSG0(RIP_WARNING, "LW_RegisterWindows: InternalRegisterClassEx failed"); fSuccess = FALSE; break; } if (fSystem && rc[i].fGlobalClass) { if (InternalRegisterClassEx(&wndcls, rc[i].fnid, CSF_SERVERSIDEPROC | CSF_SYSTEMCLASS | CSF_WIN40COMPAT) == NULL) { RIPMSG0(RIP_WARNING, "LW_RegisterWindows: InternalRegisterClassEx failed"); fSuccess = FALSE; break; } } } if (fSuccess) { ptiCurrent->ppi->W32PF_Flags |= W32PF_CLASSESREGISTERED; #ifndef LAZY_CLASS_INIT if (!fSystem && ptiCurrent->pClientInfo) { try { ptiCurrent->pClientInfo->CI_flags |= CI_REGISTERCLASSES; } except (W32ExceptionHandler(TRUE, RIP_WARNING)) { fSuccess = FALSE; } } #endif } return fSuccess; } /**********************************************************\ * VOID vCheckMMInstance * * History: * Feb-06-98 Xudong Wu [TessieW] * Wrote it. \**********************************************************/ VOID vCheckMMInstance( LPWSTR pchSrch, DESIGNVECTOR *pdv) { LPWSTR pKeyName; WCHAR szName[MAX_PATH], *pszName = szName; WCHAR szCannonicalName[MAX_PATH]; ULONG NumAxes; pdv->dvNumAxes = 0; pKeyName = pchSrch; while (*pKeyName && (*pKeyName++ != TEXT('('))) { /* do nothing */; } if (*pKeyName){ if (!_wcsicmp(pKeyName, L"OpenType)")) { pKeyName = pchSrch; while(*pKeyName != TEXT('(')) { *pszName++ = *pKeyName++; } *pszName = 0; GreGetCannonicalName(szName, szCannonicalName, &NumAxes, pdv); } } } BOOL bEnumerateRegistryFonts( BOOL bPermanent) { LPWSTR pchKeys, pchSrch, lpchT; int cchReal, cFont; WCHAR szFontFile[MAX_PATH]; FLONG flAFRW; TL tlPool; DESIGNVECTOR dv; WCHAR szPreloadFontFile[MAX_PATH]; static int LastFontLoaded = -1; /* * if we are not just checking whether this is a registry font */ flAFRW = (bPermanent ? AFRW_ADD_LOCAL_FONT : AFRW_ADD_REMOTE_FONT); cchReal = (int)FastGetProfileKeysW(NULL, PMAP_FONTS, TEXT("vgasys.fnt"), &pchKeys ); #if DBG if (cchReal == 0) { RIPMSG0(RIP_WARNING, "bEnumerateRegistryFonts: cchReal is 0"); } #endif if (!pchKeys) { return FALSE; } ThreadLockPool(PtiCurrent(), pchKeys, &tlPool); /* * If we got here first, we load the fonts until this preload font. * Preload fonts will be used by Winlogon UI, then we need to make sure * the font is available when Winlogon UI comes up. */ if (LastFontLoaded == -1) { FastGetProfileStringW(NULL, PMAP_WINLOGON, TEXT("PreloadFontFile"), TEXT("Micross.ttf"), szPreloadFontFile, MAX_PATH, 0); RIPMSG1(RIP_VERBOSE, "Winlogon preload font = %ws\n",szPreloadFontFile); } /* * Now we have all the key names in pchKeys. */ if (cchReal != 0) { cFont = 0; pchSrch = pchKeys; do { // check to see whether this is MM(OpenType) instance vCheckMMInstance(pchSrch, &dv); if (FastGetProfileStringW(NULL, PMAP_FONTS, pchSrch, TEXT("vgasys.fon"), szFontFile, (MAX_PATH - 5), 0)) { /* * If no extension, append ".FON" */ for (lpchT = szFontFile; *lpchT != TEXT('.'); lpchT++) { if (*lpchT == 0) { wcscat(szFontFile, TEXT(".FON")); break; } } if ((cFont > LastFontLoaded) && bPermanent) { /* * skip if we've already loaded this local font. */ xxxAddFontResourceW(szFontFile, flAFRW, dv.dvNumAxes ? &dv : NULL); } if (!bPermanent) { xxxAddFontResourceW(szFontFile, flAFRW, dv.dvNumAxes ? &dv : NULL); } if ((LastFontLoaded == -1) && /* * Compare with the font file name from Registry. */ (!_wcsnicmp(szFontFile, szPreloadFontFile, wcslen(szPreloadFontFile))) && (bPermanent)) { /* * On the first time through only load up until * ms sans serif for winlogon to use. Later we * will spawn off a thread which loads the remaining * fonts in the background. */ LastFontLoaded = cFont; ThreadUnlockAndFreePool(PtiCurrent(), &tlPool); return TRUE; } } /* * Skip to the next key. */ while (*pchSrch++) { /* do nothing */; } cFont += 1; } while (pchSrch < ((LPWSTR)pchKeys + cchReal)); } /* * signal that all the permanent fonts have been loaded */ bPermanentFontsLoaded = TRUE; ThreadUnlockAndFreePool(PtiCurrent(), &tlPool); if (!bPermanent) { SET_PUDF(PUDF_FONTSARELOADED); } return TRUE; } extern VOID CloseFNTCache(VOID); /***************************************************************************\ * xxxLW_LoadFonts * * * History: \***************************************************************************/ VOID xxxLW_LoadFonts( BOOL bRemote) { BOOL bTimeOut = FALSE; if (bRemote) { LARGE_INTEGER li; ULONG ulWaitCount = 0; /* * Before we can proceed we must make sure that all the permanent * fonts have been loaded. */ while (!bPermanentFontsLoaded) { if (!gbRemoteSession || ulWaitCount < MAX_TIME_OUT) { LeaveCrit(); li.QuadPart = (LONGLONG)-10000 * CMSSLEEP; KeDelayExecutionThread(KernelMode, FALSE, &li); EnterCrit(); } else { bTimeOut = TRUE; break; } ulWaitCount++; } if (!bTimeOut) { if (!bEnumerateRegistryFonts(FALSE)) { return; // Nothing we can do. } // Add remote type 1 fonts. ClientLoadRemoteT1Fonts(); } } else { xxxAddFontResourceW(L"marlett.ttf", AFRW_ADD_LOCAL_FONT,NULL); if (!bEnumerateRegistryFonts(TRUE)) { return; // Nothing we can do. } // // Add local type 1 fonts. // Only want to be called once, the second time after ms sans serif // was installed // if (bPermanentFontsLoaded) { ClientLoadLocalT1Fonts(); // All the fonts loaded, we can close the FNTCache. CloseFNTCache(); } } } /***************************************************************************\ * FinalUserInit * * History: \***************************************************************************/ BOOL FinalUserInit( VOID) { HBITMAP hbm; PPCLS ppcls; gpDispInfo->hdcGray = GreCreateCompatibleDC(gpDispInfo->hdcScreen); if (gpDispInfo->hdcGray == NULL) { return FALSE; } GreSelectFont(gpDispInfo->hdcGray, ghFontSys); GreSetDCOwner(gpDispInfo->hdcGray, OBJECT_OWNER_PUBLIC); gpDispInfo->cxGray = gpsi->cxSysFontChar * GRAY_STRLEN; gpDispInfo->cyGray = gpsi->cySysFontChar + 2; gpDispInfo->hbmGray = GreCreateBitmap(gpDispInfo->cxGray, gpDispInfo->cyGray, 1, 1, 0L); if (gpDispInfo->hbmGray == NULL) { return FALSE; } GreSetBitmapOwner(gpDispInfo->hbmGray, OBJECT_OWNER_PUBLIC); hbm = GreSelectBitmap(gpDispInfo->hdcGray, gpDispInfo->hbmGray); GreSetTextColor(gpDispInfo->hdcGray, 0x00000000L); GreSelectBrush(gpDispInfo->hdcGray, gpsi->hbrGray); GreSetBkMode(gpDispInfo->hdcGray, OPAQUE); GreSetBkColor(gpDispInfo->hdcGray, 0x00FFFFFFL); /* * Setup menu animation dc for global menu state */ if (MNSetupAnimationDC(&gMenuState)) { GreSetDCOwner(gMenuState.hdcAni, OBJECT_OWNER_PUBLIC); } else { RIPMSG0(RIP_WARNING, "FinalUserInit: MNSetupAnimationDC failed"); } /* * Creation of the queue registers some bogus classes. Get rid * of them and register the real ones. */ ppcls = &PpiCurrent()->pclsPublicList; while ((*ppcls != NULL) && !((*ppcls)->style & CS_GLOBALCLASS)) { DestroyClass(ppcls); } return TRUE; } /***************************************************************************\ * InitializeClientPfnArrays * * This routine gets called by the client to tell the kernel where * its important functions can be located. * * 18-Apr-1995 JimA Created. \***************************************************************************/ NTSTATUS InitializeClientPfnArrays( CONST PFNCLIENT *ppfnClientA, CONST PFNCLIENT *ppfnClientW, CONST PFNCLIENTWORKER *ppfnClientWorker, HANDLE hModUser) { static BOOL fHaveClientPfns = FALSE; /* * Remember client side addresses in this global structure. These are * always constant, so this is ok. Note that if either of the pointers * are invalid, the exception will be handled in the thunk and * fHaveClientPfns will not be set. */ if (!fHaveClientPfns && ppfnClientA != NULL) { if (!ISCSRSS()) { RIPMSG0(RIP_WARNING, "InitializeClientPfnArrays failed !csrss"); return STATUS_ACCESS_DENIED; } gpsi->apfnClientA = *ppfnClientA; gpsi->apfnClientW = *ppfnClientW; gpsi->apfnClientWorker = *ppfnClientWorker; gpfnwp[ICLS_BUTTON] = gpsi->apfnClientW.pfnButtonWndProc; gpfnwp[ICLS_EDIT] = gpsi->apfnClientW.pfnDefWindowProc; gpfnwp[ICLS_STATIC] = gpsi->apfnClientW.pfnStaticWndProc; gpfnwp[ICLS_LISTBOX] = gpsi->apfnClientW.pfnListBoxWndProc; gpfnwp[ICLS_SCROLLBAR] = (PROC)xxxSBWndProc; gpfnwp[ICLS_COMBOBOX] = gpsi->apfnClientW.pfnComboBoxWndProc; gpfnwp[ICLS_DESKTOP] = (PROC)xxxDesktopWndProc; gpfnwp[ICLS_DIALOG] = gpsi->apfnClientW.pfnDialogWndProc; gpfnwp[ICLS_MENU] = (PROC)xxxMenuWindowProc; gpfnwp[ICLS_SWITCH] = (PROC)xxxSwitchWndProc; gpfnwp[ICLS_ICONTITLE] = gpsi->apfnClientW.pfnTitleWndProc; gpfnwp[ICLS_MDICLIENT] = gpsi->apfnClientW.pfnMDIClientWndProc; gpfnwp[ICLS_COMBOLISTBOX] = gpsi->apfnClientW.pfnComboListBoxProc; gpfnwp[ICLS_TOOLTIP] = (PROC)xxxTooltipWndProc; /* * Change this assert when new classes are added. */ UserAssert(ICLS_MAX == ICLS_GHOST + 1); hModClient = hModUser; fHaveClientPfns = TRUE; } /* * Assert that user32.dll on the client side has loaded at the correct * address. */ UserAssert(ppfnClientA == NULL || gpsi->apfnClientA.pfnButtonWndProc == ppfnClientA->pfnButtonWndProc); return STATUS_SUCCESS; } /***************************************************************************\ * GetKbdLangSwitch * * read the kbd language hotkey setting - if any - from the registry and set * LangToggle[] appropriately. * * values are: * 1 : VK_MENU (this is the default) * 2 : VK_CONTROL * 3 : none * History: \***************************************************************************/ BOOL GetKbdLangSwitch( PUNICODE_STRING pProfileUserName) { DWORD dwToggle; LCID lcid; FastGetProfileIntW(pProfileUserName, PMAP_UKBDLAYOUTTOGGLE, TEXT("Hotkey"), 1, &dwToggle, 0); gbGraveKeyToggle = FALSE; switch (dwToggle) { case 4: /* * Grave accent keyboard switch for thai locales */ ZwQueryDefaultLocale(FALSE, &lcid); gbGraveKeyToggle = (PRIMARYLANGID(lcid) == LANG_THAI) ? TRUE : FALSE; /* * fall through (intentional) and disable the ctrl/alt toggle mechanism */ case 3: gLangToggle[0].bVkey = 0; gLangToggle[0].bScan = 0; break; case 2: gLangToggle[0].bVkey = VK_CONTROL; break; default: gLangToggle[0].bVkey = VK_MENU; break; } return TRUE; } /***************************************************************************\ * HideMouseTrails * * Hide the mouse trails one by one. * * History: * 04-10-00 MHamid Created. \***************************************************************************/ VOID HideMouseTrails( PWND pwnd, UINT message, UINT_PTR nID, LPARAM lParam) { if (gMouseTrailsToHide > 0) { if (InterlockedDecrement(&gMouseTrailsToHide) < gMouseTrails) { GreMovePointer(gpDispInfo->hDev, gpsi->ptCursor.x, gpsi->ptCursor.y, MP_PROCEDURAL); } } UNREFERENCED_PARAMETER(pwnd); UNREFERENCED_PARAMETER(message); UNREFERENCED_PARAMETER(nID); UNREFERENCED_PARAMETER(lParam); } /***************************************************************************\ * * SetMouseTrails * * n = 0,1 turn off mouse trails. * n > 1 turn on mouse trails (Trials = n-1). * \***************************************************************************/ VOID SetMouseTrails( UINT n) { CheckCritIn(); SetPointer(FALSE); gMouseTrails = n ? n-1 : n; SetPointer(TRUE); if (!IsRemoteConnection() && (!!gtmridMouseTrails ^ !!gMouseTrails)) { if (gMouseTrails) { /* * Create the gtmridMouseTrails timer in the desktop thread, * becuase if we creat it here it will get killed when the current * thread (App thread calling SPI_SETMOUSETRAILS) get destroied. */ _PostMessage(gTermIO.ptiDesktop->pDeskInfo->spwnd, WM_CREATETRAILTIMER, 0, 0); } else { FindTimer(NULL, gtmridMouseTrails, TMRF_RIT, TRUE); gtmridMouseTrails = 0; } } } #ifdef IMM_PER_LOGON extern BOOL IsIMMEnabledSystem(VOID); extern BOOL IsCTFIMEEnabledSystem(VOID); BOOL UpdatePerUserImmEnabling( VOID) { /* * Update the IME enabling flag */ SET_OR_CLEAR_SRVIF(SRVIF_IME, IsIMMEnabledSystem()); RIPMSGF1(RIP_VERBOSE, "New Imm flag = %d", !!IS_IME_ENABLED()); /* * Update the CTFIME enabling flag */ SET_OR_CLEAR_SRVIF(SRVIF_CTFIME_ENABLED, IsCTFIMEEnabledSystem()); RIPMSG1(RIP_VERBOSE, "_UpdatePerUserImmEnabling: new CTFIME flag = %d", !!IS_CICERO_ENABLED()); return TRUE; } #endif /***************************************************************************\ * xxxUpdatePerUserSystemParameters * * Called by winlogon to set Window system parameters to the current user's * profile. * * 18-Sep-1992 IanJa Created. * 18-Nov-1993 SanfordS Moved more winlogon init code to here for speed. * 31-Mar-2001 Msadek Changed parm from BOOL to flags for TS Slow Link * Perf DCR. * 02-Feb-2002 MMcCr Added SPI_SETBLOCKSENDINPUTRESETS feature \***************************************************************************/ BOOL xxxUpdatePerUserSystemParameters( DWORD dwFlags) { /* * NB - Any local variables that are used in appiPolicy must be initialized. * Otherwise, during a policy change, it is possible for them to be used w/o * being initialized and all heck breaks loose. Windows Bug #314150. */ int i; HANDLE hKey; DWORD dwFontSmoothing = GreGetFontEnumeration(); DWORD dwFontSmoothingContrast; DWORD dwFontSmoothingOrientation; BOOL fDragFullWindows = TEST_PUDF(PUDF_DRAGFULLWINDOWS); TL tlName; PUNICODE_STRING pProfileUserName = NULL; DWORD dwPolicyFlags = 0; DWORD dwData; BOOL bPolicyChange; BOOL bUserLoggedOn; BOOL bRemoteSettings; SPINFO spiPolicy[] = { { PMAP_DESKTOP, SPI_SETBLOCKSENDINPUTRESETS, STR_BLOCKSENDINPUTRESETS, 0 }, { PMAP_DESKTOP, SPI_SETSCREENSAVETIMEOUT, STR_SCREENSAVETIMEOUT, 0 }, { PMAP_DESKTOP, SPI_SETSCREENSAVEACTIVE, STR_SCREENSAVEACTIVE, 0 }, { PMAP_DESKTOP, SPI_SETDRAGHEIGHT, STR_DRAGHEIGHT, 4 }, { PMAP_DESKTOP, SPI_SETDRAGWIDTH, STR_DRAGWIDTH, 4 }, { PMAP_DESKTOP, SPI_SETWHEELSCROLLLINES, STR_WHEELSCROLLLINES, 3 }, }; SPINFO spiNotPolicy[] = { { PMAP_KEYBOARD, SPI_SETKEYBOARDDELAY, STR_KEYDELAY, 0 }, { PMAP_KEYBOARD, SPI_SETKEYBOARDSPEED, STR_KEYSPEED, 15 }, { PMAP_MOUSE, SPI_SETDOUBLECLICKTIME, STR_DBLCLKSPEED, 500 }, { PMAP_MOUSE, SPI_SETDOUBLECLKWIDTH, STR_DOUBLECLICKWIDTH, 4 }, { PMAP_MOUSE, SPI_SETDOUBLECLKHEIGHT, STR_DOUBLECLICKHEIGHT, 4 }, { PMAP_MOUSE, SPI_SETSNAPTODEFBUTTON, STR_SNAPTO, 0 }, { PMAP_WINDOWSU, SPI_SETMENUDROPALIGNMENT, STR_MENUDROPALIGNMENT, 0 }, { PMAP_INPUTMETHOD, SPI_SETSHOWIMEUI, STR_SHOWIMESTATUS, 1 }, }; PROFINTINFO apiiPolicy[] = { { PMAP_DESKTOP, (LPWSTR)STR_MENUSHOWDELAY, 400, &gdtMNDropDown }, { PMAP_DESKTOP, (LPWSTR)STR_DRAGFULLWINDOWS, 2, &fDragFullWindows }, { PMAP_DESKTOP, (LPWSTR)STR_FASTALTTABROWS, 3, &gnFastAltTabRows }, { PMAP_DESKTOP, (LPWSTR)STR_FASTALTTABCOLUMNS, 7, &gnFastAltTabColumns }, { PMAP_DESKTOP, (LPWSTR)STR_MAXLEFTOVERLAPCHARS, 3, &(gpsi->wMaxLeftOverlapChars) }, { PMAP_DESKTOP, (LPWSTR)STR_MAXRIGHTOVERLAPCHARS, 3, &(gpsi->wMaxRightOverlapChars) }, { PMAP_DESKTOP, (LPWSTR)STR_FONTSMOOTHING, 0, &dwFontSmoothing }, { 0, NULL, 0, NULL } }; PROFINTINFO apiiNoPolicy[] = { { PMAP_MOUSE, (LPWSTR)STR_MOUSETHRESH1, 6, &gMouseThresh1 }, { PMAP_MOUSE, (LPWSTR)STR_MOUSETHRESH2, 10, &gMouseThresh2 }, { PMAP_MOUSE, (LPWSTR)STR_MOUSESPEED, 1, &gMouseSpeed }, { PMAP_INPUTMETHOD, (LPWSTR)STR_HEXNUMPAD, 0, &gfEnableHexNumpad }, { 0, NULL, 0, NULL } }; UserAssert(IsWinEventNotifyDeferredOK()); bPolicyChange = dwFlags & UPUSP_POLICYCHANGE; bUserLoggedOn = dwFlags & UPUSP_USERLOGGEDON; bRemoteSettings = dwFlags & UPUSP_REMOTESETTINGS; /* * Make sure the caller is the logon process. */ if (PsGetCurrentProcessId() != gpidLogon) { if (!bPolicyChange) { RIPMSG0(RIP_WARNING, "Access denied in xxxUpdatePerUserSystemParameters"); } return FALSE; } pProfileUserName = CreateProfileUserName(&tlName); /* * If the desktop policy hasn't changed and we came here because we * thought it had, we're done. */ if (bPolicyChange && !bRemoteSettings) { if (!CheckDesktopPolicyChange(pProfileUserName)) { FreeProfileUserName(pProfileUserName, &tlName); return FALSE; } dwPolicyFlags = POLICY_ONLY; UserAssert(!bUserLoggedOn); } /* * If new user is logging in, we need to recheck for * user policy changes. */ if (bUserLoggedOn) { gdwPolicyFlags |= POLICY_USER; } /* * We don't want remote settings to be read all the time so spcify it here * if the caller wants to.Update it here since we do not save it in * gdwPolicyFlags [msadek]. */ if (bRemoteSettings) { dwPolicyFlags |= POLICY_REMOTE; } /* * Get the timeout for low level hooks from the registry. */ dwData = 300; FastGetProfileValue(pProfileUserName, PMAP_DESKTOP, (LPWSTR)STR_LLHOOKSTIMEOUT, (LPBYTE)&dwData, (LPBYTE)&gnllHooksTimeout, sizeof(int), dwPolicyFlags); /* * Control Panel User Preferences. */ LoadCPUserPreferences(pProfileUserName, dwPolicyFlags); #ifdef LAME_BUTTON /* * Lame button text. */ FastGetProfileValue(pProfileUserName, PMAP_DESKTOP, (LPWSTR)STR_LAMEBUTTONENABLED, NULL, (LPBYTE)&gdwLameFlags, sizeof(DWORD), dwPolicyFlags); #endif // LAME_BUTTON if (!bPolicyChange) { /* * Set syscolors from registry. */ xxxODI_ColorInit(pProfileUserName); LW_LoadResources(pProfileUserName); /* * This is the initialization from Chicago. */ xxxSetWindowNCMetrics(pProfileUserName, NULL, TRUE, -1); // Colors must be set first SetMinMetrics(pProfileUserName, NULL); SetIconMetrics(pProfileUserName, NULL); /* * Read the keyboard layout switching hot key. */ GetKbdLangSwitch(pProfileUserName); /* * Set the default thread locale for the system based on the value * in the current user's registry profile. */ ZwSetDefaultLocale( TRUE, 0 ); /* * Set the default UI language based on the value in the current * user's registry profile. */ ZwSetDefaultUILanguage(0); /* * And then Get it. */ ZwQueryDefaultUILanguage(&(gpsi->UILangID)); /* * Now load strings using the currnet UILangID. */ xxxLoadSomeStrings(); /* * Destroy the desktop system menus, so that they're recreated with * the correct UI language if the current user's UI language is * different from the previous one. This is done by finding the * interactive window station and destroying all its desktops's * system menus. */ if (grpWinStaList != NULL) { PDESKTOP pdesk; PMENU pmenu; UserAssert(!(grpWinStaList->dwWSF_Flags & WSF_NOIO)); for (pdesk = grpWinStaList->rpdeskList; pdesk != NULL; pdesk = pdesk->rpdeskNext) { if (pdesk->spmenuSys != NULL) { pmenu = pdesk->spmenuSys; if (UnlockDesktopSysMenu(&pdesk->spmenuSys)) { _DestroyMenu(pmenu); } } if (pdesk->spmenuDialogSys != NULL) { pmenu = pdesk->spmenuDialogSys; if (UnlockDesktopSysMenu(&pdesk->spmenuDialogSys)) { _DestroyMenu(pmenu); } } } } xxxUpdateSystemCursorsFromRegistry(pProfileUserName); /* * now go set a bunch of random values from the win.ini file. */ for (i = 0; i < ARRAY_SIZE(spiNotPolicy); i++) { if (FastGetProfileIntFromID(pProfileUserName, spiNotPolicy[i].idSection, spiNotPolicy[i].idRes, spiNotPolicy[i].def, &dwData, 0)) { xxxSystemParametersInfo(spiNotPolicy[i].id, dwData, 0L, 0); } } FastGetProfileIntsW(pProfileUserName, apiiNoPolicy, 0); } /* * Reset desktop pattern now. Note no parameters. It just goes off * and reads the registry and sets the desktop pattern. */ xxxSystemParametersInfo(SPI_SETDESKPATTERN, (UINT)-1, 0L, 0); // 265 version /* * Initialize IME show status */ if (bUserLoggedOn) { gfIMEShowStatus = IMESHOWSTATUS_NOTINITIALIZED; } /* * Now go set a bunch of random values from the registry. */ for (i = 0; i < ARRAY_SIZE(spiPolicy); i++) { if (FastGetProfileIntFromID(pProfileUserName, spiPolicy[i].idSection, spiPolicy[i].idRes, spiPolicy[i].def, &dwData, dwPolicyFlags)) { xxxSystemParametersInfo(spiPolicy[i].id, dwData, 0L, 0); } } /* * Read profile integers and do any fixups. */ FastGetProfileIntsW(pProfileUserName, apiiPolicy, dwPolicyFlags); if (gnFastAltTabColumns < 2) { gnFastAltTabColumns = 7; } if (gnFastAltTabRows < 1) { gnFastAltTabRows = 3; } /* * If this is the first time the user logs on, set the DragFullWindows * to the default. If we have an accelerated device, enable full drag. */ if (fDragFullWindows == 2) { WCHAR szTemp[40], szDragFullWindows[40]; SET_OR_CLEAR_PUDF( PUDF_DRAGFULLWINDOWS, GreGetDeviceCaps(gpDispInfo->hdcScreen, BLTALIGNMENT) == 0); if (bUserLoggedOn) { swprintf(szTemp, L"%d", TEST_BOOL_PUDF(PUDF_DRAGFULLWINDOWS)); ServerLoadString(hModuleWin, STR_DRAGFULLWINDOWS, szDragFullWindows, ARRAY_SIZE(szDragFullWindows)); FastWriteProfileStringW(pProfileUserName, PMAP_DESKTOP, szDragFullWindows, szTemp); } } else { SET_OR_CLEAR_PUDF(PUDF_DRAGFULLWINDOWS, fDragFullWindows); } /* * !!!LATER!!! (adams) See if the following profile retrievals can't * be done in the "spi" array above (e.g. SPI_SETSNAPTO). */ /* * For remote connections or remote assistance, we may not want a * blinking caret for perf reasons. So, we try to read the value from * the registry, if there is one set. If nothing is set, we will * default to whatever is on desktop. */ dwData = gpsi->dtCaretBlink; if (FastGetProfileIntFromID(pProfileUserName, PMAP_DESKTOP, STR_BLINK, 500, &dwData, bRemoteSettings? dwPolicyFlags : bPolicyChange)) { _SetCaretBlinkTime(dwData); } if (!bPolicyChange) { /* * Set mouse settings */ FastGetProfileIntFromID(pProfileUserName, PMAP_MOUSE, STR_MOUSESENSITIVITY, MOUSE_SENSITIVITY_DEFAULT, &gMouseSensitivity, 0); if ((gMouseSensitivity < MOUSE_SENSITIVITY_MIN) || (gMouseSensitivity > MOUSE_SENSITIVITY_MAX)) { gMouseSensitivity = MOUSE_SENSITIVITY_DEFAULT; } gMouseSensitivityFactor = CalculateMouseSensitivity(gMouseSensitivity); #ifdef SUBPIXEL_MOUSE ReadDefaultAccelerationCurves(pProfileUserName); ResetMouseAccelerationCurves(); #endif /* * Set mouse trails. */ FastGetProfileIntFromID(pProfileUserName, PMAP_MOUSE, STR_MOUSETRAILS, 0, &dwData, 0); SetMouseTrails(dwData); /* * Font Information */ FastGetProfileIntW(pProfileUserName, PMAP_TRUETYPE, TEXT("TTOnly"), FALSE, &dwData, 0); GreSetFontEnumeration(dwData); /* * Window animation */ FastGetProfileIntFromID(pProfileUserName, PMAP_METRICS, STR_MINANIMATE, TRUE, &dwData, 0); SET_OR_CLEAR_PUDF(PUDF_ANIMATE, dwData); /* * Mouse tracking variables */ FastGetProfileIntFromID(pProfileUserName, PMAP_MOUSE, STR_MOUSEHOVERWIDTH, SYSMET(CXDOUBLECLK), &gcxMouseHover, 0); FastGetProfileIntFromID(pProfileUserName, PMAP_MOUSE, STR_MOUSEHOVERHEIGHT, SYSMET(CYDOUBLECLK), &gcyMouseHover, 0); FastGetProfileIntFromID(pProfileUserName, PMAP_MOUSE, STR_MOUSEHOVERTIME, gdtMNDropDown, &gdtMouseHover, 0); } /* * Initial Keyboard state: ScrollLock, NumLock and CapsLock state; * global (per-user) kbd layout attributes (such as ShiftLock/CapsLock) */ if (!bPolicyChange) { UpdatePerUserKeyboardIndicators(pProfileUserName); UpdatePerUserKeyboardMappings(pProfileUserName); FastGetProfileDwordW(pProfileUserName, PMAP_UKBDLAYOUT, L"Attributes", 0, &gdwKeyboardAttributes, 0); gdwKeyboardAttributes = KLL_GLOBAL_ATTR_FROM_KLF(gdwKeyboardAttributes); xxxUpdatePerUserAccessPackSettings(pProfileUserName); } /* * If we successfully opened this, we assume we have a network. */ if (hKey = OpenCacheKeyEx(NULL, PMAP_NETWORK, KEY_READ, NULL)) { RIPMSG0(RIP_WARNING | RIP_NONAME, ""); SYSMET(NETWORK) = RNC_NETWORKS; ZwClose(hKey); } SYSMET(NETWORK) |= RNC_LOGON; /* * Font smoothing */ /* clear the flags from what could have been set for the previous user */ GreSetFontEnumeration(FE_SET_AA); GreSetFontEnumeration(FE_SET_CT); if (dwFontSmoothing & FE_AA_ON) GreSetFontEnumeration( dwFontSmoothing | FE_SET_AA ); if (UPDWORDValue(SPI_GETFONTSMOOTHINGTYPE) & FE_FONTSMOOTHINGCLEARTYPE) GreSetFontEnumeration( dwFontSmoothing | FE_SET_CT | FE_CT_ON); dwFontSmoothingContrast = UPDWORDValue(SPI_GETFONTSMOOTHINGCONTRAST); if (dwFontSmoothingContrast == 0) dwFontSmoothingContrast = DEFAULT_CT_CONTRAST; GreSetFontContrast(dwFontSmoothingContrast); dwFontSmoothingOrientation = UPDWORDValue(SPI_GETFONTSMOOTHINGORIENTATION); GreSetLCDOrientation(dwFontSmoothingOrientation); /* * Desktop Build Number Painting */ if (USER_SHARED_DATA->SystemExpirationDate.QuadPart || gfUnsignedDrivers) { gdwCanPaintDesktop = 1; } else { FastGetProfileDwordW(pProfileUserName, PMAP_DESKTOP, L"PaintDesktopVersion", 0, &gdwCanPaintDesktop, dwPolicyFlags); } if (!bPolicyChange) { FastGetProfileStringW(pProfileUserName, PMAP_WINLOGON, TEXT("DefaultUserName"), TEXT("Unknown"), gszUserName, ARRAY_SIZE(gszUserName), 0); FastGetProfileStringW(pProfileUserName, PMAP_WINLOGON, TEXT("DefaultDomainName"), TEXT("Unknown"), gszDomainName, ARRAY_SIZE(gszDomainName), 0); FastGetProfileStringW(pProfileUserName, PMAP_COMPUTERNAME, TEXT("ComputerName"), TEXT("Unknown"), gszComputerName, ARRAY_SIZE(gszComputerName), 0); } FreeProfileUserName(pProfileUserName, &tlName); /* * Do this if we are here for real policy change * i.e. not a remote settings policy change. */ if (dwFlags == UPUSP_POLICYCHANGE) { xxxUserResetDisplayDevice(); } return TRUE; } /* * Called by InitOemXlateTables via SFI_INITANSIOEM */ VOID InitAnsiOem(PCHAR pOemToAnsi, PCHAR pAnsiToOem) { UserAssert(gpsi != NULL); UserAssert(pOemToAnsi != NULL); UserAssert(pAnsiToOem != NULL); try { ProbeForRead(pOemToAnsi, NCHARS, sizeof(BYTE)); ProbeForRead(pAnsiToOem, NCHARS, sizeof(BYTE)); RtlCopyMemory(gpsi->acOemToAnsi, pOemToAnsi, NCHARS); RtlCopyMemory(gpsi->acAnsiToOem, pAnsiToOem, NCHARS); } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { } } /***************************************************************************\ * RegisterLPK * * Called by InitializeLpkHooks on the client side after an LPK is * loaded for the current process. * * 05-Nov-1996 GregoryW Created. \***************************************************************************/ VOID RegisterLPK( DWORD dwLpkEntryPoints) { PpiCurrent()->dwLpkEntryPoints = dwLpkEntryPoints; } /***************************************************************************\ * Enforce color-depth dependent settings on systems with less * then 256 colors. * * 2/13/1998 vadimg created \***************************************************************************/ VOID EnforceColorDependentSettings(VOID) { if (gpDispInfo->fAnyPalette) { gbDisableAlpha = TRUE; } else if (GreGetDeviceCaps(gpDispInfo->hdcScreen, NUMCOLORS) == -1) { gbDisableAlpha = FALSE; } else { gbDisableAlpha = TRUE; } } #if DBG VOID InitGlobalThreadLockArray( DWORD dwIndex) { PTL pTLArray = gpaThreadLocksArrays[dwIndex]; int i; for (i = 0; i < MAX_THREAD_LOCKS - 1; i++) { pTLArray[i].next = &pTLArray[i + 1]; } pTLArray[MAX_THREAD_LOCKS - 1].next = NULL; } #endif /***************************************************************************\ * CheckLUIDDosDevicesEnabled * * Checks if LUID DosDevices are Enabled. * * 8/20/2000 ELi created \***************************************************************************/ VOID CheckLUIDDosDevicesEnabled( PBOOL pResult) { ULONG LUIDDeviceMapsEnabled; NTSTATUS Status; UserAssert(pResult != NULL); Status = NtQueryInformationProcess(NtCurrentProcess(), ProcessLUIDDeviceMapsEnabled, &LUIDDeviceMapsEnabled, sizeof(LUIDDeviceMapsEnabled), NULL); if (NT_SUCCESS(Status)) { *pResult = (LUIDDeviceMapsEnabled != 0); } else { *pResult = FALSE; } }