rework long path normalization stuf

Simplify, set error codes, ensure 32-bit is ok as well. The
canonicalization part is still an issue on win7 as the API
is missing there. However a partial improvement is reached
there as well thanks to the slash conversion.
This commit is contained in:
Anatol Belski 2016-07-24 03:43:17 +02:00
parent ca64223193
commit 4acde210fd
2 changed files with 31 additions and 22 deletions

View file

@ -66,7 +66,7 @@
#include <winnls.h>
*/
typedef HRESULT (WINAPI *MyPathCchCanonicalizeEx)(wchar_t *pszPathOut, size_t cchPathOut, const wchar_t *pszPathIn, unsigned long dwFlags);
typedef HRESULT (__stdcall *MyPathCchCanonicalizeEx)(wchar_t *pszPathOut, size_t cchPathOut, const wchar_t *pszPathIn, unsigned long dwFlags);
static MyPathCchCanonicalizeEx canonicalize_path_w = NULL;
@ -506,14 +506,14 @@ PW32IO size_t php_win32_ioutil_dirname(char *path, size_t len)
return ret_len;
}/*}}}*/
PW32IO BOOL php_win32_ioutil_normalize_path_w(wchar_t **buf, size_t len, size_t *new_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, canonicalw_len, shift;
size_t ret_len = len;
if (len >= MAXPATHLEN) {
SET_ERRNO_FROM_WIN32_CODE(ERROR_BUFFER_OVERFLOW);
return FALSE;
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) {
@ -521,30 +521,29 @@ PW32IO BOOL php_win32_ioutil_normalize_path_w(wchar_t **buf, size_t len, size_t
idx = pos++;
}
shift = PHP_WIN32_IOUTIL_IS_LONG_PATHW(*buf, len) ? PHP_WIN32_IOUTIL_LONG_PATH_PREFIX_LENW : 0;
if (S_OK != canonicalize_path_w(canonicalw, MAXPATHLEN, *buf + shift, PATHCCH_ALLOW_LONG_PATHS)) {
*new_len = ret_len;
return FALSE;
if (S_OK != canonicalize_path_w(canonicalw, MAXPATHLEN, *buf, PATHCCH_ALLOW_LONG_PATHS)) {
return PHP_WIN32_IOUTIL_NORM_PARTIAL;
}
canonicalw_len = wcslen(canonicalw);
if (canonicalw_len + shift != len) {
if (canonicalw_len > len) {
*buf = realloc(*buf, (canonicalw_len + 1) * sizeof(wchar_t));
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 + shift, canonicalw, (canonicalw_len + 1) * sizeof(wchar_t));
ret_len = canonicalw_len + shift;
memmove(*buf, canonicalw, (ret_len + 1) * sizeof(wchar_t));
}
*new_len = ret_len;
return TRUE;
return PHP_WIN32_IOUTIL_NORM_OK;
}/*}}}*/
static HRESULT MyPathCchCanonicalizeExFallback(wchar_t *pszPathOut, size_t cchPathOut, const wchar_t *pszPathIn, unsigned long dwFlags)
static HRESULT __stdcall MyPathCchCanonicalizeExFallback(wchar_t *pszPathOut, size_t cchPathOut, const wchar_t *pszPathIn, unsigned long dwFlags)
{/*{{{*/
cchPathOut = wcslen(pszPathIn);
memmove(pszPathOut, pszPathIn, (cchPathOut + 1) * sizeof(wchar_t));
return S_OK;
return -42;
}/*}}}*/
BOOL php_win32_ioutil_init(void)

View file

@ -87,6 +87,11 @@ typedef enum {
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 '/'
@ -133,7 +138,7 @@ typedef enum {
} \
} while (0);
PW32IO BOOL php_win32_ioutil_normalize_path_w(wchar_t **buf, size_t len, size_t *new_len);
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. */
@ -160,6 +165,11 @@ __forceinline static wchar_t *php_win32_ioutil_conv_any_to_w(const char* in, siz
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)) {