1999-04-18 23:54:18 +08:00
|
|
|
#include "php.h"
|
|
|
|
#include "php_ini.h"
|
2006-11-10 19:42:07 +08:00
|
|
|
#include "php_win32_globals.h"
|
2000-03-25 09:32:47 +08:00
|
|
|
|
2006-08-03 21:54:05 +08:00
|
|
|
#define PHP_REGISTRY_KEY "SOFTWARE\\PHP"
|
|
|
|
|
|
|
|
#define PHP_VER1(V1) #V1
|
|
|
|
#define PHP_VER2(V1,V2) #V1"."#V2
|
|
|
|
#define PHP_VER3(V1,V2,V3) #V1"."#V2"."#V3
|
|
|
|
|
|
|
|
#define PHP_REGISTRY_KEYV(VER) PHP_REGISTRY_KEY"\\"VER
|
|
|
|
#define PHP_REGISTRY_KEY1(V1) PHP_REGISTRY_KEY"\\"PHP_VER1(V1)
|
|
|
|
#define PHP_REGISTRY_KEY2(V1,V2) PHP_REGISTRY_KEY"\\"PHP_VER2(V1,V2)
|
|
|
|
#define PHP_REGISTRY_KEY3(V1,V2,V3) PHP_REGISTRY_KEY"\\"PHP_VER3(V1,V2,V3)
|
|
|
|
|
|
|
|
static const char* registry_keys[] = {
|
|
|
|
PHP_REGISTRY_KEYV(PHP_VERSION),
|
|
|
|
PHP_REGISTRY_KEY3(PHP_MAJOR_VERSION, PHP_MINOR_VERSION, PHP_RELEASE_VERSION),
|
|
|
|
PHP_REGISTRY_KEY2(PHP_MAJOR_VERSION, PHP_MINOR_VERSION),
|
|
|
|
PHP_REGISTRY_KEY1(PHP_MAJOR_VERSION),
|
|
|
|
PHP_REGISTRY_KEY,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static int OpenPhpRegistryKey(char* sub_key, HKEY *hKey)
|
|
|
|
{
|
|
|
|
const char **key_name = registry_keys;
|
|
|
|
|
|
|
|
if (sub_key) {
|
2014-10-28 02:23:03 +08:00
|
|
|
size_t main_key_len;
|
|
|
|
size_t sub_key_len = strlen(sub_key);
|
2006-08-03 21:54:05 +08:00
|
|
|
char *reg_key;
|
|
|
|
|
|
|
|
while (*key_name) {
|
|
|
|
LONG ret;
|
|
|
|
|
|
|
|
main_key_len = strlen(*key_name);
|
|
|
|
reg_key = emalloc(main_key_len + sub_key_len + 1);
|
|
|
|
memcpy(reg_key, *key_name, main_key_len);
|
2015-01-03 17:22:58 +08:00
|
|
|
memcpy(reg_key + main_key_len, sub_key, sub_key_len + 1);
|
2006-08-03 21:54:05 +08:00
|
|
|
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, reg_key, 0, KEY_READ, hKey);
|
|
|
|
efree(reg_key);
|
2015-01-03 17:22:58 +08:00
|
|
|
|
2006-08-03 21:54:05 +08:00
|
|
|
if (ret == ERROR_SUCCESS) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
++key_name;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
while (*key_name) {
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, *key_name, 0, KEY_READ, hKey) == ERROR_SUCCESS) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
++key_name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
2003-10-19 18:22:21 +08:00
|
|
|
|
2006-11-10 19:42:07 +08:00
|
|
|
static int LoadDirectory(HashTable *directories, HKEY key, char *path, int path_len, HashTable *parent_ht)
|
|
|
|
{
|
|
|
|
DWORD keys, values, max_key, max_name, max_value;
|
|
|
|
int ret = 0;
|
|
|
|
HashTable *ht = NULL;
|
|
|
|
|
|
|
|
if (RegQueryInfoKey(key, NULL, NULL, NULL, &keys, &max_key, NULL, &values, &max_name, &max_value, NULL, NULL) == ERROR_SUCCESS) {
|
2015-01-03 17:22:58 +08:00
|
|
|
|
2006-11-10 19:42:07 +08:00
|
|
|
if (values) {
|
|
|
|
DWORD i;
|
|
|
|
char *name = (char*)emalloc(max_name+1);
|
|
|
|
char *value = (char*)emalloc(max_value+1);
|
|
|
|
DWORD name_len, type, value_len;
|
|
|
|
|
|
|
|
for (i = 0; i < values; i++) {
|
|
|
|
name_len = max_name+1;
|
|
|
|
value_len = max_value+1;
|
2015-03-05 02:26:47 +08:00
|
|
|
|
|
|
|
memset(name, '\0', max_name+1);
|
|
|
|
memset(value, '\0', max_value+1);
|
|
|
|
|
2006-11-10 19:42:07 +08:00
|
|
|
if (RegEnumValue(key, i, name, &name_len, NULL, &type, value, &value_len) == ERROR_SUCCESS) {
|
|
|
|
if ((type == REG_SZ) || (type == REG_EXPAND_SZ)) {
|
2015-03-05 02:26:47 +08:00
|
|
|
zval data;
|
|
|
|
|
2006-11-10 19:42:07 +08:00
|
|
|
if (!ht) {
|
2012-08-30 20:32:13 +08:00
|
|
|
ht = (HashTable*)malloc(sizeof(HashTable));
|
|
|
|
if (!ht) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
zend_hash_init(ht, 0, NULL, ZVAL_INTERNAL_PTR_DTOR, 1);
|
2006-11-10 19:42:07 +08:00
|
|
|
}
|
2015-03-05 02:26:47 +08:00
|
|
|
ZVAL_PSTRINGL(&data, value, value_len-1);
|
2014-05-15 02:06:18 +08:00
|
|
|
zend_hash_str_update(ht, name, name_len, &data);
|
2006-11-10 19:42:07 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ht) {
|
|
|
|
if (parent_ht) {
|
2014-05-15 02:06:18 +08:00
|
|
|
zend_string *index;
|
2015-03-05 02:26:47 +08:00
|
|
|
zend_ulong num;
|
2014-05-15 02:06:18 +08:00
|
|
|
zval *tmpdata;
|
2006-11-10 19:42:07 +08:00
|
|
|
|
2014-05-15 02:06:18 +08:00
|
|
|
ZEND_HASH_FOREACH_KEY_VAL(parent_ht, num, index, tmpdata) {
|
|
|
|
zend_hash_add(ht, index, tmpdata);
|
2015-01-03 17:22:58 +08:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
2006-11-10 19:42:07 +08:00
|
|
|
}
|
2015-03-05 02:26:47 +08:00
|
|
|
zend_hash_str_update_mem(directories, path, path_len, ht, sizeof(HashTable));
|
2006-11-10 19:42:07 +08:00
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
efree(name);
|
|
|
|
efree(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ht == NULL) {
|
|
|
|
ht = parent_ht;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (keys) {
|
|
|
|
DWORD i;
|
|
|
|
char *name = (char*)emalloc(max_key+1);
|
|
|
|
char *new_path = (char*)emalloc(path_len+max_key+2);
|
|
|
|
DWORD name_len;
|
|
|
|
FILETIME t;
|
|
|
|
HKEY subkey;
|
|
|
|
|
|
|
|
for (i = 0; i < keys; i++) {
|
|
|
|
name_len = max_key+1;
|
|
|
|
if (RegEnumKeyEx(key, i, name, &name_len, NULL, NULL, NULL, &t) == ERROR_SUCCESS) {
|
|
|
|
if (RegOpenKeyEx(key, name, 0, KEY_READ, &subkey) == ERROR_SUCCESS) {
|
|
|
|
if (path_len) {
|
|
|
|
memcpy(new_path, path, path_len);
|
|
|
|
new_path[path_len] = '/';
|
2007-04-22 18:25:18 +08:00
|
|
|
memcpy(new_path+path_len+1, name, name_len+1);
|
|
|
|
zend_str_tolower(new_path, path_len+name_len+1);
|
2007-05-02 18:16:34 +08:00
|
|
|
name_len += path_len+1;
|
2007-04-22 18:25:18 +08:00
|
|
|
} else {
|
|
|
|
memcpy(new_path, name, name_len+1);
|
|
|
|
zend_str_tolower(new_path, name_len);
|
2006-11-10 19:42:07 +08:00
|
|
|
}
|
2007-05-02 18:16:34 +08:00
|
|
|
if (LoadDirectory(directories, subkey, new_path, name_len, ht)) {
|
2006-11-10 19:42:07 +08:00
|
|
|
ret = 1;
|
|
|
|
}
|
|
|
|
RegCloseKey(subkey);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
efree(new_path);
|
|
|
|
efree(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-07-15 19:50:42 +08:00
|
|
|
static void delete_internal_hashtable(zval *zv)
|
2006-11-10 19:42:07 +08:00
|
|
|
{
|
2015-03-05 02:26:47 +08:00
|
|
|
HashTable *ht = (HashTable *)Z_PTR_P(zv);
|
|
|
|
zend_hash_destroy(ht);
|
|
|
|
free(ht);
|
2006-11-10 19:42:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#define RegNotifyFlags (REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_ATTRIBUTES | REG_NOTIFY_CHANGE_LAST_SET)
|
|
|
|
|
2014-12-14 06:06:14 +08:00
|
|
|
void UpdateIniFromRegistry(char *path)
|
1999-04-18 23:54:18 +08:00
|
|
|
{
|
|
|
|
char *p, *orig_path;
|
2006-11-10 19:42:07 +08:00
|
|
|
int path_len;
|
1999-04-18 23:54:18 +08:00
|
|
|
|
2009-10-14 04:10:07 +08:00
|
|
|
if(!path) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2006-11-10 19:42:07 +08:00
|
|
|
if (!PW32G(registry_directories)) {
|
|
|
|
PW32G(registry_directories) = (HashTable*)malloc(sizeof(HashTable));
|
2012-05-16 19:40:12 +08:00
|
|
|
if (!PW32G(registry_directories)) {
|
|
|
|
return;
|
|
|
|
}
|
2006-11-10 19:42:07 +08:00
|
|
|
zend_hash_init(PW32G(registry_directories), 0, NULL, delete_internal_hashtable, 1);
|
|
|
|
if (!OpenPhpRegistryKey("\\Per Directory Values", &PW32G(registry_key))) {
|
|
|
|
PW32G(registry_key) = NULL;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
PW32G(registry_event) = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
|
|
if (PW32G(registry_event)) {
|
|
|
|
RegNotifyChangeKeyValue(PW32G(registry_key), TRUE, RegNotifyFlags, PW32G(registry_event), TRUE);
|
|
|
|
}
|
|
|
|
if (!LoadDirectory(PW32G(registry_directories), PW32G(registry_key), "", 0, NULL)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (PW32G(registry_event) && WaitForSingleObject(PW32G(registry_event), 0) == WAIT_OBJECT_0) {
|
|
|
|
RegNotifyChangeKeyValue(PW32G(registry_key), TRUE, RegNotifyFlags, PW32G(registry_event), TRUE);
|
|
|
|
zend_hash_clean(PW32G(registry_directories));
|
|
|
|
if (!LoadDirectory(PW32G(registry_directories), PW32G(registry_key), "", 0, NULL)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else if (zend_hash_num_elements(PW32G(registry_directories)) == 0) {
|
1999-04-18 23:54:18 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
orig_path = path = estrdup(path);
|
|
|
|
|
|
|
|
/* Get rid of C:, if exists */
|
|
|
|
p = strchr(path, ':');
|
|
|
|
if (p) {
|
2000-03-25 09:32:47 +08:00
|
|
|
*p = path[0]; /* replace the colon with the drive letter */
|
|
|
|
path = p; /* make path point to the drive letter */
|
1999-04-18 23:54:18 +08:00
|
|
|
} else {
|
|
|
|
if (path[0] != '\\' && path[0] != '/') {
|
|
|
|
char tmp_buf[MAXPATHLEN], *cwd;
|
2000-03-25 09:32:47 +08:00
|
|
|
char drive_letter;
|
1999-04-18 23:54:18 +08:00
|
|
|
|
|
|
|
/* get current working directory and prepend it to the path */
|
2001-04-30 20:45:02 +08:00
|
|
|
if (!VCWD_GETCWD(tmp_buf, MAXPATHLEN)) {
|
1999-04-18 23:54:18 +08:00
|
|
|
efree(orig_path);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cwd = strchr(tmp_buf, ':');
|
|
|
|
if (!cwd) {
|
2000-03-25 09:32:47 +08:00
|
|
|
drive_letter = 'C';
|
1999-04-18 23:54:18 +08:00
|
|
|
cwd = tmp_buf;
|
|
|
|
} else {
|
2000-03-25 09:32:47 +08:00
|
|
|
drive_letter = tmp_buf[0];
|
1999-04-18 23:54:18 +08:00
|
|
|
cwd++;
|
|
|
|
}
|
2005-03-14 20:42:05 +08:00
|
|
|
while (*cwd == '\\' || *cwd == '/') {
|
|
|
|
cwd++;
|
|
|
|
}
|
2007-02-24 10:17:47 +08:00
|
|
|
spprintf(&path, 0, "%c\\%s\\%s", drive_letter, cwd, orig_path);
|
1999-04-18 23:54:18 +08:00
|
|
|
efree(orig_path);
|
|
|
|
orig_path = path;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-11-10 19:42:07 +08:00
|
|
|
path_len = 0;
|
|
|
|
while (path[path_len] != 0) {
|
|
|
|
if (path[path_len] == '\\') {
|
|
|
|
path[path_len] = '/';
|
1999-04-18 23:54:18 +08:00
|
|
|
}
|
2006-11-10 19:42:07 +08:00
|
|
|
path_len++;
|
|
|
|
}
|
|
|
|
zend_str_tolower(path, path_len);
|
2015-03-05 02:26:47 +08:00
|
|
|
|
2015-03-06 23:41:57 +08:00
|
|
|
while (path_len > 0) {
|
2015-03-05 02:26:47 +08:00
|
|
|
HashTable *ht = (HashTable *)zend_hash_str_find_ptr(PW32G(registry_directories), path, path_len);
|
|
|
|
|
|
|
|
if (ht != NULL) {
|
2014-05-15 02:06:18 +08:00
|
|
|
zend_string *index;
|
|
|
|
zval *data;
|
2001-03-20 23:44:55 +08:00
|
|
|
|
2015-02-10 20:43:12 +08:00
|
|
|
ZEND_HASH_FOREACH_STR_KEY_VAL(ht, index, data) {
|
2015-03-05 02:26:47 +08:00
|
|
|
zend_alter_ini_entry(index, Z_STR_P(data), PHP_INI_USER, PHP_INI_STAGE_ACTIVATE);
|
2015-01-03 17:22:58 +08:00
|
|
|
} ZEND_HASH_FOREACH_END();
|
1999-04-18 23:54:18 +08:00
|
|
|
}
|
2014-05-15 02:06:18 +08:00
|
|
|
|
2015-03-06 23:41:57 +08:00
|
|
|
do {
|
|
|
|
path_len--;
|
|
|
|
} while (path_len > 0 && path[path_len] != '/');
|
2006-11-10 19:42:07 +08:00
|
|
|
path[path_len] = 0;
|
1999-04-18 23:54:18 +08:00
|
|
|
}
|
2006-11-10 19:42:07 +08:00
|
|
|
|
1999-04-18 23:54:18 +08:00
|
|
|
efree(orig_path);
|
|
|
|
}
|
2003-10-19 18:22:21 +08:00
|
|
|
|
|
|
|
#define PHPRC_REGISTRY_NAME "IniFilePath"
|
|
|
|
|
|
|
|
char *GetIniPathFromRegistry()
|
|
|
|
{
|
|
|
|
char *reg_location = NULL;
|
|
|
|
HKEY hKey;
|
2015-01-03 17:22:58 +08:00
|
|
|
|
2006-08-03 21:54:05 +08:00
|
|
|
if (OpenPhpRegistryKey(NULL, &hKey)) {
|
2003-10-19 18:22:21 +08:00
|
|
|
DWORD buflen = MAXPATHLEN;
|
2003-10-19 18:36:36 +08:00
|
|
|
reg_location = emalloc(MAXPATHLEN+1);
|
2003-10-19 18:22:21 +08:00
|
|
|
if(RegQueryValueEx(hKey, PHPRC_REGISTRY_NAME, 0, NULL, reg_location, &buflen) != ERROR_SUCCESS) {
|
2015-03-10 03:38:34 +08:00
|
|
|
RegCloseKey(hKey);
|
2003-10-19 18:22:21 +08:00
|
|
|
efree(reg_location);
|
|
|
|
reg_location = NULL;
|
|
|
|
return reg_location;
|
|
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
}
|
|
|
|
return reg_location;
|
|
|
|
}
|