NTSTATUS NTAPI SmpInvokeAutoChk(IN PUNICODE_STRING FileName, IN PUNICODE_STRING Directory, IN PUNICODE_STRING Arguments, IN ULONG Flags) { ANSI_STRING MessageString; CHAR MessageBuffer[256]; UNICODE_STRING Destination; WCHAR Buffer[1024]; BOOLEAN BootState, BootOkay, ShutdownOkay; /* Check if autochk should show dots (if the user booted with /SOS) */ if (SmpQueryRegistrySosOption()) SmpEnableDots = FALSE; /* Make sure autochk was actually found */ if (Flags & SMP_INVALID_PATH) { /* It wasn't, so create an error message to print on the screen */ sprintf_nt(MessageBuffer, "%wZ program not found - skipping AUTOCHECK\r\n", FileName); RtlInitAnsiString(&MessageString, MessageBuffer); if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&Destination, &MessageString, TRUE))) { /* And show it */ NtDisplayString(&Destination); RtlFreeUnicodeString(&Destination); } } else { /* Autochk is there, so record the BSD state */ BootState = SmpSaveAndClearBootStatusData(&BootOkay, &ShutdownOkay); /* Build the path to autochk and place its arguments */ RtlInitEmptyUnicodeString(&Destination, Buffer, sizeof(Buffer)); RtlAppendUnicodeStringToString(&Destination, FileName); RtlAppendUnicodeToString(&Destination, L" "); RtlAppendUnicodeStringToString(&Destination, Arguments); /* Execute it */ SmpExecuteImage(FileName, Directory, &Destination, 0, Flags & ~SMP_AUTOCHK_FLAG, NULL); /* Restore the BSD state */ if (BootState) SmpRestoreBootStatusData(BootOkay, ShutdownOkay); } /* We're all done! */ return STATUS_SUCCESS; }
NTSTATUS ConstructDeviceName( IN PCWSTR Path, IN UCHAR Index, OUT PUNICODE_STRING DeviceName) { UNICODE_STRING UnicodePath; UNICODE_STRING UnicodeIndex; WCHAR IndexStringBuffer[5]; USHORT Size; USHORT LastCharacterIndex; /* Check for NULL parameters */ if ( ( ! Path ) || ( ! DeviceName ) ) { DPRINT("Unexpected NULL parameter"); return STATUS_INVALID_PARAMETER; } /* Range-check */ if ( Index >= SOUND_MAX_DEVICES ) { DPRINT("Device index %d out of range", Index); return STATUS_INVALID_PARAMETER; } /* Initialise the unicode path string */ RtlInitUnicodeString(&UnicodePath, Path); /* Calculate the length to hold the full string */ Size = UnicodePath.Length + sizeof(IndexStringBuffer) + sizeof(UNICODE_NULL); /* Allocate memory for DeviceName */ DeviceName->Buffer = ExAllocatePool(PagedPool, Size); DeviceName->MaximumLength = Size; if ( ! DeviceName->Buffer ) { DPRINT("Couldn't allocate memory for device name string"); return STATUS_INSUFFICIENT_RESOURCES; } /* Copy the path */ RtlCopyUnicodeString(DeviceName, &UnicodePath); /* Convert Index to string and append */ UnicodeIndex.Buffer = IndexStringBuffer; UnicodeIndex.MaximumLength = sizeof(IndexStringBuffer); RtlIntegerToUnicodeString((ULONG)Index, 10, &UnicodeIndex); RtlAppendUnicodeStringToString(DeviceName, &UnicodeIndex); /* Terminate the string */ LastCharacterIndex = DeviceName->Length / sizeof(UNICODE_NULL); DeviceName->Buffer[LastCharacterIndex] = UNICODE_NULL; return STATUS_SUCCESS; }
NTSTATUS SoundCreateDeviceName( PCWSTR PrePrefix, PCWSTR Prefix, UCHAR Index, PUNICODE_STRING DeviceName ) { UNICODE_STRING Number; WCHAR NumberBuffer[5]; UNICODE_STRING uPrePrefix; UNICODE_STRING uPrefix; ULONG Size; RtlInitUnicodeString(&uPrePrefix, PrePrefix); RtlInitUnicodeString(&uPrefix, Prefix); Size = uPrePrefix.Length + uPrefix.Length + sizeof(NumberBuffer) + sizeof(UNICODE_NULL); DeviceName->Buffer = ExAllocatePool(PagedPool, Size); DeviceName->MaximumLength = (USHORT)Size; if (DeviceName->Buffer == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } RtlCopyUnicodeString(DeviceName, &uPrePrefix); RtlAppendUnicodeStringToString(DeviceName, &uPrefix); if (Index != 255) { Number.Buffer = NumberBuffer; Number.MaximumLength = sizeof(NumberBuffer); RtlIntegerToUnicodeString((ULONG)Index, 10, &Number); RtlAppendUnicodeStringToString(DeviceName, &Number); } /* ** Null terminate for some uses (but don't increase the 'length' or ** the UNICODE_STRING version will have a 0 on the end. */ DeviceName->Buffer[DeviceName->Length / sizeof(UNICODE_NULL)] = UNICODE_NULL; return STATUS_SUCCESS; }
NTSTATUS MyDLPKBF_CreateDevice (IN PDRIVER_OBJECT pDriverObject, IN ULONG DeviceNumber) { PDEVICE_OBJECT pDevObj; UNICODE_STRING uniNtDeviceName, uniDosDeviceName, uniNumber; WCHAR ntDeviceNameBuffer[MYDLP_MAX_NAME_LENGTH]; WCHAR dosDeviceNameBuffer[MYDLP_MAX_NAME_LENGTH]; WCHAR numberBuffer[2]; PMYDLPKBF_DEVICE_EXTENSION pDevExt; NTSTATUS status; DbgPrint("MyDLPKBF_CreateDevice: Start\n"); status = STATUS_SUCCESS; uniNtDeviceName.Buffer = ntDeviceNameBuffer; uniNtDeviceName.MaximumLength = MYDLP_MAX_NAME_LENGTH * 2; uniNtDeviceName.Length = 0; uniDosDeviceName.Buffer = dosDeviceNameBuffer; uniDosDeviceName.MaximumLength = MYDLP_MAX_NAME_LENGTH * 2; uniDosDeviceName.Length = 0; uniNumber.Buffer = numberBuffer; uniNumber.MaximumLength = 4; uniNumber.Length = 0; RtlIntegerToUnicodeString( DeviceNumber, 10, &uniNumber); RtlAppendUnicodeToString( &uniNtDeviceName, NT_DEVICE_NAME); RtlAppendUnicodeStringToString( &uniNtDeviceName, &uniNumber); RtlAppendUnicodeToString( &uniDosDeviceName, DOS_DEVICE_NAME); RtlAppendUnicodeStringToString( &uniDosDeviceName, &uniNumber); status = IoCreateDevice(pDriverObject, sizeof(MYDLPKBF_DEVICE_EXTENSION), &uniNtDeviceName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDevObj); if(!NT_SUCCESS(status)) { DbgPrint("MyDLPKBF_CreateDevice: IoCreateDevice failed\ device no:%d\n", DeviceNumber); return status; }
static NTSTATUS XenM2BPdoQueryDeviceText(PXENM2B_PDO_EXTENSION pPdoExt, PIRP pIrp) { PIO_STACK_LOCATION pIrpStack; PVOID pBuffer; UNICODE_STRING Text; NTSTATUS Status; pIrpStack = IoGetCurrentIrpStackLocation(pIrp); switch (pIrpStack->Parameters.QueryDeviceText.DeviceTextType) { case DeviceTextDescription: TraceDebug(("%s: DeviceTextDescription\n", __FUNCTION__)); break; case DeviceTextLocationInformation: TraceDebug(("%s: DeviceTextLocationInformation\n", __FUNCTION__)); break; default: pIrp->IoStatus.Information = 0; return STATUS_NOT_SUPPORTED; } pBuffer = ExAllocatePoolWithTag(PagedPool, XENM2B_MAX_TEXT_LENGTH, XENM2B_POOL_TAG); if (pBuffer == NULL) return STATUS_INSUFFICIENT_RESOURCES; RtlZeroMemory(pBuffer, XENM2B_MAX_TEXT_LENGTH); Text.Buffer = pBuffer; Text.MaximumLength = XENM2B_MAX_TEXT_LENGTH; Text.Length = 0; switch (pIrpStack->Parameters.QueryDeviceText.DeviceTextType) { case DeviceTextDescription: RtlAppendUnicodeStringToString(&Text, &pPdoExt->DeviceName); break; case DeviceTextLocationInformation: RtlAppendUnicodeToString(&Text, L"Xen PV HID Device on XenM2B Bus"); break; default: ASSERT(FALSE); break; } TraceDebug(("%s: %wZ\n", __FUNCTION__, &Text)); pIrp->IoStatus.Information = (ULONG_PTR)pBuffer; return STATUS_SUCCESS; }
NTSTATUS openfile ( IN PHANDLE filehandle, IN PUCHAR BasePath, IN PUCHAR Name ) { ANSI_STRING AscBasePath, AscName; UNICODE_STRING UniPathName, UniName; NTSTATUS status; OBJECT_ATTRIBUTES ObjA; IO_STATUS_BLOCK IOSB; UCHAR StringBuf[500]; // // Build name // UniPathName.Buffer = (PWCHAR)StringBuf; UniPathName.Length = 0; UniPathName.MaximumLength = sizeof( StringBuf ); RtlInitString(&AscBasePath, BasePath); RtlAnsiStringToUnicodeString( &UniPathName, &AscBasePath, FALSE ); RtlInitString(&AscName, Name); RtlAnsiStringToUnicodeString( &UniName, &AscName, TRUE ); RtlAppendUnicodeStringToString (&UniPathName, &UniName); InitializeObjectAttributes( &ObjA, &UniPathName, OBJ_CASE_INSENSITIVE, 0, 0 ); // // open file // status = NtOpenFile ( filehandle, // return handle SYNCHRONIZE | FILE_READ_DATA, // desired access &ObjA, // Object &IOSB, // io status block FILE_SHARE_READ | FILE_SHARE_WRITE, // share access FILE_SYNCHRONOUS_IO_ALERT // open options ); RtlFreeUnicodeString (&UniName); return status; }
/* * @implemented */ NTSTATUS CreateNewVolumeName(OUT PUNICODE_STRING VolumeName, IN PGUID VolumeGuid OPTIONAL) { GUID Guid; NTSTATUS Status; UNICODE_STRING GuidString; /* If no GUID was provided, then create one */ if (!VolumeGuid) { Status = ExUuidCreate(&Guid); if (!NT_SUCCESS(Status)) { return Status; } } else { RtlCopyMemory(&Guid, VolumeGuid, sizeof(GUID)); } /* Convert GUID to string */ Status = RtlStringFromGUID(&Guid, &GuidString); if (!NT_SUCCESS(Status)) { return Status; } /* Size for volume namespace, litteral GUID, and null char */ VolumeName->MaximumLength = 0x14 + 0x4C + sizeof(UNICODE_NULL); VolumeName->Buffer = AllocatePool(0x14 + 0x4C + sizeof(UNICODE_NULL)); if (!VolumeName->Buffer) { Status = STATUS_INSUFFICIENT_RESOURCES; } else { RtlCopyUnicodeString(VolumeName, &Volume); RtlAppendUnicodeStringToString(VolumeName, &GuidString); VolumeName->Buffer[VolumeName->Length / sizeof(WCHAR)] = UNICODE_NULL; Status = STATUS_SUCCESS; } ExFreePoolWithTag(GuidString.Buffer, 0); return Status; }
NTSTATUS IopQueueTargetDeviceEvent(const GUID *Guid, PUNICODE_STRING DeviceIds) { PPNP_EVENT_ENTRY EventEntry; UNICODE_STRING Copy; ULONG TotalSize; NTSTATUS Status; ASSERT(DeviceIds); /* Allocate a big enough buffer */ Copy.Length = 0; Copy.MaximumLength = DeviceIds->Length + sizeof(UNICODE_NULL); TotalSize = FIELD_OFFSET(PLUGPLAY_EVENT_BLOCK, TargetDevice.DeviceIds) + Copy.MaximumLength; EventEntry = ExAllocatePool(NonPagedPool, TotalSize + FIELD_OFFSET(PNP_EVENT_ENTRY, Event)); if (!EventEntry) return STATUS_INSUFFICIENT_RESOURCES; /* Fill the buffer with the event GUID */ RtlCopyMemory(&EventEntry->Event.EventGuid, Guid, sizeof(GUID)); EventEntry->Event.EventCategory = TargetDeviceChangeEvent; EventEntry->Event.TotalSize = TotalSize; /* Fill the device id */ Copy.Buffer = EventEntry->Event.TargetDevice.DeviceIds; Status = RtlAppendUnicodeStringToString(&Copy, DeviceIds); if (!NT_SUCCESS(Status)) { ExFreePool(EventEntry); return Status; } InsertHeadList(&IopPnpEventQueueHead, &EventEntry->ListEntry); KeSetEvent(&IopPnpNotifyEvent, 0, FALSE); return STATUS_SUCCESS; }
/*++ * @name IopOpenInterfaceKey * * Returns the alias device interface of the specified device interface * * @param InterfaceClassGuid * FILLME * * @param DesiredAccess * FILLME * * @param pInterfaceKey * FILLME * * @return Usual NTSTATUS * * @remarks None * *--*/ static NTSTATUS IopOpenInterfaceKey(IN CONST GUID *InterfaceClassGuid, IN ACCESS_MASK DesiredAccess, OUT HANDLE *pInterfaceKey) { UNICODE_STRING LocalMachine = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\"); UNICODE_STRING GuidString; UNICODE_STRING KeyName; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE InterfaceKey = INVALID_HANDLE_VALUE; NTSTATUS Status; GuidString.Buffer = KeyName.Buffer = NULL; Status = RtlStringFromGUID(InterfaceClassGuid, &GuidString); if (!NT_SUCCESS(Status)) { DPRINT("RtlStringFromGUID() failed with status 0x%08lx\n", Status); goto cleanup; } KeyName.Length = 0; KeyName.MaximumLength = LocalMachine.Length + ((USHORT)wcslen(REGSTR_PATH_DEVICE_CLASSES) + 1) * sizeof(WCHAR) + GuidString.Length; KeyName.Buffer = ExAllocatePool(PagedPool, KeyName.MaximumLength); if (!KeyName.Buffer) { DPRINT("ExAllocatePool() failed\n"); Status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } Status = RtlAppendUnicodeStringToString(&KeyName, &LocalMachine); if (!NT_SUCCESS(Status)) { DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status); goto cleanup; } Status = RtlAppendUnicodeToString(&KeyName, REGSTR_PATH_DEVICE_CLASSES); if (!NT_SUCCESS(Status)) { DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status); goto cleanup; } Status = RtlAppendUnicodeToString(&KeyName, L"\\"); if (!NT_SUCCESS(Status)) { DPRINT("RtlAppendUnicodeToString() failed with status 0x%08lx\n", Status); goto cleanup; } Status = RtlAppendUnicodeStringToString(&KeyName, &GuidString); if (!NT_SUCCESS(Status)) { DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status); goto cleanup; } InitializeObjectAttributes( &ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenKey( &InterfaceKey, DesiredAccess, &ObjectAttributes); if (!NT_SUCCESS(Status)) { DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); goto cleanup; } *pInterfaceKey = InterfaceKey; Status = STATUS_SUCCESS; cleanup: if (!NT_SUCCESS(Status)) { if (InterfaceKey != INVALID_HANDLE_VALUE) ZwClose(InterfaceKey); } RtlFreeUnicodeString(&GuidString); RtlFreeUnicodeString(&KeyName); return Status; }
static NTSTATUS OpenRegistryHandlesFromSymbolicLink(IN PUNICODE_STRING SymbolicLinkName, IN ACCESS_MASK DesiredAccess, IN OPTIONAL PHANDLE GuidKey, IN OPTIONAL PHANDLE DeviceKey, IN OPTIONAL PHANDLE InstanceKey) { OBJECT_ATTRIBUTES ObjectAttributes; WCHAR PathBuffer[MAX_PATH]; UNICODE_STRING BaseKeyU; UNICODE_STRING GuidString, SubKeyName, ReferenceString; PWCHAR StartPosition, EndPosition; HANDLE ClassesKey; PHANDLE GuidKeyRealP, DeviceKeyRealP, InstanceKeyRealP; HANDLE GuidKeyReal, DeviceKeyReal, InstanceKeyReal; NTSTATUS Status; SubKeyName.Buffer = NULL; if (GuidKey != NULL) GuidKeyRealP = GuidKey; else GuidKeyRealP = &GuidKeyReal; if (DeviceKey != NULL) DeviceKeyRealP = DeviceKey; else DeviceKeyRealP = &DeviceKeyReal; if (InstanceKey != NULL) InstanceKeyRealP = InstanceKey; else InstanceKeyRealP = &InstanceKeyReal; *GuidKeyRealP = INVALID_HANDLE_VALUE; *DeviceKeyRealP = INVALID_HANDLE_VALUE; *InstanceKeyRealP = INVALID_HANDLE_VALUE; BaseKeyU.Buffer = PathBuffer; BaseKeyU.Length = 0; BaseKeyU.MaximumLength = MAX_PATH * sizeof(WCHAR); RtlAppendUnicodeToString(&BaseKeyU, BaseKeyString); /* Open the DeviceClasses key */ InitializeObjectAttributes(&ObjectAttributes, &BaseKeyU, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwOpenKey(&ClassesKey, DesiredAccess | KEY_ENUMERATE_SUB_KEYS, &ObjectAttributes); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to open %wZ\n", &BaseKeyU); goto cleanup; } StartPosition = wcschr(SymbolicLinkName->Buffer, L'{'); EndPosition = wcschr(SymbolicLinkName->Buffer, L'}'); if (!StartPosition || !EndPosition || StartPosition > EndPosition) { DPRINT1("Bad symbolic link: %wZ\n", SymbolicLinkName); return STATUS_INVALID_PARAMETER_1; } GuidString.Buffer = StartPosition; GuidString.MaximumLength = GuidString.Length = (USHORT)((ULONG_PTR)(EndPosition + 1) - (ULONG_PTR)StartPosition); InitializeObjectAttributes(&ObjectAttributes, &GuidString, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, ClassesKey, NULL); Status = ZwOpenKey(GuidKeyRealP, DesiredAccess | KEY_ENUMERATE_SUB_KEYS, &ObjectAttributes); ZwClose(ClassesKey); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to open %wZ%wZ (%x)\n", &BaseKeyU, &GuidString, Status); goto cleanup; } SubKeyName.MaximumLength = SymbolicLinkName->Length + sizeof(WCHAR); SubKeyName.Length = 0; SubKeyName.Buffer = ExAllocatePool(PagedPool, SubKeyName.MaximumLength); if (!SubKeyName.Buffer) { Status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } RtlAppendUnicodeStringToString(&SubKeyName, SymbolicLinkName); SubKeyName.Buffer[SubKeyName.Length / sizeof(WCHAR)] = UNICODE_NULL; SubKeyName.Buffer[0] = L'#'; SubKeyName.Buffer[1] = L'#'; SubKeyName.Buffer[2] = L'?'; SubKeyName.Buffer[3] = L'#'; ReferenceString.Buffer = wcsrchr(SubKeyName.Buffer, '\\'); if (ReferenceString.Buffer != NULL) { ReferenceString.Buffer[0] = L'#'; SubKeyName.Length = (USHORT)((ULONG_PTR)(ReferenceString.Buffer) - (ULONG_PTR)SubKeyName.Buffer); ReferenceString.Length = SymbolicLinkName->Length - SubKeyName.Length; } else { RtlInitUnicodeString(&ReferenceString, L"#"); } InitializeObjectAttributes(&ObjectAttributes, &SubKeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, *GuidKeyRealP, NULL); Status = ZwOpenKey(DeviceKeyRealP, DesiredAccess | KEY_ENUMERATE_SUB_KEYS, &ObjectAttributes); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to open %wZ%wZ\\%wZ\n", &BaseKeyU, &GuidString, &SubKeyName); goto cleanup; } InitializeObjectAttributes(&ObjectAttributes, &ReferenceString, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, *DeviceKeyRealP, NULL); Status = ZwOpenKey(InstanceKeyRealP, DesiredAccess, &ObjectAttributes); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to open %wZ%wZ\\%wZ%\\%wZ (%x)\n", &BaseKeyU, &GuidString, &SubKeyName, &ReferenceString, Status); goto cleanup; } Status = STATUS_SUCCESS; cleanup: if (SubKeyName.Buffer != NULL) ExFreePool(SubKeyName.Buffer); if (NT_SUCCESS(Status)) { if (!GuidKey) ZwClose(*GuidKeyRealP); if (!DeviceKey) ZwClose(*DeviceKeyRealP); if (!InstanceKey) ZwClose(*InstanceKeyRealP); } else { if (*GuidKeyRealP != INVALID_HANDLE_VALUE) ZwClose(*GuidKeyRealP); if (*DeviceKeyRealP != INVALID_HANDLE_VALUE) ZwClose(*DeviceKeyRealP); if (*InstanceKeyRealP != INVALID_HANDLE_VALUE) ZwClose(*InstanceKeyRealP); } return Status; }
NTSTATUS NTAPI IntCreateRegistryPath( IN PCUNICODE_STRING DriverRegistryPath, OUT PUNICODE_STRING DeviceRegistryPath) { static WCHAR RegistryMachineSystem[] = L"\\REGISTRY\\MACHINE\\SYSTEM\\"; static WCHAR CurrentControlSet[] = L"CURRENTCONTROLSET\\"; static WCHAR ControlSet[] = L"CONTROLSET"; static WCHAR Insert1[] = L"Hardware Profiles\\Current\\System\\CurrentControlSet\\"; static WCHAR Insert2[] = L"\\Device0"; BOOLEAN Valid; UNICODE_STRING AfterControlSet; AfterControlSet = *DriverRegistryPath; /* Check if path begins with \\REGISTRY\\MACHINE\\SYSTEM\\ */ Valid = (DriverRegistryPath->Length > sizeof(RegistryMachineSystem) && 0 == _wcsnicmp(DriverRegistryPath->Buffer, RegistryMachineSystem, wcslen(RegistryMachineSystem))); if (Valid) { AfterControlSet.Buffer += wcslen(RegistryMachineSystem); AfterControlSet.Length -= sizeof(RegistryMachineSystem) - sizeof(UNICODE_NULL); /* Check if path contains CURRENTCONTROLSET */ if (AfterControlSet.Length > sizeof(CurrentControlSet) && 0 == _wcsnicmp(AfterControlSet.Buffer, CurrentControlSet, wcslen(CurrentControlSet))) { AfterControlSet.Buffer += wcslen(CurrentControlSet); AfterControlSet.Length -= sizeof(CurrentControlSet) - sizeof(UNICODE_NULL); } /* Check if path contains CONTROLSETnum */ else if (AfterControlSet.Length > sizeof(ControlSet) && 0 == _wcsnicmp(AfterControlSet.Buffer, ControlSet, wcslen(ControlSet))) { AfterControlSet.Buffer += wcslen(ControlSet); AfterControlSet.Length -= sizeof(ControlSet) - sizeof(UNICODE_NULL); while (AfterControlSet.Length > 0 && *AfterControlSet.Buffer >= L'0' && *AfterControlSet.Buffer <= L'9') { AfterControlSet.Buffer++; AfterControlSet.Length -= sizeof(WCHAR); } Valid = (AfterControlSet.Length > 0 && L'\\' == *AfterControlSet.Buffer); AfterControlSet.Buffer++; AfterControlSet.Length -= sizeof(WCHAR); AfterControlSet.MaximumLength = AfterControlSet.Length; } else { Valid = FALSE; } } if (Valid) { DeviceRegistryPath->MaximumLength = DriverRegistryPath->Length + sizeof(Insert1) + sizeof(Insert2); DeviceRegistryPath->Buffer = ExAllocatePoolWithTag(PagedPool, DeviceRegistryPath->MaximumLength, TAG_VIDEO_PORT); if (DeviceRegistryPath->Buffer != NULL) { /* Build device path */ wcsncpy(DeviceRegistryPath->Buffer, DriverRegistryPath->Buffer, AfterControlSet.Buffer - DriverRegistryPath->Buffer); DeviceRegistryPath->Length = (AfterControlSet.Buffer - DriverRegistryPath->Buffer) * sizeof(WCHAR); RtlAppendUnicodeToString(DeviceRegistryPath, Insert1); RtlAppendUnicodeStringToString(DeviceRegistryPath, &AfterControlSet); RtlAppendUnicodeToString(DeviceRegistryPath, Insert2); /* Check if registry key exists */ Valid = NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, DeviceRegistryPath->Buffer)); if (!Valid) ExFreePoolWithTag(DeviceRegistryPath->Buffer, TAG_VIDEO_PORT); } else { Valid = FALSE; } } else { WARN_(VIDEOPRT, "Unparsable registry path %wZ", DriverRegistryPath); } /* If path doesn't point to *ControlSet*, use DriverRegistryPath directly */ if (!Valid) { DeviceRegistryPath->MaximumLength = DriverRegistryPath->Length + sizeof(Insert2); DeviceRegistryPath->Buffer = ExAllocatePoolWithTag(NonPagedPool, DeviceRegistryPath->MaximumLength, TAG_VIDEO_PORT); if (!DeviceRegistryPath->Buffer) return STATUS_NO_MEMORY; RtlCopyUnicodeString(DeviceRegistryPath, DriverRegistryPath); RtlAppendUnicodeToString(DeviceRegistryPath, Insert2); } DbgPrint("Formatted registry key '%wZ' -> '%wZ'\n", DriverRegistryPath, DeviceRegistryPath); return STATUS_SUCCESS; }
NTSTATUS ReadonlyMakeFullFileName ( IN PFILESPY_DEVICE_EXTENSION DevExt, IN PFILE_OBJECT FileObject, IN PUNICODE_STRING FullFileName, IN BOOLEAN FileDirectoryFile ) { NTSTATUS status; do { if (FileObject->RelatedFileObject) { if (ReadonlyLookUpCcb(DevExt->LfsDeviceExt.Readonly, FileObject->RelatedFileObject)) { PNDAS_FCB relatedFcb = FileObject->RelatedFileObject->FsContext; PNDAS_CCB relatedCcb = FileObject->RelatedFileObject->FsContext2; ASSERT( relatedCcb->Mark == CCB_MARK ); status = RtlAppendUnicodeStringToString( FullFileName, &relatedFcb->FullFileName ); if (status != STATUS_SUCCESS) break; if (relatedFcb->FullFileName.Length >= 2 && relatedFcb->FullFileName.Buffer[relatedFcb->FullFileName.Length/sizeof(WCHAR)-1] != L'\\') { SPY_LOG_PRINT( LFS_DEBUG_SECONDARY_TRACE, ("Secondary_MakeFullFileName, relatedFcb->FullFileName = %wZ, FileObject->FileName = %wZ\n", &relatedFcb->FullFileName, &FileObject->FileName) ); status = RtlAppendUnicodeToString( FullFileName, L"\\" ); if (status != STATUS_SUCCESS) break; } else { if (FileObject->FileName.Length == 0) { //NDAS_ASSERT( FALSE ); } } } else { if (FileObject->RelatedFileObject->FileName.Length == 0) { status = RtlAppendUnicodeStringToString( FullFileName, &DevExt->LfsDeviceExt.NetdiskPartitionInformation.VolumeName ); if (status != STATUS_SUCCESS) break; } else { status = STATUS_OBJECT_NAME_INVALID; break; } } } else { status = RtlAppendUnicodeStringToString( FullFileName, &DevExt->LfsDeviceExt.NetdiskPartitionInformation.VolumeName ); if (status != STATUS_SUCCESS) break; } status = RtlAppendUnicodeStringToString( FullFileName, &FileObject->FileName ); if (status != STATUS_SUCCESS) break; if (FileDirectoryFile && FullFileName->Buffer[FullFileName->Length/sizeof(WCHAR)-1] != L'\\') { status = RtlAppendUnicodeToString( FullFileName, L"\\" ); } } while (0); return status; }
static VOID NTAPI TestSymlinks(VOID) { HANDLE ReparseHandle; NTSTATUS Status; IO_STATUS_BLOCK IoStatusBlock; OBJECT_ATTRIBUTES ObjectAttributes; PREPARSE_DATA_BUFFER Reparse; FILE_DISPOSITION_INFORMATION ToDelete; PFILE_OBJECT FileObject; UNICODE_STRING SysDir, Foobar, Regedit; ULONG Size; /* Get Windows/ReactOS directory */ InitializeObjectAttributes(&ObjectAttributes, &SystemRoot, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenFile(&ReparseHandle, FILE_READ_DATA, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_DIRECTORY_FILE); if (skip(NT_SUCCESS(Status), "Opening \\SystemRoot failed: %lx\n", Status)) { return; } Status = ObReferenceObjectByHandle(ReparseHandle, FILE_READ_DATA, *IoFileObjectType, UserMode, (PVOID *)&FileObject, NULL); if (skip(NT_SUCCESS(Status), "Querying name failed: %lx\n", Status)) { ZwClose(ReparseHandle); return; } SysDir.Buffer = ExAllocatePool(NonPagedPool, FileObject->FileName.Length + sizeof(L"\\??\\C:")); if (skip(SysDir.Buffer != NULL, "Allocating memory failed\n")) { ObDereferenceObject(FileObject); ZwClose(ReparseHandle); return; } SysDir.Length = sizeof(L"\\??\\C:") - sizeof(UNICODE_NULL); SysDir.MaximumLength = FileObject->FileName.Length + sizeof(L"\\??\\C:"); RtlCopyMemory(SysDir.Buffer, L"\\??\\C:", sizeof(L"\\??\\C:") - sizeof(UNICODE_NULL)); RtlAppendUnicodeStringToString(&SysDir, &FileObject->FileName); Foobar.Buffer = ExAllocatePool(NonPagedPool, FileObject->FileName.Length + sizeof(L"\\foobar.exe")); if (skip(Foobar.Buffer != NULL, "Allocating memory failed\n")) { ExFreePool(SysDir.Buffer); ObDereferenceObject(FileObject); ZwClose(ReparseHandle); return; } Foobar.Length = 0; Foobar.MaximumLength = FileObject->FileName.Length + sizeof(L"\\foobar.exe"); RtlCopyUnicodeString(&Foobar, &FileObject->FileName); RtlCopyMemory(&Foobar.Buffer[Foobar.Length / sizeof(WCHAR)], L"\\foobar.exe", sizeof(L"\\foobar.exe") - sizeof(UNICODE_NULL)); Foobar.Length += (sizeof(L"\\foobar.exe") - sizeof(UNICODE_NULL)); Regedit.Buffer = ExAllocatePool(NonPagedPool, FileObject->FileName.Length + sizeof(L"\\regedit.exe")); if (skip(Regedit.Buffer != NULL, "Allocating memory failed\n")) { ExFreePool(Foobar.Buffer); ExFreePool(SysDir.Buffer); ObDereferenceObject(FileObject); ZwClose(ReparseHandle); return; } Regedit.Length = 0; Regedit.MaximumLength = FileObject->FileName.Length + sizeof(L"\\regedit.exe"); RtlCopyUnicodeString(&Regedit, &FileObject->FileName); RtlCopyMemory(&Regedit.Buffer[Regedit.Length / sizeof(WCHAR)], L"\\regedit.exe", sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL)); Regedit.Length += (sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL)); ObDereferenceObject(FileObject); ZwClose(ReparseHandle); ToDelete.DeleteFile = TRUE; Size = FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + SysDir.Length * 2 + sizeof(L"\\regedit.exe") * 2 - sizeof(L"\\??\\") - sizeof(UNICODE_NULL); InitializeObjectAttributes(&ObjectAttributes, &SystemRootFoobar, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwCreateFile(&ReparseHandle, GENERIC_READ | GENERIC_WRITE | DELETE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SUPERSEDE, FILE_NON_DIRECTORY_FILE, NULL, 0); ok_eq_hex(Status, STATUS_SUCCESS); if (skip(NT_SUCCESS(Status), "Creating file failed: %lx\n", Status)) { ExFreePool(Regedit.Buffer); ExFreePool(Foobar.Buffer); ExFreePool(SysDir.Buffer); return; } Reparse = ExAllocatePool(NonPagedPool, Size); RtlZeroMemory(Reparse, Size); Reparse->ReparseTag = IO_REPARSE_TAG_SYMLINK; Reparse->ReparseDataLength = 12 + SysDir.Length * 2 + sizeof(L"\\regedit.exe") * 2 - sizeof(L"\\??\\") - sizeof(UNICODE_NULL); Reparse->SymbolicLinkReparseBuffer.SubstituteNameLength = SysDir.Length + sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL); Reparse->SymbolicLinkReparseBuffer.PrintNameLength = SysDir.Length + sizeof(L"\\regedit.exe") - sizeof(L"\\??\\"); Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset = Reparse->SymbolicLinkReparseBuffer.PrintNameLength; RtlCopyMemory(Reparse->SymbolicLinkReparseBuffer.PathBuffer, (WCHAR *)((ULONG_PTR)SysDir.Buffer + sizeof(L"\\??\\") - sizeof(UNICODE_NULL)), SysDir.Length - sizeof(L"\\??\\") + sizeof(UNICODE_NULL)); RtlCopyMemory((WCHAR *)((ULONG_PTR)Reparse->SymbolicLinkReparseBuffer.PathBuffer + SysDir.Length - sizeof(L"\\??\\") + sizeof(UNICODE_NULL)), L"\\regedit.exe", sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL)); RtlCopyMemory((WCHAR *)((ULONG_PTR)Reparse->SymbolicLinkReparseBuffer.PathBuffer + Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset), SysDir.Buffer, SysDir.Length); RtlCopyMemory((WCHAR *)((ULONG_PTR)Reparse->SymbolicLinkReparseBuffer.PathBuffer + Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset + SysDir.Length), L"\\regedit.exe", sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL)); Status = ZwFsControlFile(ReparseHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_SET_REPARSE_POINT, Reparse, Size, NULL, 0); ok_eq_hex(Status, STATUS_SUCCESS); if (!NT_SUCCESS(Status)) { ZwClose(ReparseHandle); Status = ZwCreateFile(&ReparseHandle, FILE_WRITE_ATTRIBUTES | DELETE | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_SUPERSEDE, FILE_NON_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0); if (skip(NT_SUCCESS(Status), "Creating symlink failed: %lx\n", Status)) { Status = ZwOpenFile(&ReparseHandle, DELETE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_DELETE, FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE); ok_eq_hex(Status, STATUS_SUCCESS); ZwClose(ReparseHandle); ExFreePool(Regedit.Buffer); ExFreePool(Foobar.Buffer); ExFreePool(SysDir.Buffer); ExFreePool(Reparse); return; } Status = ZwFsControlFile(ReparseHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_SET_REPARSE_POINT, Reparse, Size, NULL, 0); } if (skip(NT_SUCCESS(Status), "Creating symlink failed: %lx\n", Status)) { ZwSetInformationFile(ReparseHandle, &IoStatusBlock, &ToDelete, sizeof(ToDelete), FileDispositionInformation); ZwClose(ReparseHandle); ExFreePool(Regedit.Buffer); ExFreePool(Foobar.Buffer); ExFreePool(SysDir.Buffer); ExFreePool(Reparse); return; } ZwClose(ReparseHandle); Status = ZwCreateFile(&ReparseHandle, GENERIC_READ, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0); ok(Status == STATUS_SUCCESS || /* Windows Vista+ */ Status == STATUS_IO_REPARSE_TAG_NOT_HANDLED, /* Windows 2003 (SP1, SP2) */ "ZwCreateFile returned unexpected status: %lx\n", Status); if (NT_SUCCESS(Status)) { Status = ObReferenceObjectByHandle(ReparseHandle, FILE_READ_DATA, *IoFileObjectType, UserMode, (PVOID *)&FileObject, NULL); ok_eq_hex(Status, STATUS_SUCCESS); if (NT_SUCCESS(Status)) { ok(RtlCompareUnicodeString(&Regedit, &FileObject->FileName, TRUE) == 0, "Expected: %wZ. Opened: %wZ\n", &Regedit, &FileObject->FileName); ObDereferenceObject(FileObject); } ZwClose(ReparseHandle); } ExFreePool(Regedit.Buffer); Status = IoCreateFile(&ReparseHandle, GENERIC_READ, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0, CreateFileTypeNone, NULL, IO_NO_PARAMETER_CHECKING | IO_STOP_ON_SYMLINK); ok(Status == STATUS_STOPPED_ON_SYMLINK || /* Windows Vista+ */ Status == STATUS_IO_REPARSE_TAG_NOT_HANDLED, /* Windows 2003 (SP1, SP2) */ "ZwCreateFile returned unexpected status: %lx\n", Status); if (NT_SUCCESS(Status)) { ZwClose(ReparseHandle); } Status = ZwCreateFile(&ReparseHandle, GENERIC_READ | GENERIC_WRITE | DELETE, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT | FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0); if (skip(NT_SUCCESS(Status), "Creating opening reparse point: %lx\n", Status)) { Status = ZwOpenFile(&ReparseHandle, DELETE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_DELETE, FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE); ok_eq_hex(Status, STATUS_SUCCESS); ZwClose(ReparseHandle); ExFreePool(Foobar.Buffer); ExFreePool(SysDir.Buffer); ExFreePool(Reparse); return; } Status = ObReferenceObjectByHandle(ReparseHandle, FILE_READ_DATA, *IoFileObjectType, UserMode, (PVOID *)&FileObject, NULL); ok_eq_hex(Status, STATUS_SUCCESS); if (NT_SUCCESS(Status)) { ok(RtlCompareUnicodeString(&Foobar, &FileObject->FileName, TRUE) == 0, "Expected: %wZ. Opened: %wZ\n", &Foobar, &FileObject->FileName); ObDereferenceObject(FileObject); } ExFreePool(Foobar.Buffer); RtlZeroMemory(Reparse, Size); Status = ZwFsControlFile(ReparseHandle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_GET_REPARSE_POINT, NULL, 0, Reparse, Size); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_hex(IoStatusBlock.Information, Size); if (NT_SUCCESS(Status)) { PWSTR Buffer; UNICODE_STRING ReparsePath, FullPath; ok_eq_hex(Reparse->ReparseTag, IO_REPARSE_TAG_SYMLINK); ok_eq_hex(Reparse->ReparseDataLength, 12 + SysDir.Length * 2 + sizeof(L"\\regedit.exe") * 2 - sizeof(L"\\??\\") - sizeof(UNICODE_NULL)); ok_eq_hex(Reparse->SymbolicLinkReparseBuffer.Flags, 0); FullPath.Length = 0; FullPath.MaximumLength = SysDir.Length + sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL); Buffer = FullPath.Buffer = ExAllocatePool(NonPagedPool, FullPath.MaximumLength); if (!skip(Buffer != NULL, "Memory allocation failed!\n")) { RtlCopyUnicodeString(&FullPath, &SysDir); RtlCopyMemory(&FullPath.Buffer[FullPath.Length / sizeof(WCHAR)], L"\\regedit.exe", sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL)); FullPath.Length += (sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL)); ReparsePath.Buffer = (PWSTR)((ULONG_PTR)Reparse->SymbolicLinkReparseBuffer.PathBuffer + Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset); ReparsePath.Length = ReparsePath.MaximumLength = Reparse->SymbolicLinkReparseBuffer.SubstituteNameLength; ok(RtlCompareUnicodeString(&ReparsePath, &FullPath, TRUE) == 0, "Expected: %wZ. Got: %wZ\n", &ReparsePath, &FullPath); FullPath.Length -= (sizeof(L"\\??\\") - sizeof(UNICODE_NULL)); FullPath.MaximumLength -= (sizeof(L"\\??\\") - sizeof(UNICODE_NULL)); FullPath.Buffer = (PWSTR)((ULONG_PTR)Buffer + sizeof(L"\\??\\") - sizeof(UNICODE_NULL)); ReparsePath.Buffer = (PWSTR)((ULONG_PTR)Reparse->SymbolicLinkReparseBuffer.PathBuffer + Reparse->SymbolicLinkReparseBuffer.PrintNameOffset); ReparsePath.Length = ReparsePath.MaximumLength = Reparse->SymbolicLinkReparseBuffer.PrintNameLength; ok(RtlCompareUnicodeString(&ReparsePath, &FullPath, TRUE) == 0, "Expected: %wZ. Got: %wZ\n", &ReparsePath, &FullPath); ExFreePool(Buffer); } } ExFreePool(SysDir.Buffer); ExFreePool(Reparse); ZwSetInformationFile(ReparseHandle, &IoStatusBlock, &ToDelete, sizeof(ToDelete), FileDispositionInformation); ZwClose(ReparseHandle); }
NTSTATUS NTAPI CmpOpenHiveFiles(IN PCUNICODE_STRING BaseName, IN PCWSTR Extension OPTIONAL, OUT PHANDLE Primary, OUT PHANDLE Log, OUT PULONG PrimaryDisposition, OUT PULONG LogDisposition, IN BOOLEAN CreateAllowed, IN BOOLEAN MarkAsSystemHive, IN BOOLEAN NoBuffering, OUT PULONG ClusterSize OPTIONAL) { HANDLE EventHandle; PKEVENT Event; NTSTATUS Status; UNICODE_STRING FullName, ExtensionName; PWCHAR NameBuffer; USHORT Length; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; ULONG AttributeFlags, ShareMode, DesiredAccess, CreateDisposition, IoFlags; USHORT CompressionState; FILE_STANDARD_INFORMATION FileInformation; FILE_FS_SIZE_INFORMATION FsSizeInformation; /* Create event */ Status = CmpCreateEvent(NotificationEvent, &EventHandle, &Event); if (!NT_SUCCESS(Status)) return Status; /* Initialize the full name */ RtlInitEmptyUnicodeString(&FullName, NULL, 0); Length = BaseName->Length; /* Check if we have an extension */ if (Extension) { /* Update the name length */ Length += (USHORT)wcslen(Extension) * sizeof(WCHAR) + sizeof(UNICODE_NULL); /* Allocate the buffer for the full name */ NameBuffer = ExAllocatePoolWithTag(PagedPool, Length, TAG_CM); if (!NameBuffer) { /* Fail */ ObDereferenceObject(Event); ZwClose(EventHandle); return STATUS_NO_MEMORY; } /* Build the full name */ FullName.Buffer = NameBuffer; FullName.MaximumLength = Length; RtlAppendUnicodeStringToString(&FullName, BaseName); } else { /* The base name is the full name */ FullName = *BaseName; NameBuffer = NULL; } /* Initialize the attributes */ InitializeObjectAttributes(&ObjectAttributes, &FullName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); /* Check if we can create the hive */ if ((CreateAllowed) && !(CmpShareSystemHives)) { /* Open only or create */ CreateDisposition = FILE_OPEN_IF; } else { /* Open only */ CreateDisposition = FILE_OPEN; } /* Setup the flags */ // FIXME : FILE_OPEN_FOR_BACKUP_INTENT is unimplemented and breaks 3rd stage boot IoFlags = //FILE_OPEN_FOR_BACKUP_INTENT | FILE_NO_COMPRESSION | FILE_RANDOM_ACCESS | (NoBuffering ? FILE_NO_INTERMEDIATE_BUFFERING : 0); /* Set share and access modes */ if ((CmpMiniNTBoot) && (CmpShareSystemHives)) { /* We're on Live CD or otherwise sharing */ DesiredAccess = FILE_READ_DATA; ShareMode = FILE_SHARE_READ; } else { /* We want to write exclusively */ ShareMode = 0; DesiredAccess = FILE_READ_DATA | FILE_WRITE_DATA; } /* Default attributes */ AttributeFlags = FILE_ATTRIBUTE_NORMAL; /* Now create the file */ Status = ZwCreateFile(Primary, DesiredAccess | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, NULL, AttributeFlags, ShareMode, CreateDisposition, FILE_SYNCHRONOUS_IO_NONALERT | IoFlags, NULL, 0); /* Check if anything failed until now */ if (!NT_SUCCESS(Status)) { /* Close handles and free buffers */ if (NameBuffer) ExFreePoolWithTag(NameBuffer, TAG_CM); ObDereferenceObject(Event); ZwClose(EventHandle); DPRINT1("ZwCreateFile failed : %lx.\n", Status); *Primary = NULL; return Status; } if (MarkAsSystemHive) { /* We opened it, mark it as a system hive */ Status = ZwFsControlFile(*Primary, EventHandle, NULL, NULL, &IoStatusBlock, FSCTL_MARK_AS_SYSTEM_HIVE, NULL, 0, NULL, 0); if (Status == STATUS_PENDING) { /* Wait for completion */ KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); Status = IoStatusBlock.Status; } /* If we don't support it, ignore the failure */ if (Status == STATUS_INVALID_DEVICE_REQUEST) Status = STATUS_SUCCESS; if (!NT_SUCCESS(Status)) { /* Close handles and free buffers */ if (NameBuffer) ExFreePoolWithTag(NameBuffer, TAG_CM); ObDereferenceObject(Event); ZwClose(EventHandle); ZwClose(*Primary); *Primary = NULL; return Status; } } /* Disable compression */ CompressionState = 0; Status = ZwFsControlFile(*Primary, EventHandle, NULL, NULL, &IoStatusBlock, FSCTL_SET_COMPRESSION, &CompressionState, sizeof(CompressionState), NULL, 0); if (Status == STATUS_PENDING) { /* Wait for completion */ KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); } /* Get the disposition */ *PrimaryDisposition = (ULONG)IoStatusBlock.Information; if (IoStatusBlock.Information != FILE_CREATED) { /* Check how large the file is */ Status = ZwQueryInformationFile(*Primary, &IoStatusBlock, &FileInformation, sizeof(FileInformation), FileStandardInformation); if (NT_SUCCESS(Status)) { /* Check if it's 0 bytes */ if (!FileInformation.EndOfFile.QuadPart) { /* Assume it's a new file */ *PrimaryDisposition = FILE_CREATED; } } } /* Check if the caller wants cluster size returned */ if (ClusterSize) { /* Query it */ Status = ZwQueryVolumeInformationFile(*Primary, &IoStatusBlock, &FsSizeInformation, sizeof(FsSizeInformation), FileFsSizeInformation); if (!NT_SUCCESS(Status)) { /* Close handles and free buffers */ if (NameBuffer) ExFreePoolWithTag(NameBuffer, TAG_CM); ObDereferenceObject(Event); ZwClose(EventHandle); return Status; } /* Check if the sector size is invalid */ if (FsSizeInformation.BytesPerSector > HBLOCK_SIZE) { /* Close handles and free buffers */ if (NameBuffer) ExFreePoolWithTag(NameBuffer, TAG_CM); ObDereferenceObject(Event); ZwClose(EventHandle); return STATUS_CANNOT_LOAD_REGISTRY_FILE; } /* Return cluster size */ *ClusterSize = max(1, FsSizeInformation.BytesPerSector / HSECTOR_SIZE); } /* Check if we don't need to create a log file */ if (!Extension) { /* We're done, close handles */ ObDereferenceObject(Event); ZwClose(EventHandle); return STATUS_SUCCESS; } /* Check if we can create the hive */ CreateDisposition = CmpShareSystemHives ? FILE_OPEN : FILE_OPEN_IF; if (*PrimaryDisposition == FILE_CREATED) { /* Over-write the existing log file, since this is a new hive */ CreateDisposition = FILE_SUPERSEDE; } /* Setup the name */ RtlInitUnicodeString(&ExtensionName, Extension); RtlAppendUnicodeStringToString(&FullName, &ExtensionName); /* Initialize the attributes */ InitializeObjectAttributes(&ObjectAttributes, &FullName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); /* Setup the flags */ IoFlags = FILE_NO_COMPRESSION | FILE_NO_INTERMEDIATE_BUFFERING; /* Check if this is a log file */ if (!_wcsnicmp(Extension, L".log", 4)) { /* Hide log files */ AttributeFlags |= FILE_ATTRIBUTE_HIDDEN; } /* Now create the file */ Status = ZwCreateFile(Log, DesiredAccess, &ObjectAttributes, &IoStatusBlock, NULL, AttributeFlags, ShareMode, CreateDisposition, IoFlags, NULL, 0); if ((NT_SUCCESS(Status)) && (MarkAsSystemHive)) { /* We opened it, mark it as a system hive */ Status = ZwFsControlFile(*Log, EventHandle, NULL, NULL, &IoStatusBlock, FSCTL_MARK_AS_SYSTEM_HIVE, NULL, 0, NULL, 0); if (Status == STATUS_PENDING) { /* Wait for completion */ KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); Status = IoStatusBlock.Status; } /* If we don't support it, ignore the failure */ if (Status == STATUS_INVALID_DEVICE_REQUEST) Status = STATUS_SUCCESS; /* If we failed, close the handle */ if (!NT_SUCCESS(Status)) ZwClose(*Log); } /* Check if anything failed until now */ if (!NT_SUCCESS(Status)) { /* Clear the handle */ *Log = NULL; } else { /* Disable compression */ Status = ZwFsControlFile(*Log, EventHandle, NULL, NULL, &IoStatusBlock, FSCTL_SET_COMPRESSION, &CompressionState, sizeof(CompressionState), NULL, 0); if (Status == STATUS_PENDING) { /* Wait for completion */ KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL); } /* Return the disposition */ *LogDisposition = (ULONG)IoStatusBlock.Information; } /* We're done, close handles and free buffers */ if (NameBuffer) ExFreePoolWithTag(NameBuffer, TAG_CM); ObDereferenceObject(Event); ZwClose(EventHandle); return STATUS_SUCCESS; }
/*++ * @name CsrSbApiPortInitialize * * The CsrSbApiPortInitialize routine initializes the LPC Port used for * communications with the Session Manager (SM) and initializes the static * thread that will handle connection requests and APIs. * * @param None * * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise. * * @remarks None. * *--*/ NTSTATUS NTAPI CsrSbApiPortInitialize(VOID) { ULONG Size; PSECURITY_DESCRIPTOR PortSd; OBJECT_ATTRIBUTES ObjectAttributes; NTSTATUS Status; HANDLE hRequestThread; CLIENT_ID ClientId; /* Calculate how much space we'll need for the Port Name */ Size = CsrDirectoryName.Length + sizeof(SB_PORT_NAME) + sizeof(WCHAR); /* Create the buffer for it */ CsrSbApiPortName.Buffer = RtlAllocateHeap(CsrHeap, 0, Size); if (!CsrSbApiPortName.Buffer) return STATUS_NO_MEMORY; /* Setup the rest of the empty string */ CsrSbApiPortName.Length = 0; CsrSbApiPortName.MaximumLength = (USHORT)Size; /* Now append the full port name */ RtlAppendUnicodeStringToString(&CsrSbApiPortName, &CsrDirectoryName); RtlAppendUnicodeToString(&CsrSbApiPortName, UNICODE_PATH_SEP); RtlAppendUnicodeToString(&CsrSbApiPortName, SB_PORT_NAME); if (CsrDebug & 2) DPRINT1("CSRSS: Creating %wZ port and associated thread\n", &CsrSbApiPortName); /* Create Security Descriptor for this Port */ Status = CsrCreateLocalSystemSD(&PortSd); if (!NT_SUCCESS(Status)) return Status; /* Initialize the Attributes */ InitializeObjectAttributes(&ObjectAttributes, &CsrSbApiPortName, 0, NULL, PortSd); /* Create the Port Object */ Status = NtCreatePort(&CsrSbApiPort, &ObjectAttributes, sizeof(SB_CONNECTION_INFO), sizeof(SB_API_MSG), 32 * sizeof(SB_API_MSG)); if (PortSd) RtlFreeHeap(CsrHeap, 0, PortSd); if (NT_SUCCESS(Status)) { /* Create the Thread to handle the API Requests */ Status = RtlCreateUserThread(NtCurrentProcess(), NULL, TRUE, 0, 0, 0, (PVOID)CsrSbApiRequestThread, NULL, &hRequestThread, &ClientId); if (NT_SUCCESS(Status)) { /* Add it as a Static Server Thread */ CsrSbApiRequestThreadPtr = CsrAddStaticServerThread(hRequestThread, &ClientId, 0); /* Activate it */ Status = NtResumeThread(hRequestThread, NULL); } } return Status; }
BOOLEAN RemoveModule(void) { UNICODE_STRING usKeyName, usServiceName; ANSI_STRING asServiceName; BOOLEAN fRet = TRUE; HANDLE hKey; OBJECT_ATTRIBUTES objAttr; NTSTATUS status; IO_STATUS_BLOCK ioStatusBlock; UNICODE_STRING usServicesKey; UNICODE_STRING usEnumKeyName; RtlInitUnicodeString(&usServicesKey, L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\"); RtlInitUnicodeString(&usEnumKeyName, L"\\Enum"); RtlInitUnicodeString(&usKeyName, NULL); DBGOUT(("ServiceName ANSI: %s", g_ServiceName)); RtlInitAnsiString(&asServiceName, g_ServiceName); status = RtlAnsiStringToUnicodeString(&usServiceName, &asServiceName, TRUE); if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: FAILURE in RtlAnsiStringToUnicodeString %08x!", status)); fRet = FALSE; goto end; } DBGOUT(("ServiceName UNICODE: %S", usServiceName.Buffer)); // Remove our registry entries usKeyName.MaximumLength = usServicesKey.Length + usServiceName.Length + usEnumKeyName.Length + sizeof(WCHAR); usKeyName.Buffer = ExAllocatePoolWithTag(NonPagedPool, usKeyName.MaximumLength, HELPER_POOL_TAG); RtlZeroMemory(usKeyName.Buffer, usKeyName.MaximumLength); DBGOUT(("KeyName Length: %d", usKeyName.MaximumLength)); RtlCopyUnicodeString(&usKeyName, &usServicesKey); status = RtlAppendUnicodeStringToString(&usKeyName, &usServiceName); if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: FAILURE in RtlAppendUnicodeStringToString %08x!", status)); fRet = FALSE; goto end; } status = RtlAppendUnicodeStringToString(&usKeyName, &usEnumKeyName); if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: FAILURE in RtlAppendUnicodeStringToString %08x!", status)); fRet = FALSE; goto end; } InitializeObjectAttributes(&objAttr, &usKeyName,0,NULL,NULL); DBGOUT(("Attempting to delete reg key %S", usKeyName.Buffer)); #ifdef ENABLE_ANTIDETECTION status = s_fnZwOpenKey(&hKey, DELETE, &objAttr); #else status = ZwOpenKey(&hKey, DELETE, &objAttr); #endif if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: FAILURE in ZwOpenKey %08x!", status)); fRet = FALSE; goto end; } status = ZwDeleteKey(hKey); if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: Unable to ZwDeleteKey %08x!", status)); fRet = FALSE; goto end; } // Remove our root key entry now RtlZeroMemory(usKeyName.Buffer, usKeyName.MaximumLength); RtlCopyUnicodeString(&usKeyName, &usServicesKey); status = RtlAppendUnicodeStringToString(&usKeyName, &usServiceName); if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: FAILURE in RtlAppendUnicodeStringToString %08x!", status)); fRet = FALSE; goto end; } InitializeObjectAttributes(&objAttr, &usKeyName,0,NULL,NULL); DBGOUT(("Attempting to delete reg key %S", usKeyName.Buffer)); #ifdef ENABLE_ANTIDETECTION status = s_fnZwOpenKey(&hKey, DELETE, &objAttr); #else status = ZwOpenKey(&hKey, DELETE, &objAttr); #endif if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: FAILURE in ZwOpenKey %08x!", status)); fRet = FALSE; goto end; } status = ZwDeleteKey(hKey); if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: Unable to ZwDeleteKey %08x!", status)); fRet = FALSE; goto end; } if(!_wcsnicmp(g_ImagePath.Buffer, L"system32", 8)) { UNICODE_STRING usSysRoot; RtlInitUnicodeString(&usSysRoot, L"\\SystemRoot\\"); // Prepend \SystemRoot\ to the string ExFreePool(usKeyName.Buffer); usKeyName.MaximumLength = usSysRoot.Length + g_ImagePath.Length + sizeof(WCHAR); usKeyName.Buffer = ExAllocatePoolWithTag(NonPagedPool, usKeyName.MaximumLength, HELPER_POOL_TAG); RtlZeroMemory(usKeyName.Buffer, usKeyName.MaximumLength); RtlCopyUnicodeString(&usKeyName, &usSysRoot); status = RtlAppendUnicodeStringToString(&usKeyName, &g_ImagePath); if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: FAILURE in RtlAppendUnicodeStringToString %08x!", status)); fRet = FALSE; goto end; } InitializeObjectAttributes(&objAttr, &usKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL); } else { // Use whatever was there InitializeObjectAttributes(&objAttr, &g_ImagePath, OBJ_CASE_INSENSITIVE, NULL, NULL); } // Remove our file DBGOUT(("Removing file %S", objAttr.ObjectName->Buffer)); status = ZwCreateFile(&hKey, DELETE, &objAttr, &ioStatusBlock, (PLARGE_INTEGER)NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, FILE_DELETE_ON_CLOSE, 0, 0); if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: Unable to ZwCreateFile %08x!", status)); fRet = FALSE; goto end; } status = ZwClose(hKey); if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: Unable to ZwClose File %08x!", status)); fRet = FALSE; goto end; } end: RtlFreeUnicodeString(&usServiceName); ExFreePool(usKeyName.Buffer); return fRet; }
//在注册表子项中设置LowerFilters子项 NTSTATUS SetLowerFilters(PUNICODE_STRING szUName,ULONG uFlag) { UNICODE_STRING dst,src,ValueName; HANDLE hRegister,hSubKey; WCHAR dst_buf[256]; //初始化UNICODE_STRING字符串 RtlInitEmptyUnicodeString(&dst,dst_buf,256*sizeof(WCHAR)); //初始化src为U盘注册表位置 RtlInitUnicodeString(&src,USBSTOR); RtlCopyUnicodeString(&dst,&src); //将U盘名字追加到注册表位置末尾,为选中U盘的实际注册表位置 RtlAppendUnicodeStringToString(&dst,szUName); OBJECT_ATTRIBUTES objectAttributes; //初始化objectAttributes InitializeObjectAttributes(&objectAttributes, &dst, //文件名 OBJ_CASE_INSENSITIVE,//对大小写敏感 NULL, NULL ); //打开注册表 NTSTATUS ntStatus = ZwOpenKey( &hRegister, //返回被打开的句柄 KEY_ALL_ACCESS, //打开权限,一般都这么设置 &objectAttributes); //打开注册表成功 if (NT_SUCCESS(ntStatus)) { DbgPrint("Open register successfully\n"); } //要在注册表子项下添加LowerFilters的表项 RtlInitUnicodeString(&ValueName,L"LowerFilters"); //键值设为过滤类名,如果随便设一个会导致U盘连接状态但是不能查看到 PWCHAR strValue=L"UsbFilter"; ULONG ulSize; //第一次调用ZwQueryKey为了获取KEY_FULL_INFORMATION数据的长度(因为是变长的) ZwQueryKey(hRegister, KeyFullInformation, //查询类别,一般都这么设置 NULL, 0, &ulSize); //返回数据KEY_FULL_INFORMATION的长度 PKEY_FULL_INFORMATION pfi = (PKEY_FULL_INFORMATION) ExAllocatePool(PagedPool,ulSize); //第二次调用ZwQueryKey为了获取KEY_FULL_INFORMATION数据的数据 ZwQueryKey(hRegister, KeyFullInformation, pfi, //查询数据的指针 ulSize, //数据长度 &ulSize); //ZwQueryKey的作用主要就是获得某注册表究竟有多少个子项 //而ZwEnumerateKey的作用主要是针对第几个子项获取该子项的具体信息 for (ULONG i=0;i<pfi->SubKeys;i++) { //第一次调用ZwEnumerateKey为了获取KEY_BASIC_INFORMATION数据的长度 ZwEnumerateKey(hRegister, i, KeyBasicInformation, NULL, 0, &ulSize); PKEY_BASIC_INFORMATION pbi = (PKEY_BASIC_INFORMATION) ExAllocatePool(PagedPool,ulSize); //第二次调用ZwEnumerateKey为了获取KEY_BASIC_INFORMATION数据的数据 ZwEnumerateKey(hRegister, i, KeyBasicInformation, pbi, ulSize, &ulSize); UNICODE_STRING uniKeyName; //获取子项名字的长度 uniKeyName.Length = uniKeyName.MaximumLength = (USHORT)pbi->NameLength; uniKeyName.Buffer = pbi->Name; WCHAR bufTmp[256]; //初始化值 RtlInitEmptyUnicodeString(&src,bufTmp,256*sizeof(WCHAR)); RtlCopyUnicodeString(&src,&dst); UNICODE_STRING szX; RtlInitUnicodeString(&szX,L"\\"); RtlAppendUnicodeStringToString(&src,&szX), //这里就得到注册表子项名字的具体路径名,保存在src中 RtlAppendUnicodeStringToString(&src,&uniKeyName); //初始化ObjectAttributes InitializeObjectAttributes(&objectAttributes, &src, OBJ_CASE_INSENSITIVE,//对大小写敏感 NULL, NULL ); //打开注册表 ZwOpenKey( &hSubKey, KEY_ALL_ACCESS, &objectAttributes); //uFlag为0则删除注册表键值(既关写保护),否则设置注册表键值(既开写保护) if(uFlag==0) { ntStatus=ZwDeleteValueKey(hSubKey,&ValueName); } else { ntStatus=ZwSetValueKey(hSubKey,&ValueName,0,REG_SZ,strValue,wcslen(strValue)*2+2); } //成功的话 if (NT_SUCCESS(ntStatus)) { DbgPrint("Charge Value successfully\n"); } else DbgPrint("Charge Value failed!\n"); DbgPrint("The %d sub item name:%wZ\n",i,&src); //回收内存 ExFreePool(pbi); //关闭句柄 ZwClose(hSubKey); } ExFreePool(pfi); ZwClose(hRegister); return STATUS_SUCCESS; }
NTSTATUS KspReadMediaCategory( IN LPGUID Category, PKEY_VALUE_PARTIAL_INFORMATION *OutInformation) { UNICODE_STRING MediaPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\MediaCategories\\"); UNICODE_STRING Name = RTL_CONSTANT_STRING(L"Name"); UNICODE_STRING GuidString, Path; NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE hKey; ULONG Size; PKEY_VALUE_PARTIAL_INFORMATION KeyInfo; /* convert the guid to string */ Status = RtlStringFromGUID(Category, &GuidString); if (!NT_SUCCESS(Status)) return Status; /* allocate buffer for the registry key */ Path.Length = 0; Path.MaximumLength = MediaPath.MaximumLength + GuidString.MaximumLength; Path.Buffer = AllocateItem(NonPagedPool, Path.MaximumLength); if (!Path.Buffer) { /* not enough memory */ RtlFreeUnicodeString(&GuidString); return STATUS_INSUFFICIENT_RESOURCES; } RtlAppendUnicodeStringToString(&Path, &MediaPath); RtlAppendUnicodeStringToString(&Path, &GuidString); /* free guid string */ RtlFreeUnicodeString(&GuidString); /* initialize object attributes */ InitializeObjectAttributes(&ObjectAttributes, &Path, OBJ_CASE_INSENSITIVE, NULL, NULL); /* open the key */ Status = ZwOpenKey(&hKey, GENERIC_READ, &ObjectAttributes); DPRINT("ZwOpenKey() status 0x%08lx %wZ\n", Status, &Path); /* free path buffer */ FreeItem(Path.Buffer); /* check for success */ if (!NT_SUCCESS(Status)) { DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status); return Status; } /* query the name size */ Status = ZwQueryValueKey(hKey, &Name, KeyValuePartialInformation, NULL, 0, &Size); if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) { /* failed to query for name key */ ZwClose(hKey); return Status; } /* allocate buffer to read key info */ KeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION) AllocateItem(NonPagedPool, Size); if (!KeyInfo) { /* not enough memory */ ZwClose(hKey); return STATUS_INSUFFICIENT_RESOURCES; } /* now read the info */ Status = ZwQueryValueKey(hKey, &Name, KeyValuePartialInformation, (PVOID)KeyInfo, Size, &Size); /* close the key */ ZwClose(hKey); if (!NT_SUCCESS(Status)) { /* failed to read key */ FreeItem(KeyInfo); return Status; } /* store key information */ *OutInformation = KeyInfo; return Status; }
NTSTATUS IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode, PWCHAR Level1Key, PWCHAR Level2Key) { NTSTATUS Status; ULONG Disposition; HANDLE PnpMgrLevel1, PnpMgrLevel2, ResourceMapKey; UNICODE_STRING KeyName; OBJECT_ATTRIBUTES ObjectAttributes; RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP"); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, 0, NULL); Status = ZwCreateKey(&ResourceMapKey, KEY_ALL_ACCESS, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, &Disposition); if (!NT_SUCCESS(Status)) return Status; RtlInitUnicodeString(&KeyName, Level1Key); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, ResourceMapKey, NULL); Status = ZwCreateKey(&PnpMgrLevel1, KEY_ALL_ACCESS, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, &Disposition); ZwClose(ResourceMapKey); if (!NT_SUCCESS(Status)) return Status; RtlInitUnicodeString(&KeyName, Level2Key); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, PnpMgrLevel1, NULL); Status = ZwCreateKey(&PnpMgrLevel2, KEY_ALL_ACCESS, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, &Disposition); ZwClose(PnpMgrLevel1); if (!NT_SUCCESS(Status)) return Status; if (DeviceNode->ResourceList) { UNICODE_STRING NameU; UNICODE_STRING RawSuffix, TranslatedSuffix; ULONG OldLength = 0; ASSERT(DeviceNode->ResourceListTranslated); RtlInitUnicodeString(&TranslatedSuffix, L".Translated"); RtlInitUnicodeString(&RawSuffix, L".Raw"); Status = IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject, DevicePropertyPhysicalDeviceObjectName, 0, NULL, &OldLength); if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) { ASSERT(OldLength); NameU.Buffer = ExAllocatePool(PagedPool, OldLength + TranslatedSuffix.Length); if (!NameU.Buffer) { ZwClose(PnpMgrLevel2); return STATUS_INSUFFICIENT_RESOURCES; } NameU.Length = 0; NameU.MaximumLength = (USHORT)OldLength + TranslatedSuffix.Length; Status = IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject, DevicePropertyPhysicalDeviceObjectName, NameU.MaximumLength, NameU.Buffer, &OldLength); if (!NT_SUCCESS(Status)) { ZwClose(PnpMgrLevel2); ExFreePool(NameU.Buffer); return Status; } } else if (!NT_SUCCESS(Status)) { /* Some failure */ ZwClose(PnpMgrLevel2); return Status; } else { /* This should never happen */ ASSERT(FALSE); } NameU.Length = (USHORT)OldLength; RtlAppendUnicodeStringToString(&NameU, &RawSuffix); Status = ZwSetValueKey(PnpMgrLevel2, &NameU, 0, REG_RESOURCE_LIST, DeviceNode->ResourceList, PnpDetermineResourceListSize(DeviceNode->ResourceList)); if (!NT_SUCCESS(Status)) { ZwClose(PnpMgrLevel2); ExFreePool(NameU.Buffer); return Status; } /* "Remove" the suffix by setting the length back to what it used to be */ NameU.Length = (USHORT)OldLength; RtlAppendUnicodeStringToString(&NameU, &TranslatedSuffix); Status = ZwSetValueKey(PnpMgrLevel2, &NameU, 0, REG_RESOURCE_LIST, DeviceNode->ResourceListTranslated, PnpDetermineResourceListSize(DeviceNode->ResourceListTranslated)); ZwClose(PnpMgrLevel2); ExFreePool(NameU.Buffer); if (!NT_SUCCESS(Status)) return Status; } else { ZwClose(PnpMgrLevel2); } return STATUS_SUCCESS; }
static NTSTATUS XenM2BPdoQueryId(PXENM2B_PDO_EXTENSION pPdoExt, PIRP pIrp) { PIO_STACK_LOCATION pIrpStack; PWCHAR pBuffer; UNICODE_STRING Id; ULONG Type; size_t Length; NTSTATUS Status; pIrpStack = IoGetCurrentIrpStackLocation(pIrp); switch (pIrpStack->Parameters.QueryId.IdType) { case BusQueryInstanceID: TraceDebug(("%s: BusQueryInstanceID\n", __FUNCTION__)); break; case BusQueryDeviceID: TraceDebug(("%s: BusQueryDeviceID\n", __FUNCTION__)); break; case BusQueryHardwareIDs: TraceDebug(("%s: BusQueryHardwareIDs\n", __FUNCTION__)); break; default: pIrp->IoStatus.Information = 0; return STATUS_NOT_SUPPORTED; } pBuffer = ExAllocatePoolWithTag(PagedPool, XENM2B_MAX_DEVID_LENGTH, XENM2B_POOL_TAG); if (pBuffer == NULL) return STATUS_INSUFFICIENT_RESOURCES; RtlZeroMemory(pBuffer, XENM2B_MAX_DEVID_LENGTH); Id.Buffer = pBuffer; Id.MaximumLength = XENM2B_MAX_DEVID_LENGTH; Id.Length = 0; switch (pIrpStack->Parameters.QueryId.IdType) { case BusQueryInstanceID: Type = REG_SZ; RtlAppendUnicodeStringToString(&Id, &pPdoExt->InstanceID); break; case BusQueryDeviceID: Type = REG_SZ; RtlAppendUnicodeToString(&Id, L"XENM2B\\DEVICE"); break; case BusQueryHardwareIDs: Type = REG_MULTI_SZ; RtlAppendUnicodeToString(&Id, L"XENM2B\\DEVICE"); Id.Buffer += Id.Length/2; Id.Buffer++; // past terminator Id.MaximumLength = Id.MaximumLength - Id.Length; Id.MaximumLength -= sizeof(WCHAR); Id.Length = 0; RtlAppendUnicodeToString(&Id, L"XENDEVICE"); break; default: Type = REG_NONE; ASSERT(FALSE); break; } Id.Buffer = pBuffer; Id.MaximumLength = XENM2B_MAX_DEVID_LENGTH; Id.Length = 0; switch (Type) { case REG_SZ: TraceDebug(("%s: %ws\n", __FUNCTION__, Id.Buffer)); break; case REG_MULTI_SZ: do { TraceDebug(("%s: - %ws\n", __FUNCTION__, Id.Buffer)); Id.Buffer += wcslen(Id.Buffer); Id.Buffer++; } while (*Id.Buffer != L'\0'); break; default: ASSERT(FALSE); break; } pIrp->IoStatus.Information = (ULONG_PTR)pBuffer; return STATUS_SUCCESS; }
PPRIMARY_SESSION PrimarySession_Create ( IN PIRP_CONTEXT IrpContext, IN PVOLUME_DEVICE_OBJECT VolDo, IN PSESSION_INFORMATION SessionInformation, IN PIRP Irp ) { PPRIMARY_SESSION primarySession; OBJECT_ATTRIBUTES objectAttributes; NTSTATUS status; LARGE_INTEGER timeOut; ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL ); VolDo_Reference( VolDo ); primarySession = FsRtlAllocatePoolWithTag( NonPagedPool, sizeof(PRIMARY_SESSION), NDFAT_ALLOC_TAG ); if (primarySession == NULL) { ASSERT( NDASFAT_INSUFFICIENT_RESOURCES ); VolDo_Dereference( VolDo ); return NULL; } try { RtlZeroMemory( primarySession, sizeof(PRIMARY_SESSION) ); primarySession->Flags = PRIMARY_SESSION_FLAG_INITIALIZING; primarySession->ReferenceCount = 1; primarySession->VolDo = VolDo; ExInitializeFastMutex( &primarySession->FastMutex ) InitializeListHead( &primarySession->ListEntry ); primarySession->NetdiskPartitionInformation = SessionInformation->NetdiskPartitionInformation; RtlInitEmptyUnicodeString( &primarySession->NetdiskPartitionInformation.VolumeName, primarySession->NetdiskPartitionInformation.VolumeNameBuffer, sizeof(primarySession->NetdiskPartitionInformation.VolumeNameBuffer) ); if (RtlAppendUnicodeStringToString( &primarySession->NetdiskPartitionInformation.VolumeName, &SessionInformation->NetdiskPartitionInformation.VolumeName) != STATUS_SUCCESS) { ASSERT( NDASFAT_UNEXPECTED ); } ASSERT( primarySession->NetdiskPartitionInformation.VolumeName.Buffer == primarySession->NetdiskPartitionInformation.VolumeNameBuffer ); primarySession->ConnectionFileHandle = SessionInformation->ConnectionFileHandle; primarySession->ConnectionFileObject = SessionInformation->ConnectionFileObject; primarySession->RemoteAddress = SessionInformation->RemoteAddress; primarySession->IsLocalAddress = SessionInformation->IsLocalAddress; primarySession->Irp = Irp; primarySession->SessionContext = SessionInformation->SessionContext; primarySession->SessionContext.PrimaryMaxDataSize = DEFAULT_NDAS_MAX_DATA_SIZE; //SessionInformation->PrimaryMaxDataSize; primarySession->SessionContext.SecondaryMaxDataSize = DEFAULT_NDAS_MAX_DATA_SIZE; // SessionInformation->SecondaryMaxDataSize; DebugTrace2( 0, Dbg2, ("primarySession->ConnectionFileHandle = %x " "primarySession->SessionContext.PrimaryMaxDataSize = %x primarySession->SessionContext.SecondaryMaxDataSize = %x\n", primarySession->ConnectionFileHandle, primarySession->SessionContext.PrimaryMaxDataSize, primarySession->SessionContext.SecondaryMaxDataSize) ); KeInitializeEvent( &primarySession->ReadyEvent, NotificationEvent, FALSE ); InitializeListHead( &primarySession->RequestQueue ); KeInitializeSpinLock( &primarySession->RequestQSpinLock ); KeInitializeEvent( &primarySession->RequestEvent, NotificationEvent, FALSE ); primarySession->ThreadHandle = 0; primarySession->ThreadObject = NULL; primarySession->Thread.TdiReceiveContext.Irp = NULL; KeInitializeEvent( &primarySession->Thread.TdiReceiveContext.CompletionEvent, NotificationEvent, FALSE ); InitializeObjectAttributes( &objectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL ); primarySession->Thread.SessionState = SESSION_TREE_CONNECT; ExInterlockedInsertTailList( &VolDo->PrimarySessionQueue, &primarySession->ListEntry, &VolDo->PrimarySessionQSpinLock ); status = PsCreateSystemThread( &primarySession->ThreadHandle, THREAD_ALL_ACCESS, &objectAttributes, NULL, NULL, PrimarySessionThreadProc, primarySession ); if (!NT_SUCCESS(status)) { leave; } status = ObReferenceObjectByHandle( primarySession->ThreadHandle, FILE_READ_DATA, NULL, KernelMode, &primarySession->ThreadObject, NULL ); if (!NT_SUCCESS(status)) { leave; } timeOut.QuadPart = -NDASFAT_TIME_OUT; status = KeWaitForSingleObject( &primarySession->ReadyEvent, Executive, KernelMode, FALSE, &timeOut ); if (!NT_SUCCESS(status)) { leave; } KeClearEvent( &primarySession->ReadyEvent ); DebugTrace2( 0, Dbg, ("PrimarySession_Create: The primary thread are ready\n") ); DebugTrace2( 0, Dbg2, ("Fat PrimarySession_Create: primarySession = %p\n", primarySession) ); } finally { if (AbnormalTermination()) { status = IrpContext->ExceptionStatus; } if (!NT_SUCCESS(status)) { ASSERT( NDASFAT_UNEXPECTED ); PrimarySession_Close( primarySession ); primarySession = NULL; } } return primarySession; }
/*++ * @name IoGetDeviceInterfaces * @implemented * * Returns a list of device interfaces of a particular device interface class. * Documented in WDK * * @param InterfaceClassGuid * Points to a class GUID specifying the device interface class * * @param PhysicalDeviceObject * Points to an optional PDO that narrows the search to only the * device interfaces of the device represented by the PDO * * @param Flags * Specifies flags that modify the search for device interfaces. The * DEVICE_INTERFACE_INCLUDE_NONACTIVE flag specifies that the list of * returned symbolic links should contain also disabled device * interfaces in addition to the enabled ones. * * @param SymbolicLinkList * Points to a character pointer that is filled in on successful return * with a list of unicode strings identifying the device interfaces * that match the search criteria. The newly allocated buffer contains * a list of symbolic link names. Each unicode string in the list is * null-terminated; the end of the whole list is marked by an additional * NULL. The caller is responsible for freeing the buffer (ExFreePool) * when it is no longer needed. * If no device interfaces match the search criteria, this routine * returns STATUS_SUCCESS and the string contains a single NULL * character. * * @return Usual NTSTATUS * * @remarks None * *--*/ NTSTATUS NTAPI IoGetDeviceInterfaces(IN CONST GUID *InterfaceClassGuid, IN PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL, IN ULONG Flags, OUT PWSTR *SymbolicLinkList) { UNICODE_STRING Control = RTL_CONSTANT_STRING(L"Control"); UNICODE_STRING SymbolicLink = RTL_CONSTANT_STRING(L"SymbolicLink"); HANDLE InterfaceKey = INVALID_HANDLE_VALUE; HANDLE DeviceKey = INVALID_HANDLE_VALUE; HANDLE ReferenceKey = INVALID_HANDLE_VALUE; HANDLE ControlKey = INVALID_HANDLE_VALUE; PKEY_BASIC_INFORMATION DeviceBi = NULL; PKEY_BASIC_INFORMATION ReferenceBi = NULL; PKEY_VALUE_PARTIAL_INFORMATION bip = NULL; PKEY_VALUE_PARTIAL_INFORMATION PartialInfo; UNICODE_STRING KeyName; OBJECT_ATTRIBUTES ObjectAttributes; BOOLEAN FoundRightPDO = FALSE; ULONG i = 0, j, Size, NeededLength, ActualLength, LinkedValue; UNICODE_STRING ReturnBuffer = { 0, 0, NULL }; NTSTATUS Status; PAGED_CODE(); Status = IopOpenInterfaceKey(InterfaceClassGuid, KEY_ENUMERATE_SUB_KEYS, &InterfaceKey); if (!NT_SUCCESS(Status)) { DPRINT("IopOpenInterfaceKey() failed with status 0x%08lx\n", Status); goto cleanup; } /* Enumerate subkeys (i.e. the different device objects) */ while (TRUE) { Status = ZwEnumerateKey( InterfaceKey, i, KeyBasicInformation, NULL, 0, &Size); if (Status == STATUS_NO_MORE_ENTRIES) { break; } else if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) { DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); goto cleanup; } DeviceBi = ExAllocatePool(PagedPool, Size); if (!DeviceBi) { DPRINT("ExAllocatePool() failed\n"); Status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } Status = ZwEnumerateKey( InterfaceKey, i++, KeyBasicInformation, DeviceBi, Size, &Size); if (!NT_SUCCESS(Status)) { DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); goto cleanup; } /* Open device key */ KeyName.Length = KeyName.MaximumLength = (USHORT)DeviceBi->NameLength; KeyName.Buffer = DeviceBi->Name; InitializeObjectAttributes( &ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, InterfaceKey, NULL); Status = ZwOpenKey( &DeviceKey, KEY_ENUMERATE_SUB_KEYS, &ObjectAttributes); if (!NT_SUCCESS(Status)) { DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); goto cleanup; } if (PhysicalDeviceObject) { /* Check if we are on the right physical device object, * by reading the DeviceInstance string */ DPRINT1("PhysicalDeviceObject != NULL. Case not implemented.\n"); //FoundRightPDO = TRUE; Status = STATUS_NOT_IMPLEMENTED; goto cleanup; } /* Enumerate subkeys (ie the different reference strings) */ j = 0; while (TRUE) { Status = ZwEnumerateKey( DeviceKey, j, KeyBasicInformation, NULL, 0, &Size); if (Status == STATUS_NO_MORE_ENTRIES) { break; } else if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) { DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); goto cleanup; } ReferenceBi = ExAllocatePool(PagedPool, Size); if (!ReferenceBi) { DPRINT("ExAllocatePool() failed\n"); Status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } Status = ZwEnumerateKey( DeviceKey, j++, KeyBasicInformation, ReferenceBi, Size, &Size); if (!NT_SUCCESS(Status)) { DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); goto cleanup; } KeyName.Length = KeyName.MaximumLength = (USHORT)ReferenceBi->NameLength; KeyName.Buffer = ReferenceBi->Name; if (RtlEqualUnicodeString(&KeyName, &Control, TRUE)) { /* Skip Control subkey */ goto NextReferenceString; } /* Open reference key */ InitializeObjectAttributes( &ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, DeviceKey, NULL); Status = ZwOpenKey( &ReferenceKey, KEY_QUERY_VALUE, &ObjectAttributes); if (!NT_SUCCESS(Status)) { DPRINT("ZwOpenKey() failed with status 0x%08lx\n", Status); goto cleanup; } if (!(Flags & DEVICE_INTERFACE_INCLUDE_NONACTIVE)) { /* We have to check if the interface is enabled, by * reading the Linked value in the Control subkey */ InitializeObjectAttributes( &ObjectAttributes, &Control, OBJ_CASE_INSENSITIVE, ReferenceKey, NULL); Status = ZwOpenKey( &ControlKey, KEY_QUERY_VALUE, &ObjectAttributes); if (Status == STATUS_OBJECT_NAME_NOT_FOUND) { /* That's OK. The key doesn't exist (yet) because * the interface is not activated. */ goto NextReferenceString; } else if (!NT_SUCCESS(Status)) { DPRINT1("ZwOpenKey() failed with status 0x%08lx\n", Status); goto cleanup; } RtlInitUnicodeString(&KeyName, L"Linked"); Status = ZwQueryValueKey(ControlKey, &KeyName, KeyValuePartialInformation, NULL, 0, &NeededLength); if (Status == STATUS_BUFFER_TOO_SMALL) { ActualLength = NeededLength; PartialInfo = ExAllocatePool(NonPagedPool, ActualLength); if (!PartialInfo) { Status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } Status = ZwQueryValueKey(ControlKey, &KeyName, KeyValuePartialInformation, PartialInfo, ActualLength, &NeededLength); if (!NT_SUCCESS(Status)) { DPRINT1("ZwQueryValueKey #2 failed (%x)\n", Status); ExFreePool(PartialInfo); goto cleanup; } if (PartialInfo->Type != REG_DWORD || PartialInfo->DataLength != sizeof(ULONG)) { DPRINT1("Bad registry read\n"); ExFreePool(PartialInfo); goto cleanup; } RtlCopyMemory(&LinkedValue, PartialInfo->Data, PartialInfo->DataLength); ExFreePool(PartialInfo); if (LinkedValue == 0) { /* This interface isn't active */ goto NextReferenceString; } } else { DPRINT1("ZwQueryValueKey #1 failed (%x)\n", Status); goto cleanup; } } /* Read the SymbolicLink string and add it into SymbolicLinkList */ Status = ZwQueryValueKey( ReferenceKey, &SymbolicLink, KeyValuePartialInformation, NULL, 0, &Size); if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL) { DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status); goto cleanup; } bip = ExAllocatePool(PagedPool, Size); if (!bip) { DPRINT("ExAllocatePool() failed\n"); Status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } Status = ZwQueryValueKey( ReferenceKey, &SymbolicLink, KeyValuePartialInformation, bip, Size, &Size); if (!NT_SUCCESS(Status)) { DPRINT("ZwQueryValueKey() failed with status 0x%08lx\n", Status); goto cleanup; } else if (bip->Type != REG_SZ) { DPRINT("Unexpected registry type 0x%lx (expected 0x%lx)\n", bip->Type, REG_SZ); Status = STATUS_UNSUCCESSFUL; goto cleanup; } else if (bip->DataLength < 5 * sizeof(WCHAR)) { DPRINT("Registry string too short (length %lu, expected %lu at least)\n", bip->DataLength, 5 * sizeof(WCHAR)); Status = STATUS_UNSUCCESSFUL; goto cleanup; } KeyName.Length = KeyName.MaximumLength = (USHORT)bip->DataLength; KeyName.Buffer = (PWSTR)bip->Data; /* Fixup the prefix (from "\\?\") */ RtlCopyMemory(KeyName.Buffer, L"\\??\\", 4 * sizeof(WCHAR)); /* Add new symbolic link to symbolic link list */ if (ReturnBuffer.Length + KeyName.Length + sizeof(WCHAR) > ReturnBuffer.MaximumLength) { PWSTR NewBuffer; ReturnBuffer.MaximumLength = (USHORT)max(2 * ReturnBuffer.MaximumLength, (USHORT)(ReturnBuffer.Length + KeyName.Length + 2 * sizeof(WCHAR))); NewBuffer = ExAllocatePool(PagedPool, ReturnBuffer.MaximumLength); if (!NewBuffer) { DPRINT("ExAllocatePool() failed\n"); Status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } if (ReturnBuffer.Buffer) { RtlCopyMemory(NewBuffer, ReturnBuffer.Buffer, ReturnBuffer.Length); ExFreePool(ReturnBuffer.Buffer); } ReturnBuffer.Buffer = NewBuffer; } DPRINT("Adding symbolic link %wZ\n", &KeyName); Status = RtlAppendUnicodeStringToString(&ReturnBuffer, &KeyName); if (!NT_SUCCESS(Status)) { DPRINT("RtlAppendUnicodeStringToString() failed with status 0x%08lx\n", Status); goto cleanup; } /* RtlAppendUnicodeStringToString added a NULL at the end of the * destination string, but didn't increase the Length field. * Do it for it. */ ReturnBuffer.Length += sizeof(WCHAR); NextReferenceString: ExFreePool(ReferenceBi); ReferenceBi = NULL; if (bip) ExFreePool(bip); bip = NULL; if (ReferenceKey != INVALID_HANDLE_VALUE) { ZwClose(ReferenceKey); ReferenceKey = INVALID_HANDLE_VALUE; } if (ControlKey != INVALID_HANDLE_VALUE) { ZwClose(ControlKey); ControlKey = INVALID_HANDLE_VALUE; } } if (FoundRightPDO) { /* No need to go further, as we already have found what we searched */ break; } ExFreePool(DeviceBi); DeviceBi = NULL; ZwClose(DeviceKey); DeviceKey = INVALID_HANDLE_VALUE; } /* Add final NULL to ReturnBuffer */ NT_ASSERT(ReturnBuffer.Length <= ReturnBuffer.MaximumLength); if (ReturnBuffer.Length >= ReturnBuffer.MaximumLength) { PWSTR NewBuffer; ReturnBuffer.MaximumLength += sizeof(WCHAR); NewBuffer = ExAllocatePool(PagedPool, ReturnBuffer.MaximumLength); if (!NewBuffer) { DPRINT("ExAllocatePool() failed\n"); Status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } if (ReturnBuffer.Buffer) { RtlCopyMemory(NewBuffer, ReturnBuffer.Buffer, ReturnBuffer.Length); ExFreePool(ReturnBuffer.Buffer); } ReturnBuffer.Buffer = NewBuffer; } ReturnBuffer.Buffer[ReturnBuffer.Length / sizeof(WCHAR)] = UNICODE_NULL; *SymbolicLinkList = ReturnBuffer.Buffer; Status = STATUS_SUCCESS; cleanup: if (!NT_SUCCESS(Status) && ReturnBuffer.Buffer) ExFreePool(ReturnBuffer.Buffer); if (InterfaceKey != INVALID_HANDLE_VALUE) ZwClose(InterfaceKey); if (DeviceKey != INVALID_HANDLE_VALUE) ZwClose(DeviceKey); if (ReferenceKey != INVALID_HANDLE_VALUE) ZwClose(ReferenceKey); if (ControlKey != INVALID_HANDLE_VALUE) ZwClose(ControlKey); if (DeviceBi) ExFreePool(DeviceBi); if (ReferenceBi) ExFreePool(ReferenceBi); if (bip) ExFreePool(bip); return Status; }
/*++ * @name IoRegisterDeviceInterface * @implemented * * Registers a device interface class, if it has not been previously registered, * and creates a new instance of the interface class, which a driver can * subsequently enable for use by applications or other system components. * Documented in WDK. * * @param PhysicalDeviceObject * Points to an optional PDO that narrows the search to only the * device interfaces of the device represented by the PDO * * @param InterfaceClassGuid * Points to a class GUID specifying the device interface class * * @param ReferenceString * Optional parameter, pointing to a unicode string. For a full * description of this rather rarely used param (usually drivers * pass NULL here) see WDK * * @param SymbolicLinkName * Pointer to the resulting unicode string * * @return Usual NTSTATUS * * @remarks Must be called at IRQL = PASSIVE_LEVEL in the context of a * system thread * *--*/ NTSTATUS NTAPI IoRegisterDeviceInterface(IN PDEVICE_OBJECT PhysicalDeviceObject, IN CONST GUID *InterfaceClassGuid, IN PUNICODE_STRING ReferenceString OPTIONAL, OUT PUNICODE_STRING SymbolicLinkName) { PUNICODE_STRING InstancePath; UNICODE_STRING GuidString; UNICODE_STRING SubKeyName; UNICODE_STRING InterfaceKeyName; UNICODE_STRING BaseKeyName; UCHAR PdoNameInfoBuffer[sizeof(OBJECT_NAME_INFORMATION) + (256 * sizeof(WCHAR))]; POBJECT_NAME_INFORMATION PdoNameInfo = (POBJECT_NAME_INFORMATION)PdoNameInfoBuffer; UNICODE_STRING DeviceInstance = RTL_CONSTANT_STRING(L"DeviceInstance"); UNICODE_STRING SymbolicLink = RTL_CONSTANT_STRING(L"SymbolicLink"); HANDLE ClassKey; HANDLE InterfaceKey; HANDLE SubKey; ULONG StartIndex; OBJECT_ATTRIBUTES ObjectAttributes; ULONG i; NTSTATUS Status, SymLinkStatus; PEXTENDED_DEVOBJ_EXTENSION DeviceObjectExtension; ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); DPRINT("IoRegisterDeviceInterface(): PDO %p, RefString: %wZ\n", PhysicalDeviceObject, ReferenceString); /* Parameters must pass three border of checks */ DeviceObjectExtension = (PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension; /* 1st level: Presence of a Device Node */ if (DeviceObjectExtension->DeviceNode == NULL) { DPRINT("PhysicalDeviceObject 0x%p doesn't have a DeviceNode\n", PhysicalDeviceObject); return STATUS_INVALID_DEVICE_REQUEST; } /* 2nd level: Presence of an non-zero length InstancePath */ if (DeviceObjectExtension->DeviceNode->InstancePath.Length == 0) { DPRINT("PhysicalDeviceObject 0x%p's DOE has zero-length InstancePath\n", PhysicalDeviceObject); return STATUS_INVALID_DEVICE_REQUEST; } /* 3rd level: Optional, based on WDK documentation */ if (ReferenceString != NULL) { /* Reference string must not contain path-separator symbols */ for (i = 0; i < ReferenceString->Length / sizeof(WCHAR); i++) { if ((ReferenceString->Buffer[i] == '\\') || (ReferenceString->Buffer[i] == '/')) return STATUS_INVALID_DEVICE_REQUEST; } } Status = RtlStringFromGUID(InterfaceClassGuid, &GuidString); if (!NT_SUCCESS(Status)) { DPRINT("RtlStringFromGUID() failed with status 0x%08lx\n", Status); return Status; } /* Create Pdo name: \Device\xxxxxxxx (unnamed device) */ Status = ObQueryNameString( PhysicalDeviceObject, PdoNameInfo, sizeof(PdoNameInfoBuffer), &i); if (!NT_SUCCESS(Status)) { DPRINT("ObQueryNameString() failed with status 0x%08lx\n", Status); return Status; } ASSERT(PdoNameInfo->Name.Length); /* Create base key name for this interface: HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */ ASSERT(((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode); InstancePath = &((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode->InstancePath; BaseKeyName.Length = (USHORT)wcslen(BaseKeyString) * sizeof(WCHAR); BaseKeyName.MaximumLength = BaseKeyName.Length + GuidString.Length; BaseKeyName.Buffer = ExAllocatePool( PagedPool, BaseKeyName.MaximumLength); if (!BaseKeyName.Buffer) { DPRINT("ExAllocatePool() failed\n"); return STATUS_INSUFFICIENT_RESOURCES; } wcscpy(BaseKeyName.Buffer, BaseKeyString); RtlAppendUnicodeStringToString(&BaseKeyName, &GuidString); /* Create BaseKeyName key in registry */ InitializeObjectAttributes( &ObjectAttributes, &BaseKeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_OPENIF, NULL, /* RootDirectory */ NULL); /* SecurityDescriptor */ Status = ZwCreateKey( &ClassKey, KEY_WRITE, &ObjectAttributes, 0, /* TileIndex */ NULL, /* Class */ REG_OPTION_VOLATILE, NULL); /* Disposition */ if (!NT_SUCCESS(Status)) { DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); ExFreePool(BaseKeyName.Buffer); return Status; } /* Create key name for this interface: ##?#ACPI#PNP0501#1#{GUID} */ InterfaceKeyName.Length = 0; InterfaceKeyName.MaximumLength = 4 * sizeof(WCHAR) + /* 4 = size of ##?# */ InstancePath->Length + sizeof(WCHAR) + /* 1 = size of # */ GuidString.Length; InterfaceKeyName.Buffer = ExAllocatePool( PagedPool, InterfaceKeyName.MaximumLength); if (!InterfaceKeyName.Buffer) { DPRINT("ExAllocatePool() failed\n"); return STATUS_INSUFFICIENT_RESOURCES; } RtlAppendUnicodeToString(&InterfaceKeyName, L"##?#"); StartIndex = InterfaceKeyName.Length / sizeof(WCHAR); RtlAppendUnicodeStringToString(&InterfaceKeyName, InstancePath); for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++) { if (InterfaceKeyName.Buffer[StartIndex + i] == '\\') InterfaceKeyName.Buffer[StartIndex + i] = '#'; } RtlAppendUnicodeToString(&InterfaceKeyName, L"#"); RtlAppendUnicodeStringToString(&InterfaceKeyName, &GuidString); /* Create the interface key in registry */ InitializeObjectAttributes( &ObjectAttributes, &InterfaceKeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE | OBJ_OPENIF, ClassKey, NULL); /* SecurityDescriptor */ Status = ZwCreateKey( &InterfaceKey, KEY_WRITE, &ObjectAttributes, 0, /* TileIndex */ NULL, /* Class */ REG_OPTION_VOLATILE, NULL); /* Disposition */ if (!NT_SUCCESS(Status)) { DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); ZwClose(ClassKey); ExFreePool(BaseKeyName.Buffer); return Status; } /* Write DeviceInstance entry. Value is InstancePath */ Status = ZwSetValueKey( InterfaceKey, &DeviceInstance, 0, /* TileIndex */ REG_SZ, InstancePath->Buffer, InstancePath->Length); if (!NT_SUCCESS(Status)) { DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); ZwClose(InterfaceKey); ZwClose(ClassKey); ExFreePool(InterfaceKeyName.Buffer); ExFreePool(BaseKeyName.Buffer); return Status; } /* Create subkey. Name is #ReferenceString */ SubKeyName.Length = 0; SubKeyName.MaximumLength = sizeof(WCHAR); if (ReferenceString && ReferenceString->Length) SubKeyName.MaximumLength += ReferenceString->Length; SubKeyName.Buffer = ExAllocatePool( PagedPool, SubKeyName.MaximumLength); if (!SubKeyName.Buffer) { DPRINT("ExAllocatePool() failed\n"); ZwClose(InterfaceKey); ZwClose(ClassKey); ExFreePool(InterfaceKeyName.Buffer); ExFreePool(BaseKeyName.Buffer); return STATUS_INSUFFICIENT_RESOURCES; } RtlAppendUnicodeToString(&SubKeyName, L"#"); if (ReferenceString && ReferenceString->Length) RtlAppendUnicodeStringToString(&SubKeyName, ReferenceString); /* Create SubKeyName key in registry */ InitializeObjectAttributes( &ObjectAttributes, &SubKeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, InterfaceKey, /* RootDirectory */ NULL); /* SecurityDescriptor */ Status = ZwCreateKey( &SubKey, KEY_WRITE, &ObjectAttributes, 0, /* TileIndex */ NULL, /* Class */ REG_OPTION_VOLATILE, NULL); /* Disposition */ if (!NT_SUCCESS(Status)) { DPRINT("ZwCreateKey() failed with status 0x%08lx\n", Status); ZwClose(InterfaceKey); ZwClose(ClassKey); ExFreePool(InterfaceKeyName.Buffer); ExFreePool(BaseKeyName.Buffer); return Status; } /* Create symbolic link name: \??\ACPI#PNP0501#1#{GUID}\ReferenceString */ SymbolicLinkName->Length = 0; SymbolicLinkName->MaximumLength = SymbolicLinkName->Length + 4 * sizeof(WCHAR) /* 4 = size of \??\ */ + InstancePath->Length + sizeof(WCHAR) /* 1 = size of # */ + GuidString.Length + sizeof(WCHAR); /* final NULL */ if (ReferenceString && ReferenceString->Length) SymbolicLinkName->MaximumLength += sizeof(WCHAR) + ReferenceString->Length; SymbolicLinkName->Buffer = ExAllocatePool( PagedPool, SymbolicLinkName->MaximumLength); if (!SymbolicLinkName->Buffer) { DPRINT("ExAllocatePool() failed\n"); ZwClose(SubKey); ZwClose(InterfaceKey); ZwClose(ClassKey); ExFreePool(InterfaceKeyName.Buffer); ExFreePool(SubKeyName.Buffer); ExFreePool(BaseKeyName.Buffer); return STATUS_INSUFFICIENT_RESOURCES; } RtlAppendUnicodeToString(SymbolicLinkName, L"\\??\\"); StartIndex = SymbolicLinkName->Length / sizeof(WCHAR); RtlAppendUnicodeStringToString(SymbolicLinkName, InstancePath); for (i = 0; i < InstancePath->Length / sizeof(WCHAR); i++) { if (SymbolicLinkName->Buffer[StartIndex + i] == '\\') SymbolicLinkName->Buffer[StartIndex + i] = '#'; } RtlAppendUnicodeToString(SymbolicLinkName, L"#"); RtlAppendUnicodeStringToString(SymbolicLinkName, &GuidString); SymbolicLinkName->Buffer[SymbolicLinkName->Length/sizeof(WCHAR)] = L'\0'; /* Create symbolic link */ DPRINT("IoRegisterDeviceInterface(): creating symbolic link %wZ -> %wZ\n", SymbolicLinkName, &PdoNameInfo->Name); SymLinkStatus = IoCreateSymbolicLink(SymbolicLinkName, &PdoNameInfo->Name); /* If the symbolic link already exists, return an informational success status */ if (SymLinkStatus == STATUS_OBJECT_NAME_COLLISION) { /* HACK: Delete the existing symbolic link and update it to the new PDO name */ IoDeleteSymbolicLink(SymbolicLinkName); IoCreateSymbolicLink(SymbolicLinkName, &PdoNameInfo->Name); SymLinkStatus = STATUS_OBJECT_NAME_EXISTS; } if (!NT_SUCCESS(SymLinkStatus)) { DPRINT1("IoCreateSymbolicLink() failed with status 0x%08lx\n", SymLinkStatus); ZwClose(SubKey); ZwClose(InterfaceKey); ZwClose(ClassKey); ExFreePool(SubKeyName.Buffer); ExFreePool(InterfaceKeyName.Buffer); ExFreePool(BaseKeyName.Buffer); ExFreePool(SymbolicLinkName->Buffer); return SymLinkStatus; } if (ReferenceString && ReferenceString->Length) { RtlAppendUnicodeToString(SymbolicLinkName, L"\\"); RtlAppendUnicodeStringToString(SymbolicLinkName, ReferenceString); } SymbolicLinkName->Buffer[SymbolicLinkName->Length/sizeof(WCHAR)] = L'\0'; /* Write symbolic link name in registry */ SymbolicLinkName->Buffer[1] = '\\'; Status = ZwSetValueKey( SubKey, &SymbolicLink, 0, /* TileIndex */ REG_SZ, SymbolicLinkName->Buffer, SymbolicLinkName->Length); if (!NT_SUCCESS(Status)) { DPRINT1("ZwSetValueKey() failed with status 0x%08lx\n", Status); ExFreePool(SymbolicLinkName->Buffer); } else { SymbolicLinkName->Buffer[1] = '?'; } ZwClose(SubKey); ZwClose(InterfaceKey); ZwClose(ClassKey); ExFreePool(SubKeyName.Buffer); ExFreePool(InterfaceKeyName.Buffer); ExFreePool(BaseKeyName.Buffer); return NT_SUCCESS(Status) ? SymLinkStatus : Status; }
VOID NonPnpEvtDeviceFileCreate ( IN WDFDEVICE Device, IN WDFREQUEST Request, IN WDFFILEOBJECT FileObject ) /*++ Routine Description: The framework calls a driver's EvtDeviceFileCreate callback when it receives an IRP_MJ_CREATE request. The system sends this request when a user application opens the device to perform an I/O operation, such as reading or writing a file. This callback is called synchronously, in the context of the thread that created the IRP_MJ_CREATE request. Arguments: Device - Handle to a framework device object. FileObject - Pointer to fileobject that represents the open handle. CreateParams - Parameters of IO_STACK_LOCATION for create Return Value: NT status code --*/ { PUNICODE_STRING fileName; UNICODE_STRING absFileName, directory; OBJECT_ATTRIBUTES fileAttributes; IO_STATUS_BLOCK ioStatus; PCONTROL_DEVICE_EXTENSION devExt; NTSTATUS status; USHORT length = 0; UNREFERENCED_PARAMETER( FileObject ); PAGED_CODE (); devExt = ControlGetData(Device); // // Assume the directory is a temp directory under %windir% // RtlInitUnicodeString(&directory, L"\\SystemRoot\\temp"); // // Parsed filename has "\" in the begining. The object manager strips // of all "\", except one, after the device name. // fileName = WdfFileObjectGetFileName(FileObject); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "NonPnpEvtDeviceFileCreate %wZ%wZ", &directory, fileName); // // Find the total length of the directory + filename // length = directory.Length + fileName->Length; absFileName.Buffer = ExAllocatePoolWithTag(PagedPool, length, POOL_TAG); if(absFileName.Buffer == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "ExAllocatePoolWithTag failed"); goto End; } absFileName.Length = 0; absFileName.MaximumLength = length; status = RtlAppendUnicodeStringToString(&absFileName, &directory); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "RtlAppendUnicodeStringToString failed with status %!STATUS!", status); goto End; } status = RtlAppendUnicodeStringToString(&absFileName, fileName); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "RtlAppendUnicodeStringToString failed with status %!STATUS!", status); goto End; } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT, "Absolute Filename %wZ", &absFileName); InitializeObjectAttributes( &fileAttributes, &absFileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, // RootDirectory NULL // SecurityDescriptor ); status = ZwCreateFile ( &devExt->FileHandle, SYNCHRONIZE | GENERIC_WRITE | GENERIC_READ, &fileAttributes, &ioStatus, NULL,// alloc size = none FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT |FILE_NON_DIRECTORY_FILE, NULL,// eabuffer 0// ealength ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "ZwCreateFile failed with status %!STATUS!", status); devExt->FileHandle = NULL; } End: if(absFileName.Buffer != NULL) { ExFreePool(absFileName.Buffer); } WdfRequestComplete(Request, status); return; }
NTSTATUS FmCreateDosDevicesSymbolicLink( WDFDEVICE Device, PFM_DEVICE_DATA FmDeviceData ) { NTSTATUS status; UNICODE_STRING comPort; UNICODE_STRING pdoName; UNICODE_STRING symbolicLink; WDFKEY hKey = NULL; DECLARE_CONST_UNICODE_STRING(valueName, L"PortName"); WDFSTRING string = NULL; WDFMEMORY memory; WDF_OBJECT_ATTRIBUTES memoryAttributes; size_t bufferLength; PAGED_CODE(); symbolicLink.Buffer = NULL; // // Open the device registry and read the "PortName" value written by the // class installer. // status = WdfDeviceOpenRegistryKey(Device, PLUGPLAY_REGKEY_DEVICE, STANDARD_RIGHTS_ALL, NULL, // PWDF_OBJECT_ATTRIBUTES &hKey); if (!NT_SUCCESS (status)) { goto Error; } status = WdfStringCreate( NULL, WDF_NO_OBJECT_ATTRIBUTES , &string ); if (!NT_SUCCESS(status)) { goto Error; } // // Retrieve the value of ValueName from registry // status = WdfRegistryQueryString( hKey, &valueName, string ); if (!NT_SUCCESS (status)) { goto Error; } // // Retrieve the UNICODE_STRING from string object // WdfStringGetUnicodeString( string, &comPort ); WdfRegistryClose(hKey); hKey = NULL; symbolicLink.Length=0; symbolicLink.MaximumLength = sizeof(OBJECT_DIRECTORY) + comPort.MaximumLength; symbolicLink.Buffer = ExAllocatePoolWithTag(PagedPool, symbolicLink.MaximumLength + sizeof(WCHAR), 'wkaF'); if (symbolicLink.Buffer == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto Error; } RtlZeroMemory(symbolicLink.Buffer, symbolicLink.MaximumLength); RtlAppendUnicodeToString(&symbolicLink, OBJECT_DIRECTORY); RtlAppendUnicodeStringToString(&symbolicLink, &comPort); // // This DDI will get the underlying PDO name and create a symbolic to that // because our FDO doesn't have a name. // status = WdfDeviceCreateSymbolicLink(Device, &symbolicLink); if (!NT_SUCCESS(status)) { goto Error; } WDF_OBJECT_ATTRIBUTES_INIT(&memoryAttributes); memoryAttributes.ParentObject = Device; status = WdfDeviceAllocAndQueryProperty(Device, DevicePropertyPhysicalDeviceObjectName, PagedPool, &memoryAttributes, &memory); if (!NT_SUCCESS(status)) { // // We expect a zero length buffer. Anything else is fatal. // goto Error; } pdoName.Buffer = WdfMemoryGetBuffer(memory, &bufferLength); if (pdoName.Buffer == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto Error; } pdoName.MaximumLength = (USHORT) bufferLength; pdoName.Length = (USHORT) bufferLength - sizeof(UNICODE_NULL); status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP, L"SERIALCOMM", pdoName.Buffer, REG_SZ, comPort.Buffer, comPort.Length); if (!NT_SUCCESS(status)) { goto Error; } FmDeviceData->Flags |= REG_VALUE_CREATED_FLAG; // // Store it so it can be deleted later. // FmDeviceData->PdoName = pdoName; Error: if (symbolicLink.Buffer != NULL) { ExFreePool(symbolicLink.Buffer); } if (hKey != NULL) { WdfRegistryClose(hKey); } if (string != NULL) { WdfObjectDelete(string); } return status; }
NTSTATUS RamDiskEvtDeviceAdd( IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: EvtDeviceAdd is called by the framework in response to AddDevice call from the PnP manager. We create and initialize a device object to represent a new instance of the device. Arguments: Driver - Handle to a framework driver object created in DriverEntry DeviceInit - Pointer to a framework-allocated WDFDEVICE_INIT structure. Return Value: NTSTATUS --*/ { WDF_OBJECT_ATTRIBUTES deviceAttributes; NTSTATUS status; WDFDEVICE device; WDF_OBJECT_ATTRIBUTES queueAttributes; WDF_IO_QUEUE_CONFIG ioQueueConfig; PDEVICE_EXTENSION pDeviceExtension; PQUEUE_EXTENSION pQueueContext = NULL; WDFQUEUE queue; DECLARE_CONST_UNICODE_STRING(ntDeviceName, NT_DEVICE_NAME); PAGED_CODE(); UNREFERENCED_PARAMETER(Driver); // // Storage drivers have to name their FDOs. Since we are not unique'fying // the device name, we wouldn't be able to install more than one instance // of this ramdisk driver. // status = WdfDeviceInitAssignName(DeviceInit, &ntDeviceName); if (!NT_SUCCESS(status)) { return status; } WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_DISK); WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect); WdfDeviceInitSetExclusive(DeviceInit, FALSE); // // Since this is a pure software only driver, there is no need to register // any PNP/Power event callbacks. Framework will respond to these // events appropriately. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_EXTENSION); deviceAttributes.EvtCleanupCallback = RamDiskEvtDeviceContextCleanup; status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (!NT_SUCCESS(status)) { return status; } // // Now that the WDF device object has been created, set up any context // that it requires. // pDeviceExtension = DeviceGetExtension(device); // // Configure a default queue so that requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching to goto // other queues get dispatched here. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE ( &ioQueueConfig, WdfIoQueueDispatchSequential ); ioQueueConfig.EvtIoDeviceControl = RamDiskEvtIoDeviceControl; ioQueueConfig.EvtIoRead = RamDiskEvtIoRead; ioQueueConfig.EvtIoWrite = RamDiskEvtIoWrite; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&queueAttributes, QUEUE_EXTENSION); // // By default, Static Driver Verifier (SDV) displays a warning if it // doesn't find the EvtIoStop callback on a power-managed queue. // The 'assume' below causes SDV to suppress this warning. If the driver // has not explicitly set PowerManaged to WdfFalse, the framework creates // power-managed queues when the device is not a filter driver. Normally // the EvtIoStop is required for power-managed queues, but for this driver // it is not needed b/c the driver doesn't hold on to the requests or // forward them to other drivers. This driver completes the requests // directly in the queue's handlers. If the EvtIoStop callback is not // implemented, the framework waits for all driver-owned requests to be // done before moving in the Dx/sleep states or before removing the // device, which is the correct behavior for this type of driver. // If the requests were taking an indeterminate amount of time to complete, // or if the driver forwarded the requests to a lower driver/another stack, // the queue should have an EvtIoStop/EvtIoResume. // __analysis_assume(ioQueueConfig.EvtIoStop != 0); status = WdfIoQueueCreate( device, &ioQueueConfig, &queueAttributes, &queue ); __analysis_assume(ioQueueConfig.EvtIoStop == 0); if (!NT_SUCCESS(status)) { return status; } // Context is the Queue handle pQueueContext = QueueGetExtension(queue); // // Set the context for our default queue as our device extension. // pQueueContext->DeviceExtension = pDeviceExtension; #if KMDF_VERSION_MINOR >= 9 // // Enable forward progress on the queue we just created. // NOTE: If you are planning to use this code without forward progress, // comment out the call to SetForwardProgressOnQueue below. // status = SetForwardProgressOnQueue(queue); if (!NT_SUCCESS(status)) { return status; } #endif // // Now do any RAM-Disk specific initialization // pDeviceExtension->DiskRegInfo.DriveLetter.Buffer = (PWSTR) &pDeviceExtension->DriveLetterBuffer; pDeviceExtension->DiskRegInfo.DriveLetter.MaximumLength = sizeof(pDeviceExtension->DriveLetterBuffer); // // Get the disk parameters from the registry // RamDiskQueryDiskRegParameters( WdfDriverGetRegistryPath(WdfDeviceGetDriver(device)), &pDeviceExtension->DiskRegInfo ); // // Allocate memory for the disk image. // pDeviceExtension->DiskImage = ExAllocatePoolWithTag( NonPagedPool, pDeviceExtension->DiskRegInfo.DiskSize, RAMDISK_TAG ); if (pDeviceExtension->DiskImage) { UNICODE_STRING deviceName; UNICODE_STRING win32Name; RamDiskFormatDisk(pDeviceExtension); status = STATUS_SUCCESS; // // Now try to create a symbolic link for the drive letter. // RtlInitUnicodeString(&win32Name, DOS_DEVICE_NAME); RtlInitUnicodeString(&deviceName, NT_DEVICE_NAME); pDeviceExtension->SymbolicLink.Buffer = (PWSTR) &pDeviceExtension->DosDeviceNameBuffer; pDeviceExtension->SymbolicLink.MaximumLength = sizeof(pDeviceExtension->DosDeviceNameBuffer); pDeviceExtension->SymbolicLink.Length = win32Name.Length; RtlCopyUnicodeString(&pDeviceExtension->SymbolicLink, &win32Name); RtlAppendUnicodeStringToString(&pDeviceExtension->SymbolicLink, &pDeviceExtension->DiskRegInfo.DriveLetter); status = WdfDeviceCreateSymbolicLink(device, &pDeviceExtension->SymbolicLink); } return status; }
NTSTATUS NTAPI IopQueryDeviceDescription( PIO_QUERY Query, UNICODE_STRING RootKey, HANDLE RootKeyHandle, ULONG Bus, PKEY_VALUE_FULL_INFORMATION *BusInformation) { NTSTATUS Status = STATUS_SUCCESS; /* Controller Stuff */ UNICODE_STRING ControllerString; UNICODE_STRING ControllerRootRegName = RootKey; UNICODE_STRING ControllerRegName; HANDLE ControllerKeyHandle; PKEY_FULL_INFORMATION ControllerFullInformation = NULL; PKEY_VALUE_FULL_INFORMATION ControllerInformation[3] = {NULL, NULL, NULL}; ULONG ControllerNumber; ULONG ControllerLoop; ULONG MaximumControllerNumber; /* Peripheral Stuff */ UNICODE_STRING PeripheralString; HANDLE PeripheralKeyHandle; PKEY_FULL_INFORMATION PeripheralFullInformation; PKEY_VALUE_FULL_INFORMATION PeripheralInformation[3] = {NULL, NULL, NULL}; ULONG PeripheralNumber; ULONG PeripheralLoop; ULONG MaximumPeripheralNumber; /* Global Registry Stuff */ OBJECT_ATTRIBUTES ObjectAttributes; ULONG LenFullInformation; ULONG LenKeyFullInformation; UNICODE_STRING TempString; WCHAR TempBuffer[14]; PWSTR Strings[3] = { L"Identifier", L"Configuration Data", L"Component Information" }; /* Temporary String */ TempString.MaximumLength = sizeof(TempBuffer); TempString.Length = 0; TempString.Buffer = TempBuffer; /* Add Controller Name to String */ RtlAppendUnicodeToString(&ControllerRootRegName, L"\\"); RtlAppendUnicodeToString(&ControllerRootRegName, ArcTypes[*Query->ControllerType]); /* Set the Controller Number if specified */ if (Query->ControllerNumber && *(Query->ControllerNumber)) { ControllerNumber = *Query->ControllerNumber; MaximumControllerNumber = ControllerNumber + 1; } else { /* Find out how many Controller Numbers there are */ InitializeObjectAttributes( &ObjectAttributes, &ControllerRootRegName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenKey(&ControllerKeyHandle, KEY_READ, &ObjectAttributes); if (NT_SUCCESS(Status)) { /* How much buffer space */ ZwQueryKey(ControllerKeyHandle, KeyFullInformation, NULL, 0, &LenFullInformation); /* Allocate it */ ControllerFullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE); /* Get the Information */ Status = ZwQueryKey(ControllerKeyHandle, KeyFullInformation, ControllerFullInformation, LenFullInformation, &LenFullInformation); ZwClose(ControllerKeyHandle); ControllerKeyHandle = NULL; } /* No controller was found, go back to function. */ if (!NT_SUCCESS(Status)) { if (ControllerFullInformation != NULL) ExFreePoolWithTag(ControllerFullInformation, TAG_IO_RESOURCE); return Status; } /* Find out Controller Numbers */ ControllerNumber = 0; MaximumControllerNumber = ControllerFullInformation->SubKeys; /* Free Memory */ ExFreePoolWithTag(ControllerFullInformation, TAG_IO_RESOURCE); ControllerFullInformation = NULL; } /* Save String */ ControllerRegName = ControllerRootRegName; /* Loop through controllers */ for (; ControllerNumber < MaximumControllerNumber; ControllerNumber++) { /* Load String */ ControllerRootRegName = ControllerRegName; /* Controller Number to Registry String */ Status = RtlIntegerToUnicodeString(ControllerNumber, 10, &TempString); /* Create String */ Status |= RtlAppendUnicodeToString(&ControllerRootRegName, L"\\"); Status |= RtlAppendUnicodeStringToString(&ControllerRootRegName, &TempString); /* Something messed up */ if (!NT_SUCCESS(Status)) break; /* Open the Registry Key */ InitializeObjectAttributes( &ObjectAttributes, &ControllerRootRegName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenKey(&ControllerKeyHandle, KEY_READ, &ObjectAttributes); /* Read the Configuration Data... */ if (NT_SUCCESS(Status)) { for (ControllerLoop = 0; ControllerLoop < 3; ControllerLoop++) { /* Identifier String First */ RtlInitUnicodeString(&ControllerString, Strings[ControllerLoop]); /* How much buffer space */ Status = ZwQueryValueKey(ControllerKeyHandle, &ControllerString, KeyValueFullInformation, NULL, 0, &LenKeyFullInformation); if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW) continue; /* Allocate it */ ControllerInformation[ControllerLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE); /* Get the Information */ Status = ZwQueryValueKey(ControllerKeyHandle, &ControllerString, KeyValueFullInformation, ControllerInformation[ControllerLoop], LenKeyFullInformation, &LenKeyFullInformation); } /* Clean Up */ ZwClose(ControllerKeyHandle); ControllerKeyHandle = NULL; } /* Something messed up */ if (!NT_SUCCESS(Status)) goto EndLoop; /* We now have Bus *AND* Controller Information.. is it enough? */ if (!Query->PeripheralType || !(*Query->PeripheralType)) { Status = Query->CalloutRoutine( Query->Context, &ControllerRootRegName, *Query->BusType, Bus, BusInformation, *Query->ControllerType, ControllerNumber, ControllerInformation, 0, 0, NULL); goto EndLoop; } /* Not enough...caller also wants peripheral name */ Status = RtlAppendUnicodeToString(&ControllerRootRegName, L"\\"); Status |= RtlAppendUnicodeToString(&ControllerRootRegName, ArcTypes[*Query->PeripheralType]); /* Something messed up */ if (!NT_SUCCESS(Status)) goto EndLoop; /* Set the Peripheral Number if specified */ if (Query->PeripheralNumber && *Query->PeripheralNumber) { PeripheralNumber = *Query->PeripheralNumber; MaximumPeripheralNumber = PeripheralNumber + 1; } else { /* Find out how many Peripheral Numbers there are */ InitializeObjectAttributes( &ObjectAttributes, &ControllerRootRegName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenKey(&PeripheralKeyHandle, KEY_READ, &ObjectAttributes); if (NT_SUCCESS(Status)) { /* How much buffer space */ ZwQueryKey(PeripheralKeyHandle, KeyFullInformation, NULL, 0, &LenFullInformation); /* Allocate it */ PeripheralFullInformation = ExAllocatePoolWithTag(PagedPool, LenFullInformation, TAG_IO_RESOURCE); /* Get the Information */ Status = ZwQueryKey(PeripheralKeyHandle, KeyFullInformation, PeripheralFullInformation, LenFullInformation, &LenFullInformation); ZwClose(PeripheralKeyHandle); PeripheralKeyHandle = NULL; } /* No controller was found, go back to function but clean up first */ if (!NT_SUCCESS(Status)) { Status = STATUS_SUCCESS; goto EndLoop; } /* Find out Peripheral Number */ PeripheralNumber = 0; MaximumPeripheralNumber = PeripheralFullInformation->SubKeys; /* Free Memory */ ExFreePoolWithTag(PeripheralFullInformation, TAG_IO_RESOURCE); PeripheralFullInformation = NULL; } /* Save Name */ ControllerRegName = ControllerRootRegName; /* Loop through Peripherals */ for (; PeripheralNumber < MaximumPeripheralNumber; PeripheralNumber++) { /* Restore Name */ ControllerRootRegName = ControllerRegName; /* Peripheral Number to Registry String */ Status = RtlIntegerToUnicodeString(PeripheralNumber, 10, &TempString); /* Create String */ Status |= RtlAppendUnicodeToString(&ControllerRootRegName, L"\\"); Status |= RtlAppendUnicodeStringToString(&ControllerRootRegName, &TempString); /* Something messed up */ if (!NT_SUCCESS(Status)) break; /* Open the Registry Key */ InitializeObjectAttributes( &ObjectAttributes, &ControllerRootRegName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenKey(&PeripheralKeyHandle, KEY_READ, &ObjectAttributes); if (NT_SUCCESS(Status)) { for (PeripheralLoop = 0; PeripheralLoop < 3; PeripheralLoop++) { /* Identifier String First */ RtlInitUnicodeString(&PeripheralString, Strings[PeripheralLoop]); /* How much buffer space */ Status = ZwQueryValueKey(PeripheralKeyHandle, &PeripheralString, KeyValueFullInformation, NULL, 0, &LenKeyFullInformation); if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL && Status != STATUS_BUFFER_OVERFLOW) { PeripheralInformation[PeripheralLoop] = NULL; continue; } /* Allocate it */ PeripheralInformation[PeripheralLoop] = ExAllocatePoolWithTag(PagedPool, LenKeyFullInformation, TAG_IO_RESOURCE); /* Get the Information */ Status = ZwQueryValueKey(PeripheralKeyHandle, &PeripheralString, KeyValueFullInformation, PeripheralInformation[PeripheralLoop], LenKeyFullInformation, &LenKeyFullInformation); } /* Clean Up */ ZwClose(PeripheralKeyHandle); PeripheralKeyHandle = NULL; /* We now have everything the caller could possibly want */ if (NT_SUCCESS(Status)) { Status = Query->CalloutRoutine( Query->Context, &ControllerRootRegName, *Query->BusType, Bus, BusInformation, *Query->ControllerType, ControllerNumber, ControllerInformation, *Query->PeripheralType, PeripheralNumber, PeripheralInformation); } /* Free the allocated memory */ for (PeripheralLoop = 0; PeripheralLoop < 3; PeripheralLoop++) { if (PeripheralInformation[PeripheralLoop]) { ExFreePoolWithTag(PeripheralInformation[PeripheralLoop], TAG_IO_RESOURCE); PeripheralInformation[PeripheralLoop] = NULL; } } /* Something Messed up */ if (!NT_SUCCESS(Status)) break; } } EndLoop: /* Free the allocated memory */ for (ControllerLoop = 0; ControllerLoop < 3; ControllerLoop++) { if (ControllerInformation[ControllerLoop]) { ExFreePoolWithTag(ControllerInformation[ControllerLoop], TAG_IO_RESOURCE); ControllerInformation[ControllerLoop] = NULL; } } /* Something Messed up */ if (!NT_SUCCESS(Status)) break; } return Status; }
NTSTATUS NTAPI IntCreateNewRegistryPath( PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension) { static UNICODE_STRING VideoIdValueName = RTL_CONSTANT_STRING(L"VideoId"); static UNICODE_STRING ControlVideoPathName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Video\\"); HANDLE DevInstRegKey, SettingsKey, NewKey; UCHAR VideoIdBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + GUID_STRING_LENGTH]; UNICODE_STRING VideoIdString; UUID VideoId; PKEY_VALUE_PARTIAL_INFORMATION ValueInformation ; NTSTATUS Status; ULONG ResultLength; USHORT KeyMaxLength; OBJECT_ATTRIBUTES ObjectAttributes; /* Open the hardware key: HKLM\System\CurrentControlSet\Enum\... */ Status = IoOpenDeviceRegistryKey(DeviceExtension->PhysicalDeviceObject, PLUGPLAY_REGKEY_DEVICE, KEY_ALL_ACCESS, &DevInstRegKey); if (Status != STATUS_SUCCESS) { ERR_(VIDEOPRT, "IoOpenDeviceRegistryKey failed: status 0x%lx\n", Status); return Status; } /* Query the VideoId value */ ValueInformation = (PKEY_VALUE_PARTIAL_INFORMATION)VideoIdBuffer; Status = ZwQueryValueKey(DevInstRegKey, &VideoIdValueName, KeyValuePartialInformation, ValueInformation, sizeof(VideoIdBuffer), &ResultLength); if (!NT_SUCCESS(Status)) { /* Create a new video Id */ Status = ExUuidCreate(&VideoId); if (!NT_SUCCESS(Status)) { ERR_(VIDEOPRT, "ExUuidCreate failed: status 0x%lx\n", Status); ObCloseHandle(DevInstRegKey, KernelMode); return Status; } /* Convert the GUID into a string */ Status = RtlStringFromGUID(&VideoId, &VideoIdString); if (!NT_SUCCESS(Status)) { ERR_(VIDEOPRT, "RtlStringFromGUID failed: status 0x%lx\n", Status); ObCloseHandle(DevInstRegKey, KernelMode); return Status; } /* Copy the GUID String to our buffer */ ValueInformation->DataLength = min(VideoIdString.Length, GUID_STRING_LENGTH); RtlCopyMemory(ValueInformation->Data, VideoIdString.Buffer, ValueInformation->DataLength); /* Free the GUID string */ RtlFreeUnicodeString(&VideoIdString); /* Write the VideoId registry value */ Status = ZwSetValueKey(DevInstRegKey, &VideoIdValueName, 0, REG_SZ, ValueInformation->Data, ValueInformation->DataLength); if (!NT_SUCCESS(Status)) { ERR_(VIDEOPRT, "ZwSetValueKey failed: status 0x%lx\n", Status); ObCloseHandle(DevInstRegKey, KernelMode); return Status; } } /* Initialize the VideoId string from the registry data */ VideoIdString.Buffer = (PWCHAR)ValueInformation->Data; VideoIdString.Length = (USHORT)ValueInformation->DataLength; VideoIdString.MaximumLength = VideoIdString.Length; /* Close the hardware key */ ObCloseHandle(DevInstRegKey, KernelMode); /* Calculate the size needed for the new registry path name */ KeyMaxLength = ControlVideoPathName.Length + VideoIdString.Length + sizeof(L"\\0000"); /* Allocate the path name buffer */ DeviceExtension->NewRegistryPath.Length = 0; DeviceExtension->NewRegistryPath.MaximumLength = KeyMaxLength; DeviceExtension->NewRegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool, KeyMaxLength, TAG_VIDEO_PORT); if (DeviceExtension->NewRegistryPath.Buffer == NULL) { ERR_(VIDEOPRT, "Failed to allocate key name buffer.\n"); return STATUS_INSUFFICIENT_RESOURCES; } /* Copy the root key name and append the VideoId string */ RtlCopyUnicodeString(&DeviceExtension->NewRegistryPath, &ControlVideoPathName); RtlAppendUnicodeStringToString(&DeviceExtension->NewRegistryPath, &VideoIdString); /* Check if we have the key already */ Status = RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, DeviceExtension->NewRegistryPath.Buffer); if (Status != STATUS_SUCCESS) { /* Try to create the new key */ Status = RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE, DeviceExtension->NewRegistryPath.Buffer); } /* Append a the instance path */ /// \todo HACK RtlAppendUnicodeToString(&DeviceExtension->NewRegistryPath, L"\\"); RtlAppendUnicodeToString(&DeviceExtension->NewRegistryPath, L"0000"); /* Check this key again */ Status = RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, DeviceExtension->NewRegistryPath.Buffer); if (Status != STATUS_SUCCESS) { /* Try to create the new key */ Status = RtlCreateRegistryKey(RTL_REGISTRY_ABSOLUTE, DeviceExtension->NewRegistryPath.Buffer); if (!NT_SUCCESS(Status)) { ERR_(VIDEOPRT, "Failed create key '%wZ'\n", &DeviceExtension->NewRegistryPath); return Status; } /* Open the new key */ InitializeObjectAttributes(&ObjectAttributes, &DeviceExtension->NewRegistryPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenKey(&NewKey, KEY_READ, &ObjectAttributes); if (!NT_SUCCESS(Status)) { ERR_(VIDEOPRT, "Failed to open settings key. Status 0x%lx\n", Status); return Status; } /* Open the device profile key */ InitializeObjectAttributes(&ObjectAttributes, &DeviceExtension->RegistryPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenKey(&SettingsKey, KEY_READ, &ObjectAttributes); if (!NT_SUCCESS(Status)) { ERR_(VIDEOPRT, "Failed to open settings key. Status 0x%lx\n", Status); ObCloseHandle(NewKey, KernelMode); return Status; } /* Copy the registry data from the legacy key */ Status = IntCopyRegistryKey(SettingsKey, NewKey); } return Status; }
NTSTATUS SetLowerFilters(PUNICODE_STRING szUName,ULONG uFlag) { //设置底层过滤函数,完成对注册表的处理 UNICODE_STRING dst,src,ValueName; HANDLE hRegister,hSubKey; WCHAR dst_buf[256]; //初始化UNICODE_STRING字符串 RtlInitEmptyUnicodeString(&dst,dst_buf,256*sizeof(WCHAR)); RtlInitUnicodeString(&src,USBSTOR); RtlCopyUnicodeString(&dst,&src); RtlAppendUnicodeStringToString(&dst,szUName); OBJECT_ATTRIBUTES objectAttributes; //初始化objectAttributes InitializeObjectAttributes(&objectAttributes, &dst, OBJ_CASE_INSENSITIVE,//对大小写敏感 NULL, NULL ); //打开注册表 NTSTATUS ntStatus = ZwOpenKey( &hRegister, KEY_ALL_ACCESS, &objectAttributes); //打开注册表成功 if (NT_SUCCESS(ntStatus)) { DbgPrint("Open register successfully\n"); } RtlInitUnicodeString(&ValueName,L"LowerFilters"); PWCHAR strValue=L"USBFilter"; ULONG ulSize; //第一次调用ZwQueryKey为了获取KEY_FULL_INFORMATION数据的长度 ZwQueryKey(hRegister, KeyFullInformation, NULL, 0, &ulSize); PKEY_FULL_INFORMATION pfi = (PKEY_FULL_INFORMATION) ExAllocatePool(PagedPool,ulSize); //第二次调用ZwQueryKey为了获取KEY_FULL_INFORMATION数据的数据 ZwQueryKey(hRegister, KeyFullInformation, pfi, ulSize, &ulSize); for (ULONG i=0;i<pfi->SubKeys;i++) { //第一次调用ZwEnumerateKey为了获取KEY_BASIC_INFORMATION数据的长度 ZwEnumerateKey(hRegister, i, KeyBasicInformation, NULL, 0, &ulSize); PKEY_BASIC_INFORMATION pbi = (PKEY_BASIC_INFORMATION) ExAllocatePool(PagedPool,ulSize); //第二次调用ZwEnumerateKey为了获取KEY_BASIC_INFORMATION数据的数据 ZwEnumerateKey(hRegister, i, KeyBasicInformation, pbi, ulSize, &ulSize); UNICODE_STRING uniKeyName; uniKeyName.Length = uniKeyName.MaximumLength = (USHORT)pbi->NameLength; uniKeyName.Buffer = pbi->Name; WCHAR bufTmp[256]; //初始化值 RtlInitEmptyUnicodeString(&src,bufTmp,256*sizeof(WCHAR)); RtlCopyUnicodeString(&src,&dst); UNICODE_STRING szX; RtlInitUnicodeString(&szX,L"\\"); RtlAppendUnicodeStringToString(&src,&szX), RtlAppendUnicodeStringToString(&src,&uniKeyName); //初始化ObjectAttributes InitializeObjectAttributes(&objectAttributes, &src, OBJ_CASE_INSENSITIVE,//对大小写敏感 NULL, NULL ); //打开注册表 ZwOpenKey( &hSubKey, KEY_ALL_ACCESS, &objectAttributes); //uFlag为0则删除注册表键值,否则设置注册表键值 if(uFlag==0) { ntStatus=ZwDeleteValueKey(hSubKey,&ValueName); } else { ntStatus=ZwSetValueKey(hSubKey,&ValueName,0,REG_SZ,strValue,wcslen(strValue)*2+2); } //成功的话 if (NT_SUCCESS(ntStatus)) { DbgPrint("Charge Value successfully\n"); } else DbgPrint("Charge Value failed!\n"); DbgPrint("The %d sub item name:%wZ\n",i,&src); //回收内存 ExFreePool(pbi); //关闭句柄 ZwClose(hSubKey); } ExFreePool(pfi); ZwClose(hRegister); return STATUS_SUCCESS; }
NTSTATUS FileInfo_NtPathToDosPath (HANDLE hProcess, HANDLE hDirectory, PUNICODE_STRING pusNtPath, PUNICODE_STRING pusDosPath) { ASSERT (pusDosPath!=NULL) ; ASSERT (pusDosPath->Buffer!=NULL) ; if( pusNtPath==NULL || pusNtPath->Buffer==NULL ) { TRACE_WARNING (TEXT("NT Path is NULL\n")) ; pusDosPath->Buffer[0] = 0 ; pusDosPath->Length = 0 ; return STATUS_OBJECT_PATH_INVALID ; } TRACE_INFO (TEXT("pusNtPath->Length = %d\n"), pusNtPath->Length) ; TRACE_INFO (TEXT("pusNtPath->MaximumLength = %d\n"), pusNtPath->MaximumLength) ; TRACE_INFO (TEXT("pusNtPath->Buffer = %ls\n"), pusNtPath->Buffer) ; if( _FileInfo_CheckPrefix(pusNtPath,L"\\??\\") ) { if( pusNtPath->Buffer[5]==L':' ) { UNICODE_STRING usTemp ; usTemp.Length = pusNtPath->Length-4*sizeof(WCHAR) ; usTemp.MaximumLength = pusNtPath->MaximumLength-4*sizeof(WCHAR) ; usTemp.Buffer = pusNtPath->Buffer+4 ; //TRACE_INFO (TEXT("Removing prefix \\??\\ on absolute path\n")) ; RtlCopyUnicodeString (pusDosPath, &usTemp) ; #if APPEND_TERMINAL_NULL pusDosPath->Buffer[pusDosPath->Length/2] = 0 ; #endif } else { RtlCopyUnicodeString (pusDosPath, pusNtPath) ; #if APPEND_TERMINAL_NULL pusDosPath->Buffer[pusDosPath->Length/2] = 0 ; #endif } return STATUS_SUCCESS ; } if( _FileInfo_CheckPrefix(pusNtPath,L"\\SystemRoot\\") ) { UNICODE_STRING usTemp ; //TRACE_INFO (TEXT("Changing prefix \\SystemRoot\n")) ; if( hProcess && STATUS_SUCCESS==ProcInfo_GetSystemRoot(hProcess, pusDosPath) ) { } else if( STATUS_SUCCESS==SystInfo_GetSystemRoot(pusDosPath) ) { } else { TRACE_WARNING (TEXT("SystInfo_GetSystemRoot failed\n")) ; RtlInitUnicodeString (&usTemp, L"%systemroot%") ; RtlCopyUnicodeString (pusDosPath, &usTemp) ; } usTemp.Length = pusNtPath->Length-11*sizeof(WCHAR) ; usTemp.MaximumLength = pusNtPath->MaximumLength-11*sizeof(WCHAR) ; usTemp.Buffer = pusNtPath->Buffer+11 ; RtlAppendUnicodeStringToString (pusDosPath, &usTemp) ; #if APPEND_TERMINAL_NULL pusDosPath->Buffer[pusDosPath->Length/2] = 0 ; #endif return STATUS_SUCCESS ; } if( _FileInfo_CheckPrefix(pusNtPath,L"\\Device\\") ) { RtlCopyUnicodeString (pusDosPath, pusNtPath) ; #if APPEND_TERMINAL_NULL pusDosPath->Buffer[pusDosPath->Length/2] = 0 ; #endif return STATUS_SUCCESS ; } if( pusNtPath->Buffer[1]==L':' ) { RtlCopyUnicodeString (pusDosPath, pusNtPath) ; #if APPEND_TERMINAL_NULL pusDosPath->Buffer[pusDosPath->Length/2] = 0 ; #endif return STATUS_SUCCESS ; } TRACE_WARNING (TEXT("Difficulty : %ls (length=%u)\n"), pusNtPath->Buffer, pusNtPath->Length) ; if( hDirectory!=NULL ) { UNICODE_STRING usDirectory ; NTSTATUS nStatus ; WCHAR wszDirectory[MAX_PATH] ; TRACE_WARNING (TEXT("Trying to complete with directory handle\n")) ; usDirectory.Length = 0 ; usDirectory.MaximumLength = MAX_PATH * sizeof(WCHAR) ; usDirectory.Buffer = wszDirectory ; nStatus = FileInfo_GetPath (hDirectory, &usDirectory) ; if( nStatus==STATUS_SUCCESS ) { TRACE_WARNING (TEXT("Directory = %ls\n"), usDirectory.Buffer) ; RtlAppendUnicodeToString(&usDirectory, L"\\") ; RtlAppendUnicodeStringToString (&usDirectory, pusNtPath) ; RtlCopyUnicodeString (pusDosPath, &usDirectory) ; #if APPEND_TERMINAL_NULL pusDosPath->Buffer[pusDosPath->Length/2] = 0 ; #endif } else { TRACE_WARNING (TEXT("FileInfo_GetPath failed (status=0x%08X)\n"), nStatus) ; RtlCopyUnicodeString (pusDosPath, pusNtPath) ; #if APPEND_TERMINAL_NULL pusDosPath->Buffer[pusDosPath->Length/2] = 0 ; #endif } } else if( hProcess!=NULL ) { NTSTATUS nStatus ; TRACE_WARNING (TEXT("Trying to complete with current directory\n")) ; nStatus = ProcInfo_GetCurDirDosPath (hProcess, pusDosPath) ; if( nStatus==STATUS_SUCCESS ) { RtlAppendUnicodeStringToString (pusDosPath, pusNtPath) ; #if APPEND_TERMINAL_NULL pusDosPath->Buffer[pusDosPath->Length/2] = 0 ; #endif } else { TRACE_ERROR (TEXT("Failed to get current directory\n")) ; RtlCopyUnicodeString (pusDosPath, pusNtPath) ; #if APPEND_TERMINAL_NULL pusDosPath->Buffer[pusDosPath->Length/2] = 0 ; #endif } } else { TRACE_WARNING (TEXT("No directory\n")) ; RtlCopyUnicodeString (pusDosPath, pusNtPath) ; #if APPEND_TERMINAL_NULL pusDosPath->Buffer[pusDosPath->Length/2] = 0 ; #endif } TRACE_WARNING (TEXT("Result : %ls\n"), pusDosPath->Buffer) ; return STATUS_SUCCESS ; }