Bearsampp 2026.5.5
Loading...
Searching...
No Matches
Win32Native Class Reference

Static Public Member Functions

static countFilesFolders ($path)
static countFilesFoldersCOM ($path)
static createShortcut ($shortcutPath, $targetPath, $workingDir='', $description='', $iconPath='')
static findProcessesByName ($name, $properties=[])
static getCurrentPid ()
static getDefaultBrowser ()
static getInstalledBrowsers ()
static getProcessInfo ($pid, $properties=[])
static getProcessList ($properties=[])
static getServiceInfo ($serviceName, $properties=[])
static getServiceState ($serviceName)
static getSpecialFolderPath ($folderName)
static killProcess ($pid)
static listServices ($properties=[])
static processExists ($pid)
static registryDeleteKey ($hive, $key)
static registryDeleteValue ($hive, $key, $value)
static registryExists ($hive, $key, $value=null)
static registryGetValue ($hive, $key, $value='')
static registrySetValue ($hive, $key, $value, $data, $type='REG_SZ')
static resetConnections ()
static serviceExists ($serviceName)

Static Private Member Functions

static countFilesFoldersManual ($path)
static countFolderItemsCOM ($fso, $path)
static extractBrowserExecutablePath ($commandPath)
static getWmiCimv2 ()
static getWmiStdRegProv ()
static getWscriptShell ()
static mapRegistryHive ($hive)

Static Private Attributes

static COM $wmiCimv2 = null
static COM $wmiStdRegProv = null
static COM $wscriptShell = null

Detailed Description

Class Win32Native

This class provides native Windows operations using PHP COM extension. Replaces VBScript operations with direct COM/WMI access from PHP. Uses Windows Management Instrumentation (WMI) and WScript.Shell COM objects.

Definition at line 16 of file class.win32native.php.

Member Function Documentation

◆ countFilesFolders()

countFilesFolders ( $path)
static

Counts files and folders recursively using native PHP. Replaces VBS with native PHP (faster than COM FileSystemObject).

Parameters
string$pathThe path to count files and folders in
Returns
int|false The count of files and folders, or false on failure

Definition at line 749 of file class.win32native.php.

750 {
751 Log::debug('countFilesFolders: Counting in ' . $path . ' (Native PHP)');
752
753 $startTime = microtime(true);
754
755 try {
756 if (!is_dir($path)) {
757 Log::error('countFilesFolders: Path is not a directory: ' . $path);
758 return false;
759 }
760
761 $count = 0;
762
763 // Use RecursiveDirectoryIterator for efficient recursive counting
764 try {
765 $iterator = new RecursiveIteratorIterator(
766 new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS),
767 RecursiveIteratorIterator::SELF_FIRST
768 );
769
770 foreach ($iterator as $item) {
771 $count++;
772 }
773 } catch (Exception $e) {
774 // If RecursiveIterator fails, fall back to manual recursion
775 Log::debug('countFilesFolders: RecursiveIterator failed, using manual recursion');
776 $count = self::countFilesFoldersManual($path);
777 }
778
779 $duration = round((microtime(true) - $startTime) * 1000, 2);
780 Log::debug('countFilesFolders: Counted ' . $count . ' items in ' . $duration . 'ms (Native PHP)');
781
782 return $count;
783
784 } catch (Exception $e) {
785 Log::error('countFilesFolders: Exception: ' . $e->getMessage());
786 return false;
787 }
788 }
static debug($data, $file=null)
static error($data, $file=null)
static countFilesFoldersManual($path)

References countFilesFoldersManual(), Log\debug(), and Log\error().

◆ countFilesFoldersCOM()

countFilesFoldersCOM ( $path)
static

Counts files and folders recursively using COM FileSystemObject. Alternative COM-based implementation (slower than native PHP).

Parameters
string$pathThe path to count files and folders in
Returns
int|false The count of files and folders, or false on failure

Definition at line 835 of file class.win32native.php.

836 {
837 Log::debug('countFilesFoldersCOM: Counting in ' . $path . ' (COM/FSO)');
838
839 $startTime = microtime(true);
840
841 try {
842 $fso = new COM("Scripting.FileSystemObject");
843
844 if (!$fso->FolderExists($path)) {
845 Log::error('countFilesFoldersCOM: Path does not exist: ' . $path);
846 return false;
847 }
848
849 $count = self::countFolderItemsCOM($fso, $path);
850
851 $duration = round((microtime(true) - $startTime) * 1000, 2);
852 Log::debug('countFilesFoldersCOM: Counted ' . $count . ' items in ' . $duration . 'ms (COM/FSO)');
853
854 return $count;
855
856 } catch (Exception $e) {
857 Log::error('countFilesFoldersCOM: COM exception: ' . $e->getMessage());
858 return false;
859 }
860 }
static countFolderItemsCOM($fso, $path)

References countFolderItemsCOM(), Log\debug(), and Log\error().

◆ countFilesFoldersManual()

countFilesFoldersManual ( $path)
staticprivate

Manual recursive file/folder counting (fallback method). Helper method for countFilesFolders.

Parameters
string$pathThe path to count
Returns
int The count of files and folders

Definition at line 797 of file class.win32native.php.

798 {
799 $count = 0;
800
801 try {
802 $items = @scandir($path);
803
804 if ($items === false) {
805 return 0;
806 }
807
808 foreach ($items as $item) {
809 if ($item === '.' || $item === '..') {
810 continue;
811 }
812
813 $fullPath = $path . DIRECTORY_SEPARATOR . $item;
814 $count++; // Count this item
815
816 if (is_dir($fullPath)) {
817 // Recursively count subdirectory
818 $count += self::countFilesFoldersManual($fullPath);
819 }
820 }
821 } catch (Exception $e) {
822 // Silently handle errors (permission denied, etc.)
823 }
824
825 return $count;
826 }

References countFilesFoldersManual().

Referenced by countFilesFolders(), and countFilesFoldersManual().

◆ countFolderItemsCOM()

countFolderItemsCOM ( $fso,
$path )
staticprivate

Recursive helper for COM-based file/folder counting. Helper method for countFilesFoldersCOM.

Parameters
COM$fsoFileSystemObject instance
string$pathThe path to count
Returns
int The count of files and folders

Definition at line 870 of file class.win32native.php.

871 {
872 try {
873 $folder = $fso->GetFolder($path);
874
875 // Count files and subfolders in this folder
876 $count = $folder->Files->Count + $folder->SubFolders->Count;
877
878 // Recursively count subfolders
879 foreach ($folder->SubFolders as $subFolder) {
880 $count += self::countFolderItemsCOM($fso, $subFolder->Path);
881 }
882
883 return $count;
884
885 } catch (Exception $e) {
886 // Silently handle errors (permission denied, etc.)
887 return 0;
888 }
889 }

References countFolderItemsCOM().

Referenced by countFilesFoldersCOM(), and countFolderItemsCOM().

◆ createShortcut()

createShortcut ( $shortcutPath,
$targetPath,
$workingDir = '',
$description = '',
$iconPath = '' )
static

Creates a Windows shortcut using COM. Replaces VBS with direct COM access.

Parameters
string$shortcutPathFull path where to save the shortcut (.lnk file)
string$targetPathPath to the target executable
string$workingDirWorking directory for the shortcut
string$descriptionShortcut description
string$iconPathPath to icon file
Returns
bool True on success, false on failure

Definition at line 696 of file class.win32native.php.

697 {
698 Log::debug('createShortcut: Creating shortcut at ' . $shortcutPath . ' (COM)');
699
700 $startTime = microtime(true);
701
702 try {
703 $shell = self::getWscriptShell();
704
705 // Create the shortcut object
706 $shortcut = $shell->CreateShortcut($shortcutPath);
707
708 // Set shortcut properties
709 $shortcut->TargetPath = $targetPath;
710
711 if (!empty($workingDir)) {
712 $shortcut->WorkingDirectory = $workingDir;
713 }
714
715 if (!empty($description)) {
716 $shortcut->Description = $description;
717 }
718
719 if (!empty($iconPath)) {
720 $shortcut->IconLocation = $iconPath;
721 }
722
723 // Save the shortcut
724 $shortcut->Save();
725
726 $duration = round((microtime(true) - $startTime) * 1000, 2);
727 Log::debug('createShortcut: Successfully created shortcut in ' . $duration . 'ms (COM)');
728
729 return true;
730
731 } catch (Exception $e) {
733 Log::error('createShortcut: COM exception: ' . $e->getMessage());
734 return false;
735 }
736 }
static resetConnections()
static getWscriptShell()

References Log\debug(), Log\error(), getWscriptShell(), and resetConnections().

Referenced by Util\enableLaunchStartup().

◆ extractBrowserExecutablePath()

extractBrowserExecutablePath ( $commandPath)
staticprivate

Extracts the executable path from a browser command string. Helper method for browser detection.

Parameters
string$commandPathThe command path string from registry
Returns
string|false The extracted executable path, or false on failure

Definition at line 1227 of file class.win32native.php.

1228 {
1229 if (empty($commandPath)) {
1230 return false;
1231 }
1232
1233 // Method 1: Extract path from quotes
1234 // Format: "C:\Program Files\Browser\browser.exe" --arguments
1235 if (preg_match('/"([^"]+\\.exe)"/i', $commandPath, $matches)) {
1236 return $matches[1];
1237 }
1238
1239 // Method 2: Extract path without quotes but with .exe
1240 // Format: C:\Program Files\Browser\browser.exe --arguments
1241 if (preg_match('/^([^\\s]+\\.exe)/i', trim($commandPath), $matches)) {
1242 return $matches[1];
1243 }
1244
1245 // Method 3: Handle paths with spaces but no quotes (rare)
1246 // Try to find .exe in the string
1247 if (preg_match('/([A-Z]:\\\\[^"]+\\.exe)/i', $commandPath, $matches)) {
1248 return $matches[1];
1249 }
1250
1251 // Method 4: Fallback - take everything before first space
1252 $parts = explode(' ', trim($commandPath));
1253 $path = str_replace('"', '', $parts[0]);
1254
1255 // Validate it looks like a path
1256 if (stripos($path, '.exe') !== false) {
1257 return $path;
1258 }
1259
1260 return false;
1261 }

Referenced by getInstalledBrowsers().

◆ findProcessesByName()

findProcessesByName ( $name,
$properties = [] )
static

Finds processes by name.

Parameters
string$nameProcess name (e.g., 'notepad.exe')
array$propertiesProperties to retrieve
Returns
array Array of matching processes

Definition at line 281 of file class.win32native.php.

282 {
283 if (empty($name)) {
284 return [];
285 }
286
287 if (empty($properties)) {
288 $properties = ['Name', 'ProcessID', 'ExecutablePath'];
289 }
290
291 try {
292 $wmi = self::getWmiCimv2();
293 $selectClause = implode(', ', $properties);
294
295 // Sanitize the name parameter to prevent WQL injection
296 // Escape single quotes by doubling them (WQL standard)
297 $safeName = str_replace("'", "''", $name);
298
299 $query = "SELECT {$selectClause} FROM Win32_Process WHERE Name = '{$safeName}'";
300 $processes = $wmi->ExecQuery($query);
301
302 $result = [];
303 foreach ($processes as $proc) {
304 $process = [];
305 foreach ($properties as $prop) {
306 try {
307 $value = $proc->$prop;
308 $process[$prop] = $value ?? '';
309 } catch (Exception $e) {
310 $process[$prop] = '';
311 }
312 }
313 $result[] = $process;
314 }
315
316 return $result;
317
318 } catch (Exception $e) {
320 Log::error('findProcessesByName: COM exception: ' . $e->getMessage());
321 return [];
322 }
323 }
$result
$proc
Definition ajax.php:61

References $proc, $result, Log\error(), getWmiCimv2(), and resetConnections().

◆ getCurrentPid()

getCurrentPid ( )
static

Gets the current PHP process ID.

Returns
int Current process ID

Definition at line 330 of file class.win32native.php.

331 {
332 return getmypid();
333 }

◆ getDefaultBrowser()

getDefaultBrowser ( )
static

Gets the default browser's executable path using COM. Replaces VBS with direct COM registry access.

Returns
string|false The path to the default browser executable, or false on failure

Definition at line 1094 of file class.win32native.php.

1095 {
1096 Log::debug('getDefaultBrowser: Reading default browser (COM)');
1097
1098 $startTime = microtime(true);
1099
1100 // Try to read the default browser from registry
1101 $browserPath = self::registryGetValue('HKLM', 'SOFTWARE\\Classes\\http\\shell\\open\\command', '');
1102
1103 if ($browserPath === null) {
1104 Log::debug('getDefaultBrowser: No default browser found');
1105 return false;
1106 }
1107
1108 $duration = round((microtime(true) - $startTime) * 1000, 2);
1109
1110 // Extract the executable path from the command
1111 // Format is usually: "C:\Program Files\Browser\browser.exe" -- "%1"
1112 if (preg_match('/"([^"]+)"/', $browserPath, $matches)) {
1113 $path = $matches[1];
1114 } else {
1115 // No quotes, take everything before the first space or use as-is
1116 $path = trim(explode(' ', $browserPath)[0]);
1117 $path = str_replace('"', '', $path);
1118 }
1119
1120 Log::debug('getDefaultBrowser: Found browser in ' . $duration . 'ms (COM)');
1121 return $path;
1122 }
static registryGetValue($hive, $key, $value='')

References Log\debug(), and registryGetValue().

Referenced by ActionReload\__construct(), and ActionStartup\checkBrowser().

◆ getInstalledBrowsers()

getInstalledBrowsers ( )
static

Gets a list of installed browsers using hybrid approach. Hybrid approach - known browsers + pattern matching (NO VBS!)

Returns
array An array of browser executable paths (empty array if none found)

Definition at line 1130 of file class.win32native.php.

1131 {
1132 Log::debug('getInstalledBrowsers: Enumerating installed browsers (Hybrid - No VBS)');
1133
1134 $startTime = microtime(true);
1135 $browsers = [];
1136
1137 // Known browser registry names (covers 99% of browsers)
1138 $knownBrowsers = [
1139 // Major browsers
1140 'Google Chrome',
1141 'Microsoft Edge',
1142 'Opera',
1143 'Brave',
1144 'Vivaldi',
1145 'Chromium',
1146
1147 // Firefox variants
1148 'Firefox',
1149 'Firefox-308046B0AF4A39CB', // Common Firefox GUID
1150 'Firefox Developer Edition',
1151 'Firefox Nightly',
1152
1153 // Other browsers
1154 'Safari',
1155 'Waterfox',
1156 'Pale Moon',
1157 'Yandex',
1158 'IEXPLORE.EXE',
1159 'Total Browser',
1160 'Maxthon',
1161 'Seamonkey',
1162 'K-Meleon',
1163 'Basilisk',
1164 'Tor Browser',
1165 'Slimjet',
1166 'Epic Privacy Browser',
1167 'Comodo Dragon',
1168 'SRWare Iron',
1169 'Cent Browser',
1170 '360 Browser',
1171 'UC Browser',
1172 'Avast Secure Browser',
1173 'AVG Secure Browser',
1174 ];
1175
1176 // Registry paths to check
1177 $registryPaths = [
1178 ['hive' => 'HKLM', 'key' => 'SOFTWARE\\WOW6432Node\\Clients\\StartMenuInternet'],
1179 ['hive' => 'HKLM', 'key' => 'SOFTWARE\\Clients\\StartMenuInternet'],
1180 ['hive' => 'HKCU', 'key' => 'SOFTWARE\\Clients\\StartMenuInternet'],
1181 ];
1182
1183 // Check each known browser in each registry path
1184 foreach ($registryPaths as $regPath) {
1185 $hive = $regPath['hive'];
1186 $basePath = $regPath['key'];
1187
1188 foreach ($knownBrowsers as $browserName) {
1189 try {
1190 // Try to read the browser's command path
1191 $commandPath = self::registryGetValue(
1192 $hive,
1193 $basePath . '\\' . $browserName . '\\shell\\open\\command',
1194 ''
1195 );
1196
1197 if ($commandPath !== null && !empty($commandPath)) {
1198 // Extract executable path
1199 $exePath = self::extractBrowserExecutablePath($commandPath);
1200
1201 if ($exePath && !in_array($exePath, $browsers)) {
1202 Log::debug('getInstalledBrowsers: Found ' . $browserName . ': ' . $exePath);
1203 $browsers[] = $exePath;
1204 }
1205 }
1206 } catch (Exception $e) {
1207 // Browser not found, continue
1208 continue;
1209 }
1210 }
1211 }
1212
1213 $duration = round((microtime(true) - $startTime) * 1000, 2);
1214 Log::debug('getInstalledBrowsers: Found ' . count($browsers) . ' browser(s) in ' . $duration . 'ms (Hybrid - No VBS)');
1215
1216 // Always return an array (possibly empty) to simplify call sites
1217 return $browsers;
1218 }
static extractBrowserExecutablePath($commandPath)

References Log\debug(), extractBrowserExecutablePath(), and registryGetValue().

Referenced by ActionChangeBrowser\__construct().

◆ getProcessInfo()

getProcessInfo ( $pid,
$properties = [] )
static

Gets information about a specific process by PID.

Parameters
int$pidThe process ID
array$propertiesProperties to retrieve
Returns
array|false Process information or false if not found

Definition at line 236 of file class.win32native.php.

237 {
238 if (!is_numeric($pid) || $pid <= 0) {
239 return false;
240 }
241
242 if (empty($properties)) {
243 $properties = ['Name', 'ProcessID', 'ExecutablePath', 'CommandLine'];
244 }
245
246 try {
247 $wmi = self::getWmiCimv2();
248 $selectClause = implode(', ', $properties);
249 $query = "SELECT {$selectClause} FROM Win32_Process WHERE ProcessID = {$pid}";
250 $processes = $wmi->ExecQuery($query);
251
252 foreach ($processes as $proc) {
253 $result = [];
254 foreach ($properties as $prop) {
255 try {
256 $value = $proc->$prop;
257 $result[$prop] = $value ?? '';
258 } catch (Exception $e) {
259 $result[$prop] = '';
260 }
261 }
262 return $result;
263 }
264
265 return false;
266
267 } catch (Exception $e) {
269 Log::error('getProcessInfo: COM exception: ' . $e->getMessage());
270 return false;
271 }
272 }

References $proc, $result, Log\error(), getWmiCimv2(), and resetConnections().

◆ getProcessList()

getProcessList ( $properties = [])
static

Gets a list of running processes using COM/WMI. Replaces VBS WMI process query with direct PHP COM access.

Parameters
array$propertiesOptional array of properties to retrieve (e.g., ['Name', 'ProcessID', 'ExecutablePath'])
Returns
array Array of processes with requested information

Definition at line 85 of file class.win32native.php.

86 {
87 Log::debug('getProcessList: Listing processes (COM/WMI)');
88
89 $startTime = microtime(true);
90
91 try {
92 // Create WMI connection
93 $wmi = self::getWmiCimv2();
94
95 // Build WQL query
96 if (empty($properties)) {
97 $properties = ['Name', 'ProcessID', 'ExecutablePath'];
98 }
99
100 $selectClause = implode(', ', $properties);
101 $query = "SELECT {$selectClause} FROM Win32_Process";
102
103 // Execute query
104 $processes = $wmi->ExecQuery($query);
105
106 // Convert to array
107 $result = [];
108 foreach ($processes as $proc) {
109 $process = [];
110 foreach ($properties as $prop) {
111 // Handle property access
112 try {
113 $value = $proc->$prop;
114 $process[$prop] = $value ?? '';
115 } catch (Exception $e) {
116 $process[$prop] = '';
117 }
118 }
119 $result[] = $process;
120 }
121
122 $duration = round((microtime(true) - $startTime) * 1000, 2);
123 Log::debug('getProcessList: Found ' . count($result) . ' processes in ' . $duration . 'ms (COM/WMI)');
124
125 return $result;
126
127 } catch (Exception $e) {
129 Log::error('getProcessList: COM exception: ' . $e->getMessage());
130 return [];
131 }
132 }

References $proc, $result, Log\debug(), Log\error(), getWmiCimv2(), and resetConnections().

Referenced by Win32Ps\getListProcs().

◆ getServiceInfo()

getServiceInfo ( $serviceName,
$properties = [] )
static

Gets information about a Windows service using COM/WMI. Replaces VBS with direct COM/WMI access.

Parameters
string$serviceNameThe name of the service
array$propertiesOptional array of properties to retrieve
Returns
array|false Service information array, or false on failure

Definition at line 903 of file class.win32native.php.

904 {
905 Log::debug('getServiceInfo: Getting info for service ' . $serviceName . ' (COM/WMI)');
906
907 $startTime = microtime(true);
908
909 try {
910 // Create WMI connection
911 $wmi = self::getWmiCimv2();
912
913 // Default properties if none specified
914 if (empty($properties)) {
915 $properties = [
916 'Name',
917 'DisplayName',
918 'State',
919 'Status',
920 'StartMode',
921 'PathName',
922 'ProcessId',
923 'Started',
924 'StartName',
925 'Description'
926 ];
927 }
928
929 // Build WQL query
930 $selectClause = implode(', ', $properties);
931 $safeServiceName = str_replace("'", "''", $serviceName);
932 $query = "SELECT {$selectClause} FROM Win32_Service WHERE Name = '{$safeServiceName}'";
933
934 // Execute query
935 $services = $wmi->ExecQuery($query);
936
937 // Get the first (and should be only) result
938 foreach ($services as $service) {
939 $result = [];
940 foreach ($properties as $prop) {
941 try {
942 $value = $service->$prop;
943 $result[$prop] = $value ?? '';
944 } catch (Exception $e) {
945 $result[$prop] = '';
946 }
947 }
948
949 $duration = round((microtime(true) - $startTime) * 1000, 2);
950 Log::debug('getServiceInfo: Found service in ' . $duration . 'ms (COM/WMI)');
951
952 return $result;
953 }
954
955 // Service not found
956 Log::debug('getServiceInfo: Service not found');
957 return false;
958
959 } catch (Exception $e) {
961 Log::error('getServiceInfo: COM exception: ' . $e->getMessage());
962 return false;
963 }
964 }

References $result, Log\debug(), Log\error(), getWmiCimv2(), and resetConnections().

Referenced by Nssm\infos(), and Win32Service\infos().

◆ getServiceState()

getServiceState ( $serviceName)
static

Gets the state of a Windows service. Additional helper method.

Parameters
string$serviceNameThe name of the service
Returns
string|false The service state (Running, Stopped, etc.), or false if not found

Definition at line 1060 of file class.win32native.php.

1061 {
1062 try {
1063 $wmi = self::getWmiCimv2();
1064 // Sanitize the serviceName parameter to prevent WQL injection
1065 // Escape single quotes by doubling them (WQL standard)
1066 $safeServiceName = str_replace("'", "''", $serviceName);
1067 $query = "SELECT State FROM Win32_Service WHERE Name = '{$safeServiceName}'";
1068
1069 // Execute query
1070 $services = $wmi->ExecQuery($query);
1071
1072 foreach ($services as $service) {
1073 return $service->State;
1074 }
1075
1076 return false;
1077
1078 } catch (Exception $e) {
1080 return false;
1081 }
1082 }

References getWmiCimv2(), and resetConnections().

Referenced by ActionLoading\checkAllServicesStarted().

◆ getSpecialFolderPath()

getSpecialFolderPath ( $folderName)
static

Gets a Windows special folder path using COM. Replaces VBS with direct COM access.

Parameters
string$folderNameThe special folder name (Desktop, Startup, etc.)
Returns
string|false The folder path, or false on failure

Definition at line 654 of file class.win32native.php.

655 {
656 Log::debug('getSpecialFolderPath: Getting ' . $folderName . ' path (COM)');
657
658 $startTime = microtime(true);
659
660 try {
661 $shell = self::getWscriptShell();
662
663 // Get the special folder path
664 $path = $shell->SpecialFolders($folderName);
665
666 $duration = round((microtime(true) - $startTime) * 1000, 2);
667
668 if ($path && !empty($path)) {
669 // Convert to Unix-style path
670 $path = str_replace('\\', '/', $path);
671 Log::debug('getSpecialFolderPath: Found ' . $folderName . ' in ' . $duration . 'ms (COM)');
672 return $path;
673 } else {
674 Log::debug('getSpecialFolderPath: ' . $folderName . ' not found');
675 return false;
676 }
677
678 } catch (Exception $e) {
680 Log::error('getSpecialFolderPath: COM exception: ' . $e->getMessage());
681 return false;
682 }
683 }

References Log\debug(), Log\error(), getWscriptShell(), and resetConnections().

Referenced by Util\getStartupLnkPath().

◆ getWmiCimv2()

getWmiCimv2 ( )
staticprivate

Returns the cached WMI cimv2 connection, creating it on first use.

Definition at line 37 of file class.win32native.php.

37 : COM
38 {
39 if (self::$wmiCimv2 === null) {
40 self::$wmiCimv2 = new COM("winmgmts://./root/cimv2");
41 }
42 return self::$wmiCimv2;
43 }

Referenced by findProcessesByName(), getProcessInfo(), getProcessList(), getServiceInfo(), getServiceState(), killProcess(), listServices(), processExists(), and serviceExists().

◆ getWmiStdRegProv()

getWmiStdRegProv ( )
staticprivate

Returns the cached WMI StdRegProv connection, creating it on first use.

Definition at line 48 of file class.win32native.php.

48 : COM
49 {
50 if (self::$wmiStdRegProv === null) {
51 self::$wmiStdRegProv = new COM("winmgmts://./root/default:StdRegProv");
52 }
53 return self::$wmiStdRegProv;
54 }

Referenced by registryExists().

◆ getWscriptShell()

getWscriptShell ( )
staticprivate

Returns the cached WScript.Shell object, creating it on first use.

Definition at line 59 of file class.win32native.php.

59 : COM
60 {
61 if (self::$wscriptShell === null) {
62 self::$wscriptShell = new COM("WScript.Shell");
63 }
64 return self::$wscriptShell;
65 }

Referenced by createShortcut(), getSpecialFolderPath(), registryDeleteKey(), registryDeleteValue(), registryExists(), registryGetValue(), and registrySetValue().

◆ killProcess()

killProcess ( $pid)
static

Kills a process by PID using COM/WMI. Replaces VBS WMI process termination with direct PHP COM access.

Parameters
int$pidThe process ID to kill
Returns
bool True on success, false on failure

Definition at line 141 of file class.win32native.php.

142 {
143 // Validate PID
144 if (!is_numeric($pid) || $pid <= 0) {
145 Log::error('killProcess: Invalid PID: ' . $pid);
146 return false;
147 }
148
149 Log::debug('killProcess: Killing process PID ' . $pid . ' (COM/WMI)');
150
151 $startTime = microtime(true);
152
153 try {
154 // Create WMI connection
155 $wmi = self::getWmiCimv2();
156
157 // Query for specific process
158 $query = "SELECT * FROM Win32_Process WHERE ProcessID = {$pid}";
159 $processes = $wmi->ExecQuery($query);
160
161 // Terminate the process
162 $found = false;
163 $terminateResult = null;
164 foreach ($processes as $proc) {
165 $terminateResult = $proc->Terminate();
166 $found = true;
167 break;
168 }
169
170 $duration = round((microtime(true) - $startTime) * 1000, 2);
171
172 if (!$found) {
173 Log::debug('killProcess: Process ' . $pid . ' not found');
174 return false;
175 }
176
177 // Check if Terminate() returned success (0 = success)
178 if ($terminateResult !== 0) {
179 Log::error('killProcess: Terminate() failed with status code: ' . $terminateResult);
180 return false;
181 }
182
183 // Additional verification: check if process still exists after a short delay
184 usleep(100000); // Wait 100ms for termination to take effect
185 if (self::processExists($pid)) {
186 Log::error('killProcess: Process ' . $pid . ' still exists after termination attempt');
187 return false;
188 }
189
190 Log::debug('killProcess: Successfully killed process ' . $pid . ' in ' . $duration . 'ms (COM/WMI)');
191 return true;
192
193 } catch (Exception $e) {
195 Log::error('killProcess: COM exception: ' . $e->getMessage());
196 return false;
197 }
198 }

References $proc, Log\debug(), Log\error(), getWmiCimv2(), and resetConnections().

Referenced by Win32Ps\kill(), and ActionQuit\terminatePhpProcesses().

◆ listServices()

listServices ( $properties = [])
static

Lists all Windows services using COM/WMI. Additional helper method.

Parameters
array$propertiesOptional array of properties to retrieve
Returns
array Array of service information

Definition at line 973 of file class.win32native.php.

974 {
975 Log::debug('listServices: Listing all services (COM/WMI)');
976
977 $startTime = microtime(true);
978
979 try {
980 // Create WMI connection
981 $wmi = self::getWmiCimv2();
982
983 // Default properties if none specified
984 if (empty($properties)) {
985 $properties = ['Name', 'DisplayName', 'State', 'StartMode'];
986 }
987
988 // Build WQL query
989 $selectClause = implode(', ', $properties);
990 $query = "SELECT {$selectClause} FROM Win32_Service";
991
992 // Execute query
993 $services = $wmi->ExecQuery($query);
994
995 // Convert to array
996 $result = [];
997 foreach ($services as $service) {
998 $serviceInfo = [];
999 foreach ($properties as $prop) {
1000 try {
1001 $value = $service->$prop;
1002 $serviceInfo[$prop] = $value ?? '';
1003 } catch (Exception $e) {
1004 $serviceInfo[$prop] = '';
1005 }
1006 }
1007 $result[] = $serviceInfo;
1008 }
1009
1010 $duration = round((microtime(true) - $startTime) * 1000, 2);
1011 Log::debug('listServices: Found ' . count($result) . ' services in ' . $duration . 'ms (COM/WMI)');
1012
1013 return $result;
1014
1015 } catch (Exception $e) {
1017 Log::error('listServices: COM exception: ' . $e->getMessage());
1018 return [];
1019 }
1020 }

References $result, Log\debug(), Log\error(), getWmiCimv2(), and resetConnections().

◆ mapRegistryHive()

mapRegistryHive ( $hive)
staticprivate

Maps registry hive abbreviations to full names for WScript.Shell.

Parameters
string$hiveThe registry hive (HKLM, HKCU, HKCR, HKU)
Returns
string The full hive name

Definition at line 345 of file class.win32native.php.

346 {
347 $hiveMap = [
348 'HKLM' => 'HKLM',
349 'HKCU' => 'HKCU',
350 'HKCR' => 'HKCR',
351 'HKU' => 'HKU',
352 'HKEY_LOCAL_MACHINE' => 'HKLM',
353 'HKEY_CURRENT_USER' => 'HKCU',
354 'HKEY_CLASSES_ROOT' => 'HKCR',
355 'HKEY_USERS' => 'HKU',
356 ];
357
358 return isset($hiveMap[$hive]) ? $hiveMap[$hive] : $hive;
359 }

Referenced by registryDeleteKey(), registryDeleteValue(), registryExists(), registryGetValue(), and registrySetValue().

◆ processExists()

processExists ( $pid)
static

Checks if a process with the given PID exists.

Parameters
int$pidThe process ID to check
Returns
bool True if process exists, false otherwise

Definition at line 206 of file class.win32native.php.

207 {
208 if (!is_numeric($pid) || $pid <= 0) {
209 return false;
210 }
211
212 try {
213 $wmi = self::getWmiCimv2();
214 $query = "SELECT ProcessID FROM Win32_Process WHERE ProcessID = {$pid}";
215 $processes = $wmi->ExecQuery($query);
216
217 foreach ($processes as $proc) {
218 return true;
219 }
220
221 return false;
222
223 } catch (Exception $e) {
225 return false;
226 }
227 }

References $proc, getWmiCimv2(), and resetConnections().

◆ registryDeleteKey()

registryDeleteKey ( $hive,
$key )
static

Deletes a registry key and all its subkeys using COM. Additional helper method for key deletion.

Parameters
string$hiveThe registry hive (HKLM, HKCU, etc.)
string$keyThe registry key path to delete
Returns
bool True on success, false on failure

Definition at line 612 of file class.win32native.php.

613 {
614 $hive = self::mapRegistryHive($hive);
615 $regPath = $hive . '\\' . $key . '\\';
616
617 Log::debug('registryDeleteKey: Deleting ' . $regPath . ' (COM)');
618
619 try {
620 $shell = self::getWscriptShell();
621
622 // Delete the key (note the trailing backslash)
623 $shell->RegDelete($regPath);
624
625 Log::debug('registryDeleteKey: Successfully deleted key (COM)');
626 return true;
627
628 } catch (Exception $e) {
629 // If the key doesn't exist, that's OK
630 $errorMsg = $e->getMessage();
631 if (strpos($errorMsg, 'Unable to remove') !== false ||
632 strpos($errorMsg, 'Invalid root') !== false) {
633 Log::debug('registryDeleteKey: Key does not exist (already deleted)');
634 return true;
635 }
636
638 Log::error('registryDeleteKey: COM exception: ' . $e->getMessage());
639 return false;
640 }
641 }
static mapRegistryHive($hive)

References Log\debug(), Log\error(), getWscriptShell(), mapRegistryHive(), and resetConnections().

Referenced by Registry\setValue().

◆ registryDeleteValue()

registryDeleteValue ( $hive,
$key,
$value )
static

Deletes a value from the Windows registry using COM. Replaces VBS/reg.exe with direct COM access.

Parameters
string$hiveThe registry hive (HKLM, HKCU, etc.)
string$keyThe registry key path
string$valueThe value name to delete
Returns
bool True on success, false on failure

Definition at line 569 of file class.win32native.php.

570 {
571 $hive = self::mapRegistryHive($hive);
572 $regPath = $hive . '\\' . $key . '\\' . $value;
573
574 Log::debug('registryDeleteValue: Deleting ' . $regPath . ' (COM)');
575
576 $startTime = microtime(true);
577
578 try {
579 $shell = self::getWscriptShell();
580
581 // Delete the value
582 $shell->RegDelete($regPath);
583
584 $duration = round((microtime(true) - $startTime) * 1000, 2);
585 Log::debug('registryDeleteValue: Successfully deleted value in ' . $duration . 'ms (COM)');
586
587 return true;
588
589 } catch (Exception $e) {
590 // If the value doesn't exist, that's OK
591 $errorMsg = $e->getMessage();
592 if (strpos($errorMsg, 'Unable to remove') !== false ||
593 strpos($errorMsg, 'Invalid root') !== false) {
594 Log::debug('registryDeleteValue: Value does not exist (already deleted)');
595 return true;
596 }
597
599 Log::error('registryDeleteValue: COM exception: ' . $e->getMessage());
600 return false;
601 }
602 }

References Log\debug(), Log\error(), getWscriptShell(), mapRegistryHive(), and resetConnections().

Referenced by Registry\setValue().

◆ registryExists()

registryExists ( $hive,
$key,
$value = null )
static

Checks if a registry key or value exists using COM. Replaces VBS/reg.exe with direct COM access.

Uses StdRegProv for key existence checks (more reliable than WScript.Shell::RegRead). Uses WScript.Shell::RegRead for value existence checks.

Parameters
string$hiveThe registry hive (HKLM, HKCU, etc.)
string$keyThe registry key path
string | null$valueThe value name (null to check key existence only)
Returns
bool True if exists, false otherwise

Definition at line 373 of file class.win32native.php.

374 {
375 $hive = self::mapRegistryHive($hive);
376 $regPath = $hive . '\\' . $key;
377
378 Log::debug('registryExists: Checking ' . $regPath . ($value !== null ? '\\' . $value : ' (key)') . ' (COM)');
379
380 try {
381 if ($value === null) {
382 // Check if the key itself exists
383 // Use StdRegProv::EnumKey for reliable key existence checking
384 // This avoids false negatives from checking for a default value that may not exist
385 try {
386 $wmi = self::getWmiStdRegProv();
387
388 // Map hive names to WMI constants
389 $hiveConstMap = [
390 'HKCR' => 0x80000000, // HKEY_CLASSES_ROOT
391 'HKCU' => 0x80000001, // HKEY_CURRENT_USER
392 'HKLM' => 0x80000002, // HKEY_LOCAL_MACHINE
393 'HKU' => 0x80000003, // HKEY_USERS
394 ];
395
396 $hConst = $hiveConstMap[$hive] ?? 0x80000002; // Default to HKLM
397
398 // EnumKey checks if parent key's subkeys contain the requested key
399 // For root-level checks, pass empty parent
400 $pathParts = explode('\\', $key);
401
402 if (count($pathParts) === 1) {
403 // Top-level key: parent is root
404 $parentKey = '';
405 $keyName = $pathParts[0];
406 } else {
407 // Nested key: split parent from key name
408 $keyName = array_pop($pathParts);
409 $parentKey = implode('\\', $pathParts);
410 }
411
412 $subKeys = null;
413 $rc = $wmi->EnumKey($hConst, $parentKey, $subKeys);
414
415 if ($rc !== 0 || !is_array($subKeys)) {
416 Log::debug('registryExists: Key not found (EnumKey failed)');
417 return false;
418 }
419
420 // Check if our key name is in the list of subkeys
421 $exists = false;
422 foreach ($subKeys as $subKey) {
423 if (strcasecmp($subKey, $keyName) === 0) {
424 $exists = true;
425 break;
426 }
427 }
428
429 if ($exists) {
430 Log::debug('registryExists: Key found');
431 return true;
432 } else {
433 Log::debug('registryExists: Key not found');
434 return false;
435 }
436
437 } catch (Exception $e) {
438 self::$wmiStdRegProv = null;
439 Log::error('registryExists: StdRegProv exception during key check: ' . $e->getMessage());
440 return false;
441 }
442 } else {
443 // Check if a specific value exists within the key
444 // Use WScript.Shell::RegRead for value existence
445 try {
446 $shell = self::getWscriptShell();
447 $valuePath = $regPath . '\\' . $value;
448 $shell->RegRead($valuePath);
449 Log::debug('registryExists: Value found');
450 return true;
451 } catch (Exception $e) {
452 Log::debug('registryExists: Value not found');
453 return false;
454 }
455 }
456
457 } catch (Exception $e) {
459 Log::error('registryExists: COM exception: ' . $e->getMessage());
460 return false;
461 }
462 }
static getWmiStdRegProv()

References Log\debug(), Log\error(), getWmiStdRegProv(), getWscriptShell(), mapRegistryHive(), and resetConnections().

Referenced by Registry\exists().

◆ registryGetValue()

registryGetValue ( $hive,
$key,
$value = '' )
static

Gets a value from the Windows registry using COM. Replaces VBS/reg.exe with direct COM access.

Parameters
string$hiveThe registry hive (HKLM, HKCU, etc.)
string$keyThe registry key path
string$valueThe value name (empty string for default value)
Returns
mixed|null The registry value data, or null if not found

Definition at line 473 of file class.win32native.php.

474 {
475 $hive = self::mapRegistryHive($hive);
476 $regPath = $hive . '\\' . $key;
477
478 if ($value !== '') {
479 $regPath .= '\\' . $value;
480 } else {
481 // For default value, append backslash
482 $regPath .= '\\';
483 }
484
485 Log::debug('registryGetValue: Reading ' . $regPath . ' (COM)');
486
487 $startTime = microtime(true);
488
489 try {
490 $shell = self::getWscriptShell();
491 $result = $shell->RegRead($regPath);
492
493 $duration = round((microtime(true) - $startTime) * 1000, 2);
494
495 // Convert result to appropriate PHP type
496 if (is_object($result)) {
497 // COM objects need special handling
498 $result = (string)$result;
499 }
500
501 Log::debug('registryGetValue: Found value in ' . $duration . 'ms (COM)');
502 return $result;
503
504 } catch (Exception $e) {
505 Log::debug('registryGetValue: Value not found');
506 return null;
507 }
508 }

References $result, Log\debug(), getWscriptShell(), and mapRegistryHive().

Referenced by getDefaultBrowser(), getInstalledBrowsers(), Registry\getValue(), and Registry\setValue().

◆ registrySetValue()

registrySetValue ( $hive,
$key,
$value,
$data,
$type = 'REG_SZ' )
static

Sets a value in the Windows registry using COM. Replaces VBS/reg.exe with direct COM access.

Parameters
string$hiveThe registry hive (HKLM, HKCU, etc.)
string$keyThe registry key path
string$valueThe value name
mixed$dataThe data to write
string$typeThe registry type (REG_SZ, REG_EXPAND_SZ, REG_DWORD, REG_BINARY)
Returns
bool True on success, false on failure

Definition at line 521 of file class.win32native.php.

522 {
523 $hive = self::mapRegistryHive($hive);
524 $regPath = $hive . '\\' . $key . '\\' . $value;
525
526 // Validate type
527 $validTypes = ['REG_SZ', 'REG_EXPAND_SZ', 'REG_DWORD', 'REG_BINARY'];
528 if (!in_array($type, $validTypes)) {
529 Log::error('registrySetValue: Invalid type: ' . $type);
530 return false;
531 }
532
533 Log::debug('registrySetValue: Writing ' . $regPath . ' (' . $type . ') (COM)');
534
535 $startTime = microtime(true);
536
537 try {
538 $shell = self::getWscriptShell();
539
540 // Convert data based on type
541 if ($type === 'REG_DWORD') {
542 $data = (int)$data;
543 }
544
545 // Write the value
546 $shell->RegWrite($regPath, $data, $type);
547
548 $duration = round((microtime(true) - $startTime) * 1000, 2);
549 Log::debug('registrySetValue: Successfully wrote value in ' . $duration . 'ms (COM)');
550
551 return true;
552
553 } catch (Exception $e) {
555 Log::error('registrySetValue: COM exception: ' . $e->getMessage());
556 return false;
557 }
558 }

References Log\debug(), Log\error(), getWscriptShell(), mapRegistryHive(), and resetConnections().

Referenced by Registry\setValue().

◆ resetConnections()

resetConnections ( )
static

Clears all cached COM connections. Call this after a COM operation fails so the next call gets a fresh connection.

Definition at line 71 of file class.win32native.php.

71 : void
72 {
73 self::$wmiCimv2 = null;
74 self::$wmiStdRegProv = null;
75 self::$wscriptShell = null;
76 }

Referenced by createShortcut(), findProcessesByName(), getProcessInfo(), getProcessList(), getServiceInfo(), getServiceState(), getSpecialFolderPath(), killProcess(), listServices(), processExists(), registryDeleteKey(), registryDeleteValue(), registryExists(), registrySetValue(), and serviceExists().

◆ serviceExists()

serviceExists ( $serviceName)
static

Checks if a Windows service exists. Additional helper method.

Parameters
string$serviceNameThe name of the service
Returns
bool True if service exists, false otherwise

Definition at line 1029 of file class.win32native.php.

1030 {
1031 try {
1032 $wmi = self::getWmiCimv2();
1033 // Sanitize the serviceName parameter to prevent WQL injection
1034 // Escape single quotes by doubling them (WQL standard)
1035 $safeServiceName = str_replace("'", "''", $serviceName);
1036 $query = "SELECT Name FROM Win32_Service WHERE Name = '{$safeServiceName}'";
1037
1038 // Execute query
1039 $services = $wmi->ExecQuery($query);
1040
1041 foreach ($services as $service) {
1042 return true;
1043 }
1044
1045 return false;
1046
1047 } catch (Exception $e) {
1049 return false;
1050 }
1051 }

References getWmiCimv2(), and resetConnections().

Field Documentation

◆ $wmiCimv2

COM $wmiCimv2 = null
staticprivate

Definition at line 26 of file class.win32native.php.

◆ $wmiStdRegProv

COM $wmiStdRegProv = null
staticprivate

Definition at line 29 of file class.win32native.php.

◆ $wscriptShell

COM $wscriptShell = null
staticprivate

Definition at line 32 of file class.win32native.php.


The documentation for this class was generated from the following file: