FreeRDP
registry.c
1 
20 #include <winpr/config.h>
21 
22 #include <winpr/registry.h>
23 
24 /*
25  * Windows registry MSDN pages:
26  * Reference: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724880/
27  * Functions: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724875/
28  */
29 
30 #if !defined(_WIN32) || defined(_UWP)
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 
36 #include <winpr/crt.h>
37 #include <winpr/assert.h>
38 
39 #include "registry_reg.h"
40 
41 #include "../log.h"
42 #define TAG WINPR_TAG("registry")
43 
44 static Reg* instance = NULL;
45 
46 static Reg* RegGetInstance(void)
47 {
48  if (!instance)
49  instance = reg_open(1);
50 
51  return instance;
52 }
53 
54 LONG RegCloseKey(HKEY hKey)
55 {
56  WINPR_UNUSED(hKey);
57  return 0;
58 }
59 
60 LONG RegCopyTreeW(HKEY hKeySrc, LPCWSTR lpSubKey, HKEY hKeyDest)
61 {
62  WLog_ERR(TAG, "TODO: Implement");
63  return -1;
64 }
65 
66 LONG RegCopyTreeA(HKEY hKeySrc, LPCSTR lpSubKey, HKEY hKeyDest)
67 {
68  WLog_ERR(TAG, "TODO: Implement");
69  return -1;
70 }
71 
72 LONG RegCreateKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD Reserved, LPWSTR lpClass, DWORD dwOptions,
73  REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult,
74  LPDWORD lpdwDisposition)
75 {
76  WLog_ERR(TAG, "TODO: Implement");
77  return -1;
78 }
79 
80 LONG RegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, DWORD dwOptions,
81  REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult,
82  LPDWORD lpdwDisposition)
83 {
84  WLog_ERR(TAG, "TODO: Implement");
85  return -1;
86 }
87 
88 LONG RegDeleteKeyExW(HKEY hKey, LPCWSTR lpSubKey, REGSAM samDesired, DWORD Reserved)
89 {
90  WLog_ERR(TAG, "TODO: Implement");
91  return -1;
92 }
93 
94 LONG RegDeleteKeyExA(HKEY hKey, LPCSTR lpSubKey, REGSAM samDesired, DWORD Reserved)
95 {
96  WLog_ERR(TAG, "TODO: Implement");
97  return -1;
98 }
99 
100 LONG RegDeleteTreeW(HKEY hKey, LPCWSTR lpSubKey)
101 {
102  WLog_ERR(TAG, "TODO: Implement");
103  return -1;
104 }
105 
106 LONG RegDeleteTreeA(HKEY hKey, LPCSTR lpSubKey)
107 {
108  WLog_ERR(TAG, "TODO: Implement");
109  return -1;
110 }
111 
112 LONG RegDeleteValueW(HKEY hKey, LPCWSTR lpValueName)
113 {
114  WLog_ERR(TAG, "TODO: Implement");
115  return -1;
116 }
117 
118 LONG RegDeleteValueA(HKEY hKey, LPCSTR lpValueName)
119 {
120  WLog_ERR(TAG, "TODO: Implement");
121  return -1;
122 }
123 
124 LONG RegDisablePredefinedCacheEx(void)
125 {
126  WLog_ERR(TAG, "TODO: Implement");
127  return -1;
128 }
129 
130 LONG RegEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcName, LPDWORD lpReserved,
131  LPWSTR lpClass, LPDWORD lpcClass, PFILETIME lpftLastWriteTime)
132 {
133  WLog_ERR(TAG, "TODO: Implement");
134  return -1;
135 }
136 
137 LONG RegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcName, LPDWORD lpReserved,
138  LPSTR lpClass, LPDWORD lpcClass, PFILETIME lpftLastWriteTime)
139 {
140  WLog_ERR(TAG, "TODO: Implement");
141  return -1;
142 }
143 
144 LONG RegEnumValueW(HKEY hKey, DWORD dwIndex, LPWSTR lpValueName, LPDWORD lpcchValueName,
145  LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
146 {
147  WLog_ERR(TAG, "TODO: Implement");
148  return -1;
149 }
150 
151 LONG RegEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpValueName, LPDWORD lpcchValueName,
152  LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
153 {
154  WLog_ERR(TAG, "TODO: Implement");
155  return -1;
156 }
157 
158 LONG RegFlushKey(HKEY hKey)
159 {
160  WLog_ERR(TAG, "TODO: Implement");
161  return -1;
162 }
163 
164 LONG RegGetKeySecurity(HKEY hKey, SECURITY_INFORMATION SecurityInformation,
165  PSECURITY_DESCRIPTOR pSecurityDescriptor, LPDWORD lpcbSecurityDescriptor)
166 {
167  WLog_ERR(TAG, "TODO: Implement");
168  return -1;
169 }
170 
171 LONG RegGetValueW(HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpValue, DWORD dwFlags, LPDWORD pdwType,
172  PVOID pvData, LPDWORD pcbData)
173 {
174  WLog_ERR(TAG, "TODO: Implement");
175  return -1;
176 }
177 
178 LONG RegGetValueA(HKEY hkey, LPCSTR lpSubKey, LPCSTR lpValue, DWORD dwFlags, LPDWORD pdwType,
179  PVOID pvData, LPDWORD pcbData)
180 {
181  WLog_ERR(TAG, "TODO: Implement");
182  return -1;
183 }
184 
185 LONG RegLoadAppKeyW(LPCWSTR lpFile, PHKEY phkResult, REGSAM samDesired, DWORD dwOptions,
186  DWORD Reserved)
187 {
188  WLog_ERR(TAG, "TODO: Implement");
189  return -1;
190 }
191 
192 LONG RegLoadAppKeyA(LPCSTR lpFile, PHKEY phkResult, REGSAM samDesired, DWORD dwOptions,
193  DWORD Reserved)
194 {
195  WLog_ERR(TAG, "TODO: Implement");
196  return -1;
197 }
198 
199 LONG RegLoadKeyW(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpFile)
200 {
201  WLog_ERR(TAG, "TODO: Implement");
202  return -1;
203 }
204 
205 LONG RegLoadKeyA(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpFile)
206 {
207  WLog_ERR(TAG, "TODO: Implement");
208  return -1;
209 }
210 
211 LONG RegLoadMUIStringW(HKEY hKey, LPCWSTR pszValue, LPWSTR pszOutBuf, DWORD cbOutBuf,
212  LPDWORD pcbData, DWORD Flags, LPCWSTR pszDirectory)
213 {
214  WLog_ERR(TAG, "TODO: Implement");
215  return -1;
216 }
217 
218 LONG RegLoadMUIStringA(HKEY hKey, LPCSTR pszValue, LPSTR pszOutBuf, DWORD cbOutBuf, LPDWORD pcbData,
219  DWORD Flags, LPCSTR pszDirectory)
220 {
221  WLog_ERR(TAG, "TODO: Implement");
222  return -1;
223 }
224 
225 LONG RegNotifyChangeKeyValue(HKEY hKey, BOOL bWatchSubtree, DWORD dwNotifyFilter, HANDLE hEvent,
226  BOOL fAsynchronous)
227 {
228  WLog_ERR(TAG, "TODO: Implement");
229  return -1;
230 }
231 
232 LONG RegOpenCurrentUser(REGSAM samDesired, PHKEY phkResult)
233 {
234  WLog_ERR(TAG, "TODO: Implement");
235  return -1;
236 }
237 
238 LONG RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
239 {
240  LONG rc = 0;
241  char* str = ConvertWCharToUtf8Alloc(lpSubKey, NULL);
242  if (!str)
243  return ERROR_FILE_NOT_FOUND;
244 
245  rc = RegOpenKeyExA(hKey, str, ulOptions, samDesired, phkResult);
246  free(str);
247  return rc;
248 }
249 
250 LONG RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
251 {
252  Reg* reg = RegGetInstance();
253 
254  if (!reg)
255  return -1;
256 
257  if (hKey != HKEY_LOCAL_MACHINE)
258  {
259  WLog_WARN(TAG, "Registry emulation only supports HKEY_LOCAL_MACHINE");
260  return ERROR_FILE_NOT_FOUND;
261  }
262 
263  WINPR_ASSERT(reg->root_key);
264  RegKey* pKey = reg->root_key->subkeys;
265 
266  while (pKey != NULL)
267  {
268  WINPR_ASSERT(lpSubKey);
269 
270  if (pKey->subname && (_stricmp(pKey->subname, lpSubKey) == 0))
271  {
272  *phkResult = (HKEY)pKey;
273  return ERROR_SUCCESS;
274  }
275 
276  pKey = pKey->next;
277  }
278 
279  *phkResult = NULL;
280 
281  return ERROR_FILE_NOT_FOUND;
282 }
283 
284 LONG RegOpenUserClassesRoot(HANDLE hToken, DWORD dwOptions, REGSAM samDesired, PHKEY phkResult)
285 {
286  WLog_ERR(TAG, "TODO: Implement");
287  return -1;
288 }
289 
290 LONG RegQueryInfoKeyW(HKEY hKey, LPWSTR lpClass, LPDWORD lpcClass, LPDWORD lpReserved,
291  LPDWORD lpcSubKeys, LPDWORD lpcMaxSubKeyLen, LPDWORD lpcMaxClassLen,
292  LPDWORD lpcValues, LPDWORD lpcMaxValueNameLen, LPDWORD lpcMaxValueLen,
293  LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime)
294 {
295  WLog_ERR(TAG, "TODO: Implement");
296  return -1;
297 }
298 
299 LONG RegQueryInfoKeyA(HKEY hKey, LPSTR lpClass, LPDWORD lpcClass, LPDWORD lpReserved,
300  LPDWORD lpcSubKeys, LPDWORD lpcMaxSubKeyLen, LPDWORD lpcMaxClassLen,
301  LPDWORD lpcValues, LPDWORD lpcMaxValueNameLen, LPDWORD lpcMaxValueLen,
302  LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime)
303 {
304  WLog_ERR(TAG, "TODO: Implement");
305  return -1;
306 }
307 
308 static LONG reg_read_int(const RegVal* pValue, LPBYTE lpData, LPDWORD lpcbData)
309 {
310  const BYTE* ptr = NULL;
311  DWORD required = 0;
312 
313  WINPR_ASSERT(pValue);
314 
315  switch (pValue->type)
316  {
317  case REG_DWORD:
318  case REG_DWORD_BIG_ENDIAN:
319  required = sizeof(DWORD);
320  ptr = (const BYTE*)&pValue->data.dword;
321  break;
322  case REG_QWORD:
323  required = sizeof(UINT64);
324  ptr = (const BYTE*)&pValue->data.qword;
325  break;
326  default:
327  return ERROR_INTERNAL_ERROR;
328  }
329 
330  if (lpcbData)
331  {
332  DWORD size = *lpcbData;
333  *lpcbData = required;
334  if (lpData)
335  {
336  if (size < *lpcbData)
337  return ERROR_MORE_DATA;
338  }
339  }
340 
341  if (lpData != NULL)
342  {
343  DWORD size = 0;
344  WINPR_ASSERT(lpcbData);
345 
346  size = *lpcbData;
347  *lpcbData = required;
348  if (size < required)
349  return ERROR_MORE_DATA;
350  memcpy(lpData, ptr, required);
351  }
352  else if (lpcbData != NULL)
353  *lpcbData = required;
354  return ERROR_SUCCESS;
355 }
356 
357 // NOLINTBEGIN(readability-non-const-parameter)
358 LONG RegQueryValueExW(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType,
359  LPBYTE lpData, LPDWORD lpcbData)
360 // NOLINTEND(readability-non-const-parameter)
361 {
362  LONG status = ERROR_FILE_NOT_FOUND;
363  RegKey* key = NULL;
364  RegVal* pValue = NULL;
365  char* valueName = NULL;
366 
367  WINPR_UNUSED(lpReserved);
368 
369  key = (RegKey*)hKey;
370  WINPR_ASSERT(key);
371 
372  valueName = ConvertWCharToUtf8Alloc(lpValueName, NULL);
373  if (!valueName)
374  goto end;
375 
376  pValue = key->values;
377 
378  while (pValue != NULL)
379  {
380  if (strcmp(pValue->name, valueName) == 0)
381  {
382  if (lpType)
383  *lpType = pValue->type;
384 
385  switch (pValue->type)
386  {
387  case REG_DWORD_BIG_ENDIAN:
388  case REG_QWORD:
389  case REG_DWORD:
390  status = reg_read_int(pValue, lpData, lpcbData);
391  goto end;
392  case REG_SZ:
393  {
394  const size_t length = strnlen(pValue->data.string, UINT32_MAX) * sizeof(WCHAR);
395 
396  status = ERROR_SUCCESS;
397  if (lpData != NULL)
398  {
399  DWORD size = 0;
400  union
401  {
402  WCHAR* wc;
403  BYTE* b;
404  } cnv;
405  WINPR_ASSERT(lpcbData);
406 
407  cnv.b = lpData;
408  size = *lpcbData;
409  *lpcbData = (DWORD)length;
410  if (size < length)
411  status = ERROR_MORE_DATA;
412  if (ConvertUtf8NToWChar(pValue->data.string, length, cnv.wc, length) < 0)
413  status = ERROR_OUTOFMEMORY;
414  }
415  else if (lpcbData)
416  *lpcbData = (UINT32)length;
417 
418  goto end;
419  }
420  default:
421  WLog_WARN(TAG,
422  "Registry emulation does not support value type %s [0x%08" PRIx32 "]",
423  reg_type_string(pValue->type), pValue->type);
424  break;
425  }
426  }
427 
428  pValue = pValue->next;
429  }
430 
431 end:
432  free(valueName);
433  return status;
434 }
435 
436 // NOLINTBEGIN(readability-non-const-parameter)
437 LONG RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType,
438  LPBYTE lpData, LPDWORD lpcbData)
439 // NOLINTEND(readability-non-const-parameter)
440 {
441  RegKey* key = NULL;
442  RegVal* pValue = NULL;
443 
444  WINPR_UNUSED(lpReserved);
445 
446  key = (RegKey*)hKey;
447  WINPR_ASSERT(key);
448 
449  pValue = key->values;
450 
451  while (pValue != NULL)
452  {
453  if (strcmp(pValue->name, lpValueName) == 0)
454  {
455  if (lpType)
456  *lpType = pValue->type;
457 
458  switch (pValue->type)
459  {
460  case REG_DWORD_BIG_ENDIAN:
461  case REG_QWORD:
462  case REG_DWORD:
463  return reg_read_int(pValue, lpData, lpcbData);
464  case REG_SZ:
465  {
466  const size_t length = strnlen(pValue->data.string, UINT32_MAX);
467  char* pData = (char*)lpData;
468 
469  if (pData != NULL)
470  {
471  DWORD size = 0;
472  WINPR_ASSERT(lpcbData);
473 
474  size = *lpcbData;
475  *lpcbData = (DWORD)length;
476  if (size < length)
477  return ERROR_MORE_DATA;
478  memcpy(pData, pValue->data.string, length);
479  pData[length] = '\0';
480  }
481  else if (lpcbData)
482  *lpcbData = (UINT32)length;
483 
484  return ERROR_SUCCESS;
485  }
486  default:
487  WLog_WARN(TAG,
488  "Registry emulation does not support value type %s [0x%08" PRIx32 "]",
489  reg_type_string(pValue->type), pValue->type);
490  break;
491  }
492  }
493 
494  pValue = pValue->next;
495  }
496 
497  return ERROR_FILE_NOT_FOUND;
498 }
499 
500 LONG RegRestoreKeyW(HKEY hKey, LPCWSTR lpFile, DWORD dwFlags)
501 {
502  WLog_ERR(TAG, "TODO: Implement");
503  return -1;
504 }
505 
506 LONG RegRestoreKeyA(HKEY hKey, LPCSTR lpFile, DWORD dwFlags)
507 {
508  WLog_ERR(TAG, "TODO: Implement");
509  return -1;
510 }
511 
512 LONG RegSaveKeyExW(HKEY hKey, LPCWSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
513  DWORD Flags)
514 {
515  WLog_ERR(TAG, "TODO: Implement");
516  return -1;
517 }
518 
519 LONG RegSaveKeyExA(HKEY hKey, LPCSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
520  DWORD Flags)
521 {
522  WLog_ERR(TAG, "TODO: Implement");
523  return -1;
524 }
525 
526 LONG RegSetKeySecurity(HKEY hKey, SECURITY_INFORMATION SecurityInformation,
527  PSECURITY_DESCRIPTOR pSecurityDescriptor)
528 {
529  WLog_ERR(TAG, "TODO: Implement");
530  return -1;
531 }
532 
533 LONG RegSetValueExW(HKEY hKey, LPCWSTR lpValueName, DWORD Reserved, DWORD dwType,
534  const BYTE* lpData, DWORD cbData)
535 {
536  WLog_ERR(TAG, "TODO: Implement");
537  return -1;
538 }
539 
540 LONG RegSetValueExA(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, const BYTE* lpData,
541  DWORD cbData)
542 {
543  WLog_ERR(TAG, "TODO: Implement");
544  return -1;
545 }
546 
547 LONG RegUnLoadKeyW(HKEY hKey, LPCWSTR lpSubKey)
548 {
549  WLog_ERR(TAG, "TODO: Implement");
550  return -1;
551 }
552 
553 LONG RegUnLoadKeyA(HKEY hKey, LPCSTR lpSubKey)
554 {
555  WLog_ERR(TAG, "TODO: Implement");
556  return -1;
557 }
558 
559 #endif