Is there any way I can show different types of variables in a MessageBox? I'm working with the Windows API, and I have for example this function:
long R1 = RegOpenKeyEx(hKey, lpSubKey, ulOptions,
samDesired, &phkResult);
The phkResult returns the pointer to the Opened Registry Key, so I would like to show that Registry Key path in a MessageBox.
Can I do that?
Thanks!
Unicode:: MessageBoxW( 0, lpSubKey, L"Reg Key Path", MB_OK ) ;
ANSI:: MessageBoxA( 0, lpSubKey, "Reg Key Path", MB_OK ) ;
Also, if you need the full path with RootKey too, then you have to put that in buffer like::
TCHAR tszRegKeyPath[MAX_PATH] = {0} ;
StringCchPrintf( tszRegKeyPath, _countof(tszRegkeyPath),\
TEXT("__Put_Here_The_Reg_Key_Name_For_Which_You_Have_The_hKey\\%s"), lpSubKey ) ;
MessageBox( 0, tszRegKeyPath, TEXT("Reg Key Path"), MB_OK ) ;
Related
I am trying to call GetComputerNameA from AutoIt, this is my code:
Local $mystruct = DllStructCreate(toStr("struct;dword;char[1024];endstruct"))
DllStructSetData($mystruct, 1, 1024)
Local $result = DllCall("kernel32.dll", "int", "GetComputerNameA", "ptr", DllStructGetPtr($mystruct, 2), "ptr", DllStructGetPtr($mystruct, 1))
MsgBox(0, "AutoIt", "Success")
But after I run it, it doesn't print anything, like the script crashed without errors.
Any idea why it failed to call it?
It has two parameters, specifically:
BOOL GetComputerNameA(
LPSTR lpBuffer,
LPDWORD nSize
);
The first is a LPSTR (pointer to a char array), the second is a LPDWORD (pointer to an unsigned int).
Here is how you'd call that:
Func _get_computer_name()
Local $dll_struct = DllStructCreate("char[17]")
$sz = DllStructCreate('int')
Local $x = DllCall("kernel32.dll","int","GetComputerNameA","ptr",DllStructGetPtr($dll_struct),"int_ptr",DllStructGetPtr($sz))
Return DllStructGetData($dll_Struct,1)
EndFunc
Windows
With Raku/Perl6, how do I use NativeCall to read the value of
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\ "EnableLUA"]
with RegQueryValueExW?
https://learn.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryvalueexw
Many thanks,
-T
edit 12-27-2019 #1: removing bad code and inserting new code
This is how far I have gotten.
Test run string:
K:\Windows\NtUtil>perl6 -I. -e "use WinMount :GetLUA; say GetLUA();"
RegOpenKeyExW
RegOpenKeyExW RtnCode 0
RegQueryValueExW
1
2
RegQueryValueExW RtnCode 87 (87 = ERROR_INVALID_PARAMETER)
lpData pointer 0
lpcbData data length 0
RegCloseKey
RegCloseKey RtnCode 0
True
WinMount.pm6
# unit module WinMount;
# WinMount.pm6#`{
Utilities to mount and dismound drive partitions
Note: LUA must be unset (0x00000000) for mount to function prpoperly
raku -I. -c WinMount.pm6
}
use NativeCall;
use WinPopUps :WinMsg;
# Reference to types and values: http://dsource.org/projects/tango/ticket/820
constant BYTE := uint8;
constant WCHAR := uint16;
constant DWORD := int32;
constant REGSAM := int32;
constant WCHARS := CArray[WCHAR];
constant BYTES := CArray[BYTE];
constant HKEY_CURRENT_USER = 0x80000001;
constant HKEY_LOCAL_MACHINE = 0x80000002;
constant KEY_QUERY_VALUE = 1;
constant ERROR_SUCCESS = 0; # Yeah, I know. The Win-Api uses 0 for success and other values to indicate errors
constant REG_SZ = 1;
constant KEY_READ = 0x20019;
constant KEY_SET_VALUE = 0x0002;
constant REG_DWORD = 0x00000004;
sub to-c-str( Str $str ) returns CArray[WCHAR] is export( :to-c-str ) {
my #str := CArray[WCHAR].new;
for ( $str.comb ).kv -> $i, $char { #str[$i] = $char.ord; }
#str[ $str.chars ] = 0;
#str;
}
sub wstr( Str $str ) returns WCHARS is export( :wstr ) {
CArray[WCHAR].new( $str.comb.map: *.ord )
}
sub GetLUA() is export( :GetLUA ) {
#`{
Returns the LUA value in the registry to True (0x00000001) or False (0x00000000)
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System]
"EnableLUA"=dword:00000000
https://docs.perl6.org/language/nativecall
Win32 return codes:
https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
}
my Str $SubName = &?ROUTINE.name;
my Str $OS = $*KERNEL.name;
if not $OS eq "win32" { say "Sorry, $SubName only work in Windows."; exit; }
my Bool $LUA = True;
my $RtnCode;
my Str $SubKey = Q[SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\];
my Str $Key = Q[EnableLUA];
my $lpSubKey = wstr( $SubKey );
my $lpValueName = wstr( $Key );
# my $lpSubKey = CArray[uint8].new($Key.encode.list);
# my $lpValueName = CArray[uint8].new($SubKey.encode.list);
my int32 $Handle;
my int32 $ulOptions = 0;
my int32 $lpData;
my int32 $lpcbData;
my int32 $lpReserved = 1;
#`{
Open the key:
https://learn.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regopenkeyexw
https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-key-security-and-access-rights
C++
LSTATUS RegOpenKeyExW(
HKEY hKey, # Hive name (HKEY_LOCAL_MACHINE)
LPCWSTR lpSubKey, # path to the key(/SOFTWARE/Microsoft/Windows/CurrentVersion/Policies/System/EnableLUA)
DWORD ulOptions, # 0
REGSAM samDesired, # KEY_READ (0x20019), KEY_SET_VALUE (0x0002)
PHKEY phkResult # A pointer to a variable that receives a handle to the opened key
);
}
say "RegOpenKeyExW";
sub RegOpenKeyExW( DWORD, WCHARS, DWORD, DWORD, DWORD is rw) is native("Kernel32.dll") returns DWORD { * };
$RtnCode = RegOpenKeyExW( HKEY_LOCAL_MACHINE, $lpSubKey, $ulOptions, KEY_READ, $Handle );
say "RegOpenKeyExW RtnCode $RtnCode\n";
#`{
Read the key:
use RegQueryValueExW if you know key and value name
https://learn.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regqueryvalueexw
C++
LSTATUS RegQueryValueExW(
HKEY hKey, # Hive name (HKEY_LOCAL_MACHINE)
LPCWSTR lpValueName, # path to the key(\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\EnableLUA)
LPDWORD lpReserved, # give it "int32" without the quotes to give it a NULL
LPDWORD lpType, # Registry Value Type (REG_DWORD which is 32 bit)
LPBYTE lpData, # Pointer to the return value
LPDWORD lpcbData # number of bytes in the return value
);
}
say "RegQueryValueExW";
sub RegQueryValueExW( DWORD, WCHARS, DWORD, DWORD, DWORD is rw, DWORD is rw ) is native("Kernel32.dll") returns DWORD { * };
say "1";
$RtnCode = RegQueryValueExW( $Handle, $lpValueName, $lpReserved, REG_DWORD, $lpData, $lpcbData );
say "2";
say "RegQueryValueExW RtnCode $RtnCode (87 = ERROR_INVALID_PARAMETER)\nlpData pointer $lpData\nlpcbData data length $lpcbData\n";
#`{
Close the key
https://learn.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regclosekey
C++
LSTATUS RegCloseKey(
HKEY hKey # handle to the open key to be closed. See RegOpenKeyExW phkResult
);
}
say "RegCloseKey";
sub RegCloseKey( DWORD ) is native("Kernel32.dll") returns DWORD { * };
$RtnCode = RegCloseKey( $Handle );
say "RegCloseKey RtnCode $RtnCode\n";
return $LUA;
}
Here's what I have so far. I am able to successfully retrieve the handle for the registry key, but when I try to read the key it throws "Native call expected argument that references a native integer, but got P6int". And I don't know why yet. But I figured I post this already, maybe someone else can shed some light.
use NativeCall;
constant BYTE := uint8;
constant WCHAR := uint16;
constant DWORD := int32;
constant REGSAM := int32;
constant WCHARS := CArray[WCHAR];
constant BYTES := CArray[BYTE];
constant HKEY_CURRENT_USER = 0x80000001;
constant HKEY_LOCAL_MACHINE = 0x80000002;
constant KEY_QUERY_VALUE = 1;
constant ERROR_SUCCESS = 0; # Yeah, I know. The Win-Api uses 0 for success and other values to indicate errors
constant REG_SZ = 1;
sub RegOpenKeyExW( DWORD, WCHARS, DWORD, REGSAM, DWORD is rw) is native("Kernel32.dll") returns DWORD { * };
#DWORD RegOpenKeyExW(
# HKEY hKey,
# LPCWSTR lpSubKey,
# DWORD ulOptions,
# REGSAM samDesired,
# PHKEY phkResult
#);
sub RegQueryValueExW( DWORD, WCHARS, DWORD is rw, DWORD is rw, BYTE is rw, DWORD is rw) is native("Kernel32.dll") returns DWORD { * };
#DWORD RegQueryValueExW(
# HKEY hKey,
# LPCWSTR lpValueName,
# LPDWORD lpReserved,
# LPDWORD lpType,
# LPBYTE lpData,
# LPDWORD lpcbData
#);
my $key = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System';
my DWORD $hkey;
my $length = 1024;
if RegOpenKeyExW(HKEY_LOCAL_MACHINE, wstr($key), 0, KEY_QUERY_VALUE, $hkey) == ERROR_SUCCESS
{
say "Got handle: $hkey";
my BYTES $buffer = CArray[BYTE].new( 0 xx 1024 );
# throws "Native call expected argument that references a native integer, but got P6int"
if RegQueryValueExW( $hkey, WCHARS, DWORD, REG_SZ, $buffer, $length ) == ERROR_SUCCESS
{
say "Got data of length $length";
say gather for 0 .. $length { take $buffer[$_] };
}
}
sub wstr( Str $str ) returns WCHARS {
CArray[WCHAR].new( $str.comb.map: *.ord )
}
I am trying to get the installed path from the registry. I have installed the python in my machine. I want to get the installed path from the registry in VC++ 6.0. I am trying the following code but it is returning error code (87) that means file not found:
dwRet = RegQueryValueEx( HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\Python\PythonCore\${PYTHON_VERSION}\InstallPath"),
NULL,
NULL,
(LPBYTE)cbData,
NULL );
Any idea?
Thanks,
working code:
HKEY hKey;
if( RegOpenKeyEx( HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Python\\PythonCore\\3.3\\InstallPath"),
0, KEY_QUERY_VALUE, &hKey ) == ERROR_SUCCESS ) {
TCHAR Path[ MAX_PATH ];
DWORD Size = (DWORD)sizeof( Path);
DWORD dwRet = RegQueryValueEx( hKey, NULL, NULL, NULL,(LPBYTE)Path, &Size );
RegCloseKey( hKey );
}
If you don't know the Python version, you should enumerate the subkeys of PythonCore. See Enumerating Registry Subkeys
HKEY hKey = 0;
DWORD dwType = REG_SZ;
TCHAR buf[255] = {0};
DWORD dwBufSize = sizeof(buf);
DWORD ret;
CComboBox m_portCombo;
if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &hKey ) == ERROR_SUCCESS )
{
if( RegQueryValueEx( hKey, TEXT("\\Device\\Serial0"), 0, &dwType, (LPBYTE)buf, &dwBufSize ) == ERROR_SUCCESS )
{
CString str = buf;
m_portCombo.AddString(str);
}
if( RegQueryValueEx( hKey, TEXT("\\Device\\Serial1"), 0, &dwType, (LPBYTE)buf, &dwBufSize ) == ERROR_SUCCESS )
{
CString str = buf;
}
if( RegQueryValueEx( hKey, TEXT("\\Device\\Serial2"), 0, &dwType, (LPBYTE)buf, &dwBufSize ) == ERROR_SUCCESS )
{
CString str = buf;
}
if( RegQueryValueEx( hKey, TEXT("\\Device\\Serial3"), 0, &dwType, (LPBYTE)buf, &dwBufSize ) == ERROR_SUCCESS )
{
CString str = buf;
}
}
First problem: i want to change the TEXT("\\Device\\Serial3") with something like TEXT("\\Device\\Serial",%i), so i can resume all that lines of code to a for loop.Is tehre a way to accomplish this?
Second problem: if i use the m_portCombo.AddString(str); i get an Debug Assertion Failed! error, and, of course, the combobox is not populated with that registry value. Why could that happen?
First Problem: Use the CString Format() function using %d for integer.
for (int i =0 ; i<10; i++)
{
CString szPath;
szPath.Format(TEXT("\\Device\\Serial%d"),i);
// ...
}
Second Problem:
There could be many reasons this would fail. Most likely of which would be having not created the combo box yet.(It needs a window handle before it can add strings) To figure out the cause of the debug assertion, click the "retry" button on the Debug Assertion Failed window and it should jump to the code which caused the assertion. For example it might be something like:
ASSERT(GetSafeHwnd()!=NULL);
Your combo box class won't be 'subclassed' until after the first DoDataExchange is called (and any attempt to use it before that happens will ASSERT). Either wait until the base class has run OnInitDialog or do something like this:
CComboBox * pcombo = static_cast<CComboBox*>(GetDlgItem( IDC_MYCOMBO ));
pcombo->AddString( szPath );
See #TheSteve's answer for string problem.
I have a subkey in my registry with an unknown numbers of values.
I want to get all the data from those values in th specified subkey.
how can I do that ? I don't know the names of the values and the number of values.
I'm programming in C.
thanks!
Here's a code for geting all string values a from given regkey (you must open this key before and close after using this function.
vector<pair<wstring, wstring>> CRegistryManager::getKeyValues(HKEY regKey)
{
vector<pair<wstring, wstring>> retValues;
DWORD numOfValues;
DWORD maxValueNameLen;
DWORD maxValueDataLen;
LONG retCode;
retCode = RegQueryInfoKey(regKey, NULL, NULL,NULL, NULL, NULL, NULL, &numOfValues, &maxValueNameLen, &maxValueDataLen, NULL, NULL);
if( (retCode == ERROR_SUCCESS) && (numOfValues != 0) )
{
TCHAR* valueName = new TCHAR[maxValueNameLen+1];
TCHAR* valueData = new TCHAR[maxValueDataLen+1];
for(int i = 0; i < numOfValues; i++)
{
DWORD valueNameBuferSize = maxValueNameLen+1;
DWORD valueDataBufferSize = maxValueDataLen+1;
retCode = RegEnumValue(regKey, i, valueName, &valueNameBuferSize, NULL,NULL, (LPBYTE)valueData, &valueDataBufferSize);
if(retCode == ERROR_SUCCESS)
{
auto pair = make_pair(wstring(valueName), wstring(valueData));
retValues.push_back(pair);
}
}
delete[] valueName;
delete[] valueData;
}
return retValues;
}
You'll want to use the Win32 API RegEnumValue to enumerate the registry values of a subkey. There is an example on MSDN which is similar to this but for enumerating registry subkeys.
You can also find some helper functions from one of my previous answers here.