summaryrefslogtreecommitdiff
path: root/win32
diff options
context:
space:
mode:
Diffstat (limited to 'win32')
-rw-r--r--win32/build/buildconf.js2
-rw-r--r--win32/build/config.w323
-rw-r--r--win32/build/config.w32.h.in10
-rw-r--r--win32/build/confutils.js13
-rw-r--r--win32/build/default.manifest9
-rw-r--r--win32/codepage.c618
-rw-r--r--win32/codepage.h162
-rw-r--r--win32/cp_enc_map.c156
-rw-r--r--win32/cp_enc_map_gen.c250
-rw-r--r--win32/dllmain.c7
-rw-r--r--win32/ftok.c52
-rw-r--r--win32/ioutil.c611
-rw-r--r--win32/ioutil.h501
-rw-r--r--win32/ipc.h29
-rw-r--r--win32/param.h3
-rw-r--r--win32/readdir.c126
-rw-r--r--win32/readdir.h24
-rw-r--r--win32/winutil.c319
-rw-r--r--win32/winutil.h29
19 files changed, 2853 insertions, 71 deletions
diff --git a/win32/build/buildconf.js b/win32/build/buildconf.js
index a3a4f1e9aa..d7975d0139 100644
--- a/win32/build/buildconf.js
+++ b/win32/build/buildconf.js
@@ -244,6 +244,8 @@ for (i = 0; i < calls.length; i++) {
}
C.WriteBlankLines(1);
+C.WriteLine("STDOUT.WriteLine(\"PHP Version: \" + PHP_VERSION_STRING);");
+C.WriteLine("STDOUT.WriteBlankLines(1);");
C.WriteLine("conf_process_args();");
C.WriteBlankLines(1);
diff --git a/win32/build/config.w32 b/win32/build/config.w32
index b7e5e49220..58b1420b89 100644
--- a/win32/build/config.w32
+++ b/win32/build/config.w32
@@ -160,7 +160,8 @@ ADD_SOURCES("main/streams", "streams.c cast.c memory.c filter.c plain_wrapper.c
ADD_FLAG("CFLAGS_BD_MAIN_STREAMS", "/D ZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
ADD_SOURCES("win32", "dllmain.c glob.c readdir.c \
- registry.c select.c sendmail.c time.c winutil.c wsyslog.c globals.c getrusage.c");
+ registry.c select.c sendmail.c time.c winutil.c wsyslog.c globals.c \
+ getrusage.c ftok.c ioutil.c codepage.c");
ADD_FLAG("CFLAGS_BD_WIN32", "/D ZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
diff --git a/win32/build/config.w32.h.in b/win32/build/config.w32.h.in
index fd02cc7878..2a8297a144 100644
--- a/win32/build/config.w32.h.in
+++ b/win32/build/config.w32.h.in
@@ -22,15 +22,6 @@
#define PHP_PREFIX "@PREFIX@"
#define PHP_SYSCONFDIR "@PREFIX@"
-/* Enable / Disable crypt() function (default: enabled) */
-#define HAVE_CRYPT 1
-#define PHP_STD_DES_CRYPT 1
-#define PHP_EXT_DES_CRYPT 1
-#define PHP_MD5_CRYPT 1
-#define PHP_BLOWFISH_CRYPT 1
-#define PHP_SHA512_CRYPT 1
-#define PHP_SHA256_CRYPT 1
-
/* PHP Runtime Configuration */
#define PHP_URL_FOPEN 1
#define USE_CONFIG_FILE 1
@@ -183,3 +174,4 @@
#define HAVE_GETRUSAGE
+#define HAVE_FTOK 1
diff --git a/win32/build/confutils.js b/win32/build/confutils.js
index 8ab4b7b0e9..038692911c 100644
--- a/win32/build/confutils.js
+++ b/win32/build/confutils.js
@@ -100,10 +100,10 @@ if (typeof(CWD) == "undefined") {
/* defaults; we pick up the precise versions from configure.in */
var PHP_VERSION = 7;
-var PHP_MINOR_VERSION = 0;
+var PHP_MINOR_VERSION = 1;
var PHP_RELEASE_VERSION = 0;
var PHP_EXTRA_VERSION = "";
-var PHP_VERSION_STRING = "7.0.0";
+var PHP_VERSION_STRING = "7.1.0";
/* Get version numbers and DEFINE as a string */
function get_version_numbers()
@@ -2694,6 +2694,15 @@ function toolset_setup_common_cflags()
if (VCVERS >= 1900) {
ADD_FLAG('CFLAGS', "/guard:cf");
}
+ if (VCVERS >= 1800) {
+ if (PHP_PGI != "yes" && PHP_PGO != "yes") {
+ ADD_FLAG('CFLAGS', "/Zc:inline");
+ }
+ /* We enable /opt:icf only with the debug pack, so /Gw only makes sense there, too. */
+ if (PHP_DEBUG_PACK == "yes") {
+ ADD_FLAG('CFLAGS', "/Gw");
+ }
+ }
}
} else if (CLANG_TOOLSET) {
diff --git a/win32/build/default.manifest b/win32/build/default.manifest
index 77b2a2165a..992f41c738 100644
--- a/win32/build/default.manifest
+++ b/win32/build/default.manifest
@@ -1,6 +1,13 @@
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
- <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
+ <security>
+ <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
+ <requestedExecutionLevel level="asInvoker" uiAccess="false" />
+ </requestedPrivileges>
+ </security>
+ </trustInfo>
+ <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
diff --git a/win32/codepage.c b/win32/codepage.c
new file mode 100644
index 0000000000..d9291305bc
--- /dev/null
+++ b/win32/codepage.c
@@ -0,0 +1,618 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2016 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Anatol Belski <ab@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+#include <assert.h>
+
+#include "php.h"
+#include "SAPI.h"
+
+ZEND_TLS const struct php_win32_cp *cur_cp = NULL;
+ZEND_TLS const struct php_win32_cp *orig_cp = NULL;
+
+#include "cp_enc_map.c"
+
+__forceinline static wchar_t *php_win32_cp_to_w_int(const char* in, size_t in_len, size_t *out_len, UINT cp, DWORD flags)
+{/*{{{*/
+ wchar_t *ret;
+ int ret_len, tmp_len;
+
+ if (!in || in_len > (size_t)INT_MAX) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+ assert(in_len ? in[in_len] == L'\0' : 1);
+
+ tmp_len = !in_len ? -1 : (int)in_len + 1;
+
+ ret_len = MultiByteToWideChar(cp, flags, in, tmp_len, NULL, 0);
+ if (ret_len == 0) {
+ SET_ERRNO_FROM_WIN32_CODE(GetLastError());
+ return NULL;
+ }
+
+ ret = malloc(ret_len * sizeof(wchar_t));
+ if (!ret) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_OUTOFMEMORY);
+ return NULL;
+ }
+
+ tmp_len = MultiByteToWideChar(cp, flags, in, tmp_len, ret, ret_len);
+ if (tmp_len == 0) {
+ free(ret);
+ SET_ERRNO_FROM_WIN32_CODE(GetLastError());
+ return NULL;
+ }
+
+ assert(ret ? tmp_len == ret_len : 1);
+ assert(ret ? wcslen(ret) == ret_len - 1 : 1);
+
+ ret[ret_len-1] = L'\0';
+
+ if (PHP_WIN32_CP_IGNORE_LEN_P != out_len) {
+ *out_len = ret_len - 1;
+ }
+
+ return ret;
+}/*}}}*/
+
+PW32CP wchar_t *php_win32_cp_conv_utf8_to_w(const char* in, size_t in_len, size_t *out_len)
+{/*{{{*/
+ return php_win32_cp_to_w_int(in, in_len, out_len, CP_UTF8, MB_ERR_INVALID_CHARS);
+}/*}}}*/
+
+PW32CP wchar_t *php_win32_cp_conv_cur_to_w(const char* in, size_t in_len, size_t *out_len)
+{/*{{{*/
+ wchar_t *ret;
+
+ ret = php_win32_cp_to_w_int(in, in_len, out_len, cur_cp->id, cur_cp->from_w_fl);
+
+ return ret;
+}/*}}}*/
+
+PW32CP wchar_t *php_win32_cp_conv_to_w(DWORD cp, DWORD flags, const char* in, size_t in_len, size_t *out_len)
+{/*{{{*/
+ return php_win32_cp_to_w_int(in, in_len, out_len, cp, flags);
+}/*}}}*/
+
+PW32CP wchar_t *php_win32_cp_conv_ascii_to_w(const char* in, size_t in_len, size_t *out_len)
+{/*{{{*/
+ wchar_t *ret = NULL;
+ const char *idx = in, *end;
+
+ assert(in && in_len ? in[in_len] == '\0' : 1);
+
+ if (!in) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return NULL;
+ } else if (0 == in_len) {
+ /* Not binary safe. */
+ in_len = strlen(in);
+ if (in_len > (size_t)INT_MAX) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+ }
+
+ end = in + in_len;
+
+ while (idx != end) {
+ if (!__isascii(*idx) && '\0' != *idx) {
+ break;
+ }
+ idx++;
+ }
+
+ if (idx == end) {
+ size_t i = 0;
+ int k = 0;
+ wchar_t *ret_idx;
+
+ ret = malloc((in_len+1)*sizeof(wchar_t));
+ if (!ret) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_OUTOFMEMORY);
+ return NULL;
+ }
+
+ ret_idx = ret;
+ do {
+ k = _snwprintf(ret_idx, in_len - i, L"%.*hs", (int)(in_len - i), in);
+
+ if (-1 == k) {
+ free(ret);
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ i += k + 1;
+
+ if (i < in_len) {
+ /* Advance as this seems to be a string with \0 in it. */
+ in += k + 1;
+ ret_idx += k + 1;
+ }
+
+
+ } while (i < in_len);
+ ret[in_len] = L'\0';
+
+ assert(ret ? wcslen(ret) == in_len : 1);
+
+ if (PHP_WIN32_CP_IGNORE_LEN_P != out_len) {
+ *out_len = in_len;
+ }
+ } else {
+ if (PHP_WIN32_CP_IGNORE_LEN_P != out_len) {
+ *out_len = 0;
+ }
+ }
+
+ return ret;
+}/*}}}*/
+
+__forceinline static char *php_win32_cp_from_w_int(const wchar_t* in, size_t in_len, size_t *out_len, UINT cp, DWORD flags)
+{/*{{{*/
+ int r;
+ int target_len, tmp_len;
+ char* target;
+
+ if (!in || in_len > INT_MAX) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+ assert(in_len ? in[in_len] == '\0' : 1);
+
+ tmp_len = !in_len ? -1 : (int)in_len + 1;
+
+ target_len = WideCharToMultiByte(cp, flags, in, tmp_len, NULL, 0, NULL, NULL);
+ if (target_len == 0) {
+ SET_ERRNO_FROM_WIN32_CODE(GetLastError());
+ return NULL;
+ }
+
+ target = malloc(target_len);
+ if (target == NULL) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_OUTOFMEMORY);
+ return NULL;
+ }
+
+ r = WideCharToMultiByte(cp, flags, in, tmp_len, target, target_len, NULL, NULL);
+ if (r == 0) {
+ free(target);
+ SET_ERRNO_FROM_WIN32_CODE(GetLastError());
+ return NULL;
+ }
+
+ assert(target ? r == target_len : 1);
+ assert(target ? strlen(target) == target_len - 1 : 1);
+
+ target[target_len-1] = '\0';
+
+ if (PHP_WIN32_CP_IGNORE_LEN_P != out_len) {
+ *out_len = target_len - 1;
+ }
+
+ return target;
+}/*}}}*/
+
+PW32CP char *php_win32_cp_conv_w_to_utf8(const wchar_t* in, size_t in_len, size_t *out_len)
+{/*{{{*/
+ return php_win32_cp_from_w_int(in, in_len, out_len, CP_UTF8, WC_ERR_INVALID_CHARS);
+}/*}}}*/
+
+PW32CP char *php_win32_cp_conv_w_to_cur(const wchar_t* in, size_t in_len, size_t *out_len)
+{/*{{{*/
+ char *ret;
+
+ ret = php_win32_cp_from_w_int(in, in_len, out_len, cur_cp->id, cur_cp->from_w_fl);
+
+ return ret;
+}/*}}}*/
+
+PW32CP char *php_win32_cp_conv_from_w(DWORD cp, DWORD flags, const wchar_t* in, size_t in_len, size_t *out_len)
+{/*{{{*/
+ return php_win32_cp_from_w_int(in, in_len, out_len, cp, flags);
+}/*}}}*/
+
+/* This is only usable after the startup phase*/
+__forceinline static char *php_win32_cp_get_enc(void)
+{/*{{{*/
+ char *enc = NULL;
+ const zend_encoding *zenc;
+
+ if (PG(internal_encoding) && PG(internal_encoding)[0]) {
+ enc = PG(internal_encoding);
+ } else if (SG(default_charset) && SG(default_charset)[0] ) {
+ enc = SG(default_charset);
+ } else {
+ zenc = zend_multibyte_get_internal_encoding();
+ if (zenc) {
+ enc = (char *)zend_multibyte_get_encoding_name(zenc);
+ }
+ }
+
+ return enc;
+}/*}}}*/
+
+PW32CP const struct php_win32_cp *php_win32_cp_get_current(void)
+{/*{{{*/
+ return cur_cp;
+}/*}}}*/
+
+PW32CP const struct php_win32_cp *php_win32_cp_get_orig(void)
+{/*{{{*/
+ return orig_cp;
+}/*}}}*/
+
+PW32CP const struct php_win32_cp *php_win32_cp_get_by_id(DWORD id)
+{/*{{{*/
+ size_t i;
+
+ for (i = 0; i < sizeof(php_win32_cp_map)/sizeof(struct php_win32_cp); i++) {
+ if (php_win32_cp_map[i].id == id) {
+ return &php_win32_cp_map[i];
+ }
+ }
+
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_NOT_FOUND);
+
+ return NULL;
+}/*}}}*/
+
+PW32CP const struct php_win32_cp *php_win32_cp_get_by_enc(const char *enc)
+{/*{{{*/
+ size_t enc_len = 0, i;
+
+ if (!enc || !enc[0]) {
+ return php_win32_cp_get_by_id(65001U);
+ }
+
+ enc_len = strlen(enc);
+
+ for (i = 0; i < sizeof(php_win32_cp_map)/sizeof(struct php_win32_cp); i++) {
+ const struct php_win32_cp *cp = &php_win32_cp_map[i];
+
+ if (!cp->name || !cp->name[0]) {
+ continue;
+ }
+
+ if (0 == zend_binary_strcasecmp(enc, enc_len, cp->name, strlen(cp->name))) {
+ cur_cp = cp;
+ return cp;
+ }
+
+ if (cp->enc) {
+ char *start = cp->enc, *idx;
+
+ idx = strpbrk(start, "|");
+
+ while (NULL != idx) {
+ if (0 == zend_binary_strcasecmp(enc, enc_len, start, idx - start)) {
+ cur_cp = cp;
+ return cp;
+ }
+ start = idx + 1;
+ idx = strpbrk(start, "|");
+ }
+ /* Last in the list, or single charset specified. */
+ if (0 == zend_binary_strcasecmp(enc, enc_len, start, strlen(start))) {
+ cur_cp = cp;
+ return cp;
+ }
+ }
+ }
+
+ return php_win32_cp_get_by_id(GetACP());
+}/*}}}*/
+
+PW32CP const struct php_win32_cp *php_win32_cp_set_by_id(DWORD id)
+{/*{{{*/
+ const struct php_win32_cp *tmp;
+ if (!IsValidCodePage(id)) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ tmp = php_win32_cp_get_by_id(id);
+ if (tmp) {
+ cur_cp = tmp;
+ }
+
+ return cur_cp;
+}/*}}}*/
+
+PW32CP BOOL php_win32_cp_use_unicode(void)
+{/*{{{*/
+ return 65001 == cur_cp->id;
+}/*}}}*/
+
+PW32CP wchar_t *php_win32_cp_env_any_to_w(const char* env)
+{/*{{{*/
+ wchar_t *envw = NULL, ew[32760];
+ char *cur = (char *)env, *prev;
+ size_t bin_len = 0;
+
+ if (!env) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ do {
+ wchar_t *tmp;
+ size_t tmp_len;
+
+ tmp = php_win32_cp_any_to_w(cur);
+ if (tmp) {
+ tmp_len = wcslen(tmp) + 1;
+ memmove(ew + bin_len, tmp, tmp_len * sizeof(wchar_t));
+ free(tmp);
+
+ bin_len += tmp_len;
+ }
+
+ prev = cur;
+
+ } while (NULL != (cur = strchr(prev, '\0')) && cur++ && *cur && bin_len + (cur - prev) < 32760);
+
+ envw = (wchar_t *) malloc((bin_len + 3) * sizeof(wchar_t));
+ if (!envw) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_OUTOFMEMORY);
+ return NULL;
+ }
+ memmove(envw, ew, bin_len * sizeof(wchar_t));
+ envw[bin_len] = L'\0';
+ envw[bin_len + 1] = L'\0';
+ envw[bin_len + 2] = L'\0';
+
+ return envw;
+}/*}}}*/
+
+PW32CP const struct php_win32_cp *php_win32_cp_do_setup(const char *enc)
+{/*{{{*/
+ if (!enc) {
+ enc = php_win32_cp_get_enc();
+ }
+
+ if (!strcmp(sapi_module.name, "cli")) {
+ orig_cp = php_win32_cp_get_by_id(GetConsoleCP());
+ } else {
+ orig_cp = php_win32_cp_get_by_id(GetACP());
+ }
+ cur_cp = php_win32_cp_get_by_enc(enc);
+
+ return cur_cp;
+}/*}}}*/
+
+PW32CP const struct php_win32_cp *php_win32_cp_do_update(const char *enc)
+{/*{{{*/
+ if (!enc) {
+ enc = php_win32_cp_get_enc();
+ }
+ cur_cp = php_win32_cp_get_by_enc(enc);
+
+ if (!strcmp(sapi_module.name, "cli")) {
+ php_win32_cp_cli_do_setup(cur_cp->id);
+ }
+
+ return cur_cp;
+}/*}}}*/
+
+PW32CP const struct php_win32_cp *php_win32_cp_shutdown(void)
+{/*{{{*/
+ return orig_cp;
+}/*}}}*/
+
+/* php_win32_cp_setup() needs to have run before! */
+PW32CP const struct php_win32_cp *php_win32_cp_cli_do_setup(DWORD id)
+{/*{{{*/
+ const struct php_win32_cp *cp;
+
+ if (!orig_cp) {
+ php_win32_cp_setup();
+ }
+
+ if (id) {
+ cp = php_win32_cp_set_by_id(id);
+ } else {
+ cp = cur_cp;
+ }
+
+ if (!cp) {
+ return NULL;
+ }
+
+ if (SetConsoleOutputCP(cp->id) && SetConsoleCP(cp->id)) {
+ return cp;
+ }
+
+ return cp;
+}/*}}}*/
+
+PW32CP const struct php_win32_cp *php_win32_cp_cli_do_restore(DWORD id)
+{/*{{{*/
+ if (!id && orig_cp) {
+ id = orig_cp->id;
+ }
+
+ if (SetConsoleOutputCP(id) && SetConsoleCP(id)) {
+ if (orig_cp) {
+ return orig_cp;
+ } else {
+ return php_win32_cp_set_by_id(id);
+ }
+ }
+
+ return NULL;
+}/*}}}*/
+
+/* Userspace functions, see basic_functions.* for arginfo and decls. */
+
+/* {{{ proto bool sapi_windows_cp_set(int cp)
+ * Set process codepage. */
+PHP_FUNCTION(sapi_windows_cp_set)
+{
+ zend_long id;
+ const struct php_win32_cp *cp;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &id) == FAILURE) {
+ return;
+ }
+
+ if (ZEND_LONG_UINT_OVFL(id)) {
+ php_error_docref(NULL, E_WARNING, "Argument %d is out of range", id);
+ RETURN_FALSE;
+ }
+
+ if (!strcmp(sapi_module.name, "cli")) {
+ cp = php_win32_cp_cli_do_setup((DWORD)id);
+ } else {
+ cp = php_win32_cp_set_by_id((DWORD)id);
+ }
+ if (!cp) {
+ php_error_docref(NULL, E_WARNING, "Failed to switch to codepage %d", id);
+ RETURN_FALSE;
+ }
+
+ RETURN_BOOL(cp->id == id);
+}
+/* }}} */
+
+/* {{{ proto int sapi_windows_cp_get([string kind])
+ * Get process codepage. */
+PHP_FUNCTION(sapi_windows_cp_get)
+{
+ char *kind;
+ size_t kind_len = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &kind, &kind_len) == FAILURE) {
+ return;
+ }
+
+ if (kind_len == sizeof("ansi")-1 && !strncasecmp(kind, "ansi", kind_len)) {
+ RETURN_LONG(GetACP());
+ } else if (kind_len == sizeof("oem")-1 && !strncasecmp(kind, "oem", kind_len)) {
+ RETURN_LONG(GetOEMCP());
+ } else {
+ const struct php_win32_cp *cp = php_win32_cp_get_current();
+ RETURN_LONG(cp->id);
+ }
+}
+/* }}} */
+
+
+/* {{{ proto bool sapi_windows_cp_is_utf8(void)
+ * Indicates whether the codepage is UTF-8 compatible. */
+PHP_FUNCTION(sapi_windows_cp_is_utf8)
+{
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ RETURN_BOOL(php_win32_cp_use_unicode());
+}
+/* }}} */
+
+/* {{{ proto string sapi_windows_cp_conv(int|string in_codepage, int|string out_codepage, string subject)
+ * Convert string from one codepage to another. */
+PHP_FUNCTION(sapi_windows_cp_conv)
+{
+ char *subj, *ret;
+ size_t subj_len, ret_len, tmpw_len;
+ wchar_t *tmpw;
+ const struct php_win32_cp *in_cp, *out_cp;
+ zval *z_in_cp, *z_out_cp;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzs", &z_in_cp, &z_out_cp, &subj, &subj_len) == FAILURE) {
+ return;
+ }
+
+ if (ZEND_SIZE_T_INT_OVFL(subj_len)) {
+ php_error_docref(NULL, E_WARNING, "String is too long");
+ RETURN_NULL();
+ }
+
+ if (IS_LONG == Z_TYPE_P(z_in_cp)) {
+ if (ZEND_LONG_UINT_OVFL(Z_LVAL_P(z_in_cp))) {
+ php_error_docref(NULL, E_WARNING, "Argument %d is out of range", Z_LVAL_P(z_in_cp));
+ RETURN_NULL();
+ }
+
+ in_cp = php_win32_cp_get_by_id((DWORD)Z_LVAL_P(z_in_cp));
+ if (!in_cp) {
+ php_error_docref(NULL, E_WARNING, "Invalid codepage %d", Z_LVAL_P(z_in_cp));
+ RETURN_NULL();
+ }
+ } else {
+ convert_to_string(z_in_cp);
+
+ in_cp = php_win32_cp_get_by_enc(Z_STRVAL_P(z_in_cp));
+ if (!in_cp) {
+ php_error_docref(NULL, E_WARNING, "Invalid charset %s", Z_STRVAL_P(z_in_cp));
+ RETURN_NULL();
+ }
+ }
+
+ if (IS_LONG == Z_TYPE_P(z_out_cp)) {
+ if (ZEND_LONG_UINT_OVFL(Z_LVAL_P(z_out_cp))) {
+ php_error_docref(NULL, E_WARNING, "Argument %d is out of range", Z_LVAL_P(z_out_cp));
+ RETURN_NULL();
+ }
+
+ out_cp = php_win32_cp_get_by_id((DWORD)Z_LVAL_P(z_out_cp));
+ if (!out_cp) {
+ php_error_docref(NULL, E_WARNING, "Invalid codepage %d", Z_LVAL_P(z_out_cp));
+ RETURN_NULL();
+ }
+ } else {
+ convert_to_string(z_out_cp);
+
+ out_cp = php_win32_cp_get_by_enc(Z_STRVAL_P(z_out_cp));
+ if (!out_cp) {
+ php_error_docref(NULL, E_WARNING, "Invalid charset %s", Z_STRVAL_P(z_out_cp));
+ RETURN_NULL();
+ }
+ }
+
+ tmpw = php_win32_cp_conv_to_w(in_cp->id, in_cp->to_w_fl, subj, subj_len, &tmpw_len);
+ if (!tmpw) {
+ php_error_docref(NULL, E_WARNING, "Wide char conversion failed");
+ RETURN_NULL();
+ }
+
+ ret = php_win32_cp_conv_from_w(out_cp->id, out_cp->from_w_fl, tmpw, tmpw_len, &ret_len);
+ if (!ret) {
+ free(tmpw);
+ php_error_docref(NULL, E_WARNING, "Wide char conversion failed");
+ RETURN_NULL();
+ }
+
+ RETVAL_STRINGL(ret, ret_len);
+
+ free(tmpw);
+ free(ret);
+}
+/* }}} */
+
+/* }}} */
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/win32/codepage.h b/win32/codepage.h
new file mode 100644
index 0000000000..96afd443ec
--- /dev/null
+++ b/win32/codepage.h
@@ -0,0 +1,162 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2016 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Anatol Belski <ab@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+#ifndef PHP_WIN32_CODEPAGE_H
+#define PHP_WIN32_CODEPAGE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef PHP_EXPORTS
+# define PW32CP __declspec(dllexport)
+#else
+# define PW32CP __declspec(dllimport)
+#endif
+
+#define PHP_WIN32_CP_IGNORE_LEN (0)
+#define PHP_WIN32_CP_IGNORE_LEN_P ((size_t *)-1)
+
+struct php_win32_cp {
+ DWORD id;
+ DWORD to_w_fl;
+ DWORD from_w_fl;
+ DWORD char_size;
+ char *name;
+ char *enc;
+ char *desc;
+};
+
+PW32CP BOOL php_win32_cp_use_unicode(void);
+PW32CP const struct php_win32_cp *php_win32_cp_do_setup(const char *);
+#define php_win32_cp_setup() php_win32_cp_do_setup(NULL)
+PW32CP const struct php_win32_cp *php_win32_cp_do_update(const char *);
+#define php_win32_cp_update() php_win32_cp_do_update(NULL)
+PW32CP const struct php_win32_cp *php_win32_cp_shutdown(void);
+PW32CP const struct php_win32_cp *php_win32_cp_get_current(void);
+PW32CP const struct php_win32_cp *php_win32_cp_get_orig(void);
+PW32CP const struct php_win32_cp *php_win32_cp_get_by_id(DWORD id);
+PW32CP const struct php_win32_cp *php_win32_cp_set_by_id(DWORD id);
+PW32CP const struct php_win32_cp *php_win32_cp_get_by_enc(const char *enc);
+PW32CP const struct php_win32_cp *php_win32_cp_cli_do_setup(DWORD);
+#define php_win32_cp_cli_setup() php_win32_cp_cli_do_setup(0)
+#define php_win32_cp_cli_update() php_win32_cp_cli_do_setup(0)
+PW32CP const struct php_win32_cp *php_win32_cp_cli_do_restore(DWORD);
+#define php_win32_cp_cli_restore() php_win32_cp_cli_do_restore(0)
+
+/* This API is binary safe and expects a \0 terminated input.
+ The returned out is \0 terminated, but the length doesn't count \0. */
+PW32CP wchar_t *php_win32_cp_conv_to_w(DWORD in_cp, DWORD flags, const char* in, size_t in_len, size_t *out_len);
+PW32CP wchar_t *php_win32_cp_conv_utf8_to_w(const char* in, size_t in_len, size_t *out_len);
+#define php_win32_cp_utf8_to_w(in) php_win32_cp_conv_utf8_to_w(in, PHP_WIN32_CP_IGNORE_LEN, PHP_WIN32_CP_IGNORE_LEN_P)
+PW32CP wchar_t *php_win32_cp_conv_cur_to_w(const char* in, size_t in_len, size_t *out_len);
+#define php_win32_cp_cur_to_w(in) php_win32_cp_conv_cur_to_w(in, PHP_WIN32_CP_IGNORE_LEN, PHP_WIN32_CP_IGNORE_LEN_P)
+PW32CP wchar_t *php_win32_cp_conv_ascii_to_w(const char* in, size_t in_len, size_t *out_len);
+#define php_win32_cp_ascii_to_w(in) php_win32_cp_conv_ascii_to_w(in, PHP_WIN32_CP_IGNORE_LEN, PHP_WIN32_CP_IGNORE_LEN_P)
+PW32CP char *php_win32_cp_conv_from_w(DWORD out_cp, DWORD flags, const wchar_t* in, size_t in_len, size_t *out_len);
+PW32CP char *php_win32_cp_conv_w_to_utf8(const wchar_t* in, size_t in_len, size_t *out_len);
+#define php_win32_cp_w_to_utf8(in) php_win32_cp_conv_w_to_utf8(in, PHP_WIN32_CP_IGNORE_LEN, PHP_WIN32_CP_IGNORE_LEN_P)
+PW32CP char *php_win32_cp_conv_w_to_cur(const wchar_t* in, size_t in_len, size_t *out_len);
+#define php_win32_cp_w_to_cur(in) php_win32_cp_conv_w_to_cur(in, PHP_WIN32_CP_IGNORE_LEN, PHP_WIN32_CP_IGNORE_LEN_P)
+PW32CP wchar_t *php_win32_cp_env_any_to_w(const char* env);
+
+/* This function tries to make the best guess to convert any
+ given string to a wide char, also prefering the fastest code
+ path to unicode. It returns NULL on fail. */
+__forceinline static wchar_t *php_win32_cp_conv_any_to_w(const char* in, size_t in_len, size_t *out_len)
+{/*{{{*/
+ wchar_t *ret = NULL;
+
+ if (php_win32_cp_use_unicode()) {
+ /* First try the pure ascii conversion. This is the fastest way to do the
+ thing. Only applicable if the source string is UTF-8 in general.
+ While it could possibly be ok with European encodings, usage with
+ Asian encodings can cause unintended side effects. Lookup the term
+ "mojibake" if need more. */
+ ret = php_win32_cp_conv_ascii_to_w(in, in_len, out_len);
+
+ /* If that failed, try to convert to multibyte. */
+ if (!ret) {
+ ret = php_win32_cp_conv_utf8_to_w(in, in_len, out_len);
+
+ /* Still need this fallback with regard to possible broken data
+ in the existing scripts. Broken data might be hardcoded in
+ the user scripts, as UTF-8 settings was de facto ignored in
+ older PHP versions. The fallback can be removed later for
+ the sake of purity, keep now for BC reasons. */
+ if (!ret) {
+ const struct php_win32_cp *acp = php_win32_cp_get_by_id(GetACP());
+
+ if (acp) {
+ ret = php_win32_cp_conv_to_w(acp->id, acp->to_w_fl, in, in_len, out_len);
+ }
+ }
+ }
+ } else {
+ /* No unicode, convert from the current thread cp. */
+ ret = php_win32_cp_conv_cur_to_w(in, in_len, out_len);
+ }
+
+ return ret;
+}/*}}}*/
+#define php_win32_cp_any_to_w(in) php_win32_cp_conv_any_to_w(in, PHP_WIN32_CP_IGNORE_LEN, PHP_WIN32_CP_IGNORE_LEN_P)
+
+/* This function converts from unicode function output back to PHP. If
+ the PHP's current charset is not compatible with unicode, so the currently
+ configured CP will be used. */
+__forceinline static char *php_win32_cp_conv_w_to_any(const wchar_t* in, size_t in_len, size_t *out_len)
+{/*{{{*/
+ return php_win32_cp_conv_w_to_cur(in, in_len, out_len);
+}/*}}}*/
+#define php_win32_cp_w_to_any(in) php_win32_cp_conv_w_to_any(in, PHP_WIN32_CP_IGNORE_LEN, PHP_WIN32_CP_IGNORE_LEN_P)
+
+#define PHP_WIN32_CP_W_TO_ANY_ARRAY(aw, aw_len, aa, aa_len) do { \
+ int i; \
+ aa_len = aw_len; \
+ aa = (char **) malloc(aw_len * sizeof(char *)); \
+ if (!aa) { \
+ break; \
+ } \
+ for (i = 0; i < aw_len; i++) { \
+ aa[i] = php_win32_cp_w_to_any(aw[i]); \
+ } \
+} while (0);
+
+
+#define PHP_WIN32_CP_FREE_ARRAY(a, a_len) do { \
+ int i; \
+ for (i = 0; i < a_len; i++) { \
+ free(a[i]); \
+ } \
+ free(a); \
+} while (0);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PHP_WIN32_CODEPAGE_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/win32/cp_enc_map.c b/win32/cp_enc_map.c
new file mode 100644
index 0000000000..08a71fdc5e
--- /dev/null
+++ b/win32/cp_enc_map.c
@@ -0,0 +1,156 @@
+/* Autogenerated file. Update cp_enc_map_gen.c and regen like
+ cp_enc_map_gen.exe > cp_enc_map.c
+*/
+
+static const struct php_win32_cp php_win32_cp_map[] = { { 37, 0, 0, 1, "IBM037", NULL, "37 (IBM EBCDIC - U.S./Canada)" },
+ { 437, 0, 0, 1, "IBM437", NULL, "437 (OEM - United States)" },
+ { 500, 0, 0, 1, "IBM500", NULL, "500 (IBM EBCDIC - International)" },
+ { 708, 0, 0, 1, "ASMO-708", NULL, "708 (Arabic - ASMO)" },
+ /* 709 is invalid */
+ /* 710 is invalid */
+ { 720, 0, 0, 1, "DOS-720", NULL, "720 (Arabic - Transparent ASMO)" },
+ { 737, 0, 0, 1, "ibm737", NULL, "737 (OEM - Greek 437G)" },
+ { 775, 0, 0, 1, "ibm775", NULL, "775 (OEM - Baltic)" },
+ { 850, 0, 0, 1, "ibm850", "850|CP850|IBM850|CSPC850MULTILINGUAL", "850 (OEM - Multilingual Latin I)" },
+ { 852, 0, 0, 1, "ibm852", NULL, "852 (OEM - Latin II)" },
+ { 855, 0, 0, 1, "IBM855", NULL, "855 (OEM - Cyrillic)" },
+ { 857, 0, 0, 1, "ibm857", NULL, "857 (OEM - Turkish)" },
+ { 858, 0, 0, 1, "IBM00858", NULL, "858 (OEM - Multilingual Latin I + Euro)" },
+ { 860, 0, 0, 1, "IBM860", NULL, "860 (OEM - Portuguese)" },
+ { 861, 0, 0, 1, "ibm861", NULL, "861 (OEM - Icelandic)" },
+ { 862, 0, 0, 1, "DOS-862", "862|CP862|IBM862|CSPC862LATINHEBREW", "862 (OEM - Hebrew)" },
+ { 863, 0, 0, 1, "IBM863", NULL, "863 (OEM - Canadian French)" },
+ { 864, 0, 0, 1, "IBM864", NULL, "864 (OEM - Arabic)" },
+ { 865, 0, 0, 1, "IBM865", NULL, "865 (OEM - Nordic)" },
+ { 866, 0, 0, 1, "cp866", "866|CP866|IBM866|CSIBM866", "866 (OEM - Russian)" },
+ { 869, 0, 0, 1, "ibm869", NULL, "869 (OEM - Modern Greek)" },
+ { 870, 0, 0, 1, "IBM870", NULL, "870 (IBM EBCDIC - Multilingual/ROECE (Latin-2))" },
+ { 874, 0, 0, 1, "windows-874", "CP874", "874 (ANSI/OEM - Thai)" },
+ { 875, 0, 0, 1, "cp875", NULL, "875 (IBM EBCDIC - Modern Greek)" },
+ { 932, 0, 0, 2, "shift_jis", "CP932|SHIFT_JIS|MS_KANJI|CSSHIFTJIS", "932 (ANSI/OEM - Japanese Shift-JIS)" },
+ { 936, 0, 0, 2, "gb2312", "GB2312|GBK|CP936|MS936|WINDOWS-936", "936 (ANSI/OEM - Simplified Chinese GBK)" },
+ { 949, 0, 0, 2, "ks_c_5601-1987", "CP949|UHC", "949 (ANSI/OEM - Korean)" },
+ { 950, 0, 0, 2, "big5", "CP950|BIG-5", "950 (ANSI/OEM - Traditional Chinese Big5)" },
+ { 1026, 0, 0, 1, "IBM1026", NULL, "1026 (IBM EBCDIC - Turkish (Latin-5))" },
+ { 1047, 0, 0, 1, "IBM01047", NULL, "1047 (IBM EBCDIC - Latin-1/Open System)" },
+ { 1140, 0, 0, 1, "IBM01140", NULL, "1140 (IBM EBCDIC - U.S./Canada (37 + Euro))" },
+ { 1141, 0, 0, 1, "IBM01141", NULL, "1141 (IBM EBCDIC - Germany (20273 + Euro))" },
+ { 1142, 0, 0, 1, "IBM01142", NULL, "1142 (IBM EBCDIC - Denmark/Norway (20277 + Euro))" },
+ { 1143, 0, 0, 1, "IBM01143", NULL, "1143 (IBM EBCDIC - Finland/Sweden (20278 + Euro))" },
+ { 1144, 0, 0, 1, "IBM01144", NULL, "1144 (IBM EBCDIC - Italy (20280 + Euro))" },
+ { 1145, 0, 0, 1, "IBM01145", NULL, "1145 (IBM EBCDIC - Latin America/Spain (20284 + Euro))" },
+ { 1146, 0, 0, 1, "IBM01146", NULL, "1146 (IBM EBCDIC - United Kingdom (20285 + Euro))" },
+ { 1148, 0, 0, 1, "IBM01148", NULL, "1148 (IBM EBCDIC - International (500 + Euro))" },
+ { 1149, 0, 0, 1, "IBM01149", NULL, "1149 (IBM EBCDIC - Icelandic (20871 + Euro))" },
+ /* 1200 is invalid */
+ /* 1201 is invalid */
+ { 1250, 0, 0, 1, "windows-1250", "CP1250|MS-EE|WINDOWS-1250", "1250 (ANSI - Central Europe)" },
+ { 1251, 0, 0, 1, "windows-1251", "CP1251|MS-CYRL|WINDOWS-1251", "1251 (ANSI - Cyrillic)" },
+ { 1252, 0, 0, 1, "windows-1252", "CP1252|MS-ANSI|WINDOWS-1252", "1252 (ANSI - Latin I)" },
+ { 1253, 0, 0, 1, "windows-1253", "CP1253|MS-GREEK|WINDOWS-1253", "1253 (ANSI - Greek)" },
+ { 1254, 0, 0, 1, "windows-1254", "CP1254|MS-TURK|WINDOWS-1254", "1254 (ANSI - Turkish)" },
+ { 1255, 0, 0, 1, "windows-1255", "CP1255|MS-HEBR|WINDOWS-1255", "1255 (ANSI - Hebrew)" },
+ { 1256, 0, 0, 1, "windows-1256", "CP1256|MS-ARAB|WINDOWS-1256", "1256 (ANSI - Arabic)" },
+ { 1257, 0, 0, 1, "windows-1257", "CP1257|WINBALTRIM|WINDOWS-1257", "1257 (ANSI - Baltic)" },
+ { 1258, 0, 0, 1, "windows-1258", "CP1258|WINDOWS-1258", "1258 (ANSI/OEM - Viet Nam)" },
+ { 1361, 0, 0, 2, "Johab", "CP1361|JOHAB", "1361 (Korean - Johab)" },
+ { 10000, 0, 0, 1, "macintosh", "MAC|MACINTOSH|MACROMAN|CSMACINTOSH", "10000 (MAC - Roman)" },
+ { 10001, 0, 0, 2, "x-mac-japanese", NULL, "10001 (MAC - Japanese)" },
+ { 10002, 0, 0, 2, "x-mac-chinesetrad", NULL, "10002 (MAC - Traditional Chinese Big5)" },
+ { 10003, 0, 0, 2, "x-mac-korean", NULL, "10003 (MAC - Korean)" },
+ { 10004, 0, 0, 1, "x-mac-arabic", "MACARABIC", "10004 (MAC - Arabic)" },
+ { 10005, 0, 0, 1, "x-mac-hebrew", "MACHEBREW", "10005 (MAC - Hebrew)" },
+ { 10006, 0, 0, 1, "x-mac-greek", "MACGREEK", "10006 (MAC - Greek I)" },
+ { 10007, 0, 0, 1, "x-mac-cyrillic", "MACCYRILLIC", "10007 (MAC - Cyrillic)" },
+ { 10008, 0, 0, 2, "x-mac-chinesesimp", NULL, "10008 (MAC - Simplified Chinese GB 2312)" },
+ { 10010, 0, 0, 1, "x-mac-romanian", "MACROMANIA", "10010 (MAC - Romania)" },
+ { 10017, 0, 0, 1, "x-mac-ukrainian", "MACUKRAINE", "10017 (MAC - Ukraine)" },
+ { 10021, 0, 0, 1, "x-mac-thai", "MACTHAI", "10021 (MAC - Thai)" },
+ { 10029, 0, 0, 1, "x-mac-ce", "MACCENTRALEUROPE", "10029 (MAC - Latin II)" },
+ { 10079, 0, 0, 1, "x-mac-icelandic", "MACICELAND", "10079 (MAC - Icelandic)" },
+ { 10081, 0, 0, 1, "x-mac-turkish", "MACTURKISH", "10081 (MAC - Turkish)" },
+ { 10082, 0, 0, 1, "x-mac-croatian", "MACCROATIAN", "10082 (MAC - Croatia)" },
+ /* 12000 is invalid */
+ /* 12001 is invalid */
+ { 20000, 0, 0, 2, "x-Chinese_CNS", NULL, "20000 (CNS - Taiwan)" },
+ { 20001, 0, 0, 2, "x-cp20001", NULL, "20001 (TCA - Taiwan)" },
+ { 20002, 0, 0, 2, "x_Chinese-Eten", NULL, "20002 (Eten - Taiwan)" },
+ { 20003, 0, 0, 2, "x-cp20003", NULL, "20003 (IBM5550 - Taiwan)" },
+ { 20004, 0, 0, 2, "x-cp20004", NULL, "20004 (TeleText - Taiwan)" },
+ { 20005, 0, 0, 2, "x-cp20005", NULL, "20005 (Wang - Taiwan)" },
+ { 20105, 0, 0, 1, "x-IA5", NULL, "20105 (IA5 IRV International Alphabet No.5)" },
+ { 20106, 0, 0, 1, "x-IA5-German", NULL, "20106 (IA5 German)" },
+ { 20107, 0, 0, 1, "x-IA5-Swedish", NULL, "20107 (IA5 Swedish)" },
+ { 20108, 0, 0, 1, "x-IA5-Norwegian", NULL, "20108 (IA5 Norwegian)" },
+ { 20127, 0, 0, 1, "us-ascii", NULL, "20127 (US-ASCII)" },
+ { 20261, 0, 0, 2, "x-cp20261", NULL, "20261 (T.61)" },
+ { 20269, 0, 0, 1, "x-cp20269", NULL, "20269 (ISO 6937 Non-Spacing Accent)" },
+ { 20273, 0, 0, 1, "IBM273", NULL, "20273 (IBM EBCDIC - Germany)" },
+ { 20277, 0, 0, 1, "IBM277", NULL, "20277 (IBM EBCDIC - Denmark/Norway)" },
+ { 20278, 0, 0, 1, "IBM278", NULL, "20278 (IBM EBCDIC - Finland/Sweden)" },
+ { 20280, 0, 0, 1, "IBM280", NULL, "20280 (IBM EBCDIC - Italy)" },
+ { 20284, 0, 0, 1, "IBM284", NULL, "20284 (IBM EBCDIC - Latin America/Spain)" },
+ { 20285, 0, 0, 1, "IBM285", NULL, "20285 (IBM EBCDIC - United Kingdom)" },
+ { 20290, 0, 0, 1, "IBM290", NULL, "20290 (IBM EBCDIC - Japanese Katakana Extended)" },
+ { 20297, 0, 0, 1, "IBM297", NULL, "20297 (IBM EBCDIC - France)" },
+ { 20420, 0, 0, 1, "IBM420", NULL, "20420 (IBM EBCDIC - Arabic)" },
+ { 20423, 0, 0, 1, "IBM423", NULL, "20423 (IBM EBCDIC - Greek)" },
+ { 20424, 0, 0, 1, "IBM424", NULL, "20424 (IBM EBCDIC - Hebrew)" },
+ { 20833, 0, 0, 1, "x-EBCDIC-KoreanExtended", NULL, "20833 (IBM EBCDIC - Korean Extended)" },
+ { 20838, 0, 0, 1, "IBM-Thai", NULL, "20838 (IBM EBCDIC - Thai)" },
+ { 20866, 0, 0, 1, "koi8-r", "KOI8-R|CSKOI8R", "20866 (Russian - KOI8)" },
+ { 20871, 0, 0, 1, "IBM871", NULL, "20871 (IBM EBCDIC - Icelandic)" },
+ { 20880, 0, 0, 1, "IBM880", NULL, "20880 (IBM EBCDIC - Cyrillic (Russian))" },
+ { 20905, 0, 0, 1, "IBM905", NULL, "20905 (IBM EBCDIC - Turkish)" },
+ { 20924, 0, 0, 1, "IBM00924", NULL, "20924 (IBM EBCDIC - Latin-1/Open System (1047 + Euro))" },
+ { 20932, 0, 0, 2, "EUC-JP", "EUC-JP|EUCJP|EXTENDED_UNIX_CODE_PACKED_FORMAT_FOR_JAPANESE|CSEUCPKDFMTJAPANESE", "20932 (JIS X 0208-1990 & 0212-1990)" },
+ { 20936, 0, 0, 2, "x-cp20936", NULL, "20936 (Simplified Chinese GB2312)" },
+ { 21025, 0, 0, 1, "cp1025", NULL, "21025 (IBM EBCDIC - Cyrillic (Serbian, Bulgarian))" },
+ { 21027, 0, 0, 1, "", NULL, "21027 (Ext Alpha Lowercase)" },
+ { 21866, 0, 0, 1, "koi8-u", "KOI8-U", "21866 (Ukrainian - KOI8-U)" },
+ { 28591, 0, 0, 1, "iso-8859-1", "CP819|IBM819|ISO-8859-1|ISO-IR-100|ISO8859-1|ISO_8859-1|ISO_8859-1:1987|L1|LATIN1|CSISOLATIN1", "28591 (ISO 8859-1 Latin I)" },
+ { 28592, 0, 0, 1, "iso-8859-2", "ISO-8859-2|ISO-IR-101|ISO8859-2|ISO_8859-2|ISO_8859-2:1987|L2|LATIN2|CSISOLATIN2", "28592 (ISO 8859-2 Central Europe)" },
+ { 28593, 0, 0, 1, "iso-8859-3", "ISO-8859-3|ISO-IR-109|ISO8859-3|ISO_8859-3|ISO_8859-3:1988|L3|LATIN3|CSISOLATIN3", "28593 (ISO 8859-3 Latin 3)" },
+ { 28594, 0, 0, 1, "iso-8859-4", "ISO-8859-4|ISO-IR-110|ISO8859-4|ISO_8859-4|ISO_8859-4:1988|L4|LATIN4|CSISOLATIN4", "28594 (ISO 8859-4 Baltic)" },
+ { 28595, 0, 0, 1, "iso-8859-5", "CYRILLIC|ISO-8859-5|ISO-IR-144|ISO8859-5|ISO_8859-5|ISO_8859-5:1988|CSISOLATINCYRILLIC", "28595 (ISO 8859-5 Cyrillic)" },
+ { 28596, 0, 0, 1, "iso-8859-6", "ARABIC|ASMO-708|ECMA-114|ISO-8859-6|ISO-IR-127|ISO8859-6|ISO_8859-6|ISO_8859-6:1987|CSISOLATINARABIC", "28596 (ISO 8859-6 Arabic)" },
+ { 28597, 0, 0, 1, "iso-8859-7", "ECMA-118|ELOT_928|GREEK|GREEK8|ISO-8859-7|ISO-IR-126|ISO8859-7|ISO_8859-7|ISO_8859-7:1987|ISO_8859-7:2003|CSISOLATINGREEK", "28597 (ISO 8859-7 Greek)" },
+ { 28598, 0, 0, 1, "iso-8859-8", "HEBREW|ISO-8859-8|ISO-IR-138|ISO8859-8|ISO_8859-8|ISO_8859-8:1988|CSISOLATINHEBREW", "28598 (ISO 8859-8 Hebrew: Visual Ordering)" },
+ { 28599, 0, 0, 1, "iso-8859-9", "ISO-8859-9|ISO-IR-148|ISO8859-9|ISO_8859-9|ISO_8859-9:1989|L5|LATIN5|CSISOLATIN5", "28599 (ISO 8859-9 Latin 5)" },
+ { 28603, 0, 0, 1, "iso-8859-13", "ISO-8859-13|ISO-IR-179|ISO8859-13|ISO_8859-13|L7|LATIN7", "28603 (ISO 8859-13 Latin 7)" },
+ { 28605, 0, 0, 1, "iso-8859-15", "ISO-8859-15|ISO-IR-203|ISO8859-15|ISO_8859-15|ISO_8859-15:1998|LATIN-9", "28605 (ISO 8859-15 Latin 9)" },
+ /* 29001 is invalid */
+ { 38598, 0, 0, 1, "iso-8859-8-i", NULL, "38598 (ISO 8859-8 Hebrew: Logical Ordering)" },
+ { 50220, 0, 0, 5, "iso-2022-jp", "CP50220", "50220 (ISO-2022 Japanese with no halfwidth Katakana)" },
+ { 50221, 0, 0, 5, "csISO2022JP", "CP50221", "50221 (ISO-2022 Japanese with halfwidth Katakana)" },
+ { 50222, 0, 0, 5, "iso-2022-jp", "ISO-2022-JP|CP50222", "50222 (ISO-2022 Japanese JIS X 0201-1989)" },
+ { 50225, 0, 0, 5, "iso-2022-kr", "ISO-2022-KR|CSISO2022KR", "50225 (ISO-2022 Korean)" },
+ { 50227, 0, 0, 5, "x-cp50227", NULL, "50227 (ISO-2022 Simplified Chinese)" },
+ { 50229, 0, 0, 5, "", NULL, "50229 (ISO-2022 Traditional Chinese)" },
+ /* 50930 is invalid */
+ /* 50931 is invalid */
+ /* 50933 is invalid */
+ /* 50935 is invalid */
+ /* 50936 is invalid */
+ /* 50937 is invalid */
+ /* 50939 is invalid */
+ /* 51932 is invalid */
+ /* 51936 is invalid */
+ { 51949, 0, 0, 2, "euc-kr", "EUC-KR|EUCKR|CSEUCKR", "51949 (EUC-Korean)" },
+ /* 51950 is invalid */
+ { 52936, 0, 0, 5, "hz-gb-2312", "HZ|HZ-GB-2312", "52936 (HZ-GB2312 Simplified Chinese)" },
+ { 54936, 8, 128, 4, "GB18030", "GB18030|CSGB18030", "54936 (GB18030 Simplified Chinese)" },
+ { 57002, 0, 0, 4, "x-iscii-de", NULL, "57002 (ISCII - Devanagari)" },
+ { 57003, 0, 0, 4, "x-iscii-be", NULL, "57003 (ISCII - Bengali)" },
+ { 57004, 0, 0, 4, "x-iscii-ta", NULL, "57004 (ISCII - Tamil)" },
+ { 57005, 0, 0, 4, "x-iscii-te", NULL, "57005 (ISCII - Telugu)" },
+ { 57006, 0, 0, 4, "x-iscii-as", NULL, "57006 (ISCII - Assamese)" },
+ { 57007, 0, 0, 4, "x-iscii-or", NULL, "57007 (ISCII - Odia (Oriya))" },
+ { 57008, 0, 0, 4, "x-iscii-ka", NULL, "57008 (ISCII - Kannada)" },
+ { 57009, 0, 0, 4, "x-iscii-ma", NULL, "57009 (ISCII - Malayalam)" },
+ { 57010, 0, 0, 4, "x-iscii-gu", NULL, "57010 (ISCII - Gujarati)" },
+ { 57011, 0, 0, 4, "x-iscii-pa", NULL, "57011 (ISCII - Punjabi (Gurmukhi))" },
+ { 65000, 0, 0, 5, "utf-7", "UTF-7", "65000 (UTF-7)" },
+ { 65001, 8, 128, 4, "utf-8", "UTF-8", "65001 (UTF-8)" },
+};
+
diff --git a/win32/cp_enc_map_gen.c b/win32/cp_enc_map_gen.c
new file mode 100644
index 0000000000..e99ef75faa
--- /dev/null
+++ b/win32/cp_enc_map_gen.c
@@ -0,0 +1,250 @@
+
+#include <stdio.h>
+
+#include <windows.h>
+
+struct cp {
+ DWORD id;
+ char *name;
+ char *enc;
+ char *desc;
+};
+
+static const struct cp cp_map[] = {
+ { 37, "IBM037", "", "IBM EBCDIC US-Canada" },
+ { 437, "IBM437", "", "OEM United States" },
+ { 500, "IBM500", "", "IBM EBCDIC International" },
+ { 708, "ASMO-708", "", "Arabic (ASMO 708)" },
+ { 709, "", "", "Arabic (ASMO-449+, BCON V4)" },
+ { 710, "", "", "Arabic - Transparent Arabic" },
+ { 720, "DOS-720", "", "Arabic (Transparent ASMO); Arabic (DOS)" },
+ { 737, "ibm737", "", "OEM Greek (formerly 437G); Greek (DOS)" },
+ { 775, "ibm775", "", "OEM Baltic; Baltic (DOS)" },
+ { 850, "ibm850", "850|CP850|IBM850|CSPC850MULTILINGUAL", "OEM Multilingual Latin 1; Western European (DOS)" },
+ { 852, "ibm852", "", "OEM Latin 2; Central European (DOS)" },
+ { 855, "IBM855", "", "OEM Cyrillic (primarily Russian)" },
+ { 857, "ibm857", "", "OEM Turkish; Turkish (DOS)" },
+ { 858, "IBM00858", "", "OEM Multilingual Latin 1 + Euro symbol" },
+ { 860, "IBM860", "", "OEM Portuguese; Portuguese (DOS)" },
+ { 861, "ibm861", "", "OEM Icelandic; Icelandic (DOS)" },
+ { 862, "DOS-862", "862|CP862|IBM862|CSPC862LATINHEBREW", "OEM Hebrew; Hebrew (DOS)" },
+ { 863, "IBM863", "", "OEM French Canadian; French Canadian (DOS)" },
+ { 864, "IBM864", "", "OEM Arabic; Arabic (864)" },
+ { 865, "IBM865", "", "OEM Nordic; Nordic (DOS)" },
+ { 866, "cp866", "866|CP866|IBM866|CSIBM866", "OEM Russian; Cyrillic (DOS)" },
+ { 869, "ibm869", "", "OEM Modern Greek; Greek, Modern (DOS)" },
+ { 870, "IBM870", "", "IBM EBCDIC Multilingual/ROECE (Latin 2); IBM EBCDIC Multilingual Latin 2" },
+ { 874, "windows-874", "CP874", "ANSI/OEM Thai (ISO 8859-11); Thai (Windows)" },
+ { 875, "cp875", "", "IBM EBCDIC Greek Modern" },
+ { 932, "shift_jis", "CP932|SHIFT_JIS|MS_KANJI|CSSHIFTJIS", "ANSI/OEM Japanese; Japanese (Shift-JIS)" },
+ { 936, "gb2312", "GB2312|GBK|CP936|MS936|WINDOWS-936", "ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312)" },
+ { 949, "ks_c_5601-1987", "CP949|UHC", "ANSI/OEM Korean (Unified Hangul Code)" },
+ { 950, "big5", "CP950|BIG-5", "ANSI/OEM Traditional Chinese (Taiwan; Hong Kong SAR, PRC); Chinese Traditional (Big5)" },
+ { 1026, "IBM1026", "", "IBM EBCDIC Turkish (Latin 5)" },
+ { 1047, "IBM01047", "", "IBM EBCDIC Latin 1/Open System" },
+ { 1140, "IBM01140", "", "IBM EBCDIC US-Canada (037 + Euro symbol); IBM EBCDIC (US-Canada-Euro)" },
+ { 1141, "IBM01141", "", "IBM EBCDIC Germany (20273 + Euro symbol); IBM EBCDIC (Germany-Euro)" },
+ { 1142, "IBM01142", "", "IBM EBCDIC Denmark-Norway (20277 + Euro symbol); IBM EBCDIC (Denmark-Norway-Euro)" },
+ { 1143, "IBM01143", "", "IBM EBCDIC Finland-Sweden (20278 + Euro symbol); IBM EBCDIC (Finland-Sweden-Euro)" },
+ { 1144, "IBM01144", "", "IBM EBCDIC Italy (20280 + Euro symbol); IBM EBCDIC (Italy-Euro)" },
+ { 1145, "IBM01145", "", "IBM EBCDIC Latin America-Spain (20284 + Euro symbol); IBM EBCDIC (Spain-Euro)" },
+ { 1146, "IBM01146", "", "IBM EBCDIC United Kingdom (20285 + Euro symbol); IBM EBCDIC (UK-Euro)" },
+ { 1147, "IBM01147", "", "IBM EBCDIC France (20297 + Euro symbol); IBM EBCDIC (France-Euro)" },
+ { 1148, "IBM01148", "", "IBM EBCDIC International (500 + Euro symbol); IBM EBCDIC (International-Euro)" },
+ { 1149, "IBM01149", "", "IBM EBCDIC Icelandic (20871 + Euro symbol); IBM EBCDIC (Icelandic-Euro)" },
+ { 1200, "utf-16", "", "Unicode UTF-16, little endian byte order (BMP of ISO 10646); available only to managed applications" },
+ { 1201, "unicodeFFFE", "", "Unicode UTF-16, big endian byte order; available only to managed applications" },
+ { 1250, "windows-1250", "CP1250|MS-EE|WINDOWS-1250", "ANSI Central European; Central European (Windows)" },
+ { 1251, "windows-1251", "CP1251|MS-CYRL|WINDOWS-1251", "ANSI Cyrillic; Cyrillic (Windows)" },
+ { 1252, "windows-1252", "CP1252|MS-ANSI|WINDOWS-1252", "ANSI Latin 1; Western European (Windows)" },
+ { 1253, "windows-1253", "CP1253|MS-GREEK|WINDOWS-1253", "ANSI Greek; Greek (Windows)" },
+ { 1254, "windows-1254", "CP1254|MS-TURK|WINDOWS-1254", "ANSI Turkish; Turkish (Windows)" },
+ { 1255, "windows-1255", "CP1255|MS-HEBR|WINDOWS-1255", "ANSI Hebrew; Hebrew (Windows)" },
+ { 1256, "windows-1256", "CP1256|MS-ARAB|WINDOWS-1256", "ANSI Arabic; Arabic (Windows)" },
+ { 1257, "windows-1257", "CP1257|WINBALTRIM|WINDOWS-1257", "ANSI Baltic; Baltic (Windows)" },
+ { 1258, "windows-1258", "CP1258|WINDOWS-1258", "ANSI/OEM Vietnamese; Vietnamese (Windows)" },
+ { 1361, "Johab", "CP1361|JOHAB", "Korean (Johab)" },
+ { 10000, "macintosh", "MAC|MACINTOSH|MACROMAN|CSMACINTOSH", "MAC Roman; Western European (Mac)" },
+ { 10001, "x-mac-japanese", "", "Japanese (Mac)" },
+ { 10002, "x-mac-chinesetrad", "", "MAC Traditional Chinese (Big5); Chinese Traditional (Mac)" },
+ { 10003, "x-mac-korean", "", "Korean (Mac)" },
+ { 10004, "x-mac-arabic", "MACARABIC", "Arabic (Mac)" },
+ { 10005, "x-mac-hebrew", "MACHEBREW", "Hebrew (Mac)" },
+ { 10006, "x-mac-greek", "MACGREEK", "Greek (Mac)" },
+ { 10007, "x-mac-cyrillic", "MACCYRILLIC", "Cyrillic (Mac)" },
+ { 10008, "x-mac-chinesesimp", "", "MAC Simplified Chinese (GB 2312); Chinese Simplified (Mac)" },
+ { 10010, "x-mac-romanian", "MACROMANIA", "Romanian (Mac)" },
+ { 10017, "x-mac-ukrainian", "MACUKRAINE", "Ukrainian (Mac)" },
+ { 10021, "x-mac-thai", "MACTHAI", "Thai (Mac)" },
+ { 10029, "x-mac-ce", "MACCENTRALEUROPE", "MAC Latin 2; Central European (Mac)" },
+ { 10079, "x-mac-icelandic", "MACICELAND", "Icelandic (Mac)" },
+ { 10081, "x-mac-turkish", "MACTURKISH", "Turkish (Mac)" },
+ { 10082, "x-mac-croatian", "MACCROATIAN", "Croatian (Mac)" },
+ { 12000, "utf-32", "", "Unicode UTF-32, little endian byte order; available only to managed applications" },
+ { 12001, "utf-32BE", "", "Unicode UTF-32, big endian byte order; available only to managed applications" },
+ { 20000, "x-Chinese_CNS", "", "CNS Taiwan; Chinese Traditional (CNS)" },
+ { 20001, "x-cp20001", "", "TCA Taiwan" },
+ { 20002, "x_Chinese-Eten", "", "Eten Taiwan; Chinese Traditional (Eten)" },
+ { 20003, "x-cp20003", "", "IBM5550 Taiwan" },
+ { 20004, "x-cp20004", "", "TeleText Taiwan" },
+ { 20005, "x-cp20005", "", "Wang Taiwan" },
+ { 20105, "x-IA5", "", "IA5 (IRV International Alphabet No. 5, 7-bit); Western European (IA5)" },
+ { 20106, "x-IA5-German", "", "IA5 German (7-bit)" },
+ { 20107, "x-IA5-Swedish", "", "IA5 Swedish (7-bit)" },
+ { 20108, "x-IA5-Norwegian", "", "IA5 Norwegian (7-bit)" },
+ { 20127, "us-ascii", "", "US-ASCII (7-bit)" },
+ { 20261, "x-cp20261", "", "T.61" },
+ { 20269, "x-cp20269", "", "ISO 6937 Non-Spacing Accent" },
+ { 20273, "IBM273", "", "IBM EBCDIC Germany" },
+ { 20277, "IBM277", "", "IBM EBCDIC Denmark-Norway" },
+ { 20278, "IBM278", "", "IBM EBCDIC Finland-Sweden" },
+ { 20280, "IBM280", "", "IBM EBCDIC Italy" },
+ { 20284, "IBM284", "", "IBM EBCDIC Latin America-Spain" },
+ { 20285, "IBM285", "", "IBM EBCDIC United Kingdom" },
+ { 20290, "IBM290", "", "IBM EBCDIC Japanese Katakana Extended" },
+ { 20297, "IBM297", "", "IBM EBCDIC France" },
+ { 20420, "IBM420", "", "IBM EBCDIC Arabic" },
+ { 20423, "IBM423", "", "IBM EBCDIC Greek" },
+ { 20424, "IBM424", "", "IBM EBCDIC Hebrew" },
+ { 20833, "x-EBCDIC-KoreanExtended", "", "IBM EBCDIC Korean Extended" },
+ { 20838, "IBM-Thai", "", "IBM EBCDIC Thai" },
+ { 20866, "koi8-r", "KOI8-R|CSKOI8R", "Russian (KOI8-R); Cyrillic (KOI8-R)" },
+ { 20871, "IBM871", "", "IBM EBCDIC Icelandic" },
+ { 20880, "IBM880", "", "IBM EBCDIC Cyrillic Russian" },
+ { 20905, "IBM905", "", "IBM EBCDIC Turkish" },
+ { 20924, "IBM00924", "", "IBM EBCDIC Latin 1/Open System (1047 + Euro symbol)" },
+ { 20932, "EUC-JP", "EUC-JP|EUCJP|EXTENDED_UNIX_CODE_PACKED_FORMAT_FOR_JAPANESE|CSEUCPKDFMTJAPANESE", "Japanese (JIS 0208-1990 and 0212-1990)" },
+ { 20936, "x-cp20936", "", "Simplified Chinese (GB2312); Chinese Simplified (GB2312-80)" },
+ { 20949, "x-cp20949", "", "Korean Wansung" },
+ { 21025, "cp1025", "", "IBM EBCDIC Cyrillic Serbian-Bulgarian" },
+ { 21027, "", "", "(deprecated)" },
+ { 21866, "koi8-u", "KOI8-U", "Ukrainian (KOI8-U); Cyrillic (KOI8-U)" },
+ { 28591, "iso-8859-1", "CP819|IBM819|ISO-8859-1|ISO-IR-100|ISO8859-1|ISO_8859-1|ISO_8859-1:1987|L1|LATIN1|CSISOLATIN1", "ISO 8859-1 Latin 1; Western European (ISO)" },
+ { 28592, "iso-8859-2", "ISO-8859-2|ISO-IR-101|ISO8859-2|ISO_8859-2|ISO_8859-2:1987|L2|LATIN2|CSISOLATIN2", "ISO 8859-2 Central European; Central European (ISO)" },
+ { 28593, "iso-8859-3", "ISO-8859-3|ISO-IR-109|ISO8859-3|ISO_8859-3|ISO_8859-3:1988|L3|LATIN3|CSISOLATIN3", "ISO 8859-3 Latin 3" },
+ { 28594, "iso-8859-4", "ISO-8859-4|ISO-IR-110|ISO8859-4|ISO_8859-4|ISO_8859-4:1988|L4|LATIN4|CSISOLATIN4", "ISO 8859-4 Baltic" },
+ { 28595, "iso-8859-5", "CYRILLIC|ISO-8859-5|ISO-IR-144|ISO8859-5|ISO_8859-5|ISO_8859-5:1988|CSISOLATINCYRILLIC", "ISO 8859-5 Cyrillic" },
+ { 28596, "iso-8859-6", "ARABIC|ASMO-708|ECMA-114|ISO-8859-6|ISO-IR-127|ISO8859-6|ISO_8859-6|ISO_8859-6:1987|CSISOLATINARABIC", "ISO 8859-6 Arabic" },
+ { 28597, "iso-8859-7", "ECMA-118|ELOT_928|GREEK|GREEK8|ISO-8859-7|ISO-IR-126|ISO8859-7|ISO_8859-7|ISO_8859-7:1987|ISO_8859-7:2003|CSISOLATINGREEK", "ISO 8859-7 Greek" },
+ { 28598, "iso-8859-8", "HEBREW|ISO-8859-8|ISO-IR-138|ISO8859-8|ISO_8859-8|ISO_8859-8:1988|CSISOLATINHEBREW", "ISO 8859-8 Hebrew; Hebrew (ISO-Visual)" },
+ { 28599, "iso-8859-9", "ISO-8859-9|ISO-IR-148|ISO8859-9|ISO_8859-9|ISO_8859-9:1989|L5|LATIN5|CSISOLATIN5", "ISO 8859-9 Turkish" },
+ { 28603, "iso-8859-13", "ISO-8859-13|ISO-IR-179|ISO8859-13|ISO_8859-13|L7|LATIN7", "ISO 8859-13 Estonian" },
+ { 28605, "iso-8859-15", "ISO-8859-15|ISO-IR-203|ISO8859-15|ISO_8859-15|ISO_8859-15:1998|LATIN-9", "ISO 8859-15 Latin 9" },
+ { 29001, "x-Europa", "", "Europa 3" },
+ { 38598, "iso-8859-8-i", "", "ISO 8859-8 Hebrew; Hebrew (ISO-Logical)" },
+ { 50220, "iso-2022-jp", "CP50220", "ISO 2022 Japanese with no halfwidth Katakana; Japanese (JIS)" },
+ { 50221, "csISO2022JP", "CP50221", "ISO 2022 Japanese with halfwidth Katakana; Japanese (JIS-Allow 1 byte Kana)" },
+ { 50222, "iso-2022-jp", "ISO-2022-JP|CP50222", "ISO 2022 Japanese JIS X 0201-1989; Japanese (JIS-Allow 1 byte Kana - SO/SI)" },
+ { 50225, "iso-2022-kr", "ISO-2022-KR|CSISO2022KR", "ISO 2022 Korean" },
+ { 50227, "x-cp50227", "", "ISO 2022 Simplified Chinese; Chinese Simplified (ISO 2022)" },
+ { 50229, "", "", "ISO 2022 Traditional Chinese" },
+ { 50930, "", "", "EBCDIC Japanese (Katakana) Extended" },
+ { 50931, "", "", "EBCDIC US-Canada and Japanese" },
+ { 50933, "", "", "EBCDIC Korean Extended and Korean" },
+ { 50935, "", "", "EBCDIC Simplified Chinese Extended and Simplified Chinese" },
+ { 50936, "", "", "EBCDIC Simplified Chinese" },
+ { 50937, "", "", "EBCDIC US-Canada and Traditional Chinese" },
+ { 50939, "", "", "EBCDIC Japanese (Latin) Extended and Japanese" },
+ { 51932, "euc-jp", "", "EUC Japanese" },
+ { 51936, "EUC-CN", "", "EUC Simplified Chinese; Chinese Simplified (EUC)" },
+ { 51949, "euc-kr", "EUC-KR|EUCKR|CSEUCKR", "EUC Korean" },
+ { 51950, "", "", "EUC Traditional Chinese" },
+ { 52936, "hz-gb-2312", "HZ|HZ-GB-2312", "HZ-GB2312 Simplified Chinese; Chinese Simplified (HZ)" },
+ { 54936, "GB18030", "GB18030|CSGB18030", "Windows XP and later: GB18030 Simplified Chinese (4 byte); Chinese Simplified (GB18030)" },
+ { 57002, "x-iscii-de", "", "ISCII Devanagari" },
+ { 57003, "x-iscii-be", "", "ISCII Bangla" },
+ { 57004, "x-iscii-ta", "", "ISCII Tamil" },
+ { 57005, "x-iscii-te", "", "ISCII Telugu" },
+ { 57006, "x-iscii-as", "", "ISCII Assamese" },
+ { 57007, "x-iscii-or", "", "ISCII Odia" },
+ { 57008, "x-iscii-ka", "", "ISCII Kannada" },
+ { 57009, "x-iscii-ma", "", "ISCII Malayalam" },
+ { 57010, "x-iscii-gu", "", "ISCII Gujarati" },
+ { 57011, "x-iscii-pa", "", "ISCII Punjabi" },
+ { 65000, "utf-7", "UTF-7", "Unicode (UTF-7)" },
+ { 65001, "utf-8", "UTF-8", "Unicode (UTF-8)" },
+ { 0, NULL, NULL },
+};
+
+
+
+
+int
+main(int argc, char **argv)
+{
+ DWORD cp;
+ CPINFOEX info;
+ struct cp *cur;
+ int rnd = 0;
+
+ /*if (argc < 2) {
+ printf("Usage: cpinfoex cp_id\n");
+ return 0;
+ }
+
+ cp = atoi(argv[1]);*/
+#if 0
+/* Ref:
+ http://www.iana.org/assignments/character-sets/character-sets.xhtml
+ https://msdn.microsoft.com/en-us/goglobal/bb964653
+ http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/
+ */
+#endif
+ /*
+ struct php_win32_cp {
+ DWORD id;
+ DWORD to_w_fl;
+ DWORD from_w_fl;
+ DWORD char_size;
+ char *name;
+ char *enc;
+ char *desc;
+ };
+ */
+ /*printf("struct php_win32_cp {\n\tDWORD id;\n\tDWORD to_w_fl;\n\tDWORD from_w_fl;\n\tDWORD char_size;\n\tchar *name;\n\tchar *enc;\n\tchar *desc;\n};\n\n"); */
+ printf("/* Autogenerated file. Update cp_enc_map_gen.c and regen like \n"
+ " cp_enc_map_gen.exe > cp_enc_map.c \n*/\n\n");
+ printf("static const struct php_win32_cp php_win32_cp_map[] = {");
+
+ cur = &cp_map[0];
+
+#ifdef ORDER_IT
+ while (rnd <= 2 && ++rnd && (cur = &cp_map[0]))
+#endif
+ while (cur->desc != NULL) {
+ if (!IsValidCodePage(cur->id)) {
+#ifdef ORDER_IT
+ if (2 == rnd)
+#endif
+ printf("\t/* %u is invalid */\n", cur->id);
+ //printf("#if 0\n\t{ %u, 0, \"%s\", \"%s\" },\n#endif\n", cur->id, cur->name, cur->desc);
+ } else if (GetCPInfoEx(cur->id, 0, &info)) {
+ DWORD to_w_fl = 0, from_w_fl = 0;
+
+ if (65001U == cur->id || 54936U == cur->id) {
+ from_w_fl = WC_ERR_INVALID_CHARS;
+ to_w_fl = MB_ERR_INVALID_CHARS;
+ }
+
+ //printf("\t{ %u, %u, \"%s\", \"%s\" },\n", cur->id, info.MaxCharSize, cur->name, cur->desc);
+ if (!cur->enc[0]) {
+#ifdef ORDER_IT
+ if (2 == rnd)
+#endif
+ //printf("\t/* { %u, %u, \"%s\", NULL, \"%s\" }, */\n", info.CodePage, info.MaxCharSize, cur->name, info.CodePageName);
+ printf("\t{ %u, %u, %u, %u, \"%s\", NULL, \"%s\" },\n", info.CodePage, to_w_fl, from_w_fl, info.MaxCharSize, cur->name, info.CodePageName);
+ } else {
+#ifdef ORDER_IT
+ if (1 == rnd)
+#endif
+ printf("\t{ %u, %u, %u, %u, \"%s\", \"%s\", \"%s\" },\n", info.CodePage, to_w_fl, from_w_fl, info.MaxCharSize, cur->name, cur->enc, info.CodePageName);
+ }
+ }
+ cur++;
+ }
+
+ printf("};\n\n");
+
+ return 0;
+}
+
diff --git a/win32/dllmain.c b/win32/dllmain.c
index a398b2201d..37408f1e76 100644
--- a/win32/dllmain.c
+++ b/win32/dllmain.c
@@ -19,6 +19,7 @@
#include <config.w32.h>
#include <win32/time.h>
+#include <win32/ioutil.h>
#include <php.h>
#ifdef HAVE_LIBXML
@@ -44,6 +45,12 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID dummy)
fprintf(stderr, "gettimeofday() initialization failed");
return ret;
}
+
+ ret = ret && php_win32_ioutil_init();
+ if (!ret) {
+ fprintf(stderr, "ioutil initialization failed");
+ return ret;
+ }
break;
#if 0 /* prepared */
case DLL_PROCESS_DETACH:
diff --git a/win32/ftok.c b/win32/ftok.c
new file mode 100644
index 0000000000..842da78192
--- /dev/null
+++ b/win32/ftok.c
@@ -0,0 +1,52 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2016 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Anatol Belski <ab@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#include "ipc.h"
+
+#include <windows.h>
+#include <sys/stat.h>
+
+
+PHPAPI key_t
+ftok(const char *pathname, int proj_id)
+{
+ HANDLE fh;
+ struct stat st;
+ BY_HANDLE_FILE_INFORMATION bhfi;
+ key_t ret;
+
+ if (stat(pathname, &st) < 0) {
+ return (key_t)-1;
+ }
+
+ if ((fh = CreateFile(pathname, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
+ return (key_t)-1;
+ }
+
+ if (!GetFileInformationByHandle(fh, &bhfi)) {
+ CloseHandle(fh);
+ return (key_t)-1;
+ }
+
+ ret = (key_t) ((proj_id & 0xff) << 24 | (st.st_dev & 0xff) << 16 | ((bhfi.nFileIndexLow | (__int64)bhfi.nFileIndexHigh << 32) & 0xffff));
+
+ CloseHandle(fh);
+
+ return ret;
+}
+
diff --git a/win32/ioutil.c b/win32/ioutil.c
new file mode 100644
index 0000000000..b661a150af
--- /dev/null
+++ b/win32/ioutil.c
@@ -0,0 +1,611 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2016 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Anatol Belski <ab@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* This file integrates several modified parts from the libuv project, which
+ * is copyrighted to
+ *
+ * Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <direct.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <io.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <sys/utime.h>
+#include <stdio.h>
+
+#include "php.h"
+#include "SAPI.h"
+#include "win32/winutil.h"
+#include "win32/time.h"
+#include "win32/ioutil.h"
+#include "win32/codepage.h"
+
+#include <pathcch.h>
+
+/*
+#undef NONLS
+#undef _WINNLS_
+#include <winnls.h>
+*/
+
+typedef HRESULT (__stdcall *MyPathCchCanonicalizeEx)(wchar_t *pszPathOut, size_t cchPathOut, const wchar_t *pszPathIn, unsigned long dwFlags);
+
+static MyPathCchCanonicalizeEx canonicalize_path_w = NULL;
+
+PW32IO BOOL php_win32_ioutil_posix_to_open_opts(int flags, mode_t mode, php_ioutil_open_opts *opts)
+{/*{{{*/
+ int current_umask;
+
+ opts->attributes = 0;
+
+ /* Obtain the active umask. umask() never fails and returns the previous */
+ /* umask. */
+ current_umask = umask(0);
+ umask(current_umask);
+
+ /* convert flags and mode to CreateFile parameters */
+ switch (flags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
+ case _O_RDONLY:
+ opts->access = FILE_GENERIC_READ;
+ /* XXX not opening dirs yet, see also at the bottom of this function. Should be evaluated properly. */
+ /*opts->attributes |= FILE_FLAG_BACKUP_SEMANTICS;*/
+ break;
+ case _O_WRONLY:
+ opts->access = FILE_GENERIC_WRITE;
+ break;
+ case _O_RDWR:
+ opts->access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
+ break;
+ default:
+ goto einval;
+ }
+
+ if (flags & _O_APPEND) {
+ /* XXX this might look wrong, but i just leave it here. Disabling FILE_WRITE_DATA prevents the current truncate behaviors for files opened with "a". */
+ /* access &= ~FILE_WRITE_DATA;*/
+ opts->access |= FILE_APPEND_DATA;
+ opts->attributes &= ~FILE_FLAG_BACKUP_SEMANTICS;
+ }
+
+ /*
+ * Here is where we deviate significantly from what CRT's _open()
+ * does. We indiscriminately use all the sharing modes, to match
+ * UNIX semantics. In particular, this ensures that the file can
+ * be deleted even whilst it's open.
+ */
+ /* opts->share = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; */
+ /* XXX No UINX behavior Good to know it's doable.
+ Not being done as this means a behavior change. Should be evaluated properly. */
+ opts->share = FILE_SHARE_READ | FILE_SHARE_WRITE;
+
+ switch (flags & (_O_CREAT | _O_EXCL | _O_TRUNC)) {
+ case 0:
+ case _O_EXCL:
+ opts->disposition = OPEN_EXISTING;
+ break;
+ case _O_CREAT:
+ opts->disposition = OPEN_ALWAYS;
+ break;
+ case _O_CREAT | _O_EXCL:
+ case _O_CREAT | _O_TRUNC | _O_EXCL:
+ opts->disposition = CREATE_NEW;
+ break;
+ case _O_TRUNC:
+ case _O_TRUNC | _O_EXCL:
+ opts->disposition = TRUNCATE_EXISTING;
+ break;
+ case _O_CREAT | _O_TRUNC:
+ opts->disposition = CREATE_ALWAYS;
+ break;
+ default:
+ goto einval;
+ }
+
+ opts->attributes |= FILE_ATTRIBUTE_NORMAL;
+ if (flags & _O_CREAT) {
+ if (!((mode & ~current_umask) & _S_IWRITE)) {
+ opts->attributes |= FILE_ATTRIBUTE_READONLY;
+ }
+ }
+
+ if (flags & _O_TEMPORARY ) {
+ opts->attributes |= FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY;
+ opts->access |= DELETE;
+ }
+
+ if (flags & _O_SHORT_LIVED) {
+ opts->attributes |= FILE_ATTRIBUTE_TEMPORARY;
+ }
+
+ switch (flags & (_O_SEQUENTIAL | _O_RANDOM)) {
+ case 0:
+ break;
+ case _O_SEQUENTIAL:
+ opts->attributes |= FILE_FLAG_SEQUENTIAL_SCAN;
+ break;
+ case _O_RANDOM:
+ opts->attributes |= FILE_FLAG_RANDOM_ACCESS;
+ break;
+ default:
+ goto einval;
+ }
+
+ /* Very compat options */
+ /*if (flags & O_ASYNC) {
+ opts->attributes |= FILE_FLAG_OVERLAPPED;
+ } else if (flags & O_SYNC) {
+ opts->attributes &= ~FILE_FLAG_OVERLAPPED;
+ }*/
+
+ /* Setting this flag makes it possible to open a directory. */
+ /* XXX not being done as this means a behavior change. Should be evaluated properly. */
+ /* opts->attributes |= FILE_FLAG_BACKUP_SEMANTICS; */
+
+ return 1;
+
+einval:
+ _set_errno(EINVAL);
+ return 0;
+}/*}}}*/
+
+PW32IO int php_win32_ioutil_open_w(const wchar_t *path, int flags, ...)
+{/*{{{*/
+ php_ioutil_open_opts open_opts;
+ HANDLE file;
+ int fd;
+ mode_t mode = 0;
+
+ PHP_WIN32_IOUTIL_CHECK_PATH_W(path, -1)
+
+ if (flags & O_CREAT) {
+ va_list arg;
+
+ va_start(arg, flags);
+ mode = (mode_t) va_arg(arg, int);
+ va_end(arg);
+ }
+
+ if (!php_win32_ioutil_posix_to_open_opts(flags, mode, &open_opts)) {
+ goto einval;
+ }
+
+ /* XXX care about security attributes here if needed, see tsrm_win32_access() */
+ file = CreateFileW(path,
+ open_opts.access,
+ open_opts.share,
+ NULL,
+ open_opts.disposition,
+ open_opts.attributes,
+ NULL);
+
+ if (file == INVALID_HANDLE_VALUE) {
+ DWORD error = GetLastError();
+
+ if (error == ERROR_FILE_EXISTS && (flags & _O_CREAT) &&
+ !(flags & _O_EXCL)) {
+ /* Special case: when ERROR_FILE_EXISTS happens and O_CREAT was */
+ /* specified, it means the path referred to a directory. */
+ _set_errno(EISDIR);
+ } else {
+ SET_ERRNO_FROM_WIN32_CODE(error);
+ }
+ return -1;
+ }
+
+ fd = _open_osfhandle((intptr_t) file, flags);
+ if (fd < 0) {
+ DWORD error = GetLastError();
+
+ /* The only known failure mode for _open_osfhandle() is EMFILE, in which
+ * case GetLastError() will return zero. However we'll try to handle other
+ * errors as well, should they ever occur.
+ */
+ if (errno == EMFILE) {
+ _set_errno(EMFILE);
+ } else if (error != ERROR_SUCCESS) {
+ SET_ERRNO_FROM_WIN32_CODE(error);
+ }
+ CloseHandle(file);
+ return -1;
+ }
+
+ if (flags & _O_TEXT) {
+ _setmode(fd, _O_TEXT);
+ } else if (flags & _O_BINARY) {
+ _setmode(fd, _O_BINARY);
+ }
+
+ return fd;
+
+ einval:
+ _set_errno(EINVAL);
+ return -1;
+}/*}}}*/
+
+PW32IO int php_win32_ioutil_close(int fd)
+{/*{{{*/
+ int result = -1;
+
+ if (-1 == fd) {
+ _set_errno(EBADF);
+ return result;
+ }
+
+ if (fd > 2) {
+ result = _close(fd);
+ } else {
+ result = 0;
+ }
+
+ /* _close doesn't set _doserrno on failure, but it does always set errno
+ * to EBADF on failure.
+ */
+ if (result == -1) {
+ _set_errno(EBADF);
+ }
+
+ return result;
+}/*}}}*/
+
+#if 0
+PW32IO int php_win32_ioutil_mkdir_w(const wchar_t *path, mode_t mode)
+{/*{{{*/
+ int ret = 0;
+ DWORD err = 0;
+
+ PHP_WIN32_IOUTIL_CHECK_PATH_W(path, -1)
+
+ /* TODO extend with mode usage */
+ if (!CreateDirectoryW(path, NULL)) {
+ err = GetLastError();
+ ret = -1;
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ }
+
+ return ret;
+}/*}}}*/
+#endif
+
+PW32IO int php_win32_ioutil_mkdir(const char *path, mode_t mode)
+{/*{{{*/
+ wchar_t *pathw = php_win32_ioutil_any_to_w(path);
+ int ret = 0;
+ DWORD err = 0;
+
+ /* TODO extend with mode usage */
+ if (!pathw) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return -1;
+ }
+
+ PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, -1)
+
+ if (!CreateDirectoryW(pathw, NULL)) {
+ err = GetLastError();
+ ret = -1;
+ }
+ free(pathw);
+
+ if (0 > ret) {
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ }
+
+ return ret;
+}/*}}}*/
+
+PW32IO int php_win32_ioutil_unlink_w(const wchar_t *path)
+{/*{{{*/
+ int ret = 0;
+ DWORD err = 0;
+
+ PHP_WIN32_IOUTIL_CHECK_PATH_W(path, -1)
+
+ if (!DeleteFileW(path)) {
+ err = GetLastError();
+ ret = -1;
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ }
+
+ return ret;
+}/*}}}*/
+
+PW32IO int php_win32_ioutil_rmdir_w(const wchar_t *path)
+{/*{{{*/
+ int ret = 0;
+ DWORD err = 0;
+
+ PHP_WIN32_IOUTIL_CHECK_PATH_W(path, -1)
+
+ if (!RemoveDirectoryW(path)) {
+ err = GetLastError();
+ ret = -1;
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ }
+
+ return ret;
+}/*}}}*/
+
+PW32IO int php_win32_ioutil_chdir_w(const wchar_t *path)
+{/*{{{*/
+ int ret = 0;
+ DWORD err = 0;
+
+ if (!SetCurrentDirectoryW(path)) {
+ err = GetLastError();
+ ret = -1;
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ }
+
+ return ret;
+}/*}}}*/
+
+PW32IO int php_win32_ioutil_rename_w(const wchar_t *oldname, const wchar_t *newname)
+{/*{{{*/
+ int ret = 0;
+ DWORD err = 0;
+
+ PHP_WIN32_IOUTIL_CHECK_PATH_W(oldname, -1)
+ PHP_WIN32_IOUTIL_CHECK_PATH_W(newname, -1)
+
+
+ if (!MoveFileExW(oldname, newname, MOVEFILE_REPLACE_EXISTING|MOVEFILE_COPY_ALLOWED)) {
+ err = GetLastError();
+ ret = -1;
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ }
+
+ return ret;
+}/*}}}*/
+
+PW32IO wchar_t *php_win32_ioutil_getcwd_w(const wchar_t *buf, int len)
+{/*{{{*/
+ DWORD err = 0;
+ wchar_t *tmp_buf = NULL;
+
+ /* If buf was NULL, the result has to be freed outside here. */
+ if (!buf) {
+ DWORD tmp_len = GetCurrentDirectoryW(0, NULL) + 1;
+ if (!tmp_len) {
+ err = GetLastError();
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ return NULL;
+ } else if (tmp_len > len) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INSUFFICIENT_BUFFER);
+ return NULL;
+ }
+
+ len = tmp_len;
+
+ tmp_buf = (wchar_t *)malloc((len)*sizeof(wchar_t));
+ if (!tmp_buf) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_NOT_ENOUGH_MEMORY);
+ return NULL;
+ }
+ buf = tmp_buf;
+ }
+
+ if (!GetCurrentDirectoryW(len, buf)) {
+ err = GetLastError();
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ return NULL;
+ }
+
+ return (wchar_t *)buf;
+}/*}}}*/
+
+/* based on zend_dirname(). */
+PW32IO size_t php_win32_ioutil_dirname(char *path, size_t len)
+{/*{{{*/
+ char *ret = NULL, *start;
+ size_t ret_len, len_adjust = 0, pathw_len;
+ wchar_t *endw, *pathw, *startw;
+
+ if (len == 0) {
+ return 0;
+ }
+
+ start = path;
+
+ startw = pathw = php_win32_ioutil_conv_any_to_w(path, len, &pathw_len);
+ if (!pathw) {
+ return 0;
+ }
+
+ endw = pathw + pathw_len - 1;
+
+ if ((2 <= len) && isalpha((int)((unsigned char *)path)[0]) && (':' == path[1])) {
+ pathw += 2;
+ path += 2;
+ len_adjust += 2;
+ if (2 == len) {
+ free(startw);
+ return len;
+ }
+ }
+
+ /* Strip trailing slashes */
+ while (endw >= pathw && PHP_WIN32_IOUTIL_IS_SLASHW(*endw)) {
+ endw--;
+ }
+ if (endw < pathw) {
+ /* The path only contained slashes */
+ path[0] = PHP_WIN32_IOUTIL_DEFAULT_SLASH;
+ path[1] = '\0';
+ return 1 + len_adjust;
+ }
+
+ /* Strip filename */
+ while (endw >= pathw && !PHP_WIN32_IOUTIL_IS_SLASHW(*endw)) {
+ endw--;
+ }
+ if (endw < pathw) {
+ path[0] = '.';
+ path[1] = '\0';
+ return 1 + len_adjust;
+ }
+
+ /* Strip slashes which came before the file name */
+ while (endw >= pathw && PHP_WIN32_IOUTIL_IS_SLASHW(*endw)) {
+ endw--;
+ }
+ if (endw < pathw) {
+ path[0] = PHP_WIN32_IOUTIL_DEFAULT_SLASH;
+ path[1] = '\0';
+ return 1 + len_adjust;
+ }
+ *(endw+1) = L'\0';
+
+ ret_len = (endw + 1 - startw);
+ if (PHP_WIN32_IOUTIL_IS_LONG_PATHW(startw, ret_len)) {
+ ret = php_win32_ioutil_conv_w_to_any(startw + PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW, ret_len - PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW, &ret_len);
+ } else {
+ ret = php_win32_ioutil_conv_w_to_any(startw, ret_len, &ret_len);
+ }
+ memmove(start, ret, ret_len+1);
+ assert(start[ret_len] == '\0');
+ free(ret);
+ free(startw);
+
+ return ret_len;
+}/*}}}*/
+
+PW32IO php_win32_ioutil_normalization_result php_win32_ioutil_normalize_path_w(wchar_t **buf, size_t len, size_t *new_len)
+{/*{{{*/
+ wchar_t *pos, *idx = *buf, canonicalw[MAXPATHLEN];
+ size_t ret_len = len;
+
+ if (len >= MAXPATHLEN) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_BAD_LENGTH);
+ return PHP_WIN32_IOUTIL_NORM_FAIL;
+ }
+
+ while (NULL != (pos = wcschr(idx, PHP_WIN32_IOUTIL_FW_SLASHW)) && idx - *buf <= len) {
+ *pos = PHP_WIN32_IOUTIL_DEFAULT_SLASHW;
+ idx = pos++;
+ }
+
+ if (S_OK != canonicalize_path_w(canonicalw, MAXPATHLEN, *buf, PATHCCH_ALLOW_LONG_PATHS)) {
+ return PHP_WIN32_IOUTIL_NORM_PARTIAL;
+ }
+ ret_len = wcslen(canonicalw);
+ if (ret_len != len) {
+ if (ret_len > len) {
+ wchar_t *tmp = realloc(*buf, (ret_len + 1) * sizeof(wchar_t));
+ if (!tmp) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_NOT_ENOUGH_MEMORY);
+ return PHP_WIN32_IOUTIL_NORM_PARTIAL;
+ }
+ *buf = tmp;
+ }
+ memmove(*buf, canonicalw, (ret_len + 1) * sizeof(wchar_t));
+ }
+ *new_len = ret_len;
+
+ return PHP_WIN32_IOUTIL_NORM_OK;
+}/*}}}*/
+
+static HRESULT __stdcall MyPathCchCanonicalizeExFallback(wchar_t *pszPathOut, size_t cchPathOut, const wchar_t *pszPathIn, unsigned long dwFlags)
+{/*{{{*/
+ return -42;
+}/*}}}*/
+
+BOOL php_win32_ioutil_init(void)
+{/*{{{*/
+ HMODULE hMod = GetModuleHandle("api-ms-win-core-path-l1-1-0");
+
+ if (hMod) {
+ canonicalize_path_w = (MyPathCchCanonicalizeEx)GetProcAddress(hMod, "PathCchCanonicalizeEx");
+ if (!canonicalize_path_w) {
+ canonicalize_path_w = (MyPathCchCanonicalizeEx)MyPathCchCanonicalizeExFallback;
+ }
+ } else {
+ canonicalize_path_w = (MyPathCchCanonicalizeEx)MyPathCchCanonicalizeExFallback;
+ }
+
+ return TRUE;
+}/*}}}*/
+
+/* an extended version could be implemented, for now direct functions can be used. */
+#if 0
+PW32IO int php_win32_ioutil_access_w(const wchar_t *path, mode_t mode)
+{
+ return _waccess(path, mode);
+}
+#endif
+
+#if 0
+PW32IO HANDLE php_win32_ioutil_findfirstfile_w(char *path, WIN32_FIND_DATA *data)
+{
+ HANDLE ret = INVALID_HANDLE_VALUE;
+ DWORD err;
+
+ if (!path) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return ret;
+ }
+
+ pathw = php_win32_ioutil_any_to_w(path);
+
+ if (!pathw) {
+ err = GetLastError();
+ SET_ERRNO_FROM_WIN32_CODE(ret);
+ return ret;
+ }
+
+ ret = FindFirstFileW(pathw, data);
+
+ if (INVALID_HANDLE_VALUE == ret && path) {
+ ret = FindFirstFileA(path, data);
+ }
+
+ /* XXX set errno */
+ return ret;
+}
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/win32/ioutil.h b/win32/ioutil.h
new file mode 100644
index 0000000000..ea40db4c66
--- /dev/null
+++ b/win32/ioutil.h
@@ -0,0 +1,501 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2016 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Anatol Belski <ab@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* This file integrates several modified parts from the libuv project, which
+ * is copyrighted to
+ *
+ * Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef PHP_WIN32_IOUTIL_H
+#define PHP_WIN32_IOUTIL_H
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <io.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "win32/winutil.h"
+#include "win32/codepage.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef PHP_EXPORTS
+# define PW32IO __declspec(dllexport)
+#else
+# define PW32IO __declspec(dllimport)
+#endif
+
+#define PHP_WIN32_IOUTIL_MAXPATHLEN 2048
+
+#if !defined(MAXPATHLEN) || MAXPATHLEN < PHP_WIN32_IOUTIL_MAXPATHLEN
+# undef MAXPATHLEN
+# define MAXPATHLEN PHP_WIN32_IOUTIL_MAXPATHLEN
+#endif
+
+#ifndef mode_t
+typedef unsigned short mode_t;
+#endif
+
+typedef struct {
+ DWORD access;
+ DWORD share;
+ DWORD disposition;
+ DWORD attributes;
+} php_ioutil_open_opts;
+
+typedef enum {
+ PHP_WIN32_IOUTIL_IS_ASCII,
+ PHP_WIN32_IOUTIL_IS_ANSI,
+ PHP_WIN32_IOUTIL_IS_UTF8
+} php_win32_ioutil_encoding;
+
+typedef enum {
+ PHP_WIN32_IOUTIL_NORM_OK,
+ PHP_WIN32_IOUTIL_NORM_PARTIAL,
+ PHP_WIN32_IOUTIL_NORM_FAIL,
+} php_win32_ioutil_normalization_result;
+
+#define PHP_WIN32_IOUTIL_FW_SLASHW L'/'
+#define PHP_WIN32_IOUTIL_FW_SLASH '/'
+#define PHP_WIN32_IOUTIL_BW_SLASHW L'\\'
+#define PHP_WIN32_IOUTIL_BW_SLASH '\\'
+#define PHP_WIN32_IOUTIL_DEFAULT_SLASHW PHP_WIN32_IOUTIL_BW_SLASHW
+#define PHP_WIN32_IOUTIL_DEFAULT_SLASH PHP_WIN32_IOUTIL_BW_SLASH
+
+#define PHP_WIN32_IOUTIL_DEFAULT_DIR_SEPARATORW L';'
+#define PHP_WIN32_IOUTIL_IS_SLASHW(c) ((c) == PHP_WIN32_IOUTIL_BW_SLASHW || (c) == PHP_WIN32_IOUTIL_FW_SLASHW)
+#define PHP_WIN32_IOUTIL_IS_LETTERW(c) (((c) >= L'a' && (c) <= L'z') || ((c) >= L'A' && (c) <= L'Z'))
+#define PHP_WIN32_IOUTIL_JUNCTION_PREFIXW L"\\??\\"
+#define PHP_WIN32_IOUTIL_JUNCTION_PREFIX_LENW 4
+#define PHP_WIN32_IOUTIL_LONG_PATH_PREFIXW L"\\\\?\\"
+#define PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW 4
+#define PHP_WIN32_IOUTIL_UNC_PATH_PREFIXW L"\\\\?\\UNC\\"
+#define PHP_WIN32_IOUTIL_UNC_PATH_PREFIX_LENW 8
+
+#define PHP_WIN32_IOUTIL_IS_LONG_PATHW(pathw, path_lenw) (path_lenw >= PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW \
+ && 0 == wcsncmp((pathw), PHP_WIN32_IOUTIL_LONG_PATH_PREFIXW, PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW))
+#define PHP_WIN32_IOUTIL_IS_ABSOLUTEW(pathw, path_lenw) (PHP_WIN32_IOUTIL_IS_LONG_PATHW(pathw, path_lenw) \
+ || path_lenw >= 3 && PHP_WIN32_IOUTIL_IS_LETTERW(pathw[0]) && L':' == pathw[1] && IS_SLASHW(pathw[2]))
+
+#define PHP_WIN32_IOUTIL_INIT_W(path) \
+ wchar_t *pathw = php_win32_ioutil_any_to_w(path); \
+
+#define PHP_WIN32_IOUTIL_CLEANUP_W() do { \
+ free(pathw); \
+ pathw = NULL; \
+} while (0);
+
+#define PHP_WIN32_IOUTIL_REINIT_W(path) do { \
+ PHP_WIN32_IOUTIL_CLEANUP_W() \
+ pathw = php_win32_ioutil_any_to_w(path); \
+} while (0);
+
+#define PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, ret) do { \
+ size_t len = wcslen(pathw); \
+ if (len >= 1 && L' ' == pathw[len-1] || \
+ len > 1 && !PHP_WIN32_IOUTIL_IS_SLASHW(pathw[len-2]) && L'.' != pathw[len-2] && L'.' == pathw[len-1] \
+ ) { \
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_ACCESS_DENIED); \
+ return ret; \
+ } \
+} while (0);
+
+PW32IO php_win32_ioutil_normalization_result php_win32_ioutil_normalize_path_w(wchar_t **buf, size_t len, size_t *new_len);
+#ifdef PHP_EXPORTS
+/* This symbols are needed only for the DllMain, but should not be exported
+ or be available when used with PHP binaries. */
+BOOL php_win32_ioutil_init(void);
+#endif
+
+/* Keep these functions aliased for case some additional handling
+ is needed later. */
+__forceinline static wchar_t *php_win32_ioutil_conv_any_to_w(const char* in, size_t in_len, size_t *out_len)
+{/*{{{*/
+ wchar_t *mb, *ret;
+ size_t mb_len;
+
+ mb = php_win32_cp_conv_any_to_w(in, in_len, &mb_len);
+ if (!mb) {
+ return NULL;
+ }
+
+ /* Only prefix with long if it's needed. */
+ if (mb_len > _MAX_PATH) {
+ ret = (wchar_t *) malloc((mb_len + PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW + 1) * sizeof(wchar_t));
+ if (!ret) {
+ free(mb);
+ return NULL;
+ }
+
+ /* The return can be ignored here, as the normalization can fail for
+ various reasons not directly related to the operation itself.
+ Partial normalization could still do a better job further. And
+ otherwise, the path might be unchanged which is ok if the path
+ was valid long one. */
+ (void)php_win32_ioutil_normalize_path_w(&mb, mb_len, &mb_len);
+
+ if (PHP_WIN32_IOUTIL_IS_LONG_PATHW(mb, mb_len)) {
+ memmove(ret, mb, mb_len * sizeof(wchar_t));
+ ret[mb_len] = L'\0';
+ } else {
+ memmove(ret, PHP_WIN32_IOUTIL_LONG_PATH_PREFIXW, PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW * sizeof(wchar_t));
+ memmove(ret+PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW, mb, mb_len * sizeof(wchar_t));
+ ret[mb_len + PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW] = L'\0';
+
+ mb_len += PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW;
+ }
+
+ free(mb);
+ } else {
+ ret = mb;
+ }
+
+ if (PHP_WIN32_CP_IGNORE_LEN_P != out_len) {
+ *out_len = mb_len;
+ }
+
+ return ret;
+}/*}}}*/
+#define php_win32_ioutil_any_to_w(in) php_win32_ioutil_conv_any_to_w(in, PHP_WIN32_CP_IGNORE_LEN, PHP_WIN32_CP_IGNORE_LEN_P)
+
+#define php_win32_ioutil_ascii_to_w php_win32_cp_ascii_to_w
+#define php_win32_ioutil_utf8_to_w php_win32_cp_utf8_to_w
+#define php_win32_ioutil_cur_to_w php_win32_cp_cur_to_w
+#define php_win32_ioutil_w_to_any php_win32_cp_w_to_any
+#define php_win32_ioutil_conv_w_to_any php_win32_cp_conv_w_to_any
+/*__forceinline static char *php_win32_ioutil_w_to_any(wchar_t* w_source_ptr)
+{
+ return php_win32_cp_w_to_any(w_source_ptr);
+}*/
+#define php_win32_ioutil_w_to_utf8 php_win32_cp_w_to_utf8
+#define php_win32_ioutil_w_to_thread php_win32_cp_w_to_thread
+
+PW32IO int php_win32_ioutil_close(int fd);
+PW32IO BOOL php_win32_ioutil_posix_to_open_opts(int flags, mode_t mode, php_ioutil_open_opts *opts);
+PW32IO int php_win32_ioutil_mkdir(const char *path, mode_t mode);
+PW32IO size_t php_win32_ioutil_dirname(char *buf, size_t len);
+
+PW32IO int php_win32_ioutil_open_w(const wchar_t *path, int flags, ...);
+PW32IO int php_win32_ioutil_chdir_w(const wchar_t *path);
+PW32IO int php_win32_ioutil_rename_w(const wchar_t *oldname, const wchar_t *newname);
+PW32IO wchar_t *php_win32_ioutil_getcwd_w(const wchar_t *buf, int len);
+
+#if 0
+PW32IO int php_win32_ioutil_mkdir_w(const wchar_t *path, mode_t mode);
+PW32IO int php_win32_ioutil_access_w(const wchar_t *path, mode_t mode);
+#endif
+
+#define php_win32_ioutil_access_cond(path, mode) _waccess(pathw, mode)
+#define php_win32_ioutil_unlink_cond(path) php_win32_ioutil_unlink_w(pathw)
+#define php_win32_ioutil_rmdir_cond(path) php_win32_ioutil_rmdir_w(pathw)
+
+__forceinline static int php_win32_ioutil_access(const char *path, mode_t mode)
+{/*{{{*/
+ PHP_WIN32_IOUTIL_INIT_W(path)
+ int ret, err;
+
+ if (!pathw) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return -1;
+ }
+
+ PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, -1)
+
+ ret = _waccess(pathw, mode);
+ _get_errno(&err);
+ PHP_WIN32_IOUTIL_CLEANUP_W()
+
+ if (0 > ret) {
+ _set_errno(err);
+ }
+
+ return ret;
+}/*}}}*/
+
+__forceinline static int php_win32_ioutil_open(const char *path, int flags, ...)
+{/*{{{*/
+ mode_t mode = 0;
+ PHP_WIN32_IOUTIL_INIT_W(path)
+ int ret = -1;
+ DWORD err;
+
+ if (!pathw) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return -1;
+ }
+
+ PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, -1)
+
+ if (flags & O_CREAT) {
+ va_list arg;
+
+ va_start(arg, flags);
+ mode = (mode_t) va_arg(arg, int);
+ va_end(arg);
+ }
+
+ ret = php_win32_ioutil_open_w(pathw, flags, mode);
+ err = GetLastError();
+ PHP_WIN32_IOUTIL_CLEANUP_W()
+
+ if (0 > ret) {
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ }
+
+ return ret;
+}/*}}}*/
+
+__forceinline static int php_win32_ioutil_unlink(const char *path)
+{/*{{{*/
+ PHP_WIN32_IOUTIL_INIT_W(path)
+ int ret = 0;
+ DWORD err = 0;
+
+ if (!pathw) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return -1;
+ }
+
+ PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, -1)
+
+ if (!DeleteFileW(pathw)) {
+ err = GetLastError();
+ ret = -1;
+ }
+ PHP_WIN32_IOUTIL_CLEANUP_W()
+
+ if (0 > ret) {
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ }
+
+ return ret;
+}/*}}}*/
+
+__forceinline static int php_win32_ioutil_rmdir(const char *path)
+{/*{{{*/
+ PHP_WIN32_IOUTIL_INIT_W(path)
+ int ret = 0;
+ DWORD err = 0;
+
+ if (!pathw) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return -1;
+ }
+
+ PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, -1)
+
+ if (!RemoveDirectoryW(pathw)) {
+ err = GetLastError();
+ ret = -1;
+ }
+
+ PHP_WIN32_IOUTIL_CLEANUP_W()
+
+ if (0 > ret) {
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ }
+
+ return ret;
+}/*}}}*/
+
+/* This needs to be improved once long path support is implemented. Use ioutil_open() and then
+fdopen() might be the way, if we learn how to convert the mode options (maybe grab the routine
+ from the streams). That will allow to split for _a and _w. */
+__forceinline static FILE *php_win32_ioutil_fopen(const char *patha, const char *modea)
+{/*{{{*/
+ FILE *ret;
+ wchar_t *pathw = php_win32_ioutil_any_to_w(patha);
+ wchar_t *modew = php_win32_ioutil_ascii_to_w(modea);
+ int err = 0;
+
+ if (!pathw || !modew) {
+ free(pathw);
+ free(modew);
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, NULL)
+
+ ret = _wfopen(pathw, modew);
+ _get_errno(&err);
+ free(pathw);
+ free(modew);
+
+ if (0 > ret) {
+ _set_errno(err);
+ }
+ return ret;
+}/*}}}*/
+
+__forceinline static int php_win32_ioutil_rename(const char *oldnamea, const char *newnamea)
+{/*{{{*/
+ wchar_t *oldnamew = php_win32_ioutil_any_to_w(oldnamea);
+ wchar_t *newnamew = php_win32_ioutil_any_to_w(newnamea);
+ int ret;
+ DWORD err = 0;
+
+ if (!oldnamew || !newnamew) {
+ free(oldnamew);
+ free(newnamew);
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return -1;
+ }
+
+ PHP_WIN32_IOUTIL_CHECK_PATH_W(oldnamew, -1)
+ PHP_WIN32_IOUTIL_CHECK_PATH_W(newnamew, -1)
+
+ ret = php_win32_ioutil_rename_w(oldnamew, newnamew);
+ err = GetLastError();
+
+ free(oldnamew);
+ free(newnamew);
+
+ if (0 > ret) {
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ }
+
+ return ret;
+}/*}}}*/
+
+__forceinline static int php_win32_ioutil_chdir(const char *patha)
+{/*{{{*/
+ int ret;
+ wchar_t *pathw = php_win32_ioutil_any_to_w(patha);
+ DWORD err = 0;
+
+ if (!pathw) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return -1;
+ }
+
+ ret = php_win32_ioutil_chdir_w(pathw);
+ err = GetLastError();
+
+ free(pathw);
+
+ if (0 > ret) {
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ }
+
+ return ret;
+}/*}}}*/
+
+__forceinline static char *php_win32_ioutil_getcwd(char *buf, int len)
+{/*{{{*/
+ wchar_t tmp_bufw[PHP_WIN32_IOUTIL_MAXPATHLEN];
+ char *tmp_bufa = NULL;
+ size_t tmp_bufa_len;
+ DWORD err = 0;
+
+ if (php_win32_ioutil_getcwd_w(tmp_bufw, PHP_WIN32_IOUTIL_MAXPATHLEN) == NULL) {
+ err = GetLastError();
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ return NULL;
+ }
+
+ tmp_bufa = php_win32_cp_conv_w_to_any(tmp_bufw, wcslen(tmp_bufw), &tmp_bufa_len);
+ if (!tmp_bufa) {
+ err = GetLastError();
+ SET_ERRNO_FROM_WIN32_CODE(err);
+ return NULL;
+ } else if (tmp_bufa_len + 1 > PHP_WIN32_IOUTIL_MAXPATHLEN) {
+ free(tmp_bufa);
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_BAD_LENGTH);
+ return NULL;
+ }
+
+ if (!buf) {
+ /* If buf was NULL, the result has to be freed outside here. */
+ buf = tmp_bufa;
+ } else {
+ if (tmp_bufa_len + 1 > len) {
+ free(tmp_bufa);
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INSUFFICIENT_BUFFER);
+ return NULL;
+ }
+ memmove(buf, tmp_bufa, tmp_bufa_len + 1);
+ free(tmp_bufa);
+ }
+
+ return buf;
+}/*}}}*/
+
+/* TODO improve with usage of native APIs, split for _a and _w. */
+__forceinline static int php_win32_ioutil_chmod(const char *patha, int mode)
+{/*{{{*/
+ wchar_t *pathw = php_win32_ioutil_any_to_w(patha);
+ int err = 0;
+ int ret;
+
+ if (!pathw) {
+ SET_ERRNO_FROM_WIN32_CODE(ERROR_INVALID_PARAMETER);
+ return -1;
+ }
+
+ PHP_WIN32_IOUTIL_CHECK_PATH_W(pathw, -1)
+
+ ret = _wchmod(pathw, mode);
+ _get_errno(&err);
+
+ free(pathw);
+
+ if (0 > ret) {
+ _set_errno(err);
+ }
+
+ return ret;
+}/*}}}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PHP_WIN32_IOUTIL_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/win32/ipc.h b/win32/ipc.h
new file mode 100644
index 0000000000..cafcf4f85e
--- /dev/null
+++ b/win32/ipc.h
@@ -0,0 +1,29 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2016 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Anatol Belski <ab@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef PHP_WIN32_IPC_H
+#define PHP_WIN32_IPC_H 1
+
+#include "php.h"
+
+typedef int key_t;
+
+PHPAPI key_t ftok(const char *path, int id);
+
+
+#endif /* PHP_WIN32_IPC_H */
diff --git a/win32/param.h b/win32/param.h
index 3d0da1e8d3..f312b03b18 100644
--- a/win32/param.h
+++ b/win32/param.h
@@ -9,7 +9,8 @@
* *
*****************************************************************************/
#ifndef MAXPATHLEN
-#define MAXPATHLEN _MAX_PATH
+#include "win32/ioutil.h"
+#define MAXPATHLEN PHP_WIN32_IOUTIL_MAXPATHLEN
#endif
#define MAXHOSTNAMELEN 64
#define howmany(x,y) (((x)+((y)-1))/(y))
diff --git a/win32/readdir.c b/win32/readdir.c
index fc2c4357ff..35afea429b 100644
--- a/win32/readdir.c
+++ b/win32/readdir.c
@@ -4,7 +4,8 @@
#include "php.h"
#include "readdir.h"
-#include "TSRM.h"
+#include "win32/ioutil.h"
+
/**********************************************************************
* Implement dirent-style opendir/readdir/rewinddir/closedir on Win32
*
@@ -19,70 +20,104 @@
* The DIR typedef is not compatible with Unix.
**********************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* typedef DIR - not the same as Unix */
+struct DIR_W32 {
+ HANDLE handle; /* _findfirst/_findnext handle */
+ int offset; /* offset into directory */
+ short finished; /* 1 if there are not more files */
+ WIN32_FIND_DATAW fileinfo; /* from _findfirst/_findnext */
+ wchar_t *dirw; /* the dir we are reading */
+ struct dirent dent; /* the dirent to return */
+};
+
DIR *opendir(const char *dir)
{
DIR *dp;
- char *filespec;
+ wchar_t *filespecw, *resolvedw;
HANDLE handle;
int index;
char resolved_path_buff[MAXPATHLEN];
+ size_t resolvedw_len, filespecw_len;
if (!VCWD_REALPATH(dir, resolved_path_buff)) {
return NULL;
}
- filespec = (char *)malloc(strlen(resolved_path_buff) + 2 + 1);
- if (filespec == NULL) {
+ dp = (DIR *) malloc(sizeof(DIR));
+ if (dp == NULL) {
return NULL;
}
- strcpy(filespec, resolved_path_buff);
- index = (int)strlen(filespec) - 1;
- if (index >= 0 && (filespec[index] == '/' ||
- (filespec[index] == '\\' && (index == 0 || !IsDBCSLeadByte(filespec[index-1])))))
- filespec[index] = '\0';
- strcat(filespec, "\\*");
- dp = (DIR *) malloc(sizeof(DIR));
- if (dp == NULL) {
- free(filespec);
+ resolvedw = php_win32_ioutil_conv_any_to_w(resolved_path_buff, PHP_WIN32_CP_IGNORE_LEN, &resolvedw_len);
+ if (!resolvedw) {
+ return NULL;
+ }
+
+ filespecw_len = resolvedw_len + 2;
+ filespecw = (wchar_t *)malloc((filespecw_len + 1)*sizeof(wchar_t));
+ if (filespecw == NULL) {
+ free(resolvedw);
return NULL;
}
- dp->offset = 0;
- dp->finished = 0;
- if ((handle = FindFirstFile(filespec, &(dp->fileinfo))) == INVALID_HANDLE_VALUE) {
+ wcscpy(filespecw, resolvedw);
+ index = (int)filespecw_len - 1;
+ if (index >= 0 && filespecw[index] == L'/' || index == 0 && filespecw[index] == L'\\')
+ filespecw[index] = L'\0';
+ wcscat(filespecw, L"\\*");
+
+ if ((handle = FindFirstFileW(filespecw, &(dp->fileinfo))) == INVALID_HANDLE_VALUE) {
DWORD err = GetLastError();
if (err == ERROR_NO_MORE_FILES || err == ERROR_FILE_NOT_FOUND) {
dp->finished = 1;
} else {
free(dp);
- free(filespec);
+ free(filespecw);
+ free(resolvedw);
return NULL;
}
}
- dp->dir = strdup(resolved_path_buff);
+ dp->dirw = _wcsdup(resolvedw);
dp->handle = handle;
- free(filespec);
+ dp->offset = 0;
+ dp->finished = 0;
+
+ free(filespecw);
+ free(resolvedw);
return dp;
}
struct dirent *readdir(DIR *dp)
{
+ char *_tmp;
+
if (!dp || dp->finished)
return NULL;
if (dp->offset != 0) {
- if (FindNextFile(dp->handle, &(dp->fileinfo)) == 0) {
+ if (FindNextFileW(dp->handle, &(dp->fileinfo)) == 0) {
dp->finished = 1;
return NULL;
}
}
+
+ _tmp = php_win32_ioutil_w_to_any(dp->fileinfo.cFileName);
+ if (!_tmp) {
+ /* wide to utf8 failed, should never happen. */
+ return NULL;
+ }
+ strlcpy(dp->dent.d_name, _tmp, _MAX_FNAME+1);
+ dp->dent.d_reclen = (unsigned short)strlen(dp->dent.d_name);
+ free(_tmp);
+
dp->offset++;
- strlcpy(dp->dent.d_name, dp->fileinfo.cFileName, _MAX_FNAME+1);
dp->dent.d_ino = 1;
- dp->dent.d_reclen = (unsigned short)strlen(dp->dent.d_name);
dp->dent.d_off = dp->offset;
return &(dp->dent);
@@ -90,23 +125,34 @@ struct dirent *readdir(DIR *dp)
int readdir_r(DIR *dp, struct dirent *entry, struct dirent **result)
{
+ char *_tmp;
+
if (!dp || dp->finished) {
*result = NULL;
return 0;
}
if (dp->offset != 0) {
- if (FindNextFile(dp->handle, &(dp->fileinfo)) == 0) {
+ if (FindNextFileW(dp->handle, &(dp->fileinfo)) == 0) {
dp->finished = 1;
*result = NULL;
return 0;
}
}
+
+ _tmp = php_win32_ioutil_w_to_any(dp->fileinfo.cFileName);
+ if (!_tmp) {
+ /* wide to utf8 failed, should never happen. */
+ result = NULL;
+ return 0;
+ }
+ strlcpy(dp->dent.d_name, _tmp, _MAX_FNAME+1);
+ dp->dent.d_reclen = (unsigned short)strlen(dp->dent.d_name);
+ free(_tmp);
+
dp->offset++;
- strlcpy(dp->dent.d_name, dp->fileinfo.cFileName, _MAX_FNAME+1);
dp->dent.d_ino = 1;
- dp->dent.d_reclen = (unsigned short)strlen(dp->dent.d_name);
dp->dent.d_off = dp->offset;
memcpy(entry, &dp->dent, sizeof(*entry));
@@ -125,8 +171,8 @@ int closedir(DIR *dp)
if (dp->handle != INVALID_HANDLE_VALUE) {
FindClose(dp->handle);
}
- if (dp->dir)
- free(dp->dir);
+ if (dp->dirw)
+ free(dp->dirw);
if (dp)
free(dp);
@@ -136,7 +182,7 @@ int closedir(DIR *dp)
int rewinddir(DIR *dp)
{
/* Re-set to the beginning */
- char *filespec;
+ wchar_t *filespecw;
HANDLE handle;
int index;
@@ -145,28 +191,32 @@ int rewinddir(DIR *dp)
dp->offset = 0;
dp->finished = 0;
- filespec = (char *)malloc(strlen(dp->dir) + 2 + 1);
- if (filespec == NULL) {
+ filespecw = (wchar_t *)malloc((wcslen((wchar_t *)dp->dirw) + 2 + 1)*sizeof(wchar_t));
+ if (filespecw == NULL) {
return -1;
}
- strcpy(filespec, dp->dir);
- index = (int)strlen(filespec) - 1;
- if (index >= 0 && (filespec[index] == '/' ||
- (filespec[index] == '\\' && (index == 0 || !IsDBCSLeadByte(filespec[index-1])))))
- filespec[index] = '\0';
- strcat(filespec, "/*");
+ wcscpy(filespecw, (wchar_t *)dp->dirw);
+ index = (int)wcslen(filespecw) - 1;
+ if (index >= 0 && (filespecw[index] == L'/' ||
+ (filespecw[index] == L'\\' && index == 0)))
+ filespecw[index] = L'\0';
+ wcscat(filespecw, L"/*");
- if ((handle = FindFirstFile(filespec, &(dp->fileinfo))) == INVALID_HANDLE_VALUE) {
+ if ((handle = FindFirstFileW(filespecw, &(dp->fileinfo))) == INVALID_HANDLE_VALUE) {
dp->finished = 1;
}
+ free(filespecw);
dp->handle = handle;
- free(filespec);
return 0;
}
+#ifdef __cplusplus
+}
+#endif
+
/*
* Local variables:
* tab-width: 4
diff --git a/win32/readdir.h b/win32/readdir.h
index d9ae477af0..4158ffc84a 100644
--- a/win32/readdir.h
+++ b/win32/readdir.h
@@ -2,6 +2,10 @@
#define READDIR_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/*
* Structures and types used to implement opendir/readdir/closedir
* on Windows 95/NT.
@@ -9,18 +13,12 @@
#include <config.w32.h>
-#include <windows.h>
-
-#include <io.h>
-#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
-#include <direct.h>
#define php_readdir_r readdir_r
/* struct dirent - same as Unix */
-
struct dirent {
long d_ino; /* inode (always 1 in WIN32) */
off_t d_off; /* offset to this dirent */
@@ -28,16 +26,8 @@ struct dirent {
char d_name[_MAX_FNAME + 1]; /* filename (null terminated) */
};
-
/* typedef DIR - not the same as Unix */
-typedef struct {
- HANDLE handle; /* _findfirst/_findnext handle */
- int offset; /* offset into directory */
- short finished; /* 1 if there are not more files */
- WIN32_FIND_DATA fileinfo; /* from _findfirst/_findnext */
- char *dir; /* the dir we are reading */
- struct dirent dent; /* the dirent to return */
-} DIR;
+typedef struct DIR_W32 DIR;
/* Function prototypes */
DIR *opendir(const char *);
@@ -46,4 +36,8 @@ int readdir_r(DIR *, struct dirent *, struct dirent **);
int closedir(DIR *);
int rewinddir(DIR *);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* READDIR_H */
diff --git a/win32/winutil.c b/win32/winutil.c
index e59e049775..cd009cadc0 100644
--- a/win32/winutil.c
+++ b/win32/winutil.c
@@ -20,9 +20,11 @@
/* $Id$ */
#include "php.h"
+#include "winutil.h"
#include <wincrypt.h>
+#include <lmcons.h>
-PHPAPI char *php_win32_error_to_msg(HRESULT error)
+PHP_WINUTIL_API char *php_win32_error_to_msg(HRESULT error)
{
char *buf = NULL;
@@ -77,7 +79,7 @@ void php_win32_free_rng_lock()
-PHPAPI int php_win32_get_random_bytes(unsigned char *buf, size_t size) { /* {{{ */
+PHP_WINUTIL_API int php_win32_get_random_bytes(unsigned char *buf, size_t size) { /* {{{ */
BOOL ret;
@@ -123,6 +125,319 @@ PHPAPI int php_win32_get_random_bytes(unsigned char *buf, size_t size) { /* {{{
}
/* }}} */
+
+/*
+* This functions based on the code from the UNIXem project under
+* the BSD like license. Modified for PHP by ab@php.net
+*
+* Home: http://synesis.com.au/software/
+*
+* Copyright (c) 2005-2010, Matthew Wilson and Synesis Software
+*/
+
+PHP_WINUTIL_API int php_win32_code_to_errno(unsigned long w32Err)
+{
+ size_t i;
+
+ struct code_to_errno_map
+ {
+ unsigned long w32Err;
+ int eerrno;
+ };
+
+ static const struct code_to_errno_map errmap[] =
+ {
+ /* 1 */ { ERROR_INVALID_FUNCTION , EINVAL }
+ /* 2 */ , { ERROR_FILE_NOT_FOUND , ENOENT }
+ /* 3 */ , { ERROR_PATH_NOT_FOUND , ENOENT }
+ /* 4 */ , { ERROR_TOO_MANY_OPEN_FILES , EMFILE }
+ /* 5 */ , { ERROR_ACCESS_DENIED , EACCES }
+ /* 6 */ , { ERROR_INVALID_HANDLE , EBADF }
+ /* 7 */ , { ERROR_ARENA_TRASHED , ENOMEM }
+ /* 8 */ , { ERROR_NOT_ENOUGH_MEMORY , ENOMEM }
+ /* 9 */ , { ERROR_INVALID_BLOCK , ENOMEM }
+ /* 10 */ , { ERROR_BAD_ENVIRONMENT , E2BIG }
+ /* 11 */ , { ERROR_BAD_FORMAT , ENOEXEC }
+ /* 12 */ , { ERROR_INVALID_ACCESS , EINVAL }
+ /* 13 */ , { ERROR_INVALID_DATA , EINVAL }
+ /* 14 */ , { ERROR_OUTOFMEMORY , ENOMEM }
+ /* 15 */ , { ERROR_INVALID_DRIVE , ENOENT }
+ /* 16 */ , { ERROR_CURRENT_DIRECTORY , ECURDIR }
+ /* 17 */ , { ERROR_NOT_SAME_DEVICE , EXDEV }
+ /* 18 */ , { ERROR_NO_MORE_FILES , ENOENT }
+ /* 19 */ , { ERROR_WRITE_PROTECT , EROFS }
+ /* 20 */ , { ERROR_BAD_UNIT , ENXIO }
+ /* 21 */ , { ERROR_NOT_READY , EBUSY }
+ /* 22 */ , { ERROR_BAD_COMMAND , EIO }
+ /* 23 */ , { ERROR_CRC , EIO }
+ /* 24 */ , { ERROR_BAD_LENGTH , EIO }
+ /* 25 */ , { ERROR_SEEK , EIO }
+ /* 26 */ , { ERROR_NOT_DOS_DISK , EIO }
+ /* 27 */ , { ERROR_SECTOR_NOT_FOUND , ENXIO }
+ /* 28 */ , { ERROR_OUT_OF_PAPER , EBUSY }
+ /* 29 */ , { ERROR_WRITE_FAULT , EIO }
+ /* 30 */ , { ERROR_READ_FAULT , EIO }
+ /* 31 */ , { ERROR_GEN_FAILURE , EIO }
+ /* 32 */ , { ERROR_SHARING_VIOLATION , EAGAIN }
+ /* 33 */ , { ERROR_LOCK_VIOLATION , EACCES }
+ /* 34 */ , { ERROR_WRONG_DISK , ENXIO }
+ /* 35 */ , { 35 , ENFILE }
+ /* 36 */ , { ERROR_SHARING_BUFFER_EXCEEDED , ENFILE }
+ /* 37 */ , { ERROR_HANDLE_EOF , EINVAL }
+ /* 38 */ , { ERROR_HANDLE_DISK_FULL , ENOSPC }
+#if 0
+ /* 39 */ , { 0 , 0 }
+ /* 40 */ , { 0 , 0 }
+ /* 41 */ , { 0 , 0 }
+ /* 42 */ , { 0 , 0 }
+ /* 43 */ , { 0 , 0 }
+ /* 44 */ , { 0 , 0 }
+ /* 45 */ , { 0 , 0 }
+ /* 46 */ , { 0 , 0 }
+ /* 47 */ , { 0 , 0 }
+ /* 48 */ , { 0 , 0 }
+ /* 49 */ , { 0 , 0 }
+#endif
+ /* 50 */ , { ERROR_NOT_SUPPORTED , ENOSYS }
+#if 0
+ /* 51 */ , { 0 , 0 }
+ /* 52 */ , { 0 , 0 }
+#endif
+ /* 53 */ , { ERROR_BAD_NETPATH , ENOENT }
+#if 0
+ /* 54 */ , { 0 , 0 }
+ /* 55 */ , { 0 , 0 }
+ /* 56 */ , { 0 , 0 }
+ /* 57 */ , { 0 , 0 }
+ /* 58 */ , { 0 , 0 }
+ /* 59 */ , { 0 , 0 }
+ /* 60 */ , { 0 , 0 }
+ /* 61 */ , { 0 , 0 }
+ /* 62 */ , { 0 , 0 }
+ /* 63 */ , { 0 , 0 }
+ /* 64 */ , { 0 , 0 }
+#endif
+ /* 65 */ , { ERROR_NETWORK_ACCESS_DENIED , EACCES }
+#if 0
+ /* 66 */ , { 0 , 0 }
+#endif
+ /* 67 */ , { ERROR_BAD_NET_NAME , ENOENT }
+#if 0
+ /* 68 */ , { 0 , 0 }
+ /* 69 */ , { 0 , 0 }
+ /* 70 */ , { 0 , 0 }
+ /* 71 */ , { 0 , 0 }
+ /* 72 */ , { 0 , 0 }
+ /* 73 */ , { 0 , 0 }
+ /* 74 */ , { 0 , 0 }
+ /* 75 */ , { 0 , 0 }
+ /* 76 */ , { 0 , 0 }
+ /* 77 */ , { 0 , 0 }
+ /* 78 */ , { 0 , 0 }
+ /* 79 */ , { 0 , 0 }
+#endif
+ /* 80 */ , { ERROR_FILE_EXISTS , EEXIST }
+#if 0
+ /* 81 */ , { 0 , 0 }
+#endif
+ /* 82 */ , { ERROR_CANNOT_MAKE , EACCES }
+ /* 83 */ , { ERROR_FAIL_I24 , EACCES }
+#if 0
+ /* 84 */ , { 0 , 0 }
+ /* 85 */ , { 0 , 0 }
+ /* 86 */ , { 0 , 0 }
+#endif
+ /* 87 */ , { ERROR_INVALID_PARAMETER , EINVAL }
+#if 0
+ /* 88 */ , { 0 , 0 }
+#endif
+ /* 89 */ , { ERROR_NO_PROC_SLOTS , EAGAIN }
+#if 0
+ /* 90 */ , { 0 , 0 }
+ /* 91 */ , { 0 , 0 }
+ /* 92 */ , { 0 , 0 }
+ /* 93 */ , { 0 , 0 }
+ /* 94 */ , { 0 , 0 }
+ /* 95 */ , { 0 , 0 }
+ /* 96 */ , { 0 , 0 }
+ /* 97 */ , { 0 , 0 }
+ /* 98 */ , { 0 , 0 }
+ /* 99 */ , { 0 , 0 }
+ /* 100 */ , { 0 , 0 }
+ /* 101 */ , { 0 , 0 }
+ /* 102 */ , { 0 , 0 }
+ /* 103 */ , { 0 , 0 }
+ /* 104 */ , { 0 , 0 }
+ /* 105 */ , { 0 , 0 }
+ /* 106 */ , { 0 , 0 }
+ /* 107 */ , { 0 , 0 }
+#endif
+ /* 108 */ , { ERROR_DRIVE_LOCKED , EACCES }
+ /* 109 */ , { ERROR_BROKEN_PIPE , EPIPE }
+#if 0
+ /* 110 */ , { 0 , 0 }
+#endif
+ /* 111 */ , { ERROR_BUFFER_OVERFLOW , ENAMETOOLONG }
+ /* 112 */ , { ERROR_DISK_FULL , ENOSPC }
+#if 0
+ /* 113 */ , { 0 , 0 }
+#endif
+ /* 114 */ , { ERROR_INVALID_TARGET_HANDLE , EBADF }
+#if 0
+ /* 115 */ , { 0 , 0 }
+ /* 116 */ , { 0 , 0 }
+ /* 117 */ , { 0 , 0 }
+ /* 118 */ , { 0 , 0 }
+ /* 119 */ , { 0 , 0 }
+ /* 120 */ , { 0 , 0 }
+ /* 121 */ , { 0 , 0 }
+#endif
+ /* 122 */ , { ERROR_INSUFFICIENT_BUFFER , ERANGE }
+ /* 123 */ , { ERROR_INVALID_NAME , ENOENT }
+ /* 124 */ , { ERROR_INVALID_HANDLE , EINVAL }
+#if 0
+ /* 125 */ , { 0 , 0 }
+ /* 126 */ , { 0 , 0 }
+ /* 127 */ , { 0 , 0 }
+#endif
+ /* 128 */ , { ERROR_WAIT_NO_CHILDREN , ECHILD }
+ /* 129 */ , { ERROR_CHILD_NOT_COMPLETE , ECHILD }
+ /* 130 */ , { ERROR_DIRECT_ACCESS_HANDLE , EBADF }
+ /* 131 */ , { ERROR_NEGATIVE_SEEK , EINVAL }
+ /* 132 */ , { ERROR_SEEK_ON_DEVICE , EACCES }
+#if 0
+ /* 133 */ , { 0 , 0 }
+ /* 134 */ , { 0 , 0 }
+ /* 135 */ , { 0 , 0 }
+ /* 136 */ , { 0 , 0 }
+ /* 137 */ , { 0 , 0 }
+ /* 138 */ , { 0 , 0 }
+ /* 139 */ , { 0 , 0 }
+ /* 140 */ , { 0 , 0 }
+ /* 141 */ , { 0 , 0 }
+ /* 142 */ , { 0 , 0 }
+ /* 143 */ , { 0 , 0 }
+ /* 144 */ , { 0 , 0 }
+#endif
+ /* 145 */ , { ERROR_DIR_NOT_EMPTY , ENOTEMPTY }
+#if 0
+ /* 146 */ , { 0 , 0 }
+ /* 147 */ , { 0 , 0 }
+ /* 148 */ , { 0 , 0 }
+ /* 149 */ , { 0 , 0 }
+ /* 150 */ , { 0 , 0 }
+ /* 151 */ , { 0 , 0 }
+ /* 152 */ , { 0 , 0 }
+ /* 153 */ , { 0 , 0 }
+ /* 154 */ , { 0 , 0 }
+ /* 155 */ , { 0 , 0 }
+ /* 156 */ , { 0 , 0 }
+ /* 157 */ , { 0 , 0 }
+#endif
+ /* 158 */ , { ERROR_NOT_LOCKED , EACCES }
+#if 0
+ /* 159 */ , { 0 , 0 }
+ /* 160 */ , { 0 , 0 }
+#endif
+ /* 161 */ , { ERROR_BAD_PATHNAME , ENOENT }
+#if 0
+ /* 162 */ , { 0 , 0 }
+ /* 163 */ , { 0 , 0 }
+#endif
+ /* 164 */ , { ERROR_MAX_THRDS_REACHED , EAGAIN }
+#if 0
+ /* 165 */ , { 0 , 0 }
+ /* 166 */ , { 0 , 0 }
+#endif
+ /* 167 */ , { ERROR_LOCK_FAILED , EACCES }
+#if 0
+ /* 168 */ , { 0 , 0 }
+ /* 169 */ , { 0 , 0 }
+ /* 170 */ , { 0 , 0 }
+ /* 171 */ , { 0 , 0 }
+ /* 172 */ , { 0 , 0 }
+ /* 173 */ , { 0 , 0 }
+ /* 174 */ , { 0 , 0 }
+ /* 175 */ , { 0 , 0 }
+ /* 176 */ , { 0 , 0 }
+ /* 177 */ , { 0 , 0 }
+ /* 178 */ , { 0 , 0 }
+ /* 179 */ , { 0 , 0 }
+ /* 180 */ , { 0 , 0 }
+ /* 181 */ , { 0 , 0 }
+ /* 182 */ , { 0 , 0 }
+#endif
+ /* 183 */ , { ERROR_ALREADY_EXISTS , EEXIST }
+#if 0
+ /* 184 */ , { 0 , 0 }
+ /* 185 */ , { 0 , 0 }
+ /* 186 */ , { 0 , 0 }
+ /* 187 */ , { 0 , 0 }
+ /* 188 */ , { 0 , 0 }
+ /* 189 */ , { 0 , 0 }
+ /* 190 */ , { 0 , 0 }
+ /* 191 */ , { 0 , 0 }
+ /* 192 */ , { 0 , 0 }
+ /* 193 */ , { 0 , 0 }
+ /* 194 */ , { 0 , 0 }
+ /* 195 */ , { 0 , 0 }
+ /* 196 */ , { 0 , 0 }
+ /* 197 */ , { 0 , 0 }
+ /* 198 */ , { 0 , 0 }
+ /* 199 */ , { 0 , 0 }
+#endif
+
+ /* 206 */ , { ERROR_FILENAME_EXCED_RANGE , ENAMETOOLONG }
+
+ /* 215 */ , { ERROR_NESTING_NOT_ALLOWED , EAGAIN }
+ /* 258 */ , { WAIT_TIMEOUT, ETIME}
+
+ /* 267 */ , { ERROR_DIRECTORY , ENOTDIR }
+
+ /* 996 */ , { ERROR_IO_INCOMPLETE , EAGAIN }
+ /* 997 */ , { ERROR_IO_PENDING , EAGAIN }
+
+ /* 1004 */ , { ERROR_INVALID_FLAGS , EINVAL }
+ /* 1113 */ , { ERROR_NO_UNICODE_TRANSLATION , EINVAL }
+ /* 1168 */ , { ERROR_NOT_FOUND , ENOENT }
+ /* 1816 */ , { ERROR_NOT_ENOUGH_QUOTA , ENOMEM }
+ , { ERROR_ABANDONED_WAIT_0 , EIO }
+ };
+
+ for(i = 0; i < sizeof(errmap)/sizeof(struct code_to_errno_map); ++i)
+ {
+ if(w32Err == errmap[i].w32Err)
+ {
+ return errmap[i].eerrno;
+ }
+ }
+
+ assert(!"Unrecognised value");
+
+ return EINVAL;
+}
+
+PHP_WINUTIL_API char *php_win32_get_username(void)
+{
+ wchar_t unamew[UNLEN + 1];
+ size_t uname_len;
+ char *uname;
+ DWORD unsize = UNLEN;
+
+ GetUserNameW(unamew, &unsize);
+ uname = php_win32_cp_conv_w_to_any(unamew, unsize - 1, &uname_len);
+ if (!uname) {
+ return NULL;
+ }
+
+ /* Ensure the length doesn't overflow. */
+ if (uname_len > UNLEN) {
+ uname[uname_len] = '\0';
+ }
+
+ return uname;
+}
+
/*
* Local variables:
* tab-width: 4
diff --git a/win32/winutil.h b/win32/winutil.h
index bdb0f8702b..2edccaab4f 100644
--- a/win32/winutil.h
+++ b/win32/winutil.h
@@ -16,11 +16,17 @@
+----------------------------------------------------------------------+
*/
-PHPAPI char *php_win32_error_to_msg(HRESULT error);
+#ifdef PHP_EXPORTS
+# define PHP_WINUTIL_API __declspec(dllexport)
+#else
+# define PHP_WINUTIL_API __declspec(dllimport)
+#endif
+
+PHP_WINUTIL_API char *php_win32_error_to_msg(HRESULT error);
#define php_win_err() php_win32_error_to_msg(GetLastError())
int php_win32_check_trailing_space(const char * path, const int path_len);
-PHPAPI int php_win32_get_random_bytes(unsigned char *buf, size_t size);
+PHP_WINUTIL_API int php_win32_get_random_bytes(unsigned char *buf, size_t size);
#ifdef ZTS
void php_win32_init_rng_lock();
@@ -29,3 +35,22 @@ void php_win32_free_rng_lock();
#define php_win32_init_rng_lock();
#define php_win32_free_rng_lock();
#endif
+
+#if !defined(ECURDIR)
+# define ECURDIR EACCES
+#endif /* !ECURDIR */
+#if !defined(ENOSYS)
+# define ENOSYS EPERM
+#endif /* !ENOSYS */
+
+PHP_WINUTIL_API int php_win32_code_to_errno(unsigned long w32Err);
+
+#define SET_ERRNO_FROM_WIN32_CODE(err) \
+ do { \
+ int ern = php_win32_code_to_errno(err); \
+ SetLastError(err); \
+ _set_errno(ern); \
+ } while (0)
+
+PHP_WINUTIL_API char *php_win32_get_username(void);
+