[SHELL32] SHChangeNotify: Use tree for CDirectoryList (#6784)
[reactos.git] / base / services / svchost / registry.c
1 /*
2 * PROJECT: ReactOS Service Host
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: base/services/svchost/registry.c
5 * PURPOSE: Helper functions for accessing the registry
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include "svchost.h"
12
13 /* FUNCTIONS *****************************************************************/
14
15 DWORD
16 WINAPI
17 RegQueryValueWithAlloc (
18 _In_ HKEY hKey,
19 _In_ LPCWSTR pszValueName,
20 _In_ DWORD dwExpectedType,
21 _Out_ PBYTE* ppbData,
22 _Out_ PDWORD pdwSize
23 )
24 {
25 DWORD dwError, dwType, dwBytes;
26 PBYTE pbData;
27 ASSERT(hKey);
28 ASSERT(pszValueName);
29 ASSERT(ppbData);
30 ASSERT(pdwSize);
31
32 /* Assume failure */
33 *ppbData = NULL;
34 *pdwSize = 0;
35
36 /* Query how big and what type the registry data is */
37 dwBytes = 0;
38 dwError = RegQueryValueExW(hKey,
39 pszValueName,
40 NULL,
41 &dwType,
42 NULL,
43 &dwBytes);
44 if (dwError != ERROR_SUCCESS) return dwError;
45
46 /* It if's not the right type, or it's sero bytes, fail*/
47 if ((dwType != dwExpectedType) || (dwBytes == 0)) return ERROR_INVALID_DATA;
48
49 /* Allocate space to hold the data */
50 pbData = MemAlloc(0, dwBytes);
51 if (pbData == NULL) return ERROR_OUTOFMEMORY;
52
53 /* Now get the real registry data */
54 dwError = RegQueryValueExW(hKey,
55 pszValueName,
56 NULL,
57 &dwType,
58 pbData,
59 &dwBytes);
60 if (dwError != ERROR_SUCCESS)
61 {
62 /* We failed, free the data since it won't be needed */
63 MemFree(pbData);
64 }
65 else
66 {
67 /* It worked, return the data and size back to the caller */
68 *ppbData = pbData;
69 *pdwSize = dwBytes;
70 }
71
72 /* All done */
73 return dwError;
74 }
75
76 DWORD
77 WINAPI
78 RegQueryDword (
79 _In_ HKEY hKey,
80 _In_ LPCWSTR pszValueName,
81 _Out_ PDWORD pdwValue
82 )
83 {
84 DWORD dwError, cbData, dwType;
85 ASSERT(hKey);
86 ASSERT(pszValueName);
87 ASSERT(pdwValue);
88
89 /* Attempt to read 4 bytes */
90 cbData = sizeof(DWORD);
91 dwError = RegQueryValueExW(hKey, pszValueName, 0, &dwType, 0, &cbData);
92
93 /* If we didn't get back a DWORD... */
94 if ((dwError == ERROR_SUCCESS) && (dwType != REG_DWORD))
95 {
96 /* Zero out the output and fail */
97 *pdwValue = 0;
98 dwError = ERROR_INVALID_DATATYPE;
99 }
100
101 /* All done! */
102 return dwError;
103 }
104
105 DWORD
106 WINAPI
107 RegQueryString (
108 _In_ HKEY hKey,
109 _In_ LPCWSTR pszValueName,
110 _In_ DWORD dwExpectedType,
111 _Out_ PBYTE* ppbData
112 )
113 {
114 DWORD dwSize;
115 ASSERT(hKey);
116 ASSERT(pszValueName);
117
118 /* Call the helper function */
119 return RegQueryValueWithAlloc(hKey,
120 pszValueName,
121 dwExpectedType,
122 ppbData,
123 &dwSize);
124 }
125
126 DWORD
127 WINAPI
128 RegQueryStringA (
129 _In_ HKEY hKey,
130 _In_ LPCWSTR pszValueName,
131 _In_ DWORD dwExpectedType,
132 _Out_ LPCSTR* ppszData
133 )
134 {
135 DWORD dwError;
136 LPWSTR pbLocalData;
137 DWORD cchValueName, cbMultiByte;
138 LPSTR pszData;
139 ASSERT(hKey);
140 ASSERT(pszValueName);
141 ASSERT(ppszData);
142
143 /* Assume failure */
144 *ppszData = NULL;
145
146 /* Query the string in Unicode first */
147 dwError = RegQueryString(hKey,
148 pszValueName,
149 dwExpectedType,
150 (PBYTE*)&pbLocalData);
151 if (dwError != ERROR_SUCCESS) return dwError;
152
153 /* Get the length of the Unicode string */
154 cchValueName = lstrlenW(pbLocalData);
155
156 /* See how much space it would take to convert to ANSI */
157 cbMultiByte = WideCharToMultiByte(CP_ACP,
158 0,
159 pbLocalData,
160 cchValueName + 1,
161 NULL,
162 0,
163 NULL,
164 NULL);
165 if (cbMultiByte != 0)
166 {
167 /* Allocate the space, assuming failure */
168 dwError = ERROR_OUTOFMEMORY;
169 pszData = MemAlloc(0, cbMultiByte);
170 if (pszData != NULL)
171 {
172 /* What do you know, it worked! */
173 dwError = ERROR_SUCCESS;
174
175 /* Now do the real conversion */
176 if (WideCharToMultiByte(CP_ACP,
177 0,
178 pbLocalData,
179 cchValueName + 1,
180 pszData,
181 cbMultiByte,
182 NULL,
183 NULL) != 0)
184 {
185 /* It worked, return the data back to the caller */
186 *ppszData = pszData;
187 }
188 else
189 {
190 /* It failed, free our buffer and get the error code */
191 MemFree(pszData);
192 dwError = GetLastError();
193 }
194 }
195 }
196
197 /* Free the original Unicode string and return the error */
198 MemFree(pbLocalData);
199 return dwError;
200 }
201