xref: /reactos/base/services/svchost/registry.c (revision 8a978a17)
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 
202