Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home NTDEV

Before Posting...

Please check out the Community Guidelines in the Announcements and Administration Category.

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


Possible to read values from registry in DriverEntry?

OSR_Community_UserOSR_Community_User Member Posts: 110,217
Any Win9X wizards on this list? Is there a better list on which I could ask
this question?

I'm doing a Win98 miniport, which needs to get a value out of the registry
in the DriverEntry routine, and I'm not having any success.

I can open a key, and read the name of the value I'm looking for, but I
can't read the value itself. Since I already know the name of the value,
being able to retrieve it really doesn't help much. But it does appear to
validate that the ZwOpenKey call is returning a valid handle. Doesn't it?

Below is the code demonstrating the problem. I've tried ZwCreateKey with
the same options as ZwOpenKey, and it didn't work any better. Any
suggestions for different options, incantations, or other secret sauce that
might make this work?

UNICODE_STRING uPath, uName, uResult;
ANSI_STRING aResult;
HANDLE hFolder = NULL;
OBJECT_ATTRIBUTES objAttribs;
NTSTATUS lastError = STATUS_SUCCESS;
ULONG dataLength = 0x80;
ULONG structLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + \
dataLength + sizeof(UNICODE_NULL);
PKEY_VALUE_BASIC_INFORMATION pBasicValue = NULL;
PKEY_VALUE_PARTIAL_INFORMATION pPartialValue = NULL;
PKEY_VALUE_FULL_INFORMATION pFullValue = NULL;
pBasicValue = (PKEY_VALUE_BASIC_INFORMATION) \
ExAllocatePool(PagedPool, structLength);
pPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION) \
ExAllocatePool(PagedPool, structLength);
pFullValue = (PKEY_VALUE_FULL_INFORMATION) \
ExAllocatePool(PagedPool, structLength);

RtlInitUnicodeString(&uPath, L"\\Registry\\Machine\\System\\"\
L"CurrentControlSet\\Services\\Class\\Dummy");
RtlInitUnicodeString(&uName, L"Target");

InitializeObjectAttributes(&objAttribs, &uPath, \
OBJ_CASE_INSENSITIVE, NULL, NULL);

lastError = ZwOpenKey(&hFolder, KEY_ALL_ACCESS, &objAttribs);

if(lastError != ERROR_SUCCESS)
{
DbgPrint("Couldn't open key: %s. Ending function.\n", pKeyPath);
return lastError;
}

//Try to verify that the name is what I think it is.
memset(pBasicValue, 0, structLength);
lastError = ZwQueryValueKey(&hFolder, &uName, KeyValueBasicInformation, \
pBasicValue, structLength,
&dataLength);
switch(lastError)
{
case STATUS_INVALID_HANDLE:
//We're dead in the water here. Should never get here!
DbgPrint("ZwQueryValueKey(Basic) says the handle is bogus.\n");
break;
case STATUS_BUFFER_OVERFLOW:
//Since it failed because of insufficient storage, allocate enough.
ExFreePool(pBasicValue);
structLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + dataLength + \
sizeof(UNICODE_NULL);
pBasicValue = (PKEY_VALUE_BASIC_INFORMATION) \
ExAllocatePool(PagedPool, structLength);
lastError = ZwQueryValueKey(&hFolder, &uName, \
KeyValueBasicInformation, pBasicValue, \
structLength, &dataLength);
if(lastError != ERROR_SUCCESS)
{
//Just give it up. Shouldn't get here, either.
DbgPrint("ZwQueryValueKey(Basic): Still didn't get it. "\
"Status: %X\n", lastError);
break;
}
//Fall Through
case ERROR_SUCCESS:
RtlInitUnicodeString(&uResult, pBasicValue->Name);
break;
}
ExFreePool(pBasicValue);

//Try to read the value, using the PKEY_VALUE_PARTIAL_INFORMATION.
memset(pPartialValue, 0, structLength);
lastError = ZwQueryValueKey(&hFolder, &uName, \
KeyValuePartialInformation, pPartialValue, \
structLength, &dataLength);
switch(lastError)
{
case STATUS_INVALID_HANDLE: //Always end up here.
DbgPrint("ZwQueryValueKey(Partial) says the handle is bogus.\n");
break;
case STATUS_BUFFER_OVERFLOW:
//Since it failed because of insufficient storage, allocate enough.
ExFreePool(pPartialValue);
structLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + \
dataLength + sizeof(UNICODE_NULL);
pPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)\
ExAllocatePool(PagedPool, structLength);
lastError = ZwQueryValueKey(&hFolder, &uName, \
KeyValuePartialInformation, pPartialValue, \
structLength, &dataLength);
if(lastError != ERROR_SUCCESS)
{
//Just give it up. Shouldn't get here, either.
DbgPrint("ZwQueryValueKey(Partial): Still didn't get it."\
" Status: %X\n", lastError);
break;
}
//Fall Through
case ERROR_SUCCESS:
RtlInitAnsiString(&aResult, pPartialValue->Data);
break;
}
ExFreePool(pPartialValue);

//Try to read the whole thing, using the PKEY_VALUE_FULL_INFORMATION.
memset(pFullValue, 0, structLength);
lastError = ZwQueryValueKey(&hFolder, &uName, \
KeyValueFullInformation, pFullValue, structLength, \
&dataLength);
switch(lastError)
{
case STATUS_INVALID_HANDLE: //Always end up here.
DbgPrint("ZwQueryValueKey(Full) says the handle is bogus.\n");
break;
case STATUS_BUFFER_OVERFLOW:
//Since it failed because of insufficient storage, allocate enough.
ExFreePool(pFullValue);
structLength = sizeof(KEY_VALUE_FULL_INFORMATION) + \
dataLength + sizeof(UNICODE_NULL);
pFullValue = (PKEY_VALUE_FULL_INFORMATION)\
ExAllocatePool(PagedPool, structLength);
lastError = ZwQueryValueKey(&hFolder, &uName, \
KeyValueFullInformation, pFullValue, \
structLength, &dataLength);
if(lastError != ERROR_SUCCESS)
{
//Just give it up. Shouldn't get here, either.
DbgPrint("ZwQueryValueKey(Full): Still didn't get it."\
" Status: %X\n", lastError);
break;
}
//Fall Through
case ERROR_SUCCESS:
RtlInitUnicodeString(&uResult, pFullValue->Name);
RtlInitUnicodeString(&uResult, (PWCHAR)(pFullValue +
pFullValue->DataOffset));
break;
}
ExFreePool(pFullValue);

return ERROR_SUCCESS;

Thanks,

Phil

* Philip D. Barila | (503) 264-8386
* Intel Corp. | M/S JF2-53 Office JF2-2-G6
* Storage Architecture and Performance
* Internet Systems Lab

Comments

  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    I hate to reply to my own message, especially when it's to point at myself
    and laugh, but I found the source of my problem. Somehow, in a flurry of
    activity, I managed to toss in the & symbol on the handle to the open key.
    So instead of passing a handle, I was passing a pointer to a handle. Why it
    would work on one call but not another is a mystery, but the reason the
    compiler didn't catch it is that ultimately, a HANDLE is just a pointer to
    void, so one pointer is as good as another, and the compiler didn't complain
    about the extra indirection. @#$%^!

    Phil

    -----Original Message-----
    From: Barila, Phil [mailto:[email protected]]
    Sent: Thursday, July 27, 2000 6:17 PM
    To: NT Developers Interest List
    Subject: [ntdev] Possible to read values from registry in DriverEntry?


    Any Win9X wizards on this list? Is there a better list on which I could ask
    this question?

    I'm doing a Win98 miniport, which needs to get a value out of the registry
    in the DriverEntry routine, and I'm not having any success.

    I can open a key, and read the name of the value I'm looking for, but I
    can't read the value itself. Since I already know the name of the value,
    being able to retrieve it really doesn't help much. But it does appear to
    validate that the ZwOpenKey call is returning a valid handle. Doesn't it?

    Below is the code demonstrating the problem. I've tried ZwCreateKey with
    the same options as ZwOpenKey, and it didn't work any better. Any
    suggestions for different options, incantations, or other secret sauce that
    might make this work?

    UNICODE_STRING uPath, uName, uResult;
    ANSI_STRING aResult;
    HANDLE hFolder = NULL;
    OBJECT_ATTRIBUTES objAttribs;
    NTSTATUS lastError = STATUS_SUCCESS;
    ULONG dataLength = 0x80;
    ULONG structLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + \
    dataLength + sizeof(UNICODE_NULL);
    PKEY_VALUE_BASIC_INFORMATION pBasicValue = NULL;
    PKEY_VALUE_PARTIAL_INFORMATION pPartialValue = NULL;
    PKEY_VALUE_FULL_INFORMATION pFullValue = NULL;
    pBasicValue = (PKEY_VALUE_BASIC_INFORMATION) \
    ExAllocatePool(PagedPool, structLength);
    pPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION) \
    ExAllocatePool(PagedPool, structLength);
    pFullValue = (PKEY_VALUE_FULL_INFORMATION) \
    ExAllocatePool(PagedPool, structLength);

    RtlInitUnicodeString(&uPath, L"\\Registry\\Machine\\System\\"\
    L"CurrentControlSet\\Services\\Class\\Dummy");
    RtlInitUnicodeString(&uName, L"Target");

    InitializeObjectAttributes(&objAttribs, &uPath, \
    OBJ_CASE_INSENSITIVE, NULL, NULL);

    lastError = ZwOpenKey(&hFolder, KEY_ALL_ACCESS, &objAttribs);

    if(lastError != ERROR_SUCCESS)
    {
    DbgPrint("Couldn't open key: %s. Ending function.\n", pKeyPath);
    return lastError;
    }

    //Try to verify that the name is what I think it is.
    memset(pBasicValue, 0, structLength);
    lastError = ZwQueryValueKey(&hFolder, &uName, KeyValueBasicInformation, \
    pBasicValue, structLength,
    &dataLength);
    switch(lastError)
    {
    case STATUS_INVALID_HANDLE:
    //We're dead in the water here. Should never get here!
    DbgPrint("ZwQueryValueKey(Basic) says the handle is bogus.\n");
    break;
    case STATUS_BUFFER_OVERFLOW:
    //Since it failed because of insufficient storage, allocate enough.
    ExFreePool(pBasicValue);
    structLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + dataLength + \
    sizeof(UNICODE_NULL);
    pBasicValue = (PKEY_VALUE_BASIC_INFORMATION) \
    ExAllocatePool(PagedPool, structLength);
    lastError = ZwQueryValueKey(&hFolder, &uName, \
    KeyValueBasicInformation, pBasicValue, \
    structLength, &dataLength);
    if(lastError != ERROR_SUCCESS)
    {
    //Just give it up. Shouldn't get here, either.
    DbgPrint("ZwQueryValueKey(Basic): Still didn't get it. "\
    "Status: %X\n", lastError);
    break;
    }
    //Fall Through
    case ERROR_SUCCESS:
    RtlInitUnicodeString(&uResult, pBasicValue->Name);
    break;
    }
    ExFreePool(pBasicValue);

    //Try to read the value, using the PKEY_VALUE_PARTIAL_INFORMATION.
    memset(pPartialValue, 0, structLength);
    lastError = ZwQueryValueKey(&hFolder, &uName, \
    KeyValuePartialInformation, pPartialValue, \
    structLength, &dataLength);
    switch(lastError)
    {
    case STATUS_INVALID_HANDLE: //Always end up here.
    DbgPrint("ZwQueryValueKey(Partial) says the handle is bogus.\n");
    break;
    case STATUS_BUFFER_OVERFLOW:
    //Since it failed because of insufficient storage, allocate enough.
    ExFreePool(pPartialValue);
    structLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + \
    dataLength + sizeof(UNICODE_NULL);
    pPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)\
    ExAllocatePool(PagedPool, structLength);
    lastError = ZwQueryValueKey(&hFolder, &uName, \
    KeyValuePartialInformation, pPartialValue, \
    structLength, &dataLength);
    if(lastError != ERROR_SUCCESS)
    {
    //Just give it up. Shouldn't get here, either.
    DbgPrint("ZwQueryValueKey(Partial): Still didn't get it."\
    " Status: %X\n", lastError);
    break;
    }
    //Fall Through
    case ERROR_SUCCESS:
    RtlInitAnsiString(&aResult, pPartialValue->Data);
    break;
    }
    ExFreePool(pPartialValue);

    //Try to read the whole thing, using the PKEY_VALUE_FULL_INFORMATION.
    memset(pFullValue, 0, structLength);
    lastError = ZwQueryValueKey(&hFolder, &uName, \
    KeyValueFullInformation, pFullValue, structLength, \
    &dataLength);
    switch(lastError)
    {
    case STATUS_INVALID_HANDLE: //Always end up here.
    DbgPrint("ZwQueryValueKey(Full) says the handle is bogus.\n");
    break;
    case STATUS_BUFFER_OVERFLOW:
    //Since it failed because of insufficient storage, allocate enough.
    ExFreePool(pFullValue);
    structLength = sizeof(KEY_VALUE_FULL_INFORMATION) + \
    dataLength + sizeof(UNICODE_NULL);
    pFullValue = (PKEY_VALUE_FULL_INFORMATION)\
    ExAllocatePool(PagedPool, structLength);
    lastError = ZwQueryValueKey(&hFolder, &uName, \
    KeyValueFullInformation, pFullValue, \
    structLength, &dataLength);
    if(lastError != ERROR_SUCCESS)
    {
    //Just give it up. Shouldn't get here, either.
    DbgPrint("ZwQueryValueKey(Full): Still didn't get it."\
    " Status: %X\n", lastError);
    break;
    }
    //Fall Through
    case ERROR_SUCCESS:
    RtlInitUnicodeString(&uResult, pFullValue->Name);
    RtlInitUnicodeString(&uResult, (PWCHAR)(pFullValue +
    pFullValue->DataOffset));
    break;
    }
    ExFreePool(pFullValue);

    return ERROR_SUCCESS;

    Thanks,

    Phil

    * Philip D. Barila | (503) 264-8386
    * Intel Corp. | M/S JF2-53 Office JF2-2-G6
    * Storage Architecture and Performance
    * Internet Systems Lab



    ---
    You are currently subscribed to ntdev as: [email protected]
    To unsubscribe send a blank email to $subst('Email.Unsub')
  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    When does the driver load?
    I know that on NT there are load phases when Registry hasn't been loaded, yet.
    In that case, you should read registry later on...

    Unfortunatelly, I'm no Win9x wizard :)

    Giga

    "Barila, Phil" wrote:

    > Any Win9X wizards on this list? Is there a better list on which I could ask
    > this question?
    >
    > I'm doing a Win98 miniport, which needs to get a value out of the registry
    > in the DriverEntry routine, and I'm not having any success.
    >
    > I can open a key, and read the name of the value I'm looking for, but I
    > can't read the value itself. Since I already know the name of the value,
    > being able to retrieve it really doesn't help much. But it does appear to
    > validate that the ZwOpenKey call is returning a valid handle. Doesn't it?
    >
    > Below is the code demonstrating the problem. I've tried ZwCreateKey with
    > the same options as ZwOpenKey, and it didn't work any better. Any
    > suggestions for different options, incantations, or other secret sauce that
    > might make this work?
    >
    > UNICODE_STRING uPath, uName, uResult;
    > ANSI_STRING aResult;
    > HANDLE hFolder = NULL;
    > OBJECT_ATTRIBUTES objAttribs;
    > NTSTATUS lastError = STATUS_SUCCESS;
    > ULONG dataLength = 0x80;
    > ULONG structLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + \
    > dataLength + sizeof(UNICODE_NULL);
    > PKEY_VALUE_BASIC_INFORMATION pBasicValue = NULL;
    > PKEY_VALUE_PARTIAL_INFORMATION pPartialValue = NULL;
    > PKEY_VALUE_FULL_INFORMATION pFullValue = NULL;
    > pBasicValue = (PKEY_VALUE_BASIC_INFORMATION) \
    > ExAllocatePool(PagedPool, structLength);
    > pPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION) \
    > ExAllocatePool(PagedPool, structLength);
    > pFullValue = (PKEY_VALUE_FULL_INFORMATION) \
    > ExAllocatePool(PagedPool, structLength);
    >
    > RtlInitUnicodeString(&uPath, L"\\Registry\\Machine\\System\\"\
    > L"CurrentControlSet\\Services\\Class\\Dummy");
    > RtlInitUnicodeString(&uName, L"Target");
    >
    > InitializeObjectAttributes(&objAttribs, &uPath, \
    > OBJ_CASE_INSENSITIVE, NULL, NULL);
    >
    > lastError = ZwOpenKey(&hFolder, KEY_ALL_ACCESS, &objAttribs);
    >
    > if(lastError != ERROR_SUCCESS)
    > {
    > DbgPrint("Couldn't open key: %s. Ending function.\n", pKeyPath);
    > return lastError;
    > }
    >
    > //Try to verify that the name is what I think it is.
    > memset(pBasicValue, 0, structLength);
    > lastError = ZwQueryValueKey(&hFolder, &uName, KeyValueBasicInformation, \
    > pBasicValue, structLength,
    > &dataLength);
    > switch(lastError)
    > {
    > case STATUS_INVALID_HANDLE:
    > //We're dead in the water here. Should never get here!
    > DbgPrint("ZwQueryValueKey(Basic) says the handle is bogus.\n");
    > break;
    > case STATUS_BUFFER_OVERFLOW:
    > //Since it failed because of insufficient storage, allocate enough.
    > ExFreePool(pBasicValue);
    > structLength = sizeof(KEY_VALUE_BASIC_INFORMATION) + dataLength + \
    > sizeof(UNICODE_NULL);
    > pBasicValue = (PKEY_VALUE_BASIC_INFORMATION) \
    > ExAllocatePool(PagedPool, structLength);
    > lastError = ZwQueryValueKey(&hFolder, &uName, \
    > KeyValueBasicInformation, pBasicValue, \
    > structLength, &dataLength);
    > if(lastError != ERROR_SUCCESS)
    > {
    > //Just give it up. Shouldn't get here, either.
    > DbgPrint("ZwQueryValueKey(Basic): Still didn't get it. "\
    > "Status: %X\n", lastError);
    > break;
    > }
    > //Fall Through
    > case ERROR_SUCCESS:
    > RtlInitUnicodeString(&uResult, pBasicValue->Name);
    > break;
    > }
    > ExFreePool(pBasicValue);
    >
    > //Try to read the value, using the PKEY_VALUE_PARTIAL_INFORMATION.
    > memset(pPartialValue, 0, structLength);
    > lastError = ZwQueryValueKey(&hFolder, &uName, \
    > KeyValuePartialInformation, pPartialValue, \
    > structLength, &dataLength);
    > switch(lastError)
    > {
    > case STATUS_INVALID_HANDLE: //Always end up here.
    > DbgPrint("ZwQueryValueKey(Partial) says the handle is bogus.\n");
    > break;
    > case STATUS_BUFFER_OVERFLOW:
    > //Since it failed because of insufficient storage, allocate enough.
    > ExFreePool(pPartialValue);
    > structLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + \
    > dataLength + sizeof(UNICODE_NULL);
    > pPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)\
    > ExAllocatePool(PagedPool, structLength);
    > lastError = ZwQueryValueKey(&hFolder, &uName, \
    > KeyValuePartialInformation, pPartialValue, \
    > structLength, &dataLength);
    > if(lastError != ERROR_SUCCESS)
    > {
    > //Just give it up. Shouldn't get here, either.
    > DbgPrint("ZwQueryValueKey(Partial): Still didn't get it."\
    > " Status: %X\n", lastError);
    > break;
    > }
    > //Fall Through
    > case ERROR_SUCCESS:
    > RtlInitAnsiString(&aResult, pPartialValue->Data);
    > break;
    > }
    > ExFreePool(pPartialValue);
    >
    > //Try to read the whole thing, using the PKEY_VALUE_FULL_INFORMATION.
    > memset(pFullValue, 0, structLength);
    > lastError = ZwQueryValueKey(&hFolder, &uName, \
    > KeyValueFullInformation, pFullValue, structLength, \
    > &dataLength);
    > switch(lastError)
    > {
    > case STATUS_INVALID_HANDLE: //Always end up here.
    > DbgPrint("ZwQueryValueKey(Full) says the handle is bogus.\n");
    > break;
    > case STATUS_BUFFER_OVERFLOW:
    > //Since it failed because of insufficient storage, allocate enough.
    > ExFreePool(pFullValue);
    > structLength = sizeof(KEY_VALUE_FULL_INFORMATION) + \
    > dataLength + sizeof(UNICODE_NULL);
    > pFullValue = (PKEY_VALUE_FULL_INFORMATION)\
    > ExAllocatePool(PagedPool, structLength);
    > lastError = ZwQueryValueKey(&hFolder, &uName, \
    > KeyValueFullInformation, pFullValue, \
    > structLength, &dataLength);
    > if(lastError != ERROR_SUCCESS)
    > {
    > //Just give it up. Shouldn't get here, either.
    > DbgPrint("ZwQueryValueKey(Full): Still didn't get it."\
    > " Status: %X\n", lastError);
    > break;
    > }
    > //Fall Through
    > case ERROR_SUCCESS:
    > RtlInitUnicodeString(&uResult, pFullValue->Name);
    > RtlInitUnicodeString(&uResult, (PWCHAR)(pFullValue +
    > pFullValue->DataOffset));
    > break;
    > }
    > ExFreePool(pFullValue);
    >
    > return ERROR_SUCCESS;
    >
    > Thanks,
    >
    > Phil
    >
    > * Philip D. Barila | (503) 264-8386
    > * Intel Corp. | M/S JF2-53 Office JF2-2-G6
    > * Storage Architecture and Performance
    > * Internet Systems Lab
    >
    > ---
    > You are currently subscribed to ntdev as: [email protected]
    > To unsubscribe send a blank email to $subst('Email.Unsub')

    --
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Gregory Giguashvili
    Software Engineer
    Email: [email protected]
    Tel: 972-9-9709379 Fax: 972-3-9709337
    Paradigm Geophysical Ltd.
    http://www.math.tau.ac.il/~gregoryg
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. Sign in or register to get started.

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Kernel Debugging 13-17 May 2024 Live, Online
Developing Minifilters 1-5 Apr 2024 Live, Online
Internals & Software Drivers 11-15 Mar 2024 Live, Online
Writing WDF Drivers 20-24 May 2024 Live, Online