| 548 | return OriginalNtEnumerateKey(key, correctedIndex, keyInformationClass, keyInformation, keyInformationLength, resultLength); |
| 549 | } |
| 550 | static NTSTATUS NTAPI HookedNtEnumerateValueKey(HANDLE key, ULONG index, NT_KEY_VALUE_INFORMATION_CLASS keyValueInformationClass, LPVOID keyValueInformation, ULONG keyValueInformationLength, PULONG resultLength) |
| 551 | { |
| 552 | HANDLE cacheKey = (HANDLE)TlsGetValue(TlsNtEnumerateValueKeyCacheKey); |
| 553 | ULONG cacheIndex = (ULONG)TlsGetValue(TlsNtEnumerateValueKeyCacheIndex); |
| 554 | ULONG cacheI = (ULONG)TlsGetValue(TlsNtEnumerateValueKeyCacheI); |
| 555 | ULONG cacheCorrectedIndex = (ULONG)TlsGetValue(TlsNtEnumerateValueKeyCacheCorrectedIndex); |
| 556 | |
| 557 | ULONG i = 0; |
| 558 | ULONG correctedIndex = 0; |
| 559 | |
| 560 | if (cacheKey == key && cacheIndex == index - 1) |
| 561 | { |
| 562 | // This function was recently called the index - 1, so we can continue from the last known position. |
| 563 | // This increases performance from O(N^2) to O(N). |
| 564 | i = cacheI; |
| 565 | correctedIndex = cacheCorrectedIndex + 1; |
| 566 | } |
| 567 | |
| 568 | WCHAR keyPath[1000]; |
| 569 | if (!GetRegistryKeyName(key, keyPath, 1000)) keyPath[0] = L'\0'; |
| 570 | |
| 571 | BYTE buffer[1024]; |
| 572 | WCHAR fullPath[1000]; |
| 573 | PNT_KEY_VALUE_BASIC_INFORMATION basicInformation = (PNT_KEY_VALUE_BASIC_INFORMATION)buffer; |
| 574 | |
| 575 | for (; i <= index; correctedIndex++) |
| 576 | { |
| 577 | if (OriginalNtEnumerateValueKey(key, correctedIndex, KeyValueBasicInformation, basicInformation, 1024, resultLength) != ERROR_SUCCESS) |
| 578 | { |
| 579 | return OriginalNtEnumerateValueKey(key, correctedIndex, keyValueInformationClass, keyValueInformation, keyValueInformationLength, resultLength); |
| 580 | } |
| 581 | |
| 582 | basicInformation->Name[basicInformation->NameLength / sizeof(WCHAR)] = L'\0'; |
| 583 | |
| 584 | BOOL hidden = FALSE; |
| 585 | |
| 586 | if (HasPrefix(basicInformation->Name)) |
| 587 | { |
| 588 | hidden = TRUE; |
| 589 | } |
| 590 | else if (lstrlenW(keyPath) > 0) |
| 591 | { |
| 592 | StrCpyW(fullPath, keyPath); |
| 593 | StrCatW(fullPath, L"\\"); |
| 594 | StrCatW(fullPath, basicInformation->Name); |
| 595 | |
| 596 | if (IsRegistryPathHidden(fullPath)) |
| 597 | { |
| 598 | hidden = TRUE; |
| 599 | } |
| 600 | } |
| 601 | |
| 602 | if (!hidden) |
| 603 | { |
| 604 | i++; |
| 605 | } |
| 606 | } |
| 607 |
nothing calls this directly
no test coverage detected