root/win32/registry.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. OpenPhpRegistryKey
  2. LoadDirectory
  3. delete_internal_hashtable
  4. UpdateIniFromRegistry
  5. GetIniPathFromRegistry

   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_USER, 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 }

/* [<][>][^][v][top][bottom][index][help] */