NTSTATUS IniCacheLoad( PINICACHE *Cache, PWCHAR FileName, BOOLEAN String) { UNICODE_STRING Name; OBJECT_ATTRIBUTES ObjectAttributes; FILE_STANDARD_INFORMATION FileInfo; IO_STATUS_BLOCK IoStatusBlock; HANDLE FileHandle; NTSTATUS Status; PCHAR FileBuffer; ULONG FileLength; PCHAR Ptr; LARGE_INTEGER FileOffset; PINICACHESECTION Section; PINICACHEKEY Key; PCHAR SectionName; ULONG SectionNameSize; PCHAR KeyName; ULONG KeyNameSize; PCHAR KeyValue; ULONG KeyValueSize; *Cache = NULL; /* Open ini file */ RtlInitUnicodeString(&Name, FileName); InitializeObjectAttributes(&ObjectAttributes, &Name, 0, NULL, NULL); Status = NtOpenFile(&FileHandle, GENERIC_READ | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE); if (!NT_SUCCESS(Status)) { DPRINT("NtOpenFile() failed (Status %lx)\n", Status); return Status; } DPRINT("NtOpenFile() successful\n"); /* Query file size */ Status = NtQueryInformationFile(FileHandle, &IoStatusBlock, &FileInfo, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation); if (!NT_SUCCESS(Status)) { DPRINT("NtQueryInformationFile() failed (Status %lx)\n", Status); NtClose(FileHandle); return Status; } FileLength = FileInfo.EndOfFile.u.LowPart; DPRINT("File size: %lu\n", FileLength); /* Allocate file buffer */ FileBuffer = (CHAR*)RtlAllocateHeap(ProcessHeap, 0, FileLength + 1); if (FileBuffer == NULL) { DPRINT1("RtlAllocateHeap() failed\n"); NtClose(FileHandle); return STATUS_INSUFFICIENT_RESOURCES; } /* Read file */ FileOffset.QuadPart = 0ULL; Status = NtReadFile(FileHandle, NULL, NULL, NULL, &IoStatusBlock, FileBuffer, FileLength, &FileOffset, NULL); /* Append string terminator */ FileBuffer[FileLength] = 0; NtClose(FileHandle); if (!NT_SUCCESS(Status)) { DPRINT("NtReadFile() failed (Status %lx)\n", Status); RtlFreeHeap(ProcessHeap, 0, FileBuffer); return Status; } /* Allocate inicache header */ *Cache = (PINICACHE)RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(INICACHE)); if (*Cache == NULL) { DPRINT("RtlAllocateHeap() failed\n"); return STATUS_INSUFFICIENT_RESOURCES; } /* Parse ini file */ Section = NULL; Ptr = FileBuffer; while (Ptr != NULL && *Ptr != 0) { Ptr = IniCacheSkipWhitespace(Ptr); if (Ptr == NULL) continue; if (*Ptr == '[') { Section = NULL; Ptr++; Ptr = IniCacheGetSectionName(Ptr, &SectionName, &SectionNameSize); DPRINT1("[%.*s]\n", SectionNameSize, SectionName); Section = IniCacheAddSection(*Cache, SectionName, SectionNameSize); if (Section == NULL) { DPRINT("IniCacheAddSection() failed\n"); Ptr = IniCacheSkipToNextSection(Ptr); continue; } } else { if (Section == NULL) { Ptr = IniCacheSkipToNextSection(Ptr); continue; } Ptr = IniCacheGetKeyName(Ptr, &KeyName, &KeyNameSize); Ptr = IniCacheGetKeyValue(Ptr, &KeyValue, &KeyValueSize, String); DPRINT1("'%.*s' = '%.*s'\n", KeyNameSize, KeyName, KeyValueSize, KeyValue); Key = IniCacheAddKey(Section, KeyName, KeyNameSize, KeyValue, KeyValueSize); if (Key == NULL) { DPRINT("IniCacheAddKey() failed\n"); } } } /* Free file buffer */ RtlFreeHeap(ProcessHeap, 0, FileBuffer); return Status; }
UINT64 GetDirectoryAllocationSizeInternal(OBJECT_ATTRIBUTES ObjectAttributes, std::map<UINT64, DWORD>& FileMap) { HANDLE hFile; //OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(OBJECT_ATTRIBUTES), hRootDir, (UNICODE_STRING*)&FileName, OBJ_CASE_INSENSITIVE }; IO_STATUS_BLOCK IoStatusBlock; auto Status = NtOpenFile(&hFile, SYNCHRONIZE | FILE_LIST_DIRECTORY, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_VALID_FLAGS, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); if (Status) return 0; UINT64 Space = 0; byte Buffer[sizeof(FILE_FULL_DIR_INFORMATION) + 512]; FILE_FULL_DIR_INFORMATION & FileInfo = *(FILE_FULL_DIR_INFORMATION *)Buffer; UNICODE_STRING TempFileName = { 0,0,FileInfo.FileName }; Status = -1; ObjectAttributes.RootDirectory = hFile; ObjectAttributes.ObjectName = &TempFileName; FILE_STANDARD_INFORMATION FileStandardInfo; FILE_INTERNAL_INFORMATION FileInternalInfo; while (ZwQueryDirectoryFile(hFile, NULL, NULL, NULL, &IoStatusBlock, Buffer, sizeof(Buffer), FileFullDirectoryInformation, -1, NULL, 0) == ERROR_SUCCESS) { TempFileName.Length = TempFileName.MaximumLength = FileInfo.FileNameLength; if (FileInfo.FileAttributes&FILE_ATTRIBUTE_DIRECTORY) { if (FileInfo.FileAttributes&FILE_ATTRIBUTE_REPARSE_POINT) { if (IsReparseTagNameSurrogate(FileInfo.EaSize)) continue; } else { if (IsDots(FileInfo.FileName, FileInfo.FileNameLength)) continue; } Space += GetDirectoryAllocationSizeInternal(ObjectAttributes, FileMap); } else { if (NtGetFileId(&ObjectAttributes, &FileStandardInfo, &FileInternalInfo)) continue; if (FileStandardInfo.NumberOfLinks != 1) { auto T = FileMap.insert(std::pair<UINT64, DWORD>(FileInternalInfo.IndexNumber.QuadPart, FileStandardInfo.NumberOfLinks)).first; if (--(T->second)) continue; } Space += FileInfo.AllocationSize.QuadPart; } } NtClose(hFile); return Space; }
static NTSTATUS NTAPI GuiInitFrontEnd(IN OUT PFRONTEND This, IN PCONSRV_CONSOLE Console) { PGUI_INIT_INFO GuiInitInfo; PGUI_CONSOLE_DATA GuiData; if (This == NULL || Console == NULL || This->Context2 == NULL) return STATUS_INVALID_PARAMETER; ASSERT(This->Console == Console); GuiInitInfo = This->Context2; /* Terminal data allocation */ GuiData = ConsoleAllocHeap(HEAP_ZERO_MEMORY, sizeof(*GuiData)); if (!GuiData) { DPRINT1("CONSRV: Failed to create GUI_CONSOLE_DATA\n"); return STATUS_UNSUCCESSFUL; } /// /* HACK */ Console->FrontEndIFace.Context = (PVOID)GuiData; /* HACK */ GuiData->Console = Console; GuiData->ActiveBuffer = Console->ActiveBuffer; GuiData->hWindow = NULL; GuiData->IsWindowVisible = GuiInitInfo->IsWindowVisible; /* The console can be resized */ Console->FixedSize = FALSE; InitializeCriticalSection(&GuiData->Lock); /* * Set up GUI data */ RtlCopyMemory(&GuiData->GuiInfo, &GuiInitInfo->TermInfo, sizeof(GuiInitInfo->TermInfo)); /* Initialize the icon handles */ if (GuiInitInfo->hIcon != NULL) GuiData->hIcon = GuiInitInfo->hIcon; else GuiData->hIcon = ghDefaultIcon; if (GuiInitInfo->hIconSm != NULL) GuiData->hIconSm = GuiInitInfo->hIconSm; else GuiData->hIconSm = ghDefaultIconSm; ASSERT(GuiData->hIcon && GuiData->hIconSm); /* Mouse is shown by default with its default cursor shape */ GuiData->hCursor = ghDefaultCursor; GuiData->MouseCursorRefCount = 0; /* A priori don't ignore mouse signals */ GuiData->IgnoreNextMouseSignal = FALSE; /* Initialize HACK FOR CORE-8394. See conwnd.c!OnMouse for more details. */ GuiData->HackCORE8394IgnoreNextMove = FALSE; /* Close button and the corresponding system menu item are enabled by default */ GuiData->IsCloseButtonEnabled = TRUE; /* There is no user-reserved menu id range by default */ GuiData->CmdIdLow = GuiData->CmdIdHigh = 0; /* Initialize the selection */ RtlZeroMemory(&GuiData->Selection, sizeof(GuiData->Selection)); GuiData->Selection.dwFlags = CONSOLE_NO_SELECTION; RtlZeroMemory(&GuiData->dwSelectionCursor, sizeof(GuiData->dwSelectionCursor)); GuiData->LineSelection = FALSE; // Default to block selection // TODO: Retrieve the selection mode via the registry. GuiData->InputThreadId = GuiInitInfo->InputThreadId; GuiData->WinSta = GuiInitInfo->WinSta; GuiData->Desktop = GuiInitInfo->Desktop; /* Finally, finish to initialize the frontend structure */ This->Context = GuiData; ConsoleFreeHeap(This->Context2); This->Context2 = NULL; /* * We need to wait until the GUI has been fully initialized * to retrieve custom settings i.e. WindowSize etc... * Ideally we could use SendNotifyMessage for this but its not * yet implemented. */ NtCreateEvent(&GuiData->hGuiInitEvent, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); NtCreateEvent(&GuiData->hGuiTermEvent, EVENT_ALL_ACCESS, NULL, SynchronizationEvent, FALSE); DPRINT("GUI - Checkpoint\n"); /* Create the terminal window */ PostThreadMessageW(GuiData->InputThreadId, PM_CREATE_CONSOLE, 0, (LPARAM)GuiData); /* Wait until initialization has finished */ NtWaitForSingleObject(GuiData->hGuiInitEvent, FALSE, NULL); DPRINT("OK we created the console window\n"); NtClose(GuiData->hGuiInitEvent); GuiData->hGuiInitEvent = NULL; /* Check whether we really succeeded in initializing the terminal window */ if (GuiData->hWindow == NULL) { DPRINT("GuiInitConsole - We failed at creating a new terminal window\n"); GuiDeinitFrontEnd(This); return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; }
NTSTATUS LeGlobalData::Initialize() { BOOL IsLoader; PLEPEB LePeb; PLDR_MODULE Ntdll; PPEB_BASE Peb; NTSTATUS Status; NLSTABLEINFO NlsTableInfo; UNICODE_STRING SystemDirectory, NlsFileName, OemNlsFileName, LangFileName; PKEY_VALUE_PARTIAL_INFORMATION IndexValue; IsLoader = IsLeLoader(); Wow64 = Ps::IsWow64Process(); Ntdll = GetNtdllLdrModule(); LOOP_ONCE { LePeb = OpenOrCreateLePeb(); if (LePeb == nullptr) { ULONG_PTR DefaultACPLength, DefaultLCIDLength, DefaultOEMCPLength; WCHAR DefaultACP[0x20], DefaultOEMCP[0x20], DefaultLCID[0x20]; PVOID ReloadedNtdll; PUNICODE_STRING FullDllName; LePeb = GetLePeb(); InitDefaultLeb(&LePeb->Leb); FullDllName = &FindLdrModuleByHandle(&__ImageBase)->FullDllName; CopyMemory(LePeb->LeDllFullPath, FullDllName->Buffer, FullDllName->Length + sizeof(WCHAR)); Status = LoadPeImage(Ntdll->FullDllName.Buffer, &ReloadedNtdll, nullptr, LOAD_PE_IGNORE_RELOC); if (NT_SUCCESS(Status)) { PVOID LdrLoadDllAddress; LdrLoadDllAddress = LookupExportTable(ReloadedNtdll, NTDLL_LdrLoadDll); LePeb->LdrLoadDllAddress = PtrAdd(LdrLoadDllAddress, PtrOffset(Ntdll->DllBase, ReloadedNtdll)); CopyMemory(LePeb->LdrLoadDllBackup, LdrLoadDllAddress, LDR_LOAD_DLL_BACKUP_SIZE); LePeb->LdrLoadDllBackupSize = LDR_LOAD_DLL_BACKUP_SIZE; UnloadPeImage(ReloadedNtdll); } DefaultACPLength = (swprintf(DefaultACP, L"%d", LePeb->Leb.AnsiCodePage) + 1) * sizeof(WCHAR); DefaultOEMCPLength = (swprintf(DefaultOEMCP, L"%d", LePeb->Leb.OemCodePage) + 1) * sizeof(WCHAR); DefaultLCIDLength = (swprintf(DefaultLCID, L"%d", LePeb->Leb.LocaleID) + 1) * sizeof(WCHAR); REGISTRY_REDIRECTION_ENTRY64 *Entry, Entries[] = { { { (ULONG64)HKEY_LOCAL_MACHINE, USTR64(REGPATH_CODEPAGE), USTR64(REGKEY_ACP), REG_SZ, }, { (ULONG64)HKEY_LOCAL_MACHINE, USTR64(REGPATH_CODEPAGE), USTR64(REGKEY_ACP), REG_SZ, DefaultACP, DefaultACPLength }, }, { { (ULONG64)HKEY_LOCAL_MACHINE, USTR64(REGPATH_CODEPAGE), USTR64(REGKEY_OEMCP), REG_SZ, }, { (ULONG64)HKEY_LOCAL_MACHINE, USTR64(REGPATH_CODEPAGE), USTR64(REGKEY_OEMCP), REG_SZ, DefaultOEMCP, DefaultOEMCPLength }, }, { { (ULONG64)HKEY_LOCAL_MACHINE, USTR64(REGPATH_LANGUAGE), USTR64(REGKEY_DEFAULT_LANGUAGE), REG_SZ, }, { (ULONG64)HKEY_LOCAL_MACHINE, USTR64(REGPATH_LANGUAGE), USTR64(REGKEY_DEFAULT_LANGUAGE), REG_SZ, DefaultLCID, DefaultLCIDLength }, }, }; Status = this->InitRegistryRedirection(Entries, countof(Entries), nullptr); } else { *GetLePeb() = *LePeb; Status = this->InitRegistryRedirection(LePeb->Leb.RegistryReplacement, LePeb->Leb.NumberOfRegistryRedirectionEntries, &LePeb->Leb); NtClose(LePeb->Section); CloseLePeb(LePeb); } if (IsLoader) break; Status = this->TextMetricCache.Initialize(); FAIL_RETURN(Status); PVOID NlsBaseAddress; LCID DefaultLocaleID; LARGE_INTEGER DefaultCasingTableSize; Status = NtInitializeNlsFiles(&NlsBaseAddress, &DefaultLocaleID, &DefaultCasingTableSize); FAIL_RETURN(Status); this->GetLePeb()->OriginalLocaleID = DefaultLocaleID; NtUnmapViewOfSection(CurrentProcess, NlsBaseAddress); WriteLog(L"init leb %s", GetLePeb()->LeDllFullPath); SystemDirectory = Ntdll->FullDllName; SystemDirectory.Length -= Ntdll->BaseDllName.Length; Status = RtlDuplicateUnicodeString(RTL_DUPSTR_ADD_NULL, &SystemDirectory, &this->SystemDirectory); FAIL_RETURN(Status); RtlInitEmptyString(&NlsFileName, nullptr, 0); RtlInitEmptyString(&OemNlsFileName, nullptr, 0); RtlInitEmptyString(&LangFileName, nullptr, 0); SCOPE_EXIT { RtlFreeUnicodeString(&NlsFileName); RtlFreeUnicodeString(&OemNlsFileName); RtlFreeUnicodeString(&LangFileName); } SCOPE_EXIT_END; Status = GetNlsFile(&NlsFileName, GetLeb()->AnsiCodePage, REGPATH_CODEPAGE); FAIL_RETURN(Status); Status = GetNlsFile(&OemNlsFileName, GetLeb()->OemCodePage, REGPATH_CODEPAGE); FAIL_RETURN(Status); Status = GetLangFile(&LangFileName, GetLeb()->LocaleID, REGPATH_LANGUAGE); FAIL_RETURN(Status); NtFileMemory AnsiFile, OemFile, LangFile; Status = ReadFileInSystemDirectory(AnsiFile, &NlsFileName); FAIL_RETURN(Status); Status = ReadFileInSystemDirectory(OemFile, &OemNlsFileName); FAIL_RETURN(Status); Status = ReadFileInSystemDirectory(LangFile, &LangFileName); FAIL_RETURN(Status); AnsiCodePageOffset = 0; OemCodePageOffset = ROUND_UP(AnsiFile.GetSize32(), 16); UnicodeCaseTableOffset = OemCodePageOffset + ROUND_UP(OemFile.GetSize32(), 16); Status = AllocVirtualMemory(&CodePageMapView, UnicodeCaseTableOffset + LangFile.GetSize32(), PAGE_READWRITE, MEM_COMMIT | MEM_TOP_DOWN); FAIL_RETURN(Status); CopyMemory(PtrAdd(CodePageMapView, AnsiCodePageOffset), AnsiFile.GetBuffer(), AnsiFile.GetSize32()); CopyMemory(PtrAdd(CodePageMapView, OemCodePageOffset), OemFile.GetBuffer(), OemFile.GetSize32()); CopyMemory(PtrAdd(CodePageMapView, UnicodeCaseTableOffset), LangFile.GetBuffer(), LangFile.GetSize32()); ProtectVirtualMemory(CodePageMapView, UnicodeCaseTableOffset + LangFile.GetSize32(), PAGE_READONLY); RtlInitNlsTables( (PUSHORT)PtrAdd(CodePageMapView, AnsiCodePageOffset), (PUSHORT)PtrAdd(CodePageMapView, OemCodePageOffset), (PUSHORT)PtrAdd(CodePageMapView, UnicodeCaseTableOffset), &NlsTableInfo ); RtlResetRtlTranslations(&NlsTableInfo); WriteLog(L"reset nls"); Peb = CurrentPeb(); Peb->AnsiCodePageData = (PUSHORT)PtrAdd(CodePageMapView, AnsiCodePageOffset); Peb->OemCodePageData = (PUSHORT)PtrAdd(CodePageMapView, OemCodePageOffset); Peb->UnicodeCaseTableData = (PUSHORT)PtrAdd(CodePageMapView, UnicodeCaseTableOffset); // LdrInitShimEngineDynamic(&__ImageBase); LdrRegisterDllNotification(0, [] (ULONG NotificationReason, PCLDR_DLL_NOTIFICATION_DATA NotificationData, PVOID Context) { return ((PLeGlobalData)Context)->DllNotification(NotificationReason, NotificationData); }, this, &DllNotificationCookie ); } Status = InstallHookPort(); WriteLog(L"inst hp: %08X", Status); FAIL_RETURN(Status); HookNtdllRoutines(Ntdll->DllBase); WriteLog(L"hook ntdll"); if (IsLoader) return Status; PLDR_MODULE Kernel32Ldr; Kernel32Ldr = GetKernel32Ldr(); if (Kernel32Ldr != nullptr) { Kernel32Ldr->EntryPoint = DelayInitDllEntry; // HookKernel32Routines(Kernel32Ldr->DllBase); } WriteLog(L"init %p", Status); return Status; }
NTSTATUS NtCopyDirectory(OBJECT_ATTRIBUTES ExistingDirectoryPath, OBJECT_ATTRIBUTES NewDirectoryPath) { HANDLE hExistingFile; //OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(OBJECT_ATTRIBUTES), hRootDir, (UNICODE_STRING*)&FileName, OBJ_CASE_INSENSITIVE }; IO_STATUS_BLOCK IoStatusBlock; auto Status = NtOpenFile(&hExistingFile, SYNCHRONIZE | FILE_LIST_DIRECTORY| FILE_READ_ATTRIBUTES, &ExistingDirectoryPath, &IoStatusBlock, FILE_SHARE_VALID_FLAGS, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); if (Status) return Status; HANDLE hNewFile; Status = NtCreateFile(&hNewFile, SYNCHRONIZE | FILE_LIST_DIRECTORY| FILE_WRITE_ATTRIBUTES, &NewDirectoryPath, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_VALID_FLAGS, FILE_OPEN_IF, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT, NULL, NULL); if (Status == 0) { byte Buffer[sizeof(FILE_FULL_DIR_INFORMATION) + 512]; FILE_FULL_DIR_INFORMATION & FileInfo = *(FILE_FULL_DIR_INFORMATION *)Buffer; UNICODE_STRING TempFileName = { 0,0,FileInfo.FileName }; NewDirectoryPath.RootDirectory = hNewFile; ExistingDirectoryPath.RootDirectory = hExistingFile; ExistingDirectoryPath.ObjectName = NewDirectoryPath.ObjectName = &TempFileName; byte FileBuffer[1024]; FILE_BASIC_INFORMATION BaseInfo; while (ZwQueryDirectoryFile(hExistingFile, NULL, NULL, NULL, &IoStatusBlock, Buffer, sizeof(Buffer), FileFullDirectoryInformation, -1, NULL, 0) == ERROR_SUCCESS) { TempFileName.Length = TempFileName.MaximumLength = FileInfo.FileNameLength; if (FileInfo.FileAttributes&FILE_ATTRIBUTE_DIRECTORY) { if (IsDots(FileInfo.FileName, FileInfo.FileNameLength)) continue; Status = NtCopyDirectory(ExistingDirectoryPath, NewDirectoryPath); } else { HANDLE hExistingFile; Status = NtOpenFile(&hExistingFile, FILE_GENERIC_READ, &ExistingDirectoryPath, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_DELETE, FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); if (Status) break; HANDLE hNewFile; Status = NtCreateFile(&hNewFile, SYNCHRONIZE | FILE_GENERIC_WRITE, &NewDirectoryPath, &IoStatusBlock, NULL, FileInfo.FileAttributes, FILE_SHARE_READ, FILE_OVERWRITE_IF, FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT, NULL, NULL); if (Status) { NtClose(hExistingFile); break; } DWORD cbData; while (true) { if (!ReadFile(hExistingFile, FileBuffer, sizeof(FileBuffer), &cbData, NULL)) { Status = GetLastError_s(); break; } if (!cbData) break; WriteFile(hNewFile, FileBuffer, cbData, &cbData, NULL); } if (NtQueryInformationFile(hExistingFile, &IoStatusBlock, &BaseInfo, sizeof(BaseInfo), FileBasicInformation)==0) { NtSetInformationFile(hNewFile,&IoStatusBlock, &BaseInfo, sizeof(BaseInfo), FileBasicInformation); } NtClose(hNewFile); NtClose(hExistingFile); } } if (NtQueryInformationFile(hExistingFile, &IoStatusBlock, &BaseInfo, sizeof(BaseInfo), FileBasicInformation) == 0) { NtSetInformationFile(hNewFile, &IoStatusBlock, &BaseInfo, sizeof(BaseInfo), FileBasicInformation); } NtClose(hNewFile); } NtClose(hExistingFile); return Status; }
/*********************************************************************** * RtlCreateUserThread (NTDLL.@) */ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, const SECURITY_DESCRIPTOR *descr, BOOLEAN suspended, PVOID stack_addr, SIZE_T stack_reserve, SIZE_T stack_commit, PRTL_THREAD_START_ROUTINE start, void *param, HANDLE *handle_ptr, CLIENT_ID *id ) { sigset_t sigset; pthread_t pthread_id; pthread_attr_t attr; struct ntdll_thread_data *thread_data; struct startup_info *info = NULL; HANDLE handle = 0; TEB *teb = NULL; DWORD tid = 0; int request_pipe[2]; NTSTATUS status; if (process != NtCurrentProcess()) { apc_call_t call; apc_result_t result; memset( &call, 0, sizeof(call) ); call.create_thread.type = APC_CREATE_THREAD; call.create_thread.func = wine_server_client_ptr( start ); call.create_thread.arg = wine_server_client_ptr( param ); call.create_thread.reserve = stack_reserve; call.create_thread.commit = stack_commit; call.create_thread.suspend = suspended; status = NTDLL_queue_process_apc( process, &call, &result ); if (status != STATUS_SUCCESS) return status; if (result.create_thread.status == STATUS_SUCCESS) { if (id) id->UniqueThread = ULongToHandle(result.create_thread.tid); if (handle_ptr) *handle_ptr = wine_server_ptr_handle( result.create_thread.handle ); else NtClose( wine_server_ptr_handle( result.create_thread.handle )); } return result.create_thread.status; } if (server_pipe( request_pipe ) == -1) return STATUS_TOO_MANY_OPENED_FILES; wine_server_send_fd( request_pipe[0] ); SERVER_START_REQ( new_thread ) { req->access = THREAD_ALL_ACCESS; req->attributes = 0; /* FIXME */ req->suspend = suspended; req->request_fd = request_pipe[0]; if (!(status = wine_server_call( req ))) { handle = wine_server_ptr_handle( reply->handle ); tid = reply->tid; } close( request_pipe[0] ); } SERVER_END_REQ; if (status) { close( request_pipe[1] ); return status; } pthread_sigmask( SIG_BLOCK, &server_block_set, &sigset ); if ((status = signal_alloc_thread( &teb ))) goto error; teb->Peb = NtCurrentTeb()->Peb; teb->ClientId.UniqueProcess = ULongToHandle(GetCurrentProcessId()); teb->ClientId.UniqueThread = ULongToHandle(tid); teb->StaticUnicodeString.Buffer = teb->StaticUnicodeBuffer; teb->StaticUnicodeString.MaximumLength = sizeof(teb->StaticUnicodeBuffer); info = (struct startup_info *)(teb + 1); info->teb = teb; info->entry_point = start; info->entry_arg = param; thread_data = (struct ntdll_thread_data *)teb->SpareBytes1; thread_data->request_fd = request_pipe[1]; thread_data->reply_fd = -1; thread_data->wait_fd[0] = -1; thread_data->wait_fd[1] = -1; if ((status = virtual_alloc_thread_stack( teb, stack_reserve, stack_commit ))) goto error; pthread_attr_init( &attr ); pthread_attr_setstack( &attr, teb->DeallocationStack, (char *)teb->Tib.StackBase - (char *)teb->DeallocationStack ); pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM ); /* force creating a kernel thread */ interlocked_xchg_add( &nb_threads, 1 ); if (pthread_create( &pthread_id, &attr, (void * (*)(void *))start_thread, info )) { interlocked_xchg_add( &nb_threads, -1 ); pthread_attr_destroy( &attr ); status = STATUS_NO_MEMORY; goto error; } pthread_attr_destroy( &attr ); pthread_sigmask( SIG_SETMASK, &sigset, NULL ); if (id) id->UniqueThread = ULongToHandle(tid); if (handle_ptr) *handle_ptr = handle; else NtClose( handle ); return STATUS_SUCCESS; error: if (teb) signal_free_thread( teb ); if (handle) NtClose( handle ); pthread_sigmask( SIG_SETMASK, &sigset, NULL ); close( request_pipe[1] ); return status; }
/** * @brief A Win32 GetDriveType() native equivalent. * @param[in] letter the volume letter * @return The drive type, negative value indicates failure. */ int winx_get_drive_type(char letter) { wchar_t link_name[] = L"\\??\\A:"; #define MAX_TARGET_LENGTH 256 wchar_t link_target[MAX_TARGET_LENGTH]; PROCESS_DEVICEMAP_INFORMATION pdi; FILE_FS_DEVICE_INFORMATION ffdi; IO_STATUS_BLOCK iosb; NTSTATUS status; int drive_type; HANDLE hRoot; /* The additional checks for DFS were suggested by Stefan Pendl ([email protected]). */ /* DFS shares have DRIVE_NO_ROOT_DIR type though they are actually remote. */ letter = winx_toupper(letter); if(letter < 'A' || letter > 'Z'){ etrace("invalid letter %c",letter); return (-1); } /* check for the drive existence */ link_name[4] = (wchar_t)letter; if(winx_query_symbolic_link(link_name,link_target,MAX_TARGET_LENGTH) < 0) return (-1); /* check for an assignment made by subst command */ if(wcsstr(link_target,L"\\??\\") == (wchar_t *)link_target) return DRIVE_ASSIGNED_BY_SUBST_COMMAND; /* check for classical floppies */ if(wcsstr(link_target,L"Floppy")) return DRIVE_REMOVABLE; /* try to define exactly which type has the specified drive */ RtlZeroMemory(&pdi,sizeof(PROCESS_DEVICEMAP_INFORMATION)); status = NtQueryInformationProcess(NtCurrentProcess(), ProcessDeviceMap,&pdi, sizeof(PROCESS_DEVICEMAP_INFORMATION), NULL); if(NT_SUCCESS(status)){ drive_type = (int)pdi.Query.DriveType[letter - 'A']; /* * Type DRIVE_NO_ROOT_DIR have the following drives: * 1. assigned by subst command * 2. SCSI external drives * 3. RAID volumes * 4. DFS shares * We need additional checks to know exactly. */ if(drive_type != DRIVE_NO_ROOT_DIR) return drive_type; } else { strace(status,"cannot get device map"); return (-1); } /* try to define exactly again which type has the specified drive */ /* note that the drive motor can be powered on during this check */ hRoot = OpenRootDirectory(letter); if(hRoot == NULL) return (-1); RtlZeroMemory(&ffdi,sizeof(FILE_FS_DEVICE_INFORMATION)); status = NtQueryVolumeInformationFile(hRoot,&iosb, &ffdi,sizeof(FILE_FS_DEVICE_INFORMATION), FileFsDeviceInformation); NtClose(hRoot); if(!NT_SUCCESS(status)){ strace(status,"cannot get volume type for \'%c\'",letter); return (-1); } /* detect remote/cd/dvd/unknown drives */ if(ffdi.Characteristics & FILE_REMOTE_DEVICE) return DRIVE_REMOTE; switch(ffdi.DeviceType){ case FILE_DEVICE_CD_ROM: case FILE_DEVICE_CD_ROM_FILE_SYSTEM: case FILE_DEVICE_DVD: return DRIVE_CDROM; case FILE_DEVICE_NETWORK_FILE_SYSTEM: case FILE_DEVICE_NETWORK: /* ? */ case FILE_DEVICE_NETWORK_BROWSER: /* ? */ case FILE_DEVICE_DFS_FILE_SYSTEM: case FILE_DEVICE_DFS_VOLUME: case FILE_DEVICE_DFS: return DRIVE_REMOTE; case FILE_DEVICE_UNKNOWN: return DRIVE_UNKNOWN; } /* detect removable disks */ if(ffdi.Characteristics & FILE_REMOVABLE_MEDIA) return DRIVE_REMOVABLE; /* detect fixed disks */ switch(ffdi.DeviceType){ case FILE_DEVICE_DISK: case FILE_DEVICE_FILE_SYSTEM: /* ? */ /*case FILE_DEVICE_VIRTUAL_DISK:*/ /*case FILE_DEVICE_MASS_STORAGE:*/ case FILE_DEVICE_DISK_FILE_SYSTEM: return DRIVE_FIXED; default: break; } /* nothing detected => drive type is unknown */ return DRIVE_UNKNOWN; }
VOID RemoveRamDisk() { WCHAR mountPoint[] = L" :"/*, cDriveLetter = 0*/; VOID *deviceHandle = 0; IO_STATUS_BLOCK isb; RAMDISK_CREATE_DATA createData = { 0 }; deviceHandle = OpenRamDisk(); if (deviceHandle == INVALID_HANDLE_VALUE) return; /*cDriveLetter = GetRamDiskDriveLetter( deviceHandle );*/ R0QueryRamDisk(deviceHandle, &createData); /*if(cDriveLetter == 0) return;*/ if (createData.DriveLetter == NULL) //could not get a drive letter, return. return; //szMountPoint[0] = cDriveLetter; mountPoint[0] = createData.DriveLetter; FlushFileBuffers(deviceHandle); NtDeviceIoControlFile( deviceHandle, NULL, NULL, NULL, &isb, FSCTL_LOCK_VOLUME, NULL, NULL, NULL, NULL ); NtDeviceIoControlFile( deviceHandle, NULL, NULL, NULL, &isb, FSCTL_DISMOUNT_VOLUME, NULL, NULL, NULL, NULL ); NtDeviceIoControlFile( deviceHandle, NULL, NULL, NULL, &isb, IOCTL_STORAGE_EJECT_MEDIA, NULL, NULL, NULL, NULL ); NtDeviceIoControlFile( deviceHandle, NULL, NULL, NULL, &isb, FSCTL_UNLOCK_VOLUME, NULL, NULL, NULL, NULL ); //CloseHandle(DeviceHandle); NtClose(deviceHandle); DefineDosDeviceW(DDD_REMOVE_DEFINITION, mountPoint, NULL); }
/* * @implemented */ BOOL WINAPI CheckTokenMembership(IN HANDLE ExistingTokenHandle, IN PSID SidToCheck, OUT PBOOL IsMember) { PISECURITY_DESCRIPTOR SecurityDescriptor = NULL; ACCESS_MASK GrantedAccess; struct { PRIVILEGE_SET PrivilegeSet; LUID_AND_ATTRIBUTES Privileges[4]; } PrivBuffer; ULONG PrivBufferSize = sizeof(PrivBuffer); GENERIC_MAPPING GenericMapping = { STANDARD_RIGHTS_READ, STANDARD_RIGHTS_WRITE, STANDARD_RIGHTS_EXECUTE, STANDARD_RIGHTS_ALL }; PACL Dacl; ULONG SidLen; HANDLE hToken = NULL; NTSTATUS Status, AccessStatus; /* doesn't return gracefully if IsMember is NULL! */ *IsMember = FALSE; SidLen = RtlLengthSid(SidToCheck); if (ExistingTokenHandle == NULL) { Status = NtOpenThreadToken(NtCurrentThread(), TOKEN_QUERY, FALSE, &hToken); if (Status == STATUS_NO_TOKEN) { /* we're not impersonating, open the primary token */ Status = NtOpenProcessToken(NtCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, &hToken); if (NT_SUCCESS(Status)) { HANDLE hNewToken = FALSE; BOOL DupRet; /* duplicate the primary token to create an impersonation token */ DupRet = DuplicateTokenEx(hToken, TOKEN_QUERY | TOKEN_IMPERSONATE, NULL, SecurityImpersonation, TokenImpersonation, &hNewToken); NtClose(hToken); if (!DupRet) { WARN("Failed to duplicate the primary token!\n"); return FALSE; } hToken = hNewToken; } } if (!NT_SUCCESS(Status)) { goto Cleanup; } } else { hToken = ExistingTokenHandle; } /* create a security descriptor */ SecurityDescriptor = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(SECURITY_DESCRIPTOR) + sizeof(ACL) + SidLen + sizeof(ACCESS_ALLOWED_ACE)); if (SecurityDescriptor == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto Cleanup; } Status = RtlCreateSecurityDescriptor(SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* set the owner and group */ Status = RtlSetOwnerSecurityDescriptor(SecurityDescriptor, SidToCheck, FALSE); if (!NT_SUCCESS(Status)) { goto Cleanup; } Status = RtlSetGroupSecurityDescriptor(SecurityDescriptor, SidToCheck, FALSE); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* create the DACL */ Dacl = (PACL)(SecurityDescriptor + 1); Status = RtlCreateAcl(Dacl, sizeof(ACL) + SidLen + sizeof(ACCESS_ALLOWED_ACE), ACL_REVISION); if (!NT_SUCCESS(Status)) { goto Cleanup; } Status = RtlAddAccessAllowedAce(Dacl, ACL_REVISION, 0x1, SidToCheck); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* assign the DACL to the security descriptor */ Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor, TRUE, Dacl, FALSE); if (!NT_SUCCESS(Status)) { goto Cleanup; } /* it's time to perform the access check. Just use _some_ desired access right (same as for the ACE) and see if we're getting it granted. This indicates our SID is a member of the token. We however can't use a generic access right as those aren't mapped and return an error (STATUS_GENERIC_NOT_MAPPED). */ Status = NtAccessCheck(SecurityDescriptor, hToken, 0x1, &GenericMapping, &PrivBuffer.PrivilegeSet, &PrivBufferSize, &GrantedAccess, &AccessStatus); if (NT_SUCCESS(Status) && NT_SUCCESS(AccessStatus) && (GrantedAccess == 0x1)) { *IsMember = TRUE; } Cleanup: if (hToken != NULL && hToken != ExistingTokenHandle) { NtClose(hToken); } if (SecurityDescriptor != NULL) { RtlFreeHeap(RtlGetProcessHeap(), 0, SecurityDescriptor); } if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); return FALSE; } return TRUE; }
NTSTATUS PhSvcApiPortInitialization( _In_ PUNICODE_STRING PortName ) { static SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY; NTSTATUS status; OBJECT_ATTRIBUTES objectAttributes; PSECURITY_DESCRIPTOR securityDescriptor; ULONG sdAllocationLength; UCHAR administratorsSidBuffer[FIELD_OFFSET(SID, SubAuthority) + sizeof(ULONG) * 2]; PSID administratorsSid; PACL dacl; ULONG i; HANDLE threadHandle; // Create the API port. administratorsSid = (PSID)administratorsSidBuffer; RtlInitializeSid(administratorsSid, &ntAuthority, 2); *RtlSubAuthoritySid(administratorsSid, 0) = SECURITY_BUILTIN_DOMAIN_RID; *RtlSubAuthoritySid(administratorsSid, 1) = DOMAIN_ALIAS_RID_ADMINS; sdAllocationLength = SECURITY_DESCRIPTOR_MIN_LENGTH + (ULONG)sizeof(ACL) + (ULONG)sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(administratorsSid) + (ULONG)sizeof(ACCESS_ALLOWED_ACE) + RtlLengthSid(&PhSeEveryoneSid); securityDescriptor = PhAllocate(sdAllocationLength); dacl = (PACL)((PCHAR)securityDescriptor + SECURITY_DESCRIPTOR_MIN_LENGTH); RtlCreateSecurityDescriptor(securityDescriptor, SECURITY_DESCRIPTOR_REVISION); RtlCreateAcl(dacl, sdAllocationLength - SECURITY_DESCRIPTOR_MIN_LENGTH, ACL_REVISION); RtlAddAccessAllowedAce(dacl, ACL_REVISION, PORT_ALL_ACCESS, administratorsSid); RtlAddAccessAllowedAce(dacl, ACL_REVISION, PORT_CONNECT, &PhSeEveryoneSid); RtlSetDaclSecurityDescriptor(securityDescriptor, TRUE, dacl, FALSE); InitializeObjectAttributes( &objectAttributes, PortName, OBJ_CASE_INSENSITIVE, NULL, securityDescriptor ); status = NtCreatePort( &PhSvcApiPortHandle, &objectAttributes, sizeof(PHSVC_API_CONNECTINFO), PhIsExecutingInWow64() ? sizeof(PHSVC_API_MSG64) : sizeof(PHSVC_API_MSG), 0 ); PhFree(securityDescriptor); if (!NT_SUCCESS(status)) return status; // Start the API threads. PhSvcApiThreadContextTlsIndex = TlsAlloc(); for (i = 0; i < 2; i++) { threadHandle = PhCreateThread(0, PhSvcApiRequestThreadStart, NULL); if (threadHandle) NtClose(threadHandle); } return status; }
int rtDirNativeOpen(PRTDIRINTERNAL pDir, uintptr_t hRelativeDir, void *pvNativeRelative) { /* * Convert the filter to UTF-16. */ int rc; pDir->pNtFilterStr = NULL; if ( pDir->cchFilter > 0 && pDir->enmFilter == RTDIRFILTER_WINNT) { PRTUTF16 pwszTmp; rc = RTStrToUtf16(pDir->pszFilter, &pwszTmp); if (RT_FAILURE(rc)) return rc; pDir->NtFilterStr.Buffer = pwszTmp; pDir->NtFilterStr.Length = pDir->NtFilterStr.MaximumLength = (uint16_t)(RTUtf16Len(pwszTmp) * sizeof(RTUTF16)); pDir->pNtFilterStr = &pDir->NtFilterStr; } /* * Try open the directory */ #ifdef IPRT_WITH_NT_PATH_PASSTHRU bool fObjDir = false; #endif if (hRelativeDir != ~(uintptr_t)0 && pvNativeRelative == NULL) { /* Caller already opened it, easy! */ pDir->hDir = (HANDLE)hRelativeDir; rc = VINF_SUCCESS; } else { /* * If we have to check for reparse points, this gets complicated! */ static int volatile g_fReparsePoints = -1; uint32_t fOptions = FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT; int fReparsePoints = g_fReparsePoints; if ( fReparsePoints != 0 && (pDir->fFlags & RTDIR_F_NO_FOLLOW) && !pDir->fDirSlash) fOptions |= FILE_OPEN_REPARSE_POINT; for (;;) { if (pvNativeRelative == NULL) rc = RTNtPathOpenDir(pDir->pszPath, FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | FILE_TRAVERSE | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE, fOptions, OBJ_CASE_INSENSITIVE, &pDir->hDir, #ifdef IPRT_WITH_NT_PATH_PASSTHRU &fObjDir #else NULL #endif ); else rc = RTNtPathOpenDirEx((HANDLE)hRelativeDir, (struct _UNICODE_STRING *)pvNativeRelative, FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | FILE_TRAVERSE | SYNCHRONIZE, FILE_SHARE_READ | FILE_SHARE_WRITE, fOptions, OBJ_CASE_INSENSITIVE, &pDir->hDir, #ifdef IPRT_WITH_NT_PATH_PASSTHRU &fObjDir #else NULL #endif ); if ( !(fOptions & FILE_OPEN_REPARSE_POINT) || (rc != VINF_SUCCESS && rc != VERR_INVALID_PARAMETER) ) break; if (rc == VINF_SUCCESS) { if (fReparsePoints == -1) g_fReparsePoints = 1; /* * We now need to check if we opened a symbolic directory link. * (These can be enumerated, but contains only '.' and '..'.) */ FILE_ATTRIBUTE_TAG_INFORMATION TagInfo = { 0, 0 }; IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER; NTSTATUS rcNt = NtQueryInformationFile(pDir->hDir, &Ios, &TagInfo, sizeof(TagInfo), FileAttributeTagInformation); AssertMsg(NT_SUCCESS(rcNt), ("%#x\n", rcNt)); if (!NT_SUCCESS(rcNt)) TagInfo.FileAttributes = TagInfo.ReparseTag = 0; if (!(TagInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) break; NtClose(pDir->hDir); pDir->hDir = RTNT_INVALID_HANDLE_VALUE; if (TagInfo.ReparseTag == IO_REPARSE_TAG_SYMLINK) { rc = VERR_IS_A_SYMLINK; break; } /* Reparse point that isn't a symbolic link, try follow the reparsing. */ } else if (fReparsePoints == -1) g_fReparsePoints = fReparsePoints = 0; fOptions &= ~FILE_OPEN_REPARSE_POINT; } } if (RT_SUCCESS(rc)) { /* * Init data. */ pDir->fDataUnread = false; /* spelling it out */ pDir->uDirDev = 0; #ifdef IPRT_WITH_NT_PATH_PASSTHRU if (fObjDir) pDir->enmInfoClass = FileMaximumInformation; /* object directory. */ #endif } return rc; }
NTSTATUS InfWriteFile(HINF InfHandle, PUNICODE_STRING FileName, PUNICODE_STRING HeaderComment) { OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; HANDLE FileHandle; NTSTATUS Status; INFSTATUS InfStatus; PWCHAR Buffer; ULONG BufferSize; PWCHAR HeaderBuffer; ULONG HeaderBufferSize; UINT Index; InfStatus = InfpBuildFileBuffer((PINFCACHE) InfHandle, &Buffer, &BufferSize); if (! INF_SUCCESS(InfStatus)) { DPRINT("Failed to create buffer (Status 0x%lx)\n", InfStatus); return InfStatus; } /* Open the inf file */ InitializeObjectAttributes(&ObjectAttributes, FileName, 0, NULL, NULL); Status = NtOpenFile(&FileHandle, GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, 0, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE); if (!INF_SUCCESS(Status)) { DPRINT1("NtOpenFile() failed (Status %lx)\n", Status); FREE(Buffer); return Status; } DPRINT("NtOpenFile() successful\n"); if (NULL != HeaderComment && 0 != HeaderComment->Length) { /* This is just a comment header, don't abort on errors here */ HeaderBufferSize = HeaderComment->Length + 7 * sizeof(WCHAR); HeaderBuffer = MALLOC(HeaderBufferSize); if (NULL != HeaderBuffer) { strcpyW(HeaderBuffer, L"; "); for (Index = 0; Index < HeaderComment->Length / sizeof(WCHAR); Index++) { HeaderBuffer[2 + Index] = HeaderComment->Buffer[Index]; } strcpyW(HeaderBuffer + (2 + HeaderComment->Length / sizeof(WCHAR)), L"\r\n\r\n"); NtWriteFile(FileHandle, NULL, NULL, NULL, &IoStatusBlock, HeaderBuffer, HeaderBufferSize, NULL, NULL); FREE(HeaderBuffer); } } /* Write main contents */ Status = NtWriteFile(FileHandle, NULL, NULL, NULL, &IoStatusBlock, Buffer, BufferSize, NULL, NULL); NtClose(FileHandle); FREE(Buffer); if (!INF_SUCCESS(Status)) { DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); FREE(Buffer); return(Status); } return STATUS_SUCCESS; }
INT_PTR CALLBACK PhpServiceGeneralDlgProc( __in HWND hwndDlg, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ) { switch (uMsg) { case WM_INITDIALOG: { LPPROPSHEETPAGE propSheetPage = (LPPROPSHEETPAGE)lParam; PSERVICE_PROPERTIES_CONTEXT context = (PSERVICE_PROPERTIES_CONTEXT)propSheetPage->lParam; PPH_SERVICE_ITEM serviceItem = context->ServiceItem; SC_HANDLE serviceHandle; // HACK PhCenterWindow(GetParent(hwndDlg), GetParent(GetParent(hwndDlg))); SetProp(hwndDlg, PhMakeContextAtom(), (HANDLE)context); PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_TYPE), PhServiceTypeStrings, sizeof(PhServiceTypeStrings) / sizeof(WCHAR *)); PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_STARTTYPE), PhServiceStartTypeStrings, sizeof(PhServiceStartTypeStrings) / sizeof(WCHAR *)); PhAddComboBoxStrings(GetDlgItem(hwndDlg, IDC_ERRORCONTROL), PhServiceErrorControlStrings, sizeof(PhServiceErrorControlStrings) / sizeof(WCHAR *)); SetDlgItemText(hwndDlg, IDC_DESCRIPTION, serviceItem->DisplayName->Buffer); ComboBox_SelectString(GetDlgItem(hwndDlg, IDC_TYPE), -1, PhGetServiceTypeString(serviceItem->Type)); ComboBox_SelectString(GetDlgItem(hwndDlg, IDC_STARTTYPE), -1, PhGetServiceStartTypeString(serviceItem->StartType)); ComboBox_SelectString(GetDlgItem(hwndDlg, IDC_ERRORCONTROL), -1, PhGetServiceErrorControlString(serviceItem->ErrorControl)); serviceHandle = PhOpenService(serviceItem->Name->Buffer, SERVICE_QUERY_CONFIG); if (serviceHandle) { LPQUERY_SERVICE_CONFIG config; PPH_STRING description; BOOLEAN delayedStart; if (config = PhGetServiceConfig(serviceHandle)) { SetDlgItemText(hwndDlg, IDC_GROUP, config->lpLoadOrderGroup); SetDlgItemText(hwndDlg, IDC_BINARYPATH, config->lpBinaryPathName); SetDlgItemText(hwndDlg, IDC_USERACCOUNT, config->lpServiceStartName); PhFree(config); } if (description = PhGetServiceDescription(serviceHandle)) { SetDlgItemText(hwndDlg, IDC_DESCRIPTION, description->Buffer); PhDereferenceObject(description); } if (PhGetServiceDelayedAutoStart(serviceHandle, &delayedStart)) { context->OldDelayedStart = delayedStart; if (delayedStart) Button_SetCheck(GetDlgItem(hwndDlg, IDC_DELAYEDSTART), BST_CHECKED); } CloseServiceHandle(serviceHandle); } SetDlgItemText(hwndDlg, IDC_PASSWORD, L"password"); Button_SetCheck(GetDlgItem(hwndDlg, IDC_PASSWORDCHECK), BST_UNCHECKED); SetDlgItemText(hwndDlg, IDC_SERVICEDLL, L"N/A"); { HANDLE keyHandle; PPH_STRING keyName; keyName = PhConcatStrings( 3, L"System\\CurrentControlSet\\Services\\", serviceItem->Name->Buffer, L"\\Parameters" ); if (NT_SUCCESS(PhOpenKey( &keyHandle, KEY_READ, PH_KEY_LOCAL_MACHINE, &keyName->sr, 0 ))) { PPH_STRING serviceDllString; if (serviceDllString = PhQueryRegistryString(keyHandle, L"ServiceDll")) { PPH_STRING expandedString; if (expandedString = PhExpandEnvironmentStrings(&serviceDllString->sr)) { SetDlgItemText(hwndDlg, IDC_SERVICEDLL, expandedString->Buffer); PhDereferenceObject(expandedString); } PhDereferenceObject(serviceDllString); } NtClose(keyHandle); } PhDereferenceObject(keyName); } PhpRefreshControls(hwndDlg); context->Ready = TRUE; } break; case WM_DESTROY: { RemoveProp(hwndDlg, PhMakeContextAtom()); } break; case WM_COMMAND: { PSERVICE_PROPERTIES_CONTEXT context = (PSERVICE_PROPERTIES_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); switch (LOWORD(wParam)) { case IDCANCEL: { // Workaround for property sheet + multiline edit: http://support.microsoft.com/kb/130765 SendMessage(GetParent(hwndDlg), uMsg, wParam, lParam); } break; case IDC_PASSWORD: { if (HIWORD(wParam) == EN_CHANGE) { Button_SetCheck(GetDlgItem(hwndDlg, IDC_PASSWORDCHECK), BST_CHECKED); } } break; case IDC_DELAYEDSTART: { context->Dirty = TRUE; } break; case IDC_BROWSE: { static PH_FILETYPE_FILTER filters[] = { { L"Executable files (*.exe;*.sys)", L"*.exe;*.sys" }, { L"All files (*.*)", L"*.*" } }; PVOID fileDialog; PPH_STRING fileName; fileDialog = PhCreateOpenFileDialog(); PhSetFileDialogFilter(fileDialog, filters, sizeof(filters) / sizeof(PH_FILETYPE_FILTER)); fileName = PhGetFileName(PHA_GET_DLGITEM_TEXT(hwndDlg, IDC_BINARYPATH)); PhSetFileDialogFileName(fileDialog, fileName->Buffer); PhDereferenceObject(fileName); if (PhShowFileDialog(hwndDlg, fileDialog)) { fileName = PhGetFileDialogFileName(fileDialog); SetDlgItemText(hwndDlg, IDC_BINARYPATH, fileName->Buffer); PhDereferenceObject(fileName); } PhFreeFileDialog(fileDialog); } break; } switch (HIWORD(wParam)) { case EN_CHANGE: case CBN_SELCHANGE: { PhpRefreshControls(hwndDlg); if (context->Ready) context->Dirty = TRUE; } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case PSN_QUERYINITIALFOCUS: { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (LONG_PTR)GetDlgItem(hwndDlg, IDC_TYPE)); } return TRUE; case PSN_KILLACTIVE: { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, FALSE); } return TRUE; case PSN_APPLY: { NTSTATUS status; PSERVICE_PROPERTIES_CONTEXT context = (PSERVICE_PROPERTIES_CONTEXT)GetProp(hwndDlg, PhMakeContextAtom()); PPH_SERVICE_ITEM serviceItem = context->ServiceItem; SC_HANDLE serviceHandle; PPH_STRING newServiceTypeString; PPH_STRING newServiceStartTypeString; PPH_STRING newServiceErrorControlString; ULONG newServiceType; ULONG newServiceStartType; ULONG newServiceErrorControl; PPH_STRING newServiceGroup; PPH_STRING newServiceBinaryPath; PPH_STRING newServiceUserAccount; PPH_STRING newServicePassword; SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); if (!context->Dirty) { return TRUE; } newServiceTypeString = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_TYPE))); newServiceStartTypeString = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_STARTTYPE))); newServiceErrorControlString = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_ERRORCONTROL))); newServiceType = PhGetServiceTypeInteger(newServiceTypeString->Buffer); newServiceStartType = PhGetServiceStartTypeInteger(newServiceStartTypeString->Buffer); newServiceErrorControl = PhGetServiceErrorControlInteger(newServiceErrorControlString->Buffer); newServiceGroup = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_GROUP))); newServiceBinaryPath = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_BINARYPATH))); newServiceUserAccount = PHA_DEREFERENCE(PhGetWindowText(GetDlgItem(hwndDlg, IDC_USERACCOUNT))); if (Button_GetCheck(GetDlgItem(hwndDlg, IDC_PASSWORDCHECK)) == BST_CHECKED) { newServicePassword = PhGetWindowText(GetDlgItem(hwndDlg, IDC_PASSWORD)); } else { newServicePassword = NULL; } if (newServiceType == SERVICE_KERNEL_DRIVER && newServiceUserAccount->Length == 0) { newServiceUserAccount = NULL; } serviceHandle = PhOpenService(serviceItem->Name->Buffer, SERVICE_CHANGE_CONFIG); if (serviceHandle) { if (ChangeServiceConfig( serviceHandle, newServiceType, newServiceStartType, newServiceErrorControl, newServiceBinaryPath->Buffer, newServiceGroup->Buffer, NULL, NULL, PhGetString(newServiceUserAccount), PhGetString(newServicePassword), NULL )) { BOOLEAN newDelayedStart; newDelayedStart = Button_GetCheck(GetDlgItem(hwndDlg, IDC_DELAYEDSTART)) == BST_CHECKED; if (newDelayedStart != context->OldDelayedStart) { PhSetServiceDelayedAutoStart(serviceHandle, newDelayedStart); } PhMarkNeedsConfigUpdateServiceItem(serviceItem); CloseServiceHandle(serviceHandle); } else { CloseServiceHandle(serviceHandle); goto ErrorCase; } } else { if (GetLastError() == ERROR_ACCESS_DENIED && !PhElevated) { // Elevate using phsvc. if (PhUiConnectToPhSvc(hwndDlg, FALSE)) { if (NT_SUCCESS(status = PhSvcCallChangeServiceConfig( serviceItem->Name->Buffer, newServiceType, newServiceStartType, newServiceErrorControl, newServiceBinaryPath->Buffer, newServiceGroup->Buffer, NULL, NULL, PhGetString(newServiceUserAccount), PhGetString(newServicePassword), NULL ))) { BOOLEAN newDelayedStart; newDelayedStart = Button_GetCheck(GetDlgItem(hwndDlg, IDC_DELAYEDSTART)) == BST_CHECKED; if (newDelayedStart != context->OldDelayedStart) { SERVICE_DELAYED_AUTO_START_INFO info; info.fDelayedAutostart = newDelayedStart; PhSvcCallChangeServiceConfig2( serviceItem->Name->Buffer, SERVICE_CONFIG_DELAYED_AUTO_START_INFO, &info ); } PhMarkNeedsConfigUpdateServiceItem(serviceItem); } PhUiDisconnectFromPhSvc(); if (!NT_SUCCESS(status)) { SetLastError(PhNtStatusToDosError(status)); goto ErrorCase; } } else { // User cancelled elevation. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID); } } else { goto ErrorCase; } } goto Cleanup; ErrorCase: if (PhShowMessage( hwndDlg, MB_ICONERROR | MB_RETRYCANCEL, L"Unable to change service configuration: %s", ((PPH_STRING)PHA_DEREFERENCE(PhGetWin32Message(GetLastError())))->Buffer ) == IDRETRY) { SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, PSNRET_INVALID); } Cleanup: if (newServicePassword) { RtlSecureZeroMemory(newServicePassword->Buffer, newServicePassword->Length); PhDereferenceObject(newServicePassword); } } return TRUE; } } break; } return FALSE; }
NTSTATUS IniCacheSave( PINICACHE Cache, PWCHAR FileName) { UNICODE_STRING Name; PINICACHESECTION Section; PINICACHEKEY Key; ULONG BufferSize; PCHAR Buffer; PCHAR Ptr; ULONG Len; NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; LARGE_INTEGER Offset; HANDLE FileHandle; /* Calculate required buffer size */ BufferSize = 0; Section = Cache->FirstSection; while (Section != NULL) { BufferSize += (Section->Name ? wcslen(Section->Name) : 0) + 4; /* "[]\r\n" */ Key = Section->FirstKey; while (Key != NULL) { BufferSize += wcslen(Key->Name) + (Key->Data ? wcslen(Key->Data) : 0) + 3; /* "=\r\n" */ Key = Key->Next; } Section = Section->Next; if (Section != NULL) BufferSize += 2; /* extra "\r\n" at end of each section */ } BufferSize++; /* Null-terminator */ DPRINT("BufferSize: %lu\n", BufferSize); /* Allocate file buffer */ Buffer = (CHAR*)RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, BufferSize); if (Buffer == NULL) { DPRINT1("RtlAllocateHeap() failed\n"); return STATUS_INSUFFICIENT_RESOURCES; } /* Fill file buffer */ Ptr = Buffer; Section = Cache->FirstSection; while (Section != NULL) { Len = sprintf(Ptr, "[%S]\r\n", Section->Name); Ptr += Len; Key = Section->FirstKey; while (Key != NULL) { Len = sprintf(Ptr, "%S=%S\r\n", Key->Name, Key->Data); Ptr += Len; Key = Key->Next; } Section = Section->Next; if (Section != NULL) { Len = sprintf(Ptr, "\r\n"); Ptr += Len; } } /* Create ini file */ RtlInitUnicodeString(&Name, FileName); InitializeObjectAttributes(&ObjectAttributes, &Name, 0, NULL, NULL); Status = NtCreateFile(&FileHandle, GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_SUPERSEDE, FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY, NULL, 0); if (!NT_SUCCESS(Status)) { DPRINT("NtCreateFile() failed (Status %lx)\n", Status); RtlFreeHeap(ProcessHeap, 0, Buffer); return Status; } Offset.QuadPart = 0LL; Status = NtWriteFile(FileHandle, NULL, NULL, NULL, &IoStatusBlock, Buffer, BufferSize, &Offset, NULL); if (!NT_SUCCESS(Status)) { DPRINT("NtWriteFile() failed (Status %lx)\n", Status); NtClose(FileHandle); RtlFreeHeap(ProcessHeap, 0, Buffer); return Status; } NtClose(FileHandle); RtlFreeHeap(ProcessHeap, 0, Buffer); return STATUS_SUCCESS; }
/* * @implemented */ BOOL WINAPI WaitNamedPipeW(LPCWSTR lpNamedPipeName, DWORD nTimeOut) { UNICODE_STRING NamedPipeName, NewName, DevicePath, PipePrefix; ULONG NameLength; ULONG i; PWCHAR p; ULONG Type; OBJECT_ATTRIBUTES ObjectAttributes; NTSTATUS Status; HANDLE FileHandle; IO_STATUS_BLOCK IoStatusBlock; ULONG WaitPipeInfoSize; PFILE_PIPE_WAIT_FOR_BUFFER WaitPipeInfo; /* Start by making a unicode string of the name */ TRACE("Sent path: %S\n", lpNamedPipeName); RtlCreateUnicodeString(&NamedPipeName, lpNamedPipeName); NameLength = NamedPipeName.Length / sizeof(WCHAR); /* All slashes must become backslashes */ for (i = 0; i < NameLength; i++) { /* Check and convert */ if (NamedPipeName.Buffer[i] == L'/') NamedPipeName.Buffer[i] = L'\\'; } /* Find the path type of the name we were given */ NewName = NamedPipeName; Type = RtlDetermineDosPathNameType_U(lpNamedPipeName); /* Check if this was a device path, ie : "\\.\pipe\name" */ if (Type == RtlPathTypeLocalDevice) { /* Make sure it's a valid prefix */ RtlInitUnicodeString(&PipePrefix, L"\\\\.\\pipe\\"); RtlPrefixString((PANSI_STRING)&PipePrefix, (PANSI_STRING)&NewName, TRUE); /* Move past it */ NewName.Buffer += 9; NewName.Length -= 9 * sizeof(WCHAR); /* Initialize the Dos Devices name */ TRACE("NewName: %wZ\n", &NewName); RtlInitUnicodeString(&DevicePath, L"\\DosDevices\\pipe\\"); } else if (Type == RtlPathTypeRootLocalDevice) { /* The path is \\server\\pipe\name; find the pipename itself */ p = &NewName.Buffer[2]; /* First loop to get past the server name */ do { /* Check if this is a backslash */ if (*p == L'\\') break; /* Check next */ p++; } while (*p); /* Now make sure the full name contains "pipe\" */ if ((*p) && !(_wcsnicmp(p + 1, L"pipe\\", sizeof("pipe\\")))) { /* Get to the pipe name itself now */ p += sizeof("pipe\\") - 1; } else { /* The name is invalid */ WARN("Invalid name!\n"); BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD); return FALSE; } /* FIXME: Open \DosDevices\Unc\Server\Pipe\Name */ } else { WARN("Invalid path type\n"); BaseSetLastNTError(STATUS_OBJECT_PATH_SYNTAX_BAD); return FALSE; } /* Now calculate the total length of the structure and allocate it */ WaitPipeInfoSize = FIELD_OFFSET(FILE_PIPE_WAIT_FOR_BUFFER, Name[0]) + NewName.Length; WaitPipeInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, WaitPipeInfoSize); if (WaitPipeInfo == NULL) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } /* Initialize the object attributes */ TRACE("Opening: %wZ\n", &DevicePath); InitializeObjectAttributes(&ObjectAttributes, &DevicePath, OBJ_CASE_INSENSITIVE, NULL, NULL); /* Open the path */ Status = NtOpenFile(&FileHandle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT); if (!NT_SUCCESS(Status)) { /* Fail; couldn't open */ WARN("Status: %lx\n", Status); BaseSetLastNTError(Status); RtlFreeUnicodeString(&NamedPipeName); RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo); return FALSE; } /* Check what timeout we got */ if (nTimeOut == NMPWAIT_USE_DEFAULT_WAIT) { /* Don't use a timeout */ WaitPipeInfo->TimeoutSpecified = FALSE; } else { /* Check if we should wait forever */ if (nTimeOut == NMPWAIT_WAIT_FOREVER) { /* Set the max */ WaitPipeInfo->Timeout.LowPart = 0; WaitPipeInfo->Timeout.HighPart = 0x80000000; } else { /* Convert to NT format */ WaitPipeInfo->Timeout.QuadPart = UInt32x32To64(-10000, nTimeOut); } /* In both cases, we do have a timeout */ WaitPipeInfo->TimeoutSpecified = TRUE; } /* Set the length and copy the name */ WaitPipeInfo->NameLength = NewName.Length; RtlCopyMemory(WaitPipeInfo->Name, NewName.Buffer, NewName.Length); /* Get rid of the full name */ RtlFreeUnicodeString(&NamedPipeName); /* Let NPFS know of our request */ Status = NtFsControlFile(FileHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_PIPE_WAIT, WaitPipeInfo, WaitPipeInfoSize, NULL, 0); /* Free our pipe info data and close the handle */ RtlFreeHeap(RtlGetProcessHeap(), 0, WaitPipeInfo); NtClose(FileHandle); /* Check the status */ if (!NT_SUCCESS(Status)) { /* Failure to wait on the pipe */ WARN("Status: %lx\n", Status); BaseSetLastNTError (Status); return FALSE; } /* Success */ return TRUE; }
INT_PTR CALLBACK NetworkOutputDlgProc( __in HWND hwndDlg, __in UINT uMsg, __in WPARAM wParam, __in LPARAM lParam ) { PNETWORK_OUTPUT_CONTEXT context; if (uMsg == WM_INITDIALOG) { context = (PNETWORK_OUTPUT_CONTEXT)lParam; SetProp(hwndDlg, L"Context", (HANDLE)context); } else { context = (PNETWORK_OUTPUT_CONTEXT)GetProp(hwndDlg, L"Context"); if (uMsg == WM_DESTROY) RemoveProp(hwndDlg, L"Context"); } if (!context) return FALSE; switch (uMsg) { case WM_INITDIALOG: { WCHAR addressString[65]; HANDLE pipeWriteHandle; PhCenterWindow(hwndDlg, GetParent(hwndDlg)); context->WindowHandle = hwndDlg; if (context->Address.Type == PH_IPV4_NETWORK_TYPE) RtlIpv4AddressToString(&context->Address.InAddr, addressString); else RtlIpv6AddressToString(&context->Address.In6Addr, addressString); switch (context->Action) { case NETWORK_ACTION_PING: case NETWORK_ACTION_TRACEROUTE: if (context->Action == NETWORK_ACTION_PING) { SetDlgItemText(hwndDlg, IDC_MESSAGE, PhaFormatString(L"Pinging %s...", addressString)->Buffer); } else { SetDlgItemText(hwndDlg, IDC_MESSAGE, PhaFormatString(L"Tracing route to %s...", addressString)->Buffer); } // Doing this properly would be too complex, so we'll just // execute ping.exe/traceroute.exe and display its output. if (CreatePipe(&context->PipeReadHandle, &pipeWriteHandle, NULL, 0)) { STARTUPINFO startupInfo = { sizeof(startupInfo) }; PPH_STRING command; OBJECT_HANDLE_FLAG_INFORMATION flagInfo; startupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); startupInfo.hStdOutput = pipeWriteHandle; startupInfo.hStdError = pipeWriteHandle; startupInfo.wShowWindow = SW_HIDE; if (context->Action == NETWORK_ACTION_PING) { command = PhaFormatString( L"%s\\system32\\ping.exe %s", USER_SHARED_DATA->NtSystemRoot, addressString ); } else { command = PhaFormatString( L"%s\\system32\\tracert.exe %s", USER_SHARED_DATA->NtSystemRoot, addressString ); } // Allow the write handle to be inherited. flagInfo.Inherit = TRUE; flagInfo.ProtectFromClose = FALSE; NtSetInformationObject( pipeWriteHandle, ObjectHandleFlagInformation, &flagInfo, sizeof(OBJECT_HANDLE_FLAG_INFORMATION) ); PhCreateProcessWin32Ex( NULL, command->Buffer, NULL, NULL, &startupInfo, PH_CREATE_PROCESS_INHERIT_HANDLES, NULL, NULL, &context->ProcessHandle, NULL ); // Essential; when the process exits, the last instance of the pipe // will be disconnected and our thread will exit. NtClose(pipeWriteHandle); // Create a thread which will wait for output and display it. context->ThreadHandle = PhCreateThread(0, NetworkWorkerThreadStart, context); } break; } } break; case WM_DESTROY: { PhAcquireQueuedLockExclusive(&context->WindowHandleLock); context->WindowHandle = NULL; PhReleaseQueuedLockExclusive(&context->WindowHandleLock); if (context->ProcessHandle) { NtTerminateProcess(context->ProcessHandle, STATUS_SUCCESS); NtClose(context->ProcessHandle); } } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDCANCEL: case IDOK: EndDialog(hwndDlg, IDOK); break; } } break; case NTM_DONE: { SetDlgItemText(hwndDlg, IDC_MESSAGE, L"Finished."); } break; case NTM_RECEIVED: { OEM_STRING inputString; UNICODE_STRING convertedString; if (wParam != 0) { inputString.Buffer = (PCHAR)lParam; inputString.Length = (USHORT)wParam; if (NT_SUCCESS(RtlOemStringToUnicodeString(&convertedString, &inputString, TRUE))) { PhAppendStringBuilderEx(&context->ReceivedString, convertedString.Buffer, convertedString.Length); RtlFreeUnicodeString(&convertedString); // Remove leading newlines. if ( context->ReceivedString.String->Length >= 2 * 2 && context->ReceivedString.String->Buffer[0] == '\r' && context->ReceivedString.String->Buffer[1] == '\n' ) { PhRemoveStringBuilder(&context->ReceivedString, 0, 2); } SetDlgItemText(hwndDlg, IDC_TEXT, context->ReceivedString.String->Buffer); SendMessage( GetDlgItem(hwndDlg, IDC_TEXT), EM_SETSEL, context->ReceivedString.String->Length / 2 - 1, context->ReceivedString.String->Length / 2 - 1 ); SendMessage(GetDlgItem(hwndDlg, IDC_TEXT), WM_VSCROLL, SB_BOTTOM, 0); } } } break; } return FALSE; }
/* * @implemented */ BOOL WINAPI WaitNamedPipeW(LPCWSTR lpNamedPipeName, DWORD nTimeOut) { UNICODE_STRING NamedPipeName; NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; FILE_PIPE_WAIT_FOR_BUFFER WaitPipe; HANDLE FileHandle; IO_STATUS_BLOCK Iosb; if (RtlDosPathNameToNtPathName_U(lpNamedPipeName, &NamedPipeName, NULL, NULL) == FALSE) { return FALSE; } InitializeObjectAttributes(&ObjectAttributes, &NamedPipeName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenFile(&FileHandle, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &ObjectAttributes, &Iosb, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT); if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); RtlFreeUnicodeString(&NamedPipeName); return FALSE; } /* Check what timeout we got */ if (nTimeOut == NMPWAIT_WAIT_FOREVER) { /* Don't use a timeout */ WaitPipe.TimeoutSpecified = FALSE; } else { /* Check if default */ if (nTimeOut == NMPWAIT_USE_DEFAULT_WAIT) { /* Set it to 0 */ WaitPipe.Timeout.LowPart = 0; WaitPipe.Timeout.HighPart = 0; } else { /* Convert to NT format */ WaitPipe.Timeout.QuadPart = UInt32x32To64(-10000, nTimeOut); } /* In both cases, we do have a timeout */ WaitPipe.TimeoutSpecified = TRUE; } Status = NtFsControlFile(FileHandle, NULL, NULL, NULL, &Iosb, FSCTL_PIPE_WAIT, &WaitPipe, sizeof(WaitPipe), NULL, 0); NtClose(FileHandle); if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); RtlFreeUnicodeString(&NamedPipeName); return FALSE; } RtlFreeUnicodeString(&NamedPipeName); return TRUE; }
static void test_tp_multi_wait(void) { TP_CALLBACK_ENVIRON environment; HANDLE semaphores[512]; TP_WAIT *waits[512]; LARGE_INTEGER when; HANDLE semaphore; NTSTATUS status; TP_POOL *pool; DWORD result; int i; semaphore = CreateSemaphoreW(NULL, 0, 512, NULL); ok(semaphore != NULL, "failed to create semaphore\n"); multi_wait_info.semaphore = semaphore; /* allocate new threadpool */ pool = NULL; status = pTpAllocPool(&pool, NULL); ok(!status, "TpAllocPool failed with status %x\n", status); ok(pool != NULL, "expected pool != NULL\n"); memset(&environment, 0, sizeof(environment)); environment.Version = 1; environment.Pool = pool; /* create semaphores and corresponding wait objects */ for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++) { semaphores[i] = CreateSemaphoreW(NULL, 0, 1, NULL); ok(semaphores[i] != NULL, "failed to create semaphore %i\n", i); waits[i] = NULL; status = pTpAllocWait(&waits[i], multi_wait_cb, (void *)(DWORD_PTR)i, &environment); ok(!status, "TpAllocWait failed with status %x\n", status); ok(waits[i] != NULL, "expected waits[%d] != NULL\n", i); pTpSetWait(waits[i], semaphores[i], NULL); } /* release all semaphores and wait for callback */ for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++) { multi_wait_info.result = 0; ReleaseSemaphore(semaphores[i], 1, NULL); result = WaitForSingleObject(semaphore, 100); ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result); ok(multi_wait_info.result == i, "expected result %d, got %u\n", i, multi_wait_info.result); pTpSetWait(waits[i], semaphores[i], NULL); } /* repeat the same test in reverse order */ for (i = sizeof(semaphores)/sizeof(semaphores[0]) - 1; i >= 0; i--) { multi_wait_info.result = 0; ReleaseSemaphore(semaphores[i], 1, NULL); result = WaitForSingleObject(semaphore, 100); ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result); ok(multi_wait_info.result == i, "expected result %d, got %u\n", i, multi_wait_info.result); pTpSetWait(waits[i], semaphores[i], NULL); } /* test timeout of wait objects */ multi_wait_info.result = 0; for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++) { when.QuadPart = (ULONGLONG)50 * -10000; pTpSetWait(waits[i], semaphores[i], &when); } for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++) { result = WaitForSingleObject(semaphore, 150); ok(result == WAIT_OBJECT_0, "WaitForSingleObject returned %u\n", result); } ok(multi_wait_info.result >> 16, "expected multi_wait_info.result >> 16 != 0\n"); /* destroy the wait objects and semaphores while waiting */ for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++) { pTpSetWait(waits[i], semaphores[i], NULL); } Sleep(50); for (i = 0; i < sizeof(semaphores)/sizeof(semaphores[0]); i++) { pTpReleaseWait(waits[i]); NtClose(semaphores[i]); } pTpReleasePool(pool); CloseHandle(semaphore); }
/*********************************************************************** * TIME_GetSpecificTimeZoneInfo * * Returns time zone information for the given time zone and year. * * PARAMS * key_name [in] The time zone name. * year [in] The year, if Dynamic DST is used. * dynamic [in] Whether to use Dynamic DST. * result [out] The time zone information. * * RETURNS * TRUE if successful. */ static BOOL TIME_GetSpecificTimeZoneInfo( const WCHAR *key_name, WORD year, BOOL dynamic, DYNAMIC_TIME_ZONE_INFORMATION *tzinfo ) { static const WCHAR Dynamic_DstW[] = { 'D','y','n','a','m','i','c',' ','D','S','T',0 }; static const WCHAR fmtW[] = { '%','d',0 }; static const WCHAR stdW[] = { 'S','t','d',0 }; static const WCHAR dltW[] = { 'D','l','t',0 }; static const WCHAR tziW[] = { 'T','Z','I',0 }; HANDLE time_zone_key, dynamic_dst_key; OBJECT_ATTRIBUTES attr; UNICODE_STRING nameW; WCHAR yearW[16]; BOOL got_reg_data = FALSE; struct tz_reg_data { LONG bias; LONG std_bias; LONG dlt_bias; SYSTEMTIME std_date; SYSTEMTIME dlt_date; } tz_data; if (!TIME_GetSpecificTimeZoneKey( key_name, &time_zone_key )) return FALSE; if (!reg_query_value( time_zone_key, stdW, REG_SZ, tzinfo->StandardName, sizeof(tzinfo->StandardName)) || !reg_query_value( time_zone_key, dltW, REG_SZ, tzinfo->DaylightName, sizeof(tzinfo->DaylightName))) { NtClose( time_zone_key ); return FALSE; } lstrcpyW(tzinfo->TimeZoneKeyName, key_name); if (dynamic) { attr.Length = sizeof(attr); attr.RootDirectory = time_zone_key; attr.ObjectName = &nameW; attr.Attributes = 0; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; RtlInitUnicodeString( &nameW, Dynamic_DstW ); if (!NtOpenKey( &dynamic_dst_key, KEY_READ, &attr )) { sprintfW( yearW, fmtW, year ); got_reg_data = reg_query_value( dynamic_dst_key, yearW, REG_BINARY, &tz_data, sizeof(tz_data) ); NtClose( dynamic_dst_key ); } } if (!got_reg_data) { if (!reg_query_value( time_zone_key, tziW, REG_BINARY, &tz_data, sizeof(tz_data) )) { NtClose( time_zone_key ); return FALSE; } } tzinfo->Bias = tz_data.bias; tzinfo->StandardBias = tz_data.std_bias; tzinfo->DaylightBias = tz_data.dlt_bias; tzinfo->StandardDate = tz_data.std_date; tzinfo->DaylightDate = tz_data.dlt_date; tzinfo->DynamicDaylightTimeDisabled = !dynamic; NtClose( time_zone_key ); return TRUE; }
/** * Deal with getting info about something that could be in a directory object. * * @returns IPRT status code * @param pObjAttr The NT object attribute. * @param pObjInfo Where to return the info. * @param enmAddAttr Which extra attributes to get (/fake). * @param fFlags The flags. * @param pvBuf Query buffer space. * @param cbBuf Size of the buffer. ASSUMES lots of space. * @param rcNtCaller The status code that got us here. */ static int rtPathNtQueryInfoInDirectoryObject(OBJECT_ATTRIBUTES *pObjAttr, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr, uint32_t fFlags, void *pvBuf, size_t cbBuf, NTSTATUS rcNtCaller) { RT_NOREF(fFlags); /* * Special case: Root dir. */ if ( pObjAttr->RootDirectory == NULL && pObjAttr->ObjectName->Length == sizeof(RTUTF16) && pObjAttr->ObjectName->Buffer[0] == '\\') { pObjInfo->cbObject = 0; pObjInfo->cbAllocated = 0; RTTimeSpecSetNtTime(&pObjInfo->BirthTime, 0); RTTimeSpecSetNtTime(&pObjInfo->AccessTime, 0); RTTimeSpecSetNtTime(&pObjInfo->ModificationTime, 0); RTTimeSpecSetNtTime(&pObjInfo->ChangeTime, 0); pObjInfo->Attr.fMode = RTFS_DOS_DIRECTORY | RTFS_TYPE_DIRECTORY | 0777; return rtPathNtQueryInfoFillInDummyData(VINF_SUCCESS, pObjInfo, enmAddAttr); } /* * We must open and scan the parent directory object. */ UNICODE_STRING NtDirName; UNICODE_STRING NtDirEntry; ntPathNtSplitName(pObjAttr->ObjectName, &NtDirName, &NtDirEntry, true /*fNoParentDirSlash*/); while ( NtDirEntry.Length > sizeof(RTUTF16) && NtDirEntry.Buffer[NtDirEntry.Length / sizeof(RTUTF16) - 1] == '\\') NtDirEntry.Length -= sizeof(RTUTF16); pObjAttr->ObjectName = &NtDirName; HANDLE hDir = RTNT_INVALID_HANDLE_VALUE; NTSTATUS rcNt = NtOpenDirectoryObject(&hDir, DIRECTORY_QUERY | DIRECTORY_TRAVERSE, pObjAttr); if (NT_SUCCESS(rcNt)) { ULONG uObjDirCtx = 0; for (;;) { ULONG cbReturned = 0; rcNt = NtQueryDirectoryObject(hDir, pvBuf, (ULONG)cbBuf, FALSE /*ReturnSingleEntry */, FALSE /*RestartScan*/, &uObjDirCtx, &cbReturned); if (!NT_SUCCESS(rcNt)) break; for (POBJECT_DIRECTORY_INFORMATION pObjDir = (POBJECT_DIRECTORY_INFORMATION)pvBuf; pObjDir->Name.Length != 0; pObjDir++) { if ( pObjDir->Name.Length == NtDirEntry.Length && memcmp(pObjDir->Name.Buffer, NtDirEntry.Buffer, NtDirEntry.Length) == 0) { /* * Find it. Fill in the info we've got and return (see similar code in direnum-r3-nt.cpp). */ NtClose(hDir); pObjInfo->cbObject = 0; pObjInfo->cbAllocated = 0; RTTimeSpecSetNtTime(&pObjInfo->BirthTime, 0); RTTimeSpecSetNtTime(&pObjInfo->AccessTime, 0); RTTimeSpecSetNtTime(&pObjInfo->ModificationTime, 0); RTTimeSpecSetNtTime(&pObjInfo->ChangeTime, 0); if (ARE_UNICODE_STRINGS_EQUAL(&pObjDir->TypeName, L"Directory")) pObjInfo->Attr.fMode = RTFS_DOS_DIRECTORY | RTFS_TYPE_DIRECTORY | 0777; else if (ARE_UNICODE_STRINGS_EQUAL(&pObjDir->TypeName, L"SymbolicLink")) pObjInfo->Attr.fMode = RTFS_DOS_NT_REPARSE_POINT | RTFS_TYPE_SYMLINK | 0777; else if (ARE_UNICODE_STRINGS_EQUAL(&pObjDir->TypeName, L"Device")) pObjInfo->Attr.fMode = RTFS_DOS_NT_DEVICE | RTFS_TYPE_DEV_CHAR | 0666; else pObjInfo->Attr.fMode = RTFS_DOS_NT_NORMAL | RTFS_TYPE_FILE | 0666; pObjInfo->Attr.enmAdditional = enmAddAttr; return rtPathNtQueryInfoFillInDummyData(VINF_SUCCESS, pObjInfo, enmAddAttr); } } } NtClose(hDir); if (rcNt == STATUS_NO_MORE_FILES || rcNt == STATUS_NO_MORE_ENTRIES || rcNt == STATUS_NO_SUCH_FILE) return VERR_FILE_NOT_FOUND; } else return RTErrConvertFromNtStatus(rcNtCaller); return RTErrConvertFromNtStatus(rcNt); }
static VOID PhpRefreshProcessList( _In_ HWND hwndDlg, _In_ PCHOOSE_PROCESS_DIALOG_CONTEXT Context ) { NTSTATUS status; HWND lvHandle; PVOID processes; PSYSTEM_PROCESS_INFORMATION process; lvHandle = Context->ListViewHandle; ListView_DeleteAllItems(lvHandle); ImageList_RemoveAll(Context->ImageList); if (!NT_SUCCESS(status = PhEnumProcesses(&processes))) { PhShowStatus(hwndDlg, L"Unable to enumerate processes", status, 0); return; } ExtendedListView_SetRedraw(lvHandle, FALSE); process = PH_FIRST_PROCESS(processes); do { INT lvItemIndex; PPH_STRING name; HANDLE processHandle; PPH_STRING fileName = NULL; HICON icon = NULL; WCHAR processIdString[PH_INT32_STR_LEN_1]; PPH_STRING userName = NULL; INT imageIndex; if (process->UniqueProcessId != SYSTEM_IDLE_PROCESS_ID) name = PhCreateStringFromUnicodeString(&process->ImageName); else name = PhCreateString(SYSTEM_IDLE_PROCESS_NAME); lvItemIndex = PhAddListViewItem(lvHandle, MAXINT, name->Buffer, process->UniqueProcessId); PhDereferenceObject(name); if (NT_SUCCESS(PhOpenProcess(&processHandle, ProcessQueryAccess, process->UniqueProcessId))) { HANDLE tokenHandle; PTOKEN_USER user; if (!WINDOWS_HAS_IMAGE_FILE_NAME_BY_PROCESS_ID && process->UniqueProcessId != SYSTEM_PROCESS_ID) PhGetProcessImageFileName(processHandle, &fileName); if (NT_SUCCESS(PhOpenProcessToken(&tokenHandle, TOKEN_QUERY, processHandle))) { if (NT_SUCCESS(PhGetTokenUser(tokenHandle, &user))) { userName = PhGetSidFullName(user->User.Sid, TRUE, NULL); PhFree(user); } NtClose(tokenHandle); } NtClose(processHandle); } if (process->UniqueProcessId == SYSTEM_IDLE_PROCESS_ID && !userName && PhLocalSystemName) PhSetReference(&userName, PhLocalSystemName); if (WINDOWS_HAS_IMAGE_FILE_NAME_BY_PROCESS_ID && process->UniqueProcessId != SYSTEM_PROCESS_ID) PhGetProcessImageFileNameByProcessId(process->UniqueProcessId, &fileName); if (process->UniqueProcessId == SYSTEM_PROCESS_ID) fileName = PhGetKernelFileName(); if (fileName) PhMoveReference(&fileName, PhGetFileName(fileName)); icon = PhGetFileShellIcon(PhGetString(fileName), L".exe", FALSE); // Icon if (icon) { imageIndex = ImageList_AddIcon(Context->ImageList, icon); PhSetListViewItemImageIndex(Context->ListViewHandle, lvItemIndex, imageIndex); DestroyIcon(icon); } // PID PhPrintUInt32(processIdString, HandleToUlong(process->UniqueProcessId)); PhSetListViewSubItem(Context->ListViewHandle, lvItemIndex, 1, processIdString); // User Name PhSetListViewSubItem(Context->ListViewHandle, lvItemIndex, 2, PhGetString(userName)); if (userName) PhDereferenceObject(userName); if (fileName) PhDereferenceObject(fileName); } while (process = PH_NEXT_PROCESS(process)); PhFree(processes); ExtendedListView_SortItems(lvHandle); ExtendedListView_SetRedraw(lvHandle, TRUE); }
/** * Worker for RTPathQueryInfoEx and RTDirRelPathQueryInfo. * * @returns IPRT status code. * @param hRootDir The root directory that pNtName is relative to. * @param pNtName The NT path which we want to query info for. * @param pObjInfo Where to return the info. * @param enmAddAttr What additional info to get/fake. * @param fFlags Query flags (RTPATH_F_XXX). * @param pszPath The path for detecting executables and such. * Pass empty string if not applicable/available. */ DECLHIDDEN(int) rtPathNtQueryInfoWorker(HANDLE hRootDir, UNICODE_STRING *pNtName, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr, uint32_t fFlags, const char *pszPath) { /* * There are a three different ways of doing this: * 1. Use NtQueryFullAttributesFile to the get basic file info. * 2. Open whatever the path points to and use NtQueryInformationFile. * 3. Open the parent directory and use NtQueryDirectoryFile like RTDirReadEx. * * The first two options may fail with sharing violations or access denied, * in which case we must use the last one as fallback. */ HANDLE hFile = RTNT_INVALID_HANDLE_VALUE; IO_STATUS_BLOCK Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER; NTSTATUS rcNt; OBJECT_ATTRIBUTES ObjAttr; union { FILE_NETWORK_OPEN_INFORMATION NetOpenInfo; FILE_ALL_INFORMATION AllInfo; FILE_FS_VOLUME_INFORMATION VolInfo; FILE_BOTH_DIR_INFORMATION Both; FILE_ID_BOTH_DIR_INFORMATION BothId; uint8_t abPadding[sizeof(FILE_ID_BOTH_DIR_INFORMATION) + RTPATH_MAX * sizeof(wchar_t)]; } uBuf; /* * We can only use the first option if no additional UNIX attribs are * requested and it isn't a symbolic link. NT directory object */ int rc = VINF_TRY_AGAIN; if ( enmAddAttr != RTFSOBJATTRADD_UNIX && g_pfnNtQueryFullAttributesFile) { InitializeObjectAttributes(&ObjAttr, pNtName, OBJ_CASE_INSENSITIVE, hRootDir, NULL); rcNt = g_pfnNtQueryFullAttributesFile(&ObjAttr, &uBuf.NetOpenInfo); if (NT_SUCCESS(rcNt)) { if (!(uBuf.NetOpenInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { pObjInfo->cbObject = uBuf.NetOpenInfo.EndOfFile.QuadPart; pObjInfo->cbAllocated = uBuf.NetOpenInfo.AllocationSize.QuadPart; RTTimeSpecSetNtTime(&pObjInfo->BirthTime, uBuf.NetOpenInfo.CreationTime.QuadPart); RTTimeSpecSetNtTime(&pObjInfo->AccessTime, uBuf.NetOpenInfo.LastAccessTime.QuadPart); RTTimeSpecSetNtTime(&pObjInfo->ModificationTime, uBuf.NetOpenInfo.LastWriteTime.QuadPart); RTTimeSpecSetNtTime(&pObjInfo->ChangeTime, uBuf.NetOpenInfo.ChangeTime.QuadPart); pObjInfo->Attr.fMode = rtFsModeFromDos((uBuf.NetOpenInfo.FileAttributes << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT, pszPath, strlen(pszPath), 0 /*uReparseTag*/); pObjInfo->Attr.enmAdditional = enmAddAttr; return rtPathNtQueryInfoFillInDummyData(VINF_SUCCESS, pObjInfo, enmAddAttr); } } else if ( rcNt == STATUS_OBJECT_TYPE_MISMATCH || rcNt == STATUS_OBJECT_NAME_INVALID || rcNt == STATUS_INVALID_PARAMETER) { rc = rtPathNtQueryInfoInDirectoryObject(&ObjAttr, pObjInfo, enmAddAttr, fFlags, &uBuf, sizeof(uBuf), rcNt); if (RT_SUCCESS(rc)) return rc; } else if ( rcNt != STATUS_ACCESS_DENIED && rcNt != STATUS_SHARING_VIOLATION) rc = RTErrConvertFromNtStatus(rcNt); else RTNT_IO_STATUS_BLOCK_REINIT(&Ios); } /* * Try the 2nd option. We might have to redo this if not following symbolic * links and the reparse point isn't a symbolic link but a mount point or similar. * We want to return information about the mounted root directory if we can, not * the directory in which it was mounted. */ if (rc == VINF_TRY_AGAIN) { static int volatile g_fReparsePoints = -1; uint32_t fOptions = FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT; int fReparsePoints = g_fReparsePoints; if (fReparsePoints != 0 && !(fFlags & RTPATH_F_FOLLOW_LINK)) fOptions |= FILE_OPEN_REPARSE_POINT; InitializeObjectAttributes(&ObjAttr, pNtName, OBJ_CASE_INSENSITIVE, hRootDir, NULL); rcNt = NtCreateFile(&hFile, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &ObjAttr, &Ios, NULL /*pcbFile*/, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, fOptions, NULL /*pvEaBuffer*/, 0 /*cbEa*/); if ( ( rcNt == STATUS_INVALID_PARAMETER || rcNt == STATUS_INVALID_PARAMETER_9) && fReparsePoints == -1 && (fOptions & FILE_OPEN_REPARSE_POINT)) { fOptions &= ~FILE_OPEN_REPARSE_POINT; rcNt = NtCreateFile(&hFile, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &ObjAttr, &Ios, NULL /*pcbFile*/, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, fOptions, NULL /*pvEaBuffer*/, 0 /*cbEa*/); if (rcNt != STATUS_INVALID_PARAMETER) g_fReparsePoints = fReparsePoints = 0; } if (NT_SUCCESS(rcNt)) { /* Query tag information first in order to try re-open non-symlink reparse points. */ FILE_ATTRIBUTE_TAG_INFORMATION TagInfo; rcNt = NtQueryInformationFile(hFile, &Ios, &TagInfo, sizeof(TagInfo), FileAttributeTagInformation); if (!NT_SUCCESS(rcNt)) TagInfo.FileAttributes = TagInfo.ReparseTag = 0; if ( !(TagInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) || TagInfo.ReparseTag == IO_REPARSE_TAG_SYMLINK || (fFlags & RTPATH_F_FOLLOW_LINK)) { /* likely */ } else { /* Reparse point that isn't a symbolic link, try follow the reparsing. */ HANDLE hFile2; RTNT_IO_STATUS_BLOCK_REINIT(&Ios); rcNt = NtCreateFile(&hFile2, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &ObjAttr, &Ios, NULL /*pcbFile*/, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT, NULL /*pvEaBuffer*/, 0 /*cbEa*/); if (NT_SUCCESS(rcNt)) { NtClose(hFile); hFile = hFile2; TagInfo.FileAttributes = TagInfo.ReparseTag = 0; } } /* * Get the information we need and convert it. */ rc = rtPathNtQueryInfoFromHandle(hFile, &uBuf, sizeof(uBuf), pObjInfo, enmAddAttr, pszPath, TagInfo.ReparseTag); NtClose(hFile); if (RT_SUCCESS(rc)) return rc; if (RT_FAILURE(rc)) rc = VINF_TRY_AGAIN; } else if ( rcNt == STATUS_OBJECT_TYPE_MISMATCH || rcNt == STATUS_OBJECT_NAME_INVALID /*|| rcNt == STATUS_INVALID_PARAMETER*/) { rc = rtPathNtQueryInfoInDirectoryObject(&ObjAttr, pObjInfo, enmAddAttr, fFlags, &uBuf, sizeof(uBuf), rcNt); if (RT_SUCCESS(rc)) return rc; } else if ( rcNt != STATUS_ACCESS_DENIED && rcNt != STATUS_SHARING_VIOLATION) rc = RTErrConvertFromNtStatus(rcNt); else RTNT_IO_STATUS_BLOCK_REINIT(&Ios); } /* * Try the 3rd option if none of the other worked. * If none of the above worked, try open the directory and enumerate * the file we're after. This */ if (rc == VINF_TRY_AGAIN) { /* Split up the name into parent directory path and filename. */ UNICODE_STRING NtDirName; UNICODE_STRING NtFilter; ntPathNtSplitName(pNtName, &NtDirName, &NtFilter, false /*fNoParentDirSlash*/); /* Try open the directory. */ InitializeObjectAttributes(&ObjAttr, &NtDirName, OBJ_CASE_INSENSITIVE, hRootDir, NULL); rcNt = NtCreateFile(&hFile, FILE_LIST_DIRECTORY | SYNCHRONIZE, &ObjAttr, &Ios, NULL /*pcbFile*/, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT, NULL /*pvEaBuffer*/, 0 /*cbEa*/); if (NT_SUCCESS(rcNt)) { FILE_INFORMATION_CLASS enmInfoClass; if (RT_MAKE_U64(RTNtCurrentPeb()->OSMinorVersion, RTNtCurrentPeb()->OSMajorVersion) > RT_MAKE_U64(0,5) /* > W2K */) enmInfoClass = FileIdBothDirectoryInformation; /* Introduced in XP, from I can tell. */ else enmInfoClass = FileBothDirectoryInformation; rcNt = NtQueryDirectoryFile(hFile, NULL /* Event */, NULL /* ApcRoutine */, NULL /* ApcContext */, &Ios, &uBuf, RT_MIN(sizeof(uBuf), 0xfff0), enmInfoClass, TRUE /*ReturnSingleEntry */, &NtFilter, FALSE /*RestartScan */); if (NT_SUCCESS(rcNt)) { pObjInfo->cbObject = uBuf.Both.EndOfFile.QuadPart; pObjInfo->cbAllocated = uBuf.Both.AllocationSize.QuadPart; RTTimeSpecSetNtTime(&pObjInfo->BirthTime, uBuf.Both.CreationTime.QuadPart); RTTimeSpecSetNtTime(&pObjInfo->AccessTime, uBuf.Both.LastAccessTime.QuadPart); RTTimeSpecSetNtTime(&pObjInfo->ModificationTime, uBuf.Both.LastWriteTime.QuadPart); RTTimeSpecSetNtTime(&pObjInfo->ChangeTime, uBuf.Both.ChangeTime.QuadPart); pObjInfo->Attr.fMode = rtFsModeFromDos((uBuf.Both.FileAttributes << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT, pszPath, strlen(pszPath), uBuf.Both.EaSize); pObjInfo->Attr.enmAdditional = enmAddAttr; if (enmAddAttr == RTFSOBJATTRADD_UNIX) { pObjInfo->Attr.u.Unix.uid = ~0U; pObjInfo->Attr.u.Unix.gid = ~0U; pObjInfo->Attr.u.Unix.cHardlinks = 1; pObjInfo->Attr.u.Unix.INodeIdDevice = 0; /* below */ pObjInfo->Attr.u.Unix.INodeId = enmInfoClass == FileIdBothDirectoryInformation ? uBuf.BothId.FileId.QuadPart : 0; pObjInfo->Attr.u.Unix.fFlags = 0; pObjInfo->Attr.u.Unix.GenerationId = 0; pObjInfo->Attr.u.Unix.Device = 0; /* Get the serial number. */ rcNt = NtQueryVolumeInformationFile(hFile, &Ios, &uBuf, RT_MIN(sizeof(uBuf), _2K), FileFsVolumeInformation); if (NT_SUCCESS(rcNt)) pObjInfo->Attr.u.Unix.INodeIdDevice = uBuf.VolInfo.VolumeSerialNumber; } rc = rtPathNtQueryInfoFillInDummyData(VINF_SUCCESS, pObjInfo, enmAddAttr); } else rc = RTErrConvertFromNtStatus(rcNt); NtClose(hFile); } /* * Quite possibly a object directory. */ else if ( rcNt == STATUS_OBJECT_NAME_INVALID /* with trailing slash */ || rcNt == STATUS_OBJECT_TYPE_MISMATCH /* without trailing slash */ ) { InitializeObjectAttributes(&ObjAttr, pNtName, OBJ_CASE_INSENSITIVE, hRootDir, NULL); rc = rtPathNtQueryInfoInDirectoryObject(&ObjAttr, pObjInfo, enmAddAttr, fFlags, &uBuf, sizeof(uBuf), rcNt); if (RT_FAILURE(rc)) rc = RTErrConvertFromNtStatus(rcNt); } else rc = RTErrConvertFromNtStatus(rcNt); } return rc; }
NTSTATUS DeleteFile2(LPCWSTR FilePath) { UNICODE_STRING usFileName; if (!RtlDosPathNameToNtPathName_U(FilePath, &usFileName, NULL, NULL)) { return RtlGetLastNtStatus(); } OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(OBJECT_ATTRIBUTES), NULL, &usFileName, OBJ_CASE_INSENSITIVE }; HANDLE hFile; IO_STATUS_BLOCK IoStatusBlock; auto Status = NtOpenFile(&hFile, FILE_READ_ATTRIBUTES | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_DELETE | FILE_SHARE_READ, FILE_OPEN_REPARSE_POINT | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); if (Status) { goto Error2; } FILE_ATTRIBUTE_TAG_INFORMATION FileAttributeTagInfo; Status = NtQueryInformationFile(hFile, &IoStatusBlock, &FileAttributeTagInfo, sizeof(FileAttributeTagInfo), FileAttributeTagInformation); NtClose(hFile); if (Status) { goto Error2; } if (FileAttributeTagInfo.FileAttributes&FILE_ATTRIBUTE_READONLY) { if (Status = NtSetFileAttributes(&ObjectAttributes, FileAttributeTagInfo.FileAttributes^FILE_ATTRIBUTE_READONLY)) goto Error2; } if (FileAttributeTagInfo.FileAttributes&FILE_ATTRIBUTE_REPARSE_POINT) { if (IsReparseTagNameSurrogate(FileAttributeTagInfo.ReparseTag)) goto Delete; } if (FileAttributeTagInfo.FileAttributes&FILE_ATTRIBUTE_DIRECTORY) { if (Status = DeleteDirectoryInternal(ObjectAttributes)) goto Error; } Delete: Status = NtDeleteFile2(&ObjectAttributes); Error: if (FileAttributeTagInfo.FileAttributes&FILE_ATTRIBUTE_REPARSE_POINT) { NtSetFileAttributes(&ObjectAttributes, FileAttributeTagInfo.FileAttributes); } Error2: RtlFreeUnicodeString(&usFileName); return Status; }
BOOLEAN ExpInitializeCallbacks ( ) /*++ Routine Description: This function creates the callback object type descriptor at system initialization and stores the address of the object type descriptor in local static storage. Arguments: None. Return Value: A value of TRUE is returned if the timer object type descriptor is successfully initialized. Otherwise a value of FALSE is returned. --*/ { #ifdef _PNP_POWER_ OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; OBJECT_ATTRIBUTES ObjectAttributes; NTSTATUS Status; UNICODE_STRING unicodeString; ULONG i; HANDLE handle; // // Initialize string descriptor. // RtlInitUnicodeString(&unicodeString, L"Callback"); // // Create timer object type descriptor. // RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK; ObjectTypeInitializer.GenericMapping = ExpCallbackMapping; ObjectTypeInitializer.DeleteProcedure = ExpDeleteCallback; ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.ValidAccessMask = CALLBACK_ALL_ACCESS; Status = ObCreateObjectType(&unicodeString, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR)NULL, &ExCallbackObjectType); if (!NT_SUCCESS(Status)) { return FALSE; } RtlInitUnicodeString( &unicodeString, ExpWstrCallback ); InitializeObjectAttributes( &ObjectAttributes, &unicodeString, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, NULL, SePublicDefaultSd ); Status = NtCreateDirectoryObject( &handle, DIRECTORY_ALL_ACCESS, &ObjectAttributes ); if (!NT_SUCCESS(Status)) { return FALSE; } NtClose (handle); // // Initialize event to wait on for Unregisters which occur while // notifications are in progress // KeInitializeEvent (&ExpCallbackEvent, NotificationEvent, 0); // // Initialize NT global callbacks // for (i=0; ExpInitializeCallback[i].CallBackObject; i++) { // // Create named calledback // RtlInitUnicodeString(&unicodeString, ExpInitializeCallback[i].CallbackName); InitializeObjectAttributes( &ObjectAttributes, &unicodeString, OBJ_PERMANENT | OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = ExCreateCallback ( ExpInitializeCallback[i].CallBackObject, &ObjectAttributes, TRUE, TRUE ); if (!NT_SUCCESS(Status)) { return FALSE; } } #endif return TRUE; }
NTSTATUS DeleteDirectoryInternal(OBJECT_ATTRIBUTES ObjectAttributes) { HANDLE hFile; //OBJECT_ATTRIBUTES ObjectAttributes = { sizeof(OBJECT_ATTRIBUTES), hRootDir, (UNICODE_STRING*)&FileName, OBJ_CASE_INSENSITIVE }; IO_STATUS_BLOCK IoStatusBlock; auto Status = NtOpenFile(&hFile, SYNCHRONIZE | FILE_LIST_DIRECTORY, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_VALID_FLAGS, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); if (Status) return Status; byte Buffer[sizeof(FILE_FULL_DIR_INFORMATION) + 512]; FILE_FULL_DIR_INFORMATION & FileInfo = *(FILE_FULL_DIR_INFORMATION *)Buffer; UNICODE_STRING TempFileName = { 0,0,FileInfo.FileName }; ObjectAttributes.RootDirectory = hFile; ObjectAttributes.ObjectName = &TempFileName; NTSTATUS Error = 0; while (ZwQueryDirectoryFile(hFile, NULL, NULL, NULL, &IoStatusBlock, Buffer, sizeof(Buffer), FileFullDirectoryInformation, -1, NULL, 0) == ERROR_SUCCESS) { TempFileName.Length = TempFileName.MaximumLength = FileInfo.FileNameLength; if (FileInfo.FileAttributes&FILE_ATTRIBUTE_DIRECTORY) { if ((FileInfo.FileAttributes&FILE_ATTRIBUTE_REPARSE_POINT)) { if (IsReparseTagNameSurrogate(FileInfo.EaSize)) goto StartDelete; } else { if (IsDots(FileInfo.FileName, FileInfo.FileNameLength)) continue; } if (Error = DeleteDirectoryInternal(ObjectAttributes)) { goto OnError; } } StartDelete: if (FileInfo.FileAttributes&FILE_ATTRIBUTE_READONLY) { //取消只读属性 if (Error = NtSetFileAttributes(&ObjectAttributes, FileInfo.FileAttributes^FILE_ATTRIBUTE_READONLY)) { goto OnError; } } if (Error = NtDeleteFile2(&ObjectAttributes)) { if (FileInfo.FileAttributes&FILE_ATTRIBUTE_READONLY) { //删除失败恢复只读属性 NtSetFileAttributes(&ObjectAttributes, FileInfo.FileAttributes); } OnError: Status = Error; } } //End: NtClose(hFile); return Status; }
USHORT NTAPI PipGetDriverTagPriority(IN HANDLE ServiceHandle) { NTSTATUS Status; HANDLE KeyHandle = NULL; PKEY_VALUE_FULL_INFORMATION KeyValueInformation = NULL; PKEY_VALUE_FULL_INFORMATION KeyValueInformationTag; PKEY_VALUE_FULL_INFORMATION KeyValueInformationGroupOrderList; PVOID Buffer; UNICODE_STRING Group; PULONG GroupOrder; ULONG Count, Tag = 0; USHORT i = -1; UNICODE_STRING GroupString = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet" L"\\Control\\ServiceGroupOrder"); /* Open the key */ Status = IopOpenRegistryKeyEx(&KeyHandle, NULL, &GroupString, KEY_READ); if (!NT_SUCCESS(Status)) goto Quickie; /* Read the group */ Status = IopGetRegistryValue(ServiceHandle, L"Group", &KeyValueInformation); if (!NT_SUCCESS(Status)) goto Quickie; /* Make sure we have a group */ if ((KeyValueInformation->Type == REG_SZ) && (KeyValueInformation->DataLength)) { /* Convert to unicode string */ Buffer = (PVOID)((ULONG_PTR)KeyValueInformation + KeyValueInformation->DataOffset); PnpRegSzToString(Buffer, KeyValueInformation->DataLength, &Group.Length); Group.MaximumLength = (USHORT)KeyValueInformation->DataLength; Group.Buffer = Buffer; } /* Now read the tag */ Status = IopGetRegistryValue(ServiceHandle, L"Tag", &KeyValueInformationTag); if (!NT_SUCCESS(Status)) goto Quickie; /* Make sure we have a tag */ if ((KeyValueInformationTag->Type == REG_DWORD) && (KeyValueInformationTag->DataLength)) { /* Read it */ Tag = *(PULONG)((ULONG_PTR)KeyValueInformationTag + KeyValueInformationTag->DataOffset); } /* We can get rid of this now */ ExFreePool(KeyValueInformationTag); /* Now let's read the group's tag order */ Status = IopGetRegistryValue(KeyHandle, Group.Buffer, &KeyValueInformationGroupOrderList); /* We can get rid of this now */ Quickie: if (KeyValueInformation) ExFreePool(KeyValueInformation); if (KeyHandle) NtClose(KeyHandle); if (!NT_SUCCESS(Status)) return -1; /* We're on the success path -- validate the tag order*/ if ((KeyValueInformationGroupOrderList->Type == REG_BINARY) && (KeyValueInformationGroupOrderList->DataLength)) { /* Get the order array */ GroupOrder = (PULONG)((ULONG_PTR)KeyValueInformationGroupOrderList + KeyValueInformationGroupOrderList->DataOffset); /* Get the count */ Count = *GroupOrder; ASSERT(((Count + 1) * sizeof(ULONG)) <= KeyValueInformationGroupOrderList->DataLength); /* Now loop each tag */ GroupOrder++; for (i = 1; i <= Count; i++) { /* If we found it, we're out */ if (Tag == *GroupOrder) break; /* Try the next one */ GroupOrder++; } } /* Last buffer to free */ ExFreePool(KeyValueInformationGroupOrderList); return i; }
// 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 INIT_FUNCTION IopInitializePlugPlayServices(VOID) { NTSTATUS Status; ULONG Disposition; HANDLE KeyHandle, EnumHandle, ParentHandle, TreeHandle, ControlHandle; UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"); UNICODE_STRING PnpManagerDriverName = RTL_CONSTANT_STRING(DRIVER_ROOT_NAME L"PnpManager"); PDEVICE_OBJECT Pdo; /* Initialize locks and such */ KeInitializeSpinLock(&IopDeviceTreeLock); KeInitializeSpinLock(&IopDeviceRelationsSpinLock); InitializeListHead(&IopDeviceRelationsRequestList); /* Get the default interface */ PnpDefaultInterfaceType = IopDetermineDefaultInterfaceType(); /* Initialize arbiters */ Status = IopInitializeArbiters(); if (!NT_SUCCESS(Status)) return Status; /* Setup the group cache */ Status = PiInitCacheGroupInformation(); if (!NT_SUCCESS(Status)) return Status; /* Open the current control set */ Status = IopOpenRegistryKeyEx(&KeyHandle, NULL, &KeyName, KEY_ALL_ACCESS); if (!NT_SUCCESS(Status)) return Status; /* Create the control key */ RtlInitUnicodeString(&KeyName, L"Control"); Status = IopCreateRegistryKeyEx(&ControlHandle, KeyHandle, &KeyName, KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, &Disposition); if (!NT_SUCCESS(Status)) return Status; /* Check if it's a new key */ if (Disposition == REG_CREATED_NEW_KEY) { HANDLE DeviceClassesHandle; /* Create the device classes key */ RtlInitUnicodeString(&KeyName, L"DeviceClasses"); Status = IopCreateRegistryKeyEx(&DeviceClassesHandle, ControlHandle, &KeyName, KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, &Disposition); if (!NT_SUCCESS(Status)) return Status; ZwClose(DeviceClassesHandle); } ZwClose(ControlHandle); /* Create the enum key */ RtlInitUnicodeString(&KeyName, REGSTR_KEY_ENUM); Status = IopCreateRegistryKeyEx(&EnumHandle, KeyHandle, &KeyName, KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, &Disposition); if (!NT_SUCCESS(Status)) return Status; /* Check if it's a new key */ if (Disposition == REG_CREATED_NEW_KEY) { /* FIXME: DACLs */ DPRINT1("Need to build DACL\n"); } /* Create the root key */ ParentHandle = EnumHandle; RtlInitUnicodeString(&KeyName, REGSTR_KEY_ROOTENUM); Status = IopCreateRegistryKeyEx(&EnumHandle, ParentHandle, &KeyName, KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, &Disposition); NtClose(ParentHandle); if (!NT_SUCCESS(Status)) return Status; NtClose(EnumHandle); /* Open the root key now */ RtlInitUnicodeString(&KeyName, L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM"); Status = IopOpenRegistryKeyEx(&EnumHandle, NULL, &KeyName, KEY_ALL_ACCESS); if (NT_SUCCESS(Status)) { /* Create the root dev node */ RtlInitUnicodeString(&KeyName, REGSTR_VAL_ROOT_DEVNODE); Status = IopCreateRegistryKeyEx(&TreeHandle, EnumHandle, &KeyName, KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, NULL); NtClose(EnumHandle); if (NT_SUCCESS(Status)) NtClose(TreeHandle); } /* Create the root driver */ Status = IoCreateDriver(&PnpManagerDriverName, PnpRootDriverEntry); if (!NT_SUCCESS(Status)) { DPRINT1("IoCreateDriverObject() failed\n"); KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0); } /* Create the root PDO */ Status = IoCreateDevice(IopRootDriverObject, sizeof(IOPNP_DEVICE_EXTENSION), NULL, FILE_DEVICE_CONTROLLER, 0, FALSE, &Pdo); if (!NT_SUCCESS(Status)) { DPRINT1("IoCreateDevice() failed\n"); KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0); } /* This is a bus enumerated device */ Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; /* Create the root device node */ IopRootDeviceNode = PipAllocateDeviceNode(Pdo); /* Set flags */ IopRootDeviceNode->Flags |= DNF_STARTED + DNF_PROCESSED + DNF_ENUMERATED + DNF_MADEUP + DNF_NO_RESOURCE_REQUIRED + DNF_ADDED; /* Create instance path */ RtlCreateUnicodeString(&IopRootDeviceNode->InstancePath, REGSTR_VAL_ROOT_DEVNODE); /* Call the add device routine */ IopRootDriverObject->DriverExtension->AddDevice(IopRootDriverObject, IopRootDeviceNode->PhysicalDeviceObject); /* Initialize PnP-Event notification support */ Status = IopInitPlugPlayEvents(); if (!NT_SUCCESS(Status)) return Status; /* Report the device to the user-mode pnp manager */ IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL, &IopRootDeviceNode->InstancePath); /* Initialize the Bus Type GUID List */ PnpBusTypeGuidList = ExAllocatePool(PagedPool, sizeof(IO_BUS_TYPE_GUID_LIST)); RtlZeroMemory(PnpBusTypeGuidList, sizeof(IO_BUS_TYPE_GUID_LIST)); ExInitializeFastMutex(&PnpBusTypeGuidList->Lock); /* Launch the firmware mapper */ Status = IopUpdateRootKey(); if (!NT_SUCCESS(Status)) return Status; /* Close the handle to the control set */ NtClose(KeyHandle); /* We made it */ return STATUS_SUCCESS; }
INT_PTR CALLBACK PhpProcessStatisticsDlgProc( _In_ HWND hwndDlg, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam ) { LPPROPSHEETPAGE propSheetPage; PPH_PROCESS_PROPPAGECONTEXT propPageContext; PPH_PROCESS_ITEM processItem; PPH_STATISTICS_CONTEXT statisticsContext; if (PhpPropPageDlgProcHeader(hwndDlg, uMsg, lParam, &propSheetPage, &propPageContext, &processItem)) { statisticsContext = (PPH_STATISTICS_CONTEXT)propPageContext->Context; } else { return FALSE; } switch (uMsg) { case WM_INITDIALOG: { statisticsContext = propPageContext->Context = PhAllocate(sizeof(PH_STATISTICS_CONTEXT)); statisticsContext->WindowHandle = hwndDlg; statisticsContext->Enabled = TRUE; statisticsContext->ProcessHandle = NULL; // Try to open a process handle with PROCESS_QUERY_INFORMATION access for // WS information. PhOpenProcess( &statisticsContext->ProcessHandle, PROCESS_QUERY_INFORMATION, processItem->ProcessId ); PhRegisterCallback( &PhProcessesUpdatedEvent, StatisticsUpdateHandler, statisticsContext, &statisticsContext->ProcessesUpdatedRegistration ); PhpUpdateProcessStatistics(hwndDlg, processItem, statisticsContext); } break; case WM_DESTROY: { PhUnregisterCallback( &PhProcessesUpdatedEvent, &statisticsContext->ProcessesUpdatedRegistration ); if (statisticsContext->ProcessHandle) NtClose(statisticsContext->ProcessHandle); PhFree(statisticsContext); PhpPropPageDlgProcDestroy(hwndDlg); } break; case WM_SHOWWINDOW: { if (!propPageContext->LayoutInitialized) { PPH_LAYOUT_ITEM dialogItem; dialogItem = PhAddPropPageLayoutItem(hwndDlg, hwndDlg, PH_PROP_PAGE_TAB_CONTROL_PARENT, PH_ANCHOR_ALL); PhDoPropPageLayout(hwndDlg); propPageContext->LayoutInitialized = TRUE; } } break; case WM_COMMAND: { switch (LOWORD(wParam)) { case IDC_DETAILS: { PhShowHandleStatisticsDialog(hwndDlg, processItem->ProcessId); } break; } } break; case WM_NOTIFY: { LPNMHDR header = (LPNMHDR)lParam; switch (header->code) { case PSN_SETACTIVE: statisticsContext->Enabled = TRUE; break; case PSN_KILLACTIVE: statisticsContext->Enabled = FALSE; break; } } break; case WM_PH_STATISTICS_UPDATE: { PhpUpdateProcessStatistics(hwndDlg, processItem, statisticsContext); } break; } return FALSE; }
BOOLEAN SepAdtInitializePrivilegeAuditing( VOID ) /*++ Routine Description: Checks to see if there is an entry in the registry telling us to do full privilege auditing (which currently means audit everything we normall audit, plus backup and restore privileges). Arguments: None Return Value: BOOLEAN - TRUE if Auditing has been initialized correctly, else FALSE. --*/ { HANDLE KeyHandle; NTSTATUS Status; NTSTATUS TmpStatus; OBJECT_ATTRIBUTES Obja; ULONG ResultLength; UNICODE_STRING KeyName; UNICODE_STRING ValueName; CHAR KeyInfo[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(BOOLEAN)]; PKEY_VALUE_PARTIAL_INFORMATION pKeyInfo; BOOLEAN Verbose; PAGED_CODE(); // // Query the registry to set up the privilege auditing filter. // RtlInitUnicodeString( &KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Lsa"); InitializeObjectAttributes( &Obja, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL ); Status = NtOpenKey( &KeyHandle, KEY_QUERY_VALUE | KEY_SET_VALUE, &Obja ); if (!NT_SUCCESS( Status )) { if (Status == STATUS_OBJECT_NAME_NOT_FOUND) { return ( SepInitializePrivilegeFilter( FALSE )); } else { return( FALSE ); } } RtlInitUnicodeString( &ValueName, FULL_PRIVILEGE_AUDITING ); Status = NtQueryValueKey( KeyHandle, &ValueName, KeyValuePartialInformation, KeyInfo, sizeof(KeyInfo), &ResultLength ); TmpStatus = NtClose(KeyHandle); ASSERT(NT_SUCCESS(TmpStatus)); if (!NT_SUCCESS( Status )) { Verbose = FALSE; } else { pKeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyInfo; Verbose = (BOOLEAN) *(pKeyInfo->Data); } return ( SepInitializePrivilegeFilter( Verbose )); }