/** * @brief Terminates the current thread. * @param[in] status the exit status. * @note This routine causes a small memory leak, * because it doesn't deallocate the initial stack. * On the other hand, such deallocation seems to be * not easy and even if we'll find a proper solution * for, let's say XP, we cannot guarantee its work * on other systems. */ void winx_exit_thread(NTSTATUS status) { NTSTATUS s = ZwTerminateThread(NtCurrentThread(),status); if(!NT_SUCCESS(s)){ strace(s,"cannot terminate thread"); } }
static HANDLE GetThreadHandle(HANDLE ThreadHandle) { if (ThreadHandle == NtCurrentThread()) return CurrentThreadHandle; else return ThreadHandle; }
NTSTATUS ThreadThatExits ( IN PVOID ThreadParameter ) { NtTerminateThread(NtCurrentThread(),(NTSTATUS) ThreadParameter ); }
/*++ * @name CsrRevertToSelf * @implemented NT4 * * The CsrRevertToSelf routine will attempt to remove an active impersonation. * * @param None. * * @return TRUE if the reversion was succesful, FALSE otherwise. * * @remarks Impersonation can be recursive; as such, the impersonation token * will only be deleted once the CSR Thread's impersonaton count * has reached zero. * *--*/ BOOLEAN NTAPI CsrRevertToSelf(VOID) { NTSTATUS Status; PCSR_THREAD CurrentThread = CsrGetClientThread(); HANDLE ImpersonationToken = NULL; /* Check if we have a Current Thread */ if (CurrentThread) { /* Make sure impersonation is on */ if (!CurrentThread->ImpersonationCount) { DPRINT1("CSRSS: CsrRevertToSelf called while not impersonating\n"); // DbgBreakPoint(); return FALSE; } else if ((--CurrentThread->ImpersonationCount) > 0) { /* Success; impersonation count decreased but still not zero */ return TRUE; } } /* Impersonation has been totally removed, revert to ourselves */ Status = NtSetInformationThread(NtCurrentThread(), ThreadImpersonationToken, &ImpersonationToken, sizeof(ImpersonationToken)); /* Return TRUE or FALSE */ return NT_SUCCESS(Status); }
NTSTATUS UserClientConnect( PCSR_PROCESS Process, PVOID ConnectionInformation, PULONG pulConnectionLen) { PHANDLE pHandle = Process->ServerDllPerProcessData[USERSRV_SERVERDLL_INDEX]; int i; /* * Pass the api port to the kernel. Do this early so the kernel * can send a datagram to CSR to activate a debugger. */ if (CsrApiPort == NULL) { CsrApiPort = CsrQueryApiPort(); NtUserSetInformationThread( NtCurrentThread(), UserThreadCsrApiPort, &CsrApiPort, sizeof(HANDLE)); } /* * Initialize cached handles to NULL */ for (i = 0; i < CHANDLES; ++i) pHandle[i] = NULL; return NtUserProcessConnect(Process->ProcessHandle, (PUSERCONNECT)ConnectionInformation, *pulConnectionLen); }
NTSTATUS __cdecl _main(int argc, char *argv[], char *envp[], ULONG DebugFlag) { NTSTATUS Status = STATUS_SUCCESS; PROCESS_BASIC_INFORMATION PBI = {0}; /* Lookup yourself */ Status = NtQueryInformationProcess (NtCurrentProcess(), ProcessBasicInformation, & PBI, sizeof PBI, NULL); if(NT_SUCCESS(Status)) { SmSsProcessId = (ULONG) PBI.UniqueProcessId; } /* Initialize the system */ Status = InitSessionManager(); /* Watch required subsystems TODO */ #if 0 if (!NT_SUCCESS(Status)) { int i; for (i=0; i < (sizeof Children / sizeof Children[0]); i++) { if (Children[i]) { NtTerminateProcess(Children[i],0); } } DPRINT1("SM: Initialization failed!\n"); goto ByeBye; } Status = NtWaitForMultipleObjects(((LONG) sizeof(Children) / sizeof(HANDLE)), Children, WaitAny, TRUE, /* alertable */ NULL); /* NULL for infinite */ if (!NT_SUCCESS(Status)) { DPRINT1("SM: NtWaitForMultipleObjects failed! (Status=0x%08lx)\n", Status); } else { DPRINT1("SM: Process terminated!\n"); } ByeBye: /* Raise a hard error (crash the system/BSOD) */ NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0,0,0,0,0); // NtTerminateProcess(NtCurrentProcess(), 0); #endif return NtTerminateThread(NtCurrentThread(), Status); }
NTSTATUS ThreadThatSpins ( IN PVOID ThreadParameter ) { for(;;); NtTerminateThread(NtCurrentThread(),STATUS_SUCCESS); }
NTSTATUS ThreadThatExcepts ( IN PVOID ThreadParameter ) { foo((PULONG)0x00000001); NtTerminateThread(NtCurrentThread(),(NTSTATUS) ThreadParameter ); }
DWORD WINAPI PnpEventThread(IN LPVOID lpParameter) { NTSTATUS Status; Status = EventThread(lpParameter); NtTerminateThread(NtCurrentThread(), Status); return 0; }
SECURITY_STATUS SsprRevertSecurityContext( IN PCtxtHandle ContextHandle ) /*++ Routine Description: Reverts a thread from a security context Arguments: ContextHandle - Context handle to impersonate. Return Value: STATUS_SUCCESS - Message handled SEC_E_INVALID_HANDLE -- Context Handle is invalid --*/ { PCheaterContext Context; NTSTATUS Status; HANDLE NullTokenHandle = NULL; Context = SspLocateLocalContext(ContextHandle); if (Context == NULL) { return(SEC_E_INVALID_HANDLE); } if (Context->TokenHandle == NULL) { return(SEC_E_NO_IMPERSONATION); } // // Impersonate the TokenHandle into the callers address space. // Status = NtSetInformationThread( NtCurrentThread(), ThreadImpersonationToken, (PVOID) &NullTokenHandle, (ULONG) sizeof(HANDLE)); if (!NT_SUCCESS(Status)) { return(SspNtStatusToSecStatus(Status, SEC_E_NO_IMPERSONATION)); } return SEC_E_OK; }
// get current thread id DWORD misc_NtGetCurrentThreadId(void) { THREAD_BASIC_INFORMATION tbi; if (NT_SUCCESS(NtQueryInformationThread(NtCurrentThread(),ThreadBasicInformation,&tbi,sizeof(tbi),NULL))) return (DWORD)tbi.ClientId.UniqueThread; return 0; }
int _cdecl _main(int argc, char *argv[], char *envp[], int DebugFlag) { KPRIORITY BasePriority = (8 + 1) + 4; NTSTATUS Status; //ULONG Response; // see the #if 0 UNREFERENCED_PARAMETER(envp); UNREFERENCED_PARAMETER(DebugFlag); /* Set the Priority */ NtSetInformationProcess(NtCurrentProcess(), ProcessBasePriority, &BasePriority, sizeof(KPRIORITY)); /* Give us IOPL so that we can access the VGA registers */ Status = NtSetInformationProcess(NtCurrentProcess(), ProcessUserModeIOPL, NULL, 0); if (!NT_SUCCESS(Status)) { /* Raise a hard error */ DPRINT1("CSRSS: Could not raise IOPL, Status: 0x%08lx\n", Status); #if 0 Status = NtRaiseHardError(STATUS_IO_PRIVILEGE_FAILED, 0, 0, NULL, OptionOk, &Response); #endif } /* Initialize CSR through CSRSRV */ Status = CsrServerInitialization(argc, argv); if (!NT_SUCCESS(Status)) { /* Kill us */ DPRINT1("CSRSS: Unable to initialize server, Status: 0x%08lx\n", Status); NtTerminateProcess(NtCurrentProcess(), Status); } /* Disable errors */ CsrpSetDefaultProcessHardErrorMode(); /* If this is Session 0, make sure killing us bugchecks the system */ if (NtCurrentPeb()->SessionId == 0) RtlSetProcessIsCritical(TRUE, NULL, FALSE); /* Kill this thread. CSRSRV keeps us going */ NtTerminateThread(NtCurrentThread(), Status); return 0; }
VOID RtlAssert( IN PVOID FailedAssertion, IN PVOID FileName, IN ULONG LineNumber, IN PCHAR Message OPTIONAL ) { #if DBG || RTL_ASSERT_ALWAYS_ENABLED char Response[ 2 ]; CONTEXT Context; #ifndef BLDR_KERNEL_RUNTIME RtlCaptureContext( &Context ); #endif while (TRUE) { DbgPrint( "\n*** Assertion failed: %s%s\n*** Source File: %s, line %ld\n\n", Message ? Message : "", FailedAssertion, FileName, LineNumber ); DbgPrompt( "Break, Ignore, Terminate Process or Terminate Thread (bipt)? ", Response, sizeof( Response ) ); switch (Response[0]) { case 'B': case 'b': DbgPrint( "Execute '!cxr %p' to dump context\n", &Context); DbgBreakPoint(); break; case 'I': case 'i': return; case 'P': case 'p': ZwTerminateProcess( NtCurrentProcess(), STATUS_UNSUCCESSFUL ); break; case 'T': case 't': ZwTerminateThread( NtCurrentThread(), STATUS_UNSUCCESSFUL ); break; } } DbgBreakPoint(); ZwTerminateProcess( NtCurrentProcess(), STATUS_UNSUCCESSFUL ); #endif }
void ImpersonateToken() { pgpAssert(IsImpersonationTokenSet()); if (mAppropriateProcId != (PGPUInt32) PsGetCurrentProcessId()) return; ZwSetInformationThread(NtCurrentThread(), ThreadImpersonationToken, &mImpersonationToken, sizeof(mImpersonationToken)); }
/* * @implemented */ VOID NTAPI RtlExitUserThread(NTSTATUS Status) { /* Call the Loader and tell him to notify the DLLs */ LdrShutdownThread(); /* Shut us down */ NtCurrentTeb()->FreeStackOnTermination = TRUE; NtTerminateThread(NtCurrentThread(), Status); }
void RevertToSelf() { HANDLE nullToken = NULL; if (mAppropriateProcId != (PGPUInt32) PsGetCurrentProcessId()) return; ZwSetInformationThread(NtCurrentThread(), ThreadImpersonationToken, &nullToken, sizeof(nullToken)); }
NTSYSAPI NTSTATUS STDAPIVCALLTYPE RtlSetThreadIsCritical( IN BOOLEAN NewValue, OUT PBOOLEAN OldValue OPTIONAL, IN BOOLEAN CheckFlag ) { PPEB Peb; ULONG Enable; NTSTATUS Status; if ( ARGUMENT_PRESENT(OldValue) ) { *OldValue = FALSE; } Peb = RtlGetCurrentPeb(); if ( CheckFlag && ! (Peb->NtGlobalFlag & FLG_ENABLE_SYSTEM_CRIT_BREAKS) ) { return STATUS_UNSUCCESSFUL; } if ( ARGUMENT_PRESENT(OldValue) ) { NtQueryInformationThread(NtCurrentThread(), ThreadBreakOnTermination, &Enable, sizeof(Enable), NULL); *OldValue = (BOOLEAN) Enable; } Enable = NewValue; Status = NtSetInformationThread(NtCurrentThread(), ThreadBreakOnTermination, &Enable, sizeof(Enable)); return Status; }
/* * @implemented */ BOOL WINAPI DuplicateHandle(IN HANDLE hSourceProcessHandle, IN HANDLE hSourceHandle, IN HANDLE hTargetProcessHandle, OUT LPHANDLE lpTargetHandle, IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwOptions) { NTSTATUS Status; HANDLE hTargetHandle; hSourceHandle = TranslateStdHandle(hSourceHandle); if ((IsConsoleHandle(hSourceHandle)) && ((hSourceHandle != NtCurrentProcess()) && (hSourceHandle != NtCurrentThread()))) { if ((hSourceProcessHandle != NtCurrentProcess()) && (hTargetProcessHandle != NtCurrentProcess())) { BaseSetLastNTError(STATUS_INVALID_PARAMETER); return FALSE; } hTargetHandle = DuplicateConsoleHandle(hSourceHandle, dwDesiredAccess, bInheritHandle, dwOptions); if (hTargetHandle != INVALID_HANDLE_VALUE) { if (lpTargetHandle) *lpTargetHandle = hTargetHandle; return TRUE; } return FALSE; } Status = NtDuplicateObject(hSourceProcessHandle, hSourceHandle, hTargetProcessHandle, lpTargetHandle, dwDesiredAccess, bInheritHandle ? OBJ_INHERIT : 0, dwOptions); if (NT_SUCCESS(Status)) return TRUE; BaseSetLastNTError(Status); return FALSE; }
/* * @implemented */ NTSTATUS NTAPI RtlSetThreadIsCritical(IN BOOLEAN NewValue, OUT PBOOLEAN OldValue OPTIONAL, IN BOOLEAN NeedBreaks) { ULONG BreakOnTermination; /* Initialize to FALSE */ if (OldValue) *OldValue = FALSE; /* Fail, if the critical breaks flag is required but is not set */ if ((NeedBreaks) && !(NtCurrentPeb()->NtGlobalFlag & FLG_ENABLE_SYSTEM_CRIT_BREAKS)) { return STATUS_UNSUCCESSFUL; } /* Check if the caller wants the old value */ if (OldValue) { /* Query and return the old break on termination flag for the process */ ZwQueryInformationThread(NtCurrentThread(), ThreadBreakOnTermination, &BreakOnTermination, sizeof(ULONG), NULL); *OldValue = (BOOLEAN)BreakOnTermination; } /* Set the break on termination flag for the process */ BreakOnTermination = NewValue; return ZwSetInformationThread(NtCurrentThread(), ThreadBreakOnTermination, &BreakOnTermination, sizeof(ULONG)); }
/* * @implemented */ BOOL WINAPI TlsFree(DWORD Index) { BOOL BitSet; if (Index >= TLS_EXPANSION_SLOTS + TLS_MINIMUM_AVAILABLE) { SetLastErrorByStatus(STATUS_INVALID_PARAMETER); return FALSE; } RtlAcquirePebLock(); if (Index >= TLS_MINIMUM_AVAILABLE) { BitSet = RtlAreBitsSet(NtCurrentPeb()->TlsExpansionBitmap, Index - TLS_MINIMUM_AVAILABLE, 1); if (BitSet) RtlClearBits(NtCurrentPeb()->TlsExpansionBitmap, Index - TLS_MINIMUM_AVAILABLE, 1); } else { BitSet = RtlAreBitsSet(NtCurrentPeb()->TlsBitmap, Index, 1); if (BitSet) RtlClearBits(NtCurrentPeb()->TlsBitmap, Index, 1); } if (BitSet) { /* Clear the TLS cells (slots) in all threads of the current process. */ NtSetInformationThread(NtCurrentThread(), ThreadZeroTlsCell, &Index, sizeof(DWORD)); } else { SetLastError(ERROR_INVALID_PARAMETER); } RtlReleasePebLock(); return BitSet; }
/* * SftListThreadPriv * * Purpose: * * Test unit for thread elevation check. * */ VOID SftListThreadPriv( VOID ) { DWORD dwLen; bool bRes; HANDLE hToken; BYTE *Buffer; TOKEN_PRIVILEGES *pPrivs; WCHAR text[MAX_PATH]; if (!OpenThreadToken(NtCurrentThread(), TOKEN_QUERY, FALSE, &hToken)) return; dwLen = 0; bRes = GetTokenInformation( hToken, TokenPrivileges, NULL, 0, &dwLen ); Buffer = LocalAlloc(LPTR, dwLen); if (Buffer) { bRes = GetTokenInformation( hToken, TokenPrivileges, Buffer, dwLen, &dwLen ); pPrivs = (TOKEN_PRIVILEGES*)Buffer; for (DWORD i = 0; i < pPrivs->PrivilegeCount; i++) { if (pPrivs->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED) { text[0] = 0; ultostr(pPrivs->Privileges[i].Luid.LowPart, text); _strcat(text, TEXT("\r\n")); OutputDebugString(text); } } LocalFree(Buffer); } CloseHandle(hToken); }
/********************************************************************** * SbApiPortListener/1 * * DESCRIPTION * The \POSIX+\SbApiPort LPC port message dispatcher. * * NOTE * what is this port for? Is "Sb" for "shared block"? */ VOID STDCALL SbApiPortListener (PVOID pArg) { NTSTATUS Status; ULONG PortIdentifier; PSX_MAX_MESSAGE Request; PPSX_MAX_MESSAGE Reply = NULL; debug_print (L"PSXSS: ->%s pArg=%d", TEXT(__FUNCTION__), (ULONG) pArg); RtlZeroMemory (& Request, sizeof Request); /* TODO */ #ifdef __PSXSS_ON_W32__ Sleep(30000); TerminateThread(GetCurrentThread(),Status); #else NtTerminateThread(NtCurrentThread(),Status); #endif }
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)); }
/* * @implemented */ BOOL WINAPI SetThreadToken(IN PHANDLE ThreadHandle OPTIONAL, IN HANDLE TokenHandle) { NTSTATUS Status; HANDLE hThread; hThread = (ThreadHandle != NULL) ? *ThreadHandle : NtCurrentThread(); Status = NtSetInformationThread(hThread, ThreadImpersonationToken, &TokenHandle, sizeof(HANDLE)); if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; } return TRUE; }
/*++ * @name CsrImpersonateClient * @implemented NT4 * * The CsrImpersonateClient will impersonate the given CSR Thread. * * @param CsrThread * Pointer to the CSR Thread to impersonate. * * @return TRUE if impersonation succeeded, FALSE otherwise. * * @remarks Impersonation can be recursive. * *--*/ BOOLEAN NTAPI CsrImpersonateClient(IN PCSR_THREAD CsrThread) { NTSTATUS Status; PCSR_THREAD CurrentThread = CsrGetClientThread(); /* Use the current thread if none given */ if (!CsrThread) CsrThread = CurrentThread; /* Still no thread, something is wrong */ if (!CsrThread) { /* Failure */ return FALSE; } /* Make the call */ Status = NtImpersonateThread(NtCurrentThread(), CsrThread->ThreadHandle, &CsrSecurityQos); if (!NT_SUCCESS(Status)) { /* Failure */ DPRINT1("CSRSS: Can't impersonate client thread - Status = %lx\n", Status); // if (Status != STATUS_BAD_IMPERSONATION_LEVEL) DbgBreakPoint(); return FALSE; } /* Increase the impersonation count for the current thread */ if (CurrentThread) ++CurrentThread->ImpersonationCount; /* Return Success */ return TRUE; }
NTSTATUS NTAPI VirusTotalProcessApiThread( _In_ PVOID Parameter ) { LONG priority; IO_PRIORITY_HINT ioPriority; // TODO: Workqueue support. priority = THREAD_PRIORITY_LOWEST; ioPriority = IoPriorityVeryLow; NtSetInformationThread(NtCurrentThread(), ThreadBasePriority, &priority, sizeof(LONG)); NtSetInformationThread(NtCurrentThread(), ThreadIoPriority, &ioPriority, sizeof(IO_PRIORITY_HINT)); Sleep(10 * 1000); do { ULONG i; INT64 resultLength; PPH_BYTES jsonApiResult = NULL; PVOID jsonArray; PVOID rootJsonObject = NULL; PVOID dataJsonObject; PPH_STRING jsonArrayToSendString = NULL; PPH_LIST resultTempList = NULL; PPH_LIST virusTotalResults = NULL; jsonArray = PhCreateJsonArray(); resultTempList = PhCreateList(30); PhAcquireQueuedLockExclusive(&ProcessListLock); for (i = 0; i < VirusTotalList->Count; i++) { PVIRUSTOTAL_FILE_HASH_ENTRY extension = VirusTotalList->Items[i]; if (resultTempList->Count >= 30) break; if (!extension->Stage1) { extension->Stage1 = TRUE; PhAddItemList(resultTempList, extension); } } PhReleaseQueuedLockExclusive(&ProcessListLock); if (resultTempList->Count == 0) { Sleep(30 * 1000); // Wait 30 seconds goto CleanupExit; } for (i = 0; i < resultTempList->Count; i++) { VirusTotalBuildJsonArray(resultTempList->Items[i], jsonArray); } if (!(jsonArrayToSendString = PhGetJsonArrayString(jsonArray))) goto CleanupExit; if (!(jsonApiResult = VirusTotalSendHttpRequest(PhConvertUtf16ToUtf8(jsonArrayToSendString->Buffer)))) goto CleanupExit; if (!(rootJsonObject = PhCreateJsonParser(jsonApiResult->Buffer))) goto CleanupExit; if (!(dataJsonObject = PhGetJsonObject(rootJsonObject, "data"))) goto CleanupExit; if (!(resultLength = PhGetJsonValueAsLong64(rootJsonObject, "result"))) goto CleanupExit; if (virusTotalResults = VirusTotalJsonToResultList(dataJsonObject)) { for (i = 0; i < virusTotalResults->Count; i++) { PVIRUSTOTAL_API_RESULT result = virusTotalResults->Items[i]; if (result->Found) { PVIRUSTOTAL_FILE_HASH_ENTRY entry = VirusTotalGetCachedResultFromHash(result->FileHash); if (entry && !entry->Processed) { entry->Processed = TRUE; entry->Found = result->Found; entry->Positives = result->Positives; entry->Total = result->Total; if (!FindProcessDbObject(&entry->FileName->sr)) { CreateProcessDbObject( entry->FileName, entry->Positives, entry->Total, result->FileHash ); } } } } } CleanupExit: if (virusTotalResults) { for (i = 0; i < virusTotalResults->Count; i++) { PVIRUSTOTAL_API_RESULT result = virusTotalResults->Items[i]; // PhClearReference(&result->Permalink); // PhClearReference(&result->FileHash); // PhClearReference(&result->DetectionRatio); PhFree(result); } PhDereferenceObject(virusTotalResults); } if (rootJsonObject) { PhFreeJsonParser(rootJsonObject); } if (jsonArrayToSendString) PhDereferenceObject(jsonArrayToSendString); if (jsonArray) { PhFreeJsonParser(jsonArray); } if (jsonApiResult) { PhDereferenceObject(jsonApiResult); } if (resultTempList) { // Re-queue items without any results from VirusTotal. //for (i = 0; i < resultTempList->Count; i++) //{ // PVIRUSTOTAL_FILE_HASH_ENTRY result = resultTempList->Items[i]; // PPROCESS_EXTENSION extension = result->Extension; // // if (extension->Retries > 3) // continue; // // if (PhIsNullOrEmptyString(result->FileResult)) // { // extension->Stage1 = FALSE; // } // // extension->Retries++; //} PhDereferenceObject(resultTempList); } Sleep(5 * 1000); // Wait 5 seconds } while (VirusTotalHandle); return STATUS_SUCCESS; }
ULONG SrvDeviceEvent( IN OUT PCSR_API_MSG m, IN OUT PCSR_REPLY_STATUS ReplyStatus) { NTSTATUS Status = STATUS_SUCCESS; PDEVICEEVENTMSG a = (PDEVICEEVENTMSG)&m->u.ApiMessageData; USERTHREAD_USEDESKTOPINFO utudi; UNREFERENCED_PARAMETER(ReplyStatus); try { // // Set the desktop to the active desktop before sending the // message. // utudi.hThread = NULL; utudi.drdRestore.pdeskRestore = NULL; Status = NtUserSetInformationThread(NtCurrentThread(), UserThreadUseActiveDesktop, &utudi, sizeof(utudi)); if (!NT_SUCCESS(Status)) { #if DBG KdPrint(("--> SrvDeviceEvent: NtUserSetInformationThread failed %d\n", Status)); #endif goto Clean1; } // // Verify the window handle is still valid, if not, let the caller know // so it can be purged from the notification window hand list that the // user-mode pnp manager keeps. // if ((a->hWnd != HWND_BROADCAST) && !IsWindow(a->hWnd)) { Status = STATUS_INVALID_HANDLE; goto Clean0; } if (a->dwFlags) { // // This is a query so we have to send the message but use // timeouts so an app can't stall us forever. // RIPMSG3(RIP_VERBOSE, "--> SrvDeviceEvent: Sending WM_DEVICECHANGE to 0x%x, w 0x%x, l 0x%x", (ULONG_PTR)a->hWnd, a->wParam, a->lParam); if (!SendMessageTimeout(a->hWnd, WM_DEVICECHANGE, a->wParam, a->lParam, SMTO_ABORTIFHUNG | SMTO_NORMAL, PNP_NOTIFY_TIMEOUT, &a->dwResult)) { Status = STATUS_UNSUCCESSFUL; } } else { // // It's not a query so just post it and return, we don't // care what the app returns. // RIPMSG3(RIP_VERBOSE, "--> SrvDeviceEvent: Posting WM_DEVICECHANGE to 0x%x, w 0x%x, l 0x%x", (ULONG_PTR)a->hWnd, a->wParam, a->lParam); if (!PostMessage(a->hWnd, WM_DEVICECHANGE, a->wParam, a->lParam)) { Status = STATUS_UNSUCCESSFUL; } } Clean0: // // Reset this thread's desktop back to NULL before returning. This // decrements the desktop's reference count. // NtUserSetInformationThread(NtCurrentThread(), UserThreadUseDesktop, &utudi, sizeof(utudi)); Clean1: ; } except (EXCEPTION_EXECUTE_HANDLER) { KdPrint(("SrvDeviceEvent generated an exception (%d)\n", GetExceptionCode())); Status = STATUS_UNSUCCESSFUL; } return Status; } // SrvDeviceEvent
NTSTATUS NTAPI NtTerminateThread(IN HANDLE ThreadHandle, IN NTSTATUS ExitStatus) { PETHREAD Thread; PETHREAD CurrentThread = PsGetCurrentThread(); NTSTATUS Status; PAGED_CODE(); PSTRACE(PS_KILL_DEBUG, "ThreadHandle: %p ExitStatus: %d\n", ThreadHandle, ExitStatus); /* Handle the special NULL case */ if (!ThreadHandle) { /* Check if we're the only thread left */ if (PsGetCurrentProcess()->ActiveThreads == 1) { /* This is invalid */ return STATUS_CANT_TERMINATE_SELF; } /* Terminate us directly */ goto TerminateSelf; } else if (ThreadHandle == NtCurrentThread()) { TerminateSelf: /* Terminate this thread */ return PspTerminateThreadByPointer(CurrentThread, ExitStatus, TRUE); } /* We are terminating another thread, get the Thread Object */ Status = ObReferenceObjectByHandle(ThreadHandle, THREAD_TERMINATE, PsThreadType, KeGetPreviousMode(), (PVOID*)&Thread, NULL); if (!NT_SUCCESS(Status)) return Status; /* Check to see if we're running in the same thread */ if (Thread != CurrentThread) { /* Terminate it */ Status = PspTerminateThreadByPointer(Thread, ExitStatus, FALSE); /* Dereference the Thread and return */ ObDereferenceObject(Thread); } else { /* Dereference the thread and terminate ourselves */ ObDereferenceObject(Thread); goto TerminateSelf; } /* Return status */ return Status; }
VOID HandleMediaChangeEvent( UINT uidCdRom ) { /* * Local variables */ HANDLE hDevice; ULONG id; DWORD cb; DWORD dwLogicalDrives; DWORD dwDriveMask; DWORD dwDriveCount; DWORD dwRecipients; BOOL bResult; INT nCurrentTry; NTSTATUS Status; UNICODE_STRING ustrCdRom; UNICODE_STRING ustrCdRomId; UNICODE_STRING ustrAnyCdRom; UNICODE_STRING ustrNtPath; DEV_BROADCAST_VOLUME dbcvInfo; LPWSTR lpszCdRom = TEXT("\\Device\\CdRom"); WCHAR szDrive[] = TEXT("A:\\"); WCHAR szDevice[] = TEXT("\\\\.\\A:"); WCHAR wcDrive; WCHAR szCdRom[32]; WCHAR szBuff[256]; UserAssert(uidCdRom >= 0 && uidCdRom < NUM_MEDIA_EVENTS); // at most 24 cd-rom drives in system /* * Some initializations */ RtlInitUnicodeString( &ustrAnyCdRom, lpszCdRom ); wcDrive = UNICODE_NULL; /* * Form the \Device\CdRomX name based on uidCdRom */ wsprintfW( szCdRom, L"\\Device\\CdRom%d", uidCdRom ); RtlInitUnicodeString( &ustrCdRom, szCdRom ); /* * The uidCdRom parameter tells us which CD-ROM device generated the * MediaChange event. We need to map this device back to it's logical * drive letter because WM_DEVICECHANGE is based on drive letters. * * To avoid always searching all logical drives, we cache the last * associated drive letter. We still need to check this every time * we get notified because WinDisk can remap drive letters. */ if (wcDriveCache[uidCdRom]) { /* * Convert our DOS path name to a NT path name */ ustrNtPath.MaximumLength = sizeof(szBuff); ustrNtPath.Length = 0; ustrNtPath.Buffer = szBuff; bResult = GetDeviceObject(wcDriveCache[uidCdRom], &ustrNtPath); if (bResult) { /* * Check to see if this drive letter is the one that maps * to the CD-ROM drive that just notified us. */ if (RtlEqualUnicodeString(&ustrCdRom, &ustrNtPath, TRUE)) { /* * Yes, we found a match */ wcDrive = wcDriveCache[uidCdRom]; } } } if (!wcDrive) { /* * Either the cache wasn't initialized, or we had a re-mapping * of drive letters. Scan all drive letters looking for CD-ROM * devices and update the cache as we go. */ RtlZeroMemory(wcDriveCache, sizeof(wcDriveCache)); szDrive[0] = L'A'; szDevice[4] = L'A'; dwDriveCount = 26; //Max number of drive letters dwDriveMask = 1; //Max number of drive letters dwLogicalDrives = GetLogicalDrives(); while (dwDriveCount) { /* * Is this logical drive a CD-ROM? */ // // JOHNC - Remove after GetDriveType() is fixed if ((dwLogicalDrives & dwDriveMask) && GetDriveType(szDrive) == DRIVE_CDROM) { /* * For this CD-ROM drive, find it's NT path. */ ustrNtPath.MaximumLength = sizeof(szBuff); ustrNtPath.Length = 0; ustrNtPath.Buffer = szBuff; bResult = GetDeviceObject(szDrive[0], &ustrNtPath); if (bResult) { /* * Make sure the string is in the form \Device\CdRom */ if (RtlPrefixUnicodeString(&ustrAnyCdRom, &ustrNtPath, TRUE)) { /* * Now find it's id. We have a string that looks like * \Device\CdRom??? where ??? is the unit id */ RtlInitUnicodeString(&ustrCdRomId, (PWSTR)((PSTR)(ustrNtPath.Buffer)+ustrAnyCdRom.Length)); RtlUnicodeStringToInteger(&ustrCdRomId, 10, &id); UserAssert(id >= 0 && id < NUM_MEDIA_EVENTS); wcDriveCache[id] = szDrive[0]; //Initially set State to Unknown aDriveState[id] = DS_UNKNOWN; /* * If this is the device that notified us, remember its * drive letter so we can broadcase WM_DEVICECHANGE */ if (uidCdRom == id) { wcDrive = szDrive[0]; } } } } /* * Try the next drive */ szDrive[0] = szDrive[0] + 1; szDevice[4] = szDevice[4] + 1; dwDriveMask <<= 1; --dwDriveCount; } } /* * If we found a logical drive, determine the media state for the drive * and broadcast the WM_DEVICECHANGE notification. */ if (wcDrive) { /* * Get the Media status of this drive. Assume media is not * present in the case of an error. */ szDevice[4] = wcDrive; hDevice = CreateFile(szDevice, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hDevice == INVALID_HANDLE_VALUE) { #ifdef DEBUG KdPrint((" CreateFile( '%ls' ) Failed. Error %lx\n", szDevice,GetLastError())); #endif return; } /* * Loop and check the CD-ROM to see if media is available. We need * this loop because some CD-ROM drives notify us that media has * arrived before the drive has recognized that it had new media. */ for (nCurrentTry = 0; nCurrentTry < MAX_TRIES; nCurrentTry++) { /* * See if media is present */ bResult = (DWORD)DeviceIoControl(hDevice, IOCTL_DISK_CHECK_VERIFY, NULL, 0, NULL, 0, &cb, NULL); if (bResult) { /* * Media is present, change the state to Inserted. */ aDriveState[uidCdRom] = DS_INSERTED; break; } /* * Media wasn't present, so we need to look at GetLastError() to see * if DeviceIoControl() failed. If so we may want to try again. */ if (GetLastError() == ERROR_NOT_READY) { Sleep(500); // 1/2 second /* * We only want to retry if we the prev State was UNKNOWN or * EJECTED. If the previous State was INSERTED it means that * this event is the removal event */ if(aDriveState[uidCdRom]== DS_UNKNOWN || aDriveState[uidCdRom] == DS_EJECTED) { continue; } } /* * Call failed. Assume worst case and say the media has been removed. */ aDriveState[uidCdRom] = DS_EJECTED; break; } /* * Close the handle to the CD-ROM device */ CloseHandle(hDevice); /* * Initialize the structures used for BroadcastSystemMessage */ dbcvInfo.dbcv_size = sizeof(dbcvInfo); dbcvInfo.dbcv_devicetype = DBT_DEVTYP_VOLUME; dbcvInfo.dbcv_reserved = 0; dbcvInfo.dbcv_flags = DBTF_MEDIA; dbcvInfo.dbcv_unitmask = (1 << (wcDrive - L'A')); dwRecipients = BSM_ALLCOMPONENTS | BSM_ALLDESKTOPS; /* * Temporarily we must assign this thread to a desktop so we can * call USER's BroascastSystemMessage() routine. We call the * private SetThreadDesktopToDefault() to assign ourselves to the * desktop that is currently receiving input. */ Status = NtUserSetInformationThread(NtCurrentThread(), UserThreadUseActiveDesktop, NULL, 0); if (NT_SUCCESS(Status)) { /* * Broadcast the message */ BroadcastSystemMessage(BSF_FORCEIFHUNG, &dwRecipients, WM_DEVICECHANGE, // HACK: need to or 0x8000 in wParam // because this is a flag to let // BSM know that lParam is a pointer // to a data structure. 0x8000 | ((bResult) ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE), (LPARAM)&dbcvInfo); #ifdef DEBUG KdPrint((" Message Broadcast for '%lc:'\n", wcDrive)); #endif /* * Set our thread's desktop back to NULL. This will decrement * the desktop's reference count. */ hDevice = NULL; NtUserSetInformationThread(NtCurrentThread(), UserThreadUseDesktop, &hDevice, // hDevice = NULL sizeof(HANDLE)); } } }
/* * SfuAdjustCurrentThreadPriv * * Purpose: * * Impersonate thread and adjust privileges. * */ BOOL SfuAdjustCurrentThreadPriv( PCLIENT_ID SourceThread ) { BOOL cond = FALSE; NTSTATUS status = STATUS_UNSUCCESSFUL; HANDLE hThread = NULL, hToken = NULL; OBJECT_ATTRIBUTES obja; SECURITY_QUALITY_OF_SERVICE SecurityQos; TOKEN_PRIVILEGES *NewState = NULL; ULONG uLen; do { InitializeObjectAttributes(&obja, NULL, 0, NULL, NULL); status = NtOpenThread(&hThread, THREAD_DIRECT_IMPERSONATION, &obja, SourceThread); if (!NT_SUCCESS(status)) break; SecurityQos.Length = sizeof(SecurityQos); SecurityQos.ImpersonationLevel = SecurityImpersonation; SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING; SecurityQos.EffectiveOnly = FALSE; status = NtImpersonateThread(NtCurrentThread(), hThread, &SecurityQos); if (!NT_SUCCESS(status)) break; status = NtOpenThreadTokenEx(NtCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, 0, &hToken); if (!NT_SUCCESS(status)) break; uLen = sizeof(TOKEN_PRIVILEGES) + (6 * sizeof(LUID_AND_ATTRIBUTES)); NewState = RtlAllocateHeap(NtCurrentPeb()->ProcessHeap, HEAP_ZERO_MEMORY, uLen); if (NewState == NULL) break; NewState->PrivilegeCount = 6; NewState->Privileges[0].Luid.LowPart = SE_TCB_PRIVILEGE; NewState->Privileges[0].Luid.HighPart = 0; NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED; NewState->Privileges[1].Luid.LowPart = SE_TAKE_OWNERSHIP_PRIVILEGE; NewState->Privileges[1].Luid.HighPart = 0; NewState->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED; NewState->Privileges[2].Luid.LowPart = SE_RESTORE_PRIVILEGE; NewState->Privileges[2].Luid.HighPart = 0; NewState->Privileges[2].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED; NewState->Privileges[3].Luid.LowPart = SE_DEBUG_PRIVILEGE; NewState->Privileges[3].Luid.HighPart = 0; NewState->Privileges[3].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED; NewState->Privileges[4].Luid.LowPart = SE_LOAD_DRIVER_PRIVILEGE; NewState->Privileges[4].Luid.HighPart = 0; NewState->Privileges[4].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED; NewState->Privileges[5].Luid.LowPart = SE_SECURITY_PRIVILEGE; NewState->Privileges[5].Luid.HighPart = 0; NewState->Privileges[5].Attributes = SE_PRIVILEGE_ENABLED_BY_DEFAULT | SE_PRIVILEGE_ENABLED; status = NtAdjustPrivilegesToken(hToken, FALSE, NewState, 0, NULL, NULL); } while (cond); if (hToken != NULL) NtClose(hToken); if (hThread != NULL) NtClose(hThread); if (NewState != NULL) RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, NewState); return NT_SUCCESS(status); }