registry.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /*
  2. +----------------------------------------------------------------------+
  3. | PHP Version 7 |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1997-2018 The PHP Group |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. | Author: Zeev Suraski <zeev@php.net> |
  16. +----------------------------------------------------------------------+
  17. */
  18. #include "php.h"
  19. #include "php_ini.h"
  20. #include "php_win32_globals.h"
  21. #define PHP_REGISTRY_KEY "SOFTWARE\\PHP"
  22. #define PHP_VER1(V1) #V1
  23. #define PHP_VER2(V1,V2) #V1"."#V2
  24. #define PHP_VER3(V1,V2,V3) #V1"."#V2"."#V3
  25. #define PHP_REGISTRY_KEYV(VER) PHP_REGISTRY_KEY"\\"VER
  26. #define PHP_REGISTRY_KEY1(V1) PHP_REGISTRY_KEY"\\"PHP_VER1(V1)
  27. #define PHP_REGISTRY_KEY2(V1,V2) PHP_REGISTRY_KEY"\\"PHP_VER2(V1,V2)
  28. #define PHP_REGISTRY_KEY3(V1,V2,V3) PHP_REGISTRY_KEY"\\"PHP_VER3(V1,V2,V3)
  29. static const char* registry_keys[] = {
  30. PHP_REGISTRY_KEYV(PHP_VERSION),
  31. PHP_REGISTRY_KEY3(PHP_MAJOR_VERSION, PHP_MINOR_VERSION, PHP_RELEASE_VERSION),
  32. PHP_REGISTRY_KEY2(PHP_MAJOR_VERSION, PHP_MINOR_VERSION),
  33. PHP_REGISTRY_KEY1(PHP_MAJOR_VERSION),
  34. PHP_REGISTRY_KEY,
  35. NULL
  36. };
  37. static int OpenPhpRegistryKey(char* sub_key, HKEY *hKey)
  38. {/*{{{*/
  39. const char **key_name = registry_keys;
  40. if (sub_key) {
  41. size_t main_key_len;
  42. size_t sub_key_len = strlen(sub_key);
  43. char *reg_key;
  44. while (*key_name) {
  45. LONG ret;
  46. main_key_len = strlen(*key_name);
  47. reg_key = emalloc(main_key_len + sub_key_len + 1);
  48. memcpy(reg_key, *key_name, main_key_len);
  49. memcpy(reg_key + main_key_len, sub_key, sub_key_len + 1);
  50. ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, reg_key, 0, KEY_READ, hKey);
  51. efree(reg_key);
  52. if (ret == ERROR_SUCCESS) {
  53. return 1;
  54. }
  55. ++key_name;
  56. }
  57. } else {
  58. while (*key_name) {
  59. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, *key_name, 0, KEY_READ, hKey) == ERROR_SUCCESS) {
  60. return 1;
  61. }
  62. ++key_name;
  63. }
  64. }
  65. return 0;
  66. }/*}}}*/
  67. static int LoadDirectory(HashTable *directories, HKEY key, char *path, int path_len, HashTable *parent_ht)
  68. {/*{{{*/
  69. DWORD keys, values, max_key, max_name, max_value;
  70. int ret = 0;
  71. HashTable *ht = NULL;
  72. if (RegQueryInfoKey(key, NULL, NULL, NULL, &keys, &max_key, NULL, &values, &max_name, &max_value, NULL, NULL) == ERROR_SUCCESS) {
  73. if (values) {
  74. DWORD i;
  75. char *name = (char*)emalloc(max_name+1);
  76. char *value = (char*)emalloc(max_value+1);
  77. DWORD name_len, type, value_len;
  78. for (i = 0; i < values; i++) {
  79. name_len = max_name+1;
  80. value_len = max_value+1;
  81. memset(name, '\0', max_name+1);
  82. memset(value, '\0', max_value+1);
  83. if (RegEnumValue(key, i, name, &name_len, NULL, &type, value, &value_len) == ERROR_SUCCESS) {
  84. if ((type == REG_SZ) || (type == REG_EXPAND_SZ)) {
  85. zval data;
  86. if (!ht) {
  87. ht = (HashTable*)malloc(sizeof(HashTable));
  88. if (!ht) {
  89. return ret;
  90. }
  91. zend_hash_init(ht, 0, NULL, ZVAL_INTERNAL_PTR_DTOR, 1);
  92. }
  93. ZVAL_PSTRINGL(&data, value, value_len-1);
  94. zend_hash_str_update(ht, name, name_len, &data);
  95. }
  96. }
  97. }
  98. if (ht) {
  99. if (parent_ht) {
  100. zend_string *index;
  101. zend_ulong num;
  102. zval *tmpdata;
  103. ZEND_HASH_FOREACH_KEY_VAL(parent_ht, num, index, tmpdata) {
  104. zend_hash_add(ht, index, tmpdata);
  105. } ZEND_HASH_FOREACH_END();
  106. }
  107. zend_hash_str_update_mem(directories, path, path_len, ht, sizeof(HashTable));
  108. ret = 1;
  109. }
  110. efree(name);
  111. efree(value);
  112. }
  113. if (ht == NULL) {
  114. ht = parent_ht;
  115. }
  116. if (keys) {
  117. DWORD i;
  118. char *name = (char*)emalloc(max_key+1);
  119. char *new_path = (char*)emalloc(path_len+max_key+2);
  120. DWORD name_len;
  121. FILETIME t;
  122. HKEY subkey;
  123. for (i = 0; i < keys; i++) {
  124. name_len = max_key+1;
  125. if (RegEnumKeyEx(key, i, name, &name_len, NULL, NULL, NULL, &t) == ERROR_SUCCESS) {
  126. if (RegOpenKeyEx(key, name, 0, KEY_READ, &subkey) == ERROR_SUCCESS) {
  127. if (path_len) {
  128. memcpy(new_path, path, path_len);
  129. new_path[path_len] = '/';
  130. memcpy(new_path+path_len+1, name, name_len+1);
  131. zend_str_tolower(new_path, path_len+name_len+1);
  132. name_len += path_len+1;
  133. } else {
  134. memcpy(new_path, name, name_len+1);
  135. zend_str_tolower(new_path, name_len);
  136. }
  137. if (LoadDirectory(directories, subkey, new_path, name_len, ht)) {
  138. ret = 1;
  139. }
  140. RegCloseKey(subkey);
  141. }
  142. }
  143. }
  144. efree(new_path);
  145. efree(name);
  146. }
  147. }
  148. return ret;
  149. }/*}}}*/
  150. static void delete_internal_hashtable(zval *zv)
  151. {/*{{{*/
  152. HashTable *ht = (HashTable *)Z_PTR_P(zv);
  153. zend_hash_destroy(ht);
  154. free(ht);
  155. }/*}}}*/
  156. #define RegNotifyFlags (REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_ATTRIBUTES | REG_NOTIFY_CHANGE_LAST_SET)
  157. void UpdateIniFromRegistry(char *path)
  158. {/*{{{*/
  159. char *p, *orig_path;
  160. int path_len;
  161. if(!path) {
  162. return;
  163. }
  164. if (!PW32G(registry_directories)) {
  165. PW32G(registry_directories) = (HashTable*)malloc(sizeof(HashTable));
  166. if (!PW32G(registry_directories)) {
  167. return;
  168. }
  169. zend_hash_init(PW32G(registry_directories), 0, NULL, delete_internal_hashtable, 1);
  170. if (!OpenPhpRegistryKey("\\Per Directory Values", &PW32G(registry_key))) {
  171. PW32G(registry_key) = NULL;
  172. return;
  173. }
  174. PW32G(registry_event) = CreateEvent(NULL, TRUE, FALSE, NULL);
  175. if (PW32G(registry_event)) {
  176. RegNotifyChangeKeyValue(PW32G(registry_key), TRUE, RegNotifyFlags, PW32G(registry_event), TRUE);
  177. }
  178. if (!LoadDirectory(PW32G(registry_directories), PW32G(registry_key), "", 0, NULL)) {
  179. return;
  180. }
  181. } else if (PW32G(registry_event) && WaitForSingleObject(PW32G(registry_event), 0) == WAIT_OBJECT_0) {
  182. RegNotifyChangeKeyValue(PW32G(registry_key), TRUE, RegNotifyFlags, PW32G(registry_event), TRUE);
  183. zend_hash_clean(PW32G(registry_directories));
  184. if (!LoadDirectory(PW32G(registry_directories), PW32G(registry_key), "", 0, NULL)) {
  185. return;
  186. }
  187. } else if (zend_hash_num_elements(PW32G(registry_directories)) == 0) {
  188. return;
  189. }
  190. orig_path = path = estrdup(path);
  191. /* Get rid of C:, if exists */
  192. p = strchr(path, ':');
  193. if (p) {
  194. *p = path[0]; /* replace the colon with the drive letter */
  195. path = p; /* make path point to the drive letter */
  196. } else {
  197. if (path[0] != '\\' && path[0] != '/') {
  198. char tmp_buf[MAXPATHLEN], *cwd;
  199. char drive_letter;
  200. /* get current working directory and prepend it to the path */
  201. if (!VCWD_GETCWD(tmp_buf, MAXPATHLEN)) {
  202. efree(orig_path);
  203. return;
  204. }
  205. cwd = strchr(tmp_buf, ':');
  206. if (!cwd) {
  207. drive_letter = 'C';
  208. cwd = tmp_buf;
  209. } else {
  210. drive_letter = tmp_buf[0];
  211. cwd++;
  212. }
  213. while (*cwd == '\\' || *cwd == '/') {
  214. cwd++;
  215. }
  216. spprintf(&path, 0, "%c\\%s\\%s", drive_letter, cwd, orig_path);
  217. efree(orig_path);
  218. orig_path = path;
  219. }
  220. }
  221. path_len = 0;
  222. while (path[path_len] != 0) {
  223. if (path[path_len] == '\\') {
  224. path[path_len] = '/';
  225. }
  226. path_len++;
  227. }
  228. zend_str_tolower(path, path_len);
  229. while (path_len > 0) {
  230. HashTable *ht = (HashTable *)zend_hash_str_find_ptr(PW32G(registry_directories), path, path_len);
  231. if (ht != NULL) {
  232. zend_string *index;
  233. zval *data;
  234. ZEND_HASH_FOREACH_STR_KEY_VAL(ht, index, data) {
  235. zend_alter_ini_entry(index, Z_STR_P(data), PHP_INI_USER, PHP_INI_STAGE_ACTIVATE);
  236. } ZEND_HASH_FOREACH_END();
  237. }
  238. do {
  239. path_len--;
  240. } while (path_len > 0 && path[path_len] != '/');
  241. path[path_len] = 0;
  242. }
  243. efree(orig_path);
  244. }/*}}}*/
  245. #define PHPRC_REGISTRY_NAME "IniFilePath"
  246. char *GetIniPathFromRegistry()
  247. {/*{{{*/
  248. char *reg_location = NULL;
  249. HKEY hKey;
  250. if (OpenPhpRegistryKey(NULL, &hKey)) {
  251. DWORD buflen = MAXPATHLEN;
  252. reg_location = emalloc(MAXPATHLEN+1);
  253. if(RegQueryValueEx(hKey, PHPRC_REGISTRY_NAME, 0, NULL, reg_location, &buflen) != ERROR_SUCCESS) {
  254. RegCloseKey(hKey);
  255. efree(reg_location);
  256. reg_location = NULL;
  257. return reg_location;
  258. }
  259. RegCloseKey(hKey);
  260. }
  261. return reg_location;
  262. }/*}}}*/
  263. /*
  264. * Local variables:
  265. * tab-width: 4
  266. * c-basic-offset: 4
  267. * End:
  268. * vim600: sw=4 ts=4 fdm=marker
  269. * vim<600: sw=4 ts=4
  270. */