Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
	}
Beispiel #5
0
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;
}
Beispiel #6
0
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;
}
Beispiel #7
0
/*
 * @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;
}
Beispiel #8
0
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;
}
Beispiel #9
0
/*++
 * @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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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;
}
Beispiel #12
0
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;
}
Beispiel #13
0
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);
}
Beispiel #14
0
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;
}
Beispiel #15
0
/*++
 * @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;
}
Beispiel #16
0
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;
}
Beispiel #17
0
 //在注册表子项中设置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;
}
Beispiel #18
0
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;
}
Beispiel #19
0
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;
}
Beispiel #20
0
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;
}
Beispiel #21
0
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;
}
Beispiel #22
0
/*++
 * @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;
}
Beispiel #23
0
/*++
 * @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;
}
Beispiel #24
0
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;
}
Beispiel #25
0
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;
}
Beispiel #26
0
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;
}
Beispiel #27
0
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;
}
Beispiel #28
0
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;
}
Beispiel #29
0
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;
}
Beispiel #30
0
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 ;
}