I am new to programming, I would like to know the number of entries in a registry key. I think entries are called subkeys but I am not sure. I am trying to use RegQueryInfoKey() but I don't fully understand the MSDN webpage since I am beginner.
HKEY hKey = HKEY_LOCAL_MACHINE;
char regpath[] = "SOFTWARE\\MyApplication\\"
LPDWORD numberofEntries;
RegOpenKeyEx(hKey, regpath, 0, KEY_READ, &hKey);
RegQueryInfoKey(hKey, NULL, NULL, NULL, numberofEntries, NULL);
then I would like to printf the number of entries in this key. The code above doesn't work, the app crash.
How is it done?
Thank you
RegQueryInfoKey has 12 parameters. You are only passing 6. I can't understand how that even compiles—perhaps you are providing your own definition of RegQueryInfoKey rather than the one from the windows header files.
Perhaps you are getting confused by the fact that many of the parameters to RegQueryInfoKey are marked as optional. This only means that you can pass NULL into the function and not that you can omit the parameters altogether.
Related
Using C++ VS2017 Win10...
I am testing some code to set a characteristic value on a BLE device. I had originally had the default function call
HRESULT hr = BluetoothGATTSetCharacteristicValue(
hBleService.get(),
_pGattCharacteristic,
gatt_value,
NULL,
BLUETOOTH_GATT_FLAG_NONE);
I had to switch the flag to BLUETOOTH_GATT_FLAG_WRITE_WITHOUT_RESPONSE to get any sets to take place even though IsWritable and IsReadable were the only 2 properties set showing true but that is a different story and another topic.
Anyway, before I found the problem with the flag I had tried to use the ReliableWriteContext parameter so the code changed to
HANDLE hDevice = _bleDeviceContext.getBleDeviceHandle();
BTH_LE_GATT_RELIABLE_WRITE_CONTEXT ReliableWriteContext = NULL;
HRESULT hr1 = BluetoothGATTBeginReliableWrite(hDevice,
&ReliableWriteContext,
BLUETOOTH_GATT_FLAG_NONE);
HRESULT hr = BluetoothGATTSetCharacteristicValue(
hBleService.get(),
_pGattCharacteristic,
gatt_value,
ReliableWriteContext,
BLUETOOTH_GATT_FLAG_WRITE_WITHOUT_RESPONSE);
if (NULL != ReliableWriteContext) {
BluetoothGATTEndReliableWrite(hDevice,
ReliableWriteContext,
BLUETOOTH_GATT_FLAG_NONE);
}
Once I fixed the flag issue my BluetoothGATTSetCharacteristicValue() function would work with either the NULL or the ReliableWriteContext parameters. No difference that I could see.
My question is,then, what does the ReliableWriteContext do exactly? MS docs only say:
The BluetoothGATTBeginReliableWrite function specifies that reliable
writes are about to begin.
Well that doesn't tell me anything. So should I keep the reliable writes because the word "Reliable" sure sounds like it is something that I want? Or do I not use it because it does not seem to be necessary>
Any insight would be appreciated.
Ed
I've been playing around with the C++ registry functions, and I'm trying to get RegCopyTree working, but every time I try, I get an error like
ERROR_FILE_NOT_FOUND
or
ERROR_ACCESS_DENIED.
I am running the program as administrator, and all other registry functions work fine.
Here is the code I'm using:
HKEY destinationKey;
RegCreateKeyEx(getRootKeyFromCode(rootKeyCode),
destinationKeyPathNative, 0, NULL, 0, 0, NULL,
&destinationKey, NULL);
RegCopyTree(INSERT_ROOT_KEY_HERE,
INSERT_ORIGINAL_KEY_PATH_HERE, destinationKey);
RegCloseKey(destinationKey);
I've removed the error handling and some other irrelevant parts.
Destination key handle should have write access, to be able to copy to it. Calling RegCreateKeyEx() without specifying access mode either fails or doesn't grant write access. Try with KEY_WRITE or KEY_CREATE_SUB_KEY as sixth argument.
IMHO, the implementation of RegCopyKey() is ultimately broken.
The following code snippet:
HKEY source = nullptr;
LONG l1 = RegOpenKeyEx(HKEY_CLASSES_ROOT, L"CLSID\\{44EC053A-400F-11D0-9DCD-00A0C90391D3}", 0, KEY_READ /* KEY_ALL_ACCESS */, &source);
HKEY destination = nullptr;
LONG l2 = RegCreateKeyEx(HKEY_CURRENT_USER, L"Software\\Substitute", 0, nullptr, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, nullptr, &destination, nullptr);
LONG l3 = RegCopyTree(source, nullptr, destination);
yields l1 = 0 (NO_ERROR), l2 = 0 (NO_ERROR), l3 = 5 (ACCESS_DENIED).
The source key (COM entry for atl.dll) exists and the destination key does not exist before calling this code. The error occurs even if I start the process with elevated privileges and open the source key with KEY_ALL_ACCESS.
By examining the registry, I found out that RegCopyTree sets the attributes of the destination key to KEY_READ. Subsequently, it is unable to create any more subkeys. So basically, RegCopyTree is tumbling over its own feet.
Microsoft was unable to tackle this problem, too; see the last answer in The RegCopyTree Function
Using RegQueryValueEx and RegSetValueEx, I can manually copy the contents from source to destination, so permissions and visibility shouldn't be the problem.
The code snippet is trivial enough. Is there still something I am overlooking?
You should use administrator authority to run your application or you call registry functions will be failed.
I am trying to write a DWORD value to the registry programmatically in C++.
I've done a bit of searching and I have found that this question has been asked before. I've tried to follow their solution but have come up with a really frustrating issue which, as far as I know, have not been addressed by their solution.
This is my code:
HKEY hKey;
LPCWSTR sKeyPath;
int iResult;
sKeyPath = L"Software\\ABI\\";
iResult = RegOpenKeyEx(HKEY_CURRENT_USER, sKeyPath, NULL, KEY_ALL_ACCESS, &hKey);
DWORD value = 0x00000003;
iResult = RegSetValueEx(hKey, L"Test", NULL, REG_DWORD, (const BYTE*)value, sizeof(value));
RegCloseKey(hKey);
I've done some basic debugging and found that the value of iResult is 998 after I call RegSetValueEx. I am sure that this key is present in the windows registry because I created it manually with regedit.exe for testing purposes. The value of the DWORD "Test" is initially 0x00000009 and is unchanged after I run my program.
I am not sure where I am wrong.
Any help would be appreciated.
P.S. I've not managed to find any helpful site on the net for error 998. The only reference I found mentions that that's the worst error you can get when handling registry.
P.P.S. By the way, I'm running this program on Windows 8. I don't think that changes anything but I've had experiences with Windows 8 having some weird security issues before.
You need to pass the address of value:
iResult = RegSetValueEx(hKey,
L"Test",
NULL,
REG_DWORD,
(const BYTE*)&value, // Change made here.
sizeof(value));
The error code 998 means:
Invalid access to memory location.
When the address of value is not passed its actual value (3) is being used as a memory address, causing the failure.
i have a problem with my code ;)
hFind = FindFirstFileEx( szPath, FindExInfoMaxInfoLevel, &FindData, FindExSearchNameMatch, NULL , 0);
strncpy_s( pszFileName, 280, FindData.cFileName, strlen(FindData.cFileName));
everything seems fine but when i copy the executable to another computer (windows 2003) i get
But for pszFileName i get really strange output
Specifying FindExInfoMaxInfoLevel is incorrect. The MSDN Library says:
FindExInfoMaxInfoLevel
This value is used for validation. Supported values are less than this value.
In addition, from your usage of FindFirstFileEx, I cannot see why you do not use the simpler FindFirstFile function.
There's not enough code to diagnose the problem, especially without any evidence of error checking. However, there is something really smelly in what you posted. Your call to strncpy_s() says that pszFileName is a pointer to an array with 280 elements. Where did that number come from? Is it just a guess? It can never be more than 260 on Windows, why is it more? I suspect that when you make this a real number, like an argument passed to your function, instead of a guess that you'll fix the problem as well.
You shuold not use the output fields in FindData without first checking that hFind is valid. From the MSDN docs:
If the function fails or fails to
locate files from the search string in
the lpFileName parameter, the return
value is INVALID_HANDLE_VALUE and the
contents of lpFindFileData are
indeterminate.
Thus you should have (after fixing other problems in your API call described in the answers here):
hFind = FindFirstFileEx( szPath, /* replace FindExInfoMaxInfoLevel here */,
&FindData, FindExSearchNameMatch, NULL , 0);
if (hFind != INVALID_HANDLE_VALUE)
{
strncpy_s( pszFileName, 280, FindData.cFileName, strlen(FindData.cFileName));
}
I am looking for a clean way to check if a registry key exists. I had assumed that RegOpenKey would fail if I tried to open a key that didn't exist, but it doesn't.
I could use string processing to find and open the parent key of the one I'm looking for, and then enumerate the subkeys of that key to find out if the one I'm interested in exists, but that feels both like a performance hog and a weird way to have to implement such a simple function.
I'd guess that you could use RegQueryInfoKey for this somehow, but MSDN doesn't give too many details on how, even if it's possible.
Update: I need the solution in Win32 api, not in managed code, .NET or using any other library.
The docs in MSDN seem to indicate that you should be able to open a key for read permission and get an error if it doesn't exist, like this:
lResult = RegOpenKeyEx (hKeyRoot, lpSubKey, 0, KEY_READ, &hKey);
if (lResult != ERROR_SUCCESS)
{
if (lResult == ERROR_FILE_NOT_FOUND) {
However, I get ERROR_SUCCESS when I try this.
Update 2: My exact code is this:
HKEY subKey = nullptr;
LONG result = RegOpenKeyEx(key, subPath.c_str(), 0, KEY_READ, &subKey);
if (result != ERROR_SUCCESS) {
... but result is ERROR_SUCCESS, even though I'm trying to open a key that does not exist.
Update 3: It looks like you guys are right. This fails on one specific test example (mysteriously). If I try it on any other key, it returns the correct result. Double-checking it with the registry editor still does not show the key. Don't know what to make of all that.
First of all don't worry about performance for stuff like this. Unless you are querying it 100x per sec, it will be more than fast enough. Premature optimization will cause you all kinds of headaches.
RegOpenKeyEx will return ERROR_SUCCESS if it finds the key. Just check against this constant and you are good to go.
RegOpenKey does return an error if the key does not exist. How are you using it? The expected return value is ERROR_FILE_NOT_FOUND.
From your code:
HKEY subKey = nullptr;
LONG result = RegOpenKeyEx(key, subPath.c_str(), 0, KEY_READ, &subKey);
if (result != ERROR_SUCCESS) {
I would look at the value of key and subPath and make sure they are what you expect, and that the key does not actually exist. What is the value of subKey afterwards? It is obviously opening something - try enumerating it to see what the keys and values under it are.
There is no issue with RegOpenKey not returning an error if the key does not exist - I would not try to assume there is some kind of weird OS bug in something as commonly used as the registry.
Maybe you have a registry key that is not visible to you, the user that is running the registry editor, but not to your code? A permissions problem perhaps? Is your code running as an elevated user in windows Vista or server 2008? Did you try running the registry editor as administrator?
Note that beside the "core" Registry functions that start with "Reg" there are also helper functions starting with "SHReg". These are intended for use by the Shell i.e. Explorer but are documented and can be used in normal applications too. They're typically thin wrappers that make some common tasks easier. They're part of the "Shell LightWeight API" (shlwapi.dll)