File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / win32 / registry.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:48:06 2012 UTC (12 years, 4 months ago) by misho
Branches: php, MAIN
CVS tags: v5_4_3elwix, v5_4_17p0, v5_3_10, HEAD
php

    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));
   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 **tmpdata;
   99: 
  100: 					for (zend_hash_internal_pointer_reset_ex(parent_ht, &pos);
  101: 					     zend_hash_get_current_data_ex(parent_ht, (void**)&tmpdata, &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, tmpdata, sizeof(zval*), NULL) == SUCCESS) {
  105: 						    Z_ADDREF_PP(tmpdata);
  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: 							memcpy(new_path+path_len+1, name, name_len+1);
  137: 							zend_str_tolower(new_path, path_len+name_len+1);
  138: 							name_len += path_len+1;
  139: 						} else {
  140: 							memcpy(new_path, name, name_len+1);
  141: 							zend_str_tolower(new_path, name_len);
  142: 						}
  143: 						if (LoadDirectory(directories, subkey, new_path, name_len, ht)) {
  144: 							ret = 1;
  145: 						}
  146: 						RegCloseKey(subkey);
  147: 					}
  148: 				}
  149: 			}
  150: 			efree(new_path);
  151: 			efree(name);
  152: 		}
  153: 	}
  154: 	return ret;
  155: }
  156: 
  157: static void delete_internal_hashtable(void *data)
  158: {
  159: 	zend_hash_destroy(*(HashTable**)data);
  160: 	free(*(HashTable**)data);
  161: }
  162: 
  163: #define RegNotifyFlags (REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_ATTRIBUTES | REG_NOTIFY_CHANGE_LAST_SET)
  164: 
  165: void UpdateIniFromRegistry(char *path TSRMLS_DC)
  166: {
  167: 	char *p, *orig_path;
  168: 	int path_len;
  169: 	HashTable **pht;
  170: 
  171: 	if(!path) {
  172: 		return;
  173: 	}
  174: 
  175: 	if (!PW32G(registry_directories)) {
  176: 		PW32G(registry_directories) = (HashTable*)malloc(sizeof(HashTable));
  177: 		zend_hash_init(PW32G(registry_directories), 0, NULL, delete_internal_hashtable, 1);
  178: 		if (!OpenPhpRegistryKey("\\Per Directory Values", &PW32G(registry_key))) {
  179: 			PW32G(registry_key) = NULL;
  180: 			return;
  181: 		}
  182: 		PW32G(registry_event) = CreateEvent(NULL, TRUE, FALSE, NULL);
  183: 		if (PW32G(registry_event)) {
  184: 			RegNotifyChangeKeyValue(PW32G(registry_key), TRUE, RegNotifyFlags, PW32G(registry_event), TRUE);
  185: 		}
  186: 		if (!LoadDirectory(PW32G(registry_directories), PW32G(registry_key), "", 0, NULL)) {
  187: 			return;
  188: 		}
  189: 	} else if (PW32G(registry_event) && WaitForSingleObject(PW32G(registry_event), 0) == WAIT_OBJECT_0) {
  190: 		RegNotifyChangeKeyValue(PW32G(registry_key), TRUE, RegNotifyFlags, PW32G(registry_event), TRUE);
  191: 		zend_hash_clean(PW32G(registry_directories));
  192: 		if (!LoadDirectory(PW32G(registry_directories), PW32G(registry_key), "", 0, NULL)) {
  193: 			return;
  194: 		}
  195: 	} else if (zend_hash_num_elements(PW32G(registry_directories)) == 0) {
  196: 		return;
  197: 	}
  198: 
  199: 	orig_path = path = estrdup(path);
  200: 
  201: 	/* Get rid of C:, if exists */
  202: 	p = strchr(path, ':');
  203: 	if (p) {
  204: 		*p = path[0];	/* replace the colon with the drive letter */
  205: 		path = p;		/* make path point to the drive letter */
  206: 	} else {
  207: 		if (path[0] != '\\' && path[0] != '/') {
  208: 			char tmp_buf[MAXPATHLEN], *cwd;
  209: 			char drive_letter;
  210: 
  211: 			/* get current working directory and prepend it to the path */
  212: 			if (!VCWD_GETCWD(tmp_buf, MAXPATHLEN)) {
  213: 				efree(orig_path);
  214: 				return;
  215: 			}
  216: 			cwd = strchr(tmp_buf, ':');
  217: 			if (!cwd) {
  218: 				drive_letter = 'C';
  219: 				cwd = tmp_buf;
  220: 			} else {
  221: 				drive_letter = tmp_buf[0];
  222: 				cwd++;
  223: 			}
  224: 			while (*cwd == '\\' || *cwd == '/') {
  225: 				cwd++;
  226: 			}
  227: 			spprintf(&path, 0, "%c\\%s\\%s", drive_letter, cwd, orig_path);
  228: 			efree(orig_path);
  229: 			orig_path = path;
  230: 		}
  231: 	}
  232: 
  233: 	path_len = 0;
  234: 	while (path[path_len] != 0) {
  235: 		if (path[path_len] == '\\') {
  236: 			path[path_len] = '/';
  237: 		}
  238: 		path_len++;
  239: 	}
  240: 	zend_str_tolower(path, path_len);
  241: 	while (path_len >= 0) {
  242: 		if (zend_hash_find(PW32G(registry_directories), path, path_len+1, (void**)&pht) == SUCCESS) {
  243: 			HashTable *ht = *pht;
  244: 			HashPosition pos;
  245: 			char *index;
  246: 			uint index_len;
  247: 			ulong num;
  248: 			zval **data;
  249: 
  250: 			for (zend_hash_internal_pointer_reset_ex(ht, &pos);
  251: 			     zend_hash_get_current_data_ex(ht, (void**)&data, &pos) == SUCCESS &&
  252: 			     zend_hash_get_current_key_ex(ht, &index, &index_len, &num, 0, &pos) == HASH_KEY_IS_STRING;
  253: 			     zend_hash_move_forward_ex(ht, &pos)) {
  254: 				zend_alter_ini_entry(index, index_len, Z_STRVAL_PP(data), Z_STRLEN_PP(data), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
  255: 			}
  256: 			break;
  257: 		}
  258: 		if (--path_len > 0) {
  259: 			while (path_len > 0 && path[path_len] != '/') {
  260: 				path_len--;
  261: 			}
  262: 		}
  263: 		path[path_len] = 0;
  264: 	}
  265: 
  266: 	efree(orig_path);
  267: }
  268: 
  269: #define PHPRC_REGISTRY_NAME "IniFilePath"
  270: 
  271: char *GetIniPathFromRegistry()
  272: {
  273: 	char *reg_location = NULL;
  274: 	HKEY hKey;
  275: 	
  276: 	if (OpenPhpRegistryKey(NULL, &hKey)) {
  277: 		DWORD buflen = MAXPATHLEN;
  278: 		reg_location = emalloc(MAXPATHLEN+1);
  279: 		if(RegQueryValueEx(hKey, PHPRC_REGISTRY_NAME, 0, NULL, reg_location, &buflen) != ERROR_SUCCESS) {
  280: 			efree(reg_location);
  281: 			reg_location = NULL;
  282: 			return reg_location;
  283: 		}
  284: 		RegCloseKey(hKey);
  285: 	}
  286: 	return reg_location;
  287: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>