|
1 | 1 | #include "php.h"
|
2 | 2 | #include "php_ini.h"
|
| 3 | +#include "php_win32_globals.h" |
3 | 4 |
|
4 | 5 | #define PHP_REGISTRY_KEY "SOFTWARE\\PHP"
|
5 | 6 |
|
@@ -56,13 +57,135 @@ static int OpenPhpRegistryKey(char* sub_key, HKEY *hKey)
|
56 | 57 | return 0;
|
57 | 58 | }
|
58 | 59 |
|
| 60 | +static int LoadDirectory(HashTable *directories, HKEY key, char *path, int path_len, HashTable *parent_ht) |
| 61 | +{ |
| 62 | + DWORD keys, values, max_key, max_name, max_value; |
| 63 | + int ret = 0; |
| 64 | + HashTable *ht = NULL; |
| 65 | + |
| 66 | + if (RegQueryInfoKey(key, NULL, NULL, NULL, &keys, &max_key, NULL, &values, &max_name, &max_value, NULL, NULL) == ERROR_SUCCESS) { |
| 67 | + |
| 68 | + if (values) { |
| 69 | + DWORD i; |
| 70 | + char *name = (char*)emalloc(max_name+1); |
| 71 | + char *value = (char*)emalloc(max_value+1); |
| 72 | + DWORD name_len, type, value_len; |
| 73 | + zval *data; |
| 74 | + |
| 75 | + for (i = 0; i < values; i++) { |
| 76 | + name_len = max_name+1; |
| 77 | + value_len = max_value+1; |
| 78 | + if (RegEnumValue(key, i, name, &name_len, NULL, &type, value, &value_len) == ERROR_SUCCESS) { |
| 79 | + if ((type == REG_SZ) || (type == REG_EXPAND_SZ)) { |
| 80 | + if (!ht) { |
| 81 | + ht = (HashTable*)malloc(sizeof(HashTable)); |
| 82 | + zend_hash_init(ht, 0, NULL, ZVAL_INTERNAL_PTR_DTOR, 1); |
| 83 | + } |
| 84 | + data = (zval*)malloc(sizeof(zval)); |
| 85 | + INIT_PZVAL(data); |
| 86 | + Z_STRVAL_P(data) = zend_strndup(value, value_len-1); |
| 87 | + Z_STRLEN_P(data) = value_len-1; |
| 88 | + zend_hash_update(ht, name, name_len+1, &data, sizeof(zval*), NULL); |
| 89 | + } |
| 90 | + } |
| 91 | + } |
| 92 | + if (ht) { |
| 93 | + if (parent_ht) { |
| 94 | + HashPosition pos; |
| 95 | + char *index; |
| 96 | + uint index_len; |
| 97 | + ulong num; |
| 98 | + zval **data; |
| 99 | + |
| 100 | + for (zend_hash_internal_pointer_reset_ex(parent_ht, &pos); |
| 101 | + zend_hash_get_current_data_ex(parent_ht, (void**)&data, &pos) == SUCCESS && |
| 102 | + zend_hash_get_current_key_ex(parent_ht, &index, &index_len, &num, 0, &pos) == HASH_KEY_IS_STRING; |
| 103 | + zend_hash_move_forward_ex(parent_ht, &pos)) { |
| 104 | + if (zend_hash_add(ht, index, index_len, data, sizeof(zval*), NULL) == SUCCESS) { |
| 105 | + (*data)->refcount++; |
| 106 | + } |
| 107 | + } |
| 108 | + } |
| 109 | + zend_hash_update(directories, path, path_len+1, &ht, sizeof(HashTable*), NULL); |
| 110 | + ret = 1; |
| 111 | + } |
| 112 | + |
| 113 | + efree(name); |
| 114 | + efree(value); |
| 115 | + } |
| 116 | + |
| 117 | + if (ht == NULL) { |
| 118 | + ht = parent_ht; |
| 119 | + } |
| 120 | + |
| 121 | + if (keys) { |
| 122 | + DWORD i; |
| 123 | + char *name = (char*)emalloc(max_key+1); |
| 124 | + char *new_path = (char*)emalloc(path_len+max_key+2); |
| 125 | + DWORD name_len; |
| 126 | + FILETIME t; |
| 127 | + HKEY subkey; |
| 128 | + |
| 129 | + for (i = 0; i < keys; i++) { |
| 130 | + name_len = max_key+1; |
| 131 | + if (RegEnumKeyEx(key, i, name, &name_len, NULL, NULL, NULL, &t) == ERROR_SUCCESS) { |
| 132 | + if (RegOpenKeyEx(key, name, 0, KEY_READ, &subkey) == ERROR_SUCCESS) { |
| 133 | + if (path_len) { |
| 134 | + memcpy(new_path, path, path_len); |
| 135 | + new_path[path_len] = '/'; |
| 136 | + path_len++; |
| 137 | + } |
| 138 | + memcpy(new_path+path_len, name, name_len+1); |
| 139 | + zend_str_tolower(new_path, path_len+name_len); |
| 140 | + if (LoadDirectory(directories, subkey, new_path, path_len+name_len, ht)) { |
| 141 | + ret = 1; |
| 142 | + } |
| 143 | + RegCloseKey(subkey); |
| 144 | + } |
| 145 | + } |
| 146 | + } |
| 147 | + efree(new_path); |
| 148 | + efree(name); |
| 149 | + } |
| 150 | + } |
| 151 | + return ret; |
| 152 | +} |
| 153 | + |
| 154 | +static void delete_internal_hashtable(void *data) |
| 155 | +{ |
| 156 | + zend_hash_destroy(*(HashTable**)data); |
| 157 | + free(*(HashTable**)data); |
| 158 | +} |
| 159 | + |
| 160 | +#define RegNotifyFlags (REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_ATTRIBUTES | REG_NOTIFY_CHANGE_LAST_SET) |
| 161 | + |
59 | 162 | void UpdateIniFromRegistry(char *path TSRMLS_DC)
|
60 | 163 | {
|
61 | 164 | char *p, *orig_path;
|
62 |
| - HKEY MainKey; |
63 |
| - char *strtok_buf = NULL; |
| 165 | + int path_len; |
| 166 | + HashTable **pht; |
64 | 167 |
|
65 |
| - if (!OpenPhpRegistryKey("\\Per Directory Values", &MainKey)) { |
| 168 | + if (!PW32G(registry_directories)) { |
| 169 | + PW32G(registry_directories) = (HashTable*)malloc(sizeof(HashTable)); |
| 170 | + zend_hash_init(PW32G(registry_directories), 0, NULL, delete_internal_hashtable, 1); |
| 171 | + if (!OpenPhpRegistryKey("\\Per Directory Values", &PW32G(registry_key))) { |
| 172 | + PW32G(registry_key) = NULL; |
| 173 | + return; |
| 174 | + } |
| 175 | + PW32G(registry_event) = CreateEvent(NULL, TRUE, FALSE, NULL); |
| 176 | + if (PW32G(registry_event)) { |
| 177 | + RegNotifyChangeKeyValue(PW32G(registry_key), TRUE, RegNotifyFlags, PW32G(registry_event), TRUE); |
| 178 | + } |
| 179 | + if (!LoadDirectory(PW32G(registry_directories), PW32G(registry_key), "", 0, NULL)) { |
| 180 | + return; |
| 181 | + } |
| 182 | + } else if (PW32G(registry_event) && WaitForSingleObject(PW32G(registry_event), 0) == WAIT_OBJECT_0) { |
| 183 | + RegNotifyChangeKeyValue(PW32G(registry_key), TRUE, RegNotifyFlags, PW32G(registry_event), TRUE); |
| 184 | + zend_hash_clean(PW32G(registry_directories)); |
| 185 | + if (!LoadDirectory(PW32G(registry_directories), PW32G(registry_key), "", 0, NULL)) { |
| 186 | + return; |
| 187 | + } |
| 188 | + } else if (zend_hash_num_elements(PW32G(registry_directories)) == 0) { |
66 | 189 | return;
|
67 | 190 | }
|
68 | 191 |
|
@@ -101,48 +224,39 @@ void UpdateIniFromRegistry(char *path TSRMLS_DC)
|
101 | 224 | }
|
102 | 225 | }
|
103 | 226 |
|
104 |
| - |
105 |
| - path = p = php_strtok_r(path, "\\/", &strtok_buf); |
106 |
| - |
107 |
| - while (p) { |
108 |
| - HKEY hKey; |
109 |
| - DWORD lType; |
110 |
| - DWORD values = 0, max_name = 0, max_value = 0, i = 0; |
111 |
| - |
112 |
| - if (p>path) { |
113 |
| - *(p-1) = '\\'; /* restore the slash */ |
| 227 | + path_len = 0; |
| 228 | + while (path[path_len] != 0) { |
| 229 | + if (path[path_len] == '\\') { |
| 230 | + path[path_len] = '/'; |
114 | 231 | }
|
| 232 | + path_len++; |
| 233 | + } |
| 234 | + zend_str_tolower(path, path_len); |
| 235 | + while (path_len >= 0) { |
| 236 | + if (zend_hash_find(PW32G(registry_directories), path, path_len+1, (void**)&pht) == SUCCESS) { |
| 237 | + HashTable *ht = *pht; |
| 238 | + HashPosition pos; |
| 239 | + char *index; |
| 240 | + uint index_len; |
| 241 | + ulong num; |
| 242 | + zval **data; |
115 | 243 |
|
116 |
| - if (RegOpenKeyEx(MainKey, path, 0, KEY_READ, &hKey)!=ERROR_SUCCESS) { |
| 244 | + for (zend_hash_internal_pointer_reset_ex(ht, &pos); |
| 245 | + zend_hash_get_current_data_ex(ht, (void**)&data, &pos) == SUCCESS && |
| 246 | + zend_hash_get_current_key_ex(ht, &index, &index_len, &num, 0, &pos) == HASH_KEY_IS_STRING; |
| 247 | + zend_hash_move_forward_ex(ht, &pos)) { |
| 248 | + zend_alter_ini_entry(index, index_len, Z_STRVAL_PP(data), Z_STRLEN_PP(data), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); |
| 249 | + } |
117 | 250 | break;
|
118 | 251 | }
|
119 |
| - |
120 |
| - if(RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &values, &max_name, &max_value, NULL, NULL) == ERROR_SUCCESS) { |
121 |
| - LPTSTR namebuf = (LPTSTR)emalloc(max_name + 1); |
122 |
| - PBYTE valuebuf = (PBYTE)emalloc(max_value); |
123 |
| - |
124 |
| - while (i < values) { |
125 |
| - DWORD namebuf_len = max_name + 1; |
126 |
| - DWORD valuebuf_len = max_value; |
127 |
| - |
128 |
| - RegEnumValue(hKey, i, namebuf, &namebuf_len, NULL, &lType, valuebuf, &valuebuf_len); |
129 |
| - |
130 |
| - if ((lType == REG_SZ) || (lType == REG_EXPAND_SZ)) { |
131 |
| - /* valuebuf_len includes trailing 0 */ |
132 |
| - zend_alter_ini_entry(namebuf, namebuf_len + 1, valuebuf, valuebuf_len?valuebuf_len-1:0, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE); |
133 |
| - } |
134 |
| - |
135 |
| - i++; |
| 252 | + if (--path_len > 0) { |
| 253 | + while (path_len > 0 && path[path_len] != '/') { |
| 254 | + path_len--; |
136 | 255 | }
|
137 |
| - |
138 |
| - efree(namebuf); |
139 |
| - efree(valuebuf); |
140 | 256 | }
|
141 |
| - |
142 |
| - RegCloseKey(hKey); |
143 |
| - p = php_strtok_r(NULL, "\\/", &strtok_buf); |
| 257 | + path[path_len] = 0; |
144 | 258 | }
|
145 |
| - RegCloseKey(MainKey); |
| 259 | + |
146 | 260 | efree(orig_path);
|
147 | 261 | }
|
148 | 262 |
|
|
0 commit comments