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

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:xxxxx@intel.com]
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: xxxxx@intel.com
To unsubscribe send a blank email to $subst(‘Email.Unsub’)

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 :slight_smile:

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: xxxxx@ParadigmGeo.com
To unsubscribe send a blank email to $subst(‘Email.Unsub’)

Gregory Giguashvili  
Software Engineer  
Email: xxxxx@ParadigmGeo.com  
Tel: 972-9-9709379 Fax: 972-3-9709337  
Paradigm Geophysical Ltd.  
http://www.math.tau.ac.il/~gregoryg