Discussion:
Questions on reading registry keys with calls to Kernel32.dll
(too old to reply)
T
2019-12-29 01:11:39 UTC
Permalink
Hi All,

Questions on reading registry keys with calls to Kernel32.dll:

References:

https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regopenkeyexw
https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey
https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryvalueexw


I am trying to read the value of this key:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System]
"EnableLUA"=dword:00000000
https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regopenkeyexw
https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey
https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryvalueexw

Am I correct that to read a registry key, you must
1) open the key,
2) read the value,
3) close the key?

In these calls, are the pointers 32 bit or 64 bit depending on the
version of Windows?

To open the key, I must call
LSTATUS RegOpenKeyExW(
HKEY hKey,
LPCWSTR lpSubKey,
DWORD ulOptions,
REGSAM samDesired,
PHKEY phkResult
);

1) Is hKey is the handle of the key I just opened? And I need to keep
track of (save) it.

2) Is this the same hKey used in RegQueryValueExW and RegCloseKey?

LSTATUS RegQueryValueExW(
HKEY hKey,
LPCWSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
);
LSTATUS RegCloseKey(
HKEY hKey
);


what is “lpSubKey”?

1) is “lpSubKey”

\Microsoft\Windows\CurrentVersion\Policies\System
or
\Microsoft\Windows\CurrentVersion\Policies\System\EnableLUA
or something else?

2) forward slashes or back slashes?

3) does it use a starting slash?

4) does it use an ending slash?


RegQueryValueExW

1) what is lpSubKey?

EnableLUA
or
\Microsoft\Windows\CurrentVersion\Policies\System\EnableLUA
or something else

Many thanks,
-T
R.Wieser
2019-12-29 08:27:47 UTC
Permalink
T,
Post by T
Am I correct that to read a registry key, you must
1) open the key,
2) read the value,
3) close the key?
Thats the standard way to do it, yes.

But as the example at the bottom of the the "RegQueryValueExW" link you
posted shows (!) it can be done directly.
Post by T
In these calls, are the pointers 32 bit or 64 bit depending on the version
of Windows?
Yes.
Post by T
1) Is hKey is the handle of the key I just opened?
No. For that to be possible that argument would need to be a pointer to a
variable, which it isn't.

You need to provide a pointer to a variable that will receive the handle
thru the "phkResult" argument.
Post by T
2) Is this the same hKey used in RegQueryValueExW and RegCloseKey?
No for both. But 'yes' if you mean the by "phkResult" returned handle.

In the above "hKey" is either the handle to an already open key, or a
constant value indicating one of the 'hives', in your case
HKEY_LOCAL_MACHINE (a constant with the value 0x80000002)
Post by T
1) is "lpSubKey"
\Microsoft\Windows\CurrentVersion\Policies\System
In your case, yes. And you need to provide "EnableLUA" as the
"lpValueName" argument to the "RegQueryValueExW" call.

Hope that helps.

Regards,
Rudy Wieser
T
2019-12-29 10:43:31 UTC
Permalink
Post by R.Wieser
T,
Post by T
Am I correct that to read a registry key, you must
1) open the key,
2) read the value,
3) close the key?
Thats the standard way to do it, yes.
But as the example at the bottom of the the "RegQueryValueExW" link you
posted shows (!) it can be done directly.
Post by T
In these calls, are the pointers 32 bit or 64 bit depending on the version
of Windows?
Yes.
Post by T
1) Is hKey is the handle of the key I just opened?
No. For that to be possible that argument would need to be a pointer to a
variable, which it isn't.
You need to provide a pointer to a variable that will receive the handle
thru the "phkResult" argument.
Post by T
2) Is this the same hKey used in RegQueryValueExW and RegCloseKey?
No for both. But 'yes' if you mean the by "phkResult" returned handle.
In the above "hKey" is either the handle to an already open key, or a
constant value indicating one of the 'hives', in your case
HKEY_LOCAL_MACHINE (a constant with the value 0x80000002)
Post by T
1) is "lpSubKey"
\Microsoft\Windows\CurrentVersion\Policies\System
In your case, yes. And you need to provide "EnableLUA" as the
"lpValueName" argument to the "RegQueryValueExW" call.
Hope that helps.
Regards,
Rudy Wieser
Thank you!
T
2019-12-29 19:47:32 UTC
Permalink
Followup,

Hi Rudy,

You helped me track down what my problem was.
I am programming this is Raku/Pel6 using Native call.
Native Call translates a zero into a C NULL. I thought
the error was being caused by and incorrect NULL being
sent to lpReserved.

The culprit was M$ and lpType.

https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryvalueexw

C++
LSTATUS RegQueryValueExW(
HKEY hKey,
LPCWSTR lpValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData
);

lpType

A pointer to a variable that receives a code
indicating the type of data stored in the
specified value. For a list of the possible
type codes, see Registry Value Types. The
lpType parameter can be NULL if the type code
is not required.

I was sending lpType the value for REG_DWORD (0x00000004)
and sometimes REG_SZ (0x00000001). This caused
the call to die with no error message.

The ONLY value of lpType that actually works is 0
(NULL).

Ha! M$ STRIKES AGAIN! Good gracious I wasted and
a lot of others helping me wasted a lot of time on this!

<Editorial comment> AAAAAAHHHHHHH!!!!!!! </Editorial commend>

Thank you again for the wonderful help. You helped me
find the error.

-T
T
2019-12-29 22:25:27 UTC
Permalink
T,
Post by T
I was sending lpType the value for REG_DWORD (0x00000004)
...
Post by T
The ONLY value of lpType that actually works is 0
(NULL).
Providing a value of 0 (NULL) to lpType means that you are not interrested
in the type of the value stored in the registry.
Sendinhg it REG_DWORD (0x00000004) and sometimes REG_SZ
(0x00000001) caused the call to exit everyhting without
an error message
Post by T
Ha! M$ STRIKES AGAIN!
Are you sure it was MS'es doing ?
How did you provide the above 0 (NULL) to "lpType" ? You see, "lpType"
expects a POINTER (hence the lowercase "p" before the name), just as the
"lpcbData" argument in your post (or "cbData" in the example).
In other words, just as with "lpcbData" you need to provide a /pointer to a
variable/ in which the returned value type will be stored.
Raku's Native call convert's a zero into a NULL. And by
defination a NULL pointer in C is an address that points
to zero.

Native Call also converts lpcbData into the value it points at.

sub RegQueryValueExW(

DWORD,

WCHARS,

DWORD,

DWORD,

DWORD is rw,

DWORD is rw

)

is native("Kernel32.dll")

is symbol("RegQueryValueExW")

returns DWORD

{ * };




$RtnCode = RegQueryValueExW(
$Handle, $lpValueName, 0, 0, $lpData, $lpcbData );


NULLs..........................^..^

Interesting about the "p" being for "pointer". That one
I did not guess at. I have been doing a lot of guessing!

Thank you again for the wonder education!
-T
Regards,
Rudy Wieser
Kaz Kylheku
2019-12-30 02:10:15 UTC
Permalink
Post by T
Raku's Native call convert's a zero into a NULL. And by
defination a NULL pointer in C is an address that points
to zero.
That simply isn't so; it's just how null pointers work on a lot of
mainstream platforms. ISO C doesn't say anything about the
representation of the null pointer. (void *) 0 could have the bit
pattern 0xFFFFFFFF in a conforming implementation. A lot of programs
would break there, which would be due to not being written in an ISO C
conforming way.

An common example of a nonportability in this regard is using
memset(obj, 0, sizeof obj) to initialize an object which contains
pointers, expecting them to be null.
T
2020-01-02 17:33:41 UTC
Permalink
Post by Kaz Kylheku
That simply isn't so; it's just how null pointers work on a lot of
mainstream platforms. ISO C doesn't say anything about the
representation of the null pointer. (void *) 0 could have the bit
pattern 0xFFFFFFFF in a conforming implementation. A lot of programs
would break there, which would be due to not being written in an ISO C
conforming way.
An common example of a nonportability in this regard is using
memset(obj, 0, sizeof obj) to initialize an object which contains
pointers, expecting them to be null.
Hi Kaz,

In my limited world view, I am only dealing with C calls to Windows
API's. Maybe Linux .so's in the future.

But I will keep it in mind!

:-)

-T

I am having a hard enough time dealing with when their
integers are backward or forwards! :'(

R.Wieser
2019-12-30 07:25:20 UTC
Permalink
T,
Sendinhg it REG_DWORD (0x00000004) and sometimes REG_SZ (0x00000001)
caused the call to exit everyhting without an error message
Yes. And that is because you are POINTING at some memory address thats not
yours. Which means you get an acces violation and your program crashes.
Raku's Native call convert's a zero into a NULL.
It does not need to, as those are, value wise, exactly the same thing (in
other words, you are looking at a bit of sematic sugar).
And by defination a NULL pointer in C is an address that points to zero.
Thats true. But the function handles it as a special case, as a "No, I
(you!) do not want to know the type of the value (stored in the registry)".
In short, it (the function) will not try to write that value type.

... but if that argument is /anything else/ than a NULL value it will. And
you better make sure that when that happens the target is in some memory you
own (as in: a variable).

sub RegQueryValueExW(
DWORD,
WCHARS,
DWORD,
DWORD, <== This one is rw too !
DWORD is rw,
DWORD is rw
)
$RtnCode = RegQueryValueExW(
$Handle, $lpValueName, 0, 0, $lpData, $lpcbData );
NULLs..........................^..^
Nope, not in your case. /You/ have been trying to change that second/last
NULL into an indication which type to return. Byut it doesn't work that
way (you cannot tell it what type to return).

The value in the variable (you should be pointing at if the argument is
non-NULL) is fully ignored, and just gets overwritten.

Try this:

$RtnCode = RegQueryValueExW(
$Handle, $lpValueName, 0, $lpType, $lpData, $lpcbData );
Interesting about the "p" being for "pointer". That one
I did not guess at.
Just don't assume it will always be there though. Its upto the writer of
the program (you) or document (MS) to make up good argument names. As the
MS documentation spans a couple of decades you might run into old ones which
do not use it.
I have been doing a lot of guessing!
Thats good ! But do remember to read those MS docs if-and-when you get into
trouble.

From the "RegQueryValueExW" MS link you posted:

[quote]
lpType

A POINTER TO A VARIABLE that receives a code indicating the type of data
stored in the specified value.
[/quote]

And yes, I do realize that you probably are a newbie in this regard, and had
a /lot/ to look at and absorb. Don't worry about that. :-)
Thank you again for the wonder education!
:-) You're welcome.

Regards,
Rudy Wieser
Loading...