/*++ 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 #include #include #include #include "psxdll.h" // // First guess for value size. // #define KEY_WORK_AREA 256 int _CRTAPI1 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 = strlen(Value_A.Buffer); Value_A.MaximumLength = Value_A.Length + 1; Key_A.Buffer = path; Key_A.Length = 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; }