| 11235 | |
| 11236 | |
| 11237 | ResultType Line::PerformLoopReg(ResultToken *aResultToken, Line *&aJumpToLine, Line *aUntil |
| 11238 | , FileLoopModeType aFileLoopMode, bool aRecurseSubfolders, HKEY aRootKeyType, HKEY aRootKey, LPTSTR aRegSubkey) |
| 11239 | // aRootKeyType is the type of root key, independent of whether it's local or remote. |
| 11240 | // This is used because there's no easy way to determine which root key a remote HKEY |
| 11241 | // refers to. |
| 11242 | { |
| 11243 | RegItemStruct reg_item(aRootKeyType, aRootKey, aRegSubkey); |
| 11244 | HKEY hRegKey; |
| 11245 | |
| 11246 | // Open the specified subkey. Be sure to only open with the minimum permission level so that |
| 11247 | // the keys & values can be deleted or written to (though I'm not sure this would be an issue |
| 11248 | // in most cases): |
| 11249 | if (RegOpenKeyEx(reg_item.root_key, reg_item.subkey, 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | g->RegView, &hRegKey) != ERROR_SUCCESS) |
| 11250 | return CONDITION_FALSE; |
| 11251 | |
| 11252 | // Get the count of how many values and subkeys are contained in this parent key: |
| 11253 | DWORD count_subkeys; |
| 11254 | DWORD count_values; |
| 11255 | if (RegQueryInfoKey(hRegKey, NULL, NULL, NULL, &count_subkeys, NULL, NULL |
| 11256 | , &count_values, NULL, NULL, NULL, NULL) != ERROR_SUCCESS) |
| 11257 | { |
| 11258 | RegCloseKey(hRegKey); |
| 11259 | return CONDITION_FALSE; |
| 11260 | } |
| 11261 | |
| 11262 | ResultType result = CONDITION_FALSE; |
| 11263 | Line *jump_to_line = nullptr; |
| 11264 | DWORD i; |
| 11265 | global_struct &g = *::g; // Primarily for performance in this case. |
| 11266 | |
| 11267 | // See comments in PerformLoop() for details about this section. |
| 11268 | #define MAKE_SCRIPT_LOOP_PROCESS_THIS_ITEM \ |
| 11269 | {\ |
| 11270 | g.mLoopRegItem = ®_item;\ |
| 11271 | PERFORMLOOP_EXECUTE_BODY \ |
| 11272 | PERFORMLOOP_EVALUATE_UNTIL \ |
| 11273 | ++g.mLoopIteration;\ |
| 11274 | } |
| 11275 | |
| 11276 | DWORD name_size; |
| 11277 | |
| 11278 | // First enumerate the values, which are analogous to files in the file system. |
| 11279 | // Later, the subkeys ("subfolders") will be done: |
| 11280 | if (count_values > 0 && aFileLoopMode != FILE_LOOP_FOLDERS_ONLY) // The caller doesn't want "files" (values) excluded. |
| 11281 | { |
| 11282 | reg_item.InitForValues(); |
| 11283 | // Going in reverse order allows values to be deleted without disrupting the enumeration, |
| 11284 | // at least in some cases: |
| 11285 | for (i = count_values - 1;; --i) |
| 11286 | { |
| 11287 | // Don't use CONTINUE in loops such as this due to the loop-ending condition being explicitly |
| 11288 | // checked at the bottom. |
| 11289 | name_size = _countof(reg_item.name); // Must reset this every time through the loop. |
| 11290 | *reg_item.name = '\0'; |
| 11291 | if (RegEnumValue(hRegKey, i, reg_item.name, &name_size, NULL, ®_item.type, NULL, NULL) == ERROR_SUCCESS) |
| 11292 | MAKE_SCRIPT_LOOP_PROCESS_THIS_ITEM |
| 11293 | // else continue the loop in case some of the lower indexes can still be retrieved successfully. |
| 11294 | if (i == 0) // Check this here due to it being an unsigned value that we don't want to go negative. |
no test coverage detected