On Sun, 01 Apr 2001, you wrote:
> At 01:59 PM 31/03/2001 +0100, you wrote:
>
> <snip>
> >Compiling and running Winemine under Windows 95 this problem doesn't occur.
> >Win95 truncates the value at the first null.
>
> Under NT4 SP6, if I write (for example) '47' + 0 + 13 bytes of garbage, I get
> exactly that when querying with the same buffer length (16).
> If I use a longer buffer, one binary 0 is appended.
> If I use a shorter buffer, nothing is copied and the function does not succeed
> (ERROR_MORE_DATA).
>
> Of course under Regedit the garbage is not displayed; regedit displays only '47'
> in this case.
I've found time to do some more digging, but I'm still stumped.
This is the trace from WineMine saving one parameter in the registry (-debugmsg
+relay,+reg):
Call advapi32.248: RegSetValueExA(00000038,4038cae0 "Xpos",00000000,00000001,405e66a0,00000010) ret=40388dc8 fs=008f
Call kernel32.643: MultiByteToWideChar(00000000,00000000,405e66a0 "3",00000010,00000000,00000000) ret=407c4fe9 fs=008f
Ret kernel32.643: MultiByteToWideChar() retval=00000010 ret=407c4fe9 fs=008f
Call kernel32.553: HeapAlloc(40390000,00000000,00000020) ret=407c4fff fs=008f
Ret kernel32.553: HeapAlloc() retval=403d62fc ret=407c4fff fs=008f
Call kernel32.643: MultiByteToWideChar(00000000,00000000,405e66a0 "3",00000010,403d62fc,00000010) ret=407c5023 fs=008f
Ret kernel32.643: MultiByteToWideChar() retval=00000010 ret=407c5023 fs=008f
Call ntdll.419: RtlInitAnsiString(405e658c,4038cae0 "Xpos") ret=407c5038 fs=008f
Ret ntdll.419: RtlInitAnsiString() retval=00000000 ret=407c5038 fs=008f
Call ntdll.281: RtlAnsiStringToUnicodeString(40113578,405e658c,00000000) ret=407c504d fs=008f
Ret ntdll.281: RtlAnsiStringToUnicodeString() retval=00000000 ret=407c504d fs=008f
Call ntdll.230: NtSetValueKey(00000038,40113578,00000000,00000001,403d62fc,00000020) ret=407c5067 fs=008f
trace:reg:NtSetValueKey (0x38,L"Xpos",1,0x403d62fc,32)
Ret ntdll.230: NtSetValueKey() retval=00000000 ret=407c5067 fs=008f
Call kernel32.559: HeapFree(40390000,00000000,403d62fc) ret=407c5083 fs=008f
Ret kernel32.559: HeapFree() retval=00000001 ret=407c5083 fs=008f
Call ntdll.466: RtlNtStatusToDosError(00000000) ret=407c5089 fs=008f
Ret ntdll.466: RtlNtStatusToDosError() retval=00000000 ret=407c5089 fs=008f
Ret advapi32.248: RegSetValueExA() retval=00000000 ret=40388dc8 fs=008f
So the 16-byte buffer (containing the character "3", a null, and 14 bytes of
garbage) has been converted into a 32-byte unicode string and saved. Good.
Inside the registry this looks like:
"Xpos"="3\0\0\0`\x00ca7@\0\0\0\0\0\0\0@"
Now if we read that value back in this is what happens:
Call advapi32.236: RegQueryValueExA(00000034,4038cae0 "Xpos",00000000,405e6970,405e697c,405e6974) ret=40388a38 fs=008f
trace:reg:RegQueryValueExA (0x34,"Xpos",(nil),0x405e6970,0x405e697c,0x405e6974=16)
Call ntdll.419: RtlInitAnsiString(405e6764,4038cae0 "Xpos") ret=407c5565 fs=008f
Ret ntdll.419: RtlInitAnsiString() retval=00000000 ret=407c5565 fs=008f
Call ntdll.281: RtlAnsiStringToUnicodeString(40113578,405e6764,00000000) ret=407c557a fs=008f
Ret ntdll.281: RtlAnsiStringToUnicodeString() retval=00000000 ret=407c557a fs=008f
Call ntdll.177: NtQueryValueKey(00000034,40113578,00000002,405e676c,00000100,405e6760) ret=407c55b0 fs=008f
trace:reg:NtQueryValueKey (0x34,L"Xpos",2,0x405e676c,256)
Ret ntdll.177: NtQueryValueKey() retval=00000000 ret=407c55b0 fs=008f
Call kernel32.889: WideCharToMultiByte(00000000,00000000,405e6778 L"3",00000011,00000000,00000000,00000000,00000000) ret=407c56c9 fs=008f
Ret kernel32.889: WideCharToMultiByte() retval=00000011 ret=407c56c9 fs=008f
Call ntdll.466: RtlNtStatusToDosError(80000005) ret=407c57be fs=008f
Ret ntdll.466: RtlNtStatusToDosError() retval=000000ea ret=407c57be fs=008f
Ret advapi32.236: RegQueryValueExA() retval=000000ea ret=40388a38 fs=008f
RegQueryValueEx maintains that there are 17 characters and since they won't fit
in the buffer the function aborts.
Incidentally, the "null-terminate if the user forgot" trick is carried out both
in RegSetValueEx *and* RegQueryValueEx. Would not once be enough?
--
Dave Pickles