1 #include "precomp.h"
2 #include "utils.h"
3 #include "regutils.h"
4 
5 LRESULT
6 RegQueryRegistryKeys(IN HKEY    hRootKey,
7                      IN LPCWSTR KeyName,
8                      IN PQUERY_REGISTRY_KEYS_TABLE QueryTable,
9                      IN PVOID   Context)
10 {
11     HKEY hSubKey = NULL;
12 
13     if (RegOpenKeyExW(hRootKey, KeyName, 0, KEY_ENUMERATE_SUB_KEYS, &hSubKey) == ERROR_SUCCESS)
14     {
15         HKEY hEntryKey = NULL;
16 
17         LRESULT lError = ERROR_SUCCESS;
18         DWORD   dwIndex = 0;
19         WCHAR   szValueName[MAX_VALUE_NAME] = L"";
20         DWORD   dwValueLength = ARRAYSIZE(szValueName);
21 
22         while ( (lError = RegEnumKeyExW(hSubKey, dwIndex, szValueName, &dwValueLength, NULL, NULL, NULL, NULL)) != ERROR_NO_MORE_ITEMS )
23         {
24             if ( (lError == ERROR_SUCCESS) && (RegOpenKeyExW(hSubKey, szValueName, 0, KEY_QUERY_VALUE, &hEntryKey) == ERROR_SUCCESS) )
25             {
26                 PQUERY_REGISTRY_KEYS_TABLE pTable = QueryTable;
27                 while (pTable && pTable->QueryRoutine)
28                 {
29                     pTable->QueryRoutine(hRootKey, KeyName, szValueName, hEntryKey, Context, pTable->EntryContext);
30                     ++pTable;
31                 }
32 
33                 RegCloseKey(hEntryKey);
34             }
35 
36             ++dwIndex;
37             dwValueLength  = ARRAYSIZE(szValueName);
38             szValueName[0] = L'\0';
39         }
40 
41         RegCloseKey(hSubKey);
42     }
43 
44     return ERROR_SUCCESS;
45 }
46 
47 //
48 // Idea taken from RtlQueryRegistryValues (see DDK).
49 //
50 LRESULT
51 RegQueryRegistryValues(IN HKEY    hRootKey,
52                        IN LPCWSTR KeyName,
53                        IN PQUERY_REGISTRY_VALUES_TABLE QueryTable,
54                        IN PVOID   Context)
55 {
56     LRESULT res     = ERROR_SUCCESS;
57     HKEY    hSubKey = NULL;
58 
59     if ( (res = RegOpenKeyExW(hRootKey, KeyName, 0, KEY_QUERY_VALUE, &hSubKey)) == ERROR_SUCCESS )
60     {
61         DWORD dwIndex = 0, dwType = 0;
62         WCHAR szValueName[MAX_VALUE_NAME] = L"";
63         LPBYTE lpData = NULL;
64         DWORD dwValueLength = ARRAYSIZE(szValueName), dwDataLength = 0;
65 
66         while (RegEnumValueW(hSubKey, dwIndex, szValueName, &dwValueLength, NULL, &dwType, NULL, &dwDataLength) != ERROR_NO_MORE_ITEMS)
67         {
68             ++dwValueLength;
69             lpData = (LPBYTE)MemAlloc(0, dwDataLength);
70 
71             if (RegEnumValueW(hSubKey, dwIndex, szValueName, &dwValueLength, NULL, &dwType, lpData, &dwDataLength) == ERROR_SUCCESS)
72             {
73                 PQUERY_REGISTRY_VALUES_TABLE pTable = QueryTable;
74                 while (pTable && pTable->QueryRoutine)
75                 {
76                     pTable->QueryRoutine(hRootKey, KeyName, szValueName, dwType, lpData, dwDataLength, Context, pTable->EntryContext);
77                     ++pTable;
78                 }
79             }
80 
81             MemFree(lpData); lpData = NULL;
82 
83             ++dwIndex;
84             dwValueLength = ARRAYSIZE(szValueName), dwDataLength = 0;
85             szValueName[0] = L'\0';
86         }
87 
88         RegCloseKey(hSubKey);
89     }
90 
91     return res;
92 }
93 
94 LONG
95 RegGetDWORDValue(IN  HKEY    hKey,
96                  IN  LPCWSTR lpSubKey OPTIONAL,
97                  IN  LPCWSTR lpValue  OPTIONAL,
98                  OUT LPDWORD lpData   OPTIONAL)
99 {
100     LONG lRet      = ERROR_SUCCESS;
101     HKEY hEntryKey = NULL;
102 
103     //
104     // Open the sub-key, if any. Otherwise,
105     // use the given registry key handle.
106     //
107     if (lpSubKey)
108     {
109         lRet = RegOpenKeyExW(hKey, lpSubKey, 0, KEY_QUERY_VALUE, &hEntryKey);
110     }
111     else
112     {
113         if (hKey != INVALID_HANDLE_VALUE)
114         {
115             // TODO: Ensure that hKey has the KEY_QUERY_VALUE right.
116             hEntryKey = hKey;
117             lRet = ERROR_SUCCESS;
118         }
119         else
120         {
121             lRet = ERROR_INVALID_HANDLE;
122         }
123     }
124 
125     if (lRet == ERROR_SUCCESS)
126     {
127         DWORD dwType    = 0,
128               dwRegData = 0,
129               dwBufSize = sizeof(dwRegData /* DWORD */);
130 
131         lRet = RegQueryValueExW(hEntryKey, lpValue, NULL, &dwType, (LPBYTE)&dwRegData, &dwBufSize);
132 
133         if (lRet == ERROR_SUCCESS)
134         {
135             if ( (dwType == REG_DWORD) && (dwBufSize == sizeof(DWORD)) )
136             {
137                 if (lpData)
138                     *lpData = dwRegData;
139             }
140             else
141             {
142                 lRet = ERROR_UNSUPPORTED_TYPE;
143             }
144         }
145         else if (lRet == ERROR_MORE_DATA)
146         {
147             if (dwType != REG_DWORD)
148             {
149                 lRet = ERROR_UNSUPPORTED_TYPE;
150             }
151         }
152 
153         // Close the opened sub-key.
154         if (lpSubKey)
155             RegCloseKey(hEntryKey);
156     }
157 
158     return lRet;
159 }
160 
161 LONG
162 RegSetDWORDValue(IN HKEY    hKey,
163                  IN LPCWSTR lpSubKey OPTIONAL,
164                  IN LPCWSTR lpValue  OPTIONAL,
165                  IN BOOL    bCreateKeyIfDoesntExist,
166                  IN DWORD   dwData)
167 {
168     LONG lRet      = ERROR_SUCCESS;
169     HKEY hEntryKey = NULL;
170 
171     //
172     // Open (or create) the sub-key, if any.
173     // Otherwise, use the given registry key handle.
174     //
175     if (lpSubKey)
176     {
177         if (bCreateKeyIfDoesntExist)
178             lRet = RegCreateKeyExW(hKey, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hEntryKey, NULL);
179         else
180             lRet = RegOpenKeyExW(hKey, lpSubKey, 0, KEY_SET_VALUE, &hEntryKey);
181     }
182     else
183     {
184         if (hKey != INVALID_HANDLE_VALUE)
185         {
186             // TODO: Ensure that hKey has the KEY_QUERY_VALUE right.
187             hEntryKey = hKey;
188             lRet = ERROR_SUCCESS;
189         }
190         else
191         {
192             lRet = ERROR_INVALID_HANDLE;
193         }
194     }
195 
196     //
197     // Opening successful, can set the value now.
198     //
199     if (lRet == ERROR_SUCCESS)
200     {
201         lRet = RegSetValueExW(hEntryKey, lpValue, 0, REG_DWORD, (LPBYTE)&dwData, sizeof(dwData /* DWORD */));
202 
203         // Close the opened (or created) sub-key.
204         if (lpSubKey)
205             RegCloseKey(hEntryKey);
206     }
207 
208     return lRet;
209 }
210