registry.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. #include "php.h"
  2. #include "php_ini.h"
  3. #include "php_win32_globals.h"
  4. #define PHP_REGISTRY_KEY "SOFTWARE\\PHP"
  5. #define PHP_VER1(V1) #V1
  6. #define PHP_VER2(V1,V2) #V1"."#V2
  7. #define PHP_VER3(V1,V2,V3) #V1"."#V2"."#V3
  8. #define PHP_REGISTRY_KEYV(VER) PHP_REGISTRY_KEY"\\"VER
  9. #define PHP_REGISTRY_KEY1(V1) PHP_REGISTRY_KEY"\\"PHP_VER1(V1)
  10. #define PHP_REGISTRY_KEY2(V1,V2) PHP_REGISTRY_KEY"\\"PHP_VER2(V1,V2)
  11. #define PHP_REGISTRY_KEY3(V1,V2,V3) PHP_REGISTRY_KEY"\\"PHP_VER3(V1,V2,V3)
  12. static const char* registry_keys[] = {
  13. PHP_REGISTRY_KEYV(PHP_VERSION),
  14. PHP_REGISTRY_KEY3(PHP_MAJOR_VERSION, PHP_MINOR_VERSION, PHP_RELEASE_VERSION),
  15. PHP_REGISTRY_KEY2(PHP_MAJOR_VERSION, PHP_MINOR_VERSION),
  16. PHP_REGISTRY_KEY1(PHP_MAJOR_VERSION),
  17. PHP_REGISTRY_KEY,
  18. NULL
  19. };
  20. static int OpenPhpRegistryKey(char* sub_key, HKEY *hKey)
  21. {
  22. const char **key_name = registry_keys;
  23. if (sub_key) {
  24. int main_key_len;
  25. int sub_key_len = strlen(sub_key);
  26. char *reg_key;
  27. while (*key_name) {
  28. LONG ret;
  29. main_key_len = strlen(*key_name);
  30. reg_key = emalloc(main_key_len + sub_key_len + 1);
  31. memcpy(reg_key, *key_name, main_key_len);
  32. memcpy(reg_key + main_key_len, sub_key, sub_key_len + 1);
  33. ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, reg_key, 0, KEY_READ, hKey);
  34. efree(reg_key);
  35. if (ret == ERROR_SUCCESS) {
  36. return 1;
  37. }
  38. ++key_name;
  39. }
  40. } else {
  41. while (*key_name) {
  42. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, *key_name, 0, KEY_READ, hKey) == ERROR_SUCCESS) {
  43. return 1;
  44. }
  45. ++key_name;
  46. }
  47. }
  48. return 0;
  49. }
  50. static int LoadDirectory(HashTable *directories, HKEY key, char *path, int path_len, HashTable *parent_ht)
  51. {
  52. DWORD keys, values, max_key, max_name, max_value;
  53. int ret = 0;
  54. HashTable *ht = NULL;
  55. if (RegQueryInfoKey(key, NULL, NULL, NULL, &keys, &max_key, NULL, &values, &max_name, &max_value, NULL, NULL) == ERROR_SUCCESS) {
  56. if (values) {
  57. DWORD i;
  58. char *name = (char*)emalloc(max_name+1);
  59. char *value = (char*)emalloc(max_value+1);
  60. DWORD name_len, type, value_len;
  61. zval *data;
  62. for (i = 0; i < values; i++) {
  63. name_len = max_name+1;
  64. value_len = max_value+1;
  65. if (RegEnumValue(key, i, name, &name_len, NULL, &type, value, &value_len) == ERROR_SUCCESS) {
  66. if ((type == REG_SZ) || (type == REG_EXPAND_SZ)) {
  67. if (!ht) {
  68. ht = (HashTable*)malloc(sizeof(HashTable));
  69. if (!ht) {
  70. return ret;
  71. }
  72. zend_hash_init(ht, 0, NULL, ZVAL_INTERNAL_PTR_DTOR, 1);
  73. }
  74. data = (zval*)malloc(sizeof(zval));
  75. if (!data) {
  76. return ret;
  77. }
  78. INIT_PZVAL(data);
  79. Z_STRVAL_P(data) = zend_strndup(value, value_len-1);
  80. Z_STRLEN_P(data) = value_len-1;
  81. Z_TYPE_P(data) = IS_STRING;
  82. zend_hash_update(ht, name, name_len+1, &data, sizeof(zval*), NULL);
  83. }
  84. }
  85. }
  86. if (ht) {
  87. if (parent_ht) {
  88. HashPosition pos;
  89. char *index;
  90. uint index_len;
  91. ulong num;
  92. zval **tmpdata;
  93. for (zend_hash_internal_pointer_reset_ex(parent_ht, &pos);
  94. zend_hash_get_current_data_ex(parent_ht, (void**)&tmpdata, &pos) == SUCCESS &&
  95. zend_hash_get_current_key_ex(parent_ht, &index, &index_len, &num, 0, &pos) == HASH_KEY_IS_STRING;
  96. zend_hash_move_forward_ex(parent_ht, &pos)) {
  97. if (zend_hash_add(ht, index, index_len, tmpdata, sizeof(zval*), NULL) == SUCCESS) {
  98. Z_ADDREF_PP(tmpdata);
  99. }
  100. }
  101. }
  102. zend_hash_update(directories, path, path_len+1, &ht, sizeof(HashTable*), NULL);
  103. ret = 1;
  104. }
  105. efree(name);
  106. efree(value);
  107. }
  108. if (ht == NULL) {
  109. ht = parent_ht;
  110. }
  111. if (keys) {
  112. DWORD i;
  113. char *name = (char*)emalloc(max_key+1);
  114. char *new_path = (char*)emalloc(path_len+max_key+2);
  115. DWORD name_len;
  116. FILETIME t;
  117. HKEY subkey;
  118. for (i = 0; i < keys; i++) {
  119. name_len = max_key+1;
  120. if (RegEnumKeyEx(key, i, name, &name_len, NULL, NULL, NULL, &t) == ERROR_SUCCESS) {
  121. if (RegOpenKeyEx(key, name, 0, KEY_READ, &subkey) == ERROR_SUCCESS) {
  122. if (path_len) {
  123. memcpy(new_path, path, path_len);
  124. new_path[path_len] = '/';
  125. memcpy(new_path+path_len+1, name, name_len+1);
  126. zend_str_tolower(new_path, path_len+name_len+1);
  127. name_len += path_len+1;
  128. } else {
  129. memcpy(new_path, name, name_len+1);
  130. zend_str_tolower(new_path, name_len);
  131. }
  132. if (LoadDirectory(directories, subkey, new_path, name_len, ht)) {
  133. ret = 1;
  134. }
  135. RegCloseKey(subkey);
  136. }
  137. }
  138. }
  139. efree(new_path);
  140. efree(name);
  141. }
  142. }
  143. return ret;
  144. }
  145. static void delete_internal_hashtable(void *data)
  146. {
  147. zend_hash_destroy(*(HashTable**)data);
  148. free(*(HashTable**)data);
  149. }
  150. #define RegNotifyFlags (REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_ATTRIBUTES | REG_NOTIFY_CHANGE_LAST_SET)
  151. void UpdateIniFromRegistry(char *path TSRMLS_DC)
  152. {
  153. char *p, *orig_path;
  154. int path_len;
  155. HashTable **pht;
  156. if(!path) {
  157. return;
  158. }
  159. if (!PW32G(registry_directories)) {
  160. PW32G(registry_directories) = (HashTable*)malloc(sizeof(HashTable));
  161. if (!PW32G(registry_directories)) {
  162. return;
  163. }
  164. zend_hash_init(PW32G(registry_directories), 0, NULL, delete_internal_hashtable, 1);
  165. if (!OpenPhpRegistryKey("\\Per Directory Values", &PW32G(registry_key))) {
  166. PW32G(registry_key) = NULL;
  167. return;
  168. }
  169. PW32G(registry_event) = CreateEvent(NULL, TRUE, FALSE, NULL);
  170. if (PW32G(registry_event)) {
  171. RegNotifyChangeKeyValue(PW32G(registry_key), TRUE, RegNotifyFlags, PW32G(registry_event), TRUE);
  172. }
  173. if (!LoadDirectory(PW32G(registry_directories), PW32G(registry_key), "", 0, NULL)) {
  174. return;
  175. }
  176. } else if (PW32G(registry_event) && WaitForSingleObject(PW32G(registry_event), 0) == WAIT_OBJECT_0) {
  177. RegNotifyChangeKeyValue(PW32G(registry_key), TRUE, RegNotifyFlags, PW32G(registry_event), TRUE);
  178. zend_hash_clean(PW32G(registry_directories));
  179. if (!LoadDirectory(PW32G(registry_directories), PW32G(registry_key), "", 0, NULL)) {
  180. return;
  181. }
  182. } else if (zend_hash_num_elements(PW32G(registry_directories)) == 0) {
  183. return;
  184. }
  185. orig_path = path = estrdup(path);
  186. /* Get rid of C:, if exists */
  187. p = strchr(path, ':');
  188. if (p) {
  189. *p = path[0]; /* replace the colon with the drive letter */
  190. path = p; /* make path point to the drive letter */
  191. } else {
  192. if (path[0] != '\\' && path[0] != '/') {
  193. char tmp_buf[MAXPATHLEN], *cwd;
  194. char drive_letter;
  195. /* get current working directory and prepend it to the path */
  196. if (!VCWD_GETCWD(tmp_buf, MAXPATHLEN)) {
  197. efree(orig_path);
  198. return;
  199. }
  200. cwd = strchr(tmp_buf, ':');
  201. if (!cwd) {
  202. drive_letter = 'C';
  203. cwd = tmp_buf;
  204. } else {
  205. drive_letter = tmp_buf[0];
  206. cwd++;
  207. }
  208. while (*cwd == '\\' || *cwd == '/') {
  209. cwd++;
  210. }
  211. spprintf(&path, 0, "%c\\%s\\%s", drive_letter, cwd, orig_path);
  212. efree(orig_path);
  213. orig_path = path;
  214. }
  215. }
  216. path_len = 0;
  217. while (path[path_len] != 0) {
  218. if (path[path_len] == '\\') {
  219. path[path_len] = '/';
  220. }
  221. path_len++;
  222. }
  223. zend_str_tolower(path, path_len);
  224. while (path_len >= 0) {
  225. if (zend_hash_find(PW32G(registry_directories), path, path_len+1, (void**)&pht) == SUCCESS) {
  226. HashTable *ht = *pht;
  227. HashPosition pos;
  228. char *index;
  229. uint index_len;
  230. ulong num;
  231. zval **data;
  232. for (zend_hash_internal_pointer_reset_ex(ht, &pos);
  233. zend_hash_get_current_data_ex(ht, (void**)&data, &pos) == SUCCESS &&
  234. zend_hash_get_current_key_ex(ht, &index, &index_len, &num, 0, &pos) == HASH_KEY_IS_STRING;
  235. zend_hash_move_forward_ex(ht, &pos)) {
  236. zend_alter_ini_entry(index, index_len, Z_STRVAL_PP(data), Z_STRLEN_PP(data), PHP_INI_USER, PHP_INI_STAGE_ACTIVATE);
  237. }
  238. break;
  239. }
  240. if (--path_len > 0) {
  241. while (path_len > 0 && path[path_len] != '/') {
  242. path_len--;
  243. }
  244. }
  245. path[path_len] = 0;
  246. }
  247. efree(orig_path);
  248. }
  249. #define PHPRC_REGISTRY_NAME "IniFilePath"
  250. char *GetIniPathFromRegistry()
  251. {
  252. char *reg_location = NULL;
  253. HKEY hKey;
  254. if (OpenPhpRegistryKey(NULL, &hKey)) {
  255. DWORD buflen = MAXPATHLEN;
  256. reg_location = emalloc(MAXPATHLEN+1);
  257. if(RegQueryValueEx(hKey, PHPRC_REGISTRY_NAME, 0, NULL, reg_location, &buflen) != ERROR_SUCCESS) {
  258. efree(reg_location);
  259. reg_location = NULL;
  260. return reg_location;
  261. }
  262. RegCloseKey(hKey);
  263. }
  264. return reg_location;
  265. }