Skip to content

Native Performance Layer

Calvindd2f edited this page Jan 14, 2026 · 1 revision

Native Performance Layer

Relevant source files

The following files were used as context for generating this wiki page:

The Native Performance Layer is the C# component of OfficeScrubC2R that provides high-performance system operations through direct Win32 API calls. It is implemented in OfficeScrubC2R-Native.cs() and compiled into OfficeScrubNative.dll. This layer achieves 10-50x performance improvements over the original VBScript implementation by using compiled .NET code, parallel processing, and memory-optimized algorithms.

For detailed information about individual helper classes, see Helper Classes. For performance optimization techniques, see Performance Optimizations. For Win32 API integration details, see P/Invoke and Win32 APIs.

Architecture Overview

The native layer consists of a facade class OfficeScrubOrchestrator that provides a unified interface to nine specialized helper classes. Each helper class targets a specific Windows subsystem and exposes methods that PowerShell code can call.

Class Structure Diagram

classDiagram
    class OfficeScrubOrchestrator {
        +RegistryHelper Registry
        +FileHelper Files
        +ProcessHelper Processes
        +ShellHelper Shell
        +WindowsInstallerHelper WindowsInstaller
        +TypeLibHelper TypeLib
        +LicenseHelper License
        +ServiceHelper Services
        +GuidHelper GuidUtilities
        +bool IsC2RPath(string path)
        +bool IsInScope(string productCode)
    }
    
    class RegistryHelper {
        -bool _is64Bit
        +bool KeyExists(RegistryHiveType, string)
        +bool DeleteKey(RegistryHiveType, string, bool)
        +bool DeleteValue(RegistryHiveType, string, string)
        +string[] EnumerateKeys(RegistryHiveType, string)
        +string[] EnumerateValues(RegistryHiveType, string)
        +object GetValue(RegistryHiveType, string, string, object)
        +bool SetValue(RegistryHiveType, string, string, object, RegistryValueKind)
        +void AddPendingFileRenameOperation(string)
    }
    
    class FileHelper {
        -List~string~ _pendingDeletes
        +bool DeleteFile(string, bool)
        +bool DeleteDirectory(string, bool, bool)
        +void ScheduleDeleteOnReboot(string)
        +void ScheduleDirectoryDeleteOnReboot(string)
        +List~string~ GetPendingDeletes()
        +long GetDirectorySize(string)
        +bool IsFileLocked(string)
    }
    
    class ProcessHelper {
        +List~int~ TerminateProcesses(string[], int)
        +List~string~ GetProcessesUsingPath(string)
        +bool IsProcessRunning(string)
    }
    
    class WindowsInstallerHelper {
        -RegistryHelper _regHelper
        +void CleanupUpgradeCodes(Func~string,bool~)
        +void CleanupProducts(Func~string,bool~)
        +void CleanupComponents(Func~string,bool~)
        +void CleanupPublishedComponents(Func~string,bool~)
    }
    
    class TypeLibHelper {
        -RegistryHelper _regHelper
        -string[] KnownTypeLibs
        +void CleanupKnownTypeLibs()
    }
    
    class LicenseHelper {
        +void CleanOSPP(int versionNT)
        +void ClearVNextLicenseCache(string)
    }
    
    class ServiceHelper {
        +bool DeleteService(string)
    }
    
    class ShellHelper {
        +bool UnpinFromTaskbar(string)
        +bool UnpinFromStartMenu(string)
        +void RestartExplorer()
    }
    
    class GuidHelper {
        +string GetExpandedGuid(string)
        +string GetCompressedGuid(string)
        +bool GetDecodedGuid(string, out string)
    }
    
    OfficeScrubOrchestrator --> RegistryHelper
    OfficeScrubOrchestrator --> FileHelper
    OfficeScrubOrchestrator --> ProcessHelper
    OfficeScrubOrchestrator --> ShellHelper
    OfficeScrubOrchestrator --> WindowsInstallerHelper
    OfficeScrubOrchestrator --> TypeLibHelper
    OfficeScrubOrchestrator --> LicenseHelper
    OfficeScrubOrchestrator --> ServiceHelper
    WindowsInstallerHelper --> RegistryHelper
    TypeLibHelper --> RegistryHelper
Loading

Sources: OfficeScrubC2R-Native.cs:1349-1383, OfficeScrubC2R-Native.cs:334-616, OfficeScrubC2R-Native.cs:622-767, OfficeScrubC2R-Native.cs:774-858

Loading Mechanism

The native layer uses a smart fallback mechanism: it attempts to load a pre-compiled OfficeScrubNative.dll first, and if that fails, it compiles the C# source code at runtime.

DLL Loading Flow

flowchart TD
    Start["PowerShell imports<br/>OfficeScrubC2R.psm1"] --> CheckDLL["Check for<br/>OfficeScrubNative.dll"]
    
    CheckDLL --> DLLExists{"DLL exists<br/>and not blocked?"}
    
    DLLExists -->|"Yes"| LoadDLL["Add-Type -Path<br/>OfficeScrubNative.dll"]
    DLLExists -->|"No"| CompileSource["Add-Type -TypeDefinition<br/>from Native.cs"]
    
    LoadDLL --> LoadSuccess{"Load successful?"}
    CompileSource --> CompileSuccess{"Compile successful?"}
    
    LoadSuccess -->|"Yes"| CreateOrchestrator["Create OfficeScrubOrchestrator<br/>instance"]
    LoadSuccess -->|"No"| FallbackCompile["Fallback: compile<br/>from source"]
    
    FallbackCompile --> CompileSuccess
    
    CompileSuccess -->|"Yes"| CreateOrchestrator
    CompileSuccess -->|"No"| Error["Error: Cannot load<br/>native components"]
    
    CreateOrchestrator --> StoreGlobal["Store in<br/>$script:Orchestrator"]
    StoreGlobal --> Ready["Native layer ready<br/>for PowerShell calls"]
Loading

Sources: OfficeScrubC2R.psm1(), README.md:162-174

The pre-compiled DLL provides instant loading, while the fallback compilation ensures the module works even in restricted environments where DLLs may be blocked by security policies.

Helper Classes

The native layer is organized into specialized helper classes, each targeting a specific Windows subsystem:

Helper Class Primary Purpose Key Win32 APIs Lines
RegistryHelper Registry operations with WOW64 support RegOpenKeyEx, RegDeleteKeyEx, RegEnumKeyEx 334-616
FileHelper File/directory deletion with reboot scheduling MoveFileEx, RemoveDirectory 622-767
ProcessHelper Parallel process termination Process APIs via System.Diagnostics 774-858
WindowsInstallerHelper MSI metadata cleanup Registry APIs (via RegistryHelper) 980-1128
TypeLibHelper COM type library cleanup Registry APIs (via RegistryHelper) 1134-1209
LicenseHelper OSPP/SPP license operations WMI via System.Management 1215-1273
ServiceHelper Windows service management WMI + sc.exe fallback 1279-1343
GuidHelper GUID encoding/decoding utilities None (pure algorithm) 171-328
ShellHelper Taskbar/Start Menu integration Shell COM automation 864-974

Sources: OfficeScrubC2R-Native.cs:334-1383, README.md:162-174

Integration with PowerShell

PowerShell code accesses the native layer through the $script:Orchestrator variable, which holds an instance of OfficeScrubOrchestrator. The utilities module wraps these calls to provide a PowerShell-friendly interface.

Call Flow: PowerShell to Native

sequenceDiagram
    participant PS as "PowerShell Script<br/>(OfficeScrubC2R.ps1)"
    participant Util as "Utilities Module<br/>(OfficeScrubC2R-Utilities.psm1)"
    participant Orch as "$script:Orchestrator<br/>(OfficeScrubOrchestrator)"
    participant Helper as "Helper Class<br/>(e.g., RegistryHelper)"
    participant Win32 as "Win32 API<br/>(advapi32.dll)"
    
    PS->>Util: "Remove-RegistryKey<br/>-Hive HKLM<br/>-Key 'path'"
    
    Util->>Orch: "$script:Orchestrator<br/>.Registry"
    Orch-->>Util: "RegistryHelper instance"
    
    Util->>Helper: "DeleteKey(<br/>RegistryHiveType.LocalMachine,<br/>'path',<br/>recursive: true)"
    
    Helper->>Helper: "GetHiveKey(hive)"
    Helper->>Helper: "KeyExists(hive, subKey)"
    
    Helper->>Win32: "RegOpenKeyEx(...)"
    Win32-->>Helper: "Handle"
    
    Helper->>Win32: "RegDeleteKeyEx(...)"
    Win32-->>Helper: "ERROR_SUCCESS"
    
    Helper->>Win32: "RegCloseKey(handle)"
    
    Helper-->>Util: "bool: true"
    Util-->>PS: "Success"
Loading

Sources: OfficeScrubC2R-Utilities.psm1, OfficeScrubC2R-Native.cs:349-364

Example: Registry Operation Flow

When PowerShell code calls Remove-RegistryKey, the following sequence occurs:

  1. PowerShell layer: OfficeScrubC2R-Utilities.psm1 function Remove-RegistryKey is invoked
  2. Native access: Function accesses $script:Orchestrator.Registry to get the RegistryHelper instance
  3. WOW64 handling: RegistryHelper.DeleteKey() checks both 64-bit and 32-bit registry views OfficeScrubC2R-Native.cs:354-364
  4. Win32 API: DeleteKeyInternal() calls hive.DeleteSubKeyTree() which uses RegDeleteKeyEx P/Invoke OfficeScrubC2R-Native.cs:538-552
  5. Result propagation: Boolean success/failure returned through the call chain

P/Invoke Declarations

The native layer declares Win32 APIs through P/Invoke for direct system access. Key declarations include:

Win32 API Categories

graph LR
    subgraph "Native APIs"
        kernel32["kernel32.dll"]
        advapi32["advapi32.dll"]
        shell32["shell32.dll"]
    end
    
    subgraph "File Operations"
        MoveFileEx["MoveFileEx<br/>(reboot scheduling)"]
        RemoveDirectory["RemoveDirectory<br/>(directory deletion)"]
        SetFileAttributes["SetFileAttributes<br/>(attribute modification)"]
    end
    
    subgraph "Registry Operations"
        RegOpenKeyEx["RegOpenKeyEx<br/>(open key)"]
        RegDeleteKeyEx["RegDeleteKeyEx<br/>(delete key)"]
        RegDeleteValue["RegDeleteValue<br/>(delete value)"]
        RegEnumKeyEx["RegEnumKeyEx<br/>(enumerate subkeys)"]
        RegEnumValue["RegEnumValue<br/>(enumerate values)"]
        RegQueryValueEx["RegQueryValueEx<br/>(read value)"]
        RegCloseKey["RegCloseKey<br/>(close handle)"]
    end
    
    subgraph "Shell Operations"
        ILCreateFromPath["ILCreateFromPath<br/>(item ID list)"]
        ILFree["ILFree<br/>(free PIDL)"]
        SHCreateShellItem["SHCreateShellItem<br/>(shell item)"]
    end
    
    kernel32 --> MoveFileEx
    kernel32 --> RemoveDirectory
    kernel32 --> SetFileAttributes
    
    advapi32 --> RegOpenKeyEx
    advapi32 --> RegDeleteKeyEx
    advapi32 --> RegDeleteValue
    advapi32 --> RegEnumKeyEx
    advapi32 --> RegEnumValue
    advapi32 --> RegQueryValueEx
    advapi32 --> RegCloseKey
    
    shell32 --> ILCreateFromPath
    shell32 --> ILFree
    shell32 --> SHCreateShellItem
Loading

Sources: OfficeScrubC2R-Native.cs:60-166

All P/Invoke declarations are in the NativeMethods class with proper marshaling attributes:

internal static class NativeMethods
{
    [DllImport("advapi32.dll", SetLastError = true)]
    internal static extern int RegOpenKeyEx(...);
    
    [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    internal static extern bool MoveFileEx(...);
    
    // ... additional declarations
}

Sources: OfficeScrubC2R-Native.cs:62-153

Performance Characteristics

The native layer achieves 10-50x performance improvements through several techniques:

Optimization Technique Impact Location
Memory allocation Span<char> for GUID operations 3x faster, 80% less memory OfficeScrubC2R-Native.cs:188-224
Registry operations Direct Win32 API calls 30x faster enumeration OfficeScrubC2R-Native.cs:402-436
File deletion cmd.exe rd + parallel processing 15x faster OfficeScrubC2R-Native.cs:654-687
Process termination Parallel Task.Run Concurrent execution OfficeScrubC2R-Native.cs:777-814
String comparison StringComparison.OrdinalIgnoreCase 2x faster, no allocation Throughout
Static caching Decode table pre-allocated Eliminates per-call allocation OfficeScrubC2R-Native.cs:264-274

Sources: docs/OPTIMIZATION_ANALYSIS.md:64-202, README.md:134-142

Performance Comparison Table

Operation VBScript (baseline) PowerShell/C# Improvement
Registry enumeration (100 keys) ~10,000 ms ~300 ms 30x faster
File deletion (1000 files) ~15,000 ms ~1,000 ms 15x faster
GUID operations (1000x) 12.4 ms 3.8 ms 3.3x faster
Overall execution 5-10 minutes 30-60 seconds 10-50x faster

Sources: docs/OPTIMIZATION_ANALYSIS.md:249-286, README.md:134-142

Constants and Enumerations

The native layer defines constants and enumerations used throughout the codebase:

RegistryHiveType Enumeration

public enum RegistryHiveType
{
    ClassesRoot = unchecked((int)0x80000000),
    CurrentUser = unchecked((int)0x80000001),
    LocalMachine = unchecked((int)0x80000002),
    Users = unchecked((int)0x80000003)
}

Sources: OfficeScrubC2R-Native.cs:21-27

OfficeConstants Class

Contains Office-specific identification patterns:

Constant Value Purpose
OFFICE_ID "0000000FF1CE}" Office product GUID suffix
PROD_LEN 13 Product code length
SQUISHED 20 Squished GUID length
COMPRESSED 32 Compressed GUID length
C2R_PATTERNS String array Click-to-Run detection patterns
OFFICE_PROCESSES String array Known Office process names

Sources: OfficeScrubC2R-Native.cs:29-56

WOW64 Support

The RegistryHelper class provides transparent WOW64 (Windows-on-Windows 64-bit) support, automatically checking both 64-bit and 32-bit registry views on 64-bit systems:

flowchart TD
    Start["Registry operation<br/>requested"]
    
    Start --> Check64["Check _is64Bit field"]
    
    Check64 --> Native["Perform operation on<br/>native registry view"]
    
    Native --> Is64{"Is 64-bit<br/>system?"}
    
    Is64 -->|"Yes"| Wow64["Also perform operation on<br/>Wow6432Node registry view"]
    Is64 -->|"No"| Done["Return result"]
    
    Wow64 --> Combine["Combine results from<br/>both views"]
    Combine --> Done
Loading

Sources: OfficeScrubC2R-Native.cs:343-364, OfficeScrubC2R-Native.cs:583-593

The GetWow64Key() method OfficeScrubC2R-Native.cs:583-593 transforms registry paths to access the 32-bit registry view on 64-bit systems by injecting Wow6432Node into the path structure.

Error Handling Strategy

The native layer follows a "silent failure" pattern: methods return bool for success/failure or catch exceptions and return default values. This prevents native exceptions from propagating to PowerShell:

public bool DeleteKey(RegistryHiveType hive, string subKey, bool recursive = true)
{
    bool result = false;
    
    if (KeyExists(hive, subKey))
    {
        result = DeleteKeyInternal(GetHiveKey(hive), subKey, recursive);
    }
    
    if (_is64Bit && KeyExists(hive, GetWow64Key(subKey)))
    {
        result = DeleteKeyInternal(GetHiveKey(hive), GetWow64Key(subKey), recursive) || result;
    }
    
    return result;
}

Sources: OfficeScrubC2R-Native.cs:349-364

All Win32 API failures are caught and return false or null, allowing PowerShell code to handle errors at a higher level through standard error codes and logging.

Clone this wiki locally