RegQueryValue fails but RegQueryValueEx returns a value - c

I am attempting to play with some of the 16 and 32 bit registry functions, and I'm having trouble with using RegQueryValue (not extended). I am opening a handle to HKLM\Software\Microsoft\EventSystem (this key was chosen at random, the problem is persistent across keys). When I call RegQueryValue for "Configured", there is an error. However, for RegQueryValueEx, I am actually able to get the value.
I am running this on Windows 7 x64, tested with admin rights (Not having admin rights means RegOpenKeyEx fails with insufficient rights).
Here is the code (see https://stackoverflow.com/questions/455434/how-should-i-use-formatmessage-properly-in-c for printErrorMessage):
#define BUFLEN 80
int main() {
HKEY hkey;
DWORD ret = RegOpenKeyA(rootKey, "Software\\Microsoft\\EventSystem", &hkey);
printf("Opened key, handle is %i\n", hkey);
LONG buflen = BUFLEN;
DWORD dwbuflen = BUFLEN;
char data[BUFLEN];
BYTE bdata[BUFLEN];
ret = RegQueryValueA(hkey, "Configured", data, &buflen);
if (ret != ERROR_SUCCESS) {
printf("Unable to open Configured with RegQueryValueA\n");
printErrorMessage(ret);
} else {
printf("Value of Configured was %s\n", data);
}
ret = RegQueryValueExA(hkey, "Configured", 0, NULL, bdata, &dwbuflen);
if (ret != ERROR_SUCCESS) {
printf("Unable to open Configured with RegQueryValueExA\n");
printErrorMessage(ret);
} else {
printf("Value of Configured was %s\n", bdata);
}
}
And here is the output:
Opened key, handle is 68
Unable to open Configured with RegQueryValueA
The system cannot find the file specified.
Value of Configured was ☺
(Configured's value is wonky because I am not yet bothering to convert from REG_DWORD to a string, but it is immaterial to the problem I am having).

When you call RegQueryValue(hkey, "Configured"), that tries to read the default value (or unnamed value) of the key named "Configured". This is the semantics of RegQueryValue() as described by MSDN.
So RegQueryValue() cannot be used to read named values like "Configured", so you must use RegQueryValueEx() if you want to read a named value.

You're querying a value, but the string parameter for RegQueryValue() is a subkey. See msdn for RegQueryValue() vs. RegQueryValueEx().

Related

Berkley DB non deterministic error occurrence when adding an encrypted database within environment

I'm trying to add new and first encrypted database within an environment which already contains several unencrypted databases.
the problem is that once in several attempts to update our software version (to the version that contains the new encrypted database creation), db->open returns error 22 and the following logs from BDB being printed:
enter image description here
Berkeley DB version that being used is 4.8.30
I followed those instructions https://docs.oracle.com/cd/E17076_05/html/programmer_reference/env_encrypt.html
I didn't created new environment, I used the already exist environment with the following configurations:
static STATUS sPR_create_env(const char *passwd, BOOL open_env)
{
STATUS ret=OK, err=OK;
if( db_env_passwd == NULL )
{
asprintf(&db_env_passwd, "%s", passwd);
}
/* Create an environment object and initialize it */
ret = db_env_create(&dbenv, 0 );
dbenv->set_msgcall(dbenv, sPR_db_print_to_syslog);
dbenv->set_errcall(dbenv, sPR_db_err_print);
/*
* We want to specify the shared memory buffer pool cachesize
*/
ret = dbenv->set_cachesize(dbenv, 0, (4 * 1024 * 1024), 0);
/* Set databases prefix to data files. */
(void)dbenv->set_data_dir(dbenv, data_dir);
/* Set encrypt to environment for the supporting secure DB */
ret = dbenv->set_encrypt(dbenv, passwd, DB_ENCRYPT_AES);
ret = dbenv->set_tx_max(dbenv, MAX_NUM_OF_TRANSACTIONS);
ret = dbenv->set_lk_partitions(dbenv, 1); /* optimized for single CPU systems */
/* Set Log file auto-removal on */
ret = dbenv->log_set_config(dbenv, DB_LOG_AUTO_REMOVE, 1);
/* Set the maximum # of locks/lockers/lock-objects (should be at least 5*lock-partitions) */
ret = dbenv->set_lk_max_locks(dbenv, 4000);
ret = dbenv->set_lk_max_objects(dbenv, 4000);
ret = dbenv->set_lk_max_lockers(dbenv, 4000);
/* Reject lock request leading to deadlocks which have the least # of locks taken */
ret = dbenv->set_lk_detect(dbenv, DB_LOCK_MINWRITE);
ret = dbenv->set_lg_dir(dbenv, DB_LOG_FILE_PATH);
ret = dbenv->set_lg_max(dbenv, DB_LOG_FILE_SIZE);
if( open_env )
{
/* open environment DB */
ret = dbenv->open(dbenv, DB_home,
DB_THREAD | DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE |
DB_INIT_TXN | DB_INIT_LOCK | DB_INIT_LOG | DB_RECOVER,
0644);
}
exit:
if( err == ERROR )
{
dbenv->close(dbenv, 0);
dbenv=NULL;
}
return err;
}
the way of opening my new database is as follow:
/* set encryption */
ret = dbp->set_flags(dbp, DB_ENCRYPT);
/* Open a database with DB_BTREE access method.*/
ret = dbp->open(dbp,
NULL,
file_name,
NULL,
DB_BTREE,
flags,
0644);
all other databases being open like this:
/* Open a database with DB_BTREE access method.*/
ret = dbp->open(dbp,
NULL,
file_name,
NULL,
DB_BTREE,
flags,
0644);
what can be the reason for this error 22? can it be related to the mixing of encrypted together with unencrypted databases within the same environment?
why sometimes the program runs properly and sometimes not?
is there something wrong with the environment configurations? flags?
thanks.

GetNamedSecurityInfo fails for registry key where GetSecurityInfo succeeds

I have a registry key ACL reading request like this:
PACL dacl = NULL;
PSECURITY_DESCRIPTOR secDesc = NULL;
if (GetNamedSecurityInfoW(L"HKEY_CURRENT_USER\\SOFTWARE\\SomeSoftware\\SomeKey", SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION, NULL, NULL, &dacl, NULL, &secDesc) != ERROR_SUCCESS)
{ /*... */ }
And it fails with error 87, invalid parameter. However, if I use
HKEY handle;
DWORD Ret = RegOpenKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\SomeSoftware\\SomeKey", 0, KEY_ALL_ACCESS, &handle);
if (Ret != ERROR_SUCCESS) { /* ... */ }
DWORD secDescSize = 4096;
secDesc = LocalAlloc(LMEM_FIXED, secDescSize);
Ret = (DWORD)RegGetKeySecurity(handle, DACL_SECURITY_INFORMATION, secDesc, &secDescSize);
if (Ret != ERROR_SUCCESS) { /* ... */ }
RegOpenKey() and RegGetKeySecurity() succeed, and running GetSecurityDescriptorDacl() on the result of RegGetKeySecurity() also works.
This code works fine for SE_FILE_OBJECT and reading a directory's ACL.
This code is inside a 32-bit DLL in a 32-bit app in Windows 10 Pro 64-bit. I'm targeting XP and above, using Visual Studio 2019 Preview.
Anything I could have missed in parameter validation?
L"HKEY_CURRENT_USER\\SOFTWARE\\SomeSoftware\\SomeKey" is not a valid object name for GetNamedSecurityInfoW(). Read the SE_OBJECT_TYPE documentation for the proper format to use for a registry key:
SE_REGISTRY_KEY
Indicates a registry key. A registry key object can be in the local registry, such as CLASSES_ROOT\SomePath or in a remote registry, such as \\ComputerName\CLASSES_ROOT\SomePath.
The names of registry keys must use the following literal strings to identify the predefined registry keys: "CLASSES_ROOT", "CURRENT_USER", "MACHINE", and "USERS".
Try L"CURRENT_USER\\SOFTWARE\\SomeSoftware\\SomeKey" instead.

WINAPI C - CreateFileMapping fails with error 8 - ERROR_NOT_ENOUGH_MEMORY

I'm working with file mappings on Windows but having some troubles with them.
First off, I have the necessity to partially map a file and setting the start and the end of it dynamically.
My code is the following:
long fiveMB = 5 * pow(2, 20);
for(int i=0;i<parts;i++){
long start = (i)*fiveMB;
long end = (i + 1)*fiveMB;
long realEnd = end;
if (roundedDim<realEnd)
realEnd = dim;
long chunkDim = realEnd - start;
LARGE_INTEGER fileMapStart.QuadPart = (start/granularity)*granularity;
LARGE_INTEGER mapViewSize.QuadPart = (start%granularity) + chunkDim;
LARGE_INTEGER fileMapSize.QuadPart = start + chunkDim;
long offset = start - fileMapStart.QuadPart;
HANDLE fileMappingH= CreateFileMapping(fileH, NULL, PAGE_READONLY, fileMapSize.HighPart, fileMapSize.LowPart, NULL);
if(fileMappingH == INVALID_HANDLE_VALUE || fileMappingH == NULL){
printf("Error mapping file: %d\n",GetLastError());
CloseHandle(fileH);
return 1;
}
char *mapView = (char *)MapViewOfFile(fileMappingH, FILE_MAP_READ, fileMapStart.HighPart, fileMapStart.LowPart, mapViewSize.QuadPart);
if ((LPVOID)mapView == NULL) {
printf("Error mapView: %d\n", GetLastError());
CloseHandle(fileMappingH);
CloseHandle(file);
return 1;
}
mapView += offset;
/* doing all the stuff */
UnmapViewOfFile((LPVOID)mapView);
CloseHandle(fileMappingH);
}
As far as I know, only MapViewOfFile requires the starting byte to be aligned with the system granularity, so I didn't bother to fix the maximum file mapping size for that.
I tried this code on a 1448 KB file (printing out dim I get 1482159 bytes) while calculating the available memory via GlobalMemoryStatusEx(&memstatus) and memstatus.ullAvailVirtual I get 2092208128 bytes but still stuck on having the CreateFileMapping call failed and with error code 8, ERROR_NOT_ENOUGH_MEMORY.
I also tried calling CreateFileMapping(fileH, NULL, PAGE_READONLY, 0, 0, NULL) to memory map the whole file, but instead there were problems on MapViewOfFile, error 5, ERROR_ACCESS_DENIED.
I don't understand what I'm doing wrong here, since I successfully did it with mmap on a Linux version of the same project.
Thanks anyone who may help.
EDITS:
c was a leftover, I actually meant i
added UnmapViewOfFile and CloseHandle calls
As far as I know, MapViewOfFile only requires the starting byte to be
aligned with the system granularity, so I didn't bother to fix the
maximum file mapping size for that.
this is root of error - really from MapViewOfFile
dwNumberOfBytesToMap [in]
The number of bytes of a file mapping to map to the view. All bytes
must be within the maximum size specified by CreateFileMapping. If
this parameter is 0 (zero), the mapping extends from the specified
offset to the end of the file mapping.
if we use 0 as MaximumSize in CreateFileMapping the maximum size of the file mapping object is equal to the current size of the file. and :
if an application specifies a size for the file mapping object that is
larger than the size of the actual named file on disk and if the
page protection allows write access (that is, the flProtect
parameter specifies PAGE_READWRITE or PAGE_EXECUTE_READWRITE),
then the file on disk is increased to match the specified size of the
file mapping object.
and about GetLastError and win32 errors at all. the errors in most case returned from kernel as NTSTATUS code. the win32 layer converts the specified NTSTATUS code to its equivalent system error code via RtlNtStatusToDosError. unfortunately this conversion not injective - the many different NTSTATUS code can convert to same win32 error and we lost sensitive info here.
so in some case much more better call RtlGetLastNtStatus() instead of GetlastError() - this give to as much more info about error.
CreateFileMapping call failed and with error code
ERROR_NOT_ENOUGH_MEMORY.
based on error ERROR_NOT_ENOUGH_MEMORY we can think that not enough memory in system (STATUS_NO_MEMORY). but also another status - STATUS_SECTION_TOO_BIG converted to the ERROR_NOT_ENOUGH_MEMORY. the CreateFileMapping is thin shell over ZwCreateSection the STATUS_SECTION_TOO_BIG returned when:
The value of MaximumSize is too big. This occurs when either
MaximumSize is greater than the system-defined maximum for sections, or if MaximumSize is greater than the specified file and the
section is not writable.
and this is exactly your case: you use PAGE_READONLY in call CreateFileMapping - so section is not writable and fileMapSize is greater than the specified file (size for the file mapping object that is larger than the size of the actual file on disk)
MapViewOfFile return ERROR_ACCESS_DENIED.
again GetLastError() plays here with us a cruel joke. the initial status is not STATUS_ACCESS_DENIED how we can wait, but STATUS_INVALID_VIEW_SIZE. this status also converted to ERROR_ACCESS_DENIED. the MapViewOfFile got it when not all bytes within the maximum size specified by CreateFileMapping
and call CreateFileMapping multiple time in loop - this is design error - need call this api only once, before loop. in loop only exist sense call MapViewOfFile. the test code can be:
void TestMap(PCWSTR lpFileName, ULONG dwChunkSize)
{
HANDLE hFile = CreateFileW(lpFileName, FILE_GENERIC_READ, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
FILE_STANDARD_INFO fsi;
if (GetFileInformationByHandleEx(hFile, FileStandardInfo, &fsi, sizeof(fsi)))
{
if (HANDLE hSection = CreateFileMappingW(hFile, 0, PAGE_READONLY, 0, 0, 0))
{
if (ULONG n = (ULONG)((fsi.EndOfFile.QuadPart + (dwChunkSize - 1)) / dwChunkSize))
{
LARGE_INTEGER ofs = {};
do
{
if (PVOID pv = MapViewOfFile(hSection, FILE_MAP_READ, ofs.HighPart, ofs.LowPart, --n ? dwChunkSize : 0))
{
UnmapViewOfFile(pv);
}
else
{
RtlGetLastNtStatus();
}
} while (ofs.QuadPart += dwChunkSize, n);
}
CloseHandle(hSection);
}
else
{
RtlGetLastNtStatus();
}
}
CloseHandle(hFile);
}
else
{
RtlGetLastNtStatus();
}
}

Opening registry key in c

I have create a key using regedit, now I want to get its value. It doesn't give any error but it isn't showing anything.
Code :
int main() {
HKEY hKey;
RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"Ehsan Akbari", 0, KEY_ALL_ACCESS, &hKey);
TCHAR sz[50];
DWORD size = 50,type;
RegEnumValue(hKey, 0, L"test", &size, NULL, &type, (LPBYTE)sz, &size);
RegCloseKey(hKey);
getch();
return 0;
}
An image of regedit :picture
What am I doing wrong?
Edit
When I debugged I saw that hKey is NULL, but GetLastError doesn't report anything.
Here are the immediate problems that I can see:
You detect no errors because you don't check for errors. Read the documentation for each function. The error code is returned in the return value.
You ask for KEY_ALL_ACCESS which won't be granted under HKLM. You need to request just read access KEY_READ.
Your screenshot shows the key has been created under HKCU, and you're trying to open it under HKLM.
RegEnumValue expects the size of the data buffer in bytes. You pass the length, the number of characters.
You are mixing Unicode literals and TCHAR. This is pointless. Your code won't compile targeting MBCS and in any case you don't care about Win98 any more. Stop using TCHAR and use wchar_t instead.
The lpValueName parameter must be a modifiable buffer. You pass a literal. Remember that this function enumerates values. It does not read specific named values as perhaps you expect.
The lpcchValueName parameter contains the size of the buffer you passed to lpcchValue in characters. You pass the length of the data buffer.
The data returned may not be null terminated. You must protect against this as described in the documentation.
For a C program which ignores its arguments, the correct main is int main(void).
I expect there are more errors but I stopped looking at this point. I recommend you spend some quality time with the documentation.
To open the path "Ehsan Akbari" in HKEY_CURRENT_USER you could try this:
HKEY hKey;
long result = RegOpenKeyEx(HKEY_CURRENT_USER , TEXT("\\Ehsan Akbari"), 0, KEY_ALL_ACCESS, &hKey);
if ( result == ERROR_SUCCESS )
{
cout << "OK" << endl;
}
else
{
cout << "Error " << result << endl;
}

Unable to read certain registry keys in C

I'm using RegOpenKeyEx() and RegQueryValueEx() to try and get the value for six keys in the Windows registry. I'm able to do it for four of the six but am failing on certain others.
wchar_t * getRegKeyValue(HKEY rootKeyToGet, LPCWSTR subKeyToGet, LPCWSTR valueToGet)
{
HKEY resultHKey = 0;
wchar_t resultString[255] = L"";
DWORD dwType = REG_SZ;
DWORD resultSize = 255;
// See if the subkey exists. If it does, get its value.
if (RegOpenKeyEx(rootKeyToGet, subKeyToGet, NULL, KEY_ALL_ACCESS, &resultHKey) == ERROR_SUCCESS)
{
RegQueryValueEx(resultHKey, valueToGet, NULL, &dwType, (LPBYTE) &resultString, &resultSize);
}
RegCloseKey(resultHKey);
resultHKey = NULL;
RegCloseKey(rootKeyToGet);
rootKeyToGet = NULL;
return resultString;
}
The following are some successful calls:
swprintf(buffer, L"&ie=%s", getRegKeyValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Internet Explorer", L"Version"));
swprintf(buffer, L"&os=%s.", getRegKeyValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"CurrentVersion"));
wcscat(url, getRegKeyValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"CurrentBuild"));
Example of an unsuccessful call:
wcscpy(buffer, getRegKeyValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", L"CSDVersion"));
I'm able to open the key in the unsuccessful call but the query for that value returns an empty string. I'm running Visual Studio as an administrator. Have been scratching my head for the last day on where I am going wrong.
Update: The code returned is ERROR_FILE_NOT_FOUND. The codes are most definitely shown to exist in regedit.
I guess that you have a 32 bit process and a 64 bit machine. When this happens, registry redirection confounds matters. Attempts to read HKLM\Software\... get redirected to HKLM\Software\Wow64Node\.... So you need to open the 64 bit view of the registry with the RegistryView enumeration.

Resources