| 180 | |
| 181 | |
| 182 | void RegRead(ResultToken &aResultToken, HKEY aRootKey, LPTSTR aRegSubkey, LPTSTR aValueName, ExprTokenType *aDefault) |
| 183 | { |
| 184 | HKEY hRegKey; |
| 185 | DWORD dwRes, dwBuf, dwType; |
| 186 | LONG result; |
| 187 | |
| 188 | _f_set_retval_p(_T(""), 0); // Set default in case of early return. |
| 189 | |
| 190 | // Open the registry key |
| 191 | result = RegOpenKeyEx(aRootKey, aRegSubkey, 0, KEY_READ | g->RegView, &hRegKey); |
| 192 | if (result != ERROR_SUCCESS) |
| 193 | goto finish_skip_close; |
| 194 | |
| 195 | // Read the value and determine the type. If aValueName is the empty string, the key's default value is used. |
| 196 | result = RegQueryValueEx(hRegKey, aValueName, NULL, &dwType, NULL, NULL); |
| 197 | if (result != ERROR_SUCCESS) |
| 198 | goto finish; |
| 199 | |
| 200 | LPTSTR contents, cp; |
| 201 | |
| 202 | // The way we read is different depending on the type of the key |
| 203 | switch (dwType) |
| 204 | { |
| 205 | case REG_DWORD: |
| 206 | dwRes = sizeof(dwBuf); |
| 207 | result = RegQueryValueEx(hRegKey, aValueName, NULL, NULL, (LPBYTE)&dwBuf, &dwRes); |
| 208 | if (result == ERROR_SUCCESS) |
| 209 | { |
| 210 | // Set the return value but don't return yet. |
| 211 | aResultToken.Return(dwBuf); |
| 212 | } |
| 213 | break; |
| 214 | |
| 215 | // Note: The contents of any of these types can be >64K on NT/2k/XP+ (though that is probably rare): |
| 216 | case REG_SZ: |
| 217 | case REG_EXPAND_SZ: |
| 218 | case REG_MULTI_SZ: |
| 219 | { |
| 220 | dwRes = 0; // Retained for backward compatibility because values >64K may cause it to fail on Win95 (unverified, and MSDN implies its value should be ignored for the following call). |
| 221 | // MSDN: If lpData is NULL, and lpcbData is non-NULL, the function returns ERROR_SUCCESS and stores |
| 222 | // the size of the data, in bytes, in the variable pointed to by lpcbData. |
| 223 | result = RegQueryValueEx(hRegKey, aValueName, NULL, NULL, NULL, &dwRes); // Find how large the value is. |
| 224 | if (result != ERROR_SUCCESS || !dwRes) // Can't find size (realistically might never happen), or size is zero. |
| 225 | break; |
| 226 | DWORD dwCharLen = dwRes / sizeof(TCHAR); |
| 227 | // Set up the result buffer to receive the contents. |
| 228 | // Since dwRes includes the space for the zero terminator (if the MSDN docs |
| 229 | // are accurate), this will size it to be 1 byte larger than we need, |
| 230 | // which leaves room for the final newline character to be inserted after |
| 231 | // the last item. But add 2 to the requested capacity in case the data isn't |
| 232 | // terminated in the registry, which allows double-NULL to be put in for REG_MULTI_SZ later. |
| 233 | if (!TokenSetResult(aResultToken, NULL, dwCharLen + 2)) |
| 234 | break; // aResultToken.Error() was already called, but we still need to call RegCloseKey(). |
| 235 | //aResultToken.symbol = SYM_STRING; // Already set by _f_set_reval_p(). |
| 236 | contents = aResultToken.marker; // This target buf should now be large enough for the result. |
| 237 | |
| 238 | result = RegQueryValueEx(hRegKey, aValueName, NULL, NULL, (LPBYTE)contents, &dwRes); |
| 239 |
no test coverage detected