Read "OS install date" value from registry with RegQueryValueExA() api failed - c

I wanna read Windows Install Date value from registry using Windows API as bellow :
HKEY hKey = { 0 };
LONG lResult = ERROR_SUCCESS;
// Open a registry key
lResult = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
0, KEY_READ, &hKey);
// If registry key opened
if (lResult == ERROR_SUCCESS)
{
// Get OS install date/time
DWORD dwInstallDate = 0;
dwBufferSize = sizeof(DWORD);
if (RegQueryValueExA(hKey, "InstallDate", 0, NULL, (LPBYTE)&dwInstallDate, &dwBufferSize) == ERROR_SUCCESS)
{
printf("OS Install Date is : %lu", dwInstallDate);
}
else
{
printf("The specific key not found!");
}
// Finally we should close the key when we finished with it
RegCloseKey(hKey);
}
But the output is always 0, while "InstallDate" value is 1520291827:
OS Installe Date is : 0
Also, I'm used of "%ld" and "d" formats, but it has the same output...
The "InstallDate" value in registry, contained a REG_DWORD type.
By the way, when i create a new REG_DWORD value, my code cannot read it :
For example , I create a value in bellow reg-address as "test" with 123 data :
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
But dwInstallDate will be 0 instead of 123 :
RegQueryValueExA(hKey, "test", 0,
NULL, (LPBYTE)&dwInstallDate,
&dwBufferSize);
Any Suggestion? I'm confused about this action...

According Microsoft :
KEY_WOW64_32KEY (0x0200) :
Indicates that an application on 64-bit Windows should operate on the 32-bit registry view. This flag is ignored by 32-bit Windows. For more information, see Accessing an Alternate Registry View.
This flag must be combined using the OR operator with the other flags in this table that either query or access registry values.
Windows 2000: This flag is not supported.
KEY_WOW64_64KEY (0x0100) :
Indicates that an application on 64-bit Windows should operate on the 64-bit registry view. This flag is ignored by 32-bit Windows. For more information, see Accessing an Alternate Registry View.
This flag must be combined using the OR operator with the other flags in this table that either query or access registry values.
Windows 2000: This flag is not supported.
I used of KEY_WOW64_64KEY | KEY_READ either way x86 and x64 :
// Open a registry key
lResult = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
0, KEY_WOW64_64KEY | KEY_READ, &hKey);
It does work.

Related

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.

Opening symbolic link in kernel Windows8.1+

i'm trying to open symbolic link as a file using ZwOpenProcess in kernel space. Using code below all is ok on XP-7. But using Windows 8.1 ZwOpenProcess fails with different NTSTATUS codes, like 0xC0000001, 0xC000000D
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE FileHandle;
IO_STATUS_BLOCK IoStatus;
NTSTATUS Status;
InitializeObjectAttributes ( &ObjectAttributes,
SymLinkOrDeviceName, // <--- \Device\CEDRIVER60
OBJ_KERNEL_HANDLE,
(HANDLE) NULL,
(PSECURITY_DESCRIPTOR) NULL );
Status = ZwOpenFile ( &FileHandle,
FILE_READ_ACCESS,
&ObjectAttributes,
&IoStatus,
0,
FILE_NON_DIRECTORY_FILE );
if ( !NT_SUCCESS ( Status ) )
{
DbgPrint("TEST: ERROR %p ", Status); // <--- 0xC0000001, 0xC000000D
goto Exit;
}
I checked, using WinObj - symbolic link present in system, code works fine on XP-7.
I also trind to change Access to - FILE_ANY_ACCESS - the same result.
ZwOpenProcess
I suppose you meant ZwOpenFile.
\Device\CEDRIVER60
Did you really looked into the \Device directory? This directory usually contains device objects created by drivers. Symbolic links are usually placed into directories like \DosDevices. You should also include the OBJ_CASE_INSENSITIVE flag.
FILE_READ_ACCESS
This flag determines access right(s) required to successfully deliver an IOCTL message to a target device object. Specify a true file access right constant like FILE_READ_ATTRIBUTES, FILE_READ_DATA (its value is actually the same as FILE_READ_ACCESS) or GENERIC_READ. MSDN page on ZwOpenFile (and ZwCreateFile) is also worth of reading. You may need to include the SYNCHRONIZE flag too.
%p
NTSTATUS is defined as long (32-bit signed integer). %x is more appropriate.

RegQueryValue fails but RegQueryValueEx returns a value

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().

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.

Problem with SetComputerName Function

I used following line of code to change my computer name:
std::string mystr="MY-PC"
bSuccess = SetComputerNameA(mystr.c_str());
if( bSuccess == 0 )
printf("Unable to change computer name | ERROR %d |", GetLastError());
else
printf("Name changed successfully");
Upon executing the program, 'Name changed successfully' message appeared. Following registry items were found to have the update computer name
HKLM\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName
HKLM\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName
After restarting my computer, I checked the computer name from Control Panel\System and Security\System. To my surprise it still have the old name.
Checked the registry again which contain the new name i.e MY-PC
Any idea why the computer name at Control Panel\System and Security\System has not been updated?
The SetComputerNameA function only sets the netbios name. You need to use the SetComputerNameEx I think.
BOOL WINAPI SetComputerNameEx(
__in COMPUTER_NAME_FORMAT NameType,
__in LPCTSTR lpBuffer
);
With the COMPUTER_NAME_FORMAT as ComputerNamePhysicalDnsHostname

Resources