reg.c
来自「一个类似windows」· C语言 代码 · 共 2,371 行 · 第 1/5 页
C
2,371 行
}
return ERROR_SUCCESS;
}
/************************************************************************
* RegEnumKeyA
*
* @implemented
*/
LONG STDCALL
RegEnumKeyA (HKEY hKey,
DWORD dwIndex,
LPSTR lpName,
DWORD cbName)
{
DWORD dwLength;
dwLength = cbName;
return RegEnumKeyExA (hKey,
dwIndex,
lpName,
&dwLength,
NULL,
NULL,
NULL,
NULL);
}
/************************************************************************
* RegEnumKeyW
*
* @implemented
*/
LONG STDCALL
RegEnumKeyW (HKEY hKey,
DWORD dwIndex,
LPWSTR lpName,
DWORD cbName)
{
DWORD dwLength;
dwLength = cbName;
return RegEnumKeyExW (hKey,
dwIndex,
lpName,
&dwLength,
NULL,
NULL,
NULL,
NULL);
}
/************************************************************************
* RegEnumKeyExA
*
* @implemented
*/
LONG STDCALL
RegEnumKeyExA (HKEY hKey,
DWORD dwIndex,
LPSTR lpName,
LPDWORD lpcbName,
LPDWORD lpReserved,
LPSTR lpClass,
LPDWORD lpcbClass,
PFILETIME lpftLastWriteTime)
{
union
{
KEY_NODE_INFORMATION Node;
KEY_BASIC_INFORMATION Basic;
} *KeyInfo;
UNICODE_STRING StringU;
ANSI_STRING StringA;
LONG ErrorCode = ERROR_SUCCESS;
DWORD NameLength;
DWORD ClassLength = 0;
DWORD BufferSize;
DWORD ResultSize;
HANDLE KeyHandle;
NTSTATUS Status;
TRACE("RegEnumKeyExA(hKey 0x%x, dwIndex %d, lpName 0x%x, *lpcbName %d, lpClass 0x%x, lpcbClass %d)\n",
hKey, dwIndex, lpName, *lpcbName, lpClass, lpcbClass ? *lpcbClass : 0);
if ((lpClass) && (!lpcbClass))
{
return ERROR_INVALID_PARAMETER;
}
Status = MapDefaultKey(&KeyHandle, hKey);
if (!NT_SUCCESS(Status))
{
return RtlNtStatusToDosError (Status);
}
if (*lpcbName > 0)
{
NameLength = min (*lpcbName - 1 , REG_MAX_NAME_SIZE) * sizeof (WCHAR);
}
else
{
NameLength = 0;
}
if (lpClass)
{
if (*lpcbClass > 0)
{
ClassLength = min (*lpcbClass -1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
}
else
{
ClassLength = 0;
}
/* The class name should start at a dword boundary */
BufferSize = ((sizeof(KEY_NODE_INFORMATION) + NameLength + 3) & ~3) + ClassLength;
}
else
{
BufferSize = sizeof(KEY_BASIC_INFORMATION) + NameLength;
}
KeyInfo = RtlAllocateHeap (ProcessHeap, 0, BufferSize);
if (KeyInfo == NULL)
{
ErrorCode = ERROR_OUTOFMEMORY;
goto Cleanup;
}
Status = NtEnumerateKey (KeyHandle,
(ULONG)dwIndex,
lpClass == NULL ? KeyBasicInformation : KeyNodeInformation,
KeyInfo,
BufferSize,
&ResultSize);
TRACE("NtEnumerateKey() returned status 0x%X\n", Status);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError (Status);
}
else
{
if (lpClass == NULL)
{
if (KeyInfo->Basic.NameLength > NameLength)
{
ErrorCode = ERROR_BUFFER_OVERFLOW;
}
else
{
StringU.Buffer = KeyInfo->Basic.Name;
StringU.Length = KeyInfo->Basic.NameLength;
StringU.MaximumLength = KeyInfo->Basic.NameLength;
}
}
else
{
if (KeyInfo->Node.NameLength > NameLength ||
KeyInfo->Node.ClassLength > ClassLength)
{
ErrorCode = ERROR_BUFFER_OVERFLOW;
}
else
{
StringA.Buffer = lpClass;
StringA.Length = 0;
StringA.MaximumLength = *lpcbClass;
StringU.Buffer = (PWCHAR)((ULONG_PTR)KeyInfo->Node.Name + KeyInfo->Node.ClassOffset);
StringU.Length = KeyInfo->Node.ClassLength;
StringU.MaximumLength = KeyInfo->Node.ClassLength;
RtlUnicodeStringToAnsiString (&StringA, &StringU, FALSE);
lpClass[StringA.Length] = 0;
*lpcbClass = StringA.Length;
StringU.Buffer = KeyInfo->Node.Name;
StringU.Length = KeyInfo->Node.NameLength;
StringU.MaximumLength = KeyInfo->Node.NameLength;
}
}
if (ErrorCode == ERROR_SUCCESS)
{
StringA.Buffer = lpName;
StringA.Length = 0;
StringA.MaximumLength = *lpcbName;
RtlUnicodeStringToAnsiString (&StringA, &StringU, FALSE);
lpName[StringA.Length] = 0;
*lpcbName = StringA.Length;
if (lpftLastWriteTime != NULL)
{
if (lpClass == NULL)
{
lpftLastWriteTime->dwLowDateTime = KeyInfo->Basic.LastWriteTime.u.LowPart;
lpftLastWriteTime->dwHighDateTime = KeyInfo->Basic.LastWriteTime.u.HighPart;
}
else
{
lpftLastWriteTime->dwLowDateTime = KeyInfo->Node.LastWriteTime.u.LowPart;
lpftLastWriteTime->dwHighDateTime = KeyInfo->Node.LastWriteTime.u.HighPart;
}
}
}
}
TRACE("Key Namea0 Length %d\n", StringU.Length);
TRACE("Key Namea1 Length %d\n", NameLength);
TRACE("Key Namea Length %d\n", *lpcbName);
TRACE("Key Namea %s\n", lpName);
RtlFreeHeap (ProcessHeap,
0,
KeyInfo);
Cleanup:
ClosePredefKey(KeyHandle);
return ErrorCode;
}
/************************************************************************
* RegEnumKeyExW
*
* @implemented
*/
LONG STDCALL
RegEnumKeyExW (HKEY hKey,
DWORD dwIndex,
LPWSTR lpName,
LPDWORD lpcbName,
LPDWORD lpReserved,
LPWSTR lpClass,
LPDWORD lpcbClass,
PFILETIME lpftLastWriteTime)
{
union
{
KEY_NODE_INFORMATION Node;
KEY_BASIC_INFORMATION Basic;
} *KeyInfo;
ULONG BufferSize;
ULONG ResultSize;
ULONG NameLength;
ULONG ClassLength = 0;
HANDLE KeyHandle;
LONG ErrorCode = ERROR_SUCCESS;
NTSTATUS Status;
Status = MapDefaultKey(&KeyHandle,
hKey);
if (!NT_SUCCESS(Status))
{
return RtlNtStatusToDosError (Status);
}
if (*lpcbName > 0)
{
NameLength = min (*lpcbName - 1, REG_MAX_NAME_SIZE) * sizeof (WCHAR);
}
else
{
NameLength = 0;
}
if (lpClass)
{
if (*lpcbClass > 0)
{
ClassLength = min (*lpcbClass - 1, REG_MAX_NAME_SIZE) * sizeof(WCHAR);
}
else
{
ClassLength = 0;
}
BufferSize = ((sizeof(KEY_NODE_INFORMATION) + NameLength + 3) & ~3) + ClassLength;
}
else
{
BufferSize = sizeof(KEY_BASIC_INFORMATION) + NameLength;
}
KeyInfo = RtlAllocateHeap (ProcessHeap,
0,
BufferSize);
if (KeyInfo == NULL)
{
ErrorCode = ERROR_OUTOFMEMORY;
goto Cleanup;
}
Status = NtEnumerateKey (KeyHandle,
(ULONG)dwIndex,
lpClass ? KeyNodeInformation : KeyBasicInformation,
KeyInfo,
BufferSize,
&ResultSize);
TRACE("NtEnumerateKey() returned status 0x%X\n", Status);
if (!NT_SUCCESS(Status))
{
ErrorCode = RtlNtStatusToDosError (Status);
}
else
{
if (lpClass == NULL)
{
if (KeyInfo->Basic.NameLength > NameLength)
{
ErrorCode = ERROR_BUFFER_OVERFLOW;
}
else
{
RtlCopyMemory (lpName,
KeyInfo->Basic.Name,
KeyInfo->Basic.NameLength);
*lpcbName = (DWORD)(KeyInfo->Basic.NameLength / sizeof(WCHAR));
lpName[*lpcbName] = 0;
}
}
else
{
if (KeyInfo->Node.NameLength > NameLength ||
KeyInfo->Node.ClassLength > ClassLength)
{
ErrorCode = ERROR_BUFFER_OVERFLOW;
}
else
{
RtlCopyMemory (lpName,
KeyInfo->Node.Name,
KeyInfo->Node.NameLength);
*lpcbName = KeyInfo->Node.NameLength / sizeof(WCHAR);
lpName[*lpcbName] = 0;
RtlCopyMemory (lpClass,
(PVOID)((ULONG_PTR)KeyInfo->Node.Name + KeyInfo->Node.ClassOffset),
KeyInfo->Node.ClassLength);
*lpcbClass = (DWORD)(KeyInfo->Node.ClassLength / sizeof(WCHAR));
lpClass[*lpcbClass] = 0;
}
}
if (ErrorCode == ERROR_SUCCESS && lpftLastWriteTime != NULL)
{
if (lpClass == NULL)
{
lpftLastWriteTime->dwLowDateTime = KeyInfo->Basic.LastWriteTime.u.LowPart;
lpftLastWriteTime->dwHighDateTime = KeyInfo->Basic.LastWriteTime.u.HighPart;
}
else
{
lpftLastWriteTime->dwLowDateTime = KeyInfo->Node.LastWriteTime.u.LowPart;
lpftLastWriteTime->dwHighDateTime = KeyInfo->Node.LastWriteTime.u.HighPart;
}
}
}
RtlFreeHeap (ProcessHeap,
0,
KeyInfo);
Cleanup:
ClosePredefKey(KeyHandle);
return ErrorCode;
}
/************************************************************************
* RegEnumValueA
*
* @implemented
*/
LONG STDCALL
RegEnumValueA( HKEY hKey, DWORD index, LPSTR value, LPDWORD val_count,
LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
{
HANDLE KeyHandle;
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 = 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 );
/* NT only checks count, not val_count */
if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
status = MapDefaultKey (&KeyHandle, hKey);
if (!NT_SUCCESS(status))
{
return RtlNtStatusToDosError (status);
}
total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
if (data) total_size += *count;
total_size = min( sizeof(buffer), total_size );
status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
buffer, total_size, &total_size );
if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
/* 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 )))
{
status = STATUS_INSUFFICIENT_RESOURCES;
goto done;
}
info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
status = NtEnumerateValueKey( KeyHandle, index, KeyValueFullInformation,
buf_ptr, total_size, &total_size );
}
if (status) goto done;
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( (PCHAR)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 );
}
if (value && !status)
{
DWORD len;
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
{
RtlUnicodeToMultiByt
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?