WindowsRegistry.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. <?php
  2. /*
  3. * b3rtWindowsRegistry 1.0
  4. * ===========
  5. * Class for reading from and writing to the Windows registry
  6. *
  7. * Copyright (c) 2008, H. Poort
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions are met:
  12. * * Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * * Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. * * The name the copyright holder may not be used to endorse or promote
  18. * products derived from this software without specific prior written
  19. * permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY H. Poort "AS IS" AND ANY
  22. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  23. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  24. * DISCLAIMED. IN NO EVENT SHALL H. Poort BE LIABLE FOR ANY
  25. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  26. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  27. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  28. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  29. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  30. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. */
  33. class WindowsRegistry
  34. {
  35. private $RegistryObject;
  36. const HKEY_CLASSES_ROOT = 0x80000000;
  37. const HKEY_CURRENT_USER = 0x80000001;
  38. const HKEY_LOCAL_MACHINE = 0x80000002;
  39. const HKEY_USERS = 0x80000003;
  40. const HKEY_CURRENT_CONFIG = 0x80000005;
  41. const REG_NONE = 0;
  42. const REG_SZ = 1;
  43. const REG_EXPAND_SZ = 2;
  44. const REG_BINARY = 3;
  45. const REG_DWORD = 4;
  46. const REG_MULTI_SZ = 7;
  47. public function __construct()
  48. {
  49. /*$this->WbemLocator = new COM('WbemScripting.SWbemLocator');
  50. $this->WbemServices = $this->WbemLocator->ConnectServer('.', '/root/default');
  51. $this->WbemServices->Security_->ImpersonationLevel = 0x3;
  52. $this->RegObject = $this->WbemServices->Get('StdRegProv');*/
  53. // Get the WMI StdRegProv class
  54. try
  55. {
  56. $this->RegistryObject = new COM('WINMGMTS:{impersonationLevel=impersonate}!//./root/default:StdRegProv');
  57. }
  58. catch (Exception $ex)
  59. {
  60. $this->RegistryObject = NULL;
  61. throw new Exception('Could not get a connection to the registry.');
  62. }
  63. }
  64. public function __destruct()
  65. {
  66. unset($this->RegistryObject);
  67. }
  68. public function ReadValue($keyPath, $valueName, $asString = FALSE)
  69. {
  70. $hKeyId = 0;
  71. $subKey = '';
  72. if (!$this->SplitKeyPath($keyPath, $hKeyId, $subKey))
  73. return NULL;
  74. $valueType = $this->GetValueType($hKeyId, $subKey, $valueName);
  75. if (-1 == $valueType)
  76. return NULL;
  77. switch ($valueType)
  78. {
  79. case self::REG_NONE: // No support for REG_NONE
  80. return NULL;
  81. case self::REG_SZ:
  82. return $this->GetStringValue($hKeyId, $subKey, $valueName);
  83. case self::REG_EXPAND_SZ:
  84. return $this->GetExpandedStringValue($hKeyId, $subKey, $valueName);
  85. case self::REG_BINARY:
  86. return $this->GetBinaryValue($hKeyId, $subKey, $valueName, $asString);
  87. case self::REG_DWORD:
  88. return $this->GetDWORDValue($hKeyId, $subKey, $valueName, $asString);
  89. case self::REG_MULTI_SZ:
  90. return $this->GetMultiStringValue($hKeyId, $subKey, $valueName, $asString);
  91. }
  92. }
  93. public function WriteValue($keyPath, $valueName, $valueContents, $forceType = -1)
  94. {
  95. $hKeyId = 0;
  96. $subKey = '';
  97. if (!$this->SplitKeyPath($keyPath, $hKeyId, $subKey))
  98. return FALSE;
  99. if (!$this->CreateKey($keyPath))
  100. return FALSE;
  101. if (-1 != $forceType)
  102. $valueType = $forceType;
  103. else
  104. $valueType = $this->GetValueType($hKeyId, $subKey, $valueName);
  105. if (self::REG_NONE == $valueType) // No support for REG_NONE
  106. return FALSE;
  107. if (-1 == $valueType) // valueType unknown
  108. {
  109. if (is_string($valueContents))
  110. $valueType = self::REG_SZ;
  111. else if (is_int($valueContents))
  112. $valueType = self::REG_DWORD;
  113. else if (is_array($valueContents) && count($valueContents))
  114. {
  115. if (is_string($valueContents[0]))
  116. $valueType = self::REG_MULTI_SZ;
  117. else if (is_int($valueContents[0]))
  118. $valueType = self::REG_BINARY;
  119. }
  120. }
  121. if (-1 == $valueType) // valueType still unknown, leave
  122. return FALSE;
  123. $result = -1;
  124. if ((self::REG_SZ == $valueType) || (self::REG_EXPAND_SZ == $valueType))
  125. {
  126. //if (!is_string($valueContents))
  127. // $valueContents = strval($valueContents);
  128. if (self::REG_SZ == $valueType)
  129. $result = $this->RegistryObject->SetStringValue($hKeyId, $subKey, $valueName, $valueContents);
  130. else
  131. $result = $this->RegistryObject->SetExpandedStringValue($hKeyId, $subKey, $valueName, $valueContents);
  132. }
  133. else if (self::REG_DWORD == $valueType)
  134. {
  135. //if (!is_int($valueContents))
  136. // $valueContents = intval($valueContents);
  137. $result = $this->RegistryObject->SetDWORDValue($hKeyId, $subKey, $valueName, $valueContents);
  138. }
  139. else if (self::REG_MULTI_SZ == $valueType)
  140. {
  141. if (!is_array($valueContents) || !is_string($valueContents[0]))
  142. return FALSE;
  143. $result = $this->RegistryObject->SetMultiStringValue($hKeyId, $subKey, $valueName, $valueContents);
  144. }
  145. else if (self::REG_BINARY == $valueType)
  146. {
  147. if (!is_array($valueContents) || !is_int($valueContents[0]))
  148. return FALSE;
  149. $result = $this->RegistryObject->SetBinaryValue($hKeyId, $subKey, $valueName, $valueContents);
  150. }
  151. return (0 == $result);
  152. }
  153. public function DeleteValue($keyPath, $valueName)
  154. {
  155. $hKeyId = 0;
  156. $subKey = '';
  157. if (!$this->SplitKeyPath($keyPath, $hKeyId, $subKey))
  158. return FALSE;
  159. return ($this->RegistryObject->DeleteValue($hKeyId, $subKey, $valueName) == 0);
  160. }
  161. public function GetValueNames($keyPath, $includeTypes = FALSE)
  162. {
  163. $hKeyId = 0;
  164. $subKey = '';
  165. if (!$this->SplitKeyPath($keyPath, $hKeyId, $subKey))
  166. return FALSE;
  167. $valueList = array();
  168. if (!$this->EnumValues($hKeyId, $subKey, $valueList))
  169. return NULL;
  170. if (!$includeTypes)
  171. {
  172. $valueNames = array();
  173. for ($i = 0, $cnt = count($valueList); $i < $cnt; $i++)
  174. $valueNames[] = $valueList[$i][0];
  175. return $valueNames;
  176. }
  177. else
  178. return $valueList;
  179. }
  180. public function CreateKey($keyPath)
  181. {
  182. $hKeyId = 0;
  183. $subKey = '';
  184. if (!$this->SplitKeyPath($keyPath, $hKeyId, $subKey))
  185. return FALSE;
  186. return ($this->RegistryObject->CreateKey($hKeyId, $subKey) == 0);
  187. }
  188. public function DeleteKey($keyPath, $deleteSubkeys = FALSE)
  189. {
  190. $hKeyId = 0;
  191. $subKey = '';
  192. if (!$this->SplitKeyPath($keyPath, $hKeyId, $subKey))
  193. return FALSE;
  194. if (!$deleteSubkeys)
  195. return ($this->RegistryObject->DeleteKey($hKeyId, $subKey) == 0);
  196. else
  197. {
  198. if (!function_exists('deleteSubKeysRecursive'))
  199. {
  200. function deleteSubKeysRecursive(&$thisRef, $hKeyId, $subKey)
  201. {
  202. $mapHkeysToString = array(
  203. WindowsRegistry::HKEY_CLASSES_ROOT => 'HKEY_CLASSES_ROOT',
  204. WindowsRegistry::HKEY_CURRENT_USER => 'HKEY_CURRENT_USER',
  205. WindowsRegistry::HKEY_LOCAL_MACHINE => 'HKEY_LOCAL_MACHINE',
  206. WindowsRegistry::HKEY_USERS => 'HKEY_USERS',
  207. WindowsRegistry::HKEY_CURRENT_CONFIG => 'HKEY_CURRENT_CONFIG');
  208. if (!isset($mapHkeysToString[$hKeyId]))
  209. return FALSE;
  210. $subKeys = $thisRef->GetSubKeys($mapHkeysToString[$hKeyId] . '\\' . $subKey);
  211. if ($subKeys)
  212. {
  213. for ($i = 0, $cnt = count($subKeys); $i < $cnt; $i++)
  214. {
  215. if (!deleteSubKeysRecursive($thisRef, $hKeyId, $subKey . '\\' . $subKeys[$i]))
  216. return FALSE;
  217. }
  218. }
  219. return ($thisRef->DeleteKey($mapHkeysToString[$hKeyId] . '\\' . $subKey));
  220. }
  221. }
  222. return deleteSubKeysRecursive($this, $hKeyId, $subKey);
  223. }
  224. }
  225. public function GetSubKeys($keyPath)
  226. {
  227. $hKeyId = 0;
  228. $subKey = '';
  229. if (!$this->SplitKeyPath($keyPath, $hKeyId, $subKey))
  230. return FALSE;
  231. $keyList = array();
  232. if (!$this->EnumKeys($hKeyId, $subKey, $keyList))
  233. return NULL;
  234. return $keyList;
  235. }
  236. public function KeyExists($keyPath)
  237. {
  238. $hKeyId = 0;
  239. $subKey = '';
  240. if (!$this->SplitKeyPath($keyPath, $hKeyId, $subKey))
  241. return FALSE;
  242. return ($this->RegistryObject->EnumValues($hKeyId, $subKey, new VARIANT(), new VARIANT()) == 0);
  243. }
  244. // PRIVATE FUNCTIONS
  245. // ================================
  246. private function SplitKeyPath($keyPath, &$hKeyIdResult, &$subKeyResult)
  247. {
  248. $hKeyIdResult = 0;
  249. $subKeyResult = 'foo';
  250. $splitPath = explode('\\', $keyPath, 2);
  251. if (FALSE === $splitPath)
  252. return FALSE;
  253. else if (count($splitPath) == 1)
  254. $splitPath[1] = '';
  255. $subKeyResult = $splitPath[1];
  256. switch ($splitPath[0])
  257. {
  258. case 'HKEY_CLASSES_ROOT':
  259. $hKeyIdResult = self::HKEY_CLASSES_ROOT;
  260. break;
  261. case 'HKEY_CURRENT_USER':
  262. $hKeyIdResult = self::HKEY_CURRENT_USER;
  263. break;
  264. case 'HKEY_LOCAL_MACHINE':
  265. $hKeyIdResult = self::HKEY_LOCAL_MACHINE;
  266. break;
  267. case 'HKEY_USERS':
  268. $hKeyIdResult = self::HKEY_USERS;
  269. break;
  270. case 'HKEY_CURRENT_CONFIG':
  271. $hKeyIdResult = self::HKEY_CURRENT_CONFIG;
  272. break;
  273. default:
  274. return FALSE;
  275. }
  276. return TRUE;
  277. }
  278. private function EnumKeys($hKeyId, $subKey, &$keyList)
  279. {
  280. $keyNames = new VARIANT();
  281. if ($this->RegistryObject->EnumKey($hKeyId, $subKey, $keyNames) != 0)
  282. return FALSE;
  283. $keyList = array();
  284. if (variant_get_type($keyNames) == (VT_VARIANT | VT_ARRAY))
  285. {
  286. for ($i = 0, $cnt = count($keyNames); $i < $cnt; $i++)
  287. $keyList[] = strval($keyNames[$i]);
  288. }
  289. return TRUE;
  290. }
  291. private function EnumValues($hKeyId, $subKey, &$valueList)
  292. {
  293. $valueNames = new VARIANT();
  294. $valueTypes = new VARIANT();
  295. if ($this->RegistryObject->EnumValues($hKeyId, $subKey, $valueNames, $valueTypes) != 0)
  296. return FALSE;
  297. $valueList = array();
  298. if (variant_get_type($valueNames) == (VT_VARIANT | VT_ARRAY))
  299. {
  300. for ($i = 0, $cnt = count($valueNames); $i < $cnt; $i++)
  301. $valueList[] = array(strval($valueNames[$i]), intval($valueTypes[$i]));
  302. }
  303. else // Handle a bug in StdRegProv's EnumValues (http://groups.google.com/group/microsoft.public.win32.programmer.wmi/browse_thread/thread/d74c0ca865887e6b)
  304. {
  305. if ($this->GetStringValue($hKeyId, $subKey, '') != NULL)
  306. $valueList[] = array('', self::REG_SZ);
  307. else if ($this->GetDWORDValue($hKeyId, $subKey, '') != NULL)
  308. $valueList[] = array('', self::REG_DWORD);
  309. else if ($this->GetExpandedStringValue($hKeyId, $subKey, '') != NULL)
  310. $valueList[] = array('', self::REG_EXPAND_SZ);
  311. else if ($this->GetBinaryValue($hKeyId, $subKey, '') != NULL)
  312. $valueList[] = array('', self::REG_BINARY);
  313. else if ($this->GetMultiStringValue($hKeyId, $subKey, '') != NULL)
  314. $valueList[] = array('', self::REG_MULTI_SZ);
  315. }
  316. return TRUE;
  317. }
  318. private function GetValueType($hKeyId, $subKey, $valueName)
  319. {
  320. $valueList = array();
  321. if (!$this->EnumValues($hKeyId, $subKey, $valueList))
  322. return -1;
  323. for ($i = 0, $cnt = count($valueList); $i < $cnt; $i++)
  324. {
  325. if ($valueList[$i][0] == $valueName)
  326. return $valueList[$i][1];
  327. }
  328. return -1;
  329. }
  330. private function GetStringValue($hKeyId, $subKey, $valueName)
  331. {
  332. $stringValue = new VARIANT();
  333. return (($this->RegistryObject->GetStringValue($hKeyId, $subKey, $valueName, $stringValue) == 0) ?
  334. strval($stringValue) : NULL);
  335. }
  336. private function GetExpandedStringValue($hKeyId, $subKey, $valueName)
  337. {
  338. $expandStringValue = new VARIANT();
  339. return ((0 == $this->RegistryObject->GetExpandedStringValue($hKeyId, $subKey, $valueName, $expandStringValue)) ?
  340. strval($expandStringValue) : NULL);
  341. }
  342. private function GetBinaryValue($hKeyId, $subKey, $valueName, $asString = FALSE)
  343. {
  344. $binaryValue = new VARIANT();
  345. if ($this->RegistryObject->GetBinaryValue($hKeyId, $subKey, $valueName, $binaryValue) != 0)
  346. return NULL;
  347. if ($asString)
  348. {
  349. $result = '';
  350. for ($i = 0, $cnt = count($binaryValue); $i < $cnt; $i++)
  351. $result .= dechex($binaryValue[$i]) . ((($cnt - 1) != $i) ? ' ' : '');
  352. }
  353. else
  354. {
  355. $result = array();
  356. for ($i = 0, $cnt = count($binaryValue); $i < $cnt; $i++)
  357. $result .= intval($binaryValue[$i]);
  358. }
  359. return $result;
  360. }
  361. private function GetDWORDValue($hKeyId, $subKey, $valueName, $asString = FALSE)
  362. {
  363. $dwordValue = new VARIANT();
  364. return (($this->RegistryObject->GetDWORDValue($hKeyId, $subKey, $valueName, $dwordValue) == 0) ?
  365. ($asString ? strval($dwordValue) : intval($dwordValue)) : NULL);
  366. }
  367. private function GetMultiStringValue($hKeyId, $subKey, $valueName, $asString = FALSE)
  368. {
  369. $multiStringValue = new VARIANT();
  370. if ($this->RegistryObject->GetMultiStringValue($hKeyId, $subKey, $valueName, $multiStringValue) != 0)
  371. return NULL;
  372. if ($asString)
  373. {
  374. $result = '';
  375. for ($i = 0, $cnt = count($multiStringValue); $i < $cnt; $i++)
  376. $result .= strval($multiStringValue[$i]) . ((($cnt - 1) != $i) ? "\n" : '');
  377. }
  378. else
  379. {
  380. $result = array();
  381. for ($i = 0, $cnt = count($multiStringValue); $i < $cnt; $i++)
  382. $result[] = strval($multiStringValue[$i]);
  383. }
  384. return $result;
  385. }
  386. }
  387. ?>