NTSTATUS AllocW32Process(IN PEPROCESS Process, OUT PPROCESSINFO* W32Process) { PPROCESSINFO ppiCurrent; TRACE_CH(UserProcess, "In AllocW32Process(0x%p)\n", Process); /* Check that we were not called with an already existing Win32 process info */ ppiCurrent = PsGetProcessWin32Process(Process); if (ppiCurrent) return STATUS_SUCCESS; /* Allocate a new Win32 process info */ ppiCurrent = ExAllocatePoolWithTag(NonPagedPool, sizeof(*ppiCurrent), USERTAG_PROCESSINFO); if (ppiCurrent == NULL) { ERR_CH(UserProcess, "Failed to allocate ppi for PID:0x%lx\n", HandleToUlong(Process->UniqueProcessId)); return STATUS_NO_MEMORY; } TRACE_CH(UserProcess, "Allocated ppi 0x%p for PID:0x%lx\n", ppiCurrent, HandleToUlong(Process->UniqueProcessId)); RtlZeroMemory(ppiCurrent, sizeof(*ppiCurrent)); PsSetProcessWin32Process(Process, ppiCurrent, NULL); IntReferenceProcessInfo(ppiCurrent); *W32Process = ppiCurrent; return STATUS_SUCCESS; }
/* Called from IntDereferenceThreadInfo. */ VOID FASTCALL UserDeleteW32Thread(PTHREADINFO pti) { if (!pti->RefCount) { TRACE_CH(UserThread,"UserDeleteW32Thread pti 0x%p\n",pti); if (pti->hEventQueueClient != NULL) ZwClose(pti->hEventQueueClient); pti->hEventQueueClient = NULL; /* Free the message queue */ if (pti->MessageQueue) { MsqDestroyMessageQueue(pti); } MsqCleanupThreadMsgs(pti); IntSetThreadDesktop(NULL, TRUE); PsSetThreadWin32Thread(pti->pEThread, NULL, pti); ExFreePoolWithTag(pti, USERTAG_THREADINFO); } }
VOID WinLdrScanRegistry(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, IN LPCSTR DirectoryPath) { LONG rc = 0; FRLDRHKEY hGroupKey, hOrderKey, hServiceKey, hDriverKey; LPWSTR GroupNameBuffer; WCHAR ServiceName[256]; ULONG OrderList[128]; ULONG BufferSize; ULONG Index; ULONG TagIndex; LPWSTR GroupName; ULONG ValueSize; ULONG ValueType; ULONG StartValue; ULONG TagValue; WCHAR DriverGroup[256]; ULONG DriverGroupSize; CHAR ImagePath[256]; WCHAR TempImagePath[256]; BOOLEAN Status; /* get 'service group order' key */ rc = RegOpenKey(NULL, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder", &hGroupKey); if (rc != ERROR_SUCCESS) { TRACE_CH(ODYSSEY, "Failed to open the 'ServiceGroupOrder' key (rc %d)\n", (int)rc); return; } /* get 'group order list' key */ rc = RegOpenKey(NULL, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\GroupOrderList", &hOrderKey); if (rc != ERROR_SUCCESS) { TRACE_CH(ODYSSEY, "Failed to open the 'GroupOrderList' key (rc %d)\n", (int)rc); return; } /* enumerate drivers */ rc = RegOpenKey(NULL, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services", &hServiceKey); if (rc != ERROR_SUCCESS) { TRACE_CH(ODYSSEY, "Failed to open the 'Services' key (rc %d)\n", (int)rc); return; } /* Get the Name Group */ BufferSize = 4096; GroupNameBuffer = MmHeapAlloc(BufferSize); rc = RegQueryValue(hGroupKey, L"List", NULL, (PUCHAR)GroupNameBuffer, &BufferSize); TRACE_CH(ODYSSEY, "RegQueryValue(): rc %d\n", (int)rc); if (rc != ERROR_SUCCESS) return; TRACE_CH(ODYSSEY, "BufferSize: %d \n", (int)BufferSize); TRACE_CH(ODYSSEY, "GroupNameBuffer: '%S' \n", GroupNameBuffer); /* Loop through each group */ GroupName = GroupNameBuffer; while (*GroupName) { TRACE("Driver group: '%S'\n", GroupName); /* Query the Order */ BufferSize = sizeof(OrderList); rc = RegQueryValue(hOrderKey, GroupName, NULL, (PUCHAR)OrderList, &BufferSize); if (rc != ERROR_SUCCESS) OrderList[0] = 0; /* enumerate all drivers */ for (TagIndex = 1; TagIndex <= OrderList[0]; TagIndex++) { Index = 0; while (TRUE) { /* Get the Driver's Name */ ValueSize = sizeof(ServiceName); rc = RegEnumKey(hServiceKey, Index, ServiceName, &ValueSize); //TRACE_CH(ODYSSEY, "RegEnumKey(): rc %d\n", (int)rc); /* Makre sure it's valid, and check if we're done */ if (rc == ERROR_NO_MORE_ITEMS) break; if (rc != ERROR_SUCCESS) { MmHeapFree(GroupNameBuffer); return; } //TRACE_CH(ODYSSEY, "Service %d: '%S'\n", (int)Index, ServiceName); /* open driver Key */ rc = RegOpenKey(hServiceKey, ServiceName, &hDriverKey); if (rc == ERROR_SUCCESS) { /* Read the Start Value */ ValueSize = sizeof(ULONG); rc = RegQueryValue(hDriverKey, L"Start", &ValueType, (PUCHAR)&StartValue, &ValueSize); if (rc != ERROR_SUCCESS) StartValue = (ULONG)-1; //TRACE_CH(ODYSSEY, " Start: %x \n", (int)StartValue); /* Read the Tag */ ValueSize = sizeof(ULONG); rc = RegQueryValue(hDriverKey, L"Tag", &ValueType, (PUCHAR)&TagValue, &ValueSize); if (rc != ERROR_SUCCESS) TagValue = (ULONG)-1; //TRACE_CH(ODYSSEY, " Tag: %x \n", (int)TagValue); /* Read the driver's group */ DriverGroupSize = sizeof(DriverGroup); rc = RegQueryValue(hDriverKey, L"Group", NULL, (PUCHAR)DriverGroup, &DriverGroupSize); //TRACE_CH(ODYSSEY, " Group: '%S' \n", DriverGroup); /* Make sure it should be started */ if ((StartValue == 0) && (TagValue == OrderList[TagIndex]) && (_wcsicmp(DriverGroup, GroupName) == 0)) { /* Get the Driver's Location */ ValueSize = sizeof(TempImagePath); rc = RegQueryValue(hDriverKey, L"ImagePath", NULL, (PUCHAR)TempImagePath, &ValueSize); /* Write the whole path if it suceeded, else prepare to fail */ if (rc != ERROR_SUCCESS) { TRACE_CH(ODYSSEY, "ImagePath: not found\n"); TempImagePath[0] = 0; sprintf(ImagePath, "%s\\system32\\drivers\\%S.sys", DirectoryPath, ServiceName); } else if (TempImagePath[0] != L'\\') { sprintf(ImagePath, "%s%S", DirectoryPath, TempImagePath); } else { sprintf(ImagePath, "%S", TempImagePath); TRACE_CH(ODYSSEY, "ImagePath: '%s'\n", ImagePath); } TRACE("Adding boot driver: '%s'\n", ImagePath); Status = WinLdrAddDriverToList(&LoaderBlock->BootDriverListHead, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\", TempImagePath, ServiceName); if (!Status) ERR("Failed to add boot driver\n"); } else { //TRACE(" Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current Tag %d, current group '%S')\n", // ServiceName, StartValue, TagValue, DriverGroup, OrderList[TagIndex], GroupName); } } Index++; } } Index = 0; while (TRUE) { /* Get the Driver's Name */ ValueSize = sizeof(ServiceName); rc = RegEnumKey(hServiceKey, Index, ServiceName, &ValueSize); //TRACE_CH(ODYSSEY, "RegEnumKey(): rc %d\n", (int)rc); if (rc == ERROR_NO_MORE_ITEMS) break; if (rc != ERROR_SUCCESS) { MmHeapFree(GroupNameBuffer); return; } //TRACE_CH(ODYSSEY, "Service %d: '%S'\n", (int)Index, ServiceName); /* open driver Key */ rc = RegOpenKey(hServiceKey, ServiceName, &hDriverKey); if (rc == ERROR_SUCCESS) { /* Read the Start Value */ ValueSize = sizeof(ULONG); rc = RegQueryValue(hDriverKey, L"Start", &ValueType, (PUCHAR)&StartValue, &ValueSize); if (rc != ERROR_SUCCESS) StartValue = (ULONG)-1; //TRACE_CH(ODYSSEY, " Start: %x \n", (int)StartValue); /* Read the Tag */ ValueSize = sizeof(ULONG); rc = RegQueryValue(hDriverKey, L"Tag", &ValueType, (PUCHAR)&TagValue, &ValueSize); if (rc != ERROR_SUCCESS) TagValue = (ULONG)-1; //TRACE_CH(ODYSSEY, " Tag: %x \n", (int)TagValue); /* Read the driver's group */ DriverGroupSize = sizeof(DriverGroup); rc = RegQueryValue(hDriverKey, L"Group", NULL, (PUCHAR)DriverGroup, &DriverGroupSize); //TRACE_CH(ODYSSEY, " Group: '%S' \n", DriverGroup); for (TagIndex = 1; TagIndex <= OrderList[0]; TagIndex++) { if (TagValue == OrderList[TagIndex]) break; } if ((StartValue == 0) && (TagIndex > OrderList[0]) && (_wcsicmp(DriverGroup, GroupName) == 0)) { ValueSize = sizeof(TempImagePath); rc = RegQueryValue(hDriverKey, L"ImagePath", NULL, (PUCHAR)TempImagePath, &ValueSize); if (rc != ERROR_SUCCESS) { TRACE_CH(ODYSSEY, "ImagePath: not found\n"); TempImagePath[0] = 0; sprintf(ImagePath, "%ssystem32\\drivers\\%S.sys", DirectoryPath, ServiceName); } else if (TempImagePath[0] != L'\\') { sprintf(ImagePath, "%s%S", DirectoryPath, TempImagePath); } else { sprintf(ImagePath, "%S", TempImagePath); TRACE_CH(ODYSSEY, "ImagePath: '%s'\n", ImagePath); } TRACE(" Adding boot driver: '%s'\n", ImagePath); Status = WinLdrAddDriverToList(&LoaderBlock->BootDriverListHead, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\", TempImagePath, ServiceName); if (!Status) ERR(" Failed to add boot driver\n"); } else { //TRACE(" Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current group '%S')\n", // ServiceName, StartValue, TagValue, DriverGroup, GroupName); } } Index++; } /* Move to the next group name */ GroupName = GroupName + wcslen(GroupName) + 1; } /* Free allocated memory */ MmHeapFree(GroupNameBuffer); }
NTSTATUS APIENTRY Win32kProcessCallback(struct _EPROCESS *Process, BOOLEAN Create) { PPROCESSINFO ppiCurrent, *pppi; NTSTATUS Status; ASSERT(Process->Peb); UserEnterExclusive(); if (Create) { SIZE_T ViewSize = 0; LARGE_INTEGER Offset; PVOID UserBase = NULL; PRTL_USER_PROCESS_PARAMETERS pParams = Process->Peb->ProcessParameters; /* We might be called with an already allocated win32 process */ ppiCurrent = PsGetProcessWin32Process(Process); if (ppiCurrent != NULL) { /* There is no more to do for us (this is a success code!) */ Status = STATUS_ALREADY_WIN32; goto Leave; } /* Allocate a new win32 process */ ppiCurrent = ExAllocatePoolWithTag(NonPagedPool, sizeof(PROCESSINFO), USERTAG_PROCESSINFO); if (ppiCurrent == NULL) { ERR_CH(UserProcess, "Failed to allocate ppi for PID:0x%lx\n", HandleToUlong(Process->UniqueProcessId)); Status = STATUS_NO_MEMORY; goto Leave; } RtlZeroMemory(ppiCurrent, sizeof(PROCESSINFO)); PsSetProcessWin32Process(Process, ppiCurrent, NULL); #if DBG DbgInitDebugChannels(); #if KDBG KdRosRegisterCliCallback(DbgGdiKdbgCliCallback); #endif #endif TRACE_CH(UserProcess,"Allocated ppi 0x%p for PID:0x%lx\n", ppiCurrent, HandleToUlong(Process->UniqueProcessId)); /* map the global heap into the process */ Offset.QuadPart = 0; Status = MmMapViewOfSection(GlobalUserHeapSection, PsGetCurrentProcess(), &UserBase, 0, 0, &Offset, &ViewSize, ViewUnmap, SEC_NO_CHANGE, PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */ if (!NT_SUCCESS(Status)) { TRACE_CH(UserProcess,"Failed to map the global heap! 0x%x\n", Status); goto Leave; } ppiCurrent->HeapMappings.Next = NULL; ppiCurrent->HeapMappings.KernelMapping = (PVOID)GlobalUserHeap; ppiCurrent->HeapMappings.UserMapping = UserBase; ppiCurrent->HeapMappings.Count = 1; InitializeListHead(&ppiCurrent->MenuListHead); InitializeListHead(&ppiCurrent->GDIBrushAttrFreeList); InitializeListHead(&ppiCurrent->GDIDcAttrFreeList); InitializeListHead(&ppiCurrent->PrivateFontListHead); ExInitializeFastMutex(&ppiCurrent->PrivateFontListLock); InitializeListHead(&ppiCurrent->DriverObjListHead); ExInitializeFastMutex(&ppiCurrent->DriverObjListLock); ppiCurrent->KeyboardLayout = W32kGetDefaultKeyLayout(); if (!EngCreateEvent((PEVENT *)&ppiCurrent->InputIdleEvent)) { KeBugCheck(0); } KeInitializeEvent(ppiCurrent->InputIdleEvent, NotificationEvent, FALSE); /* map the gdi handle table to user land */ Process->Peb->GdiSharedHandleTable = GDI_MapHandleTable(Process); Process->Peb->GdiDCAttributeList = GDI_BATCH_LIMIT; pParams = Process->Peb->ProcessParameters; ppiCurrent->peProcess = Process; /* setup process flags */ ppiCurrent->W32PF_flags = W32PF_THREADCONNECTED; if ( pParams && pParams->WindowFlags & STARTF_SCRNSAVER ) { ppiScrnSaver = ppiCurrent; ppiCurrent->W32PF_flags |= W32PF_SCREENSAVER; } // Fixme check if this process is allowed. ppiCurrent->W32PF_flags |= W32PF_ALLOWFOREGROUNDACTIVATE; // Starting application it will get toggled off. /* Create pools for GDI object attributes */ ppiCurrent->pPoolDcAttr = GdiPoolCreate(sizeof(DC_ATTR), 'acdG'); ppiCurrent->pPoolBrushAttr = GdiPoolCreate(sizeof(BRUSH_ATTR), 'arbG'); ppiCurrent->pPoolRgnAttr = GdiPoolCreate(sizeof(RGN_ATTR), 'agrG'); ASSERT(ppiCurrent->pPoolDcAttr); ASSERT(ppiCurrent->pPoolBrushAttr); ASSERT(ppiCurrent->pPoolRgnAttr); /* Add the process to the global list */ ppiCurrent->ppiNext = gppiList; gppiList = ppiCurrent; } else { /* Get the Win32 Process */ ppiCurrent = PsGetProcessWin32Process(Process); ASSERT(ppiCurrent); TRACE_CH(UserProcess, "Destroying ppi 0x%p\n", ppiCurrent); ppiCurrent->W32PF_flags |= W32PF_TERMINATED; if (ppiScrnSaver == ppiCurrent) ppiScrnSaver = NULL; if (ppiCurrent->InputIdleEvent) { EngFreeMem(ppiCurrent->InputIdleEvent); ppiCurrent->InputIdleEvent = NULL; } IntCleanupMenus(Process, ppiCurrent); IntCleanupCurIcons(Process, ppiCurrent); GDI_CleanupForProcess(Process); co_IntGraphicsCheck(FALSE); /* * Deregister logon application automatically */ if(LogonProcess == ppiCurrent) { LogonProcess = NULL; } /* Close the startup desktop */ if(ppiCurrent->rpdeskStartup) ObDereferenceObject(ppiCurrent->rpdeskStartup); if(ppiCurrent->hdeskStartup) ZwClose(ppiCurrent->hdeskStartup); /* Close the current window station */ UserSetProcessWindowStation(NULL); /* Destroy GDI pools */ GdiPoolDestroy(ppiCurrent->pPoolDcAttr); GdiPoolDestroy(ppiCurrent->pPoolBrushAttr); GdiPoolDestroy(ppiCurrent->pPoolRgnAttr); if (gppiInputProvider == ppiCurrent) gppiInputProvider = NULL; pppi = &gppiList; while (*pppi != NULL && *pppi != ppiCurrent) pppi = &(*pppi)->ppiNext; ASSERT(*pppi == ppiCurrent); *pppi = ppiCurrent->ppiNext; TRACE_CH(UserProcess,"Freeing ppi 0x%p\n", ppiCurrent); #if DBG if (DBG_IS_CHANNEL_ENABLED(ppiCurrent, DbgChUserObj, WARN_LEVEL)) { DbgUserDumpHandleTable(); } #endif /* Free the PROCESSINFO */ PsSetProcessWin32Process(Process, NULL, ppiCurrent); ExFreePoolWithTag(ppiCurrent, USERTAG_PROCESSINFO); } Status = STATUS_SUCCESS; Leave: UserLeave(); return Status; }
NTSTATUS NTAPI UserDestroyThreadInfo(struct _ETHREAD *Thread) { PTHREADINFO *ppti; PSINGLE_LIST_ENTRY psle; PPROCESSINFO ppiCurrent; struct _EPROCESS *Process; PTHREADINFO ptiCurrent; Process = Thread->ThreadsProcess; /* Get the Win32 Thread */ ptiCurrent = PsGetThreadWin32Thread(Thread); ASSERT(ptiCurrent); TRACE_CH(UserThread,"Destroying pti 0x%p eThread 0x%p\n", ptiCurrent, Thread); ptiCurrent->TIF_flags |= TIF_INCLEANUP; ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; ppiCurrent = ptiCurrent->ppi; ASSERT(ppiCurrent); IsRemoveAttachThread(ptiCurrent); ptiCurrent->TIF_flags |= TIF_DONTATTACHQUEUE; ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; /* Decrement thread count and check if its 0 */ ppiCurrent->cThreads--; if(ptiCurrent->TIF_flags & TIF_GUITHREADINITIALIZED) { /* Do now some process cleanup that requires a valid win32 thread */ if(ptiCurrent->ppi->cThreads == 0) { /* Check if we have registered the user api hook */ if(ptiCurrent->ppi == ppiUahServer) { /* Unregister the api hook */ UserUnregisterUserApiHook(); } /* Notify logon application to restart shell if needed */ if(ptiCurrent->pDeskInfo) { if(ptiCurrent->pDeskInfo->ppiShellProcess == ppiCurrent) { DWORD ExitCode = PsGetProcessExitStatus(Process); TRACE_CH(UserProcess, "Shell process is exiting (%lu)\n", ExitCode); UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_SHELL_EXITED, ExitCode); ptiCurrent->pDeskInfo->ppiShellProcess = NULL; } } } DceFreeThreadDCE(ptiCurrent); HOOK_DestroyThreadHooks(Thread); EVENT_DestroyThreadEvents(Thread); DestroyTimersForThread(ptiCurrent); KeSetEvent(ptiCurrent->pEventQueueServer, IO_NO_INCREMENT, FALSE); UnregisterThreadHotKeys(ptiCurrent); /* if (IsListEmpty(&ptiCurrent->WindowListHead)) { ERR_CH(UserThread,"Thread Window List is Empty!\n"); } */ co_DestroyThreadWindows(Thread); if (ppiCurrent && ppiCurrent->ptiList == ptiCurrent && !ptiCurrent->ptiSibling && ppiCurrent->W32PF_flags & W32PF_CLASSESREGISTERED) { TRACE_CH(UserThread,"DestroyProcessClasses\n"); /* no process windows should exist at this point, or the function will assert! */ DestroyProcessClasses(ppiCurrent); ppiCurrent->W32PF_flags &= ~W32PF_CLASSESREGISTERED; } IntBlockInput(ptiCurrent, FALSE); IntCleanupThreadCallbacks(ptiCurrent); /* cleanup user object references stack */ psle = PopEntryList(&ptiCurrent->ReferencesList); while (psle) { PUSER_REFERENCE_ENTRY ref = CONTAINING_RECORD(psle, USER_REFERENCE_ENTRY, Entry); TRACE_CH(UserThread,"thread clean: remove reference obj 0x%p\n",ref->obj); UserDereferenceObject(ref->obj); psle = PopEntryList(&ptiCurrent->ReferencesList); } } /* Find the THREADINFO in the PROCESSINFO's list */ ppti = &ppiCurrent->ptiList; while (*ppti != NULL && *ppti != ptiCurrent) { ppti = &((*ppti)->ptiSibling); } /* we must have found it */ ASSERT(*ppti == ptiCurrent); /* Remove it from the list */ *ppti = ptiCurrent->ptiSibling; if (ptiCurrent->KeyboardLayout) UserDereferenceObject(ptiCurrent->KeyboardLayout); if (gptiForeground == ptiCurrent) { // IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0); // IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, NULL, OBJID_WINDOW, CHILDID_SELF, 0); gptiForeground = NULL; } // Fixes CORE-6384 & CORE-7030. /* if (ptiLastInput == ptiCurrent) { if (!ppiCurrent->ptiList) ptiLastInput = gptiForeground; else ptiLastInput = ppiCurrent->ptiList; ERR_CH(UserThread,"DTI: ptiLastInput is Cleared!!\n"); } */ TRACE_CH(UserThread,"Freeing pti 0x%p\n", ptiCurrent); /* Free the THREADINFO */ IntDereferenceThreadInfo(ptiCurrent); return STATUS_SUCCESS; }
NTSTATUS NTAPI UserCreateThreadInfo(struct _ETHREAD *Thread) { struct _EPROCESS *Process; PCLIENTINFO pci; PTHREADINFO ptiCurrent; int i; NTSTATUS Status = STATUS_SUCCESS; PTEB pTeb; LARGE_INTEGER LargeTickCount; Process = Thread->ThreadsProcess; pTeb = NtCurrentTeb(); ASSERT(pTeb); ptiCurrent = ExAllocatePoolWithTag(NonPagedPool, sizeof(THREADINFO), USERTAG_THREADINFO); if (ptiCurrent == NULL) { ERR_CH(UserThread, "Failed to allocate pti for TID %p\n", Thread->Cid.UniqueThread); return STATUS_NO_MEMORY; } TRACE_CH(UserThread,"Create pti 0x%p eThread 0x%p\n", ptiCurrent, Thread); RtlZeroMemory(ptiCurrent, sizeof(THREADINFO)); /* Initialize the THREADINFO */ PsSetThreadWin32Thread(Thread, ptiCurrent, NULL); IntReferenceThreadInfo(ptiCurrent); ptiCurrent->pEThread = Thread; ptiCurrent->ppi = PsGetCurrentProcessWin32Process(); pTeb->Win32ThreadInfo = ptiCurrent; ptiCurrent->pClientInfo = (PCLIENTINFO)pTeb->Win32ClientInfo; TRACE_CH(UserThread, "Allocated pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread); InitializeListHead(&ptiCurrent->WindowListHead); InitializeListHead(&ptiCurrent->W32CallbackListHead); InitializeListHead(&ptiCurrent->PostedMessagesListHead); InitializeListHead(&ptiCurrent->SentMessagesListHead); InitializeListHead(&ptiCurrent->DispatchingMessagesHead); InitializeListHead(&ptiCurrent->LocalDispatchingMessagesHead); InitializeListHead(&ptiCurrent->PtiLink); for (i = 0; i < NB_HOOKS; i++) { InitializeListHead(&ptiCurrent->aphkStart[i]); } ptiCurrent->ptiSibling = ptiCurrent->ppi->ptiList; ptiCurrent->ppi->ptiList = ptiCurrent; ptiCurrent->ppi->cThreads++; ptiCurrent->hEventQueueClient = NULL; Status = ZwCreateEvent(&ptiCurrent->hEventQueueClient, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); if (!NT_SUCCESS(Status)) { goto error; } Status = ObReferenceObjectByHandle(ptiCurrent->hEventQueueClient, 0, *ExEventObjectType, KernelMode, (PVOID*)&ptiCurrent->pEventQueueServer, NULL); if (!NT_SUCCESS(Status)) { ZwClose(ptiCurrent->hEventQueueClient); ptiCurrent->hEventQueueClient = NULL; goto error; } KeQueryTickCount(&LargeTickCount); ptiCurrent->timeLast = LargeTickCount.u.LowPart; ptiCurrent->MessageQueue = MsqCreateMessageQueue(ptiCurrent); if(ptiCurrent->MessageQueue == NULL) { ERR_CH(UserThread,"Failed to allocate message loop\n"); Status = STATUS_NO_MEMORY; goto error; } ptiCurrent->KeyboardLayout = W32kGetDefaultKeyLayout(); if (ptiCurrent->KeyboardLayout) UserReferenceObject(ptiCurrent->KeyboardLayout); ptiCurrent->TIF_flags &= ~TIF_INCLEANUP; if (Process == gpepCSRSS) /* If this thread is owned by CSRSS, mark it as such */ ptiCurrent->TIF_flags |= TIF_CSRSSTHREAD; ptiCurrent->pcti = &ptiCurrent->cti; /* Initialize the CLIENTINFO */ pci = (PCLIENTINFO)pTeb->Win32ClientInfo; RtlZeroMemory(pci, sizeof(CLIENTINFO)); pci->ppi = ptiCurrent->ppi; pci->fsHooks = ptiCurrent->fsHooks; pci->dwTIFlags = ptiCurrent->TIF_flags; if (ptiCurrent->KeyboardLayout) { pci->hKL = ptiCurrent->KeyboardLayout->hkl; pci->CodePage = ptiCurrent->KeyboardLayout->CodePage; } /* Assign a default window station and desktop to the process */ /* Do not try to open a desktop or window station before winlogon initializes */ if(ptiCurrent->ppi->hdeskStartup == NULL && LogonProcess != NULL) { HWINSTA hWinSta = NULL; HDESK hDesk = NULL; UNICODE_STRING DesktopPath; PDESKTOP pdesk; PRTL_USER_PROCESS_PARAMETERS ProcessParams; /* * inherit the thread desktop and process window station (if not yet inherited) from the process startup * info structure. See documentation of CreateProcess() */ ProcessParams = pTeb->ProcessEnvironmentBlock->ProcessParameters; Status = STATUS_UNSUCCESSFUL; if(ProcessParams && ProcessParams->DesktopInfo.Length > 0) { Status = IntSafeCopyUnicodeStringTerminateNULL(&DesktopPath, &ProcessParams->DesktopInfo); } if(!NT_SUCCESS(Status)) { RtlInitUnicodeString(&DesktopPath, NULL); } Status = IntParseDesktopPath(Process, &DesktopPath, &hWinSta, &hDesk); if (DesktopPath.Buffer) ExFreePoolWithTag(DesktopPath.Buffer, TAG_STRING); if(!NT_SUCCESS(Status)) { ERR_CH(UserThread, "Failed to assign default dekstop and winsta to process\n"); goto error; } if(!UserSetProcessWindowStation(hWinSta)) { Status = STATUS_UNSUCCESSFUL; ERR_CH(UserThread,"Failed to set initial process winsta\n"); goto error; } /* Validate the new desktop. */ Status = IntValidateDesktopHandle(hDesk, UserMode, 0, &pdesk); if(!NT_SUCCESS(Status)) { ERR_CH(UserThread,"Failed to validate initial desktop handle\n"); goto error; } /* Store the parsed desktop as the initial desktop */ ptiCurrent->ppi->hdeskStartup = hDesk; ptiCurrent->ppi->rpdeskStartup = pdesk; } if (ptiCurrent->ppi->hdeskStartup != NULL) { if (!IntSetThreadDesktop(ptiCurrent->ppi->hdeskStartup, FALSE)) { ERR_CH(UserThread,"Failed to set thread desktop\n"); Status = STATUS_UNSUCCESSFUL; goto error; } } /* mark the thread as fully initialized */ ptiCurrent->TIF_flags |= TIF_GUITHREADINITIALIZED; if (!(ptiCurrent->ppi->W32PF_flags & (W32PF_ALLOWFOREGROUNDACTIVATE | W32PF_APPSTARTING)) && (gptiForeground && gptiForeground->ppi == ptiCurrent->ppi )) { ptiCurrent->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE; } ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags; TRACE_CH(UserThread,"UserCreateW32Thread pti 0x%p\n",ptiCurrent); return STATUS_SUCCESS; error: ERR_CH(UserThread,"UserCreateThreadInfo failed! Freeing pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread); UserDestroyThreadInfo(Thread); return Status; }