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>