BOOL IsPrivileged( PPRIVILEGE_SET ppSet) { HANDLE hToken; NTSTATUS Status; BOOLEAN bResult = FALSE; UNICODE_STRING strSubSystem; /* * Impersonate the client */ if (!CsrImpersonateClient(NULL)) return FALSE; /* * Open the client's token */ RtlInitUnicodeString(&strSubSystem, L"USER32"); if (NT_SUCCESS(Status = NtOpenThreadToken(NtCurrentThread(), TOKEN_QUERY, (BOOLEAN)TRUE, &hToken))) { /* * Perform the check */ Status = NtPrivilegeCheck(hToken, ppSet, &bResult); NtPrivilegeObjectAuditAlarm(&strSubSystem, NULL, hToken, 0, ppSet, bResult); NtClose(hToken); if (!bResult) { SetLastError(ERROR_ACCESS_DENIED); } } CsrRevertToSelf(); if (!NT_SUCCESS(Status)) SetLastError(RtlNtStatusToDosError(Status)); /* * Return result of privilege check */ return (BOOL)(bResult && NT_SUCCESS(Status)); }
ULONG SrvLogon( IN OUT PCSR_API_MSG m, IN OUT PCSR_REPLY_STATUS ReplyStatus) { PLOGONMSG a = (PLOGONMSG)&m->u.ApiMessageData; NTSTATUS Status; if (a->fLogon) { if (!CsrImpersonateClient(NULL)) return (ULONG)STATUS_UNSUCCESSFUL; /* * Take care of NLS cache for LogON. */ BaseSrvNlsLogon(TRUE); /* * Set the cleanup event so that the RIT can handle the NLS * registry notification. */ gfLogon = TRUE; Status = NtSetEvent( ghNlsEvent, NULL ); ASSERT(NT_SUCCESS(Status)); /* * Initialize console attributes */ InitializeConsoleAttributes(); CsrRevertToSelf(); } else { /* * Take care of NLS cache for LogOFF. */ BaseSrvNlsLogon(FALSE); } return (ULONG)STATUS_SUCCESS; }
VOID LinkGetRegistryValues( LPWSTR ConsoleTitle, LPLNKPROPNTCONSOLE lpCon ) /*++ Routine Description: This routine reads in values from the registry and places them in the supplied structure. Arguments: pStateInfo - optional pointer to structure to receive information Return Value: current page number --*/ { HKEY hCurrentUserKey; HKEY hConsoleKey; HKEY hTitleKey; NTSTATUS Status; LPWSTR TranslatedTitle; DWORD dwValue; DWORD i; WCHAR awchFaceName[LF_FACESIZE]; WCHAR awchBuffer[ 16 ]; // // Impersonate the client process // if (!CsrImpersonateClient(NULL)) { KdPrint(("CONSRV: GetRegistryValues Impersonate failed\n")); return; } // // Open the current user registry key // Status = RtlOpenCurrentUser(MAXIMUM_ALLOWED, &hCurrentUserKey); if (!NT_SUCCESS(Status)) { CsrRevertToSelf(); return; } // // Open the console registry key // Status = MyRegOpenKey(hCurrentUserKey, CONSOLE_REGISTRY_STRING, &hConsoleKey); if (!NT_SUCCESS(Status)) { NtClose(hCurrentUserKey); CsrRevertToSelf(); return; } // // If there is no structure to fill out, just bail out // if (!lpCon) goto CloseKeys; // // Open the console title subkey, if there is one // if (ConsoleTitle && (*ConsoleTitle != L'\0')) { TranslatedTitle = TranslateConsoleTitle(ConsoleTitle); if (TranslatedTitle == NULL) goto GetDefaultConsole; Status = MyRegOpenKey( hConsoleKey, TranslatedTitle, &hTitleKey); HeapFree(pConHeap,0,TranslatedTitle); if (!NT_SUCCESS(Status)) goto GetDefaultConsole; } else { GetDefaultConsole: hTitleKey = hConsoleKey; } // // Initial screen fill // if (NT_SUCCESS(MyRegQueryValue(hTitleKey, CONSOLE_REGISTRY_FILLATTR, sizeof(dwValue), (PBYTE)&dwValue))) { lpCon->wFillAttribute = (WORD)dwValue; } // // Initial popup fill // if (NT_SUCCESS(MyRegQueryValue(hTitleKey, CONSOLE_REGISTRY_POPUPATTR, sizeof(dwValue), (PBYTE)&dwValue))) { lpCon->wPopupFillAttribute = (WORD)dwValue; } // // Initial insert mode // if (NT_SUCCESS(MyRegQueryValue(hTitleKey, CONSOLE_REGISTRY_INSERTMODE, sizeof(dwValue), (PBYTE)&dwValue))) { lpCon->bInsertMode = !!dwValue; } // // Initial quick edit mode // if (NT_SUCCESS(MyRegQueryValue(hTitleKey, CONSOLE_REGISTRY_QUICKEDIT, sizeof(dwValue), (PBYTE)&dwValue))) { lpCon->bQuickEdit = !!dwValue; } #ifdef _X86_ // // Initial full screen mode // if (NT_SUCCESS(MyRegQueryValue(hTitleKey, CONSOLE_REGISTRY_FULLSCR, sizeof(dwValue), (PBYTE)&dwValue))) { lpCon->bFullScreen = !!dwValue; } #endif // // Initial screen buffer size // if (NT_SUCCESS(MyRegQueryValue(hTitleKey, CONSOLE_REGISTRY_BUFFERSIZE, sizeof(dwValue), (PBYTE)&dwValue))) { lpCon->dwScreenBufferSize.X = LOWORD(dwValue); lpCon->dwScreenBufferSize.Y = HIWORD(dwValue); } // // Initial window size // if (NT_SUCCESS(MyRegQueryValue(hTitleKey, CONSOLE_REGISTRY_WINDOWSIZE, sizeof(dwValue), (PBYTE)&dwValue))) { lpCon->dwWindowSize.X = LOWORD(dwValue); lpCon->dwWindowSize.Y = HIWORD(dwValue); } // // Initial window position // if (NT_SUCCESS(MyRegQueryValue(hTitleKey, CONSOLE_REGISTRY_WINDOWPOS, sizeof(dwValue), (PBYTE)&dwValue))) { lpCon->dwWindowOrigin.X = (SHORT)LOWORD(dwValue); lpCon->dwWindowOrigin.Y = (SHORT)HIWORD(dwValue); lpCon->bAutoPosition = FALSE; } // // Initial font size // if (NT_SUCCESS(MyRegQueryValue(hTitleKey, CONSOLE_REGISTRY_FONTSIZE, sizeof(dwValue), (PBYTE)&dwValue))) { lpCon->dwFontSize.X = LOWORD(dwValue); lpCon->dwFontSize.Y = HIWORD(dwValue); } // // Initial font family // if (NT_SUCCESS(MyRegQueryValue(hTitleKey, CONSOLE_REGISTRY_FONTFAMILY, sizeof(dwValue), (PBYTE)&dwValue))) { lpCon->uFontFamily = dwValue; } // // Initial font weight // if (NT_SUCCESS(MyRegQueryValue(hTitleKey, CONSOLE_REGISTRY_FONTWEIGHT, sizeof(dwValue), (PBYTE)&dwValue))) { lpCon->uFontWeight = dwValue; } // // Initial font face name // if (NT_SUCCESS(MyRegQueryValue(hTitleKey, CONSOLE_REGISTRY_FACENAME, sizeof(awchFaceName), (PBYTE)awchFaceName))) { RtlCopyMemory(lpCon->FaceName, awchFaceName, sizeof(awchFaceName)); } // // Initial cursor size // if (NT_SUCCESS(MyRegQueryValue(hTitleKey, CONSOLE_REGISTRY_CURSORSIZE, sizeof(dwValue), (PBYTE)&dwValue))) { lpCon->uCursorSize = dwValue; } // // Initial history buffer size // if (NT_SUCCESS(MyRegQueryValue(hTitleKey, CONSOLE_REGISTRY_HISTORYSIZE, sizeof(dwValue), (PBYTE)&dwValue))) { lpCon->uHistoryBufferSize = dwValue; } // // Initial number of history buffers // if (NT_SUCCESS(MyRegQueryValue(hTitleKey, CONSOLE_REGISTRY_HISTORYBUFS, sizeof(dwValue), (PBYTE)&dwValue))) { lpCon->uNumberOfHistoryBuffers = dwValue; } // // Initial history duplication mode // if (NT_SUCCESS(MyRegQueryValue(hTitleKey, CONSOLE_REGISTRY_HISTORYNODUP, sizeof(dwValue), (PBYTE)&dwValue))) { lpCon->bHistoryNoDup = dwValue; } // // Initial color table // for (i=0; i<16; i++) { wsprintf(awchBuffer, CONSOLE_REGISTRY_COLORTABLE, i); if (NT_SUCCESS(MyRegQueryValue(hTitleKey, awchBuffer, sizeof(dwValue), (PBYTE)&dwValue))) { lpCon->ColorTable[i] = dwValue; } } // // Close the registry keys // if (hTitleKey != hConsoleKey) { NtClose(hTitleKey); } CloseKeys: NtClose(hConsoleKey); NtClose(hCurrentUserKey); CsrRevertToSelf(); }
/*++ * @name FindProcessForShutdown * * The FindProcessForShutdown routine returns a CSR Process which is ready * to be shutdown, and sets the appropriate shutdown flags for it. * * @param CallerLuid * Pointer to the LUID of the CSR Process calling this routine. * * @return Pointer to a CSR Process which is ready to be shutdown. * * @remarks None. * *--*/ PCSR_PROCESS NTAPI FindProcessForShutdown(IN PLUID CallerLuid) { PCSR_PROCESS CsrProcess, ReturnCsrProcess = NULL; PCSR_THREAD CsrThread; NTSTATUS Status; ULONG Level = 0; LUID ProcessLuid; LUID SystemLuid = SYSTEM_LUID; PLIST_ENTRY NextEntry; /* Set the List Pointers */ NextEntry = CsrRootProcess->ListLink.Flink; while (NextEntry != &CsrRootProcess->ListLink) { /* Get the process */ CsrProcess = CONTAINING_RECORD(NextEntry, CSR_PROCESS, ListLink); /* Move to the next entry */ NextEntry = NextEntry->Flink; /* Skip this process if it's already been processed */ if (CsrProcess->Flags & CsrProcessSkipShutdown) continue; /* Get the LUID of this process */ Status = CsrGetProcessLuid(CsrProcess->ProcessHandle, &ProcessLuid); /* Check if we didn't get access to the LUID */ if (Status == STATUS_ACCESS_DENIED) { /* Check if we have any threads */ if (CsrProcess->ThreadCount) { /* Impersonate one of the threads and retry */ CsrThread = CONTAINING_RECORD(CsrProcess->ThreadList.Flink, CSR_THREAD, Link); if (CsrImpersonateClient(CsrThread)) { Status = CsrGetProcessLuid(NULL, &ProcessLuid); CsrRevertToSelf(); } else { Status = STATUS_BAD_IMPERSONATION_LEVEL; } } } if (!NT_SUCCESS(Status)) { /* We didn't have access, so skip it */ CsrProcess->Flags |= CsrProcessSkipShutdown; continue; } /* Check if this is the System LUID */ if (RtlEqualLuid(&ProcessLuid, &SystemLuid)) { /* Mark this process */ CsrProcess->ShutdownFlags |= CsrShutdownSystem; } else if (!RtlEqualLuid(&ProcessLuid, CallerLuid)) { /* Our LUID doesn't match with the caller's */ CsrProcess->ShutdownFlags |= CsrShutdownOther; } /* Check if we're past the previous level */ if ((CsrProcess->ShutdownLevel > Level) || !ReturnCsrProcess) { /* Update the level */ Level = CsrProcess->ShutdownLevel; /* Set the final process */ ReturnCsrProcess = CsrProcess; } } /* Check if we found a process */ if (ReturnCsrProcess) { /* Skip this one next time */ ReturnCsrProcess->Flags |= CsrProcessSkipShutdown; } return ReturnCsrProcess; }
// FIXME: Maybe return a NTSTATUS static BOOL GuiInit(IN PCONSOLE_INIT_INFO ConsoleInitInfo, IN HANDLE ConsoleLeaderProcessHandle, IN OUT PGUI_INIT_INFO GuiInitInfo) { BOOL Success = TRUE; UNICODE_STRING DesktopPath; DESKTOP_CONSOLE_THREAD DesktopConsoleThreadInfo; HWINSTA hWinSta; HDESK hDesk; NTSTATUS Status; HANDLE hInputThread; CLIENT_ID ClientId; /* * Initialize and register the console window class, if needed. */ if (!ConsInitialized) { if (!RegisterConWndClass(ConSrvDllInstance)) return FALSE; ConsInitialized = TRUE; } /* * Set-up the console input thread. We have * one console input thread per desktop. */ if (!CsrImpersonateClient(NULL)) // return STATUS_BAD_IMPERSONATION_LEVEL; return FALSE; if (ConsoleInitInfo->DesktopLength) { DesktopPath.MaximumLength = ConsoleInitInfo->DesktopLength; DesktopPath.Length = DesktopPath.MaximumLength - sizeof(UNICODE_NULL); DesktopPath.Buffer = ConsoleInitInfo->Desktop; } else { RtlInitUnicodeString(&DesktopPath, L"Default"); } hDesk = NtUserResolveDesktop(ConsoleLeaderProcessHandle, &DesktopPath, 0, &hWinSta); DPRINT("NtUserResolveDesktop(DesktopPath = '%wZ') returned hDesk = 0x%p; hWinSta = 0x%p\n", &DesktopPath, hDesk, hWinSta); CsrRevertToSelf(); if (hDesk == NULL) return FALSE; /* * We need to see whether we need to create a * new console input thread for this desktop. */ DesktopConsoleThreadInfo.DesktopHandle = hDesk; DesktopConsoleThreadInfo.ThreadId = (ULONG_PTR)INVALID_HANDLE_VALUE; // Special value to say we just want to retrieve the thread ID. NtUserConsoleControl(ConsoleCtrlDesktopConsoleThread, &DesktopConsoleThreadInfo, sizeof(DesktopConsoleThreadInfo)); DPRINT("NtUserConsoleControl returned ThreadId = 0x%p\n", DesktopConsoleThreadInfo.ThreadId); /* * Save the opened window station and desktop handles in the initialization * structure. They will be used later on, and released, by the GUI frontend. */ GuiInitInfo->WinSta = hWinSta; GuiInitInfo->Desktop = hDesk; /* Here GuiInitInfo contains original handles */ /* If we already have a console input thread on this desktop... */ if (DesktopConsoleThreadInfo.ThreadId != 0) { /* ... just use it... */ DPRINT("Using input thread InputThreadId = 0x%p\n", DesktopConsoleThreadInfo.ThreadId); GuiInitInfo->InputThreadId = DesktopConsoleThreadInfo.ThreadId; goto Quit; } /* ... otherwise create a new one. */ /* Initialize a startup event for the thread to signal it */ Status = NtCreateEvent(&GuiInitInfo->GuiThreadStartupEvent, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); if (!NT_SUCCESS(Status)) { Success = FALSE; goto Quit; } /* * Duplicate the desktop handle for the console input thread internal needs. * If it happens to need also a window station handle in the future, then * it is there that you also need to duplicate the window station handle! * * Note also that we are going to temporarily overwrite the stored handles * in GuiInitInfo because it happens that we use also this structure to give * the duplicated handles to the input thread that is going to initialize. * After the input thread finishes its initialization, we restore the handles * in GuiInitInfo to their old values. */ Status = NtDuplicateObject(NtCurrentProcess(), hDesk, NtCurrentProcess(), (PHANDLE)&GuiInitInfo->Desktop, 0, 0, DUPLICATE_SAME_ACCESS); if (!NT_SUCCESS(Status)) { Success = FALSE; goto Quit; } /* Here GuiInitInfo contains duplicated handles */ Status = RtlCreateUserThread(NtCurrentProcess(), NULL, TRUE, // Start the thread in suspended state 0, 0, 0, (PVOID)GuiConsoleInputThread, (PVOID)GuiInitInfo, &hInputThread, &ClientId); if (NT_SUCCESS(Status)) { /* Add it as a static server thread and resume it */ CsrAddStaticServerThread(hInputThread, &ClientId, 0); Status = NtResumeThread(hInputThread, NULL); } DPRINT("Thread creation hInputThread = 0x%p, InputThreadId = 0x%p, Status = 0x%08lx\n", hInputThread, ClientId.UniqueThread, Status); if (!NT_SUCCESS(Status) || hInputThread == NULL) { /* Close the thread's handle */ if (hInputThread) NtClose(hInputThread); /* We need to close here the duplicated desktop handle */ CloseDesktop(GuiInitInfo->Desktop); // NtUserCloseDesktop /* Close the startup event and bail out */ NtClose(GuiInitInfo->GuiThreadStartupEvent); DPRINT1("CONSRV: Failed to create graphics console thread.\n"); Success = FALSE; goto Quit; } /* No need to close hInputThread, this is done by CSR automatically */ /* Wait for the thread to finish its initialization, and close the startup event */ NtWaitForSingleObject(GuiInitInfo->GuiThreadStartupEvent, FALSE, NULL); NtClose(GuiInitInfo->GuiThreadStartupEvent); /* * Save the input thread ID for later use, and restore the original handles. * The copies are held by the console input thread. */ GuiInitInfo->InputThreadId = (ULONG_PTR)ClientId.UniqueThread; GuiInitInfo->WinSta = hWinSta; GuiInitInfo->Desktop = hDesk; /* Here GuiInitInfo contains again original handles */ Quit: if (!Success) { /* * Close the original handles. Do not use the copies in GuiInitInfo * because we may have failed in the middle of the duplicate operation * and the handles stored in GuiInitInfo may have changed. */ CloseDesktop(hDesk); // NtUserCloseDesktop CloseWindowStation(hWinSta); // NtUserCloseWindowStation } return Success; }
NTSTATUS NTAPI GuiLoadFrontEnd(IN OUT PFRONTEND FrontEnd, IN OUT PCONSOLE_STATE_INFO ConsoleInfo, IN OUT PCONSOLE_INIT_INFO ConsoleInitInfo, IN HANDLE ConsoleLeaderProcessHandle) { PCONSOLE_START_INFO ConsoleStartInfo; PGUI_INIT_INFO GuiInitInfo; if (FrontEnd == NULL || ConsoleInfo == NULL || ConsoleInitInfo == NULL) return STATUS_INVALID_PARAMETER; ConsoleStartInfo = ConsoleInitInfo->ConsoleStartInfo; /* * Initialize a private initialization info structure for later use. * It must be freed by a call to GuiUnloadFrontEnd or GuiInitFrontEnd. */ GuiInitInfo = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*GuiInitInfo)); if (GuiInitInfo == NULL) return STATUS_NO_MEMORY; /* Initialize GUI terminal emulator common functionalities */ if (!GuiInit(ConsoleInitInfo, ConsoleLeaderProcessHandle, GuiInitInfo)) { ConsoleFreeHeap(GuiInitInfo); return STATUS_UNSUCCESSFUL; } /* * Load terminal settings */ #if 0 /* Impersonate the caller in order to retrieve settings in its context */ // if (!CsrImpersonateClient(NULL)) // return STATUS_UNSUCCESSFUL; CsrImpersonateClient(NULL); /* 1. Load the default settings */ GuiConsoleGetDefaultSettings(&GuiInitInfo->TermInfo); #endif GuiInitInfo->TermInfo.ShowWindow = SW_SHOWNORMAL; if (ConsoleInitInfo->IsWindowVisible) { /* 2. Load the remaining console settings via the registry */ if ((ConsoleStartInfo->dwStartupFlags & STARTF_TITLEISLINKNAME) == 0) { #if 0 /* Load the terminal infos from the registry */ GuiConsoleReadUserSettings(&GuiInitInfo->TermInfo); #endif /* * Now, update them with the properties the user might gave to us * via the STARTUPINFO structure before calling CreateProcess * (and which was transmitted via the ConsoleStartInfo structure). * We therefore overwrite the values read in the registry. */ if (ConsoleStartInfo->dwStartupFlags & STARTF_USESHOWWINDOW) { GuiInitInfo->TermInfo.ShowWindow = ConsoleStartInfo->wShowWindow; } if (ConsoleStartInfo->dwStartupFlags & STARTF_USEPOSITION) { ConsoleInfo->AutoPosition = FALSE; ConsoleInfo->WindowPosition.x = ConsoleStartInfo->dwWindowOrigin.X; ConsoleInfo->WindowPosition.y = ConsoleStartInfo->dwWindowOrigin.Y; } if (ConsoleStartInfo->dwStartupFlags & STARTF_RUNFULLSCREEN) { ConsoleInfo->FullScreen = TRUE; } } } #if 0 /* Revert impersonation */ CsrRevertToSelf(); #endif // Font data wcsncpy(GuiInitInfo->TermInfo.FaceName, ConsoleInfo->FaceName, LF_FACESIZE); GuiInitInfo->TermInfo.FaceName[LF_FACESIZE - 1] = UNICODE_NULL; GuiInitInfo->TermInfo.FontFamily = ConsoleInfo->FontFamily; GuiInitInfo->TermInfo.FontSize = ConsoleInfo->FontSize; GuiInitInfo->TermInfo.FontWeight = ConsoleInfo->FontWeight; // Display GuiInitInfo->TermInfo.FullScreen = ConsoleInfo->FullScreen; // GuiInitInfo->TermInfo.ShowWindow; GuiInitInfo->TermInfo.AutoPosition = ConsoleInfo->AutoPosition; GuiInitInfo->TermInfo.WindowOrigin = ConsoleInfo->WindowPosition; /* Initialize the icon handles */ // if (ConsoleStartInfo->hIcon != NULL) GuiInitInfo->hIcon = ConsoleStartInfo->hIcon; // else // GuiInitInfo->hIcon = ghDefaultIcon; // if (ConsoleStartInfo->hIconSm != NULL) GuiInitInfo->hIconSm = ConsoleStartInfo->hIconSm; // else // GuiInitInfo->hIconSm = ghDefaultIconSm; // ASSERT(GuiInitInfo->hIcon && GuiInitInfo->hIconSm); GuiInitInfo->IsWindowVisible = ConsoleInitInfo->IsWindowVisible; /* Finally, initialize the frontend structure */ FrontEnd->Vtbl = &GuiVtbl; FrontEnd->Context = NULL; FrontEnd->Context2 = GuiInitInfo; return STATUS_SUCCESS; }
BOOLEAN NTAPI BaseSrvIsVdmAllowed(VOID) { NTSTATUS Status; BOOLEAN VdmAllowed = TRUE; HANDLE RootKey, KeyHandle; UNICODE_STRING KeyName, ValueName, MachineKeyName; OBJECT_ATTRIBUTES Attributes; UCHAR ValueBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)]; PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)ValueBuffer; ULONG ActualSize; /* Initialize the unicode strings */ RtlInitUnicodeString(&MachineKeyName, L"\\Registry\\Machine"); RtlInitUnicodeString(&KeyName, VDM_POLICY_KEY_NAME); RtlInitUnicodeString(&ValueName, VDM_DISALLOWED_VALUE_NAME); InitializeObjectAttributes(&Attributes, &MachineKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL); /* Open the local machine key */ Status = NtOpenKey(&RootKey, KEY_READ, &Attributes); if (!NT_SUCCESS(Status)) return FALSE; InitializeObjectAttributes(&Attributes, &KeyName, OBJ_CASE_INSENSITIVE, RootKey, NULL); /* Open the policy key in the local machine hive, if it exists */ if (NT_SUCCESS(NtOpenKey(&KeyHandle, KEY_READ, &Attributes))) { /* Read the value, if it's set */ if (NT_SUCCESS(NtQueryValueKey(KeyHandle, &ValueName, KeyValuePartialInformation, ValueInfo, sizeof(ValueBuffer), &ActualSize))) { if (*((PULONG)ValueInfo->Data)) { /* The VDM has been disabled in the registry */ VdmAllowed = FALSE; } } NtClose(KeyHandle); } /* Close the local machine key */ NtClose(RootKey); /* If it's disabled system-wide, there's no need to check the user key */ if (!VdmAllowed) return FALSE; /* Open the current user key of the client */ if (!CsrImpersonateClient(NULL)) return VdmAllowed; Status = RtlOpenCurrentUser(KEY_READ, &RootKey); CsrRevertToSelf(); /* If that fails, return the system-wide setting */ if (!NT_SUCCESS(Status)) return VdmAllowed; InitializeObjectAttributes(&Attributes, &KeyName, OBJ_CASE_INSENSITIVE, RootKey, NULL); /* Open the policy key in the current user hive, if it exists */ if (NT_SUCCESS(NtOpenKey(&KeyHandle, KEY_READ, &Attributes))) { /* Read the value, if it's set */ if (NT_SUCCESS(NtQueryValueKey(KeyHandle, &ValueName, KeyValuePartialInformation, ValueInfo, sizeof(ValueBuffer), &ActualSize))) { if (*((PULONG)ValueInfo->Data)) { /* The VDM has been disabled in the registry */ VdmAllowed = FALSE; } } NtClose(KeyHandle); } return VdmAllowed; }
NTSTATUS _ExitWindowsEx( PCSR_THREAD pcsrt, UINT dwFlags, DWORD dwReserved) { BOOL fDoEndSession = FALSE; LUID luidCaller; NTSTATUS Status = STATUS_SUCCESS; UNREFERENCED_PARAMETER(dwReserved); if ((dwFlags & EWX_REBOOT) || (dwFlags & EWX_POWEROFF)) { dwFlags |= EWX_SHUTDOWN; } /* * Find out the callers sid. Only want to shutdown processes in the * callers sid. */ if (!CsrImpersonateClient(NULL)) { return STATUS_BAD_IMPERSONATION_LEVEL; } Status = CsrGetProcessLuid(NULL, &luidCaller); if (!NT_SUCCESS(Status)) { CsrRevertToSelf(); return Status; } try { while (1) { LARGE_INTEGER li; LeaveCrit(); Status = NtUserSetInformationThread( pcsrt->ThreadHandle, UserThreadInitiateShutdown, &dwFlags, sizeof(dwFlags)); EnterCrit(); switch (Status) { case STATUS_PENDING: /* * The logoff/shutdown is in progress and nothing * more needs to be done. */ goto fastexit; case STATUS_RETRY: /* * Another logoff/shutdown is in progress and we need * to cancel it so we can do an override. * * if someone else is trying to cancel shutdown, exit */ li.QuadPart = 0; if (NtWaitForSingleObject(heventCancel, FALSE, &li) == 0) { Status = STATUS_PENDING; goto fastexit; } /* * Cancel the old shutdown */ NtClearEvent(heventCancelled); NtSetEvent(heventCancel, NULL); /* * Wait for the other guy to be cancelled */ LeaveCrit(); NtWaitForSingleObject(heventCancelled, FALSE, NULL); EnterCrit(); /* * This signals that we are no longer trying to cancel a * shutdown */ NtClearEvent(heventCancel); continue; case STATUS_CANT_WAIT: /* * There is no notify window and the calling thread has * windows that prevent this request from succeeding. * The client handles this by starting another thread * to recall ExitWindowsEx. */ goto fastexit; default: if (!NT_SUCCESS(Status)) goto fastexit; } break; } gdwFlags = dwFlags; dwThreadEndSession = (DWORD)pcsrt->ClientId.UniqueThread; fDoEndSession = TRUE; /* * Sometimes the console calls the dialog box when not in shutdown * if now is one of those times cancel the dialog box. */ while (gcInternalDoEndTaskDialog > 0) { LARGE_INTEGER li; NtPulseEvent(heventCancel, NULL); LeaveCrit(); li.QuadPart = (LONGLONG)-10000 * CMSSLEEP; NtDelayExecution(FALSE, &li); EnterCrit(); } /* * Call csr to loop through the processes shutting them down. */ LeaveCrit(); Status = CsrShutdownProcesses(&luidCaller, dwFlags); NtUserSetInformationThread( pcsrt->ThreadHandle, UserThreadEndShutdown, &Status, sizeof(Status)); EnterCrit(); fastexit:; } finally { /* * Only turn off dwThreadEndSession if this is the * thread doing shutdown. */ if (fDoEndSession) { dwThreadEndSession = 0; NtSetEvent(heventCancelled, NULL); } } CsrRevertToSelf(); return Status; }