I want to use RegSaveKey, but getting errors when using this function on NT platforms (it works with 9x). This topic was already discussed, but without a final solution (http://nosub.win32asmcommunity.net/viewtopic.php?t=12261&highlight=regsavekey)
Perhaps someone now has a working source sample?
Posted on 2005-03-06 03:25:29 by japheth
Hi Jappeth,

Source : Undocumented WindowsNT
Section : Securty

The major WIN32 API implementation difference between Windows 95/98 and Windows NT is security. Windows 95/98's implementation does not have any support for security. In all the Win32 API functions that have SECURITY ATTRIBUTES as one of the parameters, Windows 95/98's implementation just ignores these parameters. This has some impact on the way a developer programs. Registry APIs such as RegSaveKey and RegRestoreKey work fine under Windows 95/98. However, under
Windows NT, you need to do a few things before you can use these functions. In Windows NT, there is a concept of privileges. There are different kinds of privileges, such as Shutdown, Backup, and Restore. Before using a function such as RegSaveKey, you need to acquire the Backup privilege. To use RegRestoreKey, you need to acquire the Restore privilege, and to use the InitiateSystemShutdown function, you need to
acquire the Shutdown privilege.

RegSaveKey = NtSaveKey ? (I don't try yet)

I found with google this link:


Posted on 2005-03-06 04:10:16 by CYDONIA

in fact its a security issue.

I managed to get it to work on NT platforms now. Found a simple C source fragment how to set SE_BACKUP_NAME privilege and converted it to MASM:

;// The following example can be used to enable or disable the
;// backup privilege. By making the indicated substitutions, you can
;// also use this example to enable or disable the restore privilege
;// Use the following to enable the privilege:
;// hr = ModifyPrivilege(SE_BACKUP_NAME, TRUE);
;// Use the following to disable the privilege:
;// hr = ModifyPrivilege(SE_BACKUP_NAME, FALSE);
;// Use SE_RESTORE_NAME for the restore privilege.

.model flat, stdcall
option casemap:none

include windows.inc



ModifyPrivilege proc szPrivilege:LPSTR, fEnable:BOOL
local hr:HRESULT
local luid:LUID
local hToken:HANDLE

mov hr, S_OK
mov hToken, NULL

; // Open the process token for this process.
; if (!OpenProcessToken(GetCurrentProcess(),
; &hToken ))
; {
; printf("Failed OpenProcessToken\n");
; }
invoke GetCurrentProcess
lea ecx, hToken
invoke OpenProcessToken, eax, TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, ecx
.if (!eax)

; // Get the local unique id for the privilege.
; if ( !LookupPrivilegeValue( NULL,
; szPrivilege,
; &luid ))
; {
; CloseHandle( hToken );
; printf("Failed LookupPrivilegeValue\n");
; }
invoke LookupPrivilegeValue, NULL, szPrivilege, addr luid
.if (!eax)
invoke CloseHandle, hToken

; // Assign values to the TOKEN_PRIVILEGE structure.
; NewState.PrivilegeCount = 1;
; NewState.Privileges[0].Luid = luid;
; NewState.Privileges[0].Attributes = (fEnable ? SE_PRIVILEGE_ENABLED : 0);
mov NewState.PrivilegeCount,1
mov eax, luid.LowPart
mov ecx, luid.HighPart
mov NewState.Privileges[0*sizeof LUID_AND_ATTRIBUTES].Luid.LowPart,eax
mov NewState.Privileges[0*sizeof LUID_AND_ATTRIBUTES].Luid.HighPart,ecx
.if (fEnable)
mov eax, 0
mov NewState.Privileges[0*sizeof LUID_AND_ATTRIBUTES].Attributes,eax

; // Adjust the token privilege.
; if (!AdjustTokenPrivileges(hToken,
; &NewState,
; sizeof(NewState),
; NULL))
; {
; printf("Failed AdjustTokenPrivileges\n");
; }
invoke AdjustTokenPrivileges, hToken, FALSE, addr NewState, sizeof NewState, NULL, NULL
.if (!eax)

; // Close the handle.
; CloseHandle(hToken);
invoke CloseHandle, hToken

; return hr;
mov eax, hr
ModifyPrivilege endp


this function has to be called before RegSaveKey:

invoke ModifyPrivilege, SE_BACKUP_NAME, TRUE
invoke RegSaveKey, ...

but please note that SE_BACKUP_NAME is defined wrong in MASM32's windows.inc (it has to be a string pointer, not a string constant)

Posted on 2005-03-06 04:35:45 by japheth
well if you are not averse to reverse the latest release from sysinternals
rootkitrevealer uses RegSaveKeyW to dump the
user.hiv for its reading of raw dump iirc when i poked inside it some days ago
Posted on 2005-03-06 05:18:46 by bluffer
Saving the registry values works.

With restoring the values there remains a slight problem. RegRestoreKey doesn't exist on win9x, so I tried RegLoadKey for this platform. But it seems with this function one can only "restore" keys just below the root (i.e., it works for restoring HKLM\<mykey>, but not for HKLM\Software\<mykey>). Pretty annoying. Now I remember why I always hated this registry stuff and prefer private profile files.
Posted on 2005-03-06 06:32:44 by japheth
Hello japheth,

I had a problem similar a few months ago. I ended up using CreateProcess with regedit.exe /e to backup a file which can be later restored using regedit.exe /c. Works on all windows platforms providing regedit.exe is on hard drive and there are no security issues with win nt or xp and no api's that break under wrong version of windows.

hope this is helpful and best regards,

Posted on 2005-03-06 21:11:44 by czDrillard
Hello czDrillard.

thanks, I think I will try this approach as well. It's far better because the output file may be used as import on other platforms (9x -> NT). A catch may be that it may not work if an instance of regedit.exe is already running?
Posted on 2005-03-07 00:35:45 by japheth
Works almost perfectly. But I would like to export a registry branch on winXP in old NT4 format so it can be imported on win9x systems. regedit doesn't tell me its command line options, so anyone knows them?
Posted on 2005-03-07 02:03:47 by japheth
yeah it is too late o reply :) i was reading through replies to your posts and this thread caught my attention
i think japheth might have found out this earlier
so i am posting this only to complete the question :

To export a filename.reg file, in W9x/NT4 format, suitable for merging with W9x/NT4/NT5 registries, use:

regedit /a "<Drive:>\FolderName\FileName.reg" "KeyPath"


Posted on 2005-09-06 07:26:05 by bluffer