20#include <winpr/config.h>
22#include <winpr/registry.h>
30#if !defined(_WIN32) || defined(_UWP)
37#include <winpr/assert.h>
38#include <winpr/string.h>
40#include "registry_reg.h"
43#define TAG WINPR_TAG("registry")
45static Reg* instance =
nullptr;
47static size_t regsz_length(
const char* key,
const void* value)
54 const size_t limit = 16383;
55 size_t length = strnlen((
const char*)value, limit);
57 WLog_WARN(TAG,
"REG_SZ[%s] truncated to size %" PRIuz, key, length);
61static Reg* RegGetInstance(
void)
64 instance = reg_open(1);
69LONG RegCloseKey(HKEY hKey)
75LONG RegCopyTreeW(WINPR_ATTR_UNUSED HKEY hKeySrc, WINPR_ATTR_UNUSED LPCWSTR lpSubKey,
76 WINPR_ATTR_UNUSED HKEY hKeyDest)
78 WLog_ERR(TAG,
"TODO: Implement");
82LONG RegCopyTreeA(WINPR_ATTR_UNUSED HKEY hKeySrc, WINPR_ATTR_UNUSED LPCSTR lpSubKey,
83 WINPR_ATTR_UNUSED HKEY hKeyDest)
85 WLog_ERR(TAG,
"TODO: Implement");
89LONG RegCreateKeyExW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpSubKey,
90 WINPR_ATTR_UNUSED DWORD Reserved, WINPR_ATTR_UNUSED LPWSTR lpClass,
91 WINPR_ATTR_UNUSED DWORD dwOptions, WINPR_ATTR_UNUSED REGSAM samDesired,
92 WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpSecurityAttributes,
93 WINPR_ATTR_UNUSED PHKEY phkResult, WINPR_ATTR_UNUSED LPDWORD lpdwDisposition)
95 WLog_ERR(TAG,
"TODO: Implement");
99LONG RegCreateKeyExA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpSubKey,
100 WINPR_ATTR_UNUSED DWORD Reserved, WINPR_ATTR_UNUSED LPSTR lpClass,
101 WINPR_ATTR_UNUSED DWORD dwOptions, WINPR_ATTR_UNUSED REGSAM samDesired,
102 WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpSecurityAttributes,
103 WINPR_ATTR_UNUSED PHKEY phkResult, WINPR_ATTR_UNUSED LPDWORD lpdwDisposition)
105 WLog_ERR(TAG,
"TODO: Implement");
109LONG RegDeleteKeyExW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpSubKey,
110 WINPR_ATTR_UNUSED REGSAM samDesired, WINPR_ATTR_UNUSED DWORD Reserved)
112 WLog_ERR(TAG,
"TODO: Implement");
116LONG RegDeleteKeyExA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpSubKey,
117 WINPR_ATTR_UNUSED REGSAM samDesired, WINPR_ATTR_UNUSED DWORD Reserved)
119 WLog_ERR(TAG,
"TODO: Implement");
123LONG RegDeleteTreeW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpSubKey)
125 WLog_ERR(TAG,
"TODO: Implement");
129LONG RegDeleteTreeA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpSubKey)
131 WLog_ERR(TAG,
"TODO: Implement");
135LONG RegDeleteValueW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpValueName)
137 WLog_ERR(TAG,
"TODO: Implement");
141LONG RegDeleteValueA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpValueName)
143 WLog_ERR(TAG,
"TODO: Implement");
147LONG RegDisablePredefinedCacheEx(
void)
149 WLog_ERR(TAG,
"TODO: Implement");
153LONG RegEnumKeyExW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED DWORD dwIndex,
154 WINPR_ATTR_UNUSED LPWSTR lpName, WINPR_ATTR_UNUSED LPDWORD lpcName,
155 WINPR_ATTR_UNUSED LPDWORD lpReserved, WINPR_ATTR_UNUSED LPWSTR lpClass,
156 WINPR_ATTR_UNUSED LPDWORD lpcClass,
157 WINPR_ATTR_UNUSED PFILETIME lpftLastWriteTime)
159 WLog_ERR(TAG,
"TODO: Implement");
163LONG RegEnumKeyExA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED DWORD dwIndex,
164 WINPR_ATTR_UNUSED LPSTR lpName, WINPR_ATTR_UNUSED LPDWORD lpcName,
165 WINPR_ATTR_UNUSED LPDWORD lpReserved, WINPR_ATTR_UNUSED LPSTR lpClass,
166 WINPR_ATTR_UNUSED LPDWORD lpcClass,
167 WINPR_ATTR_UNUSED PFILETIME lpftLastWriteTime)
169 WLog_ERR(TAG,
"TODO: Implement");
173LONG RegEnumValueW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED DWORD dwIndex,
174 WINPR_ATTR_UNUSED LPWSTR lpValueName, WINPR_ATTR_UNUSED LPDWORD lpcchValueName,
175 WINPR_ATTR_UNUSED LPDWORD lpReserved, WINPR_ATTR_UNUSED LPDWORD lpType,
176 WINPR_ATTR_UNUSED LPBYTE lpData, WINPR_ATTR_UNUSED LPDWORD lpcbData)
178 WLog_ERR(TAG,
"TODO: Implement");
182LONG RegEnumValueA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED DWORD dwIndex,
183 WINPR_ATTR_UNUSED LPSTR lpValueName, WINPR_ATTR_UNUSED LPDWORD lpcchValueName,
184 WINPR_ATTR_UNUSED LPDWORD lpReserved, WINPR_ATTR_UNUSED LPDWORD lpType,
185 WINPR_ATTR_UNUSED LPBYTE lpData, WINPR_ATTR_UNUSED LPDWORD lpcbData)
187 WLog_ERR(TAG,
"TODO: Implement");
191LONG RegFlushKey(WINPR_ATTR_UNUSED HKEY hKey)
193 WLog_ERR(TAG,
"TODO: Implement");
197LONG RegGetKeySecurity(WINPR_ATTR_UNUSED HKEY hKey,
198 WINPR_ATTR_UNUSED SECURITY_INFORMATION SecurityInformation,
199 WINPR_ATTR_UNUSED PSECURITY_DESCRIPTOR pSecurityDescriptor,
200 WINPR_ATTR_UNUSED LPDWORD lpcbSecurityDescriptor)
202 WLog_ERR(TAG,
"TODO: Implement");
206LONG RegGetValueW(WINPR_ATTR_UNUSED HKEY hkey, WINPR_ATTR_UNUSED LPCWSTR lpSubKey,
207 WINPR_ATTR_UNUSED LPCWSTR lpValue, WINPR_ATTR_UNUSED DWORD dwFlags,
208 WINPR_ATTR_UNUSED LPDWORD pdwType, WINPR_ATTR_UNUSED PVOID pvData,
209 WINPR_ATTR_UNUSED LPDWORD pcbData)
211 WLog_ERR(TAG,
"TODO: Implement");
215LONG RegGetValueA(WINPR_ATTR_UNUSED HKEY hkey, WINPR_ATTR_UNUSED LPCSTR lpSubKey,
216 WINPR_ATTR_UNUSED LPCSTR lpValue, WINPR_ATTR_UNUSED DWORD dwFlags,
217 WINPR_ATTR_UNUSED LPDWORD pdwType, WINPR_ATTR_UNUSED PVOID pvData,
218 WINPR_ATTR_UNUSED LPDWORD pcbData)
220 WLog_ERR(TAG,
"TODO: Implement");
224LONG RegLoadAppKeyW(WINPR_ATTR_UNUSED LPCWSTR lpFile, WINPR_ATTR_UNUSED PHKEY phkResult,
225 WINPR_ATTR_UNUSED REGSAM samDesired, WINPR_ATTR_UNUSED DWORD dwOptions,
226 WINPR_ATTR_UNUSED DWORD Reserved)
228 WLog_ERR(TAG,
"TODO: Implement");
232LONG RegLoadAppKeyA(WINPR_ATTR_UNUSED LPCSTR lpFile, WINPR_ATTR_UNUSED PHKEY phkResult,
233 WINPR_ATTR_UNUSED REGSAM samDesired, WINPR_ATTR_UNUSED DWORD dwOptions,
234 WINPR_ATTR_UNUSED DWORD Reserved)
236 WLog_ERR(TAG,
"TODO: Implement");
240LONG RegLoadKeyW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpSubKey,
241 WINPR_ATTR_UNUSED LPCWSTR lpFile)
243 WLog_ERR(TAG,
"TODO: Implement");
247LONG RegLoadKeyA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpSubKey,
248 WINPR_ATTR_UNUSED LPCSTR lpFile)
250 WLog_ERR(TAG,
"TODO: Implement");
254LONG RegLoadMUIStringW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR pszValue,
255 WINPR_ATTR_UNUSED LPWSTR pszOutBuf, WINPR_ATTR_UNUSED DWORD cbOutBuf,
256 WINPR_ATTR_UNUSED LPDWORD pcbData, WINPR_ATTR_UNUSED DWORD Flags,
257 WINPR_ATTR_UNUSED LPCWSTR pszDirectory)
259 WLog_ERR(TAG,
"TODO: Implement");
263LONG RegLoadMUIStringA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR pszValue,
264 WINPR_ATTR_UNUSED LPSTR pszOutBuf, WINPR_ATTR_UNUSED DWORD cbOutBuf,
265 WINPR_ATTR_UNUSED LPDWORD pcbData, WINPR_ATTR_UNUSED DWORD Flags,
266 WINPR_ATTR_UNUSED LPCSTR pszDirectory)
268 WLog_ERR(TAG,
"TODO: Implement");
272LONG RegNotifyChangeKeyValue(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED BOOL bWatchSubtree,
273 WINPR_ATTR_UNUSED DWORD dwNotifyFilter,
274 WINPR_ATTR_UNUSED HANDLE hEvent, WINPR_ATTR_UNUSED BOOL fAsynchronous)
276 WLog_ERR(TAG,
"TODO: Implement");
280LONG RegOpenCurrentUser(WINPR_ATTR_UNUSED REGSAM samDesired, WINPR_ATTR_UNUSED PHKEY phkResult)
282 WLog_ERR(TAG,
"TODO: Implement");
286LONG RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
289 char* str = ConvertWCharToUtf8Alloc(lpSubKey,
nullptr);
291 return ERROR_FILE_NOT_FOUND;
293 rc = RegOpenKeyExA(hKey, str, ulOptions, samDesired, phkResult);
298LONG RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, WINPR_ATTR_UNUSED DWORD ulOptions,
299 WINPR_ATTR_UNUSED REGSAM samDesired, PHKEY phkResult)
301 Reg* reg = RegGetInstance();
306 if (hKey != HKEY_LOCAL_MACHINE)
308 WLog_WARN(TAG,
"Registry emulation only supports HKEY_LOCAL_MACHINE");
309 return ERROR_FILE_NOT_FOUND;
312 WINPR_ASSERT(reg->root_key);
313 RegKey* pKey = reg->root_key->subkeys;
315 while (pKey !=
nullptr)
317 WINPR_ASSERT(lpSubKey);
319 if (pKey->subname && (_stricmp(pKey->subname, lpSubKey) == 0))
321 *phkResult = (HKEY)pKey;
322 return ERROR_SUCCESS;
328 *phkResult =
nullptr;
330 return ERROR_FILE_NOT_FOUND;
333LONG RegOpenUserClassesRoot(WINPR_ATTR_UNUSED HANDLE hToken, WINPR_ATTR_UNUSED DWORD dwOptions,
334 WINPR_ATTR_UNUSED REGSAM samDesired, WINPR_ATTR_UNUSED PHKEY phkResult)
336 WLog_ERR(TAG,
"TODO: Implement");
340LONG RegQueryInfoKeyW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPWSTR lpClass,
341 WINPR_ATTR_UNUSED LPDWORD lpcClass, WINPR_ATTR_UNUSED LPDWORD lpReserved,
342 WINPR_ATTR_UNUSED LPDWORD lpcSubKeys,
343 WINPR_ATTR_UNUSED LPDWORD lpcMaxSubKeyLen,
344 WINPR_ATTR_UNUSED LPDWORD lpcMaxClassLen, WINPR_ATTR_UNUSED LPDWORD lpcValues,
345 WINPR_ATTR_UNUSED LPDWORD lpcMaxValueNameLen,
346 WINPR_ATTR_UNUSED LPDWORD lpcMaxValueLen,
347 WINPR_ATTR_UNUSED LPDWORD lpcbSecurityDescriptor,
348 WINPR_ATTR_UNUSED PFILETIME lpftLastWriteTime)
350 WLog_ERR(TAG,
"TODO: Implement");
354LONG RegQueryInfoKeyA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPSTR lpClass,
355 WINPR_ATTR_UNUSED LPDWORD lpcClass, WINPR_ATTR_UNUSED LPDWORD lpReserved,
356 WINPR_ATTR_UNUSED LPDWORD lpcSubKeys,
357 WINPR_ATTR_UNUSED LPDWORD lpcMaxSubKeyLen,
358 WINPR_ATTR_UNUSED LPDWORD lpcMaxClassLen, WINPR_ATTR_UNUSED LPDWORD lpcValues,
359 WINPR_ATTR_UNUSED LPDWORD lpcMaxValueNameLen,
360 WINPR_ATTR_UNUSED LPDWORD lpcMaxValueLen,
361 WINPR_ATTR_UNUSED LPDWORD lpcbSecurityDescriptor,
362 WINPR_ATTR_UNUSED PFILETIME lpftLastWriteTime)
364 WLog_ERR(TAG,
"TODO: Implement");
368static LONG reg_read_int(
const RegVal* pValue, LPBYTE lpData, LPDWORD lpcbData)
370 const BYTE* ptr =
nullptr;
373 WINPR_ASSERT(pValue);
375 switch (pValue->type)
378 case REG_DWORD_BIG_ENDIAN:
379 required =
sizeof(DWORD);
380 ptr = (
const BYTE*)&pValue->data.dword;
383 required =
sizeof(UINT64);
384 ptr = (
const BYTE*)&pValue->data.qword;
387 return ERROR_INTERNAL_ERROR;
392 DWORD size = *lpcbData;
393 *lpcbData = required;
396 if (size < *lpcbData)
397 return ERROR_MORE_DATA;
401 if (lpData !=
nullptr)
404 WINPR_ASSERT(lpcbData);
407 *lpcbData = required;
409 return ERROR_MORE_DATA;
410 memcpy(lpData, ptr, required);
412 else if (lpcbData !=
nullptr)
413 *lpcbData = required;
414 return ERROR_SUCCESS;
418LONG RegQueryValueExW(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType,
419 LPBYTE lpData, LPDWORD lpcbData)
422 LONG status = ERROR_FILE_NOT_FOUND;
423 RegKey* key =
nullptr;
424 RegVal* pValue =
nullptr;
425 char* valueName =
nullptr;
427 WINPR_UNUSED(lpReserved);
432 valueName = ConvertWCharToUtf8Alloc(lpValueName,
nullptr);
436 pValue = key->values;
438 while (pValue !=
nullptr)
440 if (strcmp(pValue->name, valueName) == 0)
443 *lpType = pValue->type;
445 switch (pValue->type)
447 case REG_DWORD_BIG_ENDIAN:
450 status = reg_read_int(pValue, lpData, lpcbData);
454 const size_t length =
455 regsz_length(pValue->name, pValue->data.string) *
sizeof(WCHAR);
457 status = ERROR_SUCCESS;
458 if (lpData !=
nullptr)
466 WINPR_ASSERT(lpcbData);
470 *lpcbData = (DWORD)length;
472 status = ERROR_MORE_DATA;
473 if (ConvertUtf8NToWChar(pValue->data.string, length, cnv.wc, length) < 0)
474 status = ERROR_OUTOFMEMORY;
477 *lpcbData = (UINT32)length;
483 "Registry emulation does not support value type %s [0x%08" PRIx32
"]",
484 reg_type_string(pValue->type), pValue->type);
489 pValue = pValue->next;
498LONG RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType,
499 LPBYTE lpData, LPDWORD lpcbData)
502 RegKey* key =
nullptr;
503 RegVal* pValue =
nullptr;
505 WINPR_UNUSED(lpReserved);
510 pValue = key->values;
512 while (pValue !=
nullptr)
514 if (strcmp(pValue->name, lpValueName) == 0)
517 *lpType = pValue->type;
519 switch (pValue->type)
521 case REG_DWORD_BIG_ENDIAN:
524 return reg_read_int(pValue, lpData, lpcbData);
527 const size_t length = regsz_length(pValue->name, pValue->data.string);
529 char* pData = (
char*)lpData;
531 if (pData !=
nullptr)
534 WINPR_ASSERT(lpcbData);
537 *lpcbData = (DWORD)length;
539 return ERROR_MORE_DATA;
540 memcpy(pData, pValue->data.string, length);
541 pData[length] =
'\0';
544 *lpcbData = (UINT32)length;
546 return ERROR_SUCCESS;
550 "Registry emulation does not support value type %s [0x%08" PRIx32
"]",
551 reg_type_string(pValue->type), pValue->type);
556 pValue = pValue->next;
559 return ERROR_FILE_NOT_FOUND;
562LONG RegRestoreKeyW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpFile,
563 WINPR_ATTR_UNUSED DWORD dwFlags)
565 WLog_ERR(TAG,
"TODO: Implement");
569LONG RegRestoreKeyA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpFile,
570 WINPR_ATTR_UNUSED DWORD dwFlags)
572 WLog_ERR(TAG,
"TODO: Implement");
576LONG RegSaveKeyExW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpFile,
577 WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpSecurityAttributes,
578 WINPR_ATTR_UNUSED DWORD Flags)
580 WLog_ERR(TAG,
"TODO: Implement");
584LONG RegSaveKeyExA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpFile,
585 WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpSecurityAttributes,
586 WINPR_ATTR_UNUSED DWORD Flags)
588 WLog_ERR(TAG,
"TODO: Implement");
592LONG RegSetKeySecurity(WINPR_ATTR_UNUSED HKEY hKey,
593 WINPR_ATTR_UNUSED SECURITY_INFORMATION SecurityInformation,
594 WINPR_ATTR_UNUSED PSECURITY_DESCRIPTOR pSecurityDescriptor)
596 WLog_ERR(TAG,
"TODO: Implement");
600LONG RegSetValueExW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpValueName,
601 WINPR_ATTR_UNUSED DWORD Reserved, WINPR_ATTR_UNUSED DWORD dwType,
602 WINPR_ATTR_UNUSED
const BYTE* lpData, WINPR_ATTR_UNUSED DWORD cbData)
604 WLog_ERR(TAG,
"TODO: Implement");
608LONG RegSetValueExA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpValueName,
609 WINPR_ATTR_UNUSED DWORD Reserved, WINPR_ATTR_UNUSED DWORD dwType,
610 WINPR_ATTR_UNUSED
const BYTE* lpData, WINPR_ATTR_UNUSED DWORD cbData)
612 WLog_ERR(TAG,
"TODO: Implement");
616LONG RegUnLoadKeyW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpSubKey)
618 WLog_ERR(TAG,
"TODO: Implement");
622LONG RegUnLoadKeyA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpSubKey)
624 WLog_ERR(TAG,
"TODO: Implement");