Coverage Report

Created: 2024-09-08 06:20

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