Coverage Report

Created: 2024-05-20 06:11

/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
206k
{
48
206k
  if (!instance)
49
206k
    instance = reg_open(1);
50
51
206k
  return instance;
52
206k
}
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
206k
{
252
206k
  Reg* reg = RegGetInstance();
253
254
206k
  if (!reg)
255
206k
    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
          return reg_read_int(pValue, lpData, lpcbData);
389
0
        case REG_SZ:
390
0
        {
391
0
          const size_t length = strnlen(pValue->data.string, UINT32_MAX) * sizeof(WCHAR);
392
393
0
          if (lpData != NULL)
394
0
          {
395
0
            DWORD size = 0;
396
0
            union
397
0
            {
398
0
              WCHAR* wc;
399
0
              BYTE* b;
400
0
            } cnv;
401
0
            WINPR_ASSERT(lpcbData);
402
403
0
            cnv.b = lpData;
404
0
            size = *lpcbData;
405
0
            *lpcbData = (DWORD)length;
406
0
            if (size < length)
407
0
              return ERROR_MORE_DATA;
408
0
            if (ConvertUtf8NToWChar(pValue->data.string, length, cnv.wc, length) < 0)
409
0
              return ERROR_OUTOFMEMORY;
410
0
          }
411
0
          else if (lpcbData)
412
0
            *lpcbData = (UINT32)length;
413
414
0
          status = ERROR_SUCCESS;
415
0
          goto end;
416
0
        }
417
0
        default:
418
0
          WLog_WARN(TAG,
419
0
                    "Registry emulation does not support value type %s [0x%08" PRIx32 "]",
420
0
                    reg_type_string(pValue->type), pValue->type);
421
0
          break;
422
0
      }
423
0
    }
424
425
0
    pValue = pValue->next;
426
0
  }
427
428
0
end:
429
0
  free(valueName);
430
0
  return status;
431
0
}
432
433
LONG RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType,
434
                      LPBYTE lpData, LPDWORD lpcbData)
435
0
{
436
0
  RegKey* key = NULL;
437
0
  RegVal* pValue = NULL;
438
439
0
  WINPR_UNUSED(lpReserved);
440
441
0
  key = (RegKey*)hKey;
442
0
  WINPR_ASSERT(key);
443
444
0
  pValue = key->values;
445
446
0
  while (pValue != NULL)
447
0
  {
448
0
    if (strcmp(pValue->name, lpValueName) == 0)
449
0
    {
450
0
      if (lpType)
451
0
        *lpType = pValue->type;
452
453
0
      switch (pValue->type)
454
0
      {
455
0
        case REG_DWORD_BIG_ENDIAN:
456
0
        case REG_QWORD:
457
0
        case REG_DWORD:
458
0
          return reg_read_int(pValue, lpData, lpcbData);
459
0
        case REG_SZ:
460
0
        {
461
0
          const size_t length = strnlen(pValue->data.string, UINT32_MAX);
462
0
          char* pData = (char*)lpData;
463
464
0
          if (pData != NULL)
465
0
          {
466
0
            DWORD size = 0;
467
0
            WINPR_ASSERT(lpcbData);
468
469
0
            size = *lpcbData;
470
0
            *lpcbData = (DWORD)length;
471
0
            if (size < length)
472
0
              return ERROR_MORE_DATA;
473
0
            memcpy(pData, pValue->data.string, length);
474
0
            pData[length] = '\0';
475
0
          }
476
0
          else if (lpcbData)
477
0
            *lpcbData = (UINT32)length;
478
479
0
          return ERROR_SUCCESS;
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
  return ERROR_FILE_NOT_FOUND;
493
0
}
494
495
LONG RegRestoreKeyW(HKEY hKey, LPCWSTR lpFile, DWORD dwFlags)
496
0
{
497
0
  WLog_ERR(TAG, "TODO: Implement");
498
0
  return -1;
499
0
}
500
501
LONG RegRestoreKeyA(HKEY hKey, LPCSTR lpFile, DWORD dwFlags)
502
0
{
503
0
  WLog_ERR(TAG, "TODO: Implement");
504
0
  return -1;
505
0
}
506
507
LONG RegSaveKeyExW(HKEY hKey, LPCWSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
508
                   DWORD Flags)
509
0
{
510
0
  WLog_ERR(TAG, "TODO: Implement");
511
0
  return -1;
512
0
}
513
514
LONG RegSaveKeyExA(HKEY hKey, LPCSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
515
                   DWORD Flags)
516
0
{
517
0
  WLog_ERR(TAG, "TODO: Implement");
518
0
  return -1;
519
0
}
520
521
LONG RegSetKeySecurity(HKEY hKey, SECURITY_INFORMATION SecurityInformation,
522
                       PSECURITY_DESCRIPTOR pSecurityDescriptor)
523
0
{
524
0
  WLog_ERR(TAG, "TODO: Implement");
525
0
  return -1;
526
0
}
527
528
LONG RegSetValueExW(HKEY hKey, LPCWSTR lpValueName, DWORD Reserved, DWORD dwType,
529
                    const BYTE* lpData, DWORD cbData)
530
0
{
531
0
  WLog_ERR(TAG, "TODO: Implement");
532
0
  return -1;
533
0
}
534
535
LONG RegSetValueExA(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, const BYTE* lpData,
536
                    DWORD cbData)
537
0
{
538
0
  WLog_ERR(TAG, "TODO: Implement");
539
0
  return -1;
540
0
}
541
542
LONG RegUnLoadKeyW(HKEY hKey, LPCWSTR lpSubKey)
543
0
{
544
0
  WLog_ERR(TAG, "TODO: Implement");
545
0
  return -1;
546
0
}
547
548
LONG RegUnLoadKeyA(HKEY hKey, LPCSTR lpSubKey)
549
0
{
550
0
  WLog_ERR(TAG, "TODO: Implement");
551
0
  return -1;
552
0
}
553
554
#endif