Question

I cant figure out why i get back a unicode string with extra character per letter

Private Declare PtrSafe Function RegQueryValueEx Lib "advapi32.dll"
Alias "RegQueryValueExA" (ByVal hKey As LongPtr, ByVal lpValueName As String,
                          ByVal lpReserved As LongPtr, lpType As LongPtr,
                          lpData As Any, lpcbData As LongPtr) As LongPtr


If RegQueryValueEx(hKey, strValueName, 0, dwType,
                   ByVal RegData, lDataBufSize) = ERROR_SUCCESS Then
End If

RegData has the following value "Mobile Address Book" but if you paste that in notepad you will see all the extra characters. Do i need to convert the string to ascii?

Was it helpful?

Solution

VBA uses Unicode strings, but you are calling the Ansi version of RegQueryValueEx() (RegQueryValueExA) instead of the Unicode version (RegQueryValueExW). But in both cases, the 5th parameter will receive raw Ansi/Unicode data (depending on version called) and the 6th parameter is expressed in bytes, not in characters. So you have to account for that. You also have to account for the fact that Declare in VBA always converts String values to Ansi, never to Unicode. To work with Unicode APIs using Unicode strings in VBA, have a look at the following article for hints:

VBA: Unicode Strings and the Windows API

For example:

Private Declare PtrSafe Function RegQueryValueEx Lib "advapi32.dll"
Alias "RegQueryValueExW" (ByVal hKey As LongPtr, ByVal lpValueName As LongPtr,
                          ByVal lpReserved As LongPtr, lpType As LongPtr,
                          ByVal lpData As LongPtr, lpcbData As LongPtr) As LongPtr


If RegQueryValueEx(hKey, StrPtr(strValueName), 0, dwType,
                   StrPtr(RegData), lDataBufSize) = ERROR_SUCCESS Then
End If

Just make sure that RegData is pre-allocated to the required number of Unicode characters needed to receive the Unicode text, and that lDataBufSize is initialized with the number of bytes allocated in RegData so RegQueryValueExW() knows how many characters it can write into RegData.

Update: to read binary data:

Private Declare PtrSafe Function RegQueryValueEx Lib "advapi32.dll"
Alias "RegQueryValueExW" (ByVal hKey As LongPtr, ByVal lpValueName As LongPtr,
                          ByVal lpReserved As LongPtr, lpType As LongPtr,
                          lpData As Byte, lpcbData As LongPtr) As LongPtr


Dim RegData() As Byte
...
If RegQueryValueEx(hKey, StrPtr(strValueName), 0, dwType,
                   RegData(0), lDataBufSize) = ERROR_SUCCESS Then
End If
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top