Simple idea:
; edi is dest buffer, esp is addr SizeValBuffer
push -1 ; no limit
invoke RegQueryValueEx, hKey, pValue, 0, addr rkType, edi, esp
pop edx ; balance stack
It works - sometimes. MSDN (http://msdn.microsoft.com/en-us/library/windows/desktop/ms724911%28v=vs.85%29.aspx):
RegQueryValueEx(
_In_ HKEY hKey,
_In_opt_ LPCTSTR lpValueName,
_Reserved_ LPDWORD lpReserved,
_Out_opt_ LPDWORD lpType,
_Out_opt_ LPBYTE lpData,
_Inout_opt_ LPDWORD lpcbData
lpcbData [in, out, optional]
A pointer to a variable that specifies the size of the buffer pointed to by the lpData parameter, in bytes. When the function returns, this variable contains the size of the data copied to lpData.
Only the boyz in Redmond know why it chokes with "unlimited" size. With 65k it works, apparently...
JOCHEN,
Why not call RegQueryValueEx twice ???
Discussion at Raymond Chen's Blog that doesn't even remotely relate to your problem: Beware of Non-Null-Terminated Registry Strings, Aug 2004 (http://blogs.msdn.com/b/oldnewthing/archive/2004/08/24/219444.aspx)
Quote from: Zen on August 27, 2013, 06:01:51 AM
JOCHEN,
Why not call RegQueryValueEx twice ???
Why should I??? ::)
Hi Jochen,
WinDbg has very nice event filter . I could try to find out what an exception occurs there if I had some more lines of your code ( + data definitions )
Hi vertograd,
Nice offer :t
An exe with int 3 before the call to RegQueryValueEx is attached.
If you want to build it yourself, you need the latest version of MB (http://masm32.com/board/index.php?topic=94.0); afterwards, replace \Masm32\MasmBasic\MasmBasic.lib with the attached "special" edition.
include \masm32\MasmBasic\MasmBasic.inc ; download (http://masm32.com/board/index.php?topic=94.0)
Init
mov f2sOlly, 123 ; flag for special edition of MasmBasic.lib
void GetRegVal("HKCR\Applications\qeditor.exe\shell\open\command", 0, "No luck in HKCR/App...")
deb 4, "Registry HKCR", $eax, $Err$()
Inkey
Exit
end start
Expected outcome:
Registry HKCR
$eax "C:\masm32\qeditor.exe" "%1"
$Err$() Operation successfully completed.
UnderWin7-32, it happened to me several times that it returned nothing, although the behaviour was not predictable. Everything is fine, though, since I replaced the push -1 for sizeofdata with 65k....
Quote from: jj2007 on August 27, 2013, 02:16:53 AMpush -1 ; no limit
[...]
A pointer to a variable that specifies the size of the buffer pointed to by the lpData parameter, in bytes.
[...]
Only the boyz in Redmond know why it chokes with "unlimited" size.
you may try it with a valid buffer.
It works for me, Windows XP SP3.
;==============================================================================
include \masm32\include\masm32rt.inc
include \masm32\include\Advapi32.inc
includelib \masm32\lib\Advapi32.lib
;==============================================================================
.data
hKey HKEY 0
cbData dd -1
.code
;==============================================================================
start:
;==============================================================================
mov ebx, alloc(1024*1024*100)
invoke RegOpenKeyEx, HKEY_LOCAL_MACHINE,
chr$("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"),
0,
KEY_QUERY_VALUE,
ADDR hKey
.IF eax != ERROR_SUCCESS
printf("RegOpenKeyEx %s\n\n", LastError$())
.ENDIF
invoke RegQueryValueEx, hKey,
chr$("Identifier"),
NULL,
NULL,
ebx,
ADDR cbData
.IF eax != ERROR_SUCCESS
printf("RegQueryValueEx %s\n\n", LastError$())
.ENDIF
printf("\n%s\n%d\n\n", ebx, cbData)
invoke RegCloseKey, hKey
free ebx
inkey
exit
;==============================================================================
end start
x86 Family 6 Model 7 Stepping 3
32
There is some related information here:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms724872(v=vs.85).aspx/html
But so far I have not been able to determine what "latest format" and "standard format" mean. Perhaps your system is using the standard format.
Jochen, your code passes the buffer that's smaller than the it claimed to be - sometimes system functions check if the targed buffer doesn't satisfy claimed size, and probably if the buffer belongs specific memory location (stack or executable image). For me your code works, it may depend on SP2 vs SP3. Try your code with allocation of a buffer from a heap, not in exe .data? - probably it would work.
Quote from: jj2007 on August 27, 2013, 06:38:46 AM
Quote from: Zen on August 27, 2013, 06:01:51 AM
JOCHEN,
Why not call RegQueryValueEx twice ???
Why should I??? ::)
push 0
invoke RegQueryValueEx,hkey,offset valuename,0,0,0,esp ; lpData is set to zero - function will return the size of the data in variable pointed by lpcbData
; [esp] now is the exact size of the data
call crt_malloc ; the size is already in the stack, and this function doesn't pops it (cdecl).
xchg eax,ebx
invoke RegQueryValueEx,hkey,offset valuename,0,0,ebx,esp
pop edx
EBX now points the buffer with exact data
EDX - the size of the data
You know what they say jj, "garbage in, garbage out". If you pass 4GB as a size you should have a 4GB buffer :P
Quote from: MichaelW on August 27, 2013, 09:52:49 AM
It works for me, Windows XP SP3.
For me, too - even with mov ebx, alloc(1024).
But not always... it's the kind of un-chaseable bug that you find only by sheer coincidence, such as sending myself to google for Visual Basic ;)
@Alex & Zen: Thanks, now I got it. I didn't check for required buffer size simply because the string goes into MB's rotating buffer, and 160k is more than enough.
The whole point is about logic: From a "legal" viewpoint, qWord & sinsi are right - pass a valid buffer size. From a practical viewpoint, passing -1 should signal "don't worry", and the response of the OS should be either "I trust you" or "invalid parameter". As I see it here, Win7-32 responds sometimes with "no problem", and sometimes with "ERROR_NOT_ENOUGH_MEMORY" - which is nonsense when you are waiting for a 20-character string.
So it sometimes crashes with the exact same registry value? Or different ones?
Registry access has changed, admin rights affects things, so does a 32/64 bit OS.
For example, I don't think 32-bit vista/7 have a HKLM\Software\Wow6432Node (btw, can someone confirm this?) and that can be a silent redirect to HKLM\Software.
Quote from: sinsi on August 27, 2013, 05:36:46 PM
So it sometimes crashes with the exact same registry value?
With the same value, but in a slightly different context:
a) launched from my Masm32 folders: OK
b) launched from a temp folder: fails with error 8 (but succeeds if 65k are passed as buffer size)
Jochen,
I and WinDbg didn't found hard-coded breakpoint. Your app runs and terminates correctly here .
There's no exception reports in the debugger.
Might be a permission problem. Add a manifest to run as admin then try from both places.
Quote from: vertograd on August 27, 2013, 06:21:10 PM
Jochen,
I and WinDbg didn't found hard-coded breakpoint. Your app runs and terminates correctly here .
There's no exception reports in the debugger.
Thanxalot to everybody. New version 27b (http://masm32.com/board/index.php?topic=94.0) uses a valid 65k buffer and reports error codes better (MbGuide.rtf, GetRegVal):
- error codes for RegOpenKeyEx are in rvRegKey, those for RegQueryValueEx are in rvRegQuery
A quick guess would be the value is sometimes treated as unsigned and others as signed; so, "-1" would be 4294967295 or -1 -- indicating a huge buffer, or none at all (negative size.) If this is the case, you could probably get away with using 2147483647 (7FFFFFFh) as the largest signed value; though some functions may have been ported directly from their original 16-bit ini-file versions and cause further problems, naturally.
Anyway, if you know your buffer size is 'big enough' why not just pass its size straight in? You should already know its size if you know it's big enough.
If you're only expecting a 20 byte string, why say the buffer is any larger? And if it turns out to be larger, that actually should cause an error because it's an unexpected situation that you're not explicitly handling, which will eventually lead to difficult bugs elsewhere.
This is just corner-cutting for the sake of laziness -- do it right or it will (and should) bite you eventually.
i rarely want to permanently retain the resulting string, anyways
i find it best to:
1) call the function with a null buffer to get the size
2) probe the stack down (as required) to create a temporary buffer
if you are using the Nt functions, they return UNICODE strings that should be 16-aligned :t
so, calculate that alignment into the probe code
3) call the function again with the stack buffer and correct size
good code is bullet-proof - lol
well, almost
i know why Jochen wants to push a -1
it makes for small code :P
JOCHEN,
OK you got it. I was just being annoying. Alex explained perfectly.
Here, is Raymond Chen explaining: More Undocumented Behavior and the People Who Rely On It: Output Buffers, Sept 2005 (http://blogs.msdn.com/b/oldnewthing/archive/2005/09/01/459023.aspx)
...Sort of,...well, OK,...it's resolved,... :dazzled:
"the content of an output item, after a call has failed /absolutely/" (last post in Raymond Chen's log)
I usually try to return a short printable string on failure, like a single question mark, or "La$?" in the case of Launch$() (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1047); in the case of GetRegVal (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1047), you can specify a default string, or zero. No default string means in this case "throw an error".
@Tedd: I have difficulties to see how the same identical code could treat a number sometimes as signed, sometimes as unsigned...
Quote from: Tedd on August 28, 2013, 12:16:04 AM
A quick guess would be the value is sometimes treated as unsigned and others as signed; so, "-1" would be 4294967295 or -1 -- indicating a huge buffer, or none at all (negative size.) If this is the case, you could probably get away with using 2147483647 (7FFFFFFh) as the largest signed value; though some functions may have been ported directly from their original 16-bit ini-file versions and cause further problems, naturally.
Anyway, if you know your buffer size is 'big enough' why not just pass its size straight in? You should already know its size if you know it's big enough.
If you're only expecting a 20 byte string, why say the buffer is any larger? And if it turns out to be larger, that actually should cause an error because it's an unexpected situation that you're not explicitly handling, which will eventually lead to difficult bugs elsewhere.
This is just corner-cutting for the sake of laziness -- do it right or it will (and should) bite you eventually.
Tedd,
I do not understand what you mean by saying the buffer is any larger.
Quote from: jj2007 on August 28, 2013, 07:01:57 AM
@Tedd: I have difficulties to see how the same identical code could treat a number sometimes as signed, sometimes as unsigned...
If it's always the same function call, then obviously not; like I said, it was just a quick guess.
Quote from: Magnum on August 28, 2013, 11:51:36 AM
I do not understand what you mean by saying the buffer is any larger.
"If you're only expecting a 20 byte string, why say the buffer is some arbitrary amount larger?"