RegOpenKey, RegOpenKeyEx A/W imported and ported from WINE. This keeps the current test set in advapi32_test registry on 85/0 level
Modified: trunk/reactos/lib/advapi32/reg/reg.c

Modified: trunk/reactos/lib/advapi32/reg/reg.c
--- trunk/reactos/lib/advapi32/reg/reg.c	2005-05-04 15:27:05 UTC (rev 14968)
+++ trunk/reactos/lib/advapi32/reg/reg.c	2005-05-04 15:53:54 UTC (rev 14969)
@@ -8,6 +8,7 @@
  * UPDATE HISTORY:
  *                  Created 01/11/98
  *                  19990309 EA Stubs
+ *                  20050502 Fireball imported some stuff from WINE
  */
 
 /* INCLUDES *****************************************************************/
@@ -22,6 +23,9 @@
 #define REG_MAX_NAME_SIZE     256
 #define REG_MAX_DATA_SIZE     2048
 
+/* FIXME: should go into msvcrt.h header? */
+#define offsetof(s,m)       (size_t)&(((s*)NULL)->m)
+
 /* GLOBALS ******************************************************************/
 
 static RTL_CRITICAL_SECTION HandleTableCS;
@@ -40,6 +44,11 @@
 
 
 /* FUNCTIONS ****************************************************************/
+/* check if value type needs string conversion (Ansi<->Unicode) */
+inline static int is_string( DWORD type )
+{
+    return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ);
+}
 
 /************************************************************************
  *  RegInitDefaultHandles
@@ -1161,417 +1170,226 @@
   return ErrorCode;
 }
 
-
 /************************************************************************
  *  RegEnumValueA
  *
  * @implemented
  */
 LONG STDCALL
-RegEnumValueA (HKEY hKey,
-	       DWORD dwIndex,
-	       LPSTR lpValueName,
-	       LPDWORD lpcbValueName, // lpValueName buffer len
-	       LPDWORD lpReserved,
-	       LPDWORD lpType,
-	       LPBYTE lpData,
-	       LPDWORD lpcbData) // lpData buffer len
+RegEnumValueA( HKEY hKey, DWORD index, LPSTR value, LPDWORD val_count,
+               LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
 {
-	union
-	{
-		KEY_VALUE_FULL_INFORMATION Full;
-		KEY_VALUE_BASIC_INFORMATION	Basic;
-	} *ValueInfo;
-
-	ULONG NameLength;
-	ULONG BufferSize;
-	ULONG DataLength = 0;
-	ULONG ResultSize;
 	HANDLE KeyHandle;
-	LONG ErrorCode;
-	NTSTATUS Status;
-	UNICODE_STRING StringU;
-	ANSI_STRING	StringA;
-	BOOL IsStringType;
+    NTSTATUS status;
+    DWORD total_size;
+    char buffer[256], *buf_ptr = buffer;
+    KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer;
+    static const int info_size = offsetof( KEY_VALUE_FULL_INFORMATION, Name );
 
-	ErrorCode =	ERROR_SUCCESS;
+    //TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
+      //    hkey, index, value, val_count, reserved, type, data, count );
 
-	Status = MapDefaultKey (&KeyHandle, hKey);
-	if (!NT_SUCCESS(Status))
+    /* NT only checks count, not val_count */
+    if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
+	status = MapDefaultKey (&KeyHandle, hKey);
+	if (!NT_SUCCESS(status))
 	{
-		ErrorCode =	RtlNtStatusToDosError (Status);
+		LONG ErrorCode;
+		ErrorCode =	RtlNtStatusToDosError (status);
 		SetLastError (ErrorCode);
 		return ErrorCode;
 	}
 
-	if (*lpcbValueName > 0)
-		NameLength = min (*lpcbValueName - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
-	else
-		NameLength = 0;
+    total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
+    if (data) total_size += *count;
+    total_size = min( sizeof(buffer), total_size );
 
-	if (lpData)
-	{
-		DataLength = min (*lpcbData	* sizeof(WCHAR), REG_MAX_DATA_SIZE);
-		BufferSize = ((sizeof(KEY_VALUE_FULL_INFORMATION) +	NameLength + 3)	& ~3) +	DataLength;
-	}
-	else
-	{
-		BufferSize = sizeof(KEY_VALUE_BASIC_INFORMATION) + NameLength;
-	}
+    status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
+                                  buffer, total_size, &total_size );
+    if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
 
-	ValueInfo =	RtlAllocateHeap	(ProcessHeap, 0, BufferSize);
-	if (ValueInfo == NULL)
-	{
-		SetLastError(ERROR_OUTOFMEMORY);
-		return ERROR_OUTOFMEMORY;
-	}
+    /* we need to fetch the contents for a string type even if not requested,
+     * because we need to compute the length of the ASCII string. */
+    if (value || data || is_string(info->Type))
+    {
+        /* retry with a dynamically allocated buffer */
+        while (status == STATUS_BUFFER_OVERFLOW)
+        {
+            if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+            if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
+                return ERROR_NOT_ENOUGH_MEMORY;
+            info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
+            status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
+                                          buf_ptr, total_size, &total_size );
+        }
 
-	Status = NtEnumerateValueKey (KeyHandle,
-		(ULONG)dwIndex,
-		lpData ? KeyValueFullInformation : KeyValueBasicInformation,
-		ValueInfo,
-		BufferSize,
-		&ResultSize);
+        if (status) goto done;
 
-	DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status);
-	if (!NT_SUCCESS(Status))
-	{
-		ErrorCode =	RtlNtStatusToDosError (Status);
+        if (is_string(info->Type))
+        {
+            DWORD len;
+            RtlUnicodeToMultiByteSize( &len, (WCHAR *)(buf_ptr + info->DataOffset),
+                                       total_size - info->DataOffset );
+            if (data && len)
+            {
+                if (len > *count) status = STATUS_BUFFER_OVERFLOW;
+                else
+                {
+                    RtlUnicodeToMultiByteN( data, len, NULL, (WCHAR *)(buf_ptr + info->DataOffset),
+                                            total_size - info->DataOffset );
+                    /* if the type is REG_SZ and data is not 0-terminated
+                     * and there is enough space in the buffer NT appends a \0 */
+                    if (len < *count && data[len-1]) data[len] = 0;
+                }
+            }
+            info->DataLength = len;
+        }
+        else if (data)
+        {
+            if (total_size - info->DataOffset > *count) status = STATUS_BUFFER_OVERFLOW;
+            else memcpy( data, buf_ptr + info->DataOffset, total_size - info->DataOffset );
+        }
 
-		// handle case when BufferSize was too small
-		// we must let caller know the minimum accepted size
-		// and value type
-		if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
-		{
-			ErrorCode = ERROR_MORE_DATA;
+        if (value && !status)
+        {
+            DWORD len;
 
-			// query now with the sufficient buffer size
-			RtlFreeHeap	(ProcessHeap, 0, ValueInfo);
-			BufferSize = ResultSize;
-			ValueInfo =	RtlAllocateHeap	(ProcessHeap, 0, BufferSize); // will be freed at the bottom, as usual
-			if (ValueInfo == NULL)
-			{
-				SetLastError(ERROR_OUTOFMEMORY);
-				return ERROR_OUTOFMEMORY;
-			}
+            RtlUnicodeToMultiByteSize( &len, info->Name, info->NameLength );
+            if (len >= *val_count)
+            {
+                status = STATUS_BUFFER_OVERFLOW;
+                if (*val_count)
+                {
+                    len = *val_count - 1;
+                    RtlUnicodeToMultiByteN( value, len, NULL, info->Name, info->NameLength );
+                    value[len] = 0;
+                }
+            }
+            else
+            {
+                RtlUnicodeToMultiByteN( value, len, NULL, info->Name, info->NameLength );
+                value[len] = 0;
+                *val_count = len;
+            }
+        }
+    }
+    else status = STATUS_SUCCESS;
 
-			Status = NtEnumerateValueKey (KeyHandle,
-										(ULONG)dwIndex,
-										lpData ? KeyValueFullInformation : KeyValueBasicInformation,
-										ValueInfo,
-										BufferSize,
-										&ResultSize);
-			if (!NT_SUCCESS(Status))
-			{
-				// ok, some other error
-				ErrorCode =	RtlNtStatusToDosError (Status);
-			}
-			else
-			{
-				// we have information now, pass it to the caller
-				// but don't touch valueName length here
-				IsStringType = (ValueInfo->Full.Type ==	REG_SZ)	||
-							(ValueInfo->Full.Type == REG_MULTI_SZ) ||
-							(ValueInfo->Full.Type == REG_EXPAND_SZ); //FIXME: Include REG_LINK ?
+    if (type) *type = info->Type;
+    if (count) *count = info->DataLength;
 
-				if (lpData)
-				{
-					if (lpcbData)
-					{
-						if (IsStringType)
-							*lpcbData = ValueInfo->Full.DataLength / sizeof(WCHAR);
-						else
-							*lpcbData = ValueInfo->Full.DataLength;
-					}
-				}
-
-				// pass type also
-				if (lpType)
-					*lpType	= lpData ? ValueInfo->Full.Type	: ValueInfo->Basic.Type;
-			}            
-		}
-	}
-	else
-	{
-		IsStringType = (ValueInfo->Full.Type ==	REG_SZ)	||
-				(ValueInfo->Full.Type == REG_MULTI_SZ) ||
-				(ValueInfo->Full.Type == REG_EXPAND_SZ);
-                if (lpData)
-		{
-			if (ValueInfo->Full.NameLength > NameLength	||
-				(!IsStringType && ValueInfo->Full.DataLength > *lpcbData) ||
-				ValueInfo->Full.DataLength > DataLength)
-			{
-				// overflow data
-				ErrorCode =	ERROR_MORE_DATA;
-
-				// return correct information for data length and type
-                if (lpcbData)
-				{
-					if (IsStringType)
-						*lpcbData = ValueInfo->Full.DataLength / sizeof(WCHAR);
-					else
-						*lpcbData = ValueInfo->Full.DataLength;
-				}
-
-				if (lpType)
-					*lpType	= ValueInfo->Full.Type;
-			}
-			else
-			{
-				if (IsStringType)
-				{
-					StringU.Buffer = (PWCHAR)((ULONG_PTR)ValueInfo + ValueInfo->Full.DataOffset);
-					StringU.Length = ValueInfo->Full.DataLength;
-					StringU.MaximumLength =	DataLength;
-					StringA.Buffer = (PCHAR)lpData;
-					StringA.Length = 0;
-					StringA.MaximumLength =	*lpcbData;
-					RtlUnicodeStringToAnsiString (&StringA,	&StringU, FALSE);
-					*lpcbData =	StringA.Length;
-				}
-				else
-				{
-					RtlCopyMemory (lpData,
-						(PVOID)((ULONG_PTR)ValueInfo + ValueInfo->Full.DataOffset),
-						ValueInfo->Full.DataLength);
-					*lpcbData =	ValueInfo->Full.DataLength;
-				}
-
-				StringU.Buffer = ValueInfo->Full.Name;
-				StringU.Length = ValueInfo->Full.NameLength;
-				StringU.MaximumLength =	NameLength;
-			}
-		}
-		else
-		{
-			if (ValueInfo->Basic.NameLength	> NameLength)
-			{
-				// overflow name
-				ErrorCode =	ERROR_MORE_DATA;
-
-				if (IsStringType)
-					*lpcbData = ValueInfo->Full.DataLength / sizeof(WCHAR);
-				else
-					*lpcbData = ValueInfo->Full.DataLength;
-
-				if (lpType)
-					*lpType	= ValueInfo->Basic.Type;
-			}
-			else
-			{
-				StringU.Buffer = ValueInfo->Basic.Name;
-				StringU.Length = ValueInfo->Basic.NameLength;
-				StringU.MaximumLength =	NameLength;
-			}
-		}
-
-		if (ErrorCode == ERROR_SUCCESS)
-		{
-			StringA.Buffer = (PCHAR)lpValueName;
-			StringA.Length = 0;
-			StringA.MaximumLength =	*lpcbValueName;
-			RtlUnicodeStringToAnsiString (&StringA,	&StringU, FALSE);
-			StringA.Buffer[StringA.Length] = 0;
-			*lpcbValueName = StringA.Length;
-			if (lpType)
-			{
-				*lpType	= lpData ? ValueInfo->Full.Type	: ValueInfo->Basic.Type;
-			}
-		}
-	}
-
-	RtlFreeHeap	(ProcessHeap, 0, ValueInfo);
-
-	if (ErrorCode != ERROR_SUCCESS)
-		SetLastError(ErrorCode);
-
-	return ErrorCode;
+ done:
+    if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+    return RtlNtStatusToDosError(status);
 }
 
-
-/************************************************************************
- *  RegEnumValueW
- *
+/******************************************************************************
+ * RegEnumValueW   [ADVAPI32.@]
  * @implemented
+ * 
+ * PARAMS
+ *  hkey       [I] Handle to key to query
+ *  index      [I] Index of value to query
+ *  value      [O] Value string
+ *  val_count  [I/O] Size of value buffer (in wchars)
+ *  reserved   [I] Reserved
+ *  type       [O] Type code
+ *  data       [O] Value data
+ *  count      [I/O] Size of data buffer (in bytes)
+ *
+ * RETURNS
+ *  Success: ERROR_SUCCESS
+ *  Failure: nonzero error code from Winerror.h
  */
 LONG STDCALL
-RegEnumValueW (HKEY hKey,
-	       DWORD dwIndex,
-	       LPWSTR lpValueName,
-	       LPDWORD lpcbValueName,
-	       LPDWORD lpReserved,
-	       LPDWORD lpType,
-	       LPBYTE lpData,
-	       LPDWORD lpcbData)
+RegEnumValueW( HKEY hKey, DWORD index, LPWSTR value, PDWORD val_count,
+               PDWORD reserved, PDWORD type, LPBYTE data, PDWORD count )
 {
-	union
-	{
-		KEY_VALUE_FULL_INFORMATION Full;
-		KEY_VALUE_BASIC_INFORMATION Basic;
-	} *ValueInfo;
-
-	ULONG NameLength;
-	ULONG BufferSize;
-	ULONG DataLength = 0;
-	ULONG ResultSize;
 	HANDLE KeyHandle;
-	LONG ErrorCode;
-	NTSTATUS Status;
+    NTSTATUS status;
+    DWORD total_size;
+    char buffer[256], *buf_ptr = buffer;
+    KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer;
+    static const int info_size = offsetof( KEY_VALUE_FULL_INFORMATION, Name );
 
-	ErrorCode = ERROR_SUCCESS;
+    //TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
+    //      hkey, index, value, val_count, reserved, type, data, count );
 
-	Status = MapDefaultKey (&KeyHandle, hKey);
-	if (!NT_SUCCESS(Status))
+    /* NT only checks count, not val_count */
+    if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
+	
+	status = MapDefaultKey (&KeyHandle, hKey);
+	if (!NT_SUCCESS(status))
 	{
-		ErrorCode = RtlNtStatusToDosError (Status);
+		LONG ErrorCode;
+		ErrorCode = RtlNtStatusToDosError (status);
 		SetLastError (ErrorCode);
 		return ErrorCode;
 	}
 
-	if (*lpcbValueName > 0)
-		NameLength = min (*lpcbValueName - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
-	else
-		NameLength = 0;
+    total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
+    if (data) total_size += *count;
+    total_size = min( sizeof(buffer), total_size );
 
-	if (lpData)
-	{
-		DataLength = min(*lpcbData, REG_MAX_DATA_SIZE);
-		BufferSize = ((sizeof(KEY_VALUE_FULL_INFORMATION) + NameLength + 3) & ~3) + DataLength;
-	}
-	else
-	{
-		BufferSize = sizeof(KEY_VALUE_BASIC_INFORMATION) + NameLength;
-	}
-	ValueInfo = RtlAllocateHeap (ProcessHeap, 0, BufferSize);
-	if (ValueInfo == NULL)
-	{
-		SetLastError (ERROR_OUTOFMEMORY);
-		return ERROR_OUTOFMEMORY;
-	}
-	Status = NtEnumerateValueKey (KeyHandle,
-		(ULONG)dwIndex,
-		lpData ? KeyValueFullInformation : KeyValueBasicInformation,
-		ValueInfo,
-		BufferSize,
-		&ResultSize);
+    status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
+                                  buffer, total_size, &total_size );
+    if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
 
-	DPRINT("NtEnumerateValueKey() returned status 0x%X\n", Status);
-	if (!NT_SUCCESS(Status))
-	{
-		ErrorCode = RtlNtStatusToDosError (Status);
+    if (value || data)
+    {
+        /* retry with a dynamically allocated buffer */
+        while (status == STATUS_BUFFER_OVERFLOW)
+        {
+            if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+            if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
+                return ERROR_NOT_ENOUGH_MEMORY;
+            info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
+            status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
+                                          buf_ptr, total_size, &total_size );
+        }
 
-		// handle case when BufferSize was too small
-		// we must let caller know the minimum accepted size
-		// and value type
-		if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
-		{
-			ErrorCode = ERROR_MORE_DATA;
+        if (status) goto done;
 
-			// query now with the sufficient buffer size
-			RtlFreeHeap	(ProcessHeap, 0, ValueInfo);
-			BufferSize = ResultSize;
-			ValueInfo =	RtlAllocateHeap	(ProcessHeap, 0, BufferSize); // will be freed at the bottom, as usual
-			if (ValueInfo == NULL)
-			{
-				SetLastError(ERROR_OUTOFMEMORY);
-				return ERROR_OUTOFMEMORY;
-			}
+        if (value)
+        {
+            if (info->NameLength/sizeof(WCHAR) >= *val_count)
+            {
+                status = STATUS_BUFFER_OVERFLOW;
+                goto overflow;
+            }
+            memcpy( value, info->Name, info->NameLength );
+            *val_count = info->NameLength / sizeof(WCHAR);
+            value[*val_count] = 0;
+        }
 
-			Status = NtEnumerateValueKey (KeyHandle,
-										(ULONG)dwIndex,
-										lpData ? KeyValueFullInformation : KeyValueBasicInformation,
-										ValueInfo,
-										BufferSize,
-										&ResultSize);
-			if (!NT_SUCCESS(Status))
-			{
-				// ok, some other error
-				ErrorCode =	RtlNtStatusToDosError (Status);
-			}
-			else
-			{
-				// we have information now, pass it to the caller
-				// but don't touch valueName length here
-				if (lpData && lpcbData)
-					*lpcbData = ValueInfo->Full.DataLength;
+        if (data)
+        {
+            if (total_size - info->DataOffset > *count)
+            {
+                status = STATUS_BUFFER_OVERFLOW;
+                goto overflow;
+            }
+            memcpy( data, buf_ptr + info->DataOffset, total_size - info->DataOffset );
+            if (total_size - info->DataOffset <= *count-sizeof(WCHAR) && is_string(info->Type))
+            {
+                /* if the type is REG_SZ and data is not 0-terminated
+                 * and there is enough space in the buffer NT appends a \0 */
+                WCHAR *ptr = (WCHAR *)(data + total_size - info->DataOffset);
+                if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
+            }
+        }
+    }
+    else status = STATUS_SUCCESS;
 
-				// pass type also
-				if (lpType)
-					*lpType	= lpData ? ValueInfo->Full.Type	: ValueInfo->Basic.Type;
-			}
-		}
-	}
-	else
-	{
-		if (lpData)
-		{
-			if (ValueInfo->Full.DataLength > DataLength ||
-				ValueInfo->Full.NameLength > NameLength)
-			{
-				// overflow data
-				ErrorCode =	ERROR_MORE_DATA;
+ overflow:
+    if (type) *type = info->Type;
+    if (count) *count = info->DataLength;
 
-				// return correct information for data length and type
-                if (lpcbData)
-					*lpcbData = ValueInfo->Full.DataLength;
-
-				if (lpType)
-					*lpType	= ValueInfo->Full.Type;
-			}
-			else
-			{
-				RtlCopyMemory (lpValueName, ValueInfo->Full.Name, ValueInfo->Full.NameLength);
-				*lpcbValueName = (DWORD)(ValueInfo->Full.NameLength / sizeof(WCHAR));
-				lpValueName[*lpcbValueName] = 0;
-				RtlCopyMemory (lpData,
-					(PVOID)((ULONG_PTR)ValueInfo + ValueInfo->Full.DataOffset),
-					ValueInfo->Full.DataLength);
-				*lpcbData = (DWORD)ValueInfo->Full.DataLength;
-			}
-		}
-		else
-		{
-			if (ValueInfo->Basic.NameLength > NameLength)
-			{
-				// overflow name
-				ErrorCode =	ERROR_MORE_DATA;
-
-                if (lpcbData)
-					*lpcbData = ValueInfo->Full.DataLength;
-
-				if (lpType)
-					*lpType	= ValueInfo->Basic.Type;
-			}
-			else
-			{
-				RtlCopyMemory (lpValueName, ValueInfo->Basic.Name, ValueInfo->Basic.NameLength);
-				*lpcbValueName = (DWORD)(ValueInfo->Basic.NameLength / sizeof(WCHAR));
-				lpValueName[*lpcbValueName] = 0;
-			}
-
-			if (NULL != lpcbData)
-			{
-				*lpcbData = (DWORD)ValueInfo->Full.DataLength;
-				DPRINT1("BUG: Using ValueInfo as FULL when it is really BASIC\n");
-			}
-		}
-
-		if (ErrorCode == ERROR_SUCCESS && lpType != NULL)
-		{
-			*lpType = lpData ? ValueInfo->Full.Type : ValueInfo->Basic.Type;
-		}
-	}
-
-	RtlFreeHeap (ProcessHeap, 0, ValueInfo);
-
-	if (ErrorCode != ERROR_SUCCESS)
-		SetLastError (ErrorCode);
-
-	return ErrorCode;
+ done:
+    if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
+    return RtlNtStatusToDosError(status);
 }
 
-
 /************************************************************************
  *  RegFlushKey
  *
@@ -1818,6 +1636,8 @@
 /************************************************************************
  *  RegOpenKeyA
  *
+ *  20050503 Fireball - imported from WINE
+ *
  * @implemented
  */
 LONG STDCALL
@@ -1825,45 +1645,15 @@
 	     LPCSTR lpSubKey,
 	     PHKEY phkResult)
 {
-  OBJECT_ATTRIBUTES ObjectAttributes;
-  UNICODE_STRING SubKeyString;
-  HANDLE KeyHandle;
-  LONG ErrorCode;
-  NTSTATUS Status;
+	DPRINT("RegOpenKeyA hKey 0x%x lpSubKey %s phkResult %p\n", hKey, lpSubKey, phkResult);
 
-  DPRINT("RegOpenKeyA hKey 0x%x lpSubKey %s phkResult %p\n", hKey, lpSubKey, phkResult);
+	if (!lpSubKey || !*lpSubKey)
+	{
+		*phkResult = hKey;
+		return ERROR_SUCCESS;
+	}
 
-  // Check input params
-  if (phkResult == NULL) return ERROR_INVALID_PARAMETER;
-
-  Status = MapDefaultKey (&KeyHandle,
-			  hKey);
-  if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return Status;
-    }
-
-  RtlCreateUnicodeStringFromAsciiz (&SubKeyString,
-				    (LPSTR)lpSubKey);
-  InitializeObjectAttributes (&ObjectAttributes,
-			      &SubKeyString,
-			      OBJ_CASE_INSENSITIVE,
-			      KeyHandle,
-			      NULL);
-  Status = NtOpenKey ((PHANDLE)phkResult,
-		      MAXIMUM_ALLOWED,
-		      &ObjectAttributes);
-  RtlFreeUnicodeString (&SubKeyString);
-  if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
-    }
-
-  return ERROR_SUCCESS;
+	return RegOpenKeyExA( hKey, lpSubKey, 0, KEY_ALL_ACCESS, phkResult);
 }
 
 
@@ -1872,6 +1662,7 @@
  *
  *  19981101 Ariadne
  *  19990525 EA
+ *  20050503 Fireball - imported from WINE
  *
  * @implemented
  */
@@ -1880,44 +1671,14 @@
 	     LPCWSTR lpSubKey,
 	     PHKEY phkResult)
 {
-  OBJECT_ATTRIBUTES ObjectAttributes;
-  UNICODE_STRING SubKeyString;
-  HANDLE KeyHandle;
-  LONG ErrorCode;
-  NTSTATUS Status;
+	DPRINT("RegOpenKeyW hKey 0x%x lpSubKey %S phkResult %p\n", hKey, lpSubKey, phkResult);
 
-  DPRINT("RegOpenKeyW hKey 0x%x lpSubKey %S phkResult %p\n", hKey, lpSubKey, phkResult);
-
-  // Check input params
-  if (phkResult == NULL) return ERROR_INVALID_PARAMETER;
-
-  Status = MapDefaultKey (&KeyHandle,
-			  hKey);
-  if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return Status;
-    }
-
-  RtlInitUnicodeString (&SubKeyString,
-			(LPWSTR)lpSubKey);
-  InitializeObjectAttributes (&ObjectAttributes,
-			      &SubKeyString,
-			      OBJ_CASE_INSENSITIVE,
-			      KeyHandle,
-			      NULL);
-  Status = NtOpenKey ((PHANDLE)phkResult,
-		      MAXIMUM_ALLOWED,
-		      &ObjectAttributes);
-  if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError(ErrorCode);
-      return ErrorCode;
-    }
-
-  return ERROR_SUCCESS;
+	if (!lpSubKey || !*lpSubKey)
+	{
+		*phkResult = hKey;
+		return ERROR_SUCCESS;
+	}
+	return RegOpenKeyExW(hKey, lpSubKey, 0, KEY_ALL_ACCESS, phkResult);
 }
 
 
@@ -1933,42 +1694,40 @@
 	       REGSAM samDesired,
 	       PHKEY phkResult)
 {
-  OBJECT_ATTRIBUTES ObjectAttributes;
-  UNICODE_STRING SubKeyString;
-  HANDLE KeyHandle;
-  LONG ErrorCode;
-  NTSTATUS Status;
+	OBJECT_ATTRIBUTES ObjectAttributes;
+	UNICODE_STRING SubKeyString;
+	HANDLE KeyHandle;
+	LONG ErrorCode;
+	NTSTATUS Status;
 
-  DPRINT("RegOpenKeyExA hKey 0x%x lpSubKey %s ulOptions 0x%x samDesired 0x%x phkResult %p\n",
-         hKey, lpSubKey, ulOptions, samDesired, phkResult);
-  Status = MapDefaultKey (&KeyHandle,
-			  hKey);
-  if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
-    }
+	DPRINT("RegOpenKeyExA hKey 0x%x lpSubKey %s ulOptions 0x%x samDesired 0x%x phkResult %p\n",
+		hKey, lpSubKey, ulOptions, samDesired, phkResult);
 
-  RtlCreateUnicodeStringFromAsciiz (&SubKeyString,
-				    (LPSTR)lpSubKey);
-  InitializeObjectAttributes (&ObjectAttributes,
-			      &SubKeyString,
-			      OBJ_CASE_INSENSITIVE,
-			      KeyHandle,
-			      NULL);
-  Status = NtOpenKey ((PHANDLE)phkResult,
-		      samDesired,
-		      &ObjectAttributes);
-  RtlFreeUnicodeString (&SubKeyString);
-  if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
-   }
+	Status = MapDefaultKey (&KeyHandle, hKey);
+	if (!NT_SUCCESS(Status))
+	{
+		ErrorCode = RtlNtStatusToDosError (Status);
+		SetLastError (ErrorCode);
+		return ErrorCode;
+	}
 
-  return ERROR_SUCCESS;
+	RtlCreateUnicodeStringFromAsciiz (&SubKeyString, (LPSTR)lpSubKey);
+	InitializeObjectAttributes (&ObjectAttributes,
+		&SubKeyString,
+		OBJ_CASE_INSENSITIVE,
+		KeyHandle,
+		NULL);
+
+	Status = NtOpenKey ((PHANDLE)phkResult, samDesired, &ObjectAttributes);
+	RtlFreeUnicodeString (&SubKeyString);
+	if (!NT_SUCCESS(Status))
+	{
+		ErrorCode = RtlNtStatusToDosError (Status);
+		SetLastError (ErrorCode);
+		return ErrorCode;
+	}
+
+	return ERROR_SUCCESS;
 }
 
 
@@ -1984,49 +1743,44 @@
 	       REGSAM samDesired,
 	       PHKEY phkResult)
 {
-  OBJECT_ATTRIBUTES ObjectAttributes;
-  UNICODE_STRING SubKeyString;
-  HANDLE KeyHandle;
-  LONG ErrorCode;
-  NTSTATUS Status;
+	OBJECT_ATTRIBUTES ObjectAttributes;
+	UNICODE_STRING SubKeyString;
+	HANDLE KeyHandle;
+	LONG ErrorCode;
+	NTSTATUS Status;
 
-  DPRINT("RegOpenKeyExW hKey 0x%x lpSubKey %S ulOptions 0x%x samDesired 0x%x phkResult %p\n",
-         hKey, lpSubKey, ulOptions, samDesired, phkResult);
-  Status = MapDefaultKey (&KeyHandle,
-			  hKey);
-  if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
-    }
+	DPRINT("RegOpenKeyExW hKey 0x%x lpSubKey %S ulOptions 0x%x samDesired 0x%x phkResult %p\n",
+		hKey, lpSubKey, ulOptions, samDesired, phkResult);
+	
+	Status = MapDefaultKey (&KeyHandle, hKey);
+	if (!NT_SUCCESS(Status))
+	{
+		ErrorCode = RtlNtStatusToDosError (Status);
+		SetLastError (ErrorCode);
+		return ErrorCode;
+	}
 
-  if (lpSubKey != NULL)
-    {
-      RtlInitUnicodeString (&SubKeyString,
-			    (LPWSTR)lpSubKey);
-    }
-  else
-    {
-      RtlInitUnicodeString (&SubKeyString,
-			    (LPWSTR)L"");
-    }
-  InitializeObjectAttributes (&ObjectAttributes,
-			      &SubKeyString,
-			      OBJ_CASE_INSENSITIVE,
-			      KeyHandle,
-			      NULL);
-  Status = NtOpenKey ((PHANDLE)phkResult,
-		      samDesired,
-		      &ObjectAttributes);
-  if (!NT_SUCCESS(Status))
-    {
-      ErrorCode = RtlNtStatusToDosError (Status);
-      SetLastError (ErrorCode);
-      return ErrorCode;
-    }
+	if (lpSubKey != NULL)
+		RtlInitUnicodeString (&SubKeyString, (LPWSTR)lpSubKey);
+	else
+		RtlInitUnicodeString (&SubKeyString, (LPWSTR)L"");
 
-  return ERROR_SUCCESS;
+	InitializeObjectAttributes (&ObjectAttributes,
+		&SubKeyString,
+		OBJ_CASE_INSENSITIVE,
+		KeyHandle,
+		NULL);
+
+	Status = NtOpenKey ((PHANDLE)phkResult,	samDesired,	&ObjectAttributes);
+
+	if (!NT_SUCCESS(Status))
+	{
+		ErrorCode = RtlNtStatusToDosError (Status);
+		SetLastError (ErrorCode);
+		return ErrorCode;
+	}
+
+	return ERROR_SUCCESS;
 }