Showing posts with label Sysinternals Forum. Show all posts
Showing posts with label Sysinternals Forum. Show all posts

2008-07-09

In Vista, How Does the FLAGS Switch of REG.EXE Work? Part 2

Note: this content originally from http://mygreenpaste.blogspot.com. If you are reading it from some other site, please take the time to visit My Green Paste, Inc. Thank you.

Previously, I wrote about the FLAGS switch for REG.EXE in Vista and covered a technique that would set the virtualization-related flags of a registry key programmatically. This post intends to cover the other side - querying for the virtualization-related flags of a registry key. Again, we're dealing with an "undocumented" function in NTDLL.DLL - NtQueryKey:

NTSTATUS NtQueryKey(
IN HANDLE KeyHandle,
IN KEY_INFORMATION_CLASS KeyInformationClass,
OUT PVOID KeyInformation,
IN ULONG Length
OUT PULONG ResultLength );


To retrieve the flags for a key, call NtQueryKey with KeyInformationClass set to 5, which WDM.h tells us is KeyFlagsInformation.
typedef enum _KEY_INFORMATION_CLASS {
KeyBasicInformation,
KeyNodeInformation,
KeyFullInformation,
KeyNameInformation,
KeyCachedInformation,
KeyFlagsInformation,
KeyVirtualizationInformation,
MaxKeyInfoClass // MaxKeyInfoClass should always be the last enum
} KEY_INFORMATION_CLASS


REG.EXE supplies 12 for the value of the Length param, and the last 4 bytes of the buffer (KeyInformation) are modified when NtQueryKey returns. This would seem to suggest that the struct to receive the information containing the virtualization flags looks something like:
typedef struct _KEY_FLAGS_INFO {
ULONG unknown1;
ULONG unknown2;
ULONG ControlFlags;
} KEY_FLAGS_INFO, *PKEY_FLAGS_INFO;


Putting it all together, then, we have something like:
typedef NTSYSAPI NTSTATUS (NTAPI* FuncNtQueryKey)( HANDLE KeyHandle, KEY_INFORMATION_CLASS KeyInformationClass, PVOID KeyInformation, ULONG Length, PULONG ResultLength );
// ...
FuncNtQueryKey ntqk = (FuncNtQueryKey)GetProcAddress( GetModuleHandle( _T("ntdll.dll") ), "NtQueryKey" );
KEY_FLAGS_INFO kfi = {0};
HKEY hTheKey = NULL;
RegOpenKeyEx( HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Whatever"), 0, KEY_ALL_ACCESS, &hTheKey );
DWORD dwResultLen = 0;
DWORD dwNtqkResult = ntqk( hTheKey , KeyFlagsInformation, &kfi, sizeof( KEY_FLAGS_INFO ), &dwResultLen );
RegCloseKey( hTheKey );
hTheKey = NULL;


The flags (_CONTROL_FLAGS, from Part 1) are stored as a bitmask in kfi.ControlFlags.
typedef enum _CONTROL_FLAGS {
RegKeyClearFlags = 0,
RegKeyDontVirtualize = 2,
RegKeyDontSilentFail = 4,
RegKeyRecurseFlag = 8
} CONTROL_FLAGS;


The code above provides the same information as invoking REG.EXE FLAGS HKLM\Software\Whatever QUERY.

Again - note that this exploration was done on Windows Vista SP1. I would expect the content here to also apply to Windows Vista (no SP) as well as Windows Server 2008, but...

2008-05-25

Creating Programs for Windows 9x and NT with Visual C++ 2008

Note: this content originally from http://mygreenpaste.blogspot.com. If you are reading it from some other site, please take the time to visit My Green Paste, Inc. Thank you.

A recent topic in the Development forum at Sysinternals Forums contains some information about how to use Visual C++ 2008 to create binaries that run on Windows 9x and NT. For NT, it seems to just be a matter of changing the Subsystem Version to 4.0. One might think to use the /SUBSYSTEM linker switch for this. However, when one attempts to do so, the shipping link.exe reports:


LINK : warning LNK4010: invalid subsystem version number x.y; default subsystem version assumed


In this case, the default subsystem version is 5.0, and NT needs 4.0. One can use an older copy of EditBin.exe to change this (I found the version that shipped with Visual Studio .NET 2003 to work):


editbin /SUBSYSTEM:CONSOLE,4.0 c:\path\to\your.exe


The same requirement also exists to get the executable to run on Windows 9x, but one needs to do a bit more work.


Louis Solomon has taken the time and put forth the effort to find what is needed for this, and has documented it at C/C++ EXEs and DLLs created by Visual Studio 2008 don't run on Windows 4.0 (ie, NT4 and Win9x).

2008-04-27

In Vista, How Does the FLAGS Switch of REG.EXE Work?

Note: this content originally from http://mygreenpaste.blogspot.com. If you are reading it from some other site, please take the time to visit My Green Paste, Inc. Thank you.


A while back, there was a topic (Virtual Registry vs. "Real registry") in the Sysinternals Forums that brought up the question of how to set the virtualization-related flags of a registry key programmatically in Vista, rather than through the use of the REG.EXE tool's FLAGS switch. (For more information on the flags, see Mark Russinovich's article in TechNet Magazine, "Inside Windows Vista User Account Control"). Even before that topic in the forum, I had wondered how it was done but had not had a chance to explore. It didn't seem that many others were curious about it. That topic had resurrected the idea, but it quickly fell to the bottom of the list. I've finally gotten around to experimenting, and that leads to this write-up. I still don't see much in the way of this discussed anywhere, by searching for terms involved (data types, function param names, etc.), so hopefully this will help someone. (Keep in mind that there very well may be a reason Microsoft hasn't made this available through another, more direct API.)


In the referenced topic, I had gotten so far as determining that REG.EXE was doing its work through the use of NtSetInformationKey, an "undocumented" API in NTDLL.DLL.


NTSYSAPI 

NTSTATUS

NTAPI

NtSetInformationKey(

IN HANDLE KeyHandle,

IN KEY_SET_INFORMATION_CLASS InformationClass,

IN PVOID KeyInformationData,

IN ULONG DataLength );


After a bit of plonking around in WinDbg, I've come up with the following following details. REG.EXE calls NtSetInformationKey, specifying a value of 2 for the InformationClass parameter. This parameter is of type KEY_SET_INFORMATION_CLASS, which wdm.h tells us is an enum:


typedef enum _KEY_SET_INFORMATION_CLASS {

KeyWriteTimeInformation,

KeyWow64FlagsInformation,

KeyControlFlagsInformation,

KeySetVirtualizationInformation,

KeySetDebugInformation,

MaxKeySetInfoClass // MaxKeySetInfoClass should always be the last enum

} KEY_SET_INFORMATION_CLASS;


So the 2 for the InformationClass parameter would correspond to KeyControlFlagsInformation. WDM.H also suggests that this class has a type that one passes for the KeyInformationData parameter - KEY_CONTROL_FLAGS_INFORMATION:


typedef struct _KEY_CONTROL_FLAGS_INFORMATION {

ULONG ControlFlags;

} KEY_CONTROL_FLAGS_INFORMATION, *PKEY_CONTROL_FLAGS_INFORMATION;


We have a basic idea of how to call NtSetInformationKey now. But what are the values that the ControlFlags member of KEY_CONTROL_FLAGS_INFORMATION can be set to? It would appear that the following (self-made) enum covers the pertinent flags - at least the ones REG.EXE FLAGS can handle (there may be more):


typedef enum _CONTROL_FLAGS {

RegKeyClearFlags = 0,

RegKeyDontVirtualize = 2,

RegKeyDontSilentFail = 4,

RegKeyRecurseFlag = 8

} CONTROL_FLAGS;


The control flags are a bitmask, so you can OR them to set more than one.


Now that we have this information, what's left? We need to put it all together in a call to NtSetInformationKey. So, we need to get a pointer to the function in NTDLL.DLL. Then, we can declare a struct of type KEY_CONTROL_FLAGS_INFORMATION, set the ControlFlags member to be what we wish, and open a key to the desired location in the registry, that can be passed to NtSetInformationKey. In the end, we wind up with something like the following (error handling has been omitted):


typedef NTSYSAPI NTSTATUS (NTAPI* FuncNtSetInformationKey) (

HANDLE KeyHandle,

KEY_SET_INFORMATION_CLASS InformationClass,

PVOID KeyInformationData,

ULONG DataLength );

//...

FuncNtSetInformationKey ntsik = (FuncNtSetInformationKey)GetProcAddress(

GetModuleHandle( _T("ntdll.dll") ), "NtSetInformationKey" );

KEY_CONTROL_FLAGS_INFORMATION kcfi = {0};

kcfi.ControlFlags = RegKeyDontVirtualize | RegKeyRecurseFlag;

HKEY hTheKey = NULL;

RegOpenKeyEx( HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Whatever"), 0, KEY_ALL_ACCESS, &hTheKey );

ntsik( hTheKey, KeyControlFlagsInformation, &kcfi, sizeof( KEY_CONTROL_FLAGS_INFORMATION ) );

RegCloseKey( hTheKey );

hTheKey = NULL;



The code above is the equivalent of invoking REG.EXE FLAGS HKLM\Software\Whatever SET DONT_VIRTUALIZE RECURSE_FLAGS. To clear the flags, just set kcfi.ControlFlags to RegKeyClearFlags (same as REG.EXE FLAGS HKLM\Software\Whatever SET).

Hopefully, this will prove useful to those that have wished to set these flags programmatically. In a future post, I hope to explore querying for these flags, ala REG.EXE FLAGS HKLM\Software\Whatever QUERY.


Note that this exploration was done on Windows Vista SP1. I would expect the content here to also apply to Windows Vista (no SP) as well as Windows Server 2008, but...