ReactOS 0.4.17-dev-357-ga8f14ff
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#include <new>
14
16
17static HRESULT SHAllocBlob(ULONG cbData, const BYTE *pbData, FLAGGED_BYTE_BLOB** ppBlob)
18{
19 FLAGGED_BYTE_BLOB* pBlob =
20 (FLAGGED_BYTE_BLOB*)CoTaskMemAlloc(sizeof(FLAGGED_BYTE_BLOB) + cbData);
21 if (!pBlob)
22 return E_OUTOFMEMORY;
23
24 pBlob->clSize = cbData;
25 if (pbData)
26 CopyMemory(pBlob->abData, pbData, cbData);
27
28 *ppBlob = pBlob;
29 return S_OK;
30}
31
32class CRegistrySource;
33
34/******************************************************************************
35 * CRegistryEnumBase
36 */
38{
39protected:
45 WCHAR m_szBuf[64] = {};
47
48 BOOL _Next(PWSTR *ppwsz);
49 virtual BOOL _RegNext(DWORD dwIndex) = 0;
50 virtual DWORD _MaxLen() = 0;
51
52public:
53 virtual ~CRegistryEnumBase();
54
56
57 // IUnknown methods
58 STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) override;
61 // IEnumString methods
62 STDMETHODIMP Next(ULONG celt, LPWSTR* rgelt, ULONG* pceltFetched) override;
63 STDMETHODIMP Skip(ULONG celt) override;
64 STDMETHODIMP Reset() override;
65 STDMETHODIMP Clone(IEnumString ** ppenum) override;
66};
67
68/******************************************************************************
69 * CRegistryEnumValues
70 */
72{
73public:
74 BOOL _RegNext(DWORD dwIndex) override;
75 DWORD _MaxLen() override;
76};
77
78/******************************************************************************
79 * CRegistryEnumKeys
80 */
82{
83public:
84 BOOL _RegNext(DWORD dwIndex) override;
85 DWORD _MaxLen() override;
86};
87
88/******************************************************************************
89 * CRegistrySource
90 */
92 : public IQuerySourceOld
93 , public IObjectWithRegistryKeyOld
94{
97
98public:
99 virtual ~CRegistrySource();
100
102
103 // IUnknown methods
104 STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) override;
107 // IQuerySourceOld methods
108 STDMETHODIMP EnumValues(IEnumString **ppEnum) override;
109 STDMETHODIMP EnumSources(IEnumString **ppEnum) override;
110 STDMETHODIMP QueryValueString(PCWSTR keyName, PCWSTR valueName, PWSTR *ppszValue) override;
111 STDMETHODIMP QueryValueDword(PCWSTR keyName, PCWSTR valueName, DWORD *pdwValue) override;
112 STDMETHODIMP QueryValueExists(PCWSTR keyName, PCWSTR valueName) override;
113 STDMETHODIMP QueryValueDirect(PCWSTR keyName, PCWSTR valueName,
114 FLAGGED_BYTE_BLOB **ppBlob) override;
115 STDMETHODIMP OpenSource(PCWSTR keyName, BOOL bCreate, IQuerySourceOld **ppSource) override;
116 STDMETHODIMP SetValueDirect(PCWSTR keyName, PCWSTR valueName, DWORD dwType, DWORD cbData,
117 LPCVOID pvData) override;
118 // IObjectWithRegistryKeyOld methods
119 STDMETHODIMP SetKey(HKEY hKey) override;
120 STDMETHODIMP GetKey(HKEY *phKey) override;
121};
122
123/******************************************************************************/
124
126{
127 if (m_pszName && m_pszName != m_szBuf)
129 if (m_pSource)
130 m_pSource->Release();
131}
132
134{
135 m_hKey = hKey;
136 m_pSource = pSource;
137 m_pSource->AddRef();
140 {
142 }
143 else
144 {
147 }
148 return m_pszName ? S_OK : E_OUTOFMEMORY;
149}
150
152{
153 return _RegNext(m_dwIndex) && SUCCEEDED(SHStrDupW(m_pszName, ppwsz));
154}
155
157{
158 if (!ppv)
159 return E_POINTER;
160
161 if (riid == IID_IEnumString)
162 {
163 *ppv = static_cast<IEnumString*>(this);
164 AddRef();
165 return S_OK;
166 }
167 return E_NOINTERFACE;
168}
169
171{
172 return ::InterlockedIncrement(&m_cRefs);
173}
174
176{
178 if (!refs)
179 delete this;
180 return refs;
181}
182
184{
185 if (!rgelt || (celt > 1 && !pceltFetched))
186 return E_INVALIDARG;
187
188 ULONG cFetched = 0;
189
190 while (cFetched < celt)
191 {
192 if (!_Next(&rgelt[cFetched]))
193 break;
194 ++m_dwIndex;
195 ++cFetched;
196 }
197
198 if (pceltFetched)
199 *pceltFetched = cFetched;
200
201 return (cFetched == celt) ? S_OK : S_FALSE;
202}
203
205{
206 return E_NOTIMPL;
207}
208
210{
211 m_dwIndex = 0;
212 return S_OK;
213}
214
216{
217 return E_NOTIMPL;
218}
219
220/******************************************************************************/
221
223{
225}
226
228{
229 DWORD cchKeyNameMax = 0;
230 RegQueryInfoKeyW(m_hKey, NULL, NULL, NULL, NULL, &cchKeyNameMax, NULL, NULL, NULL, NULL,
231 NULL, NULL);
232 return cchKeyNameMax + 1; // Including NUL
233}
234
235/******************************************************************************/
236
238{
239 DWORD cchValueNameMax = m_cchNameMax;
240 return RegEnumValueW(m_hKey, dwIndex, m_pszName, &cchValueNameMax, NULL,
242}
243
245{
246 DWORD cchValueNameMax = 0;
247 RegQueryInfoKeyW(m_hKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &cchValueNameMax,
248 NULL, NULL, NULL);
249 return cchValueNameMax + 1; // Including NUL
250}
251
252/******************************************************************************/
253
255{
256 if (m_hKey)
258}
259
261{
263 if (bCreate)
265 else
267
269}
270
272{
273 if (!ppvObject)
274 return E_POINTER;
275
276 if (riid == IID_IQuerySourceOld)
277 {
278 *ppvObject = static_cast<IQuerySourceOld*>(this);
279 AddRef();
280 return S_OK;
281 }
282
283 if (riid == IID_IObjectWithRegistryKeyOld)
284 {
285 *ppvObject = static_cast<IObjectWithRegistryKeyOld*>(this);
286 AddRef();
287 return S_OK;
288 }
289
290 *ppvObject = NULL;
291 return E_NOINTERFACE;
292}
293
294STDMETHODIMP_(ULONG) CRegistrySource::AddRef()
295{
296 return ::InterlockedIncrement(&m_cRefs);
297}
298
299STDMETHODIMP_(ULONG) CRegistrySource::Release()
300{
302 if (!refs)
303 delete this;
304 return refs;
305}
306
308{
309 CRegistryEnumValues* pEnum = new(std::nothrow) CRegistryEnumValues();
310 if (!pEnum)
311 return E_OUTOFMEMORY;
312 HRESULT hr = pEnum->Init(m_hKey, this);
313 if (FAILED(hr))
314 {
315 pEnum->Release();
316 pEnum = NULL;
317 }
318 *ppEnum = pEnum;
319 return pEnum ? S_OK : E_OUTOFMEMORY;
320}
321
323{
324 CRegistryEnumKeys* pEnum = new(std::nothrow) CRegistryEnumKeys();
325 if (!pEnum)
326 return E_OUTOFMEMORY;
327 HRESULT hr = pEnum->Init(m_hKey, this);
328 if (FAILED(hr))
329 {
330 pEnum->Release();
331 pEnum = NULL;
332 }
333 *ppEnum = pEnum;
334 return pEnum ? S_OK : E_OUTOFMEMORY;
335}
336
338 PCWSTR keyName,
339 PCWSTR valueName,
340 PWSTR *ppszValue)
341{
342 *ppszValue = NULL;
343
344 WCHAR szData[128];
345 DWORD dwType = REG_NONE, cbData = sizeof(szData);
346 LSTATUS error = SHGetValueW(m_hKey, keyName, valueName, &dwType, szData, &cbData);
347 if (error == ERROR_SUCCESS)
348 {
349 if (dwType != REG_SZ)
350 return E_DATATYPE_MISMATCH;
351 if (!valueName && !szData[0])
353 return SHStrDupW(szData, ppszValue);
354 }
355
356 if (error != ERROR_MORE_DATA)
358
359 *ppszValue = (PWSTR)CoTaskMemAlloc(cbData);
360 if (!*ppszValue)
361 return E_OUTOFMEMORY;
362
363 HRESULT hr = S_OK;
364 error = SHGetValueW(m_hKey, keyName, valueName, &dwType, *ppszValue, &cbData);
365 if (error)
366 {
367 CoTaskMemFree(*ppszValue);
368 *ppszValue = NULL;
370 }
371
372 if (SUCCEEDED(hr) && dwType != REG_SZ)
373 {
374 CoTaskMemFree(*ppszValue);
375 *ppszValue = NULL;
377 }
378
379 return hr;
380}
381
383{
384 DWORD dwType, cbValue = sizeof(*pdwValue);
385 LSTATUS error = SHGetValueW(m_hKey, keyName, valueName, &dwType, pdwValue, &cbValue);
386 if (error)
388 if (dwType != REG_DWORD)
389 return E_DATATYPE_MISMATCH;
390 return S_OK;
391}
392
394{
395 LSTATUS error = SHGetValueW(m_hKey, keyName, valueName, NULL, NULL, NULL);
396 if (error)
398 return S_OK;
399}
400
402 PCWSTR keyName,
403 PCWSTR valueName,
404 FLAGGED_BYTE_BLOB **ppBlob)
405{
406 HRESULT hr = E_FAIL;
407 HKEY hKey = m_hKey;
408 DWORD dwType = REG_NONE;
409 DWORD cbData = 256;
410 BYTE abData[256];
411
412 *ppBlob = NULL;
413
414 if (keyName && *keyName &&
416 {
417 return E_FAIL;
418 }
419
420 LSTATUS error = RegQueryValueExW(hKey, valueName, NULL, &dwType, abData, &cbData);
421 if (error == ERROR_SUCCESS)
422 {
423 hr = SHAllocBlob(cbData, abData, ppBlob);
424 }
425 else if (error == ERROR_MORE_DATA)
426 {
427 hr = SHAllocBlob(cbData, NULL, ppBlob);
428 if (SUCCEEDED(hr))
429 {
430 error = RegQueryValueExW(hKey, valueName, NULL, &dwType, (*ppBlob)->abData, &cbData);
431 if (error != ERROR_SUCCESS)
432 {
433 CoTaskMemFree(*ppBlob);
434 *ppBlob = NULL;
436 }
437 }
438 }
439 else
440 {
442 }
443
444 if (hKey != m_hKey)
446
447 if (SUCCEEDED(hr))
448 (*ppBlob)->fFlags = dwType;
449
450 return hr;
451}
452
453STDMETHODIMP CRegistrySource::OpenSource(PCWSTR keyName, BOOL bCreate, IQuerySourceOld **ppSource)
454{
455 return QuerySourceCreateFromKey(m_hKey, keyName, bCreate, IID_IQuerySourceOld, (PVOID*)ppSource);
456}
457
459 PCWSTR keyName,
460 PCWSTR valueName,
461 DWORD dwType,
464{
465 LSTATUS error = SHSetValueW(m_hKey, keyName, valueName, dwType, pvData, cbData);
466 if (error)
468 return S_OK;
469}
470
472{
473 if (m_hKey)
474 return E_UNEXPECTED;
475
477 return m_hKey ? S_OK : E_UNEXPECTED;
478}
479
481{
482 if (!m_hKey)
483 return E_UNEXPECTED;
484
485 *phKey = SHRegDuplicateHKey(m_hKey);
486 if (!*phKey)
487 return E_UNEXPECTED;
488
489 return S_OK;
490}
491
492/**************************************************************************
493 * QuerySourceCreateFromKey (SHLWAPI.544)
494 *
495 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/regsrc/createfromkey.htm
496 */
500 _In_ HKEY hKey,
501 _In_opt_ PCWSTR lpSubKey,
505{
506 *ppv = NULL;
507
508 CRegistrySource* pRS = new(std::nothrow) CRegistrySource();
509 if (!pRS)
510 return E_OUTOFMEMORY;
511
512 HRESULT hr = pRS->Init(hKey, lpSubKey, bCreate);
513 if (SUCCEEDED(hr))
514 hr = pRS->QueryInterface(riid, ppv);
515
516 pRS->Release();
517 return hr;
518}
#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:133
STDMETHODIMP Skip(ULONG celt) override
Definition: querysrc.cpp:204
BOOL _Next(PWSTR *ppwsz)
Definition: querysrc.cpp:151
STDMETHODIMP Reset() override
Definition: querysrc.cpp:209
WCHAR m_szBuf[64]
Definition: querysrc.cpp:45
STDMETHODIMP Clone(IEnumString **ppenum) override
Definition: querysrc.cpp:215
CRegistrySource * m_pSource
Definition: querysrc.cpp:42
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) override
Definition: querysrc.cpp:156
virtual BOOL _RegNext(DWORD dwIndex)=0
STDMETHODIMP_(ULONG) Release() override
STDMETHODIMP_(ULONG) AddRef() override
virtual DWORD _MaxLen()=0
virtual ~CRegistryEnumBase()
Definition: querysrc.cpp:125
STDMETHODIMP Next(ULONG celt, LPWSTR *rgelt, ULONG *pceltFetched) override
Definition: querysrc.cpp:183
DWORD _MaxLen() override
Definition: querysrc.cpp:227
BOOL _RegNext(DWORD dwIndex) override
Definition: querysrc.cpp:222
BOOL _RegNext(DWORD dwIndex) override
Definition: querysrc.cpp:237
DWORD _MaxLen() override
Definition: querysrc.cpp:244
STDMETHODIMP QueryValueDirect(PCWSTR keyName, PCWSTR valueName, FLAGGED_BYTE_BLOB **ppBlob) override
Definition: querysrc.cpp:401
STDMETHODIMP QueryValueExists(PCWSTR keyName, PCWSTR valueName) override
Definition: querysrc.cpp:393
STDMETHODIMP OpenSource(PCWSTR keyName, BOOL bCreate, IQuerySourceOld **ppSource) override
Definition: querysrc.cpp:453
STDMETHODIMP SetKey(HKEY hKey) override
Definition: querysrc.cpp:471
HRESULT Init(HKEY hKey, PCWSTR pszSubKey, BOOL bCreate)
Definition: querysrc.cpp:260
STDMETHODIMP EnumSources(IEnumString **ppEnum) override
Definition: querysrc.cpp:322
STDMETHODIMP QueryInterface(REFIID riid, void **ppvObject) override
Definition: querysrc.cpp:271
STDMETHODIMP QueryValueString(PCWSTR keyName, PCWSTR valueName, PWSTR *ppszValue) override
Definition: querysrc.cpp:337
virtual ~CRegistrySource()
Definition: querysrc.cpp:254
STDMETHODIMP QueryValueDword(PCWSTR keyName, PCWSTR valueName, DWORD *pdwValue) override
Definition: querysrc.cpp:382
STDMETHODIMP_(ULONG) Release() override
STDMETHODIMP SetValueDirect(PCWSTR keyName, PCWSTR valueName, DWORD dwType, DWORD cbData, LPCVOID pvData) override
Definition: querysrc.cpp:458
STDMETHODIMP GetKey(HKEY *phKey) override
Definition: querysrc.cpp:480
STDMETHODIMP_(ULONG) AddRef() override
STDMETHODIMP EnumValues(IEnumString **ppEnum) override
Definition: querysrc.cpp:307
#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
void *WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: malloc.c:381
void WINAPI CoTaskMemFree(void *ptr)
Definition: malloc.c:389
HRESULT WINAPI SHStrDupW(const WCHAR *src, WCHAR **dest)
Definition: main.c:1692
DWORD WINAPI SHGetValueW(HKEY hkey, const WCHAR *subkey, const WCHAR *value, DWORD *type, void *data, DWORD *data_len)
Definition: main.c:2222
DWORD WINAPI SHSetValueW(HKEY hkey, const WCHAR *subkey, const WCHAR *value, DWORD type, const void *data, DWORD data_len)
Definition: main.c:2292
HKEY WINAPI SHRegDuplicateHKey(HKEY hKey)
Definition: main.c:1828
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
#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:499
static HRESULT SHAllocBlob(ULONG cbData, const BYTE *pbData, FLAGGED_BYTE_BLOB **ppBlob)
Definition: querysrc.cpp:17
#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