* FILE: lib/advapi32/reg/reg.c
* PURPOSE: Registry functions
* PROGRAMMER: Ariadne ( ariadne@xs4all.nl)
+ * Thomas Weidenmueller <w3seek@reactos.com>
* UPDATE HISTORY:
* Created 01/11/98
* 19990309 EA Stubs
#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;
static NTSTATUS MapDefaultKey (PHANDLE ParentKey, HKEY Key);
static VOID CloseDefaultKeys(VOID);
-#define CloseDefaultKey(Handle) \
+#define ClosePredefKey(Handle) \
if ((ULONG_PTR)Handle & 0x1) { \
NtClose(Handle); \
}
+#define IsPredefKey(HKey) \
+ (((ULONG)(HKey) & 0xF0000000) == 0x80000000)
+#define GetPredefKeyIndex(HKey) \
+ ((ULONG)(HKey) & 0x0FFFFFFF)
static NTSTATUS OpenClassesRootKey(PHANDLE KeyHandle);
static NTSTATUS OpenLocalMachineKey (PHANDLE KeyHandle);
/* FUNCTIONS ****************************************************************/
/* check if value type needs string conversion (Ansi<->Unicode) */
-inline static int is_string( DWORD type )
+__inline static int is_string( DWORD type )
{
return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ);
}
}
+static NTSTATUS
+OpenPredefinedKey(IN ULONG Index,
+ OUT HANDLE Handle)
+{
+ NTSTATUS Status;
+
+ switch (Index)
+ {
+ case 0: /* HKEY_CLASSES_ROOT */
+ Status = OpenClassesRootKey (Handle);
+ break;
+
+ case 1: /* HKEY_CURRENT_USER */
+ Status = RtlOpenCurrentUser (MAXIMUM_ALLOWED,
+ Handle);
+ break;
+
+ case 2: /* HKEY_LOCAL_MACHINE */
+ Status = OpenLocalMachineKey (Handle);
+ break;
+
+ case 3: /* HKEY_USERS */
+ Status = OpenUsersKey (Handle);
+ break;
+#if 0
+ case 4: /* HKEY_PERFORMANCE_DATA */
+ Status = OpenPerformanceDataKey (Handle);
+ break;
+#endif
+
+ case 5: /* HKEY_CURRENT_CONFIG */
+ Status = OpenCurrentConfigKey (Handle);
+ break;
+
+ case 6: /* HKEY_DYN_DATA */
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ default:
+ WARN("MapDefaultHandle() no handle creator\n");
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ return Status;
+}
+
+
static NTSTATUS
MapDefaultKey (OUT PHANDLE RealKey,
IN HKEY Key)
TRACE("MapDefaultKey (Key %x)\n", Key);
- if (((ULONG)Key & 0xF0000000) != 0x80000000)
+ if (!IsPredefKey(Key))
{
*RealKey = (HANDLE)((ULONG_PTR)Key & ~0x1);
return STATUS_SUCCESS;
}
/* Handle special cases here */
- Index = (ULONG)Key & 0x0FFFFFFF;
+ Index = GetPredefKeyIndex(Key);
if (Index >= MAX_DEFAULT_HANDLES)
{
return STATUS_INVALID_PARAMETER;
if (DoOpen)
{
/* create/open the default handle */
- switch (Index)
- {
- case 0: /* HKEY_CLASSES_ROOT */
- Status = OpenClassesRootKey (Handle);
- break;
-
- case 1: /* HKEY_CURRENT_USER */
- Status = RtlOpenCurrentUser (MAXIMUM_ALLOWED,
- Handle);
- break;
-
- case 2: /* HKEY_LOCAL_MACHINE */
- Status = OpenLocalMachineKey (Handle);
- break;
-
- case 3: /* HKEY_USERS */
- Status = OpenUsersKey (Handle);
- break;
-#if 0
- case 4: /* HKEY_PERFORMANCE_DATA */
- Status = OpenPerformanceDataKey (Handle);
- break;
-#endif
- case 5: /* HKEY_CURRENT_CONFIG */
- Status = OpenCurrentConfigKey (Handle);
- break;
-
- case 6: /* HKEY_DYN_DATA */
- Status = STATUS_NOT_IMPLEMENTED;
- break;
-
- default:
- WARN("MapDefaultHandle() no handle creator\n");
- Status = STATUS_INVALID_PARAMETER;
- break;
- }
+ Status = OpenPredefinedKey(Index,
+ Handle);
}
if (NT_SUCCESS(Status))
}
+/************************************************************************
+ * RegOverridePredefKey
+ *
+ * @implemented
+ */
+LONG STDCALL
+RegOverridePredefKey(IN HKEY hKey,
+ IN HKEY hNewHKey OPTIONAL)
+{
+ LONG ErrorCode = ERROR_SUCCESS;
+
+ if ((hKey == HKEY_CLASSES_ROOT ||
+ hKey == HKEY_CURRENT_CONFIG ||
+ hKey == HKEY_CURRENT_USER ||
+ hKey == HKEY_LOCAL_MACHINE ||
+ hKey == HKEY_PERFORMANCE_DATA ||
+ hKey == HKEY_USERS) &&
+ !IsPredefKey(hNewHKey))
+ {
+ PHANDLE Handle;
+ ULONG Index;
+
+ Index = GetPredefKeyIndex(hKey);
+ Handle = &DefaultHandleTable[Index];
+
+ if (hNewHKey == NULL)
+ {
+ /* restore the default mapping */
+ NTSTATUS Status = OpenPredefinedKey(Index,
+ &hNewHKey);
+ if (!NT_SUCCESS(Status))
+ {
+ return RtlNtStatusToDosError(Status);
+ }
+
+ ASSERT(hNewHKey != NULL);
+ }
+
+ RtlEnterCriticalSection (&HandleTableCS);
+
+ /* close the currently mapped handle if existing */
+ if (*Handle != NULL)
+ {
+ NtClose(*Handle);
+ }
+
+ /* update the mapping */
+ *Handle = hNewHKey;
+
+ RtlLeaveCriticalSection (&HandleTableCS);
+ }
+ else
+ ErrorCode = ERROR_INVALID_HANDLE;
+
+ return ErrorCode;
+}
+
+
/************************************************************************
* RegCloseKey
*
NtClose(NewKeyHandle);
Status2 = STATUS_INSUFFICIENT_RESOURCES;
- goto GoNextKey;
}
}
else
}
}
-GoNextKey:
if (!NT_SUCCESS(Status2) && NT_SUCCESS(Status))
{
Status = Status2;
}
Cleanup:
- CloseDefaultKey(DestKeyHandle);
+ ClosePredefKey(DestKeyHandle);
Cleanup2:
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
if (!NT_SUCCESS(Status))
{
RtlFreeUnicodeString (&ClassString);
}
- CloseDefaultKey(ParentKey);
+ ClosePredefKey(ParentKey);
TRACE("Status %x\n", Status);
if (!NT_SUCCESS(Status))
samDesired,
lpdwDisposition);
- CloseDefaultKey(ParentKey);
+ ClosePredefKey(ParentKey);
TRACE("Status %x\n", Status);
if (!NT_SUCCESS(Status))
NtClose (TargetKey);
Cleanup:
- CloseDefaultKey(ParentKey);
+ ClosePredefKey(ParentKey);
if (!NT_SUCCESS(Status))
{
NtClose (TargetKey);
Cleanup:
- CloseDefaultKey(ParentKey);
+ ClosePredefKey(ParentKey);
if (!NT_SUCCESS(Status))
{
}
Cleanup:
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
if (!NT_SUCCESS(Status))
{
/* open the subkey */
Status2 = NtOpenKey(&newDelKeys->KeyHandle,
- DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
+ DELETE | KEY_ENUMERATE_SUB_KEYS,
&ObjectAttributes);
if (!NT_SUCCESS(Status2))
{
Status2 = STATUS_INSUFFICIENT_RESOURCES;
}
}
+ else if (Status2 == STATUS_NO_MORE_ENTRIES)
+ {
+ /* in some race conditions where another thread would delete
+ the same tree at the same time, newDelKeys could actually
+ be != NULL! */
+ if (newDelKeys != NULL)
+ {
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ newDelKeys);
+ }
+ break;
+ }
SubKeyFailure:
- ASSERT(newDelKeys != NULL);
- RtlFreeHeap(ProcessHeap,
- 0,
- newDelKeys);
+ /* newDelKeys can be NULL here when NtEnumerateKey returned an
+ error other than STATUS_BUFFER_TOO_SMALL or STATUS_BUFFER_OVERFLOW! */
+ if (newDelKeys != NULL)
+ {
+ RtlFreeHeap(ProcessHeap,
+ 0,
+ newDelKeys);
+ }
SubKeyFailureNoFree:
/* don't break, let's try to delete as many keys as possible */
- if (Status2 != STATUS_NO_MORE_ENTRIES && NT_SUCCESS(Status))
+ if (NT_SUCCESS(Status))
{
Status = Status2;
}
}
else
Status = STATUS_INSUFFICIENT_RESOURCES;
-
+
return Status;
}
NULL);
Status = NtOpenKey(&SubKeyHandle,
- DELETE | KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
+ DELETE | KEY_ENUMERATE_SUB_KEYS,
&ObjectAttributes);
if (!NT_SUCCESS(Status))
{
subkey, because the handle would be invalid already! */
if (CurKey != KeyHandle)
{
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
}
return ERROR_SUCCESS;
}
Cleanup:
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
return RtlNtStatusToDosError(Status);
}
}
Cleanup:
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
return Ret;
}
}
Cleanup:
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
return Ret;
}
&ValueName);
RtlFreeUnicodeString (&ValueName);
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
if (!NT_SUCCESS(Status))
{
Status = NtDeleteValueKey (KeyHandle,
&ValueName);
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
if (!NT_SUCCESS(Status))
{
KeyInfo);
Cleanup:
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
return ErrorCode;
}
KeyInfo);
Cleanup:
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
return ErrorCode;
}
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 );
+ static const int info_size = FIELD_OFFSET( KEY_VALUE_FULL_INFORMATION, Name );
//TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
// hkey, index, value, val_count, reserved, type, data, count );
done:
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
return RtlNtStatusToDosError(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 );
+ static const int info_size = FIELD_OFFSET( KEY_VALUE_FULL_INFORMATION, Name );
//TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
// hkey, index, value, val_count, reserved, type, data, count );
done:
if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
return RtlNtStatusToDosError(status);
}
Status = NtFlushKey (KeyHandle);
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
if (!NT_SUCCESS(Status))
{
TRACE("MapDefaultKey() failed (Status %lx)\n", Status);
return RtlNtStatusToDosError (Status);
}
-
+#ifndef __REACTOS__
Status = NtQuerySecurityObject(KeyHandle,
SecurityInformation,
pSecurityDescriptor,
*lpcbSecurityDescriptor,
lpcbSecurityDescriptor);
+#endif
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
if (!NT_SUCCESS(Status))
{
return RtlNtStatusToDosError (Status);
}
- if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFile,
+ if (!RtlDosPathNameToNtPathName_U (lpFile,
&FileName,
NULL,
NULL))
}
Cleanup:
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
return ErrorCode;
}
ErrorCode = RtlNtStatusToDosError (Status);
}
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
return ErrorCode;
}
ErrorCode = RtlNtStatusToDosError (Status);
}
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
return ErrorCode;
}
ErrorCode = RtlNtStatusToDosError (Status);
}
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
return ErrorCode;
}
{
*lpcbMaxValueLen = FullInfo->MaxValueDataLen;
}
-
+#ifndef __REACTOS__
if (lpcbSecurityDescriptor != NULL)
{
Status = NtQuerySecurityObject(KeyHandle,
goto Cleanup;
}
}
+#endif
if (lpftLastWriteTime != NULL)
{
}
Cleanup:
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
return ErrorCode;
}
ValueInfo);
Cleanup:
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
return ErrorCode;
}
}
Cleanup:
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
return ErrorCode;
}
}
/* Convert new file name */
- if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpNewFile,
+ if (!RtlDosPathNameToNtPathName_U (lpNewFile,
&NewFileName,
NULL,
NULL))
NULL);
/* Convert old file name */
- if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpOldFile,
+ if (!RtlDosPathNameToNtPathName_U (lpOldFile,
&OldFileName,
NULL,
NULL))
}
Cleanup:
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
return ErrorCode;
}
return RtlNtStatusToDosError (Status);
}
- if (!RtlDosPathNameToNtPathName_U ((LPWSTR)lpFile,
+ if (!RtlDosPathNameToNtPathName_U (lpFile,
&FileName,
NULL,
NULL))
NtClose (FileHandle);
Cleanup:
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
if (!NT_SUCCESS(Status))
{
return RtlNtStatusToDosError (Status);
}
- if (!RtlDosPathNameToNtPathName_U ((PWSTR)lpFile,
+ if (!RtlDosPathNameToNtPathName_U (lpFile,
&FileName,
NULL,
NULL))
NtClose (FileHandle);
Cleanup:
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
if (!NT_SUCCESS(Status))
{
SecurityInformation,
pSecurityDescriptor);
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
if (!NT_SUCCESS(Status))
{
(PVOID)lpData,
(ULONG)cbData);
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
if (!NT_SUCCESS(Status))
{
}
Cleanup:
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
return ErrorCode;
}
Status = NtUnloadKey (&ObjectAttributes);
- CloseDefaultKey(KeyHandle);
+ ClosePredefKey(KeyHandle);
if (!NT_SUCCESS(Status))
{