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 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 7                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Author: Zeev Suraski <zeev@zend.com>                                 |
  16    +----------------------------------------------------------------------+
  17  */
  18 
  19 #include "php.h"
  20 #include "php_ini.h"
  21 #include "php_win32_globals.h"
  22 
  23 #define PHP_REGISTRY_KEY              "SOFTWARE\\PHP"
  24 
  25 #define PHP_VER1(V1)                  #V1
  26 #define PHP_VER2(V1,V2)               #V1"."#V2
  27 #define PHP_VER3(V1,V2,V3)            #V1"."#V2"."#V3
  28 
  29 #define PHP_REGISTRY_KEYV(VER)        PHP_REGISTRY_KEY"\\"VER
  30 #define PHP_REGISTRY_KEY1(V1)         PHP_REGISTRY_KEY"\\"PHP_VER1(V1)
  31 #define PHP_REGISTRY_KEY2(V1,V2)      PHP_REGISTRY_KEY"\\"PHP_VER2(V1,V2)
  32 #define PHP_REGISTRY_KEY3(V1,V2,V3)   PHP_REGISTRY_KEY"\\"PHP_VER3(V1,V2,V3)
  33 
  34 static const char* registry_keys[] = {
  35         PHP_REGISTRY_KEYV(PHP_VERSION),
  36         PHP_REGISTRY_KEY3(PHP_MAJOR_VERSION, PHP_MINOR_VERSION, PHP_RELEASE_VERSION),
  37         PHP_REGISTRY_KEY2(PHP_MAJOR_VERSION, PHP_MINOR_VERSION),
  38         PHP_REGISTRY_KEY1(PHP_MAJOR_VERSION),
  39         PHP_REGISTRY_KEY,
  40         NULL
  41 };
  42 
  43 static int OpenPhpRegistryKey(char* sub_key, HKEY *hKey)
  44 {
  45         const char **key_name = registry_keys;
  46 
  47         if (sub_key) {
  48                 size_t main_key_len;
  49                 size_t sub_key_len = strlen(sub_key);
  50                 char *reg_key;
  51 
  52                 while (*key_name) {
  53                         LONG ret;
  54 
  55                         main_key_len = strlen(*key_name);
  56                         reg_key = emalloc(main_key_len + sub_key_len + 1);
  57                         memcpy(reg_key, *key_name, main_key_len);
  58                         memcpy(reg_key + main_key_len, sub_key, sub_key_len + 1);
  59                         ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, reg_key, 0, KEY_READ, hKey);
  60                         efree(reg_key);
  61 
  62                         if (ret == ERROR_SUCCESS) {
  63                                 return 1;
  64                         }
  65                         ++key_name;
  66                 }
  67         } else {
  68                 while (*key_name) {
  69                         if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, *key_name, 0, KEY_READ, hKey) == ERROR_SUCCESS) {
  70                                 return 1;
  71                         }
  72                         ++key_name;
  73                 }
  74         }
  75         return 0;
  76 }
  77 
  78 static int LoadDirectory(HashTable *directories, HKEY key, char *path, int path_len, HashTable *parent_ht)
  79 {
  80         DWORD keys, values, max_key, max_name, max_value;
  81         int ret = 0;
  82         HashTable *ht = NULL;
  83 
  84         if (RegQueryInfoKey(key, NULL, NULL, NULL, &keys, &max_key, NULL, &values, &max_name, &max_value, NULL, NULL) == ERROR_SUCCESS) {
  85 
  86                 if (values) {
  87                         DWORD i;
  88                         char *name = (char*)emalloc(max_name+1);
  89                         char *value = (char*)emalloc(max_value+1);
  90                         DWORD name_len, type, value_len;
  91 
  92                         for (i = 0; i < values; i++) {
  93                                 name_len = max_name+1;
  94                                 value_len = max_value+1;
  95 
  96                                 memset(name, '\0', max_name+1);
  97                                 memset(value, '\0', max_value+1);
  98 
  99                                 if (RegEnumValue(key, i, name, &name_len, NULL, &type, value, &value_len) == ERROR_SUCCESS) {
 100                                         if ((type == REG_SZ) || (type == REG_EXPAND_SZ)) {
 101                                                 zval data;
 102 
 103                                                 if (!ht) {
 104                                                         ht = (HashTable*)malloc(sizeof(HashTable));
 105                                                         if (!ht) {
 106                                                                 return ret;
 107                                                         }
 108                                                         zend_hash_init(ht, 0, NULL, ZVAL_INTERNAL_PTR_DTOR, 1);
 109                                                 }
 110                                                 ZVAL_PSTRINGL(&data, value, value_len-1);
 111                                                 zend_hash_str_update(ht, name, name_len, &data);
 112                                         }
 113                                 }
 114                         }
 115                         if (ht) {
 116                                 if (parent_ht) {
 117                                         zend_string *index;
 118                                         zend_ulong num;
 119                                         zval *tmpdata;
 120 
 121                                         ZEND_HASH_FOREACH_KEY_VAL(parent_ht, num, index, tmpdata) {
 122                                                 zend_hash_add(ht, index, tmpdata);
 123                                         } ZEND_HASH_FOREACH_END();
 124                                 }
 125                                 zend_hash_str_update_mem(directories, path, path_len, ht, sizeof(HashTable));
 126                                 ret = 1;
 127                         }
 128 
 129                         efree(name);
 130                         efree(value);
 131                 }
 132 
 133                 if (ht == NULL) {
 134                         ht = parent_ht;
 135                 }
 136 
 137                 if (keys) {
 138                         DWORD i;
 139                         char *name = (char*)emalloc(max_key+1);
 140                         char *new_path = (char*)emalloc(path_len+max_key+2);
 141                         DWORD name_len;
 142                         FILETIME t;
 143                         HKEY subkey;
 144 
 145                         for (i = 0; i < keys; i++) {
 146                                 name_len = max_key+1;
 147                                 if (RegEnumKeyEx(key, i, name, &name_len, NULL, NULL, NULL, &t) == ERROR_SUCCESS) {
 148                                         if (RegOpenKeyEx(key, name, 0, KEY_READ, &subkey) == ERROR_SUCCESS) {
 149                                                 if (path_len) {
 150                                                         memcpy(new_path, path, path_len);
 151                                                         new_path[path_len] = '/';
 152                                                         memcpy(new_path+path_len+1, name, name_len+1);
 153                                                         zend_str_tolower(new_path, path_len+name_len+1);
 154                                                         name_len += path_len+1;
 155                                                 } else {
 156                                                         memcpy(new_path, name, name_len+1);
 157                                                         zend_str_tolower(new_path, name_len);
 158                                                 }
 159                                                 if (LoadDirectory(directories, subkey, new_path, name_len, ht)) {
 160                                                         ret = 1;
 161                                                 }
 162                                                 RegCloseKey(subkey);
 163                                         }
 164                                 }
 165                         }
 166                         efree(new_path);
 167                         efree(name);
 168                 }
 169         }
 170         return ret;
 171 }
 172 
 173 static void delete_internal_hashtable(zval *zv)
 174 {
 175         HashTable *ht = (HashTable *)Z_PTR_P(zv);
 176         zend_hash_destroy(ht);
 177         free(ht);
 178 }
 179 
 180 #define RegNotifyFlags (REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_ATTRIBUTES | REG_NOTIFY_CHANGE_LAST_SET)
 181 
 182 void UpdateIniFromRegistry(char *path)
 183 {
 184         char *p, *orig_path;
 185         int path_len;
 186 
 187         if(!path) {
 188                 return;
 189         }
 190 
 191         if (!PW32G(registry_directories)) {
 192                 PW32G(registry_directories) = (HashTable*)malloc(sizeof(HashTable));
 193                 if (!PW32G(registry_directories)) {
 194                         return;
 195                 }
 196                 zend_hash_init(PW32G(registry_directories), 0, NULL, delete_internal_hashtable, 1);
 197                 if (!OpenPhpRegistryKey("\\Per Directory Values", &PW32G(registry_key))) {
 198                         PW32G(registry_key) = NULL;
 199                         return;
 200                 }
 201                 PW32G(registry_event) = CreateEvent(NULL, TRUE, FALSE, NULL);
 202                 if (PW32G(registry_event)) {
 203                         RegNotifyChangeKeyValue(PW32G(registry_key), TRUE, RegNotifyFlags, PW32G(registry_event), TRUE);
 204                 }
 205                 if (!LoadDirectory(PW32G(registry_directories), PW32G(registry_key), "", 0, NULL)) {
 206                         return;
 207                 }
 208         } else if (PW32G(registry_event) && WaitForSingleObject(PW32G(registry_event), 0) == WAIT_OBJECT_0) {
 209                 RegNotifyChangeKeyValue(PW32G(registry_key), TRUE, RegNotifyFlags, PW32G(registry_event), TRUE);
 210                 zend_hash_clean(PW32G(registry_directories));
 211                 if (!LoadDirectory(PW32G(registry_directories), PW32G(registry_key), "", 0, NULL)) {
 212                         return;
 213                 }
 214         } else if (zend_hash_num_elements(PW32G(registry_directories)) == 0) {
 215                 return;
 216         }
 217 
 218         orig_path = path = estrdup(path);
 219 
 220         /* Get rid of C:, if exists */
 221         p = strchr(path, ':');
 222         if (p) {
 223                 *p = path[0];   /* replace the colon with the drive letter */
 224                 path = p;               /* make path point to the drive letter */
 225         } else {
 226                 if (path[0] != '\\' && path[0] != '/') {
 227                         char tmp_buf[MAXPATHLEN], *cwd;
 228                         char drive_letter;
 229 
 230                         /* get current working directory and prepend it to the path */
 231                         if (!VCWD_GETCWD(tmp_buf, MAXPATHLEN)) {
 232                                 efree(orig_path);
 233                                 return;
 234                         }
 235                         cwd = strchr(tmp_buf, ':');
 236                         if (!cwd) {
 237                                 drive_letter = 'C';
 238                                 cwd = tmp_buf;
 239                         } else {
 240                                 drive_letter = tmp_buf[0];
 241                                 cwd++;
 242                         }
 243                         while (*cwd == '\\' || *cwd == '/') {
 244                                 cwd++;
 245                         }
 246                         spprintf(&path, 0, "%c\\%s\\%s", drive_letter, cwd, orig_path);
 247                         efree(orig_path);
 248                         orig_path = path;
 249                 }
 250         }
 251 
 252         path_len = 0;
 253         while (path[path_len] != 0) {
 254                 if (path[path_len] == '\\') {
 255                         path[path_len] = '/';
 256                 }
 257                 path_len++;
 258         }
 259         zend_str_tolower(path, path_len);
 260 
 261         while (path_len > 0) {
 262                 HashTable *ht = (HashTable *)zend_hash_str_find_ptr(PW32G(registry_directories), path, path_len);
 263 
 264                 if (ht != NULL) {
 265                         zend_string *index;
 266                         zval *data;
 267 
 268                         ZEND_HASH_FOREACH_STR_KEY_VAL(ht, index, data) {
 269                                 zend_alter_ini_entry(index, Z_STR_P(data), PHP_INI_USER, PHP_INI_STAGE_ACTIVATE);
 270                         } ZEND_HASH_FOREACH_END();
 271                 }
 272 
 273                 do {
 274                         path_len--;
 275                 } while (path_len > 0 && path[path_len] != '/');
 276                 path[path_len] = 0;
 277         }
 278 
 279         efree(orig_path);
 280 }
 281 
 282 #define PHPRC_REGISTRY_NAME "IniFilePath"
 283 
 284 char *GetIniPathFromRegistry()
 285 {
 286         char *reg_location = NULL;
 287         HKEY hKey;
 288 
 289         if (OpenPhpRegistryKey(NULL, &hKey)) {
 290                 DWORD buflen = MAXPATHLEN;
 291                 reg_location = emalloc(MAXPATHLEN+1);
 292                 if(RegQueryValueEx(hKey, PHPRC_REGISTRY_NAME, 0, NULL, reg_location, &buflen) != ERROR_SUCCESS) {
 293                         RegCloseKey(hKey);
 294                         efree(reg_location);
 295                         reg_location = NULL;
 296                         return reg_location;
 297                 }
 298                 RegCloseKey(hKey);
 299         }
 300         return reg_location;
 301 }
 302 
 303 /*
 304  * Local variables:
 305  * tab-width: 4
 306  * c-basic-offset: 4
 307  * End:
 308  * vim600: sw=4 ts=4 fdm=marker
 309  * vim<600: sw=4 ts=4
 310  */

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