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 + -
显示快捷键?