Coverage Report

Created: 2025-07-01 06:46

/src/FreeRDP/winpr/libwinpr/registry/registry.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * WinPR: Windows Portable Runtime
3
 * Windows Registry
4
 *
5
 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
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
#include <winpr/string.h>
39
40
#include "registry_reg.h"
41
42
#include "../log.h"
43
#define TAG WINPR_TAG("registry")
44
45
static Reg* instance = NULL;
46
47
static size_t regsz_length(const char* key, const void* value, bool unicode)
48
0
{
49
  /* https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-element-size-limits
50
   *
51
   * while not strictly limited to this size larger values should be stored to a
52
   * file.
53
   */
54
0
  const size_t limit = 16383;
55
0
  size_t length = 0;
56
0
  if (unicode)
57
0
    length = _wcsnlen((const WCHAR*)value, limit);
58
0
  else
59
0
    length = strnlen((const char*)value, limit);
60
0
  if (length >= limit)
61
0
    WLog_WARN(TAG, "REG_SZ[%s] truncated to size %" PRIuz, key, length);
62
0
  return length;
63
0
}
64
65
static Reg* RegGetInstance(void)
66
0
{
67
0
  if (!instance)
68
0
    instance = reg_open(1);
69
70
0
  return instance;
71
0
}
72
73
LONG RegCloseKey(HKEY hKey)
74
0
{
75
0
  WINPR_UNUSED(hKey);
76
0
  return 0;
77
0
}
78
79
LONG RegCopyTreeW(WINPR_ATTR_UNUSED HKEY hKeySrc, WINPR_ATTR_UNUSED LPCWSTR lpSubKey,
80
                  WINPR_ATTR_UNUSED HKEY hKeyDest)
81
0
{
82
0
  WLog_ERR(TAG, "TODO: Implement");
83
0
  return -1;
84
0
}
85
86
LONG RegCopyTreeA(WINPR_ATTR_UNUSED HKEY hKeySrc, WINPR_ATTR_UNUSED LPCSTR lpSubKey,
87
                  WINPR_ATTR_UNUSED HKEY hKeyDest)
88
0
{
89
0
  WLog_ERR(TAG, "TODO: Implement");
90
0
  return -1;
91
0
}
92
93
LONG RegCreateKeyExW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpSubKey,
94
                     WINPR_ATTR_UNUSED DWORD Reserved, WINPR_ATTR_UNUSED LPWSTR lpClass,
95
                     WINPR_ATTR_UNUSED DWORD dwOptions, WINPR_ATTR_UNUSED REGSAM samDesired,
96
                     WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpSecurityAttributes,
97
                     WINPR_ATTR_UNUSED PHKEY phkResult, WINPR_ATTR_UNUSED LPDWORD lpdwDisposition)
98
0
{
99
0
  WLog_ERR(TAG, "TODO: Implement");
100
0
  return -1;
101
0
}
102
103
LONG RegCreateKeyExA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpSubKey,
104
                     WINPR_ATTR_UNUSED DWORD Reserved, WINPR_ATTR_UNUSED LPSTR lpClass,
105
                     WINPR_ATTR_UNUSED DWORD dwOptions, WINPR_ATTR_UNUSED REGSAM samDesired,
106
                     WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpSecurityAttributes,
107
                     WINPR_ATTR_UNUSED PHKEY phkResult, WINPR_ATTR_UNUSED LPDWORD lpdwDisposition)
108
0
{
109
0
  WLog_ERR(TAG, "TODO: Implement");
110
0
  return -1;
111
0
}
112
113
LONG RegDeleteKeyExW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpSubKey,
114
                     WINPR_ATTR_UNUSED REGSAM samDesired, WINPR_ATTR_UNUSED DWORD Reserved)
115
0
{
116
0
  WLog_ERR(TAG, "TODO: Implement");
117
0
  return -1;
118
0
}
119
120
LONG RegDeleteKeyExA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpSubKey,
121
                     WINPR_ATTR_UNUSED REGSAM samDesired, WINPR_ATTR_UNUSED DWORD Reserved)
122
0
{
123
0
  WLog_ERR(TAG, "TODO: Implement");
124
0
  return -1;
125
0
}
126
127
LONG RegDeleteTreeW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpSubKey)
128
0
{
129
0
  WLog_ERR(TAG, "TODO: Implement");
130
0
  return -1;
131
0
}
132
133
LONG RegDeleteTreeA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpSubKey)
134
0
{
135
0
  WLog_ERR(TAG, "TODO: Implement");
136
0
  return -1;
137
0
}
138
139
LONG RegDeleteValueW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpValueName)
140
0
{
141
0
  WLog_ERR(TAG, "TODO: Implement");
142
0
  return -1;
143
0
}
144
145
LONG RegDeleteValueA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpValueName)
146
0
{
147
0
  WLog_ERR(TAG, "TODO: Implement");
148
0
  return -1;
149
0
}
150
151
LONG RegDisablePredefinedCacheEx(void)
152
0
{
153
0
  WLog_ERR(TAG, "TODO: Implement");
154
0
  return -1;
155
0
}
156
157
LONG RegEnumKeyExW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED DWORD dwIndex,
158
                   WINPR_ATTR_UNUSED LPWSTR lpName, WINPR_ATTR_UNUSED LPDWORD lpcName,
159
                   WINPR_ATTR_UNUSED LPDWORD lpReserved, WINPR_ATTR_UNUSED LPWSTR lpClass,
160
                   WINPR_ATTR_UNUSED LPDWORD lpcClass,
161
                   WINPR_ATTR_UNUSED PFILETIME lpftLastWriteTime)
162
0
{
163
0
  WLog_ERR(TAG, "TODO: Implement");
164
0
  return -1;
165
0
}
166
167
LONG RegEnumKeyExA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED DWORD dwIndex,
168
                   WINPR_ATTR_UNUSED LPSTR lpName, WINPR_ATTR_UNUSED LPDWORD lpcName,
169
                   WINPR_ATTR_UNUSED LPDWORD lpReserved, WINPR_ATTR_UNUSED LPSTR lpClass,
170
                   WINPR_ATTR_UNUSED LPDWORD lpcClass,
171
                   WINPR_ATTR_UNUSED PFILETIME lpftLastWriteTime)
172
0
{
173
0
  WLog_ERR(TAG, "TODO: Implement");
174
0
  return -1;
175
0
}
176
177
LONG RegEnumValueW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED DWORD dwIndex,
178
                   WINPR_ATTR_UNUSED LPWSTR lpValueName, WINPR_ATTR_UNUSED LPDWORD lpcchValueName,
179
                   WINPR_ATTR_UNUSED LPDWORD lpReserved, WINPR_ATTR_UNUSED LPDWORD lpType,
180
                   WINPR_ATTR_UNUSED LPBYTE lpData, WINPR_ATTR_UNUSED LPDWORD lpcbData)
181
0
{
182
0
  WLog_ERR(TAG, "TODO: Implement");
183
0
  return -1;
184
0
}
185
186
LONG RegEnumValueA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED DWORD dwIndex,
187
                   WINPR_ATTR_UNUSED LPSTR lpValueName, WINPR_ATTR_UNUSED LPDWORD lpcchValueName,
188
                   WINPR_ATTR_UNUSED LPDWORD lpReserved, WINPR_ATTR_UNUSED LPDWORD lpType,
189
                   WINPR_ATTR_UNUSED LPBYTE lpData, WINPR_ATTR_UNUSED LPDWORD lpcbData)
190
0
{
191
0
  WLog_ERR(TAG, "TODO: Implement");
192
0
  return -1;
193
0
}
194
195
LONG RegFlushKey(WINPR_ATTR_UNUSED HKEY hKey)
196
0
{
197
0
  WLog_ERR(TAG, "TODO: Implement");
198
0
  return -1;
199
0
}
200
201
LONG RegGetKeySecurity(WINPR_ATTR_UNUSED HKEY hKey,
202
                       WINPR_ATTR_UNUSED SECURITY_INFORMATION SecurityInformation,
203
                       WINPR_ATTR_UNUSED PSECURITY_DESCRIPTOR pSecurityDescriptor,
204
                       WINPR_ATTR_UNUSED LPDWORD lpcbSecurityDescriptor)
205
0
{
206
0
  WLog_ERR(TAG, "TODO: Implement");
207
0
  return -1;
208
0
}
209
210
LONG RegGetValueW(WINPR_ATTR_UNUSED HKEY hkey, WINPR_ATTR_UNUSED LPCWSTR lpSubKey,
211
                  WINPR_ATTR_UNUSED LPCWSTR lpValue, WINPR_ATTR_UNUSED DWORD dwFlags,
212
                  WINPR_ATTR_UNUSED LPDWORD pdwType, WINPR_ATTR_UNUSED PVOID pvData,
213
                  WINPR_ATTR_UNUSED LPDWORD pcbData)
214
0
{
215
0
  WLog_ERR(TAG, "TODO: Implement");
216
0
  return -1;
217
0
}
218
219
LONG RegGetValueA(WINPR_ATTR_UNUSED HKEY hkey, WINPR_ATTR_UNUSED LPCSTR lpSubKey,
220
                  WINPR_ATTR_UNUSED LPCSTR lpValue, WINPR_ATTR_UNUSED DWORD dwFlags,
221
                  WINPR_ATTR_UNUSED LPDWORD pdwType, WINPR_ATTR_UNUSED PVOID pvData,
222
                  WINPR_ATTR_UNUSED LPDWORD pcbData)
223
0
{
224
0
  WLog_ERR(TAG, "TODO: Implement");
225
0
  return -1;
226
0
}
227
228
LONG RegLoadAppKeyW(WINPR_ATTR_UNUSED LPCWSTR lpFile, WINPR_ATTR_UNUSED PHKEY phkResult,
229
                    WINPR_ATTR_UNUSED REGSAM samDesired, WINPR_ATTR_UNUSED DWORD dwOptions,
230
                    WINPR_ATTR_UNUSED DWORD Reserved)
231
0
{
232
0
  WLog_ERR(TAG, "TODO: Implement");
233
0
  return -1;
234
0
}
235
236
LONG RegLoadAppKeyA(WINPR_ATTR_UNUSED LPCSTR lpFile, WINPR_ATTR_UNUSED PHKEY phkResult,
237
                    WINPR_ATTR_UNUSED REGSAM samDesired, WINPR_ATTR_UNUSED DWORD dwOptions,
238
                    WINPR_ATTR_UNUSED DWORD Reserved)
239
0
{
240
0
  WLog_ERR(TAG, "TODO: Implement");
241
0
  return -1;
242
0
}
243
244
LONG RegLoadKeyW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpSubKey,
245
                 WINPR_ATTR_UNUSED LPCWSTR lpFile)
246
0
{
247
0
  WLog_ERR(TAG, "TODO: Implement");
248
0
  return -1;
249
0
}
250
251
LONG RegLoadKeyA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpSubKey,
252
                 WINPR_ATTR_UNUSED LPCSTR lpFile)
253
0
{
254
0
  WLog_ERR(TAG, "TODO: Implement");
255
0
  return -1;
256
0
}
257
258
LONG RegLoadMUIStringW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR pszValue,
259
                       WINPR_ATTR_UNUSED LPWSTR pszOutBuf, WINPR_ATTR_UNUSED DWORD cbOutBuf,
260
                       WINPR_ATTR_UNUSED LPDWORD pcbData, WINPR_ATTR_UNUSED DWORD Flags,
261
                       WINPR_ATTR_UNUSED LPCWSTR pszDirectory)
262
0
{
263
0
  WLog_ERR(TAG, "TODO: Implement");
264
0
  return -1;
265
0
}
266
267
LONG RegLoadMUIStringA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR pszValue,
268
                       WINPR_ATTR_UNUSED LPSTR pszOutBuf, WINPR_ATTR_UNUSED DWORD cbOutBuf,
269
                       WINPR_ATTR_UNUSED LPDWORD pcbData, WINPR_ATTR_UNUSED DWORD Flags,
270
                       WINPR_ATTR_UNUSED LPCSTR pszDirectory)
271
0
{
272
0
  WLog_ERR(TAG, "TODO: Implement");
273
0
  return -1;
274
0
}
275
276
LONG RegNotifyChangeKeyValue(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED BOOL bWatchSubtree,
277
                             WINPR_ATTR_UNUSED DWORD dwNotifyFilter,
278
                             WINPR_ATTR_UNUSED HANDLE hEvent, WINPR_ATTR_UNUSED BOOL fAsynchronous)
279
0
{
280
0
  WLog_ERR(TAG, "TODO: Implement");
281
0
  return -1;
282
0
}
283
284
LONG RegOpenCurrentUser(WINPR_ATTR_UNUSED REGSAM samDesired, WINPR_ATTR_UNUSED PHKEY phkResult)
285
0
{
286
0
  WLog_ERR(TAG, "TODO: Implement");
287
0
  return -1;
288
0
}
289
290
LONG RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
291
0
{
292
0
  LONG rc = 0;
293
0
  char* str = ConvertWCharToUtf8Alloc(lpSubKey, NULL);
294
0
  if (!str)
295
0
    return ERROR_FILE_NOT_FOUND;
296
297
0
  rc = RegOpenKeyExA(hKey, str, ulOptions, samDesired, phkResult);
298
0
  free(str);
299
0
  return rc;
300
0
}
301
302
LONG RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, WINPR_ATTR_UNUSED DWORD ulOptions,
303
                   WINPR_ATTR_UNUSED REGSAM samDesired, PHKEY phkResult)
304
0
{
305
0
  Reg* reg = RegGetInstance();
306
307
0
  if (!reg)
308
0
    return -1;
309
310
0
  if (hKey != HKEY_LOCAL_MACHINE)
311
0
  {
312
0
    WLog_WARN(TAG, "Registry emulation only supports HKEY_LOCAL_MACHINE");
313
0
    return ERROR_FILE_NOT_FOUND;
314
0
  }
315
316
0
  WINPR_ASSERT(reg->root_key);
317
0
  RegKey* pKey = reg->root_key->subkeys;
318
319
0
  while (pKey != NULL)
320
0
  {
321
0
    WINPR_ASSERT(lpSubKey);
322
323
0
    if (pKey->subname && (_stricmp(pKey->subname, lpSubKey) == 0))
324
0
    {
325
0
      *phkResult = (HKEY)pKey;
326
0
      return ERROR_SUCCESS;
327
0
    }
328
329
0
    pKey = pKey->next;
330
0
  }
331
332
0
  *phkResult = NULL;
333
334
0
  return ERROR_FILE_NOT_FOUND;
335
0
}
336
337
LONG RegOpenUserClassesRoot(WINPR_ATTR_UNUSED HANDLE hToken, WINPR_ATTR_UNUSED DWORD dwOptions,
338
                            WINPR_ATTR_UNUSED REGSAM samDesired, WINPR_ATTR_UNUSED PHKEY phkResult)
339
0
{
340
0
  WLog_ERR(TAG, "TODO: Implement");
341
0
  return -1;
342
0
}
343
344
LONG RegQueryInfoKeyW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPWSTR lpClass,
345
                      WINPR_ATTR_UNUSED LPDWORD lpcClass, WINPR_ATTR_UNUSED LPDWORD lpReserved,
346
                      WINPR_ATTR_UNUSED LPDWORD lpcSubKeys,
347
                      WINPR_ATTR_UNUSED LPDWORD lpcMaxSubKeyLen,
348
                      WINPR_ATTR_UNUSED LPDWORD lpcMaxClassLen, WINPR_ATTR_UNUSED LPDWORD lpcValues,
349
                      WINPR_ATTR_UNUSED LPDWORD lpcMaxValueNameLen,
350
                      WINPR_ATTR_UNUSED LPDWORD lpcMaxValueLen,
351
                      WINPR_ATTR_UNUSED LPDWORD lpcbSecurityDescriptor,
352
                      WINPR_ATTR_UNUSED PFILETIME lpftLastWriteTime)
353
0
{
354
0
  WLog_ERR(TAG, "TODO: Implement");
355
0
  return -1;
356
0
}
357
358
LONG RegQueryInfoKeyA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPSTR lpClass,
359
                      WINPR_ATTR_UNUSED LPDWORD lpcClass, WINPR_ATTR_UNUSED LPDWORD lpReserved,
360
                      WINPR_ATTR_UNUSED LPDWORD lpcSubKeys,
361
                      WINPR_ATTR_UNUSED LPDWORD lpcMaxSubKeyLen,
362
                      WINPR_ATTR_UNUSED LPDWORD lpcMaxClassLen, WINPR_ATTR_UNUSED LPDWORD lpcValues,
363
                      WINPR_ATTR_UNUSED LPDWORD lpcMaxValueNameLen,
364
                      WINPR_ATTR_UNUSED LPDWORD lpcMaxValueLen,
365
                      WINPR_ATTR_UNUSED LPDWORD lpcbSecurityDescriptor,
366
                      WINPR_ATTR_UNUSED PFILETIME lpftLastWriteTime)
367
0
{
368
0
  WLog_ERR(TAG, "TODO: Implement");
369
0
  return -1;
370
0
}
371
372
static LONG reg_read_int(const RegVal* pValue, LPBYTE lpData, LPDWORD lpcbData)
373
0
{
374
0
  const BYTE* ptr = NULL;
375
0
  DWORD required = 0;
376
377
0
  WINPR_ASSERT(pValue);
378
379
0
  switch (pValue->type)
380
0
  {
381
0
    case REG_DWORD:
382
0
    case REG_DWORD_BIG_ENDIAN:
383
0
      required = sizeof(DWORD);
384
0
      ptr = (const BYTE*)&pValue->data.dword;
385
0
      break;
386
0
    case REG_QWORD:
387
0
      required = sizeof(UINT64);
388
0
      ptr = (const BYTE*)&pValue->data.qword;
389
0
      break;
390
0
    default:
391
0
      return ERROR_INTERNAL_ERROR;
392
0
  }
393
394
0
  if (lpcbData)
395
0
  {
396
0
    DWORD size = *lpcbData;
397
0
    *lpcbData = required;
398
0
    if (lpData)
399
0
    {
400
0
      if (size < *lpcbData)
401
0
        return ERROR_MORE_DATA;
402
0
    }
403
0
  }
404
405
0
  if (lpData != NULL)
406
0
  {
407
0
    DWORD size = 0;
408
0
    WINPR_ASSERT(lpcbData);
409
410
0
    size = *lpcbData;
411
0
    *lpcbData = required;
412
0
    if (size < required)
413
0
      return ERROR_MORE_DATA;
414
0
    memcpy(lpData, ptr, required);
415
0
  }
416
0
  else if (lpcbData != NULL)
417
0
    *lpcbData = required;
418
0
  return ERROR_SUCCESS;
419
0
}
420
421
// NOLINTBEGIN(readability-non-const-parameter)
422
LONG RegQueryValueExW(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType,
423
                      LPBYTE lpData, LPDWORD lpcbData)
424
// NOLINTEND(readability-non-const-parameter)
425
0
{
426
0
  LONG status = ERROR_FILE_NOT_FOUND;
427
0
  RegKey* key = NULL;
428
0
  RegVal* pValue = NULL;
429
0
  char* valueName = NULL;
430
431
0
  WINPR_UNUSED(lpReserved);
432
433
0
  key = (RegKey*)hKey;
434
0
  WINPR_ASSERT(key);
435
436
0
  valueName = ConvertWCharToUtf8Alloc(lpValueName, NULL);
437
0
  if (!valueName)
438
0
    goto end;
439
440
0
  pValue = key->values;
441
442
0
  while (pValue != NULL)
443
0
  {
444
0
    if (strcmp(pValue->name, valueName) == 0)
445
0
    {
446
0
      if (lpType)
447
0
        *lpType = pValue->type;
448
449
0
      switch (pValue->type)
450
0
      {
451
0
        case REG_DWORD_BIG_ENDIAN:
452
0
        case REG_QWORD:
453
0
        case REG_DWORD:
454
0
          status = reg_read_int(pValue, lpData, lpcbData);
455
0
          goto end;
456
0
        case REG_SZ:
457
0
        {
458
0
          const size_t length =
459
0
              regsz_length(pValue->name, pValue->data.string, TRUE) * sizeof(WCHAR);
460
461
0
          status = ERROR_SUCCESS;
462
0
          if (lpData != NULL)
463
0
          {
464
0
            DWORD size = 0;
465
0
            union
466
0
            {
467
0
              WCHAR* wc;
468
0
              BYTE* b;
469
0
            } cnv;
470
0
            WINPR_ASSERT(lpcbData);
471
472
0
            cnv.b = lpData;
473
0
            size = *lpcbData;
474
0
            *lpcbData = (DWORD)length;
475
0
            if (size < length)
476
0
              status = ERROR_MORE_DATA;
477
0
            if (ConvertUtf8NToWChar(pValue->data.string, length, cnv.wc, length) < 0)
478
0
              status = ERROR_OUTOFMEMORY;
479
0
          }
480
0
          else if (lpcbData)
481
0
            *lpcbData = (UINT32)length;
482
483
0
          goto end;
484
0
        }
485
0
        default:
486
0
          WLog_WARN(TAG,
487
0
                    "Registry emulation does not support value type %s [0x%08" PRIx32 "]",
488
0
                    reg_type_string(pValue->type), pValue->type);
489
0
          break;
490
0
      }
491
0
    }
492
493
0
    pValue = pValue->next;
494
0
  }
495
496
0
end:
497
0
  free(valueName);
498
0
  return status;
499
0
}
500
501
// NOLINTBEGIN(readability-non-const-parameter)
502
LONG RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType,
503
                      LPBYTE lpData, LPDWORD lpcbData)
504
// NOLINTEND(readability-non-const-parameter)
505
0
{
506
0
  RegKey* key = NULL;
507
0
  RegVal* pValue = NULL;
508
509
0
  WINPR_UNUSED(lpReserved);
510
511
0
  key = (RegKey*)hKey;
512
0
  WINPR_ASSERT(key);
513
514
0
  pValue = key->values;
515
516
0
  while (pValue != NULL)
517
0
  {
518
0
    if (strcmp(pValue->name, lpValueName) == 0)
519
0
    {
520
0
      if (lpType)
521
0
        *lpType = pValue->type;
522
523
0
      switch (pValue->type)
524
0
      {
525
0
        case REG_DWORD_BIG_ENDIAN:
526
0
        case REG_QWORD:
527
0
        case REG_DWORD:
528
0
          return reg_read_int(pValue, lpData, lpcbData);
529
0
        case REG_SZ:
530
0
        {
531
0
          const size_t length = regsz_length(pValue->name, pValue->data.string, FALSE);
532
533
0
          char* pData = (char*)lpData;
534
535
0
          if (pData != NULL)
536
0
          {
537
0
            DWORD size = 0;
538
0
            WINPR_ASSERT(lpcbData);
539
540
0
            size = *lpcbData;
541
0
            *lpcbData = (DWORD)length;
542
0
            if (size < length)
543
0
              return ERROR_MORE_DATA;
544
0
            memcpy(pData, pValue->data.string, length);
545
0
            pData[length] = '\0';
546
0
          }
547
0
          else if (lpcbData)
548
0
            *lpcbData = (UINT32)length;
549
550
0
          return ERROR_SUCCESS;
551
0
        }
552
0
        default:
553
0
          WLog_WARN(TAG,
554
0
                    "Registry emulation does not support value type %s [0x%08" PRIx32 "]",
555
0
                    reg_type_string(pValue->type), pValue->type);
556
0
          break;
557
0
      }
558
0
    }
559
560
0
    pValue = pValue->next;
561
0
  }
562
563
0
  return ERROR_FILE_NOT_FOUND;
564
0
}
565
566
LONG RegRestoreKeyW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpFile,
567
                    WINPR_ATTR_UNUSED DWORD dwFlags)
568
0
{
569
0
  WLog_ERR(TAG, "TODO: Implement");
570
0
  return -1;
571
0
}
572
573
LONG RegRestoreKeyA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpFile,
574
                    WINPR_ATTR_UNUSED DWORD dwFlags)
575
0
{
576
0
  WLog_ERR(TAG, "TODO: Implement");
577
0
  return -1;
578
0
}
579
580
LONG RegSaveKeyExW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpFile,
581
                   WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpSecurityAttributes,
582
                   WINPR_ATTR_UNUSED DWORD Flags)
583
0
{
584
0
  WLog_ERR(TAG, "TODO: Implement");
585
0
  return -1;
586
0
}
587
588
LONG RegSaveKeyExA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpFile,
589
                   WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpSecurityAttributes,
590
                   WINPR_ATTR_UNUSED DWORD Flags)
591
0
{
592
0
  WLog_ERR(TAG, "TODO: Implement");
593
0
  return -1;
594
0
}
595
596
LONG RegSetKeySecurity(WINPR_ATTR_UNUSED HKEY hKey,
597
                       WINPR_ATTR_UNUSED SECURITY_INFORMATION SecurityInformation,
598
                       WINPR_ATTR_UNUSED PSECURITY_DESCRIPTOR pSecurityDescriptor)
599
0
{
600
0
  WLog_ERR(TAG, "TODO: Implement");
601
0
  return -1;
602
0
}
603
604
LONG RegSetValueExW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpValueName,
605
                    WINPR_ATTR_UNUSED DWORD Reserved, WINPR_ATTR_UNUSED DWORD dwType,
606
                    WINPR_ATTR_UNUSED const BYTE* lpData, WINPR_ATTR_UNUSED DWORD cbData)
607
0
{
608
0
  WLog_ERR(TAG, "TODO: Implement");
609
0
  return -1;
610
0
}
611
612
LONG RegSetValueExA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpValueName,
613
                    WINPR_ATTR_UNUSED DWORD Reserved, WINPR_ATTR_UNUSED DWORD dwType,
614
                    WINPR_ATTR_UNUSED const BYTE* lpData, WINPR_ATTR_UNUSED DWORD cbData)
615
0
{
616
0
  WLog_ERR(TAG, "TODO: Implement");
617
0
  return -1;
618
0
}
619
620
LONG RegUnLoadKeyW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpSubKey)
621
0
{
622
0
  WLog_ERR(TAG, "TODO: Implement");
623
0
  return -1;
624
0
}
625
626
LONG RegUnLoadKeyA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpSubKey)
627
0
{
628
0
  WLog_ERR(TAG, "TODO: Implement");
629
0
  return -1;
630
0
}
631
632
#endif