Simplified root key handling now that the server supports a real root
key. Fixed a few prototypes. Implemented NtDeleteKey/NtDeleteValueKey.
This commit is contained in:
parent
46487282dd
commit
f9087e2bfa
235
dlls/ntdll/reg.c
235
dlls/ntdll/reg.c
|
@ -18,195 +18,138 @@
|
||||||
|
|
||||||
DEFAULT_DEBUG_CHANNEL(ntdll);
|
DEFAULT_DEBUG_CHANNEL(ntdll);
|
||||||
|
|
||||||
|
static const WCHAR root_name[] = { '\\','R','e','g','i','s','t','r','y','\\',0 };
|
||||||
|
static const UNICODE_STRING root_path =
|
||||||
|
{
|
||||||
|
sizeof(root_name)-sizeof(WCHAR), /* Length */
|
||||||
|
sizeof(root_name), /* MaximumLength */
|
||||||
|
(LPWSTR)root_name /* Buffer */
|
||||||
|
};
|
||||||
|
|
||||||
/* copy a key name into the request buffer */
|
/* copy a key name into the request buffer */
|
||||||
static inline NTSTATUS copy_nameU( LPWSTR Dest, PUNICODE_STRING Name, UINT Offset )
|
static NTSTATUS copy_key_name( LPWSTR dest, const UNICODE_STRING *name )
|
||||||
{
|
{
|
||||||
if (Name->Buffer)
|
int len = name->Length, pos = 0;
|
||||||
{
|
|
||||||
if ((Name->Length-Offset) > MAX_PATH) return STATUS_BUFFER_OVERFLOW;
|
if (len >= MAX_PATH) return STATUS_BUFFER_OVERFLOW;
|
||||||
strcpyW( Dest, Name->Buffer+Offset );
|
if (RtlPrefixUnicodeString( &root_path, name, TRUE ))
|
||||||
}
|
{
|
||||||
else Dest[0] = 0;
|
pos += root_path.Length / sizeof(WCHAR);
|
||||||
return STATUS_SUCCESS;
|
len -= root_path.Length;
|
||||||
|
}
|
||||||
|
if (len) memcpy( dest, name->Buffer + pos, len );
|
||||||
|
dest[len / sizeof(WCHAR)] = 0;
|
||||||
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* translates predefined paths to HKEY_ constants */
|
|
||||||
static BOOLEAN _NtKeyToWinKey(
|
/* copy a key name into the request buffer */
|
||||||
IN POBJECT_ATTRIBUTES ObjectAttributes,
|
static inline NTSTATUS copy_nameU( LPWSTR Dest, const UNICODE_STRING *name, UINT max )
|
||||||
OUT UINT * Offset, /* offset within ObjectName */
|
|
||||||
OUT HKEY * KeyHandle) /* translated handle */
|
|
||||||
{
|
{
|
||||||
static const WCHAR KeyPath_HKLM[] = {
|
if (name->Length >= max) return STATUS_BUFFER_OVERFLOW;
|
||||||
'\\','R','E','G','I','S','T','R','Y',
|
if (name->Length) memcpy( Dest, name->Buffer, name->Length );
|
||||||
'\\','M','A','C','H','I','N','E',0};
|
Dest[name->Length / sizeof(WCHAR)] = 0;
|
||||||
static const WCHAR KeyPath_HKU [] = {
|
return STATUS_SUCCESS;
|
||||||
'\\','R','E','G','I','S','T','R','Y',
|
|
||||||
'\\','U','S','E','R',0};
|
|
||||||
static const WCHAR KeyPath_HCC [] = {
|
|
||||||
'\\','R','E','G','I','S','T','R','Y',
|
|
||||||
'\\','M','A','C','H','I','N','E',
|
|
||||||
'\\','S','Y','S','T','E','M',
|
|
||||||
'\\','C','U','R','R','E','N','T','C','O','N','T','R','O','L','S','E','T',
|
|
||||||
'\\','H','A','R','D','W','A','R','E','P','R','O','F','I','L','E','S',
|
|
||||||
'\\','C','U','R','R','E','N','T',0};
|
|
||||||
static const WCHAR KeyPath_HCR [] = {
|
|
||||||
'\\','R','E','G','I','S','T','R','Y',
|
|
||||||
'\\','M','A','C','H','I','N','E',
|
|
||||||
'\\','S','O','F','T','W','A','R','E',
|
|
||||||
'\\','C','L','A','S','S','E','S',0};
|
|
||||||
int len;
|
|
||||||
PUNICODE_STRING ObjectName = ObjectAttributes->ObjectName;
|
|
||||||
|
|
||||||
if(ObjectAttributes->RootDirectory)
|
|
||||||
{
|
|
||||||
len = 0;
|
|
||||||
*KeyHandle = ObjectAttributes->RootDirectory;
|
|
||||||
}
|
|
||||||
else if((ObjectName->Length > (len=strlenW(KeyPath_HKLM)))
|
|
||||||
&& (0==strncmpiW(ObjectName->Buffer,KeyPath_HKLM,len)))
|
|
||||||
{ *KeyHandle = HKEY_LOCAL_MACHINE;
|
|
||||||
}
|
|
||||||
else if((ObjectName->Length > (len=strlenW(KeyPath_HKU)))
|
|
||||||
&& (0==strncmpiW(ObjectName->Buffer,KeyPath_HKU,len)))
|
|
||||||
{ *KeyHandle = HKEY_USERS;
|
|
||||||
}
|
|
||||||
else if((ObjectName->Length > (len=strlenW(KeyPath_HCR)))
|
|
||||||
&& (0==strncmpiW(ObjectName->Buffer,KeyPath_HCR,len)))
|
|
||||||
{ *KeyHandle = HKEY_CLASSES_ROOT;
|
|
||||||
}
|
|
||||||
else if((ObjectName->Length > (len=strlenW(KeyPath_HCC)))
|
|
||||||
&& (0==strncmpiW(ObjectName->Buffer,KeyPath_HCC,len)))
|
|
||||||
{ *KeyHandle = HKEY_CURRENT_CONFIG;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*KeyHandle = 0;
|
|
||||||
*Offset = 0;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (len > 0 && ObjectName->Buffer[len] == (WCHAR)'\\') len++;
|
|
||||||
*Offset = len;
|
|
||||||
|
|
||||||
TRACE("off=%u hkey=0x%08x\n", *Offset, *KeyHandle);
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* NtCreateKey [NTDLL]
|
* NtCreateKey [NTDLL]
|
||||||
* ZwCreateKey
|
* ZwCreateKey
|
||||||
*/
|
*/
|
||||||
NTSTATUS WINAPI NtCreateKey(
|
NTSTATUS WINAPI NtCreateKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
|
||||||
PHANDLE KeyHandle,
|
ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
|
||||||
ACCESS_MASK DesiredAccess,
|
PULONG dispos )
|
||||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
|
||||||
ULONG TitleIndex,
|
|
||||||
PUNICODE_STRING Class,
|
|
||||||
ULONG CreateOptions,
|
|
||||||
PULONG Disposition)
|
|
||||||
{
|
{
|
||||||
struct create_key_request *req = get_req_buffer();
|
struct create_key_request *req = get_req_buffer();
|
||||||
UINT ObjectNameOffset;
|
NTSTATUS ret;
|
||||||
HKEY RootDirectory;
|
|
||||||
NTSTATUS ret;
|
|
||||||
|
|
||||||
TRACE("(%p,0x%08lx,0x%08lx,%p(%s),0x%08lx,%p)\n",
|
TRACE( "(0x%x,%s,%s,%lx,%lx,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName),
|
||||||
KeyHandle, DesiredAccess, TitleIndex, Class, debugstr_us(Class), CreateOptions, Disposition);
|
debugstr_us(class), options, access, retkey );
|
||||||
dump_ObjectAttributes(ObjectAttributes);
|
|
||||||
|
|
||||||
if (!KeyHandle)
|
if (!retkey) return STATUS_INVALID_PARAMETER;
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
_NtKeyToWinKey(ObjectAttributes, &ObjectNameOffset, &RootDirectory);
|
req->parent = attr->RootDirectory;
|
||||||
|
req->access = access;
|
||||||
|
req->options = options;
|
||||||
|
req->modif = 0;
|
||||||
|
|
||||||
req->parent = RootDirectory;
|
if ((ret = copy_key_name( req->name, attr->ObjectName ))) return ret;
|
||||||
req->access = DesiredAccess;
|
req->class[0] = 0;
|
||||||
req->options = CreateOptions;
|
if (class)
|
||||||
req->modif = time(NULL);
|
{
|
||||||
|
if ((ret = copy_nameU( req->class, class, server_remaining(req->class) ))) return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (copy_nameU( req->name, ObjectAttributes->ObjectName, ObjectNameOffset ) != STATUS_SUCCESS)
|
if (!(ret = server_call_noerr( REQ_CREATE_KEY )))
|
||||||
return STATUS_INVALID_PARAMETER;
|
{
|
||||||
|
*retkey = req->hkey;
|
||||||
if (Class)
|
if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
|
||||||
{
|
}
|
||||||
int ClassLen = Class->Length+1;
|
return ret;
|
||||||
if ( ClassLen*sizeof(WCHAR) > server_remaining(req->class)) return STATUS_BUFFER_OVERFLOW;
|
|
||||||
memcpy( req->class, Class->Buffer, ClassLen );
|
|
||||||
req->class[ClassLen] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
req->class[0] = 0x0000;
|
|
||||||
|
|
||||||
if (!(ret = server_call_noerr(REQ_CREATE_KEY)))
|
|
||||||
{
|
|
||||||
*KeyHandle = req->hkey;
|
|
||||||
if (Disposition) *Disposition = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* NtOpenKey [NTDLL.129]
|
* NtOpenKey [NTDLL.129]
|
||||||
* ZwOpenKey
|
* ZwOpenKey
|
||||||
* OUT PHANDLE KeyHandle (returns 0 when failure)
|
* OUT PHANDLE retkey (returns 0 when failure)
|
||||||
* IN ACCESS_MASK DesiredAccess
|
* IN ACCESS_MASK access
|
||||||
* IN POBJECT_ATTRIBUTES ObjectAttributes
|
* IN POBJECT_ATTRIBUTES attr
|
||||||
*/
|
*/
|
||||||
NTSTATUS WINAPI NtOpenKey(
|
NTSTATUS WINAPI NtOpenKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr )
|
||||||
PHANDLE KeyHandle,
|
|
||||||
ACCESS_MASK DesiredAccess,
|
|
||||||
POBJECT_ATTRIBUTES ObjectAttributes)
|
|
||||||
{
|
{
|
||||||
struct open_key_request *req = get_req_buffer();
|
struct open_key_request *req = get_req_buffer();
|
||||||
UINT ObjectNameOffset;
|
NTSTATUS ret;
|
||||||
HKEY RootDirectory;
|
|
||||||
NTSTATUS ret;
|
|
||||||
|
|
||||||
TRACE("(%p,0x%08lx)\n", KeyHandle, DesiredAccess);
|
TRACE( "(0x%x,%s,%lx,%p)\n", attr->RootDirectory,
|
||||||
dump_ObjectAttributes(ObjectAttributes);
|
debugstr_us(attr->ObjectName), access, retkey );
|
||||||
|
|
||||||
if (!KeyHandle) return STATUS_INVALID_PARAMETER;
|
if (!retkey) return STATUS_INVALID_PARAMETER;
|
||||||
*KeyHandle = 0;
|
*retkey = 0;
|
||||||
|
|
||||||
_NtKeyToWinKey(ObjectAttributes, &ObjectNameOffset, &RootDirectory);
|
req->parent = attr->RootDirectory;
|
||||||
|
req->access = access;
|
||||||
|
|
||||||
req->parent = RootDirectory;
|
if ((ret = copy_key_name( req->name, attr->ObjectName ))) return ret;
|
||||||
req->access = DesiredAccess;
|
if (!(ret = server_call_noerr( REQ_OPEN_KEY ))) *retkey = req->hkey;
|
||||||
|
return ret;
|
||||||
if (copy_nameU( req->name, ObjectAttributes->ObjectName, ObjectNameOffset ) != STATUS_SUCCESS)
|
|
||||||
return STATUS_INVALID_PARAMETER;
|
|
||||||
|
|
||||||
if (!(ret = server_call_noerr(REQ_OPEN_KEY)))
|
|
||||||
{
|
|
||||||
*KeyHandle = req->hkey;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* NtDeleteKey [NTDLL]
|
* NtDeleteKey [NTDLL]
|
||||||
* ZwDeleteKey
|
* ZwDeleteKey
|
||||||
*/
|
*/
|
||||||
NTSTATUS WINAPI NtDeleteKey(HANDLE KeyHandle)
|
NTSTATUS WINAPI NtDeleteKey( HANDLE hkey )
|
||||||
{
|
{
|
||||||
FIXME("(0x%08x) stub!\n",
|
struct delete_key_request *req = get_req_buffer();
|
||||||
KeyHandle);
|
|
||||||
return STATUS_SUCCESS;
|
TRACE( "(%x)\n", hkey );
|
||||||
|
req->hkey = hkey;
|
||||||
|
req->name[0] = 0;
|
||||||
|
return server_call_noerr( REQ_DELETE_KEY );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* NtDeleteValueKey [NTDLL]
|
* NtDeleteValueKey [NTDLL]
|
||||||
* ZwDeleteValueKey
|
* ZwDeleteValueKey
|
||||||
*/
|
*/
|
||||||
NTSTATUS WINAPI NtDeleteValueKey(
|
NTSTATUS WINAPI NtDeleteValueKey( HANDLE hkey, const UNICODE_STRING *name )
|
||||||
IN HANDLE KeyHandle,
|
|
||||||
IN PUNICODE_STRING ValueName)
|
|
||||||
{
|
{
|
||||||
FIXME("(0x%08x,%p(%s)) stub!\n",
|
NTSTATUS ret;
|
||||||
KeyHandle, ValueName,debugstr_us(ValueName));
|
struct delete_key_value_request *req = get_req_buffer();
|
||||||
return STATUS_SUCCESS;
|
|
||||||
|
TRACE( "(0x%x,%s)\n", hkey, debugstr_us(name) );
|
||||||
|
|
||||||
|
req->hkey = hkey;
|
||||||
|
if (!(ret = copy_nameU( req->name, name, MAX_PATH )))
|
||||||
|
ret = server_call_noerr( REQ_DELETE_KEY_VALUE );
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* NtEnumerateKey [NTDLL]
|
* NtEnumerateKey [NTDLL]
|
||||||
* ZwEnumerateKey
|
* ZwEnumerateKey
|
||||||
|
@ -540,7 +483,7 @@ NTSTATUS WINAPI NtQueryValueKey(
|
||||||
KeyHandle, debugstr_us(ValueName), KeyValueInformationClass, KeyValueInformation, Length, ResultLength);
|
KeyHandle, debugstr_us(ValueName), KeyValueInformationClass, KeyValueInformation, Length, ResultLength);
|
||||||
|
|
||||||
req->hkey = KeyHandle;
|
req->hkey = KeyHandle;
|
||||||
if (copy_nameU(req->name, ValueName, 0) != STATUS_SUCCESS) return STATUS_BUFFER_OVERFLOW;
|
if (copy_nameU(req->name, ValueName, MAX_PATH) != STATUS_SUCCESS) return STATUS_BUFFER_OVERFLOW;
|
||||||
if ((ret = server_call_noerr(REQ_GET_KEY_VALUE)) != STATUS_SUCCESS) return ret;
|
if ((ret = server_call_noerr(REQ_GET_KEY_VALUE)) != STATUS_SUCCESS) return ret;
|
||||||
|
|
||||||
switch(KeyValueInformationClass)
|
switch(KeyValueInformationClass)
|
||||||
|
|
|
@ -812,25 +812,11 @@ NtSetSecurityObject(
|
||||||
|
|
||||||
/* registry functions */
|
/* registry functions */
|
||||||
|
|
||||||
NTSTATUS WINAPI NtCreateKey(
|
NTSTATUS WINAPI NtCreateKey(PHANDLE,ACCESS_MASK,const OBJECT_ATTRIBUTES*,ULONG,
|
||||||
PHANDLE KeyHandle,
|
const UNICODE_STRING*,ULONG,PULONG);
|
||||||
ACCESS_MASK DesiredAccess,
|
NTSTATUS WINAPI NtDeleteKey(HANDLE);
|
||||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
NTSTATUS WINAPI NtDeleteValueKey(HANDLE,const UNICODE_STRING*);
|
||||||
ULONG TitleIndex,
|
NTSTATUS WINAPI NtOpenKey(PHANDLE,ACCESS_MASK,const OBJECT_ATTRIBUTES*);
|
||||||
PUNICODE_STRING Class,
|
|
||||||
ULONG CreateOptions,
|
|
||||||
PULONG Disposition);
|
|
||||||
|
|
||||||
NTSTATUS WINAPI NtOpenKey(
|
|
||||||
PHANDLE KeyHandle,
|
|
||||||
ACCESS_MASK DesiredAccess,
|
|
||||||
POBJECT_ATTRIBUTES ObjectAttributes);
|
|
||||||
|
|
||||||
NTSTATUS WINAPI NtDeleteKey(HANDLE KeyHandle);
|
|
||||||
|
|
||||||
NTSTATUS WINAPI NtDeleteValueKey(
|
|
||||||
IN HANDLE KeyHandle,
|
|
||||||
IN PUNICODE_STRING ValueName);
|
|
||||||
|
|
||||||
NTSTATUS WINAPI NtEnumerateKey(
|
NTSTATUS WINAPI NtEnumerateKey(
|
||||||
HANDLE KeyHandle,
|
HANDLE KeyHandle,
|
||||||
|
|
Loading…
Reference in New Issue