diff options
Diffstat (limited to 'win32/winutil.c')
| -rw-r--r-- | win32/winutil.c | 94 |
1 files changed, 80 insertions, 14 deletions
diff --git a/win32/winutil.c b/win32/winutil.c index 78b5af6d7c..578e66c074 100644 --- a/win32/winutil.c +++ b/win32/winutil.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 7 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2018 The PHP Group | + | Copyright (c) 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 | @@ -19,19 +19,38 @@ #include "php.h" #include "winutil.h" +#include "codepage.h" #include <bcrypt.h> #include <lmcons.h> +#include <imagehlp.h> + PHP_WINUTIL_API char *php_win32_error_to_msg(HRESULT error) {/*{{{*/ - char *buf = NULL; + wchar_t *bufw = NULL; + char *buf; - FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&buf, 0, NULL + DWORD ret = FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&bufw, 0, NULL ); - return (buf ? (char *) buf : ""); + if (!ret || !bufw) { + return ""; + } + + buf = php_win32_cp_conv_w_to_any(bufw, ret, PHP_WIN32_CP_IGNORE_LEN_P); + + LocalFree(bufw); + + return (buf ? buf : ""); +}/*}}}*/ + +PHP_WINUTIL_API void php_win32_error_msg_free(char *msg) +{/*{{{*/ + if (msg && msg[0]) { + free(msg); + } }/*}}}*/ int php_win32_check_trailing_space(const char * path, const size_t path_len) @@ -378,8 +397,11 @@ PHP_WINUTIL_API int php_win32_code_to_errno(unsigned long w32Err) /* 1113 */ , { ERROR_NO_UNICODE_TRANSLATION , EINVAL } /* 1168 */ , { ERROR_NOT_FOUND , ENOENT } /* 1224 */ , { ERROR_USER_MAPPED_FILE , EACCES } + /* 1314 */ , { ERROR_PRIVILEGE_NOT_HELD , EACCES } /* 1816 */ , { ERROR_NOT_ENOUGH_QUOTA , ENOMEM } , { ERROR_ABANDONED_WAIT_0 , EIO } + /* 1464 */ , { ERROR_SYMLINK_NOT_SUPPORTED , EINVAL } + /* 4390 */ , { ERROR_NOT_A_REPARSE_POINT , EINVAL } }; for(i = 0; i < sizeof(errmap)/sizeof(struct code_to_errno_map); ++i) @@ -416,11 +438,55 @@ PHP_WINUTIL_API char *php_win32_get_username(void) return uname; }/*}}}*/ -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ +static zend_always_inline BOOL is_compatible(const char *name, BOOL is_smaller, char *format, char **err) +{/*{{{*/ + PLOADED_IMAGE img = ImageLoad(name, NULL); + + if (!img) { + DWORD _err = GetLastError(); + char *err_txt = php_win32_error_to_msg(_err); + spprintf(err, 0, "Failed to load %s, %s", name, err_txt); + free(err_txt); + return FALSE; + } + + DWORD major = img->FileHeader->OptionalHeader.MajorLinkerVersion; + DWORD minor = img->FileHeader->OptionalHeader.MinorLinkerVersion; + +#if PHP_LINKER_MAJOR == 14 + /* VS 2015, 2017 and 2019 are binary compatible, but only forward compatible. + It should be fine, if we load a module linked with an older one into + the core linked with the newer one, but not the otherway round. + Analogously, it should be fine, if a PHP build linked with an older version + is used with a newer CRT, but not the other way round. + Otherwise, if the linker major version is not same, it is an error, as + per the current knowledge. + + This check is to be extended as new VS versions come out. */ + DWORD core_minor = (DWORD)(PHP_LINKER_MINOR/10); + DWORD comp_minor = (DWORD)(minor/10); + if (14 == major && (is_smaller ? core_minor < comp_minor : core_minor > comp_minor) || PHP_LINKER_MAJOR != major) +#else + if (PHP_LINKER_MAJOR != major) +#endif + { + spprintf(err, 0, format, name, major, minor, PHP_LINKER_MAJOR, PHP_LINKER_MINOR); + ImageUnload(img); + return FALSE; + } + ImageUnload(img); + + return TRUE; +}/*}}}*/ + +PHP_WINUTIL_API BOOL php_win32_image_compatible(const char *name, char **err) +{/*{{{*/ + return is_compatible(name, TRUE, "Can't load module '%s' as it's linked with %u.%u, but the core is linked with %d.%d", err); +}/*}}}*/ + +/* Expect a CRT name DLL. */ +PHP_WINUTIL_API BOOL php_win32_crt_compatible(const char *name, char **err) +{/*{{{*/ + return is_compatible(name, FALSE, "'%s' %u.%u is not compatible with this PHP build linked with %d.%d", err); +}/*}}}*/ + |
