windows-nt/Source/XPSP1/NT/base/subsys/posix/client/dllreg.c

174 lines
3.6 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
dllreg.c
Abstract:
This module implements POSIX registry APIs
Author:
Matthew Bradburn (mattbr) 13-Dec-1995
Revision History:
--*/
#include <sys\utsname.h>
#include <unistd.h>
#include <string.h>
#include <stdarg.h>
#include "psxdll.h"
//
// First guess for value size.
//
#define KEY_WORK_AREA 256
int
__cdecl
getreg(char *path, int *type, void *data, size_t *size)
{
NTSTATUS Status;
UNICODE_STRING Key_U, Value_U;
ANSI_STRING Key_A, Value_A;
OBJECT_ATTRIBUTES ObjA;
HANDLE hKey = NULL;
CHAR *pch;
PKEY_VALUE_PARTIAL_INFORMATION pInfo = NULL;
UCHAR Buffer[KEY_WORK_AREA];
ULONG RequestLength, ResultLength;
int r = 0;
Key_U.Buffer = NULL;
Value_U.Buffer = NULL;
if (strlen(path) > PATH_MAX) {
errno = ENAMETOOLONG;
return -1;
}
//
// Split the path into key and value.
//
pch = strrchr(path, '\\');
if (NULL == pch) {
errno = ENOENT;
return -1;
}
Value_A.Buffer = pch + 1;
Value_A.Length = (USHORT)strlen(Value_A.Buffer);
Value_A.MaximumLength = Value_A.Length + 1;
Key_A.Buffer = path;
Key_A.Length = (USHORT)(pch - path);
Key_A.MaximumLength = Key_A.Length + 1;
Status = RtlAnsiStringToUnicodeString(&Key_U, &Key_A, TRUE);
if (!NT_SUCCESS(Status)) {
errno = PdxStatusToErrno(Status);
r = -1;
goto out;
}
Status = RtlAnsiStringToUnicodeString(&Value_U, &Value_A, TRUE);
if (!NT_SUCCESS(Status)) {
errno = PdxStatusToErrno(Status);
r = -1;
goto out;
}
InitializeObjectAttributes(&ObjA, &Key_U, OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = NtOpenKey(&hKey, KEY_READ, &ObjA);
if (!NT_SUCCESS(Status)) {
KdPrint(("PSXDLL: NtOpenKey: 0x%x\n", Status));
errno = PdxStatusToErrno(Status);
r = -1;
goto out;
}
RequestLength = KEY_WORK_AREA;
pInfo = (PKEY_VALUE_PARTIAL_INFORMATION)Buffer;
for (;;) {
Status = NtQueryValueKey(hKey, &Value_U, KeyValuePartialInformation,
(PVOID)pInfo, RequestLength, &ResultLength);
if (Status == STATUS_BUFFER_OVERFLOW) {
//
// Try to get a bigger buffer.
//
if (pInfo != (PKEY_VALUE_PARTIAL_INFORMATION)Buffer) {
RtlFreeHeap(PdxHeap, 0, pInfo);
}
RequestLength += 512;
pInfo = (PKEY_VALUE_PARTIAL_INFORMATION)
RtlAllocateHeap(PdxHeap, 0, RequestLength);
if (NULL == pInfo) {
errno = ENOMEM;
r = -1;
goto out;
}
} else {
break;
}
}
if (!NT_SUCCESS(Status)) {
r = -1;
errno = PdxStatusToErrno(Status);
} else {
if (pInfo->DataLength > *size) {
*size = pInfo->DataLength;
*type = 0;
errno = E2BIG;
r = -1;
} else {
*size = pInfo->DataLength;
*type = pInfo->Type;
memcpy(data, pInfo->Data, pInfo->DataLength);
}
}
out:
if (pInfo != NULL && pInfo != (PKEY_VALUE_PARTIAL_INFORMATION)Buffer) {
RtlFreeHeap(PdxHeap, 0, pInfo);
}
if (Key_U.Buffer != NULL) {
RtlFreeUnicodeString(&Key_U);
}
if (Value_U.Buffer != NULL) {
RtlFreeUnicodeString(&Value_U);
}
if (hKey != NULL) {
NtClose(hKey);
}
if (pInfo != NULL) {
RtlFreeHeap(PdxHeap, 0, (PVOID)pInfo);
}
return r;
}