File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / win32 / registry.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 01:32:15 2013 UTC (11 years ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29p0, v5_4_29, v5_4_20p0, v5_4_20, v5_4_17, HEAD
5.4.17

    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: 							if (!ht) {
   83: 								return ret;
   84: 							}
   85: 							zend_hash_init(ht, 0, NULL, ZVAL_INTERNAL_PTR_DTOR, 1);
   86: 						}
   87: 						data = (zval*)malloc(sizeof(zval));
   88: 						if (!data) {
   89: 							return ret;
   90: 						}
   91: 						INIT_PZVAL(data);
   92: 						Z_STRVAL_P(data) = zend_strndup(value, value_len-1);
   93: 						Z_STRLEN_P(data) = value_len-1;
   94: 						Z_TYPE_P(data) = IS_STRING;
   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));
  184: 		if (!PW32G(registry_directories)) {
  185: 			return;
  186: 		}
  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>