Annotation of embedaddon/php/win32/registry.c, revision 1.1
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));
! 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>