|
This is the Native Registry Editor (NtRegEdit) article I wrote that uses the CNtRegistry class.
Important notice: Any registry manipulation can cause harm to your system and make it so it doesn't start or run properly. Back-up your registry before using this class. I am not responsible for any damage it causes.
Introduction
There are many registry classes out there, but none (that I know of) that use NT Native API calls to manipulate the registry. Normally, we use the Microsoft APIs to do the work, but they are a bit uncomfortable to use (to say the least), especially when it comes to copying, searching, and deleting keys and values. I also liked the simple example for RegHide by SysInternals that hides registry keys (in a matter of speaking).
Now, I use Robert Pittenger's CRegistry class (found here at CodeProject) whenever I write something that accesses the registry, because of its simplicity. I also liked the idea of hiding registry keys/values from the Registry Editor (RegEdit) by Microsoft, so I decided to combine the two and write a class that does both but only uses the NT Native Registry APIs to do it. This led to the creation of the CNtRegistry class.
Hidden Registry Keys, you say?
SysInternals says it the best (see below - verbatim from their website):
A subtle but significant difference between the Win32 API and the Native API (see Inside the Native API for more information on this largely undocumented interface) is the way that names are described. In the Win32 API, strings are interpreted as NULL-terminated ANSI (8-bit) or wide character (16-bit) strings. In the Native API, names are counted as Unicode (16-bit) strings. While this distinction is usually not important, it leaves open an interesting situation: there is a class of names that can be referenced using the Native API, but that cannot be described using the Win32 API.
How is this possible? The answer is that a name which is a counted as a Unicode string can explicitly include NULL characters (0) as part of the name. For example, "Key\0". To include the NULL at the end, the length of the Unicode string is specified as 4. There is absolutely no way to specify this name using the Win32 API since if "Key\0" is passed as a name, the API will determine that the name is "Key" (3 characters in length) because the "\0" indicates the end of the name.
When a key (or any other object with a name such as a named Event, Semaphore, or Mutex) is created with such a name, any application using the Win32 API will be unable to open the name, even though they might seem to see it.
This is where you can get a copy of RegHide from SysInternals.
What can it do?
The CNtRegistry class has some useful features ... You can:
- Copy Keys and Values (including hidden ones) with in the same RootKey or across RootKeys.
BOOL CopyKeys(CString csSource, CString csTarget, BOOL bRecursively);
BOOL CopyValues(CString csSource, CString csTarget, CString csValueName, CString csNewValueName);
- Delete Keys and Values (including hidden ones and recursively).
BOOL DeleteKey (CString csKey);
BOOL DeleteKeysRecursive (CString csKey);
BOOL DeleteValue (CString csName);
- Rename Keys and Values.
BOOL RenameKey(CString csFullKey, CString csNewKeyName);
BOOL RenameValue(CString csOldName, CString csNewName);
- Search for Keys, Value names, and Values. This allows you to do searches for certain "String" occurrences. It can also Find hidden Keys. Both functions (Search/Find) can perform them recursively, but only with in the current RootKey.
BOOL Search (CString csString, CString csStartKey, CStringArray& csaResults, int nRegSearchType=3, BOOL bCaseSensitive = TRUE);
BOOL FindHiddenKeys (CString csKey, BOOL bRecursive, CStringArray& csaResults);
- Read and Write Values. Possible values/types are:
- Binary (
REG_BINARY, REG_RESOURCE_LIST, REG_FULL_RESOURCE_DECRIPTOR, REG_RESOURCE_REQUIREMENTS_LIST, REG_NONE)
UCHAR* ReadBinary(CString csKey, CString csName, UINT& uiLength);
BOOL WriteBinary(CString csKey, CString csName, UCHAR* pValue, UINT uiLength);
- DWORD (
REG_DWORD)
DWORD ReadDword(CString csKey, CString csName, DWORD dwDefault);
BOOL WriteDword(CString csKey, CString csName, DWORD dwValue);
- String (
REG_SZ, REG_EXPAND_SZ, REG_MULTI_SZ)
CString ReadString(CString csKey, CString csName, CString csDefault);
BOOL ReadMultiString(CString csKey, CString csName, CStringArray& csaReturn);
BOOL WriteString(CString csKey, CString csName, CString csValue);
BOOL WriteExpandString(CString csKey, CString csName, CString csValue);
BOOL WriteMultiString(CString csKey, CString csName, CStringArray& csaValue);
- int (
REG_DWORD)
int ReadInt(CString csKey, CString csName, int nDefault);
BOOL WriteInt(CString csKey, CString csName, int nValue);
- float (
REG_BINARY)
double ReadFloat(CString csKey, CString csName, double fDefault);
BOOL WriteFloat(CString csKey, CString csName, double fValue);
- BOOL (
REG_DWORD)
BOOL ReadBool(CString csKey, CString csName, BOOL bDefault);
BOOL WriteBool(CString csKey, CString csName, BOOL bValue);
- COleDateTime (
REG_BINARY)
COleDateTime ReadDateTime(CString csKey, CString csName, COleDateTime dtDefault);
BOOL WriteDateTime(CString csKey, CString csName, COleDateTime dtValue);
- COLORREF (
REG_BINARY)
COLORREF ReadColor(CString csKey, CString csName, COLORREF rgbDefault);
BOOL WriteColor(CString csKey, CString csName, COLORREF rgbValue);
- Objects (
REG_BINARY)
BOOL ReadFont(CString csKey, CString csName, CFont* pFont);
BOOL WriteFont(CString csKey, CString csName, CFont* pFont);
BOOL ReadPoint(CString csKey, CString csName, CPoint* pPoint);
BOOL WritePoint(CString csKey, CString csName, CPoint* pPoint);
BOOL ReadSize(CString csKey, CString csName, CSize* pSize);
BOOL WriteSize(CString csKey, CString csName, CSize* pSize);
BOOL ReadRect(CString csKey, CString csName, CRect* pRect);
BOOL WriteRect(CString csKey, CString csName, CRect* pRect);
- Display errors that come from the calls to Native APIs in nt.dll.
- Provide a default Value in case the operation fails.
- Enable privileges for the current user which gives them the ability (if it doesn't exist already) to backup/restore Hives/Keys.
Using the code
Using the CNtRegistry class is actually very simple. Once you have declared CNtRegistry, initialize the class by calling InitNtRegistry(), call SetRootKey, then SetKey to set "SOFTWARE\MyApp". You can also use SetKey(HKEY hRoot, CString strKey, BOOL bCanCreate, BOOL bCanSaveCurrentKey) which simply combines the two functions (SetRootKey and SetKey). Now call almost any function ... like CreateHiddenKey to create a hidden key (or try a number of other functions).
Here is an example that creates a hidden key, then puts some values in it (which are also hidden). #define "NtRegistry.h"
void CMyApp::ReadRegistry()
{
CNtRegistry ntReg;
ntReg.InitNtRegistry();
if (ntReg.SetKey(HKEY_LOCAL_MACHINE,
_T("Software\\MyApp\\Settings"), FALSE, TRUE))
{
if (ntReg.CreateHiddenKey(_T("Software\\MyApp\\Settings\\Hidden")))
{
ntReg.WriteInt(_T("Data1"), 777);
ntReg.WriteFloat(_T("Pi"), 3.14159);
ntReg.WriteString(_T("UserName"), _T("DMadden61"));
int nData = ntReg.ReadInt(_T("Data1"), 0);
pi = ntReg.ReadFloat(_T("Pi"), 0.0);
CString csUserName = ntReg.ReadString(_T("UserName"), _T("ERR"));
}
}
else
{
TRACE("Failed to open/set key\n");
}
}
Simple enough? Well, it is, but how it is all put together was another thing.
Differences between Nt...() calls and Reg...() calls
I am going to show you some of the NT Native Registry APIs that CNtRegistry uses (or at least, is ready for use), talk about what makes these different, and how I modified a popular function called "EnablePrivileges" to use the NT Native APIs.
|
Some Native APIs |
Related Win32 APIs |
Required Privileges |
NtCreateKey |
RegCreateKey, RegCreateKeyEx |
N/A |
NtOpenKey |
RegOpenKey, RegOpenKeyEx |
N/A |
NtDeleteKey |
RegDeleteKey |
N/A |
NtFlushKey |
RegFlushKey |
N/A |
NtSetInformationKey |
None |
N/A |
NtQueryKey |
RegQueryInfoKey |
N/A |
NtEnumerateKey |
RegEnumerateKey, RegEnumerateKeyEx |
N/A |
NtNotifyChangeKey |
RegNotifyChangeKeyValue |
N/A |
NtDeleteValueKey |
RegDeleteValue |
N/A |
NtSetValueKey |
RegSetValue, RegSetValueEx |
N/A |
NtQueryValueKey |
RegQueryValue, RegQueryValueEx |
N/A |
NtEnumerateValueKey |
RegEnumValue |
N/A |
NtQueryMultipleValueKey |
RegQueryMultipleValues |
N/A |
NtEnumerateKey |
RegEnumKey, RegEnumKeyEx |
N/A |
*NtSaveKey |
RegSaveKey |
SeBackupPrivilege |
*NtRestoreKey |
RegRestoreKey |
SeRestorePrivilege |
*NtLoadKey |
RegLoadKey |
SeRestorePrivilege |
*NtLoadKey2 |
None |
SeRestorePrivilege |
*NtReplaceKey |
RegReplaceKey |
SeRestorePrivilege |
*NtUnloadKey |
RegUnloadKey |
SeRestorePrivilege |
NtClose |
CloseHandle |
N/A |
NtCreateFile |
CreateFile |
N/A |
NtOpenThread |
OpenThread |
N/A |
NtOpenProcessToken |
None |
SeCreateTokenPrivilege |
NtAdjustPrivilegesToken |
AdjustTokenPrivileges |
N/A |
NtQueryInformationToken |
GetTokenInformation |
N/A |

The parameters used for NT Native Registry APIs are not the same ones you are familiar with. Did you know that there is actually only two (2) Root (main) Keys in the registry? The rest are simply symbolic links. The two Root Keys are "\Registry\Machine (HKEY_LOCAL_MACHINE)" and "\Registry\User (HKEY_USERS)". Look below to see the HKEY and the TEXT equivalent. Where you would normally write a path for a subkey (RegCreateKey) like this "SOFTWARE\MyApp" and also include the HKEY (HKEY_LOCAL_MACHINE), these Native APIs (NtCreateKey) need the entire "full" path to the subkey, like this: "\Registry\Machine\SOFTWARE\MyApp". The CNtRegistry class lets you make the call the way you are used to, but puts it all together for you (internally), simply by calling the two functions (see below) or one that does it both.
SetRootKey(HKEY_LOCAL_MACHINE);
SetKey(_T("SOFTWARE\\MyApp"),TRUE,TRUE);
- or just the one below which combines the two
SetKey(HKEY_LOCAL_MACHINE,_T("SOFTWARE\\MyApp"),TRUE,TRUE); HKEY_USERS \Registry\User
HKEY_CURRENT_USER \Registry\User\<Users_SID>
HKEY_LOCAL_MACHINE \Registry\Machine
HKEY_CLASSES_ROOT \Registry\Machine\SOFTWARE\Classes
HKEY_CURRENT_CONFIG \Registry\Machine\SYSTEM\CurrentControlSet\
Hardware Profiles\Current
Others are the UNICODE_STRING (U_S) and OBJECT_ATTRIBUTES (O_A) structures. The U_S structure holds the "full" Key path (Unicode string) and length. The O_A struct contains the properties. InitializeObjectAttributes(...) initializes the O_A structure that specifies the properties of an object handle to be opened. A pointer to this structure is then passed to the routine that actually opens the handle (e.g., NtOpenKey(...)).
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING;
typedef UNICODE_STRING *PUNICODE_STRING;
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES;
typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES;
#define InitializeObjectAttributes( p, n, a, r, s ) { \
(p)->Length = sizeof( OBJECT_ATTRIBUTES ); \
(p)->RootDirectory = r; \
(p)->Attributes = a; \
(p)->ObjectName = n; \
(p)->SecurityDescriptor = s; \
(p)->SecurityQualityOfService = NULL; \
}
Code example using the above structures to create a registry key (the native way):...
ANSI_STRING asName;
RtlZeroMemory(&asName,sizeof(asName));
RtlInitAnsiString(&asName,csName);
RtlZeroMemory(&usName,sizeof(usName));
RtlAnsiStringToUnicodeString(&usName,&asName,TRUE);
OBJECT_ATTRIBUTES ObjectAttributes;
InitializeObjectAttributes(&ObjectAttributes,
&usName,
OBJ_CASE_INSENSITIVE,
NULL,NULL);
HANDLE hKey = NULL;
m_NtStatus = NtCreateKey(&hKey,
KEY_ALL_ACCESS,
&ObjectAttributes,
0,
NULL,
REG_OPTION_NON_VOLATILE,
&m_dwDisposition);
if (!NT_SUCCESS(m_NtStatus)) {
return FALSE;
}
else {
NtClose(hKey);
}
...
Because I wanted to use some of the NT Registry Hive APIs (NtSaveKey, etc...), I had to re-write the function EnablePrivileges below to use NT Native APIs (except one function that I couldn't find a native call for, LookupPrivilegeValue).
NTSTATUS CNtRegistry::EnablePrivilege(CString csPrivilege, BOOL bEnable)
{
TOKEN_PRIVILEGES NewState;
HANDLE hToken = NULL;
NTSTATUS NtStatus = STATUS_SUCCESS;
NtStatus = NtOpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES|
TOKEN_QUERY|TOKEN_QUERY_SOURCE,
&hToken);
if (!NT_SUCCESS(NtStatus)) {
return NtStatus;
}
LUID luid;
if ( !LookupPrivilegeValue(NULL,
(LPCTSTR)csPrivilege,
&luid))
{
NtClose( hToken );
return (NTSTATUS) ERROR_FUNCTION_FAILED;
}
NewState.PrivilegeCount = 1;
NewState.Privileges[0].Luid = luid;
NewState.Privileges[0].Attributes = (bEnable ? SE_PRIVILEGE_ENABLED : 0);
NtStatus = NtAdjustPrivilegesToken( hToken,
FALSE,
&NewState,
sizeof(NewState),
(PTOKEN_PRIVILEGES)NULL,
0);
NtClose(hToken);
return NtStatus;
}
In closing...
Being an "Intermediate" programmer, the problems I ran into were simply learning curves in the conversion of different types. I commented out the Hive functions because I was having some problems and I didn't want folks out there to screw up their systems. I also do not use all the Native Registry APIs in the nt.dll.
That is all I have got, I don't expect this to be perfect, so please give me your ideas to make it better. One thing to remember in life itself (and all the challenges that come with it) ... if you make a "mistake" and learn from it, then it never was a mistake to begin with...it was a "lesson"!
Thanks to ...
- CRegistry by Robert Pittenger. The inspiration behind this class!!
Things To-Do
- Incorporate the "Hive" functions in the code.
Ability to "Rename" Keys/Values (shouldn't be too hard with copying/deleting capabilities already there).
Take out "un-needed" code (used when I was writing it).
- Make sure everything is commented (working).
- There is a lot more...
History
There is a lot more that can be done to this class, but time is short and I thought that someone out there might like to help :-)
- August 10, 2006 (0.0.0.37)
- Added recursive parameter to the
CopyKey function.
- Added "
DeleteKeyRecursive()" function.
- July 16, 2006 (0.0.0.36)
- Added "
ShowPermissionsDlg()" common dialog.
- Added Key path in the statusbar.
- July 2, 2006 (0.0.0.35)
- Changed the parameters of "
CopyKeys()/CopyValues()" functions.
- This makes it easier to copy anything/anywhere.
- Changed the parameters of the "
FindHiddenKeys()" function.
- This is so the output goes to a
CStringArray (instead of a message box) which allowed me to display the output in a ListCtrl for display (thanks to a suggestion from "Tcpip2005" from CodeProject)!!
- Added the "
InitNtRegistry()" function which does all the initialization.
- Added the
CaseSensitive parameter to the "Search()" function.
- Added "
#pragma comment(linker...)" to stdafx.h to show XP themes.
- Added some "
Rtl...()" string functions.
RtlInitString()
RtlInitAnsiString()
RtlInitUnicodeString()
RtlAnsiStringToUnicodeString()
RtlUnicodeStringToAnsiString()
RtlFreeString()
RtlFreeAnsiString()
RtlFreeUnicodeString()
- Jun 24, 2006 (0.0.0.34)
- Added "
RenameKey()" that uses the "NtRenameKey()".
- Added "
RenameValue()" that uses home-bread functions.
- Reformated the header and source so that the order of the functions in the header match the order in the source.
- Jun 22, 2006 (0.0.0.33)
- Combined "
SetRootKey() and SetKey" and added more explanations in the article.
- Added "
GetCurrentUsersTextualSid()" that returns the private variable "m_csSID".
- Jun 11, 2006 - Release to public.
- Jun 03, 2004 - Initial playing.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 62 (Total in Forum: 62) (Refresh) | FirstPrevNext |
|
 |
|
|
 |
|
|
Hi , I want to write a sample application for registry cleaning. I wanted to know how do we decide if a particular registry key is invaid or not so that we can delete the key. How do we search for invalid registry keys. I am using c++ Thanks, Gayatri
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I added sources to a project and it looks like the errors I get are because the class is not Unicode aware. Is there any plan for supporting Unicode?
// "In the end it's a little boy expressing himself." Yanni while (I_am_alive) {     cout<<"I love to do more than just programming."; }
modified on Monday, May 12, 2008 2:22 PM
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
Hi.. I am the administrator on my machine, and whenever I call NtLoadKey, I get the NTSTATUS error code STATUS_PRIVILEGE_NOT_HELD. How do I fix this? I don't know how to request permissions, so any spoonfeeding is appreciated.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
The article hasn't been updated for over a year, but you mention in some of your posts that you have made some changes/fixes. Is it possible to get hold of the latest version of the source code for this and also for the NtRegEdit article ?
Also, do you have changelogs for either/both of them ?
Thanks in advance!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Sorry it took soo long ... I have played around but the last 6-9 months have been very busy for me I can give what I got but cannot guarantee anything ... I do plan on really doing a lot more work on it soon. You are more than welcome to help if you would like.
Change logs I do not have ...
Regards,
Dan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Dan Madden wrote: I can give what I got but cannot guarantee anything ... I do plan on really doing a lot more work on it soon. You are more than welcome to help if you would like.
Thanks Dan. Just send the latest code to my e-mail addy (the one linked with this forum message reply). I can't promise how much work I can spend on it, but I'll pass any changes/fixes back to you for inclusion.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Dan,
I'm not a C++ programmer but I was hoping to use your NTRegistry class as a DLL and call it's functions from within my app.
I was trying to compile the NTRegistry.cpp file with Visual C++ 6.0 SP6 but get errors that, not being a C++ programmer, I have no idea of how to work around them.
For instance: \ntregistry.h(469) : error C2146: syntax error : missing ';' before identifier 'Information' \ntregistry.h(469) : error C2501: 'ULONG_PTR' : missing storage-class or type specifiers \ntregistry.h(469) : error C2501: 'Information' : missing storage-class or type specifiers
Would you happen to have an already compiled file that you could post here?
Much appreciated,
Ed
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi Ed,
Sorry for the long delay in the response. If you make this into a DLL, then you might as well use the MS Adv...32.dll which does what this does. I just bypass it to show what they are calling.
If making it into a DLL is what you really want, then it should be possible.
The error above should be fixed by adding this:
typedef ULONG *ULONG_PTR;
or
typedef unsigned long *ULONG_PTR;
I hope this helps!
Regards,
Dan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I wrote an application which creates a hidden registry key using the '\0' technique you describe.
The key is created fine. However, when I try to open the key with NtOpenKey, I am unable to. If I try to open the key using NtCreateKey() then it opens fine. I see this abnormal behavior on Windows x64 OS only - on Windows XP 32-bit OS it runs fine.
Is this a known problem and also is there a workaround for it?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
HI JeffRoz,
Hmmm, I don't have 64bit system ... I will be installing Vista shortly and I might even get a 64 bit up and running if I got time...Thanks for the info!
Regards,
Dan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi,
neat stuff but did you thought about freeing mem? I don't looked very deep through your code but I looked at ReadMultiString(CString csKey, CString csName, CStringArray& csaReturn) there I found:
RtlAnsiStringToUnicodeString(&ValueName,&asName,TRUE);
The docu says about the third parameter: Specifies TRUE if this routine should allocate the buffer space for the destination string. If it does, the caller must deallocate the buffer by calling RtlFreeUnicodeString.
Can't find any RtlFreeUnicodeString...
And it's also not very lucky to specify fixed (stack) buffer sizes for unknown sized entries: WCHAR buffer[4096];
Bye Thom
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi Thom,
Yes, I do think about it, but that doesn't mean it happens
I do appreciate your input and I will definately get these fixed. Actually, I am using some of these for the first time so I am learning everyday. I will be making some changes and when ready I will run them by you (meaning Src) for you to check out ... ok?
Regards,
Dan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi Dan,
hm, don't know. I stepped a little bit deeper in your code because I thought I can use it for some system driver, but it's, to be polite, really bad.
Look at: BOOL CNtRegistry::ReadValue(CString csKey, CString csName, DWORD dwRegType, KEY_VALUE_PARTIAL_INFORMATION** retInfo)
You reserve there a local stack mem: WCHAR infoBuffer[256];
and then return this mem, after filling it, outside. This is first class of programming (never, never ....). This normally will not work. Don't know if it ever.
So, overall, the idea is good but the code...
Thom
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Hi Dan,
sorry for making feeling you bad, but I thought the code here at CP should at least have 'some' standard. And, to my innocence, I haven't read any of the other messages here and I also don't read your article in detail. I just downloaded the code, looked into, and thought ...
So, sorry, and keep the ears up.
Thom
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
Hi Dan,
First of all, I should say that your class is very nice, but have you heard about a mean to replace the function LookupPrivilegeValue(...) which is not a native function.
In my point of view it's useless to have a native class if even one function isn't native compliant. It means that it can't be used for its purpose, which is: run before win32 has started.
I would like to be able to provide you with a solution, but I must confess that I don't know how to do it and it’s a pain in my a** (oups sorry) because it’s exactly what I need.
I wasn’t able to find anyone knowing this but the solution exists as this function is present in the win32 api.
Well, if I find a way, I will let you know…
Regards
A.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Took me 2 days to find out this one:
NewState.Privileges[0].Luid = RtlConvertUlongToLuid(privilege);
privileges are declared as ULONG and defined in ntddk.h. The RtlConvertUlongToLuid is the function you are looking for.
Regards
A.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi A.
First off let me say sorry for the late response!! Now, thanks for this and I will be updating the code to reflect this!!
Regards,
Dan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Would you like to view/test the "newer" code before posting? Send me an email...
Here is what I did:
// // // LUID CNtRegistry::RtlConvertUlongToLuid( ULONG Ulong ) { LUID TempLuid;
TempLuid.LowPart = Ulong; TempLuid.HighPart = 0; return(TempLuid); } // // This is used in the "Old" call so that it converts the Priv // to a ULONG... // // Defaults to "SE_UNDOCK_NAME" // ULONG CNtRegistry::ConvertPrivilegeToULong(CString csPrivilege) { //SE_PRIVS SePrivilege for (int n=1; n<=30; n++) { if (stSe2ULong[n].csPrivilege == csPrivilege) { return (ULONG)stSe2ULong[n].SePrivilege; } } return (ULONG)25; // SE_UNDOCK_NAME } ... ... ... ... // // The old call still exists... // NTSTATUS CNtRegistry::EnablePrivilege(CString csPrivilege, BOOL bEnable) { return EnablePrivilege((SE_PRIVS)ConvertPrivilegeToULong(csPrivilege), bEnable); }
// // And the new one uses enum values (will be converted into ULONGs) // NTSTATUS CNtRegistry::EnablePrivilege(SE_PRIVS SePrivilege, BOOL bEnable) { ... ... ... // // And now the new call... // NewState.Privileges[0].Luid = RtlConvertUlongToLuid((ULONG)SePrivilege); ... ... ... }
Is this what you had in mind?
Regards,
Dan
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
| | |