static void TestIoVolumeDeviceToDosName(void) { NTSTATUS Status; ULONG VolumeNumber; WCHAR VolumeDeviceNameBuffer[32]; UNICODE_STRING VolumeDeviceName; PFILE_OBJECT FileObject; PDEVICE_OBJECT DeviceObject; UNICODE_STRING DosName; UNICODE_STRING DosVolumePrefix = RTL_CONSTANT_STRING(L"\\\\?\\Volume"); RtlInitEmptyUnicodeString(&VolumeDeviceName, VolumeDeviceNameBuffer, sizeof(VolumeDeviceNameBuffer)); VolumeNumber = 0; Status = STATUS_SUCCESS; while (1) { Status = GetNextVolumeDevice(&VolumeDeviceName, &VolumeNumber, Status); if (!NT_SUCCESS(Status)) { trace("GetNextVolumeDevice(0x%lx) failed with %lx\n", VolumeNumber, Status); break; } RtlInitUnicodeString(&VolumeDeviceName, VolumeDeviceNameBuffer); Status = IoGetDeviceObjectPointer(&VolumeDeviceName, READ_CONTROL, &FileObject, &DeviceObject); if (!NT_SUCCESS(Status)) { trace("IoGetDeviceObjectPointer(%wZ) failed with %lx\n", &VolumeDeviceName, Status); continue; } Status = IoVolumeDeviceToDosName(DeviceObject, &DosName); ok_eq_hex(Status, STATUS_SUCCESS); if (!skip(NT_SUCCESS(Status), "No DOS name\n")) { trace("DOS name for %wZ is %wZ\n", &VolumeDeviceName, &DosName); if (DosName.Length == 2 * sizeof(WCHAR)) { ok(DosName.Buffer[0] >= L'A' && DosName.Buffer[0] <= L'Z' && DosName.Buffer[1] == L':', "Unexpected drive letter: %wZ\n", &DosName); } else { ok(RtlPrefixUnicodeString(&DosVolumePrefix, &DosName, FALSE), "Unexpected volume path: %wZ\n", &DosName); } RtlFreeUnicodeString(&DosName); } ObDereferenceObject(FileObject); Status = STATUS_SUCCESS; } ok(VolumeNumber > 1, "No volumes found\n"); }
VOID CsampUnload( __in PDRIVER_OBJECT DriverObject ) /*++ Routine Description: Free all the allocated resources, etc. Arguments: DriverObject - pointer to a driver object. Return Value: VOID --*/ { PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject; UNICODE_STRING uniWin32NameString; PDEVICE_EXTENSION devExtension = deviceObject->DeviceExtension; PAGED_CODE(); CSAMP_KDPRINT(("CsampUnload Enter\n")); // // Set the Stop flag // devExtension->ThreadShouldStop = TRUE; // // Make sure the thread wakes up // KeReleaseSemaphore(&devExtension->IrpQueueSemaphore, 0, // No priority boost 1, // Increment semaphore by 1 TRUE );// WaitForXxx after this call // // Wait for the thread to terminate // KeWaitForSingleObject(devExtension->ThreadObject, Executive, KernelMode, FALSE, NULL ); ObDereferenceObject(devExtension->ThreadObject); // // Create counted string version of our Win32 device name. // RtlInitUnicodeString( &uniWin32NameString, CSAMP_DOS_DEVICE_NAME_U ); IoDeleteSymbolicLink( &uniWin32NameString ); ASSERT(!deviceObject->AttachedDevice); IoDeleteDevice( deviceObject ); CSAMP_KDPRINT(("CsampUnload Exit\n")); return; }
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) /*++ Routine Description: This routine is called when the driver is loaded by NT. Arguments: DriverObject - Pointer to driver object created by system. RegistryPath - Pointer to the name of the services node for this driver. Return Value: The function value is the final status from the initialization operation. --*/ { NTSTATUS ntStatus; PVOID BufDriverString=NULL,BufProcessEventString=NULL,BufThreadEventString=NULL; UNICODE_STRING uszDriverString; UNICODE_STRING uszProcessEventString; UNICODE_STRING uszThreadEventString; PDEVICE_OBJECT pDeviceObject; HANDLE reg=0; OBJECT_ATTRIBUTES oa; UNICODE_STRING temp; char wbuf[100]; WORD this_cs, this_ss, this_ds, this_es, this_fs, this_gs; ULONG cr4reg; criticalSection csTest; DbgPrint("sizeof(DS_AREA_MANAGEMENT)=%d\n", sizeof(DS_AREA_MANAGEMENT)); DbgPrint("sizeof(BTS)=%d\n", sizeof(BTS)); //DbgPrint("%S",oa.ObjectName.Buffer); KernelCodeStepping=0; this_cs=getCS(); this_ss=getSS(); this_ds=getDS(); this_es=getES(); this_fs=getFS(); this_gs=getGS(); #ifdef AMD64 DbgPrint("cs=%x ss=%x ds=%x es=%x fs=%x gs=%x\n",getCS(), getSS(), getDS(), getES(), getFS(), getGS()); DbgPrint("fsbase=%llx gsbase=%llx gskernel=%llx\n", readMSR(0xc0000100), readMSR(0xc0000101), readMSR(0xc0000102)); DbgPrint("rbp=%llx\n", getRBP()); DbgPrint("gs:188=%llx\n", __readgsqword(0x188)); DbgPrint("current csr=%x\n", _mm_getcsr()); #endif DbgPrint("Test critical section routines\n"); RtlZeroMemory(&csTest,sizeof(criticalSection)); DbgPrint("csTest.locked=%d\n",csTest.locked); csEnter(&csTest); DbgPrint("After enter\n"); DbgPrint("csTest.locked=%d\n",csTest.locked); csLeave(&csTest); DbgPrint("After leave\n"); DbgPrint("csTest.locked=%d\n",csTest.locked); //lame antiviruses and more lamer users that keep crying rootkit virus.... temp.Buffer=(PWCH)wbuf; temp.Length=0; temp.MaximumLength=100; RtlAppendUnicodeToString(&temp, L"Ke"); //KeServiceDescriptorTable RtlAppendUnicodeToString(&temp, L"Service"); RtlAppendUnicodeToString(&temp, L"Descriptor"); RtlAppendUnicodeToString(&temp, L"Table"); KeServiceDescriptorTable=MmGetSystemRoutineAddress(&temp); DbgPrint("Loading driver\n"); if (RegistryPath) { DbgPrint("Registry path = %S\n", RegistryPath->Buffer); InitializeObjectAttributes(&oa,RegistryPath,OBJ_KERNEL_HANDLE ,NULL,NULL); ntStatus=ZwOpenKey(®,KEY_QUERY_VALUE,&oa); if (ntStatus == STATUS_SUCCESS) { UNICODE_STRING A,B,C,D; PKEY_VALUE_PARTIAL_INFORMATION bufA,bufB,bufC,bufD; ULONG ActualSize; DbgPrint("Opened the key\n"); BufDriverString=ExAllocatePool(PagedPool,sizeof(KEY_VALUE_PARTIAL_INFORMATION)+100); BufDeviceString=ExAllocatePool(PagedPool,sizeof(KEY_VALUE_PARTIAL_INFORMATION)+100); BufProcessEventString=ExAllocatePool(PagedPool,sizeof(KEY_VALUE_PARTIAL_INFORMATION)+100); BufThreadEventString=ExAllocatePool(PagedPool,sizeof(KEY_VALUE_PARTIAL_INFORMATION)+100); bufA=BufDriverString; bufB=BufDeviceString; bufC=BufProcessEventString; bufD=BufThreadEventString; RtlInitUnicodeString(&A, L"A"); RtlInitUnicodeString(&B, L"B"); RtlInitUnicodeString(&C, L"C"); RtlInitUnicodeString(&D, L"D"); if (ntStatus == STATUS_SUCCESS) ntStatus=ZwQueryValueKey(reg,&A,KeyValuePartialInformation ,bufA,sizeof(KEY_VALUE_PARTIAL_INFORMATION)+100,&ActualSize); if (ntStatus == STATUS_SUCCESS) ntStatus=ZwQueryValueKey(reg,&B,KeyValuePartialInformation ,bufB,sizeof(KEY_VALUE_PARTIAL_INFORMATION)+100,&ActualSize); if (ntStatus == STATUS_SUCCESS) ntStatus=ZwQueryValueKey(reg,&C,KeyValuePartialInformation ,bufC,sizeof(KEY_VALUE_PARTIAL_INFORMATION)+100,&ActualSize); if (ntStatus == STATUS_SUCCESS) ntStatus=ZwQueryValueKey(reg,&D,KeyValuePartialInformation ,bufD,sizeof(KEY_VALUE_PARTIAL_INFORMATION)+100,&ActualSize); if (ntStatus == STATUS_SUCCESS) { DbgPrint("Read ok\n"); RtlInitUnicodeString(&uszDriverString,(PCWSTR) bufA->Data); RtlInitUnicodeString(&uszDeviceString,(PCWSTR) bufB->Data); RtlInitUnicodeString(&uszProcessEventString,(PCWSTR) bufC->Data); RtlInitUnicodeString(&uszThreadEventString,(PCWSTR) bufD->Data); DbgPrint("DriverString=%S\n",uszDriverString.Buffer); DbgPrint("DeviceString=%S\n",uszDeviceString.Buffer); DbgPrint("ProcessEventString=%S\n",uszProcessEventString.Buffer); DbgPrint("ThreadEventString=%S\n",uszThreadEventString.Buffer); } else { ExFreePool(bufA); ExFreePool(bufB); ExFreePool(bufC); ExFreePool(bufD); DbgPrint("Failed reading the value\n"); ZwClose(reg); return STATUS_UNSUCCESSFUL;; } } else { DbgPrint("Failed opening the key\n"); return STATUS_UNSUCCESSFUL;; } } else loadedbydbvm=TRUE; ntStatus = STATUS_SUCCESS; if (!loadedbydbvm) { // Point uszDriverString at the driver name #ifndef CETC // Create and initialize device object ntStatus = IoCreateDevice(DriverObject, 0, &uszDriverString, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject); if(ntStatus != STATUS_SUCCESS) { DbgPrint("IoCreateDevice failed\n"); ExFreePool(BufDriverString); ExFreePool(BufDeviceString); ExFreePool(BufProcessEventString); ExFreePool(BufThreadEventString); if (reg) ZwClose(reg); return ntStatus; } // Point uszDeviceString at the device name // Create symbolic link to the user-visible name ntStatus = IoCreateSymbolicLink(&uszDeviceString, &uszDriverString); if(ntStatus != STATUS_SUCCESS) { DbgPrint("IoCreateSymbolicLink failed: %x\n",ntStatus); // Delete device object if not successful IoDeleteDevice(pDeviceObject); ExFreePool(BufDriverString); ExFreePool(BufDeviceString); ExFreePool(BufProcessEventString); ExFreePool(BufThreadEventString); if (reg) ZwClose(reg); return ntStatus; } #endif } //when loaded by dbvm driver object is 'valid' so store the function addresses DbgPrint("DriverObject=%p\n", DriverObject); // Load structure to point to IRP handlers... DriverObject->DriverUnload = UnloadDriver; DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose; if (loadedbydbvm) DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = (PDRIVER_DISPATCH)DispatchIoctlDBVM; else DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl; //Processlist init #ifndef CETC ProcessEventCount=0; KeInitializeSpinLock(&ProcesslistSL); #endif CreateProcessNotifyRoutineEnabled=FALSE; //threadlist init ThreadEventCount=0; BufferSize=0; processlist=NULL; #ifndef AMD64 //determine if PAE is used cr4reg=(ULONG)getCR4(); if ((cr4reg & 0x20)==0x20) { PTESize=8; //pae PAGE_SIZE_LARGE=0x200000; MAX_PDE_POS=0xC0604000; MAX_PTE_POS=0xC07FFFF8; } else { PTESize=4; PAGE_SIZE_LARGE=0x400000; MAX_PDE_POS=0xC0301000; MAX_PTE_POS=0xC03FFFFC; } #else PTESize=8; //pae PAGE_SIZE_LARGE=0x200000; MAX_PTE_POS=0xFFFFF6FFFFFFFFF8ULL; MAX_PDE_POS=0xFFFFF6FB7FFFFFF8ULL; #endif #ifdef CETC DbgPrint("Going to initialice CETC\n"); InitializeCETC(); #endif //hideme(DriverObject); //ok, for those that see this, enabling this WILL f**k up try except routines, even in usermode you'll get a blue sreen DbgPrint("Initializing debugger\n"); debugger_initialize(); // Return success (don't do the devicestring, I need it for unload) DbgPrint("Cleaning up initialization buffers\n"); if (BufDriverString) { ExFreePool(BufDriverString); BufDriverString=NULL; } if (BufProcessEventString) { ExFreePool(BufProcessEventString); BufProcessEventString=NULL; } if (BufThreadEventString) { ExFreePool(BufThreadEventString); BufThreadEventString=NULL; } if (reg) { ZwClose(reg); reg=0; } //fetch cpu info { DWORD r[4]; DWORD a; __cpuid(r,0); if (r[0]==0x756e6547) //Genu { __cpuid(r,1); a=r[0]; cpu_stepping=a & 0xf; cpu_model=(a >> 4) & 0xf; cpu_familyID=(a >> 8) & 0xf; cpu_type=(a >> 12) & 0x3; cpu_ext_modelID=(a >> 16) & 0xf; cpu_ext_familyID=(a >> 20) & 0xff; cpu_model=cpu_model + (cpu_ext_modelID << 4); cpu_familyID=cpu_familyID + (cpu_ext_familyID << 4); } }
static NTSTATUS IopGetRelatedDevice(PPLUGPLAY_CONTROL_RELATED_DEVICE_DATA RelatedDeviceData) { UNICODE_STRING RootDeviceName; PDEVICE_OBJECT DeviceObject = NULL; PDEVICE_NODE DeviceNode = NULL; PDEVICE_NODE RelatedDeviceNode; UNICODE_STRING TargetDeviceInstance; NTSTATUS Status = STATUS_SUCCESS; ULONG Relation = 0; ULONG MaximumLength = 0; DPRINT("IopGetRelatedDevice() called\n"); DPRINT("Device name: %wZ\n", &RelatedDeviceData->TargetDeviceInstance); Status = IopCaptureUnicodeString(&TargetDeviceInstance, &RelatedDeviceData->TargetDeviceInstance); if (!NT_SUCCESS(Status)) { return Status; } _SEH2_TRY { Relation = RelatedDeviceData->Relation; MaximumLength = RelatedDeviceData->RelatedDeviceInstanceLength; ProbeForWrite(RelatedDeviceData->RelatedDeviceInstance, MaximumLength, sizeof(WCHAR)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { if (TargetDeviceInstance.Buffer != NULL) { ExFreePool(TargetDeviceInstance.Buffer); } _SEH2_YIELD(return _SEH2_GetExceptionCode()); } _SEH2_END; RtlInitUnicodeString(&RootDeviceName, L"HTREE\\ROOT\\0"); if (RtlEqualUnicodeString(&TargetDeviceInstance, &RootDeviceName, TRUE)) { DeviceNode = IopRootDeviceNode; if (TargetDeviceInstance.Buffer != NULL) { ExFreePool(TargetDeviceInstance.Buffer); } } else { /* Get the device object */ DeviceObject = IopGetDeviceObjectFromDeviceInstance(&TargetDeviceInstance); if (TargetDeviceInstance.Buffer != NULL) { ExFreePool(TargetDeviceInstance.Buffer); } if (DeviceObject == NULL) return STATUS_NO_SUCH_DEVICE; DeviceNode = ((PEXTENDED_DEVOBJ_EXTENSION)DeviceObject->DeviceObjectExtension)->DeviceNode; } switch (Relation) { case PNP_GET_PARENT_DEVICE: RelatedDeviceNode = DeviceNode->Parent; break; case PNP_GET_CHILD_DEVICE: RelatedDeviceNode = DeviceNode->Child; break; case PNP_GET_SIBLING_DEVICE: RelatedDeviceNode = DeviceNode->Sibling; break; default: if (DeviceObject != NULL) { ObDereferenceObject(DeviceObject); } return STATUS_INVALID_PARAMETER; } if (RelatedDeviceNode == NULL) { if (DeviceObject) { ObDereferenceObject(DeviceObject); } return STATUS_NO_SUCH_DEVICE; } if (RelatedDeviceNode->InstancePath.Length > MaximumLength) { if (DeviceObject) { ObDereferenceObject(DeviceObject); } return STATUS_BUFFER_TOO_SMALL; } /* Copy related device instance name */ _SEH2_TRY { RtlCopyMemory(RelatedDeviceData->RelatedDeviceInstance, RelatedDeviceNode->InstancePath.Buffer, RelatedDeviceNode->InstancePath.Length); RelatedDeviceData->RelatedDeviceInstanceLength = RelatedDeviceNode->InstancePath.Length; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END; if (DeviceObject != NULL) { ObDereferenceObject(DeviceObject); } DPRINT("IopGetRelatedDevice() done\n"); return Status; }
NTSTATUS SetupCopyFile( PWCHAR SourceFileName, PWCHAR DestinationFileName) { OBJECT_ATTRIBUTES ObjectAttributes; HANDLE FileHandleSource; HANDLE FileHandleDest; static IO_STATUS_BLOCK IoStatusBlock; FILE_STANDARD_INFORMATION FileStandard; FILE_BASIC_INFORMATION FileBasic; ULONG RegionSize; UNICODE_STRING FileName; NTSTATUS Status; PVOID SourceFileMap = 0; HANDLE SourceFileSection; SIZE_T SourceSectionSize = 0; LARGE_INTEGER ByteOffset; #ifdef __REACTOS__ RtlInitUnicodeString(&FileName, SourceFileName); InitializeObjectAttributes(&ObjectAttributes, &FileName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenFile(&FileHandleSource, GENERIC_READ, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ, FILE_SEQUENTIAL_ONLY); if (!NT_SUCCESS(Status)) { DPRINT1("NtOpenFile failed: %x, %wZ\n", Status, &FileName); goto done; } #else FileHandleSource = CreateFileW(SourceFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (FileHandleSource == INVALID_HANDLE_VALUE) { Status = STATUS_UNSUCCESSFUL; goto done; } #endif Status = NtQueryInformationFile(FileHandleSource, &IoStatusBlock, &FileStandard, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation); if (!NT_SUCCESS(Status)) { DPRINT1("NtQueryInformationFile failed: %x\n", Status); goto closesrc; } Status = NtQueryInformationFile(FileHandleSource, &IoStatusBlock,&FileBasic, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation); if (!NT_SUCCESS(Status)) { DPRINT1("NtQueryInformationFile failed: %x\n", Status); goto closesrc; } Status = NtCreateSection(&SourceFileSection, SECTION_MAP_READ, NULL, NULL, PAGE_READONLY, SEC_COMMIT, FileHandleSource); if (!NT_SUCCESS(Status)) { DPRINT1("NtCreateSection failed: %x, %S\n", Status, SourceFileName); goto closesrc; } Status = NtMapViewOfSection(SourceFileSection, NtCurrentProcess(), &SourceFileMap, 0, 0, NULL, &SourceSectionSize, ViewUnmap, 0, PAGE_READONLY ); if (!NT_SUCCESS(Status)) { DPRINT1("NtMapViewOfSection failed: %x, %S\n", Status, SourceFileName); goto closesrcsec; } RtlInitUnicodeString(&FileName, DestinationFileName); InitializeObjectAttributes(&ObjectAttributes, &FileName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtCreateFile(&FileHandleDest, GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, FILE_NO_INTERMEDIATE_BUFFERING | FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (!NT_SUCCESS(Status)) { /* Open may have failed because the file to overwrite * is in readonly mode */ if (Status == STATUS_ACCESS_DENIED) { FILE_BASIC_INFORMATION FileBasicInfo; /* Reattempt to open it with limited access */ Status = NtCreateFile(&FileHandleDest, FILE_WRITE_ATTRIBUTES | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, FILE_NO_INTERMEDIATE_BUFFERING | FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); /* Fail for real if we cannot open it that way */ if (!NT_SUCCESS(Status)) { DPRINT1("NtCreateFile failed: %x, %wZ\n", Status, &FileName); goto unmapsrcsec; } /* Zero our basic info, just to set attributes */ RtlZeroMemory(&FileBasicInfo, sizeof(FileBasicInfo)); /* Reset attributes to normal, no read-only */ FileBasicInfo.FileAttributes = FILE_ATTRIBUTE_NORMAL; /* We basically don't care about whether it succeed: * if it didn't, later open will fail */ NtSetInformationFile(FileHandleDest, &IoStatusBlock, &FileBasicInfo, sizeof(FileBasicInfo), FileBasicInformation); /* Close file */ NtClose(FileHandleDest); /* And re-attempt overwrite */ Status = NtCreateFile(&FileHandleDest, GENERIC_WRITE | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, FILE_NO_INTERMEDIATE_BUFFERING | FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); } /* We failed */ if (!NT_SUCCESS(Status)) { DPRINT1("NtCreateFile failed: %x, %wZ\n", Status, &FileName); goto unmapsrcsec; } } RegionSize = (ULONG)PAGE_ROUND_UP(FileStandard.EndOfFile.u.LowPart); IoStatusBlock.Status = 0; ByteOffset.QuadPart = 0ULL; Status = NtWriteFile(FileHandleDest, NULL, NULL, NULL, &IoStatusBlock, SourceFileMap, RegionSize, &ByteOffset, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("NtWriteFile failed: %x:%x, iosb: %p src: %p, size: %x\n", Status, IoStatusBlock.Status, &IoStatusBlock, SourceFileMap, RegionSize); goto closedest; } /* Copy file date/time from source file */ Status = NtSetInformationFile(FileHandleDest, &IoStatusBlock, &FileBasic, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation); if (!NT_SUCCESS(Status)) { DPRINT1("NtSetInformationFile failed: %x\n", Status); goto closedest; } /* shorten the file back to it's real size after completing the write */ Status = NtSetInformationFile(FileHandleDest, &IoStatusBlock, &FileStandard.EndOfFile, sizeof(FILE_END_OF_FILE_INFORMATION), FileEndOfFileInformation); if (!NT_SUCCESS(Status)) { DPRINT1("NtSetInformationFile failed: %x\n", Status); } closedest: NtClose(FileHandleDest); unmapsrcsec: NtUnmapViewOfSection(NtCurrentProcess(), SourceFileMap); closesrcsec: NtClose(SourceFileSection); closesrc: NtClose(FileHandleSource); done: return Status; }
NTSTATUS NTAPI CmpInitializeMachineDependentConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { UNICODE_STRING KeyName, ValueName, Data, SectionName; OBJECT_ATTRIBUTES ObjectAttributes; ULONG HavePae, Length, TotalLength = 0, i, Disposition; SIZE_T ViewSize; NTSTATUS Status; HANDLE KeyHandle, BiosHandle, SystemHandle, FpuHandle, SectionHandle; CONFIGURATION_COMPONENT_DATA ConfigData; CHAR Buffer[128]; CPU_INFO CpuInfo; ULONG VendorId, ExtendedId; PKPRCB Prcb; USHORT IndexTable[MaximumType + 1] = {0}; ANSI_STRING TempString; PCHAR PartialString = NULL, BiosVersion; CHAR CpuString[48]; PVOID BaseAddress = NULL; LARGE_INTEGER ViewBase = {{0, 0}}; ULONG_PTR VideoRomBase; PCHAR CurrentVersion; extern UNICODE_STRING KeRosProcessorName, KeRosBiosDate, KeRosBiosVersion; extern UNICODE_STRING KeRosVideoBiosDate, KeRosVideoBiosVersion; /* Open the SMSS Memory Management key */ RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\" L"Control\\Session Manager\\Memory Management"); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenKey(&KeyHandle, KEY_READ | KEY_WRITE, &ObjectAttributes); if (NT_SUCCESS(Status)) { /* Detect if PAE is enabled */ HavePae = SharedUserData->ProcessorFeatures[PF_PAE_ENABLED]; /* Set the value */ RtlInitUnicodeString(&ValueName, L"PhysicalAddressExtension"); NtSetValueKey(KeyHandle, &ValueName, 0, REG_DWORD, &HavePae, sizeof(HavePae)); /* Close the key */ NtClose(KeyHandle); } /* Open the hardware description key */ RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\Hardware\\Description\\System"); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenKey(&SystemHandle, KEY_READ | KEY_WRITE, &ObjectAttributes); if (!NT_SUCCESS(Status)) return Status; /* Create the BIOS Information key */ RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\" L"Control\\BIOSINFO"); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtCreateKey(&BiosHandle, KEY_ALL_ACCESS, &ObjectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, &Disposition); if (ExpInTextModeSetup) { if (!NT_SUCCESS(Status)) BiosHandle = NULL; } else if (!NT_SUCCESS(Status)) return Status; /* Create the CPU Key, and check if it already existed */ RtlInitUnicodeString(&KeyName, L"CentralProcessor"); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, SystemHandle, NULL); Status = NtCreateKey(&KeyHandle, KEY_READ | KEY_WRITE, &ObjectAttributes, 0, NULL, 0, &Disposition); NtClose(KeyHandle); /* The key shouldn't already exist */ if (Disposition == REG_CREATED_NEW_KEY) { /* Allocate the configuration data for cmconfig.c */ CmpConfigurationData = ExAllocatePoolWithTag(PagedPool, CmpConfigurationAreaSize, TAG_CM); if (!CmpConfigurationData) return STATUS_INSUFFICIENT_RESOURCES; /* Loop all CPUs */ for (i = 0; i < KeNumberProcessors; i++) { /* Get the PRCB */ Prcb = KiProcessorBlock[i]; /* Setup the Configuration Entry for the Processor */ RtlZeroMemory(&ConfigData, sizeof (ConfigData)); ConfigData.ComponentEntry.Class = ProcessorClass; ConfigData.ComponentEntry.Type = CentralProcessor; ConfigData.ComponentEntry.Key = i; ConfigData.ComponentEntry.AffinityMask = AFFINITY_MASK(i); ConfigData.ComponentEntry.Identifier = Buffer; /* Check if the CPU doesn't support CPUID */ if (!Prcb->CpuID) { /* Build ID1-style string for older CPUs */ sprintf(Buffer, CmpID1, Prcb->CpuType, (Prcb->CpuStep >> 8) + 'A', Prcb->CpuStep & 0xff); } else {
int WINAPI WinMain( IN HINSTANCE hInstance, IN HINSTANCE hPrevInstance, IN LPSTR lpCmdLine, IN int nShowCmd) { #if 0 LSA_STRING ProcessName, PackageName; HANDLE LsaHandle; LSA_OPERATIONAL_MODE Mode; BOOLEAN Old; ULONG AuthenticationPackage; NTSTATUS Status; #endif ULONG HardErrorResponse; MSG Msg; UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); UNREFERENCED_PARAMETER(nShowCmd); hAppInstance = hInstance; /* Make us critical */ RtlSetProcessIsCritical(TRUE, NULL, FALSE); RtlSetThreadIsCritical(TRUE, NULL, FALSE); if (!RegisterLogonProcess(GetCurrentProcessId(), TRUE)) { ERR("WL: Could not register logon process\n"); NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); ExitProcess(1); } WLSession = (PWLSESSION)HeapAlloc(GetProcessHeap(), 0, sizeof(WLSESSION)); if (!WLSession) { ERR("WL: Could not allocate memory for winlogon instance\n"); NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); ExitProcess(1); } ZeroMemory(WLSession, sizeof(WLSESSION)); WLSession->DialogTimeout = 120; /* 2 minutes */ /* Initialize the dialog tracking list */ InitDialogListHead(); if (!CreateWindowStationAndDesktops(WLSession)) { ERR("WL: Could not create window station and desktops\n"); NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); ExitProcess(1); } LockWorkstation(WLSession); /* Load default keyboard layouts */ if (!InitKeyboardLayouts()) { ERR("WL: Could not preload keyboard layouts\n"); NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); ExitProcess(1); } if (!StartRpcServer()) { ERR("WL: Could not start the RPC server\n"); NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); ExitProcess(1); } if (!StartServicesManager()) { ERR("WL: Could not start services.exe\n"); NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); ExitProcess(1); } if (!StartLsass()) { ERR("WL: Failed to start lsass.exe service (error %lu)\n", GetLastError()); NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED, 0, 0, NULL, OptionOk, &HardErrorResponse); ExitProcess(1); } /* Wait for the LSA server */ WaitForLsass(); /* Init Notifications */ InitNotifications(); /* Load and initialize gina */ if (!GinaInit(WLSession)) { ERR("WL: Failed to initialize Gina\n"); // FIXME: Retrieve the real name of the GINA DLL we were trying to load. // It is known only inside the GinaInit function... DialogBoxParam(hAppInstance, MAKEINTRESOURCE(IDD_GINALOADFAILED), GetDesktopWindow(), GinaLoadFailedWindowProc, (LPARAM)L"msgina.dll"); HandleShutdown(WLSession, WLX_SAS_ACTION_SHUTDOWN_REBOOT); ExitProcess(1); } DisplayStatusMessage(WLSession, WLSession->WinlogonDesktop, IDS_REACTOSISSTARTINGUP); #if 0 /* Connect to NetLogon service (lsass.exe) */ /* Real winlogon uses "Winlogon" */ RtlInitUnicodeString((PUNICODE_STRING)&ProcessName, L"Winlogon"); Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode); if (Status == STATUS_PORT_CONNECTION_REFUSED) { /* Add the 'SeTcbPrivilege' privilege and try again */ Status = RtlAdjustPrivilege(SE_TCB_PRIVILEGE, TRUE, TRUE, &Old); if (!NT_SUCCESS(Status)) { ERR("RtlAdjustPrivilege() failed with error %lu\n", LsaNtStatusToWinError(Status)); return 1; } Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode); } if (!NT_SUCCESS(Status)) { ERR("LsaRegisterLogonProcess() failed with error %lu\n", LsaNtStatusToWinError(Status)); return 1; } RtlInitUnicodeString((PUNICODE_STRING)&PackageName, MICROSOFT_KERBEROS_NAME_W); Status = LsaLookupAuthenticationPackage(LsaHandle, &PackageName, &AuthenticationPackage); if (!NT_SUCCESS(Status)) { ERR("LsaLookupAuthenticationPackage() failed with error %lu\n", LsaNtStatusToWinError(Status)); LsaDeregisterLogonProcess(LsaHandle); return 1; } #endif CallNotificationDlls(WLSession, StartupHandler); /* Create a hidden window to get SAS notifications */ if (!InitializeSAS(WLSession)) { ERR("WL: Failed to initialize SAS\n"); ExitProcess(2); } // DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_PREPARENETWORKCONNECTIONS); // DisplayStatusMessage(Session, Session->WinlogonDesktop, IDS_APPLYINGCOMPUTERSETTINGS); /* Display logged out screen */ WLSession->LogonState = STATE_INIT; RemoveStatusMessage(WLSession); /* Check for pending setup */ if (GetSetupType() != 0) { TRACE("WL: Setup mode detected\n"); /* Run setup and reboot when done */ SwitchDesktop(WLSession->ApplicationDesktop); RunSetup(); } else PostMessageW(WLSession->SASWindow, WLX_WM_SAS, WLX_SAS_TYPE_CTRL_ALT_DEL, 0); (void)LoadLibraryW(L"sfc_os.dll"); /* Tell kernel that CurrentControlSet is good (needed * to support Last good known configuration boot) */ NtInitializeRegistry(CM_BOOT_FLAG_ACCEPTED | 1); /* Message loop for the SAS window */ while (GetMessageW(&Msg, WLSession->SASWindow, 0, 0)) { TranslateMessage(&Msg); DispatchMessageW(&Msg); } CleanupNotifications(); /* We never go there */ return 0; }
NTSTATUS DriverEntry( IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath ) /*++ Routine Description: Called on loading. We create a device object to handle user-mode requests on, and register ourselves as a protocol with NDIS. Arguments: pDriverObject - Pointer to driver object created by system. pRegistryPath - Pointer to the Unicode name of the registry path for this driver. Return Value: NT Status code --*/ { NDIS_PROTOCOL_CHARACTERISTICS protocolChar; NTSTATUS status = STATUS_SUCCESS; NDIS_STRING protoName = NDIS_STRING_CONST("NdisProt"); UNICODE_STRING ntDeviceName; UNICODE_STRING win32DeviceName; BOOLEAN fSymbolicLink = FALSE; PDEVICE_OBJECT deviceObject = NULL; UNREFERENCED_PARAMETER(pRegistryPath); DEBUGP(DL_LOUD, ("DriverEntry\n")); Globals.pDriverObject = pDriverObject; NPROT_INIT_EVENT(&Globals.BindsComplete); do { // // Create our device object using which an application can // access NDIS devices. // RtlInitUnicodeString(&ntDeviceName, NT_DEVICE_NAME); #ifndef WIN9X status = IoCreateDeviceSecure(pDriverObject, 0, &ntDeviceName, FILE_DEVICE_NETWORK, FILE_DEVICE_SECURE_OPEN, FALSE, &SDDL_DEVOBJ_SYS_ALL_ADM_ALL, NULL, &deviceObject); #else status = IoCreateDevice(pDriverObject, 0, &ntDeviceName, FILE_DEVICE_NETWORK, FILE_DEVICE_SECURE_OPEN, FALSE, &deviceObject); #endif if (!NT_SUCCESS (status)) { // // Either not enough memory to create a deviceobject or another // deviceobject with the same name exits. This could happen // if you install another instance of this device. // break; } RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME); status = IoCreateSymbolicLink(&win32DeviceName, &ntDeviceName); if (!NT_SUCCESS(status)) { break; } fSymbolicLink = TRUE; deviceObject->Flags |= DO_DIRECT_IO; Globals.ControlDeviceObject = deviceObject; NPROT_INIT_LIST_HEAD(&Globals.OpenList); NPROT_INIT_LOCK(&Globals.GlobalLock); // // Initialize the protocol characterstic structure // NdisZeroMemory(&protocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS)); protocolChar.MajorNdisVersion = 5; protocolChar.MinorNdisVersion = 0; protocolChar.Name = protoName; protocolChar.OpenAdapterCompleteHandler = NdisProtOpenAdapterComplete; protocolChar.CloseAdapterCompleteHandler = NdisProtCloseAdapterComplete; protocolChar.SendCompleteHandler = NdisProtSendComplete; protocolChar.TransferDataCompleteHandler = NdisProtTransferDataComplete; protocolChar.ResetCompleteHandler = NdisProtResetComplete; protocolChar.RequestCompleteHandler = NdisProtRequestComplete; protocolChar.ReceiveHandler = NdisProtReceive; protocolChar.ReceiveCompleteHandler = NdisProtReceiveComplete; protocolChar.StatusHandler = NdisProtStatus; protocolChar.StatusCompleteHandler = NdisProtStatusComplete; protocolChar.BindAdapterHandler = NdisProtBindAdapter; protocolChar.UnbindAdapterHandler = NdisProtUnbindAdapter; protocolChar.UnloadHandler = NULL; protocolChar.ReceivePacketHandler = NdisProtReceivePacket; protocolChar.PnPEventHandler = NdisProtPnPEventHandler; // // Register as a protocol driver // NdisRegisterProtocol( (PNDIS_STATUS)&status, &Globals.NdisProtocolHandle, &protocolChar, sizeof(NDIS_PROTOCOL_CHARACTERISTICS)); if (status != NDIS_STATUS_SUCCESS) { DEBUGP(DL_WARN, ("Failed to register protocol with NDIS\n")); status = STATUS_UNSUCCESSFUL; break; } #ifdef NDIS51 Globals.PartialCancelId = NdisGeneratePartialCancelId(); Globals.PartialCancelId <<= ((sizeof(PVOID) - 1) * 8); DEBUGP(DL_LOUD, ("DriverEntry: CancelId %lx\n", Globals.PartialCancelId)); #endif // // Now set only the dispatch points we would like to handle. // pDriverObject->MajorFunction[IRP_MJ_CREATE] = NdisProtOpen; pDriverObject->MajorFunction[IRP_MJ_CLOSE] = NdisProtClose; pDriverObject->MajorFunction[IRP_MJ_READ] = NdisProtRead; pDriverObject->MajorFunction[IRP_MJ_WRITE] = NdisProtWrite; pDriverObject->MajorFunction[IRP_MJ_CLEANUP] = NdisProtCleanup; pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NdisProtIoControl; pDriverObject->DriverUnload = NdisProtUnload; status = STATUS_SUCCESS; } while (FALSE); if (!NT_SUCCESS(status)) { if (deviceObject) { #pragma prefast(disable:28107, "within critical section, device object is held") KeEnterCriticalRegion(); IoDeleteDevice(deviceObject); Globals.ControlDeviceObject = NULL; KeLeaveCriticalRegion(); } if (fSymbolicLink) { IoDeleteSymbolicLink(&win32DeviceName); } } return status; }
NTSTATUS RtlCreateUserProcess( IN PUNICODE_STRING NtImagePathName, IN ULONG Attributes, IN PRTL_USER_PROCESS_PARAMETERS ProcessParameters, IN PSECURITY_DESCRIPTOR ProcessSecurityDescriptor OPTIONAL, IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL, IN HANDLE ParentProcess OPTIONAL, IN BOOLEAN InheritHandles, IN HANDLE DebugPort OPTIONAL, IN HANDLE ExceptionPort OPTIONAL, OUT PRTL_USER_PROCESS_INFORMATION ProcessInformation ) /*++ Routine Description: This function creates a user mode process with a single thread with a suspend count of one. The address space of the new process is initialized with the contents of specified image file. The caller can specify the Access Control List for the new process and thread. The caller can also specify the parent process to inherit process priority and processor affinity from. The default is to inherit these from the current process. Finally the caller can specify whether the new process is to inherit any of the object handles from the specified parent process or not. Information about the new process and thread is returned via the ProcessInformation parameter. Arguments: NtImagePathName - A required pointer that points to the NT Path string that identifies the image file that is to be loaded into the child process. ProcessParameters - A required pointer that points to parameters that are to passed to the child process. ProcessSecurityDescriptor - An optional pointer to the Security Descriptor give to the new process. ThreadSecurityDescriptor - An optional pointer to the Security Descriptor give to the new thread. ParentProcess - An optional process handle that will used to inherit certain properties from. InheritHandles - A boolean value. TRUE specifies that object handles associated with the specified parent process are to be inherited by the new process, provided they have the OBJ_INHERIT attribute. FALSE specifies that the new process is to inherit no handles. DebugPort - An optional handle to the debug port associated with this process. ExceptionPort - An optional handle to the exception port associated with this process. ProcessInformation - A pointer to a variable that receives information about the new process and thread. --*/ { NTSTATUS Status; HANDLE Section, File; OBJECT_ATTRIBUTES ObjectAttributes; PRTL_USER_PROCESS_PARAMETERS Parameters; SIZE_T ParameterLength; PVOID Environment; PWCHAR s; SIZE_T EnvironmentLength; SIZE_T RegionSize; PROCESS_BASIC_INFORMATION ProcessInfo; PPEB Peb; UNICODE_STRING Unicode; // // Zero output parameter and probe the addresses at the same time // RtlZeroMemory( ProcessInformation, sizeof( *ProcessInformation ) ); ProcessInformation->Length = sizeof( *ProcessInformation ); // // Open the specified image file. // Status = RtlpOpenImageFile( NtImagePathName, Attributes & (OBJ_INHERIT | OBJ_CASE_INSENSITIVE), &File, TRUE ); if (!NT_SUCCESS( Status )) { return( Status ); } // // Create a memory section backed by the opened image file // Status = ZwCreateSection( &Section, SECTION_ALL_ACCESS, NULL, NULL, PAGE_EXECUTE, SEC_IMAGE, File ); ZwClose( File ); if ( !NT_SUCCESS( Status ) ) { return( Status ); } // // Create the user mode process, defaulting the parent process to the // current process if one is not specified. The new process will not // have a name nor will the handle be inherited by other processes. // if (!ARGUMENT_PRESENT( ParentProcess )) { ParentProcess = NtCurrentProcess(); } InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, ProcessSecurityDescriptor ); if ( RtlGetNtGlobalFlags() & FLG_ENABLE_CSRDEBUG ) { if ( wcsstr(NtImagePathName->Buffer,L"csrss") || wcsstr(NtImagePathName->Buffer,L"CSRSS") ) { // // For Hydra we don't name the CSRSS process to avoid name // collissions when multiple CSRSS's are started // if (ISTERMINALSERVER()) { InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, ProcessSecurityDescriptor ); } else { RtlInitUnicodeString(&Unicode,L"\\WindowsSS"); InitializeObjectAttributes( &ObjectAttributes, &Unicode, 0, NULL, ProcessSecurityDescriptor ); } } } if ( !InheritHandles ) { ProcessParameters->CurrentDirectory.Handle = NULL; } Status = ZwCreateProcess( &ProcessInformation->Process, PROCESS_ALL_ACCESS, &ObjectAttributes, ParentProcess, InheritHandles, Section, DebugPort, ExceptionPort ); if ( !NT_SUCCESS( Status ) ) { ZwClose( Section ); return( Status ); } // // Retrieve the interesting information from the image header // Status = ZwQuerySection( Section, SectionImageInformation, &ProcessInformation->ImageInformation, sizeof( ProcessInformation->ImageInformation ), NULL ); if ( !NT_SUCCESS( Status ) ) { ZwClose( ProcessInformation->Process ); ZwClose( Section ); return( Status ); } Status = ZwQueryInformationProcess( ProcessInformation->Process, ProcessBasicInformation, &ProcessInfo, sizeof( ProcessInfo ), NULL ); if ( !NT_SUCCESS( Status ) ) { ZwClose( ProcessInformation->Process ); ZwClose( Section ); return( Status ); } Peb = ProcessInfo.PebBaseAddress; // // Duplicate Native handles into new process if any specified. // Note that the duplicated handles will overlay the input values. // try { Status = STATUS_SUCCESS; if ( ProcessParameters->StandardInput ) { Status = ZwDuplicateObject( ParentProcess, ProcessParameters->StandardInput, ProcessInformation->Process, &ProcessParameters->StandardInput, 0L, 0L, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES ); if ( !NT_SUCCESS(Status) ) { __leave; } } if ( ProcessParameters->StandardOutput ) { Status = ZwDuplicateObject( ParentProcess, ProcessParameters->StandardOutput, ProcessInformation->Process, &ProcessParameters->StandardOutput, 0L, 0L, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES ); if ( !NT_SUCCESS(Status) ) { __leave; } } if ( ProcessParameters->StandardError ) { Status = ZwDuplicateObject( ParentProcess, ProcessParameters->StandardError, ProcessInformation->Process, &ProcessParameters->StandardError, 0L, 0L, DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES ); if ( !NT_SUCCESS(Status) ) { __leave; } } } finally { if ( !NT_SUCCESS(Status) ) { ZwClose( ProcessInformation->Process ); ZwClose( Section ); } } if ( !NT_SUCCESS(Status) ) { return Status; } // // Possibly reserve some address space in the new process // if (ProcessInformation->ImageInformation.SubSystemType == IMAGE_SUBSYSTEM_NATIVE ) { if ( ProcessParameters->Flags & RTL_USER_PROC_RESERVE_1MB ) { Environment = (PVOID)(4); RegionSize = (1024*1024)-(256); Status = ZwAllocateVirtualMemory( ProcessInformation->Process, (PVOID *)&Environment, 0, &RegionSize, MEM_RESERVE, PAGE_READWRITE ); if ( !NT_SUCCESS( Status ) ) { ZwClose( ProcessInformation->Process ); ZwClose( Section ); return( Status ); } } } // // Allocate virtual memory in the new process and use NtWriteVirtualMemory // to write a copy of the process environment block into the address // space of the new process. Save the address of the allocated block in // the process parameter block so the new process can access it. // if (s = (PWCHAR)ProcessParameters->Environment) { while (*s++) { while (*s++) { } } EnvironmentLength = (SIZE_T)(s - (PWCHAR)ProcessParameters->Environment) * sizeof(WCHAR); Environment = NULL; RegionSize = EnvironmentLength; Status = ZwAllocateVirtualMemory( ProcessInformation->Process, (PVOID *)&Environment, 0, &RegionSize, MEM_COMMIT, PAGE_READWRITE ); if ( !NT_SUCCESS( Status ) ) { ZwClose( ProcessInformation->Process ); ZwClose( Section ); return( Status ); } Status = ZwWriteVirtualMemory( ProcessInformation->Process, Environment, ProcessParameters->Environment, EnvironmentLength, NULL ); if ( !NT_SUCCESS( Status ) ) { ZwClose( ProcessInformation->Process ); ZwClose( Section ); return( Status ); } ProcessParameters->Environment = Environment; } // // Allocate virtual memory in the new process and use NtWriteVirtualMemory // to write a copy of the process parameters block into the address // space of the new process. Set the initial parameter to the new thread // to be the address of the block in the new process's address space. // Parameters = NULL; ParameterLength = ProcessParameters->MaximumLength; Status = ZwAllocateVirtualMemory( ProcessInformation->Process, (PVOID *)&Parameters, 0, &ParameterLength, MEM_COMMIT, PAGE_READWRITE ); if ( !NT_SUCCESS( Status ) ) { ZwClose( ProcessInformation->Process ); ZwClose( Section ); return( Status ); } Status = ZwWriteVirtualMemory( ProcessInformation->Process, Parameters, ProcessParameters, ProcessParameters->Length, NULL ); if ( !NT_SUCCESS( Status ) ) { ZwClose( ProcessInformation->Process ); ZwClose( Section ); return( Status ); } Status = ZwWriteVirtualMemory( ProcessInformation->Process, &Peb->ProcessParameters, &Parameters, sizeof( Parameters ), NULL ); if ( !NT_SUCCESS( Status ) ) { ZwClose( ProcessInformation->Process ); ZwClose( Section ); return( Status ); } // // Create a suspended thread in the new process. Specify the size and // position of the stack, along with the start address, initial parameter // and an SECURITY_DESCRIPTOR. The new thread will not have a name and its handle will // not be inherited by other processes. // Status = RtlCreateUserThread( ProcessInformation->Process, ThreadSecurityDescriptor, TRUE, ProcessInformation->ImageInformation.ZeroBits, ProcessInformation->ImageInformation.MaximumStackSize, ProcessInformation->ImageInformation.CommittedStackSize, (PUSER_THREAD_START_ROUTINE) ProcessInformation->ImageInformation.TransferAddress, (PVOID)Peb, &ProcessInformation->Thread, &ProcessInformation->ClientId ); if ( !NT_SUCCESS( Status ) ) { ZwClose( ProcessInformation->Process ); ZwClose( Section ); return( Status ); } // // Now close the section and file handles. The objects they represent // will not actually go away until the process is destroyed. // ZwClose( Section ); // // Return success status // return( STATUS_SUCCESS ); }
/************************************************************************ *************************************** PgDumpTimerTable ************************************************************************* Description: All PatchGuard 2 related timers will wear the "suspect" sttribute. ATTENTION: The code uses undocumented kernel APIs. Please keep in mind that you shouldn't change the code logic and remember that during enumeration your code will run at DISPATCH_LEVEL! */ NTSTATUS PgDumpTimerTable() { KIRQL OldIrql; ULONG Index; PKSPIN_LOCK_QUEUE LockQueue; PKTIMER_TABLE_ENTRY TimerListHead; PLIST_ENTRY TimerList; PKTIMER Timer; PKDPC TimerDpc; CHAR LogEntryText[2048]; NTSTATUS Result = STATUS_SUCCESS; HANDLE hLogFile; UNICODE_STRING LogFileName; OBJECT_ATTRIBUTES ObjAttr; IO_STATUS_BLOCK IOStatus; ULONG LogEntryTextLen; SINGLE_LIST_ENTRY LogListHead = {NULL}; PSINGLE_LIST_ENTRY LogList; LOGENTRY* LogEntry; ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); /* Open log file... */ RtlInitUnicodeString(&LogFileName, L"\\??\\C:\\patchguard.log"); InitializeObjectAttributes( &ObjAttr, &LogFileName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL) if(!NT_SUCCESS(Result = ZwCreateFile( &hLogFile, GENERIC_WRITE, &ObjAttr, &IOStatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE, NULL, 0))) { KdPrint(("\r\n" "ERROR: Unable to open file \"\\??\\C:\\patchguard.log\". (NTSTATUS: 0x%p)\r\n", (void*)Result)); return Result; } /* Lock the dispatcher database and loop through the timer list... */ Result = STATUS_SUCCESS; OldIrql = KiAcquireDispatcherLockRaiseToSynch(); for(Index = 0; Index < TIMER_TABLE_SIZE; Index++) { // we have to emulate the windows timer bug "Index & 0xFF" for this to work... LockQueue = KeTimerIndexToLockQueue((UCHAR)(Index & 0xFF)); KeAcquireQueuedSpinLockAtDpcLevel(LockQueue); // now we can work with the timer list... TimerListHead = &KiTimerTableListHead[Index]; TimerList = TimerListHead->Entry.Flink; while(TimerList != (PLIST_ENTRY)TimerListHead) { Timer = CONTAINING_RECORD(TimerList, KTIMER, TimerListEntry); TimerDpc = PgDeobfuscateTimerDpc(Timer); TimerList = TimerList->Flink; if(TimerDpc != NULL) { memset(LogEntryText, 0, sizeof(LogEntryText)); LogEntryTextLen = _snprintf(LogEntryText, sizeof(LogEntryText) - 1, "<timer address=\"%p\" index=\"%d\" period=\"0x%p\" hand=\"%d\" duetime=\"0x%p\">\r\n" "%s" " <dpc>\r\n" " <DeferredContext value=\"0x%p\">%s</DeferredContext>\r\n" " <DeferredRoutine>0x%p</DeferredRoutine>\r\n" " <DpcListBlink value=\"0x%p\">%s</DpcListBlink>\r\n" " <DpcListFlink value=\"0x%p\">%s</DpcListFlink>\r\n" " <DpcData value=\"0x%p\">%s</DpcData>\r\n" " <Importance>%d</Importance>\r\n" " <Number>%d</Number>\r\n" " <SystemArgument1 value=\"0x%p\">%s</SystemArgument1>\r\n" " <SystemArgument2 value=\"0x%p\">%s</SystemArgument2>\r\n" " <Type>%d</Type>\r\n" " </dpc>\r\n" "</timer>\r\n\r\n", Timer, Index, (ULONGLONG)Timer->Period, (ULONG)Timer->Header.Hand, Timer->DueTime.QuadPart, PgIsPatchGuardContext(TimerDpc->DeferredContext)?" <SUSPECT>true</SUSPECT>\t\n":"", TimerDpc->DeferredContext, PointerToString(TimerDpc->DeferredContext), TimerDpc->DeferredRoutine, TimerDpc->DpcListEntry.Blink, PointerToString(TimerDpc->DpcListEntry.Blink), TimerDpc->DpcListEntry.Flink, PointerToString(TimerDpc->DpcListEntry.Flink), TimerDpc->DpcData, PointerToString(TimerDpc->DpcData), (ULONG)TimerDpc->Importance, (ULONG)TimerDpc->Number, TimerDpc->SystemArgument1, PointerToString(TimerDpc->SystemArgument1), TimerDpc->SystemArgument2, PointerToString(TimerDpc->SystemArgument2), (ULONG)TimerDpc->Type ); // allocate memory and add log entry to list... if((LogEntry = (LOGENTRY*)ExAllocatePool(NonPagedPool, sizeof(LOGENTRY) + LogEntryTextLen + 1)) == NULL) { KeReleaseQueuedSpinLockFromDpcLevel(LockQueue); Result = STATUS_NO_MEMORY; DbgPrint("\r\n" "WARNING: Not enough non-paged memory to write suspect timer to file. Aborting enumeration...\r\n"); break; } LogEntry->Text = (CHAR*)(LogEntry + 1); LogEntry->Length = LogEntryTextLen; memcpy(LogEntry->Text, LogEntryText, LogEntryTextLen); PushEntryList(&LogListHead, &LogEntry->List); } } KeReleaseQueuedSpinLockFromDpcLevel(LockQueue); } KiReleaseDispatcherLockFromSynchLevel(); KiExitDispatcher(OldIrql); KdPrint(("\r\n" "INFORMATION: Completed PatchGuard scan...\r\n")); /* Loop through the log entries and flush them to disk... In case of an error during enumeration this actually won't write any files, but just free allocated memory... */ LogList = PopEntryList(&LogListHead); while(LogList != NULL) { LogEntry = CONTAINING_RECORD(LogList, LOGENTRY, List); if(NT_SUCCESS(Result)) { Result = ZwWriteFile( hLogFile, NULL, NULL, NULL, &IOStatus, LogEntry->Text, LogEntry->Length, NULL, NULL); } ExFreePool(LogEntry); LogList = PopEntryList(&LogListHead); } ZwClose(hLogFile); return Result; }
PVOID FlushRingBuffre(){ IO_STATUS_BLOCK ioStatusBlock; HANDLE handle; NTSTATUS ntstatus; NTSTATUS FlushingToFile; OBJECT_ATTRIBUTES ObjAttr; UNICODE_STRING pathBuffer; size_t cb; PVOID pEvent; NTSTATUS Status; HANDLE hEvent; OBJECT_ATTRIBUTES oa; UNICODE_STRING us; __debugbreak(); RtlInitUnicodeString( &pathBuffer, L"\\DosDevices\\C:\\MyBufferLogger.txt"); InitializeObjectAttributes( &ObjAttr, &pathBuffer, //ObjectName OBJ_CASE_INSENSITIVE, //Attributes NULL, //RootDirectory NULL); //SecurityDescriptor // Do not try to perform any file operations at higher IRQL levels. // Instead, you may use a work item or a system worker thread to perform file operations. if(KeGetCurrentIrql() != PASSIVE_LEVEL) // return STATUS_INVALID_DEVICE_STATE; DbgPrint("STATUS_INVALID_DEVICE_STATE\n"); ntstatus = ZwCreateFile(&handle, GENERIC_WRITE, &ObjAttr, &ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); RtlInitUnicodeString( &us, L"\\BaseNamedObjects\\TestEvent"); InitializeObjectAttributes( &oa, &us, //ObjectName OBJ_CASE_INSENSITIVE, //Attributes NULL, //RootDirectory NULL); //SecurityDescriptor FlushingToFile=ZwWriteFile( handle, NULL, NULL, NULL, &ioStatusBlock, RingBuffer.tail, RingBuffer.head-RingBuffer.tail, NULL, NULL ); if(FlushingToFile!=STATUS_SUCCESS){ DbgPrint("Writing to file problem"); }else{ DbgPrint("I do not know why"); } ZwClose(handle); }
VOID MyThreadStart(__in PVOID StartContext){ HANDLE handle;//Create File handle NTSTATUS ntstatus; NTSTATUS timerStatus; //IO_STATUS_BLOCK ioStatusBlock; //OBJECT_ATTRIBUTES ObjAttr; //UNICODE_STRING path; LARGE_INTEGER timeout; //#define BUFFER_SIZE 30 // CHAR buffer[BUFFER_SIZE]; //size_t cb; NTSTATUS Status; HANDLE hEvent; //OBJECT_ATTRIBUTES oa; //UNICODE_STRING us; int counter=20; SIZE_T BytesNUM; char* dataPtr; __debugbreak(); dataPtr="123"; BytesNUM=strlen(dataPtr)*sizeof(char); WriteToRingBuffer(&dataPtr, BytesNUM); FlushRingBuffre(); RtlInitUnicodeString( &path, L"\\DosDevices\\C:\\MyLogger.txt"); InitializeObjectAttributes( &ObjAttr, &path, //ObjectName OBJ_CASE_INSENSITIVE, //Attributes NULL, //RootDirectory NULL); //SecurityDescriptor // Do not try to perform any file operations at higher IRQL levels. // Instead, you may use a work item or a system worker thread to perform file operations. if(KeGetCurrentIrql() != PASSIVE_LEVEL) // return STATUS_INVALID_DEVICE_STATE; DbgPrint("STATUS_INVALID_DEVICE_STATE\n"); ntstatus = ZwCreateFile(&handle, GENERIC_WRITE, &ObjAttr, &ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); timeout.QuadPart = -5 * 1000000; RtlInitUnicodeString( &us, L"\\BaseNamedObjects\\TestEvent"); InitializeObjectAttributes( &oa, &us, //ObjectName OBJ_CASE_INSENSITIVE, //Attributes NULL, //RootDirectory NULL); //SecurityDescriptor Status = ZwCreateEvent(&hEvent, EVENT_ALL_ACCESS, &oa, NotificationEvent, FALSE); if(NT_SUCCESS(Status)){ DbgPrint("Event created"); } else { DbgPrint("Event Not created"); } Status = ObReferenceObjectByHandle( hEvent, //Handle EVENT_ALL_ACCESS, //DesiredAccess NULL, //ObjectType KernelMode, //AccessMode &pEvent, //Object NULL); //HandleInformation if (!NT_SUCCESS(Status)) { ZwClose(hEvent); DbgPrint("Failed to reference event \n"); //return Status; }; while(counter!=0){ timerStatus = KeWaitForSingleObject( pEvent, Executive, KernelMode, FALSE, &timeout ); if(timerStatus == STATUS_TIMEOUT){ if(NT_SUCCESS(ntstatus)) { ntstatus = RtlStringCbPrintfA(buffer, sizeof(buffer), "This is %d test\r\n", counter); if(NT_SUCCESS(ntstatus)) { ntstatus = RtlStringCbLengthA(buffer, sizeof(buffer), &cb); if(NT_SUCCESS(ntstatus)) { ntstatus = ZwWriteFile(handle, NULL, NULL, NULL, &ioStatusBlock, buffer, cb, NULL, NULL); } } //ZwClose(handle); } } counter--; } ZwClose(handle); }
vxtctrlr_handle_t vxtdev_open(char * device, unsigned int permissions) { HANDLE filehandle; OBJECT_ATTRIBUTES objattrs; NTSTATUS status; IO_STATUS_BLOCK iostatus; UNICODE_STRING cwsname; wchar_t wszname[1024]; wchar_t *wcp; wchar_t wc; const char *cp; vxtctrlr_handle_t vh; vxt_fd_struct_t vps; vh = malloc(sizeof(*vh)); /* * form a Unicode pathname. If the object directory is not * given (the name does not begin with / or \) then prefix * with the raw volume object directory. */ if (device[0] != '/' && device[0] != '\\') { wcscpy(wszname, L"\\Device\\Vxt\\"); wcp = wszname + wcslen(wszname); } else { wcp = wszname; } for (cp = device; (wc = (wchar_t)(uchar_t)*cp) != 0; cp++) { if (wc == L'/') { wc = L'\\'; } *wcp++ = wc; } *wcp = 0; RtlInitUnicodeString(&cwsname, wszname); /* * open the device. If the open fails, then return NULL and * set volnt_devfile_errno to indicate the error */ InitializeObjectAttributes(&objattrs, &cwsname, OBJ_CASE_INSENSITIVE, NULL, NULL); status = NtOpenFile(&(vh->handle), SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA, &objattrs, &iostatus, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_ALERT); if (status != STATUS_SUCCESS) { return VXT_INVALID_DEV_OBJ; } if (iostatus.Status != STATUS_SUCCESS || vh->handle == NULL) { if (vh->handle) { NtClose(vh->handle); } free(vh); return VXT_INVALID_DEV_OBJ; } vh->privdata = vh->vde = NULL; if(vxtdev_ioctl(vh, IOCTL_FD_OPEN, &vps)){ NtClose(vh->handle); free(vh); return VXT_INVALID_DEV_OBJ; } vh->privdata = vps.private_data; vh->vde = vps.vde; return vh; }
NTSTATUS TdProtectNameCallback ( _In_ PTD_PROTECTNAME_INPUT pProtectName ) { NTSTATUS Status = STATUS_SUCCESS; if (!pProtectName) { DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "ObCallbackTest: TdProtectNameCallback: name to protect/filter NULL pointer\n" ); } else { DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "ObCallbackTest: TdProtectNameCallback: entering name to protect/filter %ls\n", pProtectName->Name ); } KeAcquireGuardedMutex (&TdCallbacksMutex); // Need to copy out the name and then set the flag to filter // This will allow process creation to watch for the process to be created and get the PID // and then prevent any other process from opening up that PID to terminate memcpy(TdwProtectName, pProtectName->Name, sizeof(TdwProtectName)); DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "ObCallbackTest: name copied %ls\n", TdwProtectName ); // Need to enable the OB callbacks // once the process is matched to a newly created process, the callbacks will protect the process if (bCallbacksInstalled == FALSE) { DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "ObCallbackTest: TdProtectNameCallback: installing callbacks\n" ); // Setup the Ob Registration calls CBOperationRegistrations[0].ObjectType = PsProcessType; CBOperationRegistrations[0].Operations |= OB_OPERATION_HANDLE_CREATE; CBOperationRegistrations[0].Operations |= OB_OPERATION_HANDLE_DUPLICATE; CBOperationRegistrations[0].PreOperation = CBTdPreOperationCallback; CBOperationRegistrations[0].PostOperation = CBTdPostOperationCallback; CBOperationRegistrations[1].ObjectType = PsThreadType; CBOperationRegistrations[1].Operations |= OB_OPERATION_HANDLE_CREATE; CBOperationRegistrations[1].Operations |= OB_OPERATION_HANDLE_DUPLICATE; CBOperationRegistrations[1].PreOperation = CBTdPreOperationCallback; CBOperationRegistrations[1].PostOperation = CBTdPostOperationCallback; RtlInitUnicodeString (&CBAltitude, L"1000"); CBObRegistration.Version = OB_FLT_REGISTRATION_VERSION; CBObRegistration.OperationRegistrationCount = 2; CBObRegistration.Altitude = CBAltitude; CBObRegistration.RegistrationContext = &CBCallbackRegistration; CBObRegistration.OperationRegistration = CBOperationRegistrations; Status = ObRegisterCallbacks ( &CBObRegistration, &pCBRegistrationHandle // save the registration handle to remove callbacks later ); if (!NT_SUCCESS (Status)) { DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "ObCallbackTest: installing OB callbacks failed status 0x%x\n", Status ); KeReleaseGuardedMutex (&TdCallbacksMutex); // Release the lock before exit goto Exit; } bCallbacksInstalled = TRUE; } KeReleaseGuardedMutex (&TdCallbacksMutex); DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "ObCallbackTest: TdProtectNameCallback: name to protect/filter %ls\n", TdwProtectName ); Exit: DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "ObCallbackTest: TdProtectNameCallback: exiting status 0x%x\n", Status ); return Status; }
MMRESULT OpenDevice( DeviceInfo** private_data, MIDIOPENDESC* open_desc, DWORD flags) { NTSTATUS status; HANDLE heap; HANDLE kernel_device; UNICODE_STRING beep_device_name; OBJECT_ATTRIBUTES attribs; IO_STATUS_BLOCK status_block; /* One at a time.. */ if ( the_device ) { DPRINT("Already allocated\n"); return MMSYSERR_ALLOCATED; } /* Make the device name into a unicode string and open it */ RtlInitUnicodeString(&beep_device_name, L"\\Device\\Beep"); InitializeObjectAttributes(&attribs, &beep_device_name, 0, NULL, NULL); status = NtCreateFile(&kernel_device, FILE_READ_DATA | FILE_WRITE_DATA, &attribs, &status_block, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_IF, 0, NULL, 0); if ( ! NT_SUCCESS(status) ) { DPRINT("Could not connect to BEEP device - %d\n", (int) GetLastError()); return MMSYSERR_ERROR; } DPRINT("Opened!\n"); /* Allocate and initialize the device info */ heap = GetProcessHeap(); the_device = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(DeviceInfo)); if ( ! the_device ) { DPRINT("Out of memory\n"); return MMSYSERR_NOMEM; } /* Initialize */ the_device->kernel_device = kernel_device; the_device->playing_notes_count = 0; the_device->note_list = NULL; the_device->thread_handle = 0; the_device->terminate_thread = FALSE; the_device->running_status = 0; // TODO the_device->mme_handle = (HDRVR) open_desc->hMidi; the_device->callback = open_desc->dwCallback; the_device->instance = open_desc->dwInstance; the_device->flags = flags; /* Store the pointer in the user data */ *private_data = the_device; /* This is threading-related code */ #ifdef CONTINUOUS_NOTES the_device->work_available = CreateEvent(NULL, TRUE, FALSE, NULL); if ( ! the_device->work_available ) { DPRINT("CreateEvent failed\n"); HeapFree(heap, 0, the_device); return MMSYSERR_NOMEM; } the_device->thread_handle = CreateThread(NULL, 0, ProcessPlayingNotes, (PVOID) the_device, 0, NULL); if ( ! the_device->thread_handle ) { DPRINT("CreateThread failed\n"); CloseHandle(the_device->work_available); HeapFree(heap, 0, the_device); return MMSYSERR_NOMEM; } #endif /* Now we call the client application to say the device is open */ DPRINT("Sending MOM_OPEN\n"); DPRINT("Success? %d\n", (int) CallClient(the_device, MOM_OPEN, 0, 0)); return MMSYSERR_NOERROR; }
NTSTATUS LinkDeviceToDescription( IN PUNICODE_STRING RegistryPath, IN PUNICODE_STRING DeviceName, IN INTERFACE_TYPE BusType, IN ULONG BusNumber, IN CONFIGURATION_TYPE ControllerType, IN ULONG ControllerNumber, IN CONFIGURATION_TYPE PeripheralType, IN ULONG PeripheralNumber ) { // // This routine will create a volatile "Description" key under the // drivers service key. It will store values of the following form // in that key: // // \\Device\\PointerPortX:REG_BINARY:... // \\Device\\KeyboardPortX:REG_BINARY:... // // Where the binary data is six ULONG values (passed as parameters // to this routine) that describe the physical location of the device. // NTSTATUS Status = STATUS_SUCCESS; HANDLE ServiceKey = NULL, DescriptionKey = NULL; UNICODE_STRING RegString; OBJECT_ATTRIBUTES ObjectAttributes; ULONG disposition; HWDESC_INFO HwDescInfo; HwDescInfo.InterfaceType = BusType; HwDescInfo.InterfaceNumber = BusNumber; HwDescInfo.ControllerType = ControllerType; HwDescInfo.ControllerNumber = ControllerNumber; HwDescInfo.PeripheralType = PeripheralType; HwDescInfo.PeripheralNumber = PeripheralNumber; // // Open the service subkey // InitializeObjectAttributes(&ObjectAttributes, RegistryPath, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenKey(&ServiceKey, KEY_WRITE, &ObjectAttributes); if (!NT_SUCCESS(Status)) { goto Clean0; } // // Create a volatile Description subkey under the service subkey // RtlInitUnicodeString(&RegString, L"Description"); InitializeObjectAttributes(&ObjectAttributes, &RegString, OBJ_CASE_INSENSITIVE, ServiceKey, NULL); Status = ZwCreateKey(&DescriptionKey, KEY_ALL_ACCESS, &ObjectAttributes, 0, (PUNICODE_STRING)NULL, REG_OPTION_VOLATILE, &disposition); if (!NT_SUCCESS(Status)) { goto Clean0; } // // The description data is stored under a REG_BINARY value (name // is the DeviceName passed in as a parameter) // Status = ZwSetValueKey(DescriptionKey, DeviceName, 0, REG_BINARY, &HwDescInfo, sizeof(HwDescInfo)); Clean0: if (DescriptionKey) { ZwClose(DescriptionKey); } if (ServiceKey) { ZwClose(ServiceKey); } return Status; }
/* I really want PCSZ strings as last arguments because * PnP ids are ANSI-encoded in PnP device string * identification */ NTSTATUS SerenumInitMultiSzString( OUT PUNICODE_STRING Destination, ... /* list of PCSZ */) { va_list args; PCSZ Source; ANSI_STRING AnsiString; UNICODE_STRING UnicodeString; ULONG DestinationSize = 0; NTSTATUS Status = STATUS_SUCCESS; ASSERT(Destination); /* Calculate length needed for destination unicode string */ va_start(args, Destination); Source = va_arg(args, PCSZ); while (Source != NULL) { RtlInitAnsiString(&AnsiString, Source); DestinationSize += RtlAnsiStringToUnicodeSize(&AnsiString) + sizeof(WCHAR) /* final NULL */; Source = va_arg(args, PCSZ); } va_end(args); if (DestinationSize == 0) { RtlInitUnicodeString(Destination, NULL); return STATUS_SUCCESS; } /* Initialize destination string */ DestinationSize += sizeof(WCHAR); // final NULL Destination->Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool, DestinationSize, SERENUM_TAG); if (!Destination->Buffer) return STATUS_INSUFFICIENT_RESOURCES; Destination->Length = 0; Destination->MaximumLength = (USHORT)DestinationSize; /* Copy arguments to destination string */ /* Use a temporary unicode string, which buffer is shared with * destination string, to copy arguments */ UnicodeString.Length = Destination->Length; UnicodeString.MaximumLength = Destination->MaximumLength; UnicodeString.Buffer = Destination->Buffer; va_start(args, Destination); Source = va_arg(args, PCSZ); while (Source != NULL) { RtlInitAnsiString(&AnsiString, Source); Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, FALSE); if (!NT_SUCCESS(Status)) { ExFreePoolWithTag(Destination->Buffer, SERENUM_TAG); break; } Destination->Length += UnicodeString.Length + sizeof(WCHAR); UnicodeString.MaximumLength -= UnicodeString.Length + sizeof(WCHAR); UnicodeString.Buffer += UnicodeString.Length / sizeof(WCHAR) + 1; UnicodeString.Length = 0; Source = va_arg(args, PCSZ); } va_end(args); if (NT_SUCCESS(Status)) { /* Finish multi-sz string */ Destination->Buffer[Destination->Length / sizeof(WCHAR)] = L'\0'; Destination->Length += sizeof(WCHAR); } return Status; }
static NTSTATUS LfsFiltOpenControl ( OUT PHANDLE ControlFileHandle, OUT PFILE_OBJECT *ControlFileObject ) { HANDLE controlFileHandle; PFILE_OBJECT controlFileObject; UNICODE_STRING nameString; OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK ioStatusBlock; NTSTATUS status; Bus_KdPrint_Def(BUS_DBG_SS_TRACE, ("Entered\n")); // // Init object attributes // RtlInitUnicodeString (&nameString, LFSFILT_CTLDEVICE_NAME); InitializeObjectAttributes ( &objectAttributes, &nameString, 0, NULL, NULL ); status = ZwCreateFile( &controlFileHandle, GENERIC_READ, &objectAttributes, &ioStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, 0, 0, NULL, // Open as control 0 // ); if (!NT_SUCCESS(status)) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("FAILURE, ZwCreateFile returned status code=%x\n", status)); *ControlFileHandle = NULL; *ControlFileObject = NULL; return status; } status = ioStatusBlock.Status; if (!NT_SUCCESS(status)) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("FAILURE, IoStatusBlock.Status contains status code=%x\n", status)); *ControlFileHandle = NULL; *ControlFileObject = NULL; return status; } status = ObReferenceObjectByHandle ( controlFileHandle, 0L, NULL, KernelMode, (PVOID *) &controlFileObject, NULL ); if (!NT_SUCCESS(status)) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("ObReferenceObjectByHandle() failed. STATUS=%08lx\n", status)); ZwClose(controlFileHandle); *ControlFileHandle = NULL; *ControlFileObject = NULL; return status; } *ControlFileHandle = controlFileHandle; *ControlFileObject = controlFileObject; return status; }
NTSTATUS DriverEntry( __in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath ) /*++ Routine Description: Installable driver initialization entry point. This entry point is called directly by the I/O system. Arguments: DriverObject - pointer to the driver object registryPath - pointer to a unicode string representing the path, to driver-specific key in the registry. Return Value: STATUS_SUCCESS if successful, STATUS_UNSUCCESSFUL otherwise --*/ { NTSTATUS status = STATUS_SUCCESS; UNICODE_STRING unicodeDeviceName; UNICODE_STRING unicodeDosDeviceName; PDEVICE_OBJECT deviceObject; PDEVICE_EXTENSION devExtension; HANDLE threadHandle; UNICODE_STRING sddlString; UNREFERENCED_PARAMETER (RegistryPath); CSAMP_KDPRINT(("DriverEntry Enter \n")); (void) RtlInitUnicodeString(&unicodeDeviceName, CSAMP_DEVICE_NAME_U); (void) RtlInitUnicodeString( &sddlString, L"D:P(A;;GA;;;SY)(A;;GA;;;BA)"); // // We will create a secure deviceobject so that only processes running // in admin and local system account can access the device. Refer // "Security Descriptor String Format" section in the platform // SDK documentation to understand the format of the sddl string. // We need to do because this is a legacy driver and there is no INF // involved in installing the driver. For PNP drivers, security descriptor // is typically specified for the FDO in the INF file. // status = IoCreateDeviceSecure( DriverObject, sizeof(DEVICE_EXTENSION), &unicodeDeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, (BOOLEAN) FALSE, &sddlString, (LPCGUID)&GUID_DEVCLASS_CANCEL_SAMPLE, &deviceObject ); if (!NT_SUCCESS(status)) { return status; } DbgPrint("DeviceObject %p\n", deviceObject); // // Allocate and initialize a Unicode String containing the Win32 name // for our device. // (void)RtlInitUnicodeString( &unicodeDosDeviceName, CSAMP_DOS_DEVICE_NAME_U ); status = IoCreateSymbolicLink( (PUNICODE_STRING) &unicodeDosDeviceName, (PUNICODE_STRING) &unicodeDeviceName ); if (!NT_SUCCESS(status)) { IoDeleteDevice(deviceObject); return status; } devExtension = deviceObject->DeviceExtension; DriverObject->MajorFunction[IRP_MJ_CREATE]= DriverObject->MajorFunction[IRP_MJ_CLOSE] = CsampCreateClose; DriverObject->MajorFunction[IRP_MJ_READ] = CsampRead; DriverObject->MajorFunction[IRP_MJ_CLEANUP] = CsampCleanup; DriverObject->DriverUnload = CsampUnload; // // Set the flag signifying that we will do buffered I/O. This causes NT // to allocate a buffer on a ReadFile operation which will then be copied // back to the calling application by the I/O subsystem // deviceObject->Flags |= DO_BUFFERED_IO; // // This is used to serailize access to the queue. // KeInitializeSpinLock(&devExtension->QueueLock); KeInitializeSemaphore(&devExtension->IrpQueueSemaphore, 0, MAXLONG ); // // Initialize the pending Irp devicequeue // InitializeListHead( &devExtension->PendingIrpQueue ); // // Initialize the cancel safe queue // IoCsqInitialize( &devExtension->CancelSafeQueue, CsampInsertIrp, CsampRemoveIrp, CsampPeekNextIrp, CsampAcquireLock, CsampReleaseLock, CsampCompleteCanceledIrp ); // // 10 is multiplied because system time is specified in 100ns units // devExtension->PollingInterval.QuadPart = Int32x32To64( CSAMP_RETRY_INTERVAL, -10); // // Note down system time // KeQuerySystemTime (&devExtension->LastPollTime); // // Start the polling thread. // devExtension->ThreadShouldStop = FALSE; status = PsCreateSystemThread(&threadHandle, (ACCESS_MASK)0, NULL, (HANDLE) 0, NULL, CsampPollingThread, deviceObject ); if ( !NT_SUCCESS( status )) { IoDeleteSymbolicLink( &unicodeDosDeviceName ); IoDeleteDevice( deviceObject ); return status; } // // Convert the Thread object handle into a pointer to the Thread object // itself. Then close the handle. // ObReferenceObjectByHandle(threadHandle, THREAD_ALL_ACCESS, NULL, KernelMode, &devExtension->ThreadObject, NULL ); ZwClose(threadHandle); CSAMP_KDPRINT(("DriverEntry Exit = %x\n", status)); ASSERT(NT_SUCCESS(status)); return status; }
NTSTATUS HotKeyKrnlAttachDevices( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { NTSTATUS status = 0; UNICODE_STRING uniNtNameString; PDEVICE_EXTENSION devExt; PDEVICE_OBJECT pFilterDeviceObject = NULL; PDEVICE_OBJECT pTargetDeviceObject = NULL; PDEVICE_OBJECT pLowerDeviceObject = NULL; PDRIVER_OBJECT KbdDriverObject = NULL; extern POBJECT_TYPE *IoDriverObjectType; // Exported by ntoskrnl.exe, shit ! // ref kbdclass driver object RtlInitUnicodeString(&uniNtNameString, KBD_DRIVER_NAME); status = ObReferenceObjectByName(&uniNtNameString, OBJ_CASE_INSENSITIVE, NULL, 0, *IoDriverObjectType, KernelMode, NULL, &KbdDriverObject); if(!NT_SUCCESS(status)) { KdPrint(("[shadow] ObReferenceObjectByName failed,cann't access Kbdclass.\n")); return status; } else { ObDereferenceObject(KbdDriverObject); } // 绑定该驱动对象ä¸çš„所有设备对象 pTargetDeviceObject = KbdDriverObject->DeviceObject; while (pTargetDeviceObject) { // 创建过滤设备 status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL, pTargetDeviceObject->DeviceType, pTargetDeviceObject->Characteristics, FALSE, &pFilterDeviceObject); if (!NT_SUCCESS(status)) { KdPrint(("[shadow] IoCreateDevice(filter device) failed.\n")); return status; } // 绑定 if(!(pLowerDeviceObject = IoAttachDeviceToDeviceStack(pFilterDeviceObject, pTargetDeviceObject))) { KdPrint(("[shadow] IoAttachDeviceToDeviceStack failed.\n")); IoDeleteDevice(pFilterDeviceObject); pFilterDeviceObject = NULL; return status; } devExt = (PDEVICE_EXTENSION)(pFilterDeviceObject->DeviceExtension); RtlZeroMemory(devExt, sizeof(DEVICE_EXTENSION)); devExt->NodeSize = sizeof(DEVICE_EXTENSION); devExt->pFilterDeviceObject = pFilterDeviceObject; devExt->TargetDeviceObject = pTargetDeviceObject; devExt->LowerDeviceObject = pLowerDeviceObject; pFilterDeviceObject->DeviceType = pLowerDeviceObject->DeviceType; pFilterDeviceObject->Characteristics = pLowerDeviceObject->Characteristics; pFilterDeviceObject->StackSize = pLowerDeviceObject->StackSize+1; pFilterDeviceObject->Flags |= pLowerDeviceObject->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE); pTargetDeviceObject = pTargetDeviceObject->NextDevice; } return status; }
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath ) { /* IRQL == PASSIVE_LEVEL */ UNREFERENCED_PARAMETER( DriverObject ); UNREFERENCED_PARAMETER( RegistryPath ); NTSTATUS status; DbgPrint( "file system protection filter start" ); /* initialize IRP */ InitializeIrpDispatchers( DriverObject ); /* create device */ UNICODE_STRING deviceObjectName; RtlInitUnicodeString( &deviceObjectName, L"\\device\\disklocker_fsprotdrv" ); PDEVICE_OBJECT DeviceObject; status = CreateIoDevice( deviceObjectName, DriverObject, &DeviceObject ); if (!NT_SUCCESS( status )) { DbgPrint( "CreateIoDevice() failed with code = %08x\n", status ); return status; } SetDeviceExt( DeviceObject->DeviceExtension ); /* initialize device extension */ GetDeviceExt()->DeviceObject = DeviceObject; GetDeviceExt()->DriverObject = DriverObject; GetDeviceExt()->UnloadRoutine = OnUnload; GetDeviceExt()->FileListHead = NULL; GetDeviceExt()->LastUniqueKey = 1; KeInitializeSpinLock( &(GetDeviceExt()->FileListAccessSpinLock) ); /* create symlink */ RtlInitUnicodeString( &SymbolicLinkName, L"\\DosDevices\\disklocker_fsprotdrv" ); status = IoCreateSymbolicLink( &SymbolicLinkName, &deviceObjectName ); if (!NT_SUCCESS( status )) { /* delete registered device */ IoDeleteDevice( GetDeviceExt()->DeviceObject ); DbgPrint( "IoCreateSymbolicLink() failed with code = %08x\n", status ); return status; } /* register filter */ status = FltRegisterFilter( DriverObject, &FilterRegistration, &(GetDeviceExt()->FltFilter) ); if (!NT_SUCCESS( status )) { /* delete registered symbolic link */ IoDeleteSymbolicLink( &SymbolicLinkName ); /* delete registered device */ IoDeleteDevice( GetDeviceExt()->DeviceObject ); DbgPrint( "FltRegisterFilter() failed with code = %08x\n", status ); return status; } /* start filtering */ status = FltStartFiltering( GetDeviceExt()->FltFilter ); if (!NT_SUCCESS( status )) { /* delete registered symbolic link */ IoDeleteSymbolicLink( &SymbolicLinkName ); /* delete registered device */ IoDeleteDevice( GetDeviceExt()->DeviceObject ); /* unregister filter */ FltUnregisterFilter( GetDeviceExt()->FltFilter ); DbgPrint( "FltStartFiltering() failed with code = %08x\n", status ); return status; } /* initialization done */ DbgPrint( "file system filter initialization done..." ); return STATUS_SUCCESS; }
BOOLEAN ndisprotRegisterExCallBack() { OBJECT_ATTRIBUTES ObjectAttr; UNICODE_STRING CallBackObjectName; NTSTATUS Status; BOOLEAN bResult = TRUE; DEBUGP(DL_LOUD, ("--> ndisprotRegisterExCallBack\n")); PAGED_CODE(); do { RtlInitUnicodeString(&CallBackObjectName, NDISPROT_CALLBACK_NAME); InitializeObjectAttributes(&ObjectAttr, &CallBackObjectName, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, NULL, NULL); Status = ExCreateCallback(&CallbackObject, &ObjectAttr, TRUE, TRUE); if (!NT_SUCCESS(Status)) { DEBUGP(DL_ERROR, ("RegisterExCallBack: failed to create callback %lx\n", Status)); bResult = FALSE; break; } CallbackRegisterationHandle = ExRegisterCallback(CallbackObject, ndisprotCallback, (PVOID)NULL); if (CallbackRegisterationHandle == NULL) { DEBUGP(DL_ERROR,("RegisterExCallBack: failed to register a Callback routine%lx\n", Status)); bResult = FALSE; break; } ExNotifyCallback(CallbackObject, (PVOID)CALLBACK_SOURCE_NDISPROT, (PVOID)NULL); }WHILE(FALSE); if(!bResult) { if (CallbackRegisterationHandle) { ExUnregisterCallback(CallbackRegisterationHandle); CallbackRegisterationHandle = NULL; } if (CallbackObject) { ObDereferenceObject(CallbackObject); CallbackObject = NULL; } } DEBUGP(DL_LOUD, ("<-- ndisprotRegisterExCallBack\n")); return bResult; }
/*********************************************************************** * CryptCATEnumerateMember (WINTRUST.@) */ CRYPTCATMEMBER * WINAPI CryptCATEnumerateMember(HANDLE hCatalog, CRYPTCATMEMBER *prev) { struct cryptcat *cc = hCatalog; CRYPTCATMEMBER *member = prev; CTL_ENTRY *entry; DWORD size, i; TRACE("%p, %p\n", hCatalog, prev); if (!hCatalog || hCatalog == INVALID_HANDLE_VALUE || cc->magic != CRYPTCAT_MAGIC) { SetLastError(ERROR_INVALID_PARAMETER); return NULL; } /* dumping the contents makes me think that dwReserved is the iteration number */ if (!member) { if (!(member = HeapAlloc(GetProcessHeap(), 0, sizeof(*member)))) { SetLastError(ERROR_OUTOFMEMORY); return NULL; } member->cbStruct = sizeof(*member); member->pwszFileName = member->pwszReferenceTag = NULL; member->dwReserved = 0; member->hReserved = NULL; member->gSubjectType = cc->subject; member->fdwMemberFlags = 0; member->pIndirectData = NULL; member->dwCertVersion = cc->inner->dwVersion; } else member->dwReserved++; if (member->dwReserved >= cc->inner->cCTLEntry) { SetLastError(ERROR_INVALID_PARAMETER); goto error; } /* list them backwards, like native */ entry = &cc->inner->rgCTLEntry[cc->inner->cCTLEntry - member->dwReserved - 1]; member->sEncodedIndirectData.cbData = member->sEncodedMemberInfo.cbData = 0; member->sEncodedIndirectData.pbData = member->sEncodedMemberInfo.pbData = NULL; HeapFree(GetProcessHeap(), 0, member->pIndirectData); member->pIndirectData = NULL; for (i = 0; i < entry->cAttribute; i++) { CRYPT_ATTRIBUTE *attr = entry->rgAttribute + i; if (attr->cValue != 1) { ERR("Can't handle attr->cValue of %u\n", attr->cValue); continue; } if (!strcmp(attr->pszObjId, CAT_MEMBERINFO_OBJID)) { CAT_MEMBERINFO *mi; BOOL ret; member->sEncodedMemberInfo.cbData = attr->rgValue->cbData; member->sEncodedMemberInfo.pbData = attr->rgValue->pbData; CryptDecodeObject(cc->encoding, CAT_MEMBERINFO_OBJID, attr->rgValue->pbData, attr->rgValue->cbData, 0, NULL, &size); if (!(mi = HeapAlloc(GetProcessHeap(), 0, size))) { SetLastError(ERROR_OUTOFMEMORY); goto error; } ret = CryptDecodeObject(cc->encoding, CAT_MEMBERINFO_OBJID, attr->rgValue->pbData, attr->rgValue->cbData, 0, mi, &size); if (ret) { UNICODE_STRING guid; member->dwCertVersion = mi->dwCertVersion; RtlInitUnicodeString(&guid, mi->pwszSubjGuid); if (RtlGUIDFromString(&guid, &member->gSubjectType)) { HeapFree(GetProcessHeap(), 0, mi); goto error; } } HeapFree(GetProcessHeap(), 0, mi); if (!ret) goto error; } else if (!strcmp(attr->pszObjId, SPC_INDIRECT_DATA_OBJID)) { /* SPC_INDIRECT_DATA_CONTENT is equal to SIP_INDIRECT_DATA */ member->sEncodedIndirectData.cbData = attr->rgValue->cbData; member->sEncodedIndirectData.pbData = attr->rgValue->pbData; CryptDecodeObject(cc->encoding, SPC_INDIRECT_DATA_OBJID, attr->rgValue->pbData, attr->rgValue->cbData, 0, NULL, &size); if (!(member->pIndirectData = HeapAlloc(GetProcessHeap(), 0, size))) { SetLastError(ERROR_OUTOFMEMORY); goto error; } CryptDecodeObject(cc->encoding, SPC_INDIRECT_DATA_OBJID, attr->rgValue->pbData, attr->rgValue->cbData, 0, member->pIndirectData, &size); } else /* this object id should probably be handled in CryptCATEnumerateAttr */ FIXME("unhandled object id \"%s\"\n", attr->pszObjId); } if (!member->sEncodedMemberInfo.cbData || !member->sEncodedIndirectData.cbData) { ERR("Corrupted catalog entry?\n"); SetLastError(CRYPT_E_ATTRIBUTES_MISSING); goto error; } size = (2 * member->pIndirectData->Digest.cbData + 1) * sizeof(WCHAR); if (member->pwszReferenceTag) member->pwszReferenceTag = HeapReAlloc(GetProcessHeap(), 0, member->pwszReferenceTag, size); else member->pwszReferenceTag = HeapAlloc(GetProcessHeap(), 0, size); if (!member->pwszReferenceTag) { SetLastError(ERROR_OUTOFMEMORY); goto error; } /* FIXME: reference tag is usually the file hash but doesn't have to be */ for (i = 0; i < member->pIndirectData->Digest.cbData; i++) { DWORD sub; sub = member->pIndirectData->Digest.pbData[i] >> 4; member->pwszReferenceTag[i * 2] = (sub < 10 ? '0' + sub : 'A' + sub - 10); sub = member->pIndirectData->Digest.pbData[i] & 0xf; member->pwszReferenceTag[i * 2 + 1] = (sub < 10 ? '0' + sub : 'A' + sub - 10); } member->pwszReferenceTag[i * 2] = 0; return member; error: HeapFree(GetProcessHeap(), 0, member->pIndirectData); HeapFree(GetProcessHeap(), 0, member->pwszReferenceTag); HeapFree(GetProcessHeap(), 0, member); return NULL; }
BOOLEAN INIT_FUNCTION NTAPI ObInitSystem(VOID) { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING Name; OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; OBP_LOOKUP_CONTEXT Context; HANDLE Handle; PKPRCB Prcb = KeGetCurrentPrcb(); PLIST_ENTRY ListHead, NextEntry; POBJECT_HEADER Header; POBJECT_HEADER_CREATOR_INFO CreatorInfo; POBJECT_HEADER_NAME_INFO NameInfo; NTSTATUS Status; /* Check if this is actually Phase 1 initialization */ if (ObpInitializationPhase != 0) goto ObPostPhase0; /* Initialize the OBJECT_CREATE_INFORMATION List */ ExInitializeSystemLookasideList(&ObpCreateInfoLookasideList, NonPagedPool, sizeof(OBJECT_CREATE_INFORMATION), 'ICbO', 32, &ExSystemLookasideListHead); /* Set the captured UNICODE_STRING Object Name List */ ExInitializeSystemLookasideList(&ObpNameBufferLookasideList, PagedPool, 248, 'MNbO', 16, &ExSystemLookasideListHead); /* Temporarily setup both pointers to the shared list */ Prcb->PPLookasideList[LookasideCreateInfoList].L = &ObpCreateInfoLookasideList; Prcb->PPLookasideList[LookasideCreateInfoList].P = &ObpCreateInfoLookasideList; Prcb->PPLookasideList[LookasideNameBufferList].L = &ObpNameBufferLookasideList; Prcb->PPLookasideList[LookasideNameBufferList].P = &ObpNameBufferLookasideList; /* Initialize the security descriptor cache */ ObpInitSdCache(); /* Initialize the Default Event */ KeInitializeEvent(&ObpDefaultObject, NotificationEvent, TRUE); /* Initialize the Dos Device Map mutex */ KeInitializeGuardedMutex(&ObpDeviceMapLock); /* Setup default access for the system process */ PsGetCurrentProcess()->GrantedAccess = PROCESS_ALL_ACCESS; PsGetCurrentThread()->GrantedAccess = THREAD_ALL_ACCESS; /* Setup the Object Reaper */ ExInitializeWorkItem(&ObpReaperWorkItem, ObpReapObject, NULL); /* Initialize default Quota block */ PsInitializeQuotaSystem(); /* Create kernel handle table */ PsGetCurrentProcess()->ObjectTable = ExCreateHandleTable(NULL); ObpKernelHandleTable = PsGetCurrentProcess()->ObjectTable; /* Create the Type Type */ RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); RtlInitUnicodeString(&Name, L"Type"); ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); ObjectTypeInitializer.ValidAccessMask = OBJECT_TYPE_ALL_ACCESS; ObjectTypeInitializer.UseDefaultObject = TRUE; ObjectTypeInitializer.MaintainTypeList = TRUE; ObjectTypeInitializer.PoolType = NonPagedPool; ObjectTypeInitializer.GenericMapping = ObpTypeMapping; ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_TYPE); ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK; ObjectTypeInitializer.DeleteProcedure = ObpDeleteObjectType; ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ObpTypeObjectType); /* Create the Directory Type */ RtlInitUnicodeString(&Name, L"Directory"); ObjectTypeInitializer.ValidAccessMask = DIRECTORY_ALL_ACCESS; ObjectTypeInitializer.CaseInsensitive = TRUE; ObjectTypeInitializer.MaintainTypeList = FALSE; ObjectTypeInitializer.GenericMapping = ObpDirectoryMapping; ObjectTypeInitializer.DeleteProcedure = NULL; ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_DIRECTORY); ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ObDirectoryType); /* Create 'symbolic link' object type */ RtlInitUnicodeString(&Name, L"SymbolicLink"); ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(OBJECT_SYMBOLIC_LINK); ObjectTypeInitializer.GenericMapping = ObpSymbolicLinkMapping; ObjectTypeInitializer.ValidAccessMask = SYMBOLIC_LINK_ALL_ACCESS; ObjectTypeInitializer.ParseProcedure = ObpParseSymbolicLink; ObjectTypeInitializer.DeleteProcedure = ObpDeleteSymbolicLink; ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &ObSymbolicLinkType); /* Phase 0 initialization complete */ ObpInitializationPhase++; return TRUE; ObPostPhase0: /* Re-initialize lookaside lists */ ObInit2(); /* Initialize Object Types directory attributes */ RtlInitUnicodeString(&Name, L"\\"); InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, NULL, SePublicDefaultUnrestrictedSd); /* Create the directory */ Status = NtCreateDirectoryObject(&Handle, DIRECTORY_ALL_ACCESS, &ObjectAttributes); if (!NT_SUCCESS(Status)) return FALSE; /* Get a handle to it */ Status = ObReferenceObjectByHandle(Handle, 0, ObDirectoryType, KernelMode, (PVOID*)&ObpRootDirectoryObject, NULL); if (!NT_SUCCESS(Status)) return FALSE; /* Close the extra handle */ Status = NtClose(Handle); if (!NT_SUCCESS(Status)) return FALSE; /* Initialize Object Types directory attributes */ RtlInitUnicodeString(&Name, L"\\KernelObjects"); InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, NULL, NULL); /* Create the directory */ Status = NtCreateDirectoryObject(&Handle, DIRECTORY_ALL_ACCESS, &ObjectAttributes); if (!NT_SUCCESS(Status)) return FALSE; /* Close the extra handle */ Status = NtClose(Handle); if (!NT_SUCCESS(Status)) return FALSE; /* Initialize Object Types directory attributes */ RtlInitUnicodeString(&Name, L"\\ObjectTypes"); InitializeObjectAttributes(&ObjectAttributes, &Name, OBJ_CASE_INSENSITIVE | OBJ_PERMANENT, NULL, NULL); /* Create the directory */ Status = NtCreateDirectoryObject(&Handle, DIRECTORY_ALL_ACCESS, &ObjectAttributes); if (!NT_SUCCESS(Status)) return FALSE; /* Get a handle to it */ Status = ObReferenceObjectByHandle(Handle, 0, ObDirectoryType, KernelMode, (PVOID*)&ObpTypeDirectoryObject, NULL); if (!NT_SUCCESS(Status)) return FALSE; /* Close the extra handle */ Status = NtClose(Handle); if (!NT_SUCCESS(Status)) return FALSE; /* Initialize lookup context */ ObpInitializeLookupContext(&Context); /* Lock it */ ObpAcquireDirectoryLockExclusive(ObpTypeDirectoryObject, &Context); /* Loop the object types */ ListHead = &ObpTypeObjectType->TypeList; NextEntry = ListHead->Flink; while (ListHead != NextEntry) { /* Get the creator info from the list */ CreatorInfo = CONTAINING_RECORD(NextEntry, OBJECT_HEADER_CREATOR_INFO, TypeList); /* Recover the header and the name header from the creator info */ Header = (POBJECT_HEADER)(CreatorInfo + 1); NameInfo = OBJECT_HEADER_TO_NAME_INFO(Header); /* Make sure we have a name, and aren't inserted yet */ if ((NameInfo) && !(NameInfo->Directory)) { /* Do the initial lookup to setup the context */ if (!ObpLookupEntryDirectory(ObpTypeDirectoryObject, &NameInfo->Name, OBJ_CASE_INSENSITIVE, FALSE, &Context)) { /* Insert this object type */ ObpInsertEntryDirectory(ObpTypeDirectoryObject, &Context, Header); } } /* Move to the next entry */ NextEntry = NextEntry->Flink; } /* Cleanup after lookup */ ObpReleaseLookupContext(&Context); /* Initialize DOS Devices Directory and related Symbolic Links */ Status = ObpCreateDosDevicesDirectory(); if (!NT_SUCCESS(Status)) return FALSE; return TRUE; }
PPCI_REGISTRY_INFO_INTERNAL NTAPI INIT_FUNCTION HalpQueryPciRegistryInfo(VOID) { #ifndef _MINIHAL_ WCHAR NameBuffer[8]; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING KeyName, ConfigName, IdentName; HANDLE KeyHandle, BusKeyHandle, CardListHandle; NTSTATUS Status; UCHAR KeyBuffer[sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + 100]; PKEY_VALUE_FULL_INFORMATION ValueInfo = (PVOID)KeyBuffer; UCHAR PartialKeyBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(PCI_CARD_DESCRIPTOR)]; PKEY_VALUE_PARTIAL_INFORMATION PartialValueInfo = (PVOID)PartialKeyBuffer; KEY_FULL_INFORMATION KeyInformation; ULONG ResultLength; PWSTR Tag; ULONG i, ElementCount; PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor; PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; PPCI_REGISTRY_INFO PciRegInfo; PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo; PPCI_CARD_DESCRIPTOR CardDescriptor; /* Setup the object attributes for the key */ RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\Hardware\\Description\\" L"System\\MultiFunctionAdapter"); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL); /* Open the key */ Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes); if (!NT_SUCCESS(Status)) return NULL; /* Setup the receiving string */ KeyName.Buffer = NameBuffer; KeyName.MaximumLength = sizeof(NameBuffer); /* Setup the configuration and identifier key names */ RtlInitUnicodeString(&ConfigName, L"Configuration Data"); RtlInitUnicodeString(&IdentName, L"Identifier"); /* Keep looping for each ID */ for (i = 0; TRUE; i++) { /* Setup the key name */ RtlIntegerToUnicodeString(i, 10, &KeyName); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, KeyHandle, NULL); /* Open it */ Status = ZwOpenKey(&BusKeyHandle, KEY_READ, &ObjectAttributes); if (!NT_SUCCESS(Status)) { /* None left, fail */ ZwClose(KeyHandle); return NULL; } /* Read the registry data */ Status = ZwQueryValueKey(BusKeyHandle, &IdentName, KeyValueFullInformation, ValueInfo, sizeof(KeyBuffer), &ResultLength); if (!NT_SUCCESS(Status)) { /* Failed, try the next one */ ZwClose(BusKeyHandle); continue; } /* Get the PCI Tag and validate it */ Tag = (PWSTR)((ULONG_PTR)ValueInfo + ValueInfo->DataOffset); if ((Tag[0] != L'P') || (Tag[1] != L'C') || (Tag[2] != L'I') || (Tag[3])) { /* Not a valid PCI entry, skip it */ ZwClose(BusKeyHandle); continue; } /* Now read our PCI structure */ Status = ZwQueryValueKey(BusKeyHandle, &ConfigName, KeyValueFullInformation, ValueInfo, sizeof(KeyBuffer), &ResultLength); ZwClose(BusKeyHandle); if (!NT_SUCCESS(Status)) continue; /* We read it OK! Get the actual resource descriptors */ FullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) ((ULONG_PTR)ValueInfo + ValueInfo->DataOffset); PartialDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((ULONG_PTR)FullDescriptor-> PartialResourceList.PartialDescriptors); /* Check if this is our PCI Registry Information */ if (PartialDescriptor->Type == CmResourceTypeDeviceSpecific) { /* It is, stop searching */ break; } } /* Close the key */ ZwClose(KeyHandle); /* Save the PCI information for later */ PciRegInfo = (PPCI_REGISTRY_INFO)(PartialDescriptor + 1); /* Assume no Card List entries */ ElementCount = 0; /* Set up for checking the PCI Card List key */ RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\" L"Control\\PnP\\PCI\\CardList"); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL); /* Attempt to open it */ Status = ZwOpenKey(&CardListHandle, KEY_READ, &ObjectAttributes); if (NT_SUCCESS(Status)) { /* It exists, so let's query it */ Status = ZwQueryKey(CardListHandle, KeyFullInformation, &KeyInformation, sizeof(KEY_FULL_INFORMATION), &ResultLength); if (!NT_SUCCESS(Status)) { /* Failed to query, so no info */ PciRegistryInfo = NULL; } else { /* Allocate the full structure */ PciRegistryInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(PCI_REGISTRY_INFO_INTERNAL) + (KeyInformation.Values * sizeof(PCI_CARD_DESCRIPTOR)), TAG_HAL); if (PciRegistryInfo) { /* Get the first card descriptor entry */ CardDescriptor = (PPCI_CARD_DESCRIPTOR)(PciRegistryInfo + 1); /* Loop all the values */ for (i = 0; i < KeyInformation.Values; i++) { /* Attempt to get the value */ Status = ZwEnumerateValueKey(CardListHandle, i, KeyValuePartialInformation, PartialValueInfo, sizeof(PartialKeyBuffer), &ResultLength); if (!NT_SUCCESS(Status)) { /* Something went wrong, stop the search */ break; } /* Make sure it is correctly sized */ if (PartialValueInfo->DataLength == sizeof(PCI_CARD_DESCRIPTOR)) { /* Sure is, copy it over */ *CardDescriptor = *(PPCI_CARD_DESCRIPTOR) PartialValueInfo->Data; /* One more Card List entry */ ElementCount++; /* Move to the next descriptor */ CardDescriptor = (CardDescriptor + 1); } } } } /* Close the Card List key */ ZwClose(CardListHandle); } else { /* No key, no Card List */ PciRegistryInfo = NULL; } /* Check if we failed to get the full structure */ if (!PciRegistryInfo) { /* Just allocate the basic structure then */ PciRegistryInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(PCI_REGISTRY_INFO_INTERNAL), TAG_HAL); if (!PciRegistryInfo) return NULL; } /* Save the info we got */ PciRegistryInfo->MajorRevision = PciRegInfo->MajorRevision; PciRegistryInfo->MinorRevision = PciRegInfo->MinorRevision; PciRegistryInfo->NoBuses = PciRegInfo->NoBuses; PciRegistryInfo->HardwareMechanism = PciRegInfo->HardwareMechanism; PciRegistryInfo->ElementCount = ElementCount; /* Return it */ return PciRegistryInfo; #else return NULL; #endif }
static void find_reg_tz_info(RTL_TIME_ZONE_INFORMATION *tzi) { static const WCHAR Time_ZonesW[] = { 'M','a','c','h','i','n','e','\\', 'S','o','f','t','w','a','r','e','\\', 'M','i','c','r','o','s','o','f','t','\\', 'W','i','n','d','o','w','s',' ','N','T','\\', 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', 'T','i','m','e',' ','Z','o','n','e','s',0 }; HANDLE hkey; ULONG idx; OBJECT_ATTRIBUTES attr; UNICODE_STRING nameW; WCHAR buf[128]; attr.Length = sizeof(attr); attr.RootDirectory = 0; attr.ObjectName = &nameW; attr.Attributes = 0; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; RtlInitUnicodeString(&nameW, Time_ZonesW); if (NtOpenKey(&hkey, KEY_READ, &attr)) { WARN("Unable to open the time zones key\n"); return; } idx = 0; nameW.Buffer = buf; nameW.Length = sizeof(buf); nameW.MaximumLength = sizeof(buf); while (!RtlpNtEnumerateSubKey(hkey, &nameW, idx++)) { static const WCHAR stdW[] = { 'S','t','d',0 }; static const WCHAR dltW[] = { 'D','l','t',0 }; static const WCHAR tziW[] = { 'T','Z','I',0 }; RTL_TIME_ZONE_INFORMATION reg_tzi; HANDLE hSubkey; struct tz_reg_data { LONG bias; LONG std_bias; LONG dlt_bias; RTL_SYSTEM_TIME std_date; RTL_SYSTEM_TIME dlt_date; } tz_data; attr.Length = sizeof(attr); attr.RootDirectory = hkey; attr.ObjectName = &nameW; attr.Attributes = 0; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; if (NtOpenKey(&hSubkey, KEY_READ, &attr)) { WARN("Unable to open subkey %s\n", debugstr_wn(nameW.Buffer, nameW.Length/sizeof(WCHAR))); continue; } #define get_value(hkey, name, type, data, len) \ if (!reg_query_value(hkey, name, type, data, len)) \ { \ WARN("can't read data from %s\n", debugstr_w(name)); \ NtClose(hkey); \ continue; \ } get_value(hSubkey, stdW, REG_SZ, reg_tzi.StandardName, sizeof(reg_tzi.StandardName)); get_value(hSubkey, dltW, REG_SZ, reg_tzi.DaylightName, sizeof(reg_tzi.DaylightName)); get_value(hSubkey, tziW, REG_BINARY, &tz_data, sizeof(tz_data)); #undef get_value reg_tzi.Bias = tz_data.bias; reg_tzi.StandardBias = tz_data.std_bias; reg_tzi.DaylightBias = tz_data.dlt_bias; reg_tzi.StandardDate = tz_data.std_date; reg_tzi.DaylightDate = tz_data.dlt_date; TRACE("%s: bias %d\n", debugstr_wn(nameW.Buffer, nameW.Length/sizeof(WCHAR)), reg_tzi.Bias); TRACE("std (d/m/y): %u/%02u/%04u day of week %u %u:%02u:%02u.%03u bias %d\n", reg_tzi.StandardDate.wDay, reg_tzi.StandardDate.wMonth, reg_tzi.StandardDate.wYear, reg_tzi.StandardDate.wDayOfWeek, reg_tzi.StandardDate.wHour, reg_tzi.StandardDate.wMinute, reg_tzi.StandardDate.wSecond, reg_tzi.StandardDate.wMilliseconds, reg_tzi.StandardBias); TRACE("dst (d/m/y): %u/%02u/%04u day of week %u %u:%02u:%02u.%03u bias %d\n", reg_tzi.DaylightDate.wDay, reg_tzi.DaylightDate.wMonth, reg_tzi.DaylightDate.wYear, reg_tzi.DaylightDate.wDayOfWeek, reg_tzi.DaylightDate.wHour, reg_tzi.DaylightDate.wMinute, reg_tzi.DaylightDate.wSecond, reg_tzi.DaylightDate.wMilliseconds, reg_tzi.DaylightBias); NtClose(hSubkey); if (match_tz_info(tzi, ®_tzi)) { *tzi = reg_tzi; NtClose(hkey); return; } /* reset len */ nameW.Length = sizeof(buf); nameW.MaximumLength = sizeof(buf); } NtClose(hkey); FIXME("Can't find matching timezone information in the registry for " "bias %d, std (d/m/y): %u/%02u/%04u, dlt (d/m/y): %u/%02u/%04u\n", tzi->Bias, tzi->StandardDate.wDay, tzi->StandardDate.wMonth, tzi->StandardDate.wYear, tzi->DaylightDate.wDay, tzi->DaylightDate.wMonth, tzi->DaylightDate.wYear); }
NET_API_STATUS NetpRdrFsControlTree( IN LPTSTR TreeName, IN LPTSTR TransportName OPTIONAL, IN DWORD ConnectionType, IN DWORD FsControlCode, IN LPVOID SecurityDescriptor OPTIONAL, IN LPVOID InputBuffer OPTIONAL, IN DWORD InputBufferSize, OUT LPVOID OutputBuffer OPTIONAL, IN DWORD OutputBufferSize, IN BOOL NoPermissionRequired ) /*++ Routine Description: NetpRdrFsControlTree performs a given FSCTL (file system control) on a given tree connection name. Arguments: TreeName - Remote name to do fsctl to (in \\server\share format). FsControlCode - function code to pass to the redirector. These are defined in <ntddnfs.h>. SecurityDescriptor - optionally points to a security descriptor to be used when creating the tree connection. InputBuffer - optionally points to a structure to be passed to the redirector. InputBufferSize - size of InputBuffer in bytes; must be zero if InputBuffer is a NULL pointer. OutputBuffer - optionally points to a structure to be filled in by the redirector. OutputBufferSize - size of OutputBuffer in bytes; must be zero if OutputBuffer is a NULL pointer. NoPermissionRequired - TRUE if this is a no permission required API. (I.e. TRUE if the null session may be used.) Return Value: NET_API_STATUS --*/ { NET_API_STATUS ApiStatus; IO_STATUS_BLOCK iosb; NTSTATUS ntstatus; // Status from NT operations. OBJECT_ATTRIBUTES objattrTreeConn; // Attrs for tree conn. LPTSTR pszTreeConn; // See strTreeConn below. #ifndef UNICODE STRING strTreeConn; // \Device\LanManRedir\server\share #endif UNICODE_STRING ucTreeConn; HANDLE TreeConnHandle; PFILE_FULL_EA_INFORMATION EaBuffer = NULL; PFILE_FULL_EA_INFORMATION Ea; USHORT TransportNameSize = 0; ULONG EaBufferSize = 0; PWSTR UnicodeTransportName = NULL; UCHAR EaNameDomainNameSize = (UCHAR) (ROUND_UP_COUNT( strlen(EA_NAME_DOMAIN) + sizeof(CHAR), ALIGN_WCHAR ) - sizeof(CHAR)); UCHAR EaNamePasswordSize = (UCHAR) (ROUND_UP_COUNT( strlen(EA_NAME_PASSWORD) + sizeof(CHAR), ALIGN_WCHAR ) - sizeof(CHAR)); UCHAR EaNameTransportNameSize = (UCHAR) (ROUND_UP_COUNT( strlen(EA_NAME_TRANSPORT) + sizeof(CHAR), ALIGN_WCHAR ) - sizeof(CHAR)); UCHAR EaNameTypeSize = (UCHAR) (ROUND_UP_COUNT( strlen(EA_NAME_TYPE) + sizeof(CHAR), ALIGN_DWORD ) - sizeof(CHAR)); UCHAR EaNameUserNameSize = (UCHAR) (ROUND_UP_COUNT( strlen(EA_NAME_USERNAME) + sizeof(CHAR), ALIGN_WCHAR ) - sizeof(CHAR)); USHORT TypeSize = sizeof(ULONG); IF_DEBUG(RDRFSCTL) { NetpKdPrint(( PREFIX_NETLIB "NetpRdrFsControlTree: entered, TreeName='" FORMAT_LPTSTR "', " FORMAT_LPTSTR " session.\n", TreeName, NoPermissionRequired ? TEXT("null") : TEXT("non-null") )); } if ((TreeName == NULL) || (TreeName[0] == 0)) { return (ERROR_INVALID_PARAMETER); } if (! NetpIsRemoteNameValid(TreeName)) { return (ERROR_INVALID_PARAMETER); } // // Build NT-style name for what we're connecting to. Note that there is // NOT a pair of backslashes anywhere in this name. // { DWORD NameSize = // /Device/LanManRedirector / server/share \0 #ifdef UNICODE ( ( STRLEN((LPTSTR)DD_NFS_DEVICE_NAME_U) + 1 + STRLEN(TreeName) + 1 ) ) #else ( ( STRLEN((LPTSTR)DD_NFS_DEVICE_NAME) + 1 + STRLEN(TreeName) + 1 ) ) #endif * sizeof(TCHAR); pszTreeConn = (LPTSTR)NetpMemoryAllocate( NameSize ); } if (pszTreeConn == NULL) { return (ERROR_NOT_ENOUGH_MEMORY); } // // Build the tree connect name. // #ifdef UNICODE (void) STRCPY(pszTreeConn, (LPTSTR) DD_NFS_DEVICE_NAME_U); #else (void) STRCPY(pszTreeConn, (LPTSTR) DD_NFS_DEVICE_NAME); #endif // // NOTE: We add 1, (not sizeof(TCHAR)) because pointer arithmetic is done // in terms of multiples of sizeof(*pointer), not bytes // (void) STRCAT(pszTreeConn, TreeName+1); // \server\share #ifdef UNICODE RtlInitUnicodeString(&ucTreeConn, pszTreeConn); #else RtlInitString( & strTreeConn, pszTreeConn); (void) RtlOemStringToUnicodeString(&ucTreeConn, &strTreeConn, TRUE); #endif IF_DEBUG(RDRFSCTL) { NetpKdPrint(( PREFIX_NETLIB "NetpRdrFsControlTree: UNICODE name is " FORMAT_LPWSTR ".\n", ucTreeConn.Buffer )); } // // Calculate the number of bytes needed for the EA buffer. // This may have the transport name. For regular sessions, the user // name, password, and domain name are implicit. For null sessions, we // must give 0-len user name, 0-len password, and 0-len domain name. // if (ARGUMENT_PRESENT(TransportName)) { ASSERT(ConnectionType == USE_IPC); #ifdef UNICODE UnicodeTransportName = TransportName; #else UnicodeTransportName = NetpAllocWStrFromStr(TransportName); if (UnicodeTransportName == NULL) { NetpMemoryFree(pszTreeConn); return ERROR_NOT_ENOUGH_MEMORY; } #endif TransportNameSize = (USHORT) (wcslen(UnicodeTransportName) * sizeof(WCHAR)); EaBufferSize += ROUND_UP_COUNT( FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) + EaNameTransportNameSize + sizeof(CHAR) + TransportNameSize, ALIGN_DWORD ); } if (NoPermissionRequired) { // Domain name (0-len). EaBufferSize += ROUND_UP_COUNT( FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) + EaNameDomainNameSize + sizeof(CHAR), ALIGN_DWORD ); // Password (0-len). EaBufferSize += ROUND_UP_COUNT( FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) + EaNamePasswordSize + sizeof(CHAR), ALIGN_DWORD ); // User name (0-len). EaBufferSize += ROUND_UP_COUNT( FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) + EaNameUserNameSize + sizeof(CHAR), ALIGN_DWORD ); } EaBufferSize += ((ULONG)FIELD_OFFSET( FILE_FULL_EA_INFORMATION, EaName[0]))+ EaNameTypeSize + sizeof(CHAR) + TypeSize; // // Allocate the EA buffer // if ((EaBuffer = NetpMemoryAllocate( EaBufferSize )) == NULL) { NetpMemoryFree(pszTreeConn); #ifndef UNICODE if (UnicodeTransportName != NULL) { NetpMemoryFree(UnicodeTransportName); } #endif return ERROR_NOT_ENOUGH_MEMORY; } // // Fill-in the EA buffer. // RtlZeroMemory(EaBuffer, EaBufferSize); Ea = EaBuffer; if (ARGUMENT_PRESENT(TransportName)) { // // Copy the EA name into EA buffer. EA name length does not // include the zero terminator. // strcpy(Ea->EaName, EA_NAME_TRANSPORT); Ea->EaNameLength = EaNameTransportNameSize; // // Copy the EA value into EA buffer. EA value length does not // include the zero terminator. // (VOID) wcscpy( (LPWSTR) &(Ea->EaName[EaNameTransportNameSize + sizeof(CHAR)]), UnicodeTransportName ); Ea->EaValueLength = TransportNameSize; Ea->NextEntryOffset = ROUND_UP_COUNT( FIELD_OFFSET( FILE_FULL_EA_INFORMATION, EaName[0]) + EaNameTransportNameSize + sizeof(CHAR) + TransportNameSize, ALIGN_DWORD ); Ea->Flags = 0; (ULONG) Ea += Ea->NextEntryOffset; } if (NoPermissionRequired) { // // *** DOMAIN NAME *** // Copy the EA name into EA buffer. EA name length does not // include the zero terminator. // (VOID) strcpy(Ea->EaName, EA_NAME_DOMAIN); Ea->EaNameLength = EaNameDomainNameSize; Ea->EaValueLength = 0; // There is no EA value for this. Ea->NextEntryOffset = ROUND_UP_COUNT( FIELD_OFFSET( FILE_FULL_EA_INFORMATION, EaName[0]) + EaNameDomainNameSize + sizeof(CHAR), ALIGN_DWORD ); Ea->Flags = 0; (ULONG) Ea += Ea->NextEntryOffset; // // *** PASSWORD *** // Copy the EA name into EA buffer. EA name length does not // include the zero terminator. // (VOID) strcpy(Ea->EaName, EA_NAME_PASSWORD); Ea->EaNameLength = EaNamePasswordSize; Ea->EaValueLength = 0; // There is no EA value for this. Ea->NextEntryOffset = ROUND_UP_COUNT( FIELD_OFFSET( FILE_FULL_EA_INFORMATION, EaName[0]) + EaNamePasswordSize + sizeof(CHAR), ALIGN_DWORD ); Ea->Flags = 0; (ULONG) Ea += Ea->NextEntryOffset; // // *** USER NAME *** // Copy the EA name into EA buffer. EA name length does not // include the zero terminator. // (VOID) strcpy(Ea->EaName, EA_NAME_USERNAME); Ea->EaNameLength = EaNameUserNameSize; Ea->EaValueLength = 0; // There is no EA value for this. Ea->NextEntryOffset = ROUND_UP_COUNT( FIELD_OFFSET( FILE_FULL_EA_INFORMATION, EaName[0]) + EaNameUserNameSize + sizeof(CHAR), ALIGN_DWORD ); Ea->Flags = 0; (ULONG) Ea += Ea->NextEntryOffset; } // // Copy the EA for the connection type name into EA buffer. EA name length // does not include the zero terminator. // strcpy(Ea->EaName, EA_NAME_TYPE); Ea->EaNameLength = EaNameTypeSize; *((PULONG) &(Ea->EaName[EaNameTypeSize + sizeof(CHAR)])) = ConnectionType; Ea->EaValueLength = TypeSize; Ea->NextEntryOffset = 0; Ea->Flags = 0; // Set object attributes for the tree conn. InitializeObjectAttributes( & objattrTreeConn, // obj attr to init (LPVOID) & ucTreeConn, // string to use OBJ_CASE_INSENSITIVE, // Attributes NULL, // Root directory SecurityDescriptor); // Security Descriptor // // Open a tree connection to the remote server. // IF_DEBUG(RDRFSCTL) { NetpKdPrint(( PREFIX_NETLIB "NetpRdrFsControlTree: opening " FORMAT_LPTSTR ".\n", pszTreeConn )); } ntstatus = NtCreateFile( & TreeConnHandle, // ptr to handle SYNCHRONIZE // desired... | GENERIC_READ | GENERIC_WRITE, // ...access & objattrTreeConn, // name & attributes & iosb, // I/O status block. NULL, // alloc size. FILE_ATTRIBUTE_NORMAL, // (ignored) FILE_SHARE_READ | FILE_SHARE_WRITE, // ...access FILE_OPEN_IF, // create disposition FILE_CREATE_TREE_CONNECTION // create... | FILE_SYNCHRONOUS_IO_NONALERT, // ...options EaBuffer, // EA buffer EaBufferSize ); // Ea buffer size #ifndef UNICODE RtlFreeUnicodeString( &ucTreeConn ); #endif if (! NT_SUCCESS(ntstatus)) { #ifndef UNICODE if (UnicodeTransportName != NULL) { NetpMemoryFree(UnicodeTransportName); } #endif if (EaBuffer != NULL) { NetpMemoryFree(EaBuffer); } NetpMemoryFree(pszTreeConn); ApiStatus = NetpNtStatusToApiStatus(ntstatus); if (ApiStatus == ERROR_BAD_NET_NAME) { ApiStatus = NERR_BadTransactConfig; // Special meaning if no IPC$ } if (ApiStatus != ERROR_BAD_NETPATH) { NetpKdPrint(( PREFIX_NETLIB "NetpRdrFsControlTree: unexpected create error,\n" " tree name='" FORMAT_LPTSTR "', " "ntstatus=" FORMAT_NTSTATUS ",\n" " iosb.Status=" FORMAT_NTSTATUS ", " "iosb.Info=" FORMAT_HEX_ULONG ", " " returning " FORMAT_API_STATUS ".\n", TreeName, ntstatus, iosb.Status, iosb.Information, ApiStatus )); } return (ApiStatus); } // Do the FSCTL. IF_DEBUG(RDRFSCTL) { NetpKdPrint(( PREFIX_NETLIB "NetpRdrFsControlTree: doing fsctl...\n" )); } ntstatus = NtFsControlFile( TreeConnHandle, // handle NULL, // no event NULL, // no APC routine NULL, // no APC context & iosb, // I/O stat blk (set) FsControlCode, // func code InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize); if (! NT_SUCCESS(ntstatus)) { NTSTATUS Status; Status = NtClose(TreeConnHandle); #if DBG if (!NT_SUCCESS(Status)) { NetpKdPrint(( PREFIX_NETLIB "NetpRdrFsControlTree: " "Unexpected error closing tree connect handle: " FORMAT_NTSTATUS "\n", Status )); } #endif NetpMemoryFree(pszTreeConn); #ifndef UNICODE if (UnicodeTransportName != NULL) { NetpMemoryFree(UnicodeTransportName); } #endif if (EaBuffer != NULL) { NetpMemoryFree(EaBuffer); } ApiStatus = NetpNtStatusToApiStatus(ntstatus); NetpKdPrint(( PREFIX_NETLIB "NetpRdrFsControlTree: unexpected FSCTL error,\n" " tree name='" FORMAT_LPTSTR "', " "ntstatus=" FORMAT_NTSTATUS ".\n" " ApiStatus=" FORMAT_API_STATUS ", " "iosb.Status=" FORMAT_NTSTATUS ", " "iosb.Info=" FORMAT_HEX_ULONG ".\n", TreeName, ntstatus, ApiStatus, iosb.Status, iosb.Information )); return (ApiStatus); } // Clean up. ntstatus = NtClose(TreeConnHandle); #if DBG if (!NT_SUCCESS(ntstatus)) { NetpKdPrint(( PREFIX_NETLIB "NetpRdrFsControlTree: " "Unexpected error closing tree connect handle: " FORMAT_NTSTATUS "\n", ntstatus )); } #endif NetpMemoryFree(pszTreeConn); #ifndef UNICODE if (UnicodeTransportName != NULL) { NetpMemoryFree(UnicodeTransportName); } #endif if (EaBuffer != NULL) { NetpMemoryFree(EaBuffer); } return (NERR_Success); } // NetpRdrFsControlTree
NTSTATUS GSTOpenVolume (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, MOUNT_STRUCT *mount, PWSTR pwszMountVolume, BOOL bRawDevice) { FILE_STANDARD_INFORMATION FileStandardInfo; FILE_BASIC_INFORMATION FileBasicInfo; OBJECT_ATTRIBUTES oaFileAttributes; UNICODE_STRING FullFileName; IO_STATUS_BLOCK IoStatusBlock; PCRYPTO_INFO cryptoInfoPtr = NULL; PCRYPTO_INFO tmpCryptoInfo = NULL; LARGE_INTEGER lDiskLength; __int64 partitionStartingOffset = 0; int volumeType; char *readBuffer = 0; NTSTATUS ntStatus = 0; BOOL forceAccessCheck = (!bRawDevice && !(OsMajorVersion == 5 &&OsMinorVersion == 0)); // Windows 2000 does not support OBJ_FORCE_ACCESS_CHECK attribute BOOL disableBuffering = TRUE; BOOL exclusiveAccess = mount->bExclusiveAccess; Extension->pfoDeviceFile = NULL; Extension->hDeviceFile = NULL; Extension->bTimeStampValid = FALSE; RtlInitUnicodeString (&FullFileName, pwszMountVolume); InitializeObjectAttributes (&oaFileAttributes, &FullFileName, OBJ_CASE_INSENSITIVE | (forceAccessCheck ? OBJ_FORCE_ACCESS_CHECK : 0) | OBJ_KERNEL_HANDLE, NULL, NULL); KeInitializeEvent (&Extension->keVolumeEvent, NotificationEvent, FALSE); if (Extension->SecurityClientContextValid) { ntStatus = SeImpersonateClientEx (&Extension->SecurityClientContext, NULL); if (!NT_SUCCESS (ntStatus)) goto error; } mount->VolumeMountedReadOnlyAfterDeviceWriteProtected = FALSE; // If we are opening a device, query its size first if (bRawDevice) { PARTITION_INFORMATION pi; PARTITION_INFORMATION_EX pix; LARGE_INTEGER diskLengthInfo; DISK_GEOMETRY dg; ntStatus = IoGetDeviceObjectPointer (&FullFileName, FILE_READ_DATA | FILE_READ_ATTRIBUTES, &Extension->pfoDeviceFile, &Extension->pFsdDevice); if (!NT_SUCCESS (ntStatus)) goto error; ntStatus = GSTSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_DRIVE_GEOMETRY, (char *) &dg, sizeof (dg)); if (!NT_SUCCESS (ntStatus)) goto error; lDiskLength.QuadPart = dg.Cylinders.QuadPart * dg.SectorsPerTrack * dg.TracksPerCylinder * dg.BytesPerSector; Extension->HostBytesPerSector = dg.BytesPerSector; // Drive geometry is used only when IOCTL_DISK_GET_PARTITION_INFO fails if (NT_SUCCESS (GSTSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_PARTITION_INFO_EX, (char *) &pix, sizeof (pix)))) { lDiskLength.QuadPart = pix.PartitionLength.QuadPart; partitionStartingOffset = pix.StartingOffset.QuadPart; } // Windows 2000 does not support IOCTL_DISK_GET_PARTITION_INFO_EX else if (NT_SUCCESS (GSTSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_PARTITION_INFO, (char *) &pi, sizeof (pi)))) { lDiskLength.QuadPart = pi.PartitionLength.QuadPart; partitionStartingOffset = pi.StartingOffset.QuadPart; } else if (NT_SUCCESS (GSTSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_LENGTH_INFO, &diskLengthInfo, sizeof (diskLengthInfo)))) { lDiskLength = diskLengthInfo; } ProbingHostDeviceForWrite = TRUE; if (!mount->bMountReadOnly && GSTSendHostDeviceIoControlRequest (DeviceObject, Extension, IsHiddenSystemRunning() ? GST_IOCTL_DISK_IS_WRITABLE : IOCTL_DISK_IS_WRITABLE, NULL, 0) == STATUS_MEDIA_WRITE_PROTECTED) { mount->bMountReadOnly = TRUE; DeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE; mount->VolumeMountedReadOnlyAfterDeviceWriteProtected = TRUE; } ProbingHostDeviceForWrite = FALSE; // Some Windows tools (e.g. diskmgmt, diskpart, vssadmin) fail or experience timeouts when there is a raw device // open for exclusive access. Therefore, exclusive access is used only for file-hosted volumes. // Applications requiring a consistent device image need to acquire exclusive write access first. This is prevented // when a device-hosted volume is mounted. exclusiveAccess = FALSE; } else { // Limit the maximum required buffer size if (mount->BytesPerSector > 128 * BYTES_PER_KB) { ntStatus = STATUS_INVALID_PARAMETER; goto error; } Extension->HostBytesPerSector = mount->BytesPerSector; if (Extension->HostBytesPerSector != GST_SECTOR_SIZE_FILE_HOSTED_VOLUME) disableBuffering = FALSE; } // Open the volume hosting file/device if (!mount->bMountReadOnly) { ntStatus = ZwCreateFile (&Extension->hDeviceFile, GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, &oaFileAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_SYSTEM, exclusiveAccess ? 0 : FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_RANDOM_ACCESS | FILE_WRITE_THROUGH | (disableBuffering ? FILE_NO_INTERMEDIATE_BUFFERING : 0) | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); } /* 26-4-99 NT for some partitions returns this code, it is really a access denied */ if (ntStatus == 0xc000001b) ntStatus = STATUS_ACCESS_DENIED; mount->VolumeMountedReadOnlyAfterAccessDenied = FALSE; if (mount->bMountReadOnly || ntStatus == STATUS_ACCESS_DENIED) { ntStatus = ZwCreateFile (&Extension->hDeviceFile, GENERIC_READ | SYNCHRONIZE, &oaFileAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_SYSTEM, exclusiveAccess ? FILE_SHARE_READ : FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_RANDOM_ACCESS | FILE_WRITE_THROUGH | (disableBuffering ? FILE_NO_INTERMEDIATE_BUFFERING : 0) | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (NT_SUCCESS (ntStatus) && !mount->bMountReadOnly) mount->VolumeMountedReadOnlyAfterAccessDenied = TRUE; Extension->bReadOnly = TRUE; DeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE; } else Extension->bReadOnly = FALSE; /* 26-4-99 NT for some partitions returns this code, it is really a access denied */ if (ntStatus == 0xc000001b) { /* Partitions which return this code can still be opened with FILE_SHARE_READ but this causes NT problems elsewhere in particular if you do FILE_SHARE_READ NT will die later if anyone even tries to open the partition (or file for that matter...) */ ntStatus = STATUS_SHARING_VIOLATION; } if (!NT_SUCCESS (ntStatus)) { goto error; } // If we have opened a file, query its size now if (bRawDevice == FALSE) { ntStatus = ZwQueryInformationFile (Extension->hDeviceFile, &IoStatusBlock, &FileBasicInfo, sizeof (FileBasicInfo), FileBasicInformation); if (NT_SUCCESS (ntStatus)) { if (mount->bPreserveTimestamp) { Extension->fileCreationTime = FileBasicInfo.CreationTime; Extension->fileLastAccessTime = FileBasicInfo.LastAccessTime; Extension->fileLastWriteTime = FileBasicInfo.LastWriteTime; Extension->fileLastChangeTime = FileBasicInfo.ChangeTime; Extension->bTimeStampValid = TRUE; } ntStatus = ZwQueryInformationFile (Extension->hDeviceFile, &IoStatusBlock, &FileStandardInfo, sizeof (FileStandardInfo), FileStandardInformation); } if (!NT_SUCCESS (ntStatus)) { Dump ("ZwQueryInformationFile failed while opening file: NTSTATUS 0x%08x\n", ntStatus); goto error; } lDiskLength.QuadPart = FileStandardInfo.EndOfFile.QuadPart; if (FileBasicInfo.FileAttributes & FILE_ATTRIBUTE_COMPRESSED) { Dump ("File \"%ls\" is marked as compressed - not supported!\n", pwszMountVolume); mount->nReturnCode = ERR_COMPRESSION_NOT_SUPPORTED; ntStatus = STATUS_SUCCESS; goto error; } ntStatus = ObReferenceObjectByHandle (Extension->hDeviceFile, FILE_ALL_ACCESS, *IoFileObjectType, KernelMode, &Extension->pfoDeviceFile, 0); if (!NT_SUCCESS (ntStatus)) { goto error; } /* Get the FSD device for the file (probably either NTFS or FAT) */ Extension->pFsdDevice = IoGetRelatedDeviceObject (Extension->pfoDeviceFile); } else { // Try to gain "raw" access to the partition in case there is a live filesystem on it (otherwise, // the NTFS driver guards hidden sectors and prevents mounting using a backup header e.g. after the user // accidentally quick-formats a dismounted partition-hosted GostCrypt volume as NTFS). PFILE_OBJECT pfoTmpDeviceFile = NULL; if (NT_SUCCESS (ObReferenceObjectByHandle (Extension->hDeviceFile, FILE_ALL_ACCESS, *IoFileObjectType, KernelMode, &pfoTmpDeviceFile, NULL)) && pfoTmpDeviceFile != NULL) { GSTFsctlCall (pfoTmpDeviceFile, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0); ObDereferenceObject (pfoTmpDeviceFile); } } // Check volume size if (lDiskLength.QuadPart < GST_MIN_VOLUME_SIZE_LEGACY || lDiskLength.QuadPart > GST_MAX_VOLUME_SIZE) { mount->nReturnCode = ERR_VOL_SIZE_WRONG; ntStatus = STATUS_SUCCESS; goto error; } Extension->DiskLength = lDiskLength.QuadPart; Extension->HostLength = lDiskLength.QuadPart; readBuffer = GSTalloc (max (max (GST_VOLUME_HEADER_EFFECTIVE_SIZE, PAGE_SIZE), Extension->HostBytesPerSector)); if (readBuffer == NULL) { ntStatus = STATUS_INSUFFICIENT_RESOURCES; goto error; } // Go through all volume types (e.g., normal, hidden) for (volumeType = GST_VOLUME_TYPE_NORMAL; volumeType < GST_VOLUME_TYPE_COUNT; volumeType++) { Dump ("Trying to open volume type %d\n", volumeType); if (mount->bPartitionInInactiveSysEncScope && volumeType == GST_VOLUME_TYPE_HIDDEN_LEGACY) continue; /* Read the volume header */ if (!mount->bPartitionInInactiveSysEncScope || (mount->bPartitionInInactiveSysEncScope && volumeType == GST_VOLUME_TYPE_HIDDEN)) { // Header of a volume that is not within the scope of system encryption, or // header of a system hidden volume (containing a hidden OS) LARGE_INTEGER headerOffset; if (mount->UseBackupHeader && lDiskLength.QuadPart <= GST_TOTAL_VOLUME_HEADERS_SIZE) continue; switch (volumeType) { case GST_VOLUME_TYPE_NORMAL: headerOffset.QuadPart = mount->UseBackupHeader ? lDiskLength.QuadPart - GST_VOLUME_HEADER_GROUP_SIZE : GST_VOLUME_HEADER_OFFSET; break; case GST_VOLUME_TYPE_HIDDEN: if (lDiskLength.QuadPart <= GST_VOLUME_HEADER_GROUP_SIZE) continue; headerOffset.QuadPart = mount->UseBackupHeader ? lDiskLength.QuadPart - GST_HIDDEN_VOLUME_HEADER_OFFSET : GST_HIDDEN_VOLUME_HEADER_OFFSET; break; case GST_VOLUME_TYPE_HIDDEN_LEGACY: if (mount->UseBackupHeader) continue; if (bRawDevice && Extension->HostBytesPerSector != GST_SECTOR_SIZE_LEGACY) continue; headerOffset.QuadPart = lDiskLength.QuadPart - GST_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY; break; } Dump ("Reading volume header at %I64d\n", headerOffset.QuadPart); ntStatus = ZwReadFile (Extension->hDeviceFile, NULL, NULL, NULL, &IoStatusBlock, readBuffer, bRawDevice ? max (GST_VOLUME_HEADER_EFFECTIVE_SIZE, Extension->HostBytesPerSector) : GST_VOLUME_HEADER_EFFECTIVE_SIZE, &headerOffset, NULL); } else { // Header of a partition that is within the scope of system encryption WCHAR parentDrivePath [47+1] = {0}; HANDLE hParentDeviceFile = NULL; UNICODE_STRING FullParentPath; OBJECT_ATTRIBUTES oaParentFileAttributes; LARGE_INTEGER parentKeyDataOffset; _snwprintf (parentDrivePath, sizeof (parentDrivePath) / sizeof (WCHAR) - 1, WIDE ("\\Device\\Harddisk%d\\Partition0"), mount->nPartitionInInactiveSysEncScopeDriveNo); Dump ("Mounting partition within scope of system encryption (reading key data from: %ls)\n", parentDrivePath); RtlInitUnicodeString (&FullParentPath, parentDrivePath); InitializeObjectAttributes (&oaParentFileAttributes, &FullParentPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); ntStatus = ZwCreateFile (&hParentDeviceFile, GENERIC_READ | SYNCHRONIZE, &oaParentFileAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_SYSTEM, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_RANDOM_ACCESS | FILE_WRITE_THROUGH | FILE_NO_INTERMEDIATE_BUFFERING | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (!NT_SUCCESS (ntStatus)) { if (hParentDeviceFile != NULL) ZwClose (hParentDeviceFile); Dump ("Cannot open %ls\n", parentDrivePath); goto error; } parentKeyDataOffset.QuadPart = GST_BOOT_VOLUME_HEADER_SECTOR_OFFSET; ntStatus = ZwReadFile (hParentDeviceFile, NULL, NULL, NULL, &IoStatusBlock, readBuffer, max (GST_VOLUME_HEADER_EFFECTIVE_SIZE, Extension->HostBytesPerSector), &parentKeyDataOffset, NULL); if (hParentDeviceFile != NULL) ZwClose (hParentDeviceFile); } if (!NT_SUCCESS (ntStatus) && ntStatus != STATUS_END_OF_FILE) { Dump ("Read failed: NTSTATUS 0x%08x\n", ntStatus); goto error; } if (ntStatus == STATUS_END_OF_FILE || IoStatusBlock.Information < GST_VOLUME_HEADER_EFFECTIVE_SIZE) { Dump ("Read didn't read enough data\n"); // If FSCTL_ALLOW_EXTENDED_DASD_IO failed and there is a live filesystem on the partition, then the // filesystem driver may report EOF when we are reading hidden sectors (when the filesystem is // shorter than the partition). This can happen for example after the user quick-formats a dismounted // partition-hosted GostCrypt volume and then tries to mount the volume using the embedded backup header. memset (readBuffer, 0, GST_VOLUME_HEADER_EFFECTIVE_SIZE); } /* Attempt to recognize the volume (decrypt the header) */ ReadVolumeHeaderRecoveryMode = mount->RecoveryMode; if ((volumeType == GST_VOLUME_TYPE_HIDDEN || volumeType == GST_VOLUME_TYPE_HIDDEN_LEGACY) && mount->bProtectHiddenVolume) { mount->nReturnCode = ReadVolumeHeaderWCache ( FALSE, mount->bCache, readBuffer, &mount->ProtectedHidVolPassword, &tmpCryptoInfo); } else { mount->nReturnCode = ReadVolumeHeaderWCache ( mount->bPartitionInInactiveSysEncScope && volumeType == GST_VOLUME_TYPE_NORMAL, mount->bCache, readBuffer, &mount->VolumePassword, &Extension->cryptoInfo); } ReadVolumeHeaderRecoveryMode = FALSE; if (mount->nReturnCode == 0 || mount->nReturnCode == ERR_CIPHER_INIT_WEAK_KEY) { /* Volume header successfully decrypted */ Dump ("Volume header decrypted\n"); Dump ("Required program version = %x\n", (int) Extension->cryptoInfo->RequiredProgramVersion); Dump ("Legacy volume = %d\n", (int) Extension->cryptoInfo->LegacyVolume); if (IsHiddenSystemRunning() && !Extension->cryptoInfo->hiddenVolume) { Extension->bReadOnly = mount->bMountReadOnly = TRUE; HiddenSysLeakProtectionCount++; } Extension->cryptoInfo->bProtectHiddenVolume = FALSE; Extension->cryptoInfo->bHiddenVolProtectionAction = FALSE; Extension->cryptoInfo->bPartitionInInactiveSysEncScope = mount->bPartitionInInactiveSysEncScope; if (volumeType == GST_VOLUME_TYPE_NORMAL) { if (mount->bPartitionInInactiveSysEncScope) { if (Extension->cryptoInfo->EncryptedAreaStart.Value > (unsigned __int64) partitionStartingOffset || Extension->cryptoInfo->EncryptedAreaStart.Value + Extension->cryptoInfo->VolumeSize.Value <= (unsigned __int64) partitionStartingOffset) { // The partition is not within the key scope of system encryption mount->nReturnCode = ERR_PASSWORD_WRONG; ntStatus = STATUS_SUCCESS; goto error; } if (Extension->cryptoInfo->EncryptedAreaLength.Value != Extension->cryptoInfo->VolumeSize.Value) { // Partial encryption is not supported for volumes mounted as regular mount->nReturnCode = ERR_ENCRYPTION_NOT_COMPLETED; ntStatus = STATUS_SUCCESS; goto error; } } else if (Extension->cryptoInfo->HeaderFlags & GST_HEADER_FLAG_NONSYS_INPLACE_ENC) { if (Extension->cryptoInfo->EncryptedAreaLength.Value != Extension->cryptoInfo->VolumeSize.Value) { // Non-system in-place encryption process has not been completed on this volume mount->nReturnCode = ERR_NONSYS_INPLACE_ENC_INCOMPLETE; ntStatus = STATUS_SUCCESS; goto error; } } } Extension->cryptoInfo->FirstDataUnitNo.Value = 0; if (Extension->cryptoInfo->hiddenVolume && IsHiddenSystemRunning()) { // Prevent mount of a hidden system partition if the system hosted on it is currently running if (memcmp (Extension->cryptoInfo->master_keydata, GetSystemDriveCryptoInfo()->master_keydata, EAGetKeySize (Extension->cryptoInfo->ea)) == 0) { mount->nReturnCode = ERR_VOL_ALREADY_MOUNTED; ntStatus = STATUS_SUCCESS; goto error; } } switch (volumeType) { case GST_VOLUME_TYPE_NORMAL: Extension->cryptoInfo->hiddenVolume = FALSE; if (mount->bPartitionInInactiveSysEncScope) { Extension->cryptoInfo->volDataAreaOffset = 0; Extension->DiskLength = lDiskLength.QuadPart; Extension->cryptoInfo->FirstDataUnitNo.Value = partitionStartingOffset / ENCRYPTION_DATA_UNIT_SIZE; } else if (Extension->cryptoInfo->LegacyVolume) { Extension->cryptoInfo->volDataAreaOffset = GST_VOLUME_HEADER_SIZE_LEGACY; Extension->DiskLength = lDiskLength.QuadPart - GST_VOLUME_HEADER_SIZE_LEGACY; } else { Extension->cryptoInfo->volDataAreaOffset = Extension->cryptoInfo->EncryptedAreaStart.Value; Extension->DiskLength = Extension->cryptoInfo->VolumeSize.Value; } break; case GST_VOLUME_TYPE_HIDDEN: case GST_VOLUME_TYPE_HIDDEN_LEGACY: cryptoInfoPtr = mount->bProtectHiddenVolume ? tmpCryptoInfo : Extension->cryptoInfo; if (volumeType == GST_VOLUME_TYPE_HIDDEN_LEGACY) Extension->cryptoInfo->hiddenVolumeOffset = lDiskLength.QuadPart - cryptoInfoPtr->hiddenVolumeSize - GST_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY; else Extension->cryptoInfo->hiddenVolumeOffset = cryptoInfoPtr->EncryptedAreaStart.Value; Dump ("Hidden volume offset = %I64d\n", Extension->cryptoInfo->hiddenVolumeOffset); Dump ("Hidden volume size = %I64d\n", cryptoInfoPtr->hiddenVolumeSize); Dump ("Hidden volume end = %I64d\n", Extension->cryptoInfo->hiddenVolumeOffset + cryptoInfoPtr->hiddenVolumeSize - 1); // Validate the offset if (Extension->cryptoInfo->hiddenVolumeOffset % ENCRYPTION_DATA_UNIT_SIZE != 0) { mount->nReturnCode = ERR_VOL_SIZE_WRONG; ntStatus = STATUS_SUCCESS; goto error; } // If we are supposed to actually mount the hidden volume (not just to protect it) if (!mount->bProtectHiddenVolume) { Extension->DiskLength = cryptoInfoPtr->hiddenVolumeSize; Extension->cryptoInfo->hiddenVolume = TRUE; Extension->cryptoInfo->volDataAreaOffset = Extension->cryptoInfo->hiddenVolumeOffset; } else { // Hidden volume protection Extension->cryptoInfo->hiddenVolume = FALSE; Extension->cryptoInfo->bProtectHiddenVolume = TRUE; Extension->cryptoInfo->hiddenVolumeProtectedSize = tmpCryptoInfo->hiddenVolumeSize; if (volumeType == GST_VOLUME_TYPE_HIDDEN_LEGACY) Extension->cryptoInfo->hiddenVolumeProtectedSize += GST_VOLUME_HEADER_SIZE_LEGACY; Dump ("Hidden volume protection active: %I64d-%I64d (%I64d)\n", Extension->cryptoInfo->hiddenVolumeOffset, Extension->cryptoInfo->hiddenVolumeProtectedSize + Extension->cryptoInfo->hiddenVolumeOffset - 1, Extension->cryptoInfo->hiddenVolumeProtectedSize); } break; } Dump ("Volume data offset = %I64d\n", Extension->cryptoInfo->volDataAreaOffset); Dump ("Volume data size = %I64d\n", Extension->DiskLength); Dump ("Volume data end = %I64d\n", Extension->cryptoInfo->volDataAreaOffset + Extension->DiskLength - 1); if (Extension->DiskLength == 0) { Dump ("Incorrect volume size\n"); continue; } // If this is a hidden volume, make sure we are supposed to actually // mount it (i.e. not just to protect it) if (volumeType == GST_VOLUME_TYPE_NORMAL || !mount->bProtectHiddenVolume) { // Validate sector size if (bRawDevice && Extension->cryptoInfo->SectorSize != Extension->HostBytesPerSector) { mount->nReturnCode = ERR_PARAMETER_INCORRECT; ntStatus = STATUS_SUCCESS; goto error; } // Calculate virtual volume geometry Extension->TracksPerCylinder = 1; Extension->SectorsPerTrack = 1; Extension->BytesPerSector = Extension->cryptoInfo->SectorSize; Extension->NumberOfCylinders = Extension->DiskLength / Extension->BytesPerSector; Extension->PartitionType = 0; Extension->bRawDevice = bRawDevice; memset (Extension->wszVolume, 0, sizeof (Extension->wszVolume)); if (wcsstr (pwszMountVolume, WIDE ("\\??\\UNC\\")) == pwszMountVolume) { /* UNC path */ _snwprintf (Extension->wszVolume, sizeof (Extension->wszVolume) / sizeof (WCHAR) - 1, WIDE ("\\??\\\\%s"), pwszMountVolume + 7); } else { wcsncpy (Extension->wszVolume, pwszMountVolume, sizeof (Extension->wszVolume) / sizeof (WCHAR) - 1); } } // If we are to protect a hidden volume we cannot exit yet, for we must also // decrypt the hidden volume header. if (!(volumeType == GST_VOLUME_TYPE_NORMAL && mount->bProtectHiddenVolume)) { GSTfree (readBuffer); if (tmpCryptoInfo != NULL) { crypto_close (tmpCryptoInfo); tmpCryptoInfo = NULL; } return STATUS_SUCCESS; } } else if ((mount->bProtectHiddenVolume && volumeType == GST_VOLUME_TYPE_NORMAL) || mount->nReturnCode != ERR_PASSWORD_WRONG) { /* If we are not supposed to protect a hidden volume, the only error that is tolerated is ERR_PASSWORD_WRONG (to allow mounting a possible hidden volume). If we _are_ supposed to protect a hidden volume, we do not tolerate any error (both volume headers must be successfully decrypted). */ break; } } /* Failed due to some non-OS reason so we drop through and return NT SUCCESS then nReturnCode is checked later in user-mode */ if (mount->nReturnCode == ERR_OUTOFMEMORY) ntStatus = STATUS_INSUFFICIENT_RESOURCES; else ntStatus = STATUS_SUCCESS; error: if (mount->nReturnCode == ERR_SUCCESS) mount->nReturnCode = ERR_PASSWORD_WRONG; if (tmpCryptoInfo != NULL) { crypto_close (tmpCryptoInfo); tmpCryptoInfo = NULL; } if (Extension->cryptoInfo) { crypto_close (Extension->cryptoInfo); Extension->cryptoInfo = NULL; } if (Extension->bTimeStampValid) { RestoreTimeStamp (Extension); } /* Close the hDeviceFile */ if (Extension->hDeviceFile != NULL) ZwClose (Extension->hDeviceFile); /* The cryptoInfo pointer is deallocated if the readheader routines fail so there is no need to deallocate here */ /* Dereference the user-mode file object */ if (Extension->pfoDeviceFile != NULL) ObDereferenceObject (Extension->pfoDeviceFile); /* Free the tmp IO buffers */ if (readBuffer != NULL) GSTfree (readBuffer); return ntStatus; }
/********************************************************************** * SmCreateUserProcess/5 * * DESCRIPTION * * ARGUMENTS * ImagePath: absolute path of the image to run; * CommandLine: arguments and options for ImagePath; * Flags: Wait flag: Set for boot time processes and unset for * subsystems bootstrapping; * 1Mb reserve flag: Set for subsystems, unset for everything * else * Timeout: optional: used if WaitForIt==TRUE; * ProcessHandle: optional: a duplicated handle for the child process (storage provided by the caller). * * RETURN VALUE * NTSTATUS: * */ NTSTATUS NTAPI SmCreateUserProcess (LPWSTR ImagePath, LPWSTR CommandLine, ULONG Flags, PLARGE_INTEGER Timeout OPTIONAL, PRTL_USER_PROCESS_INFORMATION UserProcessInfo OPTIONAL) { UNICODE_STRING ImagePathString = { 0, 0, NULL }; UNICODE_STRING CommandLineString = { 0, 0, NULL }; UNICODE_STRING SystemDirectory = { 0, 0, NULL }; PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL; RTL_USER_PROCESS_INFORMATION ProcessInfo = {0}; PRTL_USER_PROCESS_INFORMATION pProcessInfo = & ProcessInfo; NTSTATUS Status = STATUS_SUCCESS; DPRINT("SM: %s called\n", __FUNCTION__); if (NULL != UserProcessInfo) { pProcessInfo = UserProcessInfo; } RtlInitUnicodeString (& ImagePathString, ImagePath); RtlInitUnicodeString (& CommandLineString, CommandLine); SystemDirectory.MaximumLength = (wcslen(SharedUserData->NtSystemRoot) * sizeof(WCHAR)) + sizeof(szSystemDirectory); SystemDirectory.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, SystemDirectory.MaximumLength); if (SystemDirectory.Buffer == NULL) { Status = STATUS_NO_MEMORY; DPRINT1("SM: %s: Allocating system directory string failed (Status=0x%08lx)\n", __FUNCTION__, Status); return Status; } Status = RtlAppendUnicodeToString(& SystemDirectory, SharedUserData->NtSystemRoot); if (!NT_SUCCESS(Status)) { goto FailProcParams; } Status = RtlAppendUnicodeToString(& SystemDirectory, szSystemDirectory); if (!NT_SUCCESS(Status)) { goto FailProcParams; } Status = RtlCreateProcessParameters(& ProcessParameters, & ImagePathString, NULL, & SystemDirectory, & CommandLineString, SmSystemEnvironment, NULL, NULL, NULL, NULL); RtlFreeHeap(RtlGetProcessHeap(), 0, SystemDirectory.Buffer); if (!NT_SUCCESS(Status)) { FailProcParams: DPRINT1("SM: %s: Creating process parameters failed (Status=0x%08lx)\n", __FUNCTION__, Status); return Status; } /* Reserve lower 1Mb, if requested */ if (Flags & SM_CREATE_FLAG_RESERVE_1MB) ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB; /* Create the user process */ Status = RtlCreateUserProcess (& ImagePathString, OBJ_CASE_INSENSITIVE, ProcessParameters, NULL, NULL, NULL, FALSE, NULL, NULL, pProcessInfo); RtlDestroyProcessParameters (ProcessParameters); if (!NT_SUCCESS(Status)) { DPRINT1("SM: %s: Running \"%S\" failed (Status=0x%08lx)\n", __FUNCTION__, ImagePathString.Buffer, Status); return Status; } /* * It the caller is *not* interested in the child info, * resume it immediately. */ if (NULL == UserProcessInfo) { Status = NtResumeThread (ProcessInfo.ThreadHandle, NULL); if(!NT_SUCCESS(Status)) { DPRINT1("SM: %s: NtResumeThread failed (Status=0x%08lx)\n", __FUNCTION__, Status); } } /* Wait for process termination */ if (Flags & SM_CREATE_FLAG_WAIT) { Status = NtWaitForSingleObject (pProcessInfo->ProcessHandle, FALSE, Timeout); if (!NT_SUCCESS(Status)) { DPRINT1("SM: %s: NtWaitForSingleObject failed with Status=0x%08lx\n", __FUNCTION__, Status); } } if (NULL == UserProcessInfo) { NtClose(pProcessInfo->ProcessHandle); NtClose(pProcessInfo->ThreadHandle); } return Status; }
RT_C_DECLS_END #ifdef ALLOC_PRAGMA # pragma alloc_text(INIT, vbgdNt4CreateDevice) # pragma alloc_text(INIT, vbgdNt4FindPciDevice) #endif /** * Legacy helper function to create the device object. * * @returns NT status code. * * @param pDrvObj The driver object. * @param pDevObj Unused. NULL. Dunno why it's here, makes no sense. * @param pRegPath The driver registry path. */ NTSTATUS vbgdNt4CreateDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath) { Log(("VBoxGuest::vbgdNt4CreateDevice: pDrvObj=%p, pDevObj=%p, pRegPath=%p\n", pDrvObj, pDevObj, pRegPath)); /* * Find our virtual PCI device */ ULONG uBusNumber; PCI_SLOT_NUMBER SlotNumber; NTSTATUS rc = vbgdNt4FindPciDevice(&uBusNumber, &SlotNumber); if (NT_ERROR(rc)) { Log(("VBoxGuest::vbgdNt4CreateDevice: Device not found!\n")); return rc; } /* * Create device. */ UNICODE_STRING szDevName; RtlInitUnicodeString(&szDevName, VBOXGUEST_DEVICE_NAME_NT); PDEVICE_OBJECT pDeviceObject = NULL; rc = IoCreateDevice(pDrvObj, sizeof(VBOXGUESTDEVEXTWIN), &szDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject); if (NT_SUCCESS(rc)) { Log(("VBoxGuest::vbgdNt4CreateDevice: Device created\n")); UNICODE_STRING DosName; RtlInitUnicodeString(&DosName, VBOXGUEST_DEVICE_NAME_DOS); rc = IoCreateSymbolicLink(&DosName, &szDevName); if (NT_SUCCESS(rc)) { Log(("VBoxGuest::vbgdNt4CreateDevice: Symlink created\n")); /* * Setup the device extension. */ Log(("VBoxGuest::vbgdNt4CreateDevice: Setting up device extension ...\n")); PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDeviceObject->DeviceExtension; RT_ZERO(*pDevExt); Log(("VBoxGuest::vbgdNt4CreateDevice: Device extension created\n")); /* Store a reference to ourself. */ pDevExt->pDeviceObject = pDeviceObject; /* Store bus and slot number we've queried before. */ pDevExt->busNumber = uBusNumber; pDevExt->slotNumber = SlotNumber.u.AsULONG; #ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION rc = hlpRegisterBugCheckCallback(pDevExt); #endif /* Do the actual VBox init ... */ if (NT_SUCCESS(rc)) { rc = vbgdNtInit(pDrvObj, pDeviceObject, pRegPath); if (NT_SUCCESS(rc)) { Log(("VBoxGuest::vbgdNt4CreateDevice: Returning rc = 0x%x (succcess)\n", rc)); return rc; } /* bail out */ } IoDeleteSymbolicLink(&DosName); } else Log(("VBoxGuest::vbgdNt4CreateDevice: IoCreateSymbolicLink failed with rc = %#x\n", rc)); IoDeleteDevice(pDeviceObject); } else Log(("VBoxGuest::vbgdNt4CreateDevice: IoCreateDevice failed with rc = %#x\n", rc)); Log(("VBoxGuest::vbgdNt4CreateDevice: Returning rc = 0x%x\n", rc)); return rc; }