ReactOS 0.4.17-dev-243-g1369312
querysrc.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Shell
3 * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4 * PURPOSE: Implement QuerySourceCreateFromKey
5 * COPYRIGHT: Copyright 2026 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6 */
7
8#include "precomp.h"
9#include <shlwapi.h>
10#include <shlwapi_undoc.h>
11#include <shlobj_undoc.h>
12#include <shlguid_undoc.h>
13
15
16static HRESULT SHAllocBlob(ULONG cbData, const BYTE *pbData, FLAGGED_BYTE_BLOB** ppBlob)
17{
18 FLAGGED_BYTE_BLOB* pBlob =
19 (FLAGGED_BYTE_BLOB*)CoTaskMemAlloc(sizeof(FLAGGED_BYTE_BLOB) + cbData);
20 if (!pBlob)
21 return E_OUTOFMEMORY;
22
23 pBlob->clSize = cbData;
24 if (pbData)
25 CopyMemory(pBlob->abData, pbData, cbData);
26
27 *ppBlob = pBlob;
28 return S_OK;
29}
30
31class CRegistrySource;
32
33/******************************************************************************
34 * CRegistryEnumBase
35 */
37{
38protected:
44 WCHAR m_szBuf[64] = {};
46
47 BOOL _Next(PWSTR *ppwsz);
48 virtual BOOL _RegNext(DWORD dwIndex) = 0;
49 virtual DWORD _MaxLen() = 0;
50
51public:
52 virtual ~CRegistryEnumBase();
53
55
56 // IUnknown methods
57 STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) override;
60 // IEnumString methods
61 STDMETHODIMP Next(ULONG celt, LPWSTR* rgelt, ULONG* pceltFetched) override;
62 STDMETHODIMP Skip(ULONG celt) override;
63 STDMETHODIMP Reset() override;
64 STDMETHODIMP Clone(IEnumString ** ppenum) override;
65};
66
67/******************************************************************************
68 * CRegistryEnumValues
69 */
71{
72public:
73 BOOL _RegNext(DWORD dwIndex) override;
74 DWORD _MaxLen() override;
75};
76
77/******************************************************************************
78 * CRegistryEnumKeys
79 */
81{
82public:
83 BOOL _RegNext(DWORD dwIndex) override;
84 DWORD _MaxLen() override;
85};
86
87/******************************************************************************
88 * CRegistrySource
89 */
91 : public IQuerySourceOld
92 , public IObjectWithRegistryKeyOld
93{
96
97public:
98 virtual ~CRegistrySource();
99
101
102 // IUnknown methods
103 STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) override;
106 // IQuerySourceOld methods
107 STDMETHODIMP EnumValues(IEnumString **ppEnum) override;
108 STDMETHODIMP EnumSources(IEnumString **ppEnum) override;
109 STDMETHODIMP QueryValueString(PCWSTR keyName, PCWSTR valueName, PWSTR *ppszValue) override;
110 STDMETHODIMP QueryValueDword(PCWSTR keyName, PCWSTR valueName, DWORD *pdwValue) override;
111 STDMETHODIMP QueryValueExists(PCWSTR keyName, PCWSTR valueName) override;
112 STDMETHODIMP QueryValueDirect(PCWSTR keyName, PCWSTR valueName,
113 FLAGGED_BYTE_BLOB **ppBlob) override;
114 STDMETHODIMP OpenSource(PCWSTR keyName, BOOL bCreate, IQuerySourceOld **ppSource) override;
115 STDMETHODIMP SetValueDirect(PCWSTR keyName, PCWSTR valueName, DWORD dwType, DWORD cbData,
116 LPCVOID pvData) override;
117 // IObjectWithRegistryKeyOld methods
118 STDMETHODIMP SetKey(HKEY hKey) override;
119 STDMETHODIMP GetKey(HKEY *phKey) override;
120};
121
122/******************************************************************************/
123
125{
126 if (m_pszName && m_pszName != m_szBuf)
128 if (m_pSource)
129 m_pSource->Release();
130}
131
133{
134 m_hKey = hKey;
135 m_pSource = pSource;
136 m_pSource->AddRef();
139 {
141 }
142 else
143 {
146 }
147 return m_pszName ? S_OK : E_OUTOFMEMORY;
148}
149
151{
152 return _RegNext(m_dwIndex) && SUCCEEDED(SHStrDupW(m_pszName, ppwsz));
153}
154
156{
157 if (!ppv)
158 return E_POINTER;
159
160 if (riid == IID_IEnumString)
161 {
162 *ppv = static_cast<IEnumString*>(this);
163 AddRef();
164 return S_OK;
165 }
166 return E_NOINTERFACE;
167}
168
170{
171 return ::InterlockedIncrement(&m_cRefs);
172}
173
175{
177 if (!refs)
178 delete this;
179 return refs;
180}
181
183{
184 if (!rgelt || (celt > 1 && !pceltFetched))
185 return E_INVALIDARG;
186
187 ULONG cFetched = 0;
188
189 while (cFetched < celt)
190 {
191 if (!_Next(&rgelt[cFetched]))
192 break;
193 ++m_dwIndex;
194 ++cFetched;
195 }
196
197 if (pceltFetched)
198 *pceltFetched = cFetched;
199
200 return (cFetched == celt) ? S_OK : S_FALSE;
201}
202
204{
205 return E_NOTIMPL;
206}
207
209{
210 m_dwIndex = 0;
211 return S_OK;
212}
213
215{
216 return E_NOTIMPL;
217}
218
219/******************************************************************************/
220
222{
224}
225
227{
228 DWORD cchKeyNameMax = 0;
229 RegQueryInfoKeyW(m_hKey, NULL, NULL, NULL, NULL, &cchKeyNameMax, NULL, NULL, NULL, NULL,
230 NULL, NULL);
231 return cchKeyNameMax + 1; // Including NUL
232}
233
234/******************************************************************************/
235
237{
238 DWORD cchValueNameMax = m_cchNameMax;
239 return RegEnumValueW(m_hKey, dwIndex, m_pszName, &cchValueNameMax, NULL,
241}
242
244{
245 DWORD cchValueNameMax = 0;
246 RegQueryInfoKeyW(m_hKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &cchValueNameMax,
247 NULL, NULL, NULL);
248 return cchValueNameMax + 1; // Including NUL
249}
250
251/******************************************************************************/
252
254{
255 if (m_hKey)
257}
258
260{
262 if (bCreate)
264 else
266
268}
269
271{
272 if (!ppvObject)
273 return E_POINTER;
274
275 if (riid == IID_IQuerySourceOld)
276 {
277 *ppvObject = static_cast<IQuerySourceOld*>(this);
278 AddRef();
279 return S_OK;
280 }
281
282 if (riid == IID_IObjectWithRegistryKeyOld)
283 {
284 *ppvObject = static_cast<IObjectWithRegistryKeyOld*>(this);
285 AddRef();
286 return S_OK;
287 }
288
289 *ppvObject = NULL;
290 return E_NOINTERFACE;
291}
292
293STDMETHODIMP_(ULONG) CRegistrySource::AddRef()
294{
295 return ::InterlockedIncrement(&m_cRefs);
296}
297
298STDMETHODIMP_(ULONG) CRegistrySource::Release()
299{
301 if (!refs)
302 delete this;
303 return refs;
304}
305
307{
309 HRESULT hr = pEnum->Init(m_hKey, this);
310 if (FAILED(hr))
311 {
312 pEnum->Release();
313 pEnum = NULL;
314 }
315 *ppEnum = pEnum;
316 return pEnum ? S_OK : E_OUTOFMEMORY;
317}
318
320{
322 HRESULT hr = pEnum->Init(m_hKey, this);
323 if (FAILED(hr))
324 {
325 pEnum->Release();
326 pEnum = NULL;
327 }
328 *ppEnum = pEnum;
329 return pEnum ? S_OK : E_OUTOFMEMORY;
330}
331
333 PCWSTR keyName,
334 PCWSTR valueName,
335 PWSTR *ppszValue)
336{
337 *ppszValue = NULL;
338
339 WCHAR szData[128];
340 DWORD dwType = REG_NONE, cbData = sizeof(szData);
341 LSTATUS error = SHGetValueW(m_hKey, keyName, valueName, &dwType, szData, &cbData);
342 if (error == ERROR_SUCCESS)
343 {
344 if (dwType != REG_SZ)
345 return E_DATATYPE_MISMATCH;
346 if (!valueName && !szData[0])
348 return SHStrDupW(szData, ppszValue);
349 }
350
351 if (error != ERROR_MORE_DATA)
353
354 *ppszValue = (PWSTR)CoTaskMemAlloc(cbData);
355 if (!*ppszValue)
356 return E_OUTOFMEMORY;
357
358 HRESULT hr = S_OK;
359 error = SHGetValueW(m_hKey, keyName, valueName, &dwType, *ppszValue, &cbData);
360 if (error)
361 {
362 CoTaskMemFree(*ppszValue);
363 *ppszValue = NULL;
365 }
366
367 if (SUCCEEDED(hr) && dwType != REG_SZ)
368 {
369 CoTaskMemFree(*ppszValue);
370 *ppszValue = NULL;
372 }
373
374 return hr;
375}
376
378{
379 DWORD dwType, cbValue = sizeof(*pdwValue);
380 LSTATUS error = SHGetValueW(m_hKey, keyName, valueName, &dwType, pdwValue, &cbValue);
381 if (error)
383 if (dwType != REG_DWORD)
384 return E_DATATYPE_MISMATCH;
385 return S_OK;
386}
387
389{
390 LSTATUS error = SHGetValueW(m_hKey, keyName, valueName, NULL, NULL, NULL);
391 if (error)
393 return S_OK;
394}
395
397 PCWSTR keyName,
398 PCWSTR valueName,
399 FLAGGED_BYTE_BLOB **ppBlob)
400{
401 HRESULT hr = E_FAIL;
402 HKEY hKey = m_hKey;
403 DWORD dwType = REG_NONE;
404 DWORD cbData = 256;
405 BYTE abData[256];
406
407 *ppBlob = NULL;
408
409 if (keyName && *keyName &&
411 {
412 return E_FAIL;
413 }
414
415 LSTATUS error = RegQueryValueExW(hKey, valueName, NULL, &dwType, abData, &cbData);
416 if (error == ERROR_SUCCESS)
417 {
418 hr = SHAllocBlob(cbData, abData, ppBlob);
419 }
420 else if (error == ERROR_MORE_DATA)
421 {
422 hr = SHAllocBlob(cbData, NULL, ppBlob);
423 if (SUCCEEDED(hr))
424 {
425 error = RegQueryValueExW(hKey, valueName, NULL, &dwType, (*ppBlob)->abData, &cbData);
426 if (error != ERROR_SUCCESS)
427 {
428 CoTaskMemFree(*ppBlob);
429 *ppBlob = NULL;
431 }
432 }
433 }
434 else
435 {
437 }
438
439 if (hKey != m_hKey)
441
442 if (SUCCEEDED(hr))
443 (*ppBlob)->fFlags = dwType;
444
445 return hr;
446}
447
448STDMETHODIMP CRegistrySource::OpenSource(PCWSTR keyName, BOOL bCreate, IQuerySourceOld **ppSource)
449{
450 return QuerySourceCreateFromKey(m_hKey, keyName, bCreate, IID_IQuerySourceOld, (PVOID*)ppSource);
451}
452
454 PCWSTR keyName,
455 PCWSTR valueName,
456 DWORD dwType,
459{
460 LSTATUS error = SHSetValueW(m_hKey, keyName, valueName, dwType, pvData, cbData);
461 if (error)
463 return S_OK;
464}
465
467{
468 if (m_hKey)
469 return E_UNEXPECTED;
470
472 return m_hKey ? S_OK : E_UNEXPECTED;
473}
474
476{
477 if (!m_hKey)
478 return E_UNEXPECTED;
479
480 *phKey = SHRegDuplicateHKey(m_hKey);
481 if (!*phKey)
482 return E_UNEXPECTED;
483
484 return S_OK;
485}
486
487/**************************************************************************
488 * QuerySourceCreateFromKey (SHLWAPI.544)
489 *
490 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/regsrc/createfromkey.htm
491 */
495 _In_ HKEY hKey,
496 _In_opt_ PCWSTR lpSubKey,
500{
501 *ppv = NULL;
502
503 CRegistrySource* pRS = new CRegistrySource();
504
505 HRESULT hr = pRS->Init(hKey, lpSubKey, bCreate);
506 if (SUCCEEDED(hr))
507 hr = pRS->QueryInterface(riid, ppv);
508
509 pRS->Release();
510 return hr;
511}
#define InterlockedDecrement
Definition: armddk.h:52
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
void shell(int argc, const char *argv[])
Definition: cmds.c:1231
#define EXTERN_C
Definition: basetyps.h:12
#define STDMETHODIMP
Definition: basetyps.h:43
#define STDMETHODIMP_(t)
Definition: basetyps.h:44
#define RegCloseKey(hKey)
Definition: registry.h:49
_In_ BOOLEAN Release
Definition: cdrom.h:920
HRESULT Init(HKEY hKey, CRegistrySource *pSource)
Definition: querysrc.cpp:132
STDMETHODIMP Skip(ULONG celt) override
Definition: querysrc.cpp:203
BOOL _Next(PWSTR *ppwsz)
Definition: querysrc.cpp:150
STDMETHODIMP Reset() override
Definition: querysrc.cpp:208
WCHAR m_szBuf[64]
Definition: querysrc.cpp:44
STDMETHODIMP Clone(IEnumString **ppenum) override
Definition: querysrc.cpp:214
CRegistrySource * m_pSource
Definition: querysrc.cpp:41
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) override
Definition: querysrc.cpp:155
virtual BOOL _RegNext(DWORD dwIndex)=0
STDMETHODIMP_(ULONG) Release() override
STDMETHODIMP_(ULONG) AddRef() override
virtual DWORD _MaxLen()=0
virtual ~CRegistryEnumBase()
Definition: querysrc.cpp:124
STDMETHODIMP Next(ULONG celt, LPWSTR *rgelt, ULONG *pceltFetched) override
Definition: querysrc.cpp:182
DWORD _MaxLen() override
Definition: querysrc.cpp:226
BOOL _RegNext(DWORD dwIndex) override
Definition: querysrc.cpp:221
BOOL _RegNext(DWORD dwIndex) override
Definition: querysrc.cpp:236
DWORD _MaxLen() override
Definition: querysrc.cpp:243
STDMETHODIMP QueryValueDirect(PCWSTR keyName, PCWSTR valueName, FLAGGED_BYTE_BLOB **ppBlob) override
Definition: querysrc.cpp:396
STDMETHODIMP QueryValueExists(PCWSTR keyName, PCWSTR valueName) override
Definition: querysrc.cpp:388
STDMETHODIMP OpenSource(PCWSTR keyName, BOOL bCreate, IQuerySourceOld **ppSource) override
Definition: querysrc.cpp:448
STDMETHODIMP SetKey(HKEY hKey) override
Definition: querysrc.cpp:466
HRESULT Init(HKEY hKey, PCWSTR pszSubKey, BOOL bCreate)
Definition: querysrc.cpp:259
STDMETHODIMP EnumSources(IEnumString **ppEnum) override
Definition: querysrc.cpp:319
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) override
Definition: querysrc.cpp:270
STDMETHODIMP QueryValueString(PCWSTR keyName, PCWSTR valueName, PWSTR *ppszValue) override
Definition: querysrc.cpp:332
virtual ~CRegistrySource()
Definition: querysrc.cpp:253
STDMETHODIMP QueryValueDword(PCWSTR keyName, PCWSTR valueName, DWORD *pdwValue) override
Definition: querysrc.cpp:377
STDMETHODIMP_(ULONG) Release() override
STDMETHODIMP SetValueDirect(PCWSTR keyName, PCWSTR valueName, DWORD dwType, DWORD cbData, LPCVOID pvData) override
Definition: querysrc.cpp:453
STDMETHODIMP GetKey(HKEY *phKey) override
Definition: querysrc.cpp:475
STDMETHODIMP_(ULONG) AddRef() override
STDMETHODIMP EnumValues(IEnumString **ppEnum) override
Definition: querysrc.cpp:306
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
HRESULT hr
Definition: delayimp.cpp:582
#define ERROR_SUCCESS
Definition: deptool.c:10
static LSTATUS(WINAPI *pRegDeleteTreeW)(HKEY
#define NULL
Definition: types.h:112
LONG WINAPI RegCreateKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD Reserved, _In_opt_ LPWSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_opt_ LPDWORD lpdwDisposition)
Definition: reg.c:1096
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegEnumValueW(_In_ HKEY hKey, _In_ DWORD index, _Out_ LPWSTR value, _Inout_ PDWORD val_count, _Reserved_ PDWORD reserved, _Out_opt_ PDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ PDWORD count)
Definition: reg.c:2830
LONG WINAPI RegQueryInfoKeyW(HKEY hKey, LPWSTR lpClass, LPDWORD lpcClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcMaxSubKeyLen, LPDWORD lpcMaxClassLen, LPDWORD lpcValues, LPDWORD lpcMaxValueNameLen, LPDWORD lpcMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime)
Definition: reg.c:3662
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
LONG WINAPI RegEnumKeyW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, DWORD cbName)
Definition: reg.c:2393
DWORD WINAPI SHGetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue, LPDWORD pwType, LPVOID pvData, LPDWORD pcbData)
Definition: reg.c:1278
HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
Definition: reg.c:2256
DWORD WINAPI SHSetValueW(HKEY hKey, LPCWSTR lpszSubKey, LPCWSTR lpszValue, DWORD dwType, LPCVOID pvData, DWORD cbData)
Definition: reg.c:1348
HRESULT WINAPI SHStrDupW(LPCWSTR src, LPWSTR *dest)
Definition: string.c:2148
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
FxAutoRegKey hKey
HLOCAL NTAPI LocalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:1390
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
ULONG AddRef()
ULONG Release()
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define REG_SZ
Definition: layer.c:22
void *WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: malloc.c:381
void WINAPI CoTaskMemFree(void *ptr)
Definition: malloc.c:389
#define LPTR
Definition: minwinbase.h:93
#define CopyMemory
Definition: minwinbase.h:29
CONST void * LPCVOID
Definition: minwindef.h:164
#define error(str)
Definition: mkdosfs.c:1605
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
static ULONG WINAPI AddRef(IStream *iface)
Definition: clist.c:83
_In_ LPWSTR _In_ DWORD _In_ LPCVOID pvData
Definition: netsh.h:116
#define _Outptr_
Definition: no_sal2.h:262
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#define KEY_READ
Definition: nt_native.h:1026
#define REG_NONE
Definition: nt_native.h:1495
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
const GUID IID_IEnumString
short WCHAR
Definition: pedump.c:58
long LONG
Definition: pedump.c:60
#define REFIID
Definition: guiddef.h:118
_In_opt_ _In_opt_ _In_ _In_ DWORD cbData
Definition: shlwapi.h:761
_In_opt_ LPCSTR pszSubKey
Definition: shlwapi.h:783
EXTERN_C HRESULT WINAPI QuerySourceCreateFromKey(_In_ HKEY hKey, _In_opt_ PCWSTR lpSubKey, _In_ BOOL bCreate, _In_ REFIID riid, _Outptr_ PVOID *ppv)
Definition: querysrc.cpp:494
static HRESULT SHAllocBlob(ULONG cbData, const BYTE *pbData, FLAGGED_BYTE_BLOB **ppBlob)
Definition: querysrc.cpp:16
#define REG_DWORD
Definition: sdbapi.c:615
_In_ int _In_ BOOL bCreate
Definition: shlobj.h:1527
#define E_DATATYPE_MISMATCH
#define _countof(array)
Definition: sndvol32.h:70
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
uint16_t * LPWSTR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:3451
static HRESULT HRESULT_FROM_WIN32(unsigned int x)
Definition: winerror.h:210
#define E_NOINTERFACE
Definition: winerror.h:3479
#define E_UNEXPECTED
Definition: winerror.h:3528
#define E_POINTER
Definition: winerror.h:3480
unsigned char BYTE
Definition: xxhash.c:193