Coverage Report

Created: 2026-07-30 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/FreeRDP/winpr/libwinpr/registry/registry.c
Line
Count
Source
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 = nullptr;
46
47
static size_t regsz_length(const char* key, const void* value)
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 = strnlen((const char*)value, limit);
56
0
  if (length >= limit)
57
0
    WLog_WARN(TAG, "REG_SZ[%s] truncated to size %" PRIuz, key, length);
58
0
  return length;
59
0
}
60
61
static Reg* RegGetInstance(void)
62
0
{
63
0
  if (!instance)
64
0
    instance = reg_open(1);
65
66
0
  return instance;
67
0
}
68
69
LONG RegCloseKey(HKEY hKey)
70
0
{
71
0
  WINPR_UNUSED(hKey);
72
0
  return 0;
73
0
}
74
75
LONG RegCopyTreeW(WINPR_ATTR_UNUSED HKEY hKeySrc, WINPR_ATTR_UNUSED LPCWSTR lpSubKey,
76
                  WINPR_ATTR_UNUSED HKEY hKeyDest)
77
0
{
78
0
  WLog_ERR(TAG, "TODO: Implement");
79
0
  return -1;
80
0
}
81
82
LONG RegCopyTreeA(WINPR_ATTR_UNUSED HKEY hKeySrc, WINPR_ATTR_UNUSED LPCSTR lpSubKey,
83
                  WINPR_ATTR_UNUSED HKEY hKeyDest)
84
0
{
85
0
  WLog_ERR(TAG, "TODO: Implement");
86
0
  return -1;
87
0
}
88
89
LONG 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)
94
0
{
95
0
  WLog_ERR(TAG, "TODO: Implement");
96
0
  return -1;
97
0
}
98
99
LONG 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)
104
0
{
105
0
  WLog_ERR(TAG, "TODO: Implement");
106
0
  return -1;
107
0
}
108
109
LONG RegDeleteKeyExW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpSubKey,
110
                     WINPR_ATTR_UNUSED REGSAM samDesired, WINPR_ATTR_UNUSED DWORD Reserved)
111
0
{
112
0
  WLog_ERR(TAG, "TODO: Implement");
113
0
  return -1;
114
0
}
115
116
LONG RegDeleteKeyExA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpSubKey,
117
                     WINPR_ATTR_UNUSED REGSAM samDesired, WINPR_ATTR_UNUSED DWORD Reserved)
118
0
{
119
0
  WLog_ERR(TAG, "TODO: Implement");
120
0
  return -1;
121
0
}
122
123
LONG RegDeleteTreeW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpSubKey)
124
0
{
125
0
  WLog_ERR(TAG, "TODO: Implement");
126
0
  return -1;
127
0
}
128
129
LONG RegDeleteTreeA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpSubKey)
130
0
{
131
0
  WLog_ERR(TAG, "TODO: Implement");
132
0
  return -1;
133
0
}
134
135
LONG RegDeleteValueW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpValueName)
136
0
{
137
0
  WLog_ERR(TAG, "TODO: Implement");
138
0
  return -1;
139
0
}
140
141
LONG RegDeleteValueA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpValueName)
142
0
{
143
0
  WLog_ERR(TAG, "TODO: Implement");
144
0
  return -1;
145
0
}
146
147
LONG RegDisablePredefinedCacheEx(void)
148
0
{
149
0
  WLog_ERR(TAG, "TODO: Implement");
150
0
  return -1;
151
0
}
152
153
LONG 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)
158
0
{
159
0
  WLog_ERR(TAG, "TODO: Implement");
160
0
  return -1;
161
0
}
162
163
LONG 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)
168
0
{
169
0
  WLog_ERR(TAG, "TODO: Implement");
170
0
  return -1;
171
0
}
172
173
LONG 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)
177
0
{
178
0
  WLog_ERR(TAG, "TODO: Implement");
179
0
  return -1;
180
0
}
181
182
LONG 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)
186
0
{
187
0
  WLog_ERR(TAG, "TODO: Implement");
188
0
  return -1;
189
0
}
190
191
LONG RegFlushKey(WINPR_ATTR_UNUSED HKEY hKey)
192
0
{
193
0
  WLog_ERR(TAG, "TODO: Implement");
194
0
  return -1;
195
0
}
196
197
LONG 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)
201
0
{
202
0
  WLog_ERR(TAG, "TODO: Implement");
203
0
  return -1;
204
0
}
205
206
LONG 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)
210
0
{
211
0
  WLog_ERR(TAG, "TODO: Implement");
212
0
  return -1;
213
0
}
214
215
LONG 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)
219
0
{
220
0
  WLog_ERR(TAG, "TODO: Implement");
221
0
  return -1;
222
0
}
223
224
LONG 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)
227
0
{
228
0
  WLog_ERR(TAG, "TODO: Implement");
229
0
  return -1;
230
0
}
231
232
LONG 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)
235
0
{
236
0
  WLog_ERR(TAG, "TODO: Implement");
237
0
  return -1;
238
0
}
239
240
LONG RegLoadKeyW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpSubKey,
241
                 WINPR_ATTR_UNUSED LPCWSTR lpFile)
242
0
{
243
0
  WLog_ERR(TAG, "TODO: Implement");
244
0
  return -1;
245
0
}
246
247
LONG RegLoadKeyA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpSubKey,
248
                 WINPR_ATTR_UNUSED LPCSTR lpFile)
249
0
{
250
0
  WLog_ERR(TAG, "TODO: Implement");
251
0
  return -1;
252
0
}
253
254
LONG 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)
258
0
{
259
0
  WLog_ERR(TAG, "TODO: Implement");
260
0
  return -1;
261
0
}
262
263
LONG 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)
267
0
{
268
0
  WLog_ERR(TAG, "TODO: Implement");
269
0
  return -1;
270
0
}
271
272
LONG 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)
275
0
{
276
0
  WLog_ERR(TAG, "TODO: Implement");
277
0
  return -1;
278
0
}
279
280
LONG RegOpenCurrentUser(WINPR_ATTR_UNUSED REGSAM samDesired, WINPR_ATTR_UNUSED PHKEY phkResult)
281
0
{
282
0
  WLog_ERR(TAG, "TODO: Implement");
283
0
  return -1;
284
0
}
285
286
LONG RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
287
0
{
288
0
  LONG rc = 0;
289
0
  char* str = ConvertWCharToUtf8Alloc(lpSubKey, nullptr);
290
0
  if (!str)
291
0
    return ERROR_FILE_NOT_FOUND;
292
293
0
  rc = RegOpenKeyExA(hKey, str, ulOptions, samDesired, phkResult);
294
0
  free(str);
295
0
  return rc;
296
0
}
297
298
LONG RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, WINPR_ATTR_UNUSED DWORD ulOptions,
299
                   WINPR_ATTR_UNUSED REGSAM samDesired, PHKEY phkResult)
300
0
{
301
0
  Reg* reg = RegGetInstance();
302
303
0
  if (!reg)
304
0
    return -1;
305
306
0
  if (hKey != HKEY_LOCAL_MACHINE)
307
0
  {
308
0
    WLog_WARN(TAG, "Registry emulation only supports HKEY_LOCAL_MACHINE");
309
0
    return ERROR_FILE_NOT_FOUND;
310
0
  }
311
312
0
  WINPR_ASSERT(reg->root_key);
313
0
  RegKey* pKey = reg->root_key->subkeys;
314
315
0
  while (pKey != nullptr)
316
0
  {
317
0
    WINPR_ASSERT(lpSubKey);
318
319
0
    if (pKey->subname && (_stricmp(pKey->subname, lpSubKey) == 0))
320
0
    {
321
0
      *phkResult = (HKEY)pKey;
322
0
      return ERROR_SUCCESS;
323
0
    }
324
325
0
    pKey = pKey->next;
326
0
  }
327
328
0
  *phkResult = nullptr;
329
330
0
  return ERROR_FILE_NOT_FOUND;
331
0
}
332
333
LONG RegOpenUserClassesRoot(WINPR_ATTR_UNUSED HANDLE hToken, WINPR_ATTR_UNUSED DWORD dwOptions,
334
                            WINPR_ATTR_UNUSED REGSAM samDesired, WINPR_ATTR_UNUSED PHKEY phkResult)
335
0
{
336
0
  WLog_ERR(TAG, "TODO: Implement");
337
0
  return -1;
338
0
}
339
340
LONG 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)
349
0
{
350
0
  WLog_ERR(TAG, "TODO: Implement");
351
0
  return -1;
352
0
}
353
354
LONG 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)
363
0
{
364
0
  WLog_ERR(TAG, "TODO: Implement");
365
0
  return -1;
366
0
}
367
368
static LONG reg_read_int(const RegVal* pValue, LPBYTE lpData, LPDWORD lpcbData)
369
0
{
370
0
  const BYTE* ptr = nullptr;
371
0
  DWORD required = 0;
372
373
0
  WINPR_ASSERT(pValue);
374
375
0
  switch (pValue->type)
376
0
  {
377
0
    case REG_DWORD:
378
0
    case REG_DWORD_BIG_ENDIAN:
379
0
      required = sizeof(DWORD);
380
0
      ptr = (const BYTE*)&pValue->data.dword;
381
0
      break;
382
0
    case REG_QWORD:
383
0
      required = sizeof(UINT64);
384
0
      ptr = (const BYTE*)&pValue->data.qword;
385
0
      break;
386
0
    default:
387
0
      return ERROR_INTERNAL_ERROR;
388
0
  }
389
390
0
  if (lpcbData)
391
0
  {
392
0
    DWORD size = *lpcbData;
393
0
    *lpcbData = required;
394
0
    if (lpData)
395
0
    {
396
0
      if (size < *lpcbData)
397
0
        return ERROR_MORE_DATA;
398
0
    }
399
0
  }
400
401
0
  if (lpData != nullptr)
402
0
  {
403
0
    DWORD size = 0;
404
0
    WINPR_ASSERT(lpcbData);
405
406
0
    size = *lpcbData;
407
0
    *lpcbData = required;
408
0
    if (size < required)
409
0
      return ERROR_MORE_DATA;
410
0
    memcpy(lpData, ptr, required);
411
0
  }
412
0
  else if (lpcbData != nullptr)
413
0
    *lpcbData = required;
414
0
  return ERROR_SUCCESS;
415
0
}
416
417
// NOLINTBEGIN(readability-non-const-parameter)
418
LONG RegQueryValueExW(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType,
419
                      LPBYTE lpData, LPDWORD lpcbData)
420
// NOLINTEND(readability-non-const-parameter)
421
0
{
422
0
  LONG status = ERROR_FILE_NOT_FOUND;
423
0
  RegKey* key = nullptr;
424
0
  RegVal* pValue = nullptr;
425
0
  char* valueName = nullptr;
426
427
0
  WINPR_UNUSED(lpReserved);
428
429
0
  key = (RegKey*)hKey;
430
0
  WINPR_ASSERT(key);
431
432
0
  valueName = ConvertWCharToUtf8Alloc(lpValueName, nullptr);
433
0
  if (!valueName)
434
0
    goto end;
435
436
0
  pValue = key->values;
437
438
0
  while (pValue != nullptr)
439
0
  {
440
0
    if (strcmp(pValue->name, valueName) == 0)
441
0
    {
442
0
      if (lpType)
443
0
        *lpType = pValue->type;
444
445
0
      switch (pValue->type)
446
0
      {
447
0
        case REG_DWORD_BIG_ENDIAN:
448
0
        case REG_QWORD:
449
0
        case REG_DWORD:
450
0
          status = reg_read_int(pValue, lpData, lpcbData);
451
0
          goto end;
452
0
        case REG_SZ:
453
0
        {
454
0
          const size_t length =
455
0
              regsz_length(pValue->name, pValue->data.string) * sizeof(WCHAR);
456
457
0
          status = ERROR_SUCCESS;
458
0
          if (lpData != nullptr)
459
0
          {
460
0
            DWORD size = 0;
461
0
            union
462
0
            {
463
0
              WCHAR* wc;
464
0
              BYTE* b;
465
0
            } cnv;
466
0
            WINPR_ASSERT(lpcbData);
467
468
0
            cnv.b = lpData;
469
0
            size = *lpcbData;
470
0
            *lpcbData = (DWORD)length;
471
0
            if (size < length)
472
0
              status = ERROR_MORE_DATA;
473
0
            if (ConvertUtf8NToWChar(pValue->data.string, length, cnv.wc, length) < 0)
474
0
              status = ERROR_OUTOFMEMORY;
475
0
          }
476
0
          else if (lpcbData)
477
0
            *lpcbData = (UINT32)length;
478
479
0
          goto end;
480
0
        }
481
0
        default:
482
0
          WLog_WARN(TAG,
483
0
                    "Registry emulation does not support value type %s [0x%08" PRIx32 "]",
484
0
                    reg_type_string(pValue->type), pValue->type);
485
0
          break;
486
0
      }
487
0
    }
488
489
0
    pValue = pValue->next;
490
0
  }
491
492
0
end:
493
0
  free(valueName);
494
0
  return status;
495
0
}
496
497
// NOLINTBEGIN(readability-non-const-parameter)
498
LONG RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType,
499
                      LPBYTE lpData, LPDWORD lpcbData)
500
// NOLINTEND(readability-non-const-parameter)
501
0
{
502
0
  RegKey* key = nullptr;
503
0
  RegVal* pValue = nullptr;
504
505
0
  WINPR_UNUSED(lpReserved);
506
507
0
  key = (RegKey*)hKey;
508
0
  WINPR_ASSERT(key);
509
510
0
  pValue = key->values;
511
512
0
  while (pValue != nullptr)
513
0
  {
514
0
    if (strcmp(pValue->name, lpValueName) == 0)
515
0
    {
516
0
      if (lpType)
517
0
        *lpType = pValue->type;
518
519
0
      switch (pValue->type)
520
0
      {
521
0
        case REG_DWORD_BIG_ENDIAN:
522
0
        case REG_QWORD:
523
0
        case REG_DWORD:
524
0
          return reg_read_int(pValue, lpData, lpcbData);
525
0
        case REG_SZ:
526
0
        {
527
0
          const size_t length = regsz_length(pValue->name, pValue->data.string);
528
529
0
          char* pData = (char*)lpData;
530
531
0
          if (pData != nullptr)
532
0
          {
533
0
            DWORD size = 0;
534
0
            WINPR_ASSERT(lpcbData);
535
536
0
            size = *lpcbData;
537
0
            *lpcbData = (DWORD)length;
538
0
            if (size < length)
539
0
              return ERROR_MORE_DATA;
540
0
            memcpy(pData, pValue->data.string, length);
541
0
            pData[length] = '\0';
542
0
          }
543
0
          else if (lpcbData)
544
0
            *lpcbData = (UINT32)length;
545
546
0
          return ERROR_SUCCESS;
547
0
        }
548
0
        default:
549
0
          WLog_WARN(TAG,
550
0
                    "Registry emulation does not support value type %s [0x%08" PRIx32 "]",
551
0
                    reg_type_string(pValue->type), pValue->type);
552
0
          break;
553
0
      }
554
0
    }
555
556
0
    pValue = pValue->next;
557
0
  }
558
559
0
  return ERROR_FILE_NOT_FOUND;
560
0
}
561
562
LONG RegRestoreKeyW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpFile,
563
                    WINPR_ATTR_UNUSED DWORD dwFlags)
564
0
{
565
0
  WLog_ERR(TAG, "TODO: Implement");
566
0
  return -1;
567
0
}
568
569
LONG RegRestoreKeyA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpFile,
570
                    WINPR_ATTR_UNUSED DWORD dwFlags)
571
0
{
572
0
  WLog_ERR(TAG, "TODO: Implement");
573
0
  return -1;
574
0
}
575
576
LONG RegSaveKeyExW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpFile,
577
                   WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpSecurityAttributes,
578
                   WINPR_ATTR_UNUSED DWORD Flags)
579
0
{
580
0
  WLog_ERR(TAG, "TODO: Implement");
581
0
  return -1;
582
0
}
583
584
LONG RegSaveKeyExA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpFile,
585
                   WINPR_ATTR_UNUSED LPSECURITY_ATTRIBUTES lpSecurityAttributes,
586
                   WINPR_ATTR_UNUSED DWORD Flags)
587
0
{
588
0
  WLog_ERR(TAG, "TODO: Implement");
589
0
  return -1;
590
0
}
591
592
LONG RegSetKeySecurity(WINPR_ATTR_UNUSED HKEY hKey,
593
                       WINPR_ATTR_UNUSED SECURITY_INFORMATION SecurityInformation,
594
                       WINPR_ATTR_UNUSED PSECURITY_DESCRIPTOR pSecurityDescriptor)
595
0
{
596
0
  WLog_ERR(TAG, "TODO: Implement");
597
0
  return -1;
598
0
}
599
600
LONG 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)
603
0
{
604
0
  WLog_ERR(TAG, "TODO: Implement");
605
0
  return -1;
606
0
}
607
608
LONG 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)
611
0
{
612
0
  WLog_ERR(TAG, "TODO: Implement");
613
0
  return -1;
614
0
}
615
616
LONG RegUnLoadKeyW(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCWSTR lpSubKey)
617
0
{
618
0
  WLog_ERR(TAG, "TODO: Implement");
619
0
  return -1;
620
0
}
621
622
LONG RegUnLoadKeyA(WINPR_ATTR_UNUSED HKEY hKey, WINPR_ATTR_UNUSED LPCSTR lpSubKey)
623
0
{
624
0
  WLog_ERR(TAG, "TODO: Implement");
625
0
  return -1;
626
0
}
627
628
#endif