Back to index

php5  5.3.10
registry.c
Go to the documentation of this file.
00001 #include "php.h"
00002 #include "php_ini.h"
00003 #include "php_win32_globals.h"
00004 
00005 #define PHP_REGISTRY_KEY              "SOFTWARE\\PHP"
00006 
00007 #define PHP_VER1(V1)                  #V1
00008 #define PHP_VER2(V1,V2)               #V1"."#V2
00009 #define PHP_VER3(V1,V2,V3)            #V1"."#V2"."#V3
00010 
00011 #define PHP_REGISTRY_KEYV(VER)        PHP_REGISTRY_KEY"\\"VER
00012 #define PHP_REGISTRY_KEY1(V1)         PHP_REGISTRY_KEY"\\"PHP_VER1(V1)
00013 #define PHP_REGISTRY_KEY2(V1,V2)      PHP_REGISTRY_KEY"\\"PHP_VER2(V1,V2)
00014 #define PHP_REGISTRY_KEY3(V1,V2,V3)   PHP_REGISTRY_KEY"\\"PHP_VER3(V1,V2,V3)
00015 
00016 static const char* registry_keys[] = {
00017        PHP_REGISTRY_KEYV(PHP_VERSION),
00018        PHP_REGISTRY_KEY3(PHP_MAJOR_VERSION, PHP_MINOR_VERSION, PHP_RELEASE_VERSION),
00019        PHP_REGISTRY_KEY2(PHP_MAJOR_VERSION, PHP_MINOR_VERSION),
00020        PHP_REGISTRY_KEY1(PHP_MAJOR_VERSION),
00021        PHP_REGISTRY_KEY,
00022        NULL
00023 };
00024 
00025 static int OpenPhpRegistryKey(char* sub_key, HKEY *hKey)
00026 {
00027        const char **key_name = registry_keys;
00028 
00029        if (sub_key) {
00030               int main_key_len;
00031               int sub_key_len = strlen(sub_key);
00032               char *reg_key;
00033 
00034               while (*key_name) {
00035                      LONG ret;
00036 
00037                      main_key_len = strlen(*key_name);
00038                      reg_key = emalloc(main_key_len + sub_key_len + 1);
00039                      memcpy(reg_key, *key_name, main_key_len);
00040                      memcpy(reg_key + main_key_len, sub_key, sub_key_len + 1);                    
00041                      ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, reg_key, 0, KEY_READ, hKey);
00042                      efree(reg_key);
00043                      
00044                      if (ret == ERROR_SUCCESS) {
00045                             return 1;
00046                      }
00047                      ++key_name;
00048               }
00049        } else {
00050               while (*key_name) {
00051                      if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, *key_name, 0, KEY_READ, hKey) == ERROR_SUCCESS) {
00052                             return 1;
00053                      }
00054                      ++key_name;
00055               }
00056        }
00057        return 0;
00058 }
00059 
00060 static int LoadDirectory(HashTable *directories, HKEY key, char *path, int path_len, HashTable *parent_ht)
00061 {
00062        DWORD keys, values, max_key, max_name, max_value;
00063        int ret = 0;
00064        HashTable *ht = NULL;
00065 
00066        if (RegQueryInfoKey(key, NULL, NULL, NULL, &keys, &max_key, NULL, &values, &max_name, &max_value, NULL, NULL) == ERROR_SUCCESS) {
00067               
00068               if (values) {
00069                      DWORD i;
00070                      char *name = (char*)emalloc(max_name+1);
00071                      char *value = (char*)emalloc(max_value+1);
00072                      DWORD name_len, type, value_len;
00073                      zval *data;
00074 
00075                      for (i = 0; i < values; i++) {
00076                             name_len = max_name+1;
00077                             value_len = max_value+1;
00078                             if (RegEnumValue(key, i, name, &name_len, NULL, &type, value, &value_len) == ERROR_SUCCESS) {
00079                                    if ((type == REG_SZ) || (type == REG_EXPAND_SZ)) {
00080                                           if (!ht) {
00081                                                  ht = (HashTable*)malloc(sizeof(HashTable));
00082                                                  zend_hash_init(ht, 0, NULL, ZVAL_INTERNAL_PTR_DTOR, 1);
00083                                           }
00084                                           data = (zval*)malloc(sizeof(zval));
00085                                           INIT_PZVAL(data);
00086                                           Z_STRVAL_P(data) = zend_strndup(value, value_len-1);
00087                                           Z_STRLEN_P(data) = value_len-1;
00088                                           zend_hash_update(ht, name, name_len+1, &data, sizeof(zval*), NULL);
00089                                    }
00090                             }
00091                      }
00092                      if (ht) {
00093                             if (parent_ht) {
00094                                    HashPosition pos;
00095                                    char *index;
00096                                    uint index_len;
00097                                    ulong num;
00098                                    zval **tmpdata;
00099 
00100                                    for (zend_hash_internal_pointer_reset_ex(parent_ht, &pos);
00101                                         zend_hash_get_current_data_ex(parent_ht, (void**)&tmpdata, &pos) == SUCCESS &&
00102                                         zend_hash_get_current_key_ex(parent_ht, &index, &index_len, &num, 0, &pos) == HASH_KEY_IS_STRING;
00103                                         zend_hash_move_forward_ex(parent_ht, &pos)) {
00104                                           if (zend_hash_add(ht, index, index_len, tmpdata, sizeof(zval*), NULL) == SUCCESS) {
00105                                               Z_ADDREF_PP(tmpdata);
00106                                           }
00107                                    }
00108                             }
00109                             zend_hash_update(directories, path, path_len+1, &ht, sizeof(HashTable*), NULL);
00110                             ret = 1;
00111                      }
00112 
00113                      efree(name);
00114                      efree(value);
00115               }
00116 
00117               if (ht == NULL) {
00118                      ht = parent_ht;
00119               }
00120 
00121               if (keys) {
00122                      DWORD i;
00123                      char *name = (char*)emalloc(max_key+1);
00124                      char *new_path = (char*)emalloc(path_len+max_key+2);
00125                      DWORD name_len;
00126                      FILETIME t;
00127                      HKEY subkey;
00128 
00129                      for (i = 0; i < keys; i++) {
00130                             name_len = max_key+1;
00131                             if (RegEnumKeyEx(key, i, name, &name_len, NULL, NULL, NULL, &t) == ERROR_SUCCESS) {
00132                                    if (RegOpenKeyEx(key, name, 0, KEY_READ, &subkey) == ERROR_SUCCESS) {
00133                                           if (path_len) {
00134                                                  memcpy(new_path, path, path_len);
00135                                                  new_path[path_len] = '/';
00136                                                  memcpy(new_path+path_len+1, name, name_len+1);
00137                                                  zend_str_tolower(new_path, path_len+name_len+1);
00138                                                  name_len += path_len+1;
00139                                           } else {
00140                                                  memcpy(new_path, name, name_len+1);
00141                                                  zend_str_tolower(new_path, name_len);
00142                                           }
00143                                           if (LoadDirectory(directories, subkey, new_path, name_len, ht)) {
00144                                                  ret = 1;
00145                                           }
00146                                           RegCloseKey(subkey);
00147                                    }
00148                             }
00149                      }
00150                      efree(new_path);
00151                      efree(name);
00152               }
00153        }
00154        return ret;
00155 }
00156 
00157 static void delete_internal_hashtable(void *data)
00158 {
00159        zend_hash_destroy(*(HashTable**)data);
00160        free(*(HashTable**)data);
00161 }
00162 
00163 #define RegNotifyFlags (REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_ATTRIBUTES | REG_NOTIFY_CHANGE_LAST_SET)
00164 
00165 void UpdateIniFromRegistry(char *path TSRMLS_DC)
00166 {
00167        char *p, *orig_path;
00168        int path_len;
00169        HashTable **pht;
00170 
00171        if(!path) {
00172               return;
00173        }
00174 
00175        if (!PW32G(registry_directories)) {
00176               PW32G(registry_directories) = (HashTable*)malloc(sizeof(HashTable));
00177               zend_hash_init(PW32G(registry_directories), 0, NULL, delete_internal_hashtable, 1);
00178               if (!OpenPhpRegistryKey("\\Per Directory Values", &PW32G(registry_key))) {
00179                      PW32G(registry_key) = NULL;
00180                      return;
00181               }
00182               PW32G(registry_event) = CreateEvent(NULL, TRUE, FALSE, NULL);
00183               if (PW32G(registry_event)) {
00184                      RegNotifyChangeKeyValue(PW32G(registry_key), TRUE, RegNotifyFlags, PW32G(registry_event), TRUE);
00185               }
00186               if (!LoadDirectory(PW32G(registry_directories), PW32G(registry_key), "", 0, NULL)) {
00187                      return;
00188               }
00189        } else if (PW32G(registry_event) && WaitForSingleObject(PW32G(registry_event), 0) == WAIT_OBJECT_0) {
00190               RegNotifyChangeKeyValue(PW32G(registry_key), TRUE, RegNotifyFlags, PW32G(registry_event), TRUE);
00191               zend_hash_clean(PW32G(registry_directories));
00192               if (!LoadDirectory(PW32G(registry_directories), PW32G(registry_key), "", 0, NULL)) {
00193                      return;
00194               }
00195        } else if (zend_hash_num_elements(PW32G(registry_directories)) == 0) {
00196               return;
00197        }
00198 
00199        orig_path = path = estrdup(path);
00200 
00201        /* Get rid of C:, if exists */
00202        p = strchr(path, ':');
00203        if (p) {
00204               *p = path[0]; /* replace the colon with the drive letter */
00205               path = p;            /* make path point to the drive letter */
00206        } else {
00207               if (path[0] != '\\' && path[0] != '/') {
00208                      char tmp_buf[MAXPATHLEN], *cwd;
00209                      char drive_letter;
00210 
00211                      /* get current working directory and prepend it to the path */
00212                      if (!VCWD_GETCWD(tmp_buf, MAXPATHLEN)) {
00213                             efree(orig_path);
00214                             return;
00215                      }
00216                      cwd = strchr(tmp_buf, ':');
00217                      if (!cwd) {
00218                             drive_letter = 'C';
00219                             cwd = tmp_buf;
00220                      } else {
00221                             drive_letter = tmp_buf[0];
00222                             cwd++;
00223                      }
00224                      while (*cwd == '\\' || *cwd == '/') {
00225                             cwd++;
00226                      }
00227                      spprintf(&path, 0, "%c\\%s\\%s", drive_letter, cwd, orig_path);
00228                      efree(orig_path);
00229                      orig_path = path;
00230               }
00231        }
00232 
00233        path_len = 0;
00234        while (path[path_len] != 0) {
00235               if (path[path_len] == '\\') {
00236                      path[path_len] = '/';
00237               }
00238               path_len++;
00239        }
00240        zend_str_tolower(path, path_len);
00241        while (path_len >= 0) {
00242               if (zend_hash_find(PW32G(registry_directories), path, path_len+1, (void**)&pht) == SUCCESS) {
00243                      HashTable *ht = *pht;
00244                      HashPosition pos;
00245                      char *index;
00246                      uint index_len;
00247                      ulong num;
00248                      zval **data;
00249 
00250                      for (zend_hash_internal_pointer_reset_ex(ht, &pos);
00251                           zend_hash_get_current_data_ex(ht, (void**)&data, &pos) == SUCCESS &&
00252                           zend_hash_get_current_key_ex(ht, &index, &index_len, &num, 0, &pos) == HASH_KEY_IS_STRING;
00253                           zend_hash_move_forward_ex(ht, &pos)) {
00254                             zend_alter_ini_entry(index, index_len, Z_STRVAL_PP(data), Z_STRLEN_PP(data), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
00255                      }
00256                      break;
00257               }
00258               if (--path_len > 0) {
00259                      while (path_len > 0 && path[path_len] != '/') {
00260                             path_len--;
00261                      }
00262               }
00263               path[path_len] = 0;
00264        }
00265 
00266        efree(orig_path);
00267 }
00268 
00269 #define PHPRC_REGISTRY_NAME "IniFilePath"
00270 
00271 char *GetIniPathFromRegistry()
00272 {
00273        char *reg_location = NULL;
00274        HKEY hKey;
00275        
00276        if (OpenPhpRegistryKey(NULL, &hKey)) {
00277               DWORD buflen = MAXPATHLEN;
00278               reg_location = emalloc(MAXPATHLEN+1);
00279               if(RegQueryValueEx(hKey, PHPRC_REGISTRY_NAME, 0, NULL, reg_location, &buflen) != ERROR_SUCCESS) {
00280                      efree(reg_location);
00281                      reg_location = NULL;
00282                      return reg_location;
00283               }
00284               RegCloseKey(hKey);
00285        }
00286        return reg_location;
00287 }