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