reactos/lib/shlwapi
diff -u -r1.8 -r1.9
--- path.c 24 Sep 2004 15:17:20 -0000 1.8
+++ path.c 20 Oct 2004 16:49:27 -0000 1.9
@@ -32,7 +32,7 @@
#include "wingdi.h"
#include "winuser.h"
#include "winreg.h"
-#include "winnls.h"
+#include "winternl.h"
#define NO_SHLWAPI_STREAM
#include "shlwapi.h"
#include "wine/debug.h"
@@ -3116,8 +3116,11 @@
*/
BOOL WINAPI PathSearchAndQualifyA(LPCSTR lpszPath, LPSTR lpszBuf, UINT cchBuf)
{
- FIXME("(%s,%p,0x%08x)-stub\n", debugstr_a(lpszPath), lpszBuf, cchBuf);
- return FALSE;
+ TRACE("(%s,%p,0x%08x)\n", debugstr_a(lpszPath), lpszBuf, cchBuf);
+
+ if(SearchPathA(NULL, lpszPath, NULL, cchBuf, lpszBuf, NULL))
+ return TRUE;
+ return !!GetFullPathNameA(lpszPath, cchBuf, lpszBuf, NULL);
}
/*************************************************************************
@@ -3127,8 +3130,11 @@
*/
BOOL WINAPI PathSearchAndQualifyW(LPCWSTR lpszPath, LPWSTR lpszBuf, UINT cchBuf)
{
- FIXME("(%s,%p,0x%08x)-stub\n", debugstr_w(lpszPath), lpszBuf, cchBuf);
- return FALSE;
+ TRACE("(%s,%p,0x%08x)\n", debugstr_w(lpszPath), lpszBuf, cchBuf);
+
+ if(SearchPathW(NULL, lpszPath, NULL, cchBuf, lpszBuf, NULL))
+ return TRUE;
+ return !!GetFullPathNameW(lpszPath, cchBuf, lpszBuf, NULL);
}
/*************************************************************************
@@ -3200,6 +3206,42 @@
/*************************************************************************
* PathCreateFromUrlA [SHLWAPI.@]
*
+ * See PathCreateFromUrlW
+ */
+HRESULT WINAPI PathCreateFromUrlA(LPCSTR pszUrl, LPSTR pszPath,
+ LPDWORD pcchPath, DWORD dwReserved)
+{
+ WCHAR bufW[MAX_PATH];
+ WCHAR *pathW = bufW;
+ UNICODE_STRING urlW;
+ HRESULT ret;
+ DWORD lenW = sizeof(bufW)/sizeof(WCHAR), lenA;
+
+ if(!RtlCreateUnicodeStringFromAsciiz(&urlW, pszUrl))
+ return E_INVALIDARG;
+ if((ret = PathCreateFromUrlW(urlW.Buffer, pathW, &lenW, dwReserved)) == E_POINTER) {
+ pathW = HeapAlloc(GetProcessHeap(), 0, lenW * sizeof(WCHAR));
+ ret = PathCreateFromUrlW(urlW.Buffer, pathW, &lenW, dwReserved);
+ }
+ if(ret == S_OK) {
+ RtlUnicodeToMultiByteSize(&lenA, pathW, lenW * sizeof(WCHAR));
+ if(*pcchPath > lenA) {
+ RtlUnicodeToMultiByteN(pszPath, *pcchPath - 1, &lenA, pathW, lenW * sizeof(WCHAR));
+ pszPath[lenA] = 0;
+ *pcchPath = lenA;
+ } else {
+ *pcchPath = lenA + 1;
+ ret = E_POINTER;
+ }
+ }
+ if(pathW != bufW) HeapFree(GetProcessHeap(), 0, pathW);
+ RtlFreeUnicodeString(&urlW);
+ return ret;
+}
+
+/*************************************************************************
+ * PathCreateFromUrlW [SHLWAPI.@]
+ *
* Create a path from a URL
*
* PARAMS
@@ -3212,79 +3254,66 @@
* Success: S_OK. lpszPath contains the URL in path format,
* Failure: An HRESULT error code such as E_INVALIDARG.
*/
-HRESULT WINAPI PathCreateFromUrlA(LPCSTR lpszUrl, LPSTR lpszPath,
- LPDWORD pcchPath, DWORD dwFlags)
+HRESULT WINAPI PathCreateFromUrlW(LPCWSTR pszUrl, LPWSTR pszPath,
+ LPDWORD pcchPath, DWORD dwReserved)
{
- LPSTR pszPathPart;
- TRACE("(%s,%p,%p,0x%08lx)\n", debugstr_a(lpszUrl), lpszPath, pcchPath, dwFlags);
+ static const WCHAR file_colon[] = { 'f','i','l','e',':',0 };
+ HRESULT hr;
+ DWORD nslashes = 0;
+ WCHAR *ptr;
- if (!lpszUrl || !lpszPath || !pcchPath || !*pcchPath)
- return E_INVALIDARG;
+ TRACE("(%s,%p,%p,0x%08lx)\n", debugstr_w(pszUrl), pszPath, pcchPath, dwReserved);
- pszPathPart = StrChrA(lpszUrl, ':');
- if ((((pszPathPart - lpszUrl) == 1) && isalpha(*lpszUrl)) ||
- !lstrcmpA(lpszUrl, "file:"))
- {
- return UrlUnescapeA(pszPathPart, lpszPath, pcchPath, dwFlags);
- }
- /* extracts thing prior to : in pszURL and checks against:
- * https
- * shell
- * local
- * about - if match returns E_INVALIDARG
- */
+ if (!pszUrl || !pszPath || !pcchPath || !*pcchPath)
+ return E_INVALIDARG;
- return E_INVALIDARG;
-}
-/*************************************************************************
- * PathCreateFromUrlW [SHLWAPI.@]
- *
- * See PathCreateFromUrlA.
- */
-HRESULT WINAPI PathCreateFromUrlW(LPCWSTR lpszUrl, LPWSTR lpszPath,
- LPDWORD pcchPath, DWORD dwFlags)
-{
- static const WCHAR stemp[] = { 'f','i','l','e',':','/','/','/',0 };
- LPWSTR pwszPathPart;
- HRESULT hr;
+ if (strncmpW(pszUrl, file_colon, 5))
+ return E_INVALIDARG;
+ pszUrl += 5;
- TRACE("(%s,%p,%p,0x%08lx)\n", debugstr_w(lpszUrl), lpszPath, pcchPath, dwFlags);
+ while(*pszUrl == '/' || *pszUrl == '\\') {
+ nslashes++;
+ pszUrl++;
+ }
- if (!lpszUrl || !lpszPath || !pcchPath || !*pcchPath)
- return E_INVALIDARG;
+ if(isalphaW(*pszUrl) && (pszUrl[1] == ':' || pszUrl[1] == '|') && (pszUrl[2] == '/' || pszUrl[2] == '\\'))
+ nslashes = 0;
- /* Path of the form file:///... */
- if (!strncmpW(lpszUrl, stemp, 8))
- {
- lpszUrl += 8;
- }
- /* Path of the form file://... */
- else if (!strncmpW(lpszUrl, stemp, 7))
- {
- lpszUrl += 7;
- }
- /* Path of the form file:... */
- else if (!strncmpW(lpszUrl, stemp, 5))
- {
- lpszUrl += 5;
- }
+ switch(nslashes) {
+ case 2:
+ pszUrl -= 2;
+ break;
+ case 0:
+ break;
+ default:
+ pszUrl -= 1;
+ break;
+ }
- /* Ensure that path is of the form c:... or c|... */
- if (lpszUrl[1] != ':' && lpszUrl[1] != '|' && isalphaW(*lpszUrl))
- return E_INVALIDARG;
+ hr = UrlUnescapeW((LPWSTR)pszUrl, pszPath, pcchPath, 0);
+ if(hr != S_OK) return hr;
- hr = UrlUnescapeW((LPWSTR) lpszUrl, lpszPath, pcchPath, dwFlags);
- if (lpszPath[1] == '|')
- lpszPath[1] = ':';
+ for(ptr = pszPath; *ptr; ptr++)
+ if(*ptr == '/') *ptr = '\\';
- for (pwszPathPart = lpszPath; *pwszPathPart; pwszPathPart++)
- if (*pwszPathPart == '/')
- *pwszPathPart = '\\';
+ while(*pszPath == '\\')
+ pszPath++;
+
+ if(isalphaW(*pszPath) && pszPath[1] == '|' && pszPath[2] == '\\') /* c|\ -> c:\ */
+ pszPath[1] = ':';
+
+ if(nslashes == 2 && (ptr = strchrW(pszPath, '\\'))) { /* \\host\c:\ -> \\hostc:\ */
+ ptr++;
+ if(isalphaW(*ptr) && (ptr[1] == ':' || ptr[1] == '|') && ptr[2] == '\\') {
+ memmove(ptr - 1, ptr, (strlenW(ptr) + 1) * sizeof(WCHAR));
+ (*pcchPath)--;
+ }
+ }
- TRACE("Returning %s\n",debugstr_w(lpszPath));
+ TRACE("Returning %s\n",debugstr_w(pszPath));
- return hr;
+ return hr;
}
/*************************************************************************
reactos/lib/shlwapi
diff -u -r1.10 -r1.11
--- url.c 19 Sep 2004 10:46:48 -0000 1.10
+++ url.c 20 Oct 2004 16:49:27 -0000 1.11
@@ -30,6 +30,7 @@
#include "wine/unicode.h"
#include "wininet.h"
#include "winreg.h"
+#include "winternl.h"
#define NO_SHLWAPI_STREAM
#include "shlwapi.h"
#include "wine/debug.h"
@@ -43,30 +44,6 @@
/* The following schemes were identified in the native version of
* SHLWAPI.DLL version 5.50
*/
-typedef enum {
- URL_SCHEME_INVALID = -1,
- URL_SCHEME_UNKNOWN = 0,
- URL_SCHEME_FTP,
- URL_SCHEME_HTTP,
- URL_SCHEME_GOPHER,
- URL_SCHEME_MAILTO,
- URL_SCHEME_NEWS,
- URL_SCHEME_NNTP,
- URL_SCHEME_TELNET,
- URL_SCHEME_WAIS,
- URL_SCHEME_FILE,
- URL_SCHEME_MK,
- URL_SCHEME_HTTPS,
- URL_SCHEME_SHELL,
- URL_SCHEME_SNEWS,
- URL_SCHEME_LOCAL,
- URL_SCHEME_JAVASCRIPT,
- URL_SCHEME_VBSCRIPT,
- URL_SCHEME_ABOUT,
- URL_SCHEME_RES,
- URL_SCHEME_MAXVALUE
-} URL_SCHEME;
-
typedef struct {
URL_SCHEME scheme_number;
LPCSTR scheme_name;
@@ -116,24 +93,6 @@
USERPASS,
} WINE_URL_SCAN_TYPE;
-typedef struct {
- INT size; /* [in] (always 0x18) */
- LPCSTR ap1; /* [out] start of scheme */
- INT sizep1; /* [out] size of scheme (until colon) */
- LPCSTR ap2; /* [out] pointer following first colon */
- INT sizep2; /* [out] size of remainder */
- INT fcncde; /* [out] function match of p1 (0 if unknown) */
-} UNKNOWN_SHLWAPI_1;
-
-typedef struct {
- INT size; /* [in] (always 0x18) */
- LPCWSTR ap1; /* [out] start of scheme */
- INT sizep1; /* [out] size of scheme (until colon) */
- LPCWSTR ap2; /* [out] pointer following first colon */
- INT sizep2; /* [out] size of remainder */
- INT fcncde; /* [out] function match of p1 (0 if unknown) */
-} UNKNOWN_SHLWAPI_2;
-
static const CHAR hexDigits[] = "0123456789ABCDEF";
static const WCHAR fileW[] = {'f','i','l','e','\0'};
@@ -160,96 +119,6 @@
0x25, 0x45, 0x27, 0x75, 0x92, 0xB8, 0xA3, 0xC8, 0xDE, 0xEB, 0xF8, 0xF3, 0xDB,
0x0A, 0x98, 0x83, 0x7B, 0xE5, 0xCB, 0x4C, 0x78, 0xD1 };
-static inline BOOL URL_NeedEscapeA(CHAR ch, DWORD dwFlags)
-{
-
- if (isalnum(ch))
- return FALSE;
-
- if(dwFlags & URL_ESCAPE_SPACES_ONLY) {
- if(ch == ' ')
- return TRUE;
- else
- return FALSE;
- }
-
- if ((dwFlags & URL_ESCAPE_PERCENT) && (ch == '%'))
- return TRUE;
-
- if (ch <= 31 || ch >= 127)
- return TRUE;
-
- else {
- switch (ch) {
- case ' ':
- case '<':
- case '>':
- case '\"':
- case '{':
- case '}':
- case '|':
-/* case '\\': */
- case '^':
- case ']':
- case '[':
- case '`':
- case '&':
- return TRUE;
-
- case '/':
- case '?':
- if (dwFlags & URL_ESCAPE_SEGMENT_ONLY) return TRUE;
- default:
- return FALSE;
- }
- }
-}
-
-static inline BOOL URL_NeedEscapeW(WCHAR ch, DWORD dwFlags)
-{
-
- if (isalnumW(ch))
- return FALSE;
-
- if(dwFlags & URL_ESCAPE_SPACES_ONLY) {
- if(ch == L' ')
- return TRUE;
- else
- return FALSE;
- }
-
- if ((dwFlags & URL_ESCAPE_PERCENT) && (ch == L'%'))
- return TRUE;
-
- if (ch <= 31 || ch >= 127)
- return TRUE;
-
- else {
- switch (ch) {
- case L' ':
- case L'<':
- case L'>':
- case L'\"':
- case L'{':
- case L'}':
- case L'|':
- case L'\\':
- case L'^':
- case L']':
- case L'[':
- case L'`':
- case L'&':
- return TRUE;
-
- case L'/':
- case L'?':
- if (dwFlags & URL_ESCAPE_SEGMENT_ONLY) return TRUE;
- default:
- return FALSE;
- }
- }
-}
-
static BOOL URL_JustLocation(LPCWSTR str)
{
while(*str && (*str == L'/')) str++;
@@ -276,25 +145,25 @@
* Success: S_OK. y contains the parsed Url details.
* Failure: An HRESULT error code.
*/
-DWORD WINAPI ParseURLA(LPCSTR x, UNKNOWN_SHLWAPI_1 *y)
+HRESULT WINAPI ParseURLA(LPCSTR x, PARSEDURLA *y)
{
DWORD cnt;
const SHL_2_inet_scheme *inet_pro;
- y->fcncde = URL_SCHEME_INVALID;
- if (y->size != 0x18) return E_INVALIDARG;
+ y->nScheme = URL_SCHEME_INVALID;
+ if (y->cbSize != sizeof(*y)) return E_INVALIDARG;
/* FIXME: leading white space generates error of 0x80041001 which
* is undefined
*/
if (*x <= ' ') return 0x80041001;
cnt = 0;
- y->sizep1 = 0;
- y->ap1 = x;
+ y->cchProtocol = 0;
+ y->pszProtocol = x;
while (*x) {
if (*x == ':') {
- y->sizep1 = cnt;
+ y->cchProtocol = cnt;
cnt = -1;
- y->ap2 = x+1;
+ y->pszSuffix = x+1;
break;
}
x++;
@@ -303,21 +172,21 @@
/* check for no scheme in string start */
/* (apparently schemes *must* be larger than a single character) */
- if ((*x == '\0') || (y->sizep1 <= 1)) {
- y->ap1 = 0;
+ if ((*x == '\0') || (y->cchProtocol <= 1)) {
+ y->pszProtocol = NULL;
return 0x80041001;
}
/* found scheme, set length of remainder */
- y->sizep2 = lstrlenA(y->ap2);
+ y->cchSuffix = lstrlenA(y->pszSuffix);
/* see if known scheme and return indicator number */
- y->fcncde = URL_SCHEME_UNKNOWN;
+ y->nScheme = URL_SCHEME_UNKNOWN;
inet_pro = shlwapi_schemes;
while (inet_pro->scheme_name) {
- if (!strncasecmp(inet_pro->scheme_name, y->ap1,
- min(y->sizep1, lstrlenA(inet_pro->scheme_name)))) {
- y->fcncde = inet_pro->scheme_number;
+ if (!strncasecmp(inet_pro->scheme_name, y->pszProtocol,
+ min(y->cchProtocol, lstrlenA(inet_pro->scheme_name)))) {
+ y->nScheme = inet_pro->scheme_number;
break;
}
inet_pro++;
@@ -330,27 +199,27 @@
*
* Unicode version of ParseURLA.
*/
-DWORD WINAPI ParseURLW(LPCWSTR x, UNKNOWN_SHLWAPI_2 *y)
+HRESULT WINAPI ParseURLW(LPCWSTR x, PARSEDURLW *y)
{
DWORD cnt;
const SHL_2_inet_scheme *inet_pro;
LPSTR cmpstr;
INT len;
- y->fcncde = URL_SCHEME_INVALID;
- if (y->size != 0x18) return E_INVALIDARG;
+ y->nScheme = URL_SCHEME_INVALID;
+ if (y->cbSize != sizeof(*y)) return E_INVALIDARG;
/* FIXME: leading white space generates error of 0x80041001 which
* is undefined
*/
if (*x <= L' ') return 0x80041001;
cnt = 0;
- y->sizep1 = 0;
- y->ap1 = x;
+ y->cchProtocol = 0;
+ y->pszProtocol = x;
while (*x) {
if (*x == L':') {
- y->sizep1 = cnt;
+ y->cchProtocol = cnt;
cnt = -1;
- y->ap2 = x+1;
+ y->pszSuffix = x+1;
break;
}
x++;
@@ -359,24 +228,24 @@
/* check for no scheme in string start */
/* (apparently schemes *must* be larger than a single character) */
- if ((*x == L'\0') || (y->sizep1 <= 1)) {
- y->ap1 = 0;
+ if ((*x == L'\0') || (y->cchProtocol <= 1)) {
+ y->pszProtocol = NULL;
return 0x80041001;
}
/* found scheme, set length of remainder */
- y->sizep2 = lstrlenW(y->ap2);
+ y->cchSuffix = lstrlenW(y->pszSuffix);
/* see if known scheme and return indicator number */
- len = WideCharToMultiByte(0, 0, y->ap1, y->sizep1, 0, 0, 0, 0);
+ len = WideCharToMultiByte(0, 0, y->pszProtocol, y->cchProtocol, 0, 0, 0, 0);
cmpstr = (LPSTR)HeapAlloc(GetProcessHeap(), 0, len);
- WideCharToMultiByte(0, 0, y->ap1, y->sizep1, cmpstr, len, 0, 0);
- y->fcncde = URL_SCHEME_UNKNOWN;
+ WideCharToMultiByte(0, 0, y->pszProtocol, y->cchProtocol, cmpstr, len, 0, 0);
+ y->nScheme = URL_SCHEME_UNKNOWN;
inet_pro = shlwapi_schemes;
while (inet_pro->scheme_name) {
if (!strncasecmp(inet_pro->scheme_name, cmpstr,
min(len, lstrlenA(inet_pro->scheme_name)))) {
- y->fcncde = inet_pro->scheme_number;
+ y->nScheme = inet_pro->scheme_number;
break;
}
inet_pro++;
@@ -459,7 +328,8 @@
HRESULT hr = S_OK;
DWORD EscapeFlags;
LPWSTR lpszUrlCpy, wk1, wk2, mp, root;
- INT nLen, nByteLen, state;
+ INT nByteLen, state;
+ DWORD nLen;
TRACE("(%s %p %p 0x%08lx)\n", debugstr_w(pszUrl), pszCanonicalized,
pcchCanonicalized, dwFlags);
@@ -684,7 +554,7 @@
LPWSTR pszCombined, LPDWORD pcchCombined,
DWORD dwFlags)
{
- UNKNOWN_SHLWAPI_2 base, relative;
+ PARSEDURLW base, relative;
DWORD myflags, sizeloc = 0;
DWORD len, res1, res2, process_case = 0;
LPWSTR work, preliminary, mbase, mrelative;
@@ -699,8 +569,8 @@
if(!pszBase || !pszRelative || !pcchCombined)
return E_INVALIDARG;
- base.size = 24;
- relative.size = 24;
+ base.cbSize = sizeof(base);
+ relative.cbSize = sizeof(relative);
/* Get space for duplicates of the input and the output */
preliminary = HeapAlloc(GetProcessHeap(), 0, (3*INTERNET_MAX_URL_LENGTH) *
@@ -728,7 +598,7 @@
else do {
/* get size of location field (if it exists) */
- work = (LPWSTR)base.ap2;
+ work = (LPWSTR)base.pszSuffix;
sizeloc = 0;
if (*work++ == L'/') {
if (*work++ == L'/') {
@@ -736,23 +606,23 @@
* it ends at next '/' or end of string.
*/
while(*work && (*work != L'/')) work++;
- sizeloc = (DWORD)(work - base.ap2);
+ sizeloc = (DWORD)(work - base.pszSuffix);
}
}
/* Change .sizep2 to not have the last leaf in it,
* Note: we need to start after the location (if it exists)
*/
- work = strrchrW((base.ap2+sizeloc), L'/');
+ work = strrchrW((base.pszSuffix+sizeloc), L'/');
if (work) {
- len = (DWORD)(work - base.ap2 + 1);
- base.sizep2 = len;
+ len = (DWORD)(work - base.pszSuffix + 1);
+ base.cchSuffix = len;
}
/*
* At this point:
- * .ap2 points to location (starting with '//')
- * .sizep2 length of location (above) and rest less the last
- * leaf (if any)
+ * .pszSuffix points to location (starting with '//')
+ * .cchSuffix length of location (above) and rest less the last
+ * leaf (if any)
* sizeloc length of location (above) up to but not including
* the last '/'
*/
@@ -761,8 +631,8 @@
if (res2) {
/* no scheme in pszRelative */
TRACE("no scheme detected in Relative\n");
- relative.ap2 = mrelative; /* case 3,4,5 depends on this */
- relative.sizep2 = strlenW(mrelative);
+ relative.pszSuffix = mrelative; /* case 3,4,5 depends on this */
+ relative.cchSuffix = strlenW(mrelative);
if (*pszRelative == L':') {
/* case that is either left alone or uses pszBase */
if (dwFlags & URL_PLUGGABLE_PROTOCOL) {
@@ -788,21 +658,21 @@
process_case = 4;
break;
}
- process_case = (*base.ap2 == L'/') ? 5 : 3;
+ process_case = (*base.pszSuffix == L'/') ? 5 : 3;
break;
}
/* handle cases where pszRelative has scheme */
- if ((base.sizep1 == relative.sizep1) &&
- (strncmpW(base.ap1, relative.ap1, base.sizep1) == 0)) {
+ if ((base.cchProtocol == relative.cchProtocol) &&
+ (strncmpW(base.pszProtocol, relative.pszProtocol, base.cchProtocol) == 0)) {
/* since the schemes are the same */
- if ((*relative.ap2 == L'/') && (*(relative.ap2+1) == L'/')) {
+ if ((*relative.pszSuffix == L'/') && (*(relative.pszSuffix+1) == L'/')) {
/* case where pszRelative replaces location and following */
process_case = 3;
break;
}
- if (*relative.ap2 == L'/') {
+ if (*relative.pszSuffix == L'/') {
/* case where pszRelative is root to location */
process_case = 4;
break;
@@ -811,7 +681,7 @@
process_case = 5;
break;
}
- if ((*relative.ap2 == L'/') && (*(relative.ap2+1) == L'/')) {
+ if ((*relative.pszSuffix == L'/') && (*(relative.pszSuffix+1) == L'/')) {
/* case where pszRelative replaces scheme, location,
* and following and handles PLUGGABLE
*/
@@ -839,7 +709,7 @@
*/
strcpyW(preliminary, mrelative);
if (!(dwFlags & URL_PLUGGABLE_PROTOCOL) &&
- URL_JustLocation(relative.ap2))
+ URL_JustLocation(relative.pszSuffix))
strcatW(preliminary, single_slash);
break;
@@ -847,11 +717,11 @@
* Return the pszBase scheme with pszRelative. Basically
* keeps the scheme and replaces the domain and following.
*/
- strncpyW(preliminary, base.ap1, base.sizep1 + 1);
- work = preliminary + base.sizep1 + 1;
- strcpyW(work, relative.ap2);
+ strncpyW(preliminary, base.pszProtocol, base.cchProtocol + 1);
+ work = preliminary + base.cchProtocol + 1;
+ strcpyW(work, relative.pszSuffix);
if (!(dwFlags & URL_PLUGGABLE_PROTOCOL) &&
- URL_JustLocation(relative.ap2))
+ URL_JustLocation(relative.pszSuffix))
strcatW(work, single_slash);
break;
@@ -860,22 +730,22 @@
* after the location is pszRelative. (Replace document
* from root on.)
*/
- strncpyW(preliminary, base.ap1, base.sizep1+1+sizeloc);
- work = preliminary + base.sizep1 + 1 + sizeloc;
+ strncpyW(preliminary, base.pszProtocol, base.cchProtocol+1+sizeloc);
+ work = preliminary + base.cchProtocol + 1 + sizeloc;
if (dwFlags & URL_PLUGGABLE_PROTOCOL)
*(work++) = L'/';
- strcpyW(work, relative.ap2);
+ strcpyW(work, relative.pszSuffix);
break;
case 5: /*
* Return the pszBase without its document (if any) and
* append pszRelative after its scheme.
*/
- strncpyW(preliminary, base.ap1, base.sizep1+1+base.sizep2);
- work = preliminary + base.sizep1+1+base.sizep2 - 1;
+ strncpyW(preliminary, base.pszProtocol, base.cchProtocol+1+base.cchSuffix);
+ work = preliminary + base.cchProtocol+1+base.cchSuffix - 1;
if (*work++ != L'/')
*(work++) = L'/';
- strcpyW(work, relative.ap2);
+ strcpyW(work, relative.pszSuffix);
break;
default:
@@ -898,6 +768,107 @@
/*************************************************************************
* UrlEscapeA [SHLWAPI.@]
+ */
+
+HRESULT WINAPI UrlEscapeA(
+ LPCSTR pszUrl,
+ LPSTR pszEscaped,
+ LPDWORD pcchEscaped,
+ DWORD dwFlags)
+{
+ WCHAR bufW[INTERNET_MAX_URL_LENGTH];
+ WCHAR *escapedW = bufW;
+ UNICODE_STRING urlW;
+ HRESULT ret;
+ DWORD lenW = sizeof(bufW)/sizeof(WCHAR), lenA;
+
+ if(!RtlCreateUnicodeStringFromAsciiz(&urlW, pszUrl))
+ return E_INVALIDARG;
+ if((ret = UrlEscapeW(urlW.Buffer, escapedW, &lenW, dwFlags)) == E_POINTER) {
+ escapedW = HeapAlloc(GetProcessHeap(), 0, lenW * sizeof(WCHAR));
+ ret = UrlEscapeW(urlW.Buffer, escapedW, &lenW, dwFlags);
+ }
+ if(ret == S_OK) {
+ RtlUnicodeToMultiByteSize(&lenA, escapedW, lenW * sizeof(WCHAR));
+ if(*pcchEscaped > lenA) {
+ RtlUnicodeToMultiByteN(pszEscaped, *pcchEscaped - 1, &lenA, escapedW, lenW * sizeof(WCHAR));
+ pszEscaped[lenA] = 0;
+ *pcchEscaped = lenA;
+ } else {
+ *pcchEscaped = lenA + 1;
+ ret = E_POINTER;
+ }
+ }
+ if(escapedW != bufW) HeapFree(GetProcessHeap(), 0, escapedW);
+ RtlFreeUnicodeString(&urlW);
+ return ret;
+}
+
+#define WINE_URL_BASH_AS_SLASH 0x01
+#define WINE_URL_COLLAPSE_SLASHES 0x02
+#define WINE_URL_ESCAPE_SLASH 0x04
+#define WINE_URL_ESCAPE_HASH 0x08
+#define WINE_URL_ESCAPE_QUESTION 0x10
+#define WINE_URL_STOP_ON_HASH 0x20
+#define WINE_URL_STOP_ON_QUESTION 0x40
+
+static inline BOOL URL_NeedEscapeW(WCHAR ch, DWORD dwFlags, DWORD int_flags)
+{
+
+ if (isalnumW(ch))
+ return FALSE;
+
+ if(dwFlags & URL_ESCAPE_SPACES_ONLY) {
+ if(ch == ' ')
+ return TRUE;
+ else
+ return FALSE;
+ }
+
+ if ((dwFlags & URL_ESCAPE_PERCENT) && (ch == '%'))
+ return TRUE;
+
+ if (ch <= 31 || ch >= 127)
+ return TRUE;
+
+ else {
+ switch (ch) {
+ case ' ':
+ case '<':
+ case '>':
+ case '\"':
+ case '{':
+ case '}':
+ case '|':
+ case '\\':
+ case '^':
+ case ']':
+ case '[':
+ case '`':
+ case '&':
+ return TRUE;
+
+ case '/':
+ if (int_flags & WINE_URL_ESCAPE_SLASH) return TRUE;
+ return FALSE;
+
+ case '?':
+ if (int_flags & WINE_URL_ESCAPE_QUESTION) return TRUE;
+ return FALSE;
+
+ case '#':
+ if (int_flags & WINE_URL_ESCAPE_HASH) return TRUE;
+ return FALSE;
+
+ default:
+ return FALSE;
+ }
+ }
+}
+
+
+/*************************************************************************
+ * UrlEscapeW [SHLWAPI.@]
*
* Converts unsafe characters in a Url into escape sequences.
*
@@ -912,12 +883,12 @@
* contains its length.
* Failure: E_POINTER, if pszEscaped is not large enough. In this case
* pcchEscaped is set to the required length.
-
+ *
* Converts unsafe characters into their escape sequences.
*
* NOTES
* - By default this function stops converting at the first '?' or
- * '#' character (MSDN does not document this).
+ * '#' character.
* - If dwFlags contains URL_ESCAPE_SPACES_ONLY then only spaces are
* converted, but the conversion continues past a '?' or '#'.
* - Note that this function did not work well (or at all) in shlwapi version 4.
@@ -929,82 +900,6 @@
*| URL_ESCAPE_SEGMENT_ONLY
*| URL_ESCAPE_PERCENT
*/
-HRESULT WINAPI UrlEscapeA(
- LPCSTR pszUrl,
- LPSTR pszEscaped,
- LPDWORD pcchEscaped,
- DWORD dwFlags)
-{
- LPCSTR src;
- DWORD needed = 0, ret;
- BOOL stop_escaping = FALSE;
- char next[3], *dst = pszEscaped;
- INT len;
-
- TRACE("(%s %p %lx 0x%08lx)\n", debugstr_a(pszUrl), pszEscaped,
- pcchEscaped?*pcchEscaped:0, dwFlags);
-
- if(!pszUrl || !pszEscaped || !pcchEscaped)
- return E_INVALIDARG;
-
- if(dwFlags & ~(URL_ESCAPE_SPACES_ONLY |
- URL_ESCAPE_SEGMENT_ONLY |
- URL_DONT_ESCAPE_EXTRA_INFO |
- URL_ESCAPE_PERCENT))
- FIXME("Unimplemented flags: %08lx\n", dwFlags);
-
- /* fix up flags */
- if (dwFlags & URL_ESCAPE_SPACES_ONLY)
- /* if SPACES_ONLY specified, reset the other controls */
- dwFlags &= ~(URL_DONT_ESCAPE_EXTRA_INFO |
- URL_ESCAPE_PERCENT |
- URL_ESCAPE_SEGMENT_ONLY);
-
- else
- /* if SPACES_ONLY *not* specified then assume DONT_ESCAPE_EXTRA_INFO */
- dwFlags |= URL_DONT_ESCAPE_EXTRA_INFO;
-
- for(src = pszUrl; *src; src++) {
- if(!(dwFlags & URL_ESCAPE_SEGMENT_ONLY) &&
- (dwFlags & URL_DONT_ESCAPE_EXTRA_INFO) &&
- (*src == '#' || *src == '?'))
- stop_escaping = TRUE;
-
- if(URL_NeedEscapeA(*src, dwFlags) && stop_escaping == FALSE) {
- /* TRACE("escaping %c\n", *src); */
- next[0] = '%';
- next[1] = hexDigits[(*src >> 4) & 0xf];
- next[2] = hexDigits[*src & 0xf];
- len = 3;
- } else {
- /* TRACE("passing %c\n", *src); */
- next[0] = *src;
- len = 1;
- }
-
- if(needed + len <= *pcchEscaped) {
- memcpy(dst, next, len);
- dst += len;
- }
- needed += len;
- }
-
- if(needed < *pcchEscaped) {
- *dst = '\0';
- ret = S_OK;
- } else {
- needed++; /* add one for the '\0' */
- ret = E_POINTER;
- }
- *pcchEscaped = needed;
- return ret;
-}
-
-/*************************************************************************
- * UrlEscapeW [SHLWAPI.@]
- *
- * See UrlEscapeA.
- */
HRESULT WINAPI UrlEscapeW(
LPCWSTR pszUrl,
LPWSTR pszEscaped,
@@ -1016,6 +911,10 @@
BOOL stop_escaping = FALSE;
WCHAR next[5], *dst = pszEscaped;
INT len;
+ PARSEDURLW parsed_url;
+ DWORD int_flags;
+ DWORD slashes = 0;
+ static const WCHAR localhost[] = {'l','o','c','a','l','h','o','s','t',0};
TRACE("(%s %p %p 0x%08lx)\n", debugstr_w(pszUrl), pszEscaped,
pcchEscaped, dwFlags);
@@ -1040,39 +939,101 @@
/* if SPACES_ONLY *not* specified the assume DONT_ESCAPE_EXTRA_INFO */
dwFlags |= URL_DONT_ESCAPE_EXTRA_INFO;
- for(src = pszUrl; *src; src++) {
- /*
- * if(!(dwFlags & URL_ESCAPE_SPACES_ONLY) &&
- * (*src == L'#' || *src == L'?'))
- * stop_escaping = TRUE;
- */
- if(!(dwFlags & URL_ESCAPE_SEGMENT_ONLY) &&
- (dwFlags & URL_DONT_ESCAPE_EXTRA_INFO) &&
- (*src == L'#' || *src == L'?'))
- stop_escaping = TRUE;
-
- if(URL_NeedEscapeW(*src, dwFlags) && stop_escaping == FALSE) {
- /* TRACE("escaping %c\n", *src); */
- next[0] = L'%';
- /*
- * I would have assumed that the W form would escape
- * the character with 4 hex digits (or even 8),
- * however, experiments show that native shlwapi escapes
- * with only 2 hex digits.
- * next[1] = hexDigits[(*src >> 12) & 0xf];
- * next[2] = hexDigits[(*src >> 8) & 0xf];
- * next[3] = hexDigits[(*src >> 4) & 0xf];
- * next[4] = hexDigits[*src & 0xf];
- * len = 5;
- */
- next[1] = hexDigits[(*src >> 4) & 0xf];
- next[2] = hexDigits[*src & 0xf];
- len = 3;
- } else {
- /* TRACE("passing %c\n", *src); */
- next[0] = *src;
- len = 1;
- }
+
+ int_flags = 0;
+ if(dwFlags & URL_ESCAPE_SEGMENT_ONLY) {
+ int_flags = WINE_URL_ESCAPE_QUESTION | WINE_URL_ESCAPE_HASH | WINE_URL_ESCAPE_SLASH;
+ } else {
+ parsed_url.cbSize = sizeof(parsed_url);
+ if(ParseURLW(pszUrl, &parsed_url) != S_OK)
+ parsed_url.nScheme = URL_SCHEME_INVALID;
+
+ TRACE("scheme = %d (%s)\n", parsed_url.nScheme, debugstr_wn(parsed_url.pszProtocol, parsed_url.cchProtocol));
+
+ if(dwFlags & URL_DONT_ESCAPE_EXTRA_INFO)
+ int_flags = WINE_URL_STOP_ON_HASH | WINE_URL_STOP_ON_QUESTION;
+
+ switch(parsed_url.nScheme) {
+ case URL_SCHEME_FILE:
+ int_flags |= WINE_URL_BASH_AS_SLASH | WINE_URL_COLLAPSE_SLASHES | WINE_URL_ESCAPE_HASH;
+ int_flags &= ~WINE_URL_STOP_ON_HASH;
+ break;
+
+ case URL_SCHEME_HTTP:
+ case URL_SCHEME_HTTPS:
+ int_flags |= WINE_URL_BASH_AS_SLASH;
+ if(parsed_url.pszSuffix[0] != '/' && parsed_url.pszSuffix[0] != '\\')
+ int_flags |= WINE_URL_ESCAPE_SLASH;
+ break;
+
+ case URL_SCHEME_MAILTO:
+ int_flags |= WINE_URL_ESCAPE_SLASH | WINE_URL_ESCAPE_QUESTION | WINE_URL_ESCAPE_HASH;
+ int_flags &= ~(WINE_URL_STOP_ON_QUESTION | WINE_URL_STOP_ON_HASH);
+ break;
+
+ case URL_SCHEME_INVALID:
+ break;
+
+ case URL_SCHEME_FTP:
+ default:
+ if(parsed_url.pszSuffix[0] != '/')
+ int_flags |= WINE_URL_ESCAPE_SLASH;
+ break;
+ }
+ }
+
+ for(src = pszUrl; *src; ) {
+ WCHAR cur = *src;
+ len = 0;
+
+ if((int_flags & WINE_URL_COLLAPSE_SLASHES) && src == pszUrl + parsed_url.cchProtocol + 1) {
+ int localhost_len = sizeof(localhost)/sizeof(WCHAR) - 1;
+ while(cur == '/' || cur == '\\') {
+ slashes++;
+ cur = *++src;
+ }
+ if(slashes == 2 && !strncmpiW(src, localhost, localhost_len)) { /* file://localhost/ -> file:/// */
+ if(*(src + localhost_len) == '/' || *(src + localhost_len) == '\\')
+ src += localhost_len + 1;
+ slashes = 3;
+ }
+
+ switch(slashes) {
+ case 1:
+ case 3:
+ next[0] = next[1] = next[2] = '/';
+ len = 3;
+ break;
+ case 0:
+ len = 0;
+ break;
+ default:
+ next[0] = next[1] = '/';
+ len = 2;
+ break;
+ }
+ }
+ if(len == 0) {
+
+ if(cur == '#' && (int_flags & WINE_URL_STOP_ON_HASH))
+ stop_escaping = TRUE;
+
+ if(cur == '?' && (int_flags & WINE_URL_STOP_ON_QUESTION))
+ stop_escaping = TRUE;
+
+ if(cur == '\\' && (int_flags & WINE_URL_BASH_AS_SLASH) && !stop_escaping) cur = '/';
+
+ if(URL_NeedEscapeW(cur, dwFlags, int_flags) && stop_escaping == FALSE) {
+ next[0] = L'%';
+ next[1] = hexDigits[(cur >> 4) & 0xf];
+ next[2] = hexDigits[cur & 0xf];
+ len = 3;
+ } else {
+ next[0] = cur;
+ len = 1;
+ }
+ src++;
+ }
if(needed + len <= *pcchEscaped) {
memcpy(dst, next, len*sizeof(WCHAR));
@@ -1082,7 +1043,7 @@
}
if(needed < *pcchEscaped) {
- *dst = L'\0';
+ *dst = '\0';
ret = S_OK;
} else {
needed++; /* add one for the '\0' */
@@ -1211,10 +1172,10 @@
} else if(*src == L'%' && isxdigitW(*(src + 1)) && isxdigitW(*(src + 2))
&& stop_unescaping == FALSE) {
INT ih;
- WCHAR buf[3];
- memcpy(buf, src + 1, 2*sizeof(WCHAR));
- buf[2] = L'\0';
- ih = StrToIntW(buf);
+ WCHAR buf[5] = {'0','x',0};
+ memcpy(buf + 2, src + 1, 2*sizeof(WCHAR));
+ buf[4] = 0;
+ StrToIntExW(buf, STIF_SUPPORT_HEX, &ih);
next = (WCHAR) ih;
src += 2; /* Advance to end of escape */
} else
@@ -1271,18 +1232,18 @@
LPCSTR WINAPI UrlGetLocationA(
LPCSTR pszUrl)
{
- UNKNOWN_SHLWAPI_1 base;
+ PARSEDURLA base;
DWORD res1;
- base.size = 24;
+ base.cbSize = sizeof(base);
res1 = ParseURLA(pszUrl, &base);
if (res1) return NULL; /* invalid scheme */
/* if scheme is file: then never return pointer */
- if (strncmp(base.ap1, "file", min(4,base.sizep1)) == 0) return NULL;
+ if (strncmp(base.pszProtocol, "file", min(4,base.cchProtocol)) == 0) return NULL;
/* Look for '#' and return its addr */
- return strchr(base.ap2, '#');
+ return strchr(base.pszSuffix, '#');
}
/*************************************************************************
@@ -1293,18 +1254,18 @@
LPCWSTR WINAPI UrlGetLocationW(
LPCWSTR pszUrl)
{
- UNKNOWN_SHLWAPI_2 base;
+ PARSEDURLW base;
DWORD res1;
- base.size = 24;
+ base.cbSize = sizeof(base);
res1 = ParseURLW(pszUrl, &base);
if (res1) return NULL; /* invalid scheme */
/* if scheme is file: then never return pointer */
- if (strncmpW(base.ap1, fileW, min(4,base.sizep1)) == 0) return NULL;
+ if (strncmpW(base.pszProtocol, fileW, min(4,base.cchProtocol)) == 0) return NULL;
/* Look for '#' and return its addr */
- return strchrW(base.ap2, L'#');
+ return strchrW(base.pszSuffix, L'#');
}
/*************************************************************************
@@ -1590,7 +1551,7 @@
*/
HRESULT WINAPI UrlApplySchemeW(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut, DWORD dwFlags)
{
- UNKNOWN_SHLWAPI_2 in_scheme;
+ PARSEDURLW in_scheme;
DWORD res1;
HRESULT ret;
@@ -1605,7 +1566,7 @@
return S_FALSE;
}
- in_scheme.size = 24;
+ in_scheme.cbSize = sizeof(in_scheme);
/* See if the base has a scheme */
res1 = ParseURLW(pszIn, &in_scheme);
if (res1) {
@@ -1617,7 +1578,7 @@
}
else {
/* we have a scheme, see if valid (known scheme) */
- if (in_scheme.fcncde) {
+ if (in_scheme.nScheme) {
/* have valid scheme, so just copy and exit */
if (strlenW(pszIn) + 1 > *pcchOut) {
*pcchOut = strlenW(pszIn) + 1;
@@ -1666,17 +1627,17 @@
*/
BOOL WINAPI UrlIsA(LPCSTR pszUrl, URLIS Urlis)
{
- UNKNOWN_SHLWAPI_1 base;
+ PARSEDURLA base;
DWORD res1;
LPCSTR last;
switch (Urlis) {
case URLIS_OPAQUE:
- base.size = 24;
+ base.cbSize = sizeof(base);
res1 = ParseURLA(pszUrl, &base);
if (res1) return FALSE; /* invalid scheme */
- if ((*base.ap2 == '/') && (*(base.ap2+1) == '/'))
+ if ((*base.pszSuffix == '/') && (*(base.pszSuffix+1) == '/'))
/* has scheme followed by 2 '/' */
return FALSE;
return TRUE;
@@ -1706,17 +1667,17 @@
BOOL WINAPI UrlIsW(LPCWSTR pszUrl, URLIS Urlis)
{
static const WCHAR stemp[] = { 'f','i','l','e',':','/','/',0 };
- UNKNOWN_SHLWAPI_2 base;
+ PARSEDURLW base;
DWORD res1;
LPCWSTR last;
switch (Urlis) {
case URLIS_OPAQUE:
- base.size = 24;
+ base.cbSize = sizeof(base);
res1 = ParseURLW(pszUrl, &base);
if (res1) return FALSE; /* invalid scheme */
- if ((*base.ap2 == '/') && (*(base.ap2+1) == '/'))
+ if ((*base.pszSuffix == '/') && (*(base.pszSuffix+1) == '/'))
/* has scheme followed by 2 '/' */
return FALSE;
return TRUE;
@@ -2109,15 +2070,15 @@
*/
BOOL WINAPI PathIsURLA(LPCSTR lpstrPath)
{
- UNKNOWN_SHLWAPI_1 base;
+ PARSEDURLA base;
DWORD res1;
if (!lpstrPath || !*lpstrPath) return FALSE;
/* get protocol */
- base.size = sizeof(base);
+ base.cbSize = sizeof(base);
res1 = ParseURLA(lpstrPath, &base);
- return (base.fcncde > 0);
+ return (base.nScheme != URL_SCHEME_INVALID);
}
/*************************************************************************
@@ -2127,20 +2088,55 @@
*/
BOOL WINAPI PathIsURLW(LPCWSTR lpstrPath)
{
- UNKNOWN_SHLWAPI_2 base;
+ PARSEDURLW base;
DWORD res1;
if (!lpstrPath || !*lpstrPath) return FALSE;
/* get protocol */
- base.size = sizeof(base);
+ base.cbSize = sizeof(base);
res1 = ParseURLW(lpstrPath, &base);
- return (base.fcncde > 0);
+ return (base.nScheme != URL_SCHEME_INVALID);
}
/*************************************************************************
* UrlCreateFromPathA [SHLWAPI.@]
*
+ * See UrlCreateFromPathW
+ */
+HRESULT WINAPI UrlCreateFromPathA(LPCSTR pszPath, LPSTR pszUrl, LPDWORD pcchUrl, DWORD dwReserved)
+{
+ WCHAR bufW[INTERNET_MAX_URL_LENGTH];
[truncated at 1000 lines; 278 more skipped]
reactos/lib/shlwapi
diff -u -r1.7 -r1.8
--- winehq2ros.patch 20 Aug 2004 06:58:58 -0000 1.7
+++ winehq2ros.patch 20 Oct 2004 16:49:27 -0000 1.8
@@ -1,25 +1,160 @@
+Index: ordinal.c
+===================================================================
+RCS file: /home/wine/wine/dlls/shlwapi/ordinal.c,v
+retrieving revision 1.98
+diff -u -r1.98 ordinal.c
+--- ordinal.c 25 Sep 2004 00:29:30 -0000 1.98
++++ ordinal.c 20 Oct 2004 16:50:41 -0000
+@@ -1549,16 +1549,17 @@
+ LPVOID *p2) /* [out] ptr for call results */
+ {
+ DWORD ret, aa;
++ IUnknown *iobjectwithsite;
+
+ if (!p1) return E_FAIL;
+
+ /* see if SetSite interface exists for IObjectWithSite object */
+- ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id1, (LPVOID *)&p1);
+- TRACE("first IU_QI ret=%08lx, p1=%p\n", ret, p1);
++ ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id1, (LPVOID *)&iobjectwithsite);
++ TRACE("first IU_QI ret=%08lx, iobjectwithsite=%p\n", ret, iobjectwithsite);
+ if (ret) {
+
+ /* see if GetClassId interface exists for IPersistMoniker object */
+- ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id2, (LPVOID *)&aa);
++ ret = IUnknown_QueryInterface(p1, (REFIID)id2, (LPVOID *)&aa);
+ TRACE("second IU_QI ret=%08lx, aa=%08lx\n", ret, aa);
+ if (ret) return ret;
+
+@@ -1570,10 +1571,10 @@
+ }
+ else {
+ /* fake a SetSite call */
+- ret = IOleWindow_GetWindow((IOleWindow *)p1, (HWND*)p2);
++ ret = IOleWindow_GetWindow((IOleWindow *)iobjectwithsite, (HWND*)p2);
+ TRACE("first IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
+ *(LPDWORD)p2);
+- IUnknown_Release((IUnknown *)p1);
++ IUnknown_Release((IUnknown *)iobjectwithsite);
+ }
+ return ret;
+ }
Index: path.c
===================================================================
RCS file: /home/wine/wine/dlls/shlwapi/path.c,v
-retrieving revision 1.42
-diff -u -r1.42 path.c
---- path.c 20 Apr 2004 00:34:52 -0000 1.42
-+++ path.c 20 Aug 2004 07:09:34 -0000
-@@ -32,6 +32,7 @@
- #include "wingdi.h"
- #include "winuser.h"
- #include "winreg.h"
-+#include "winnls.h"
- #define NO_SHLWAPI_STREAM
- #include "shlwapi.h"
- #include "wine/debug.h"
+retrieving revision 1.48
+diff -u -r1.48 path.c
+--- path.c 5 Oct 2004 18:07:14 -0000 1.48
++++ path.c 20 Oct 2004 16:50:42 -0000
+@@ -3989,3 +3989,101 @@
+ return S_OK;
+ return E_FAIL;
+ }
++
++#define PATH_CHAR_CLASS_LETTER 0x0001
++#define PATH_CHAR_CLASS_ASTERIX 0x0002
++#define PATH_CHAR_CLASS_DOT 0x0004
++#define PATH_CHAR_CLASS_BACKSLASH 0x0008
++#define PATH_CHAR_CLASS_COLON 0x0010
++#define PATH_CHAR_CLASS_SEMICOLON 0x0020
++#define PATH_CHAR_CLASS_COMMA 0x0040
++#define PATH_CHAR_CLASS_SPACE 0x0080
++#define PATH_CHAR_CLASS_OTHER_VALID 0x0100
++#define PATH_CHAR_CLASS_DOUBLEQUOTE 0x0200
++
++/*************************************************************************
++ * PathIsValidCharAW [internal]
++ *
++ * Check if a char is of a certain class
++ */
++static BOOL WINAPI PathIsValidCharAW(unsigned Ch, DWORD Class)
++{
++ static struct
++ {
++ char Ch;
++ DWORD Class;
++ } CharClass[] =
++ {
++ { ' ', PATH_CHAR_CLASS_SPACE },
++ { '!', PATH_CHAR_CLASS_OTHER_VALID },
++ { '"', PATH_CHAR_CLASS_DOUBLEQUOTE },
++ { '#', PATH_CHAR_CLASS_OTHER_VALID },
++ { '$', PATH_CHAR_CLASS_OTHER_VALID },
++ { '%', PATH_CHAR_CLASS_OTHER_VALID },
++ { '&', PATH_CHAR_CLASS_OTHER_VALID },
++ { '\'', PATH_CHAR_CLASS_OTHER_VALID },
++ { '(', PATH_CHAR_CLASS_OTHER_VALID },
++ { ')', PATH_CHAR_CLASS_OTHER_VALID },
++ { '*', PATH_CHAR_CLASS_ASTERIX },
++ { '+', PATH_CHAR_CLASS_OTHER_VALID },
++ { ',', PATH_CHAR_CLASS_COMMA },
++ { '-', PATH_CHAR_CLASS_OTHER_VALID },
++ { '.', PATH_CHAR_CLASS_DOT },
++ { ':', PATH_CHAR_CLASS_COLON },
++ { ';', PATH_CHAR_CLASS_SEMICOLON },
++ { '=', PATH_CHAR_CLASS_OTHER_VALID },
++ { '?', PATH_CHAR_CLASS_LETTER },
++ { '@', PATH_CHAR_CLASS_OTHER_VALID },
++ { '[', PATH_CHAR_CLASS_OTHER_VALID },
++ { '\\', PATH_CHAR_CLASS_BACKSLASH },
++ { ']', PATH_CHAR_CLASS_OTHER_VALID },
++ { '^', PATH_CHAR_CLASS_OTHER_VALID },
++ { '_', PATH_CHAR_CLASS_OTHER_VALID },
++ { '`', PATH_CHAR_CLASS_OTHER_VALID },
++ { '{', PATH_CHAR_CLASS_OTHER_VALID },
++ { '}', PATH_CHAR_CLASS_OTHER_VALID },
++ { '~', PATH_CHAR_CLASS_OTHER_VALID },
++ { 0x7f, PATH_CHAR_CLASS_OTHER_VALID }
++ };
++ unsigned Index;
++
++ if (('A' <= Ch && Ch <= 'Z') || ('a' <= Ch && Ch <= 'z'))
++ {
++ return (Class & PATH_CHAR_CLASS_LETTER);
++ }
++
++ if (('0' <= Ch && Ch <= '9') || 0x80 <= Ch)
++ {
++ return (Class & PATH_CHAR_CLASS_OTHER_VALID);
++ }
++
++ for (Index = 0; Index < sizeof(CharClass) / sizeof(CharClass[0]); Index++)
++ {
++ if (Ch == CharClass[Index].Ch)
++ {
++ return (Class & CharClass[Index].Class);
++ }
++ }
++
++ return FALSE;
++}
++
++/*************************************************************************
++ * @ [SHLWAPI.455]
++ *
++ * Check if an Ascii char is of a certain class
++ */
++BOOL WINAPI PathIsValidCharA(char Ch, DWORD Class)
++{
++ return PathIsValidCharAW((unsigned) Ch, Class);
++}
++
++/*************************************************************************
++ * @ [SHLWAPI.456]
++ *
++ * Check if an Unicode char is of a certain class
++ */
++BOOL WINAPI PathIsValidCharW(WCHAR Ch, DWORD Class)
++{
++ return PathIsValidCharAW((unsigned) Ch, Class);
++}
Index: shlwapi.spec
===================================================================
RCS file: /home/wine/wine/dlls/shlwapi/shlwapi.spec,v
-retrieving revision 1.93
-diff -u -r1.93 shlwapi.spec
---- shlwapi.spec 19 Jul 2004 19:32:51 -0000 1.93
-+++ shlwapi.spec 20 Aug 2004 07:09:34 -0000
+retrieving revision 1.96
+diff -u -r1.96 shlwapi.spec
+--- shlwapi.spec 25 Sep 2004 00:29:30 -0000 1.96
++++ shlwapi.spec 20 Oct 2004 16:50:42 -0000
@@ -368,9 +368,9 @@
368 stdcall @(wstr wstr ptr long wstr) kernel32.GetPrivateProfileStructW
369 stdcall @(wstr wstr ptr ptr long long ptr wstr ptr ptr) kernel32.CreateProcessW
@@ -42,24 +177,30 @@
393 stdcall @(long ptr long ptr long) user32.CreateDialogIndirectParamW
394 stdcall @(long ptr long ptr long) user32.CreateDialogIndirectParamA
395 stub -noname MLWinHelpA
-@@ -456,8 +456,8 @@
- 456 stub -noname PathIsValidCharW
+@@ -452,12 +452,12 @@
+ 452 stub -noname CharUpperNoDBCSW
+ 453 stub -noname CharLowerNoDBCSA
+ 454 stub -noname CharLowerNoDBCSW
+-455 stub -noname PathIsValidCharA
+-456 stub -noname PathIsValidCharW
++455 stdcall -noname PathIsValidCharA(long long)
++456 stdcall -noname PathIsValidCharW(long long)
457 stub -noname GetLongPathNameWrapW
458 stub -noname GetLongPathNameWrapA
-459 stdcall -noname SHExpandEnvironmentStringsA(str ptr long) kernel32.ExpandEnvironmentStringsA
-460 stdcall -noname SHExpandEnvironmentStringsW(wstr ptr long) kernel32.ExpandEnvironmentStringsW
+459 stdcall SHExpandEnvironmentStringsA(str ptr long) kernel32.ExpandEnvironmentStringsA
+460 stdcall SHExpandEnvironmentStringsW(wstr ptr long) kernel32.ExpandEnvironmentStringsW
- 461 stdcall -noname SHGetAppCompatFlags()
+ 461 stdcall -noname SHGetAppCompatFlags(long)
462 stub -noname UrlFixupW
463 stub -noname SHExpandEnvironmentStringsForUserA
Index: string.c
===================================================================
RCS file: /home/wine/wine/dlls/shlwapi/string.c,v
-retrieving revision 1.47
-diff -u -r1.47 string.c
---- string.c 21 Jul 2004 03:12:16 -0000 1.47
-+++ string.c 20 Aug 2004 07:09:35 -0000
+retrieving revision 1.49
+diff -u -r1.49 string.c
+--- string.c 13 Sep 2004 18:11:56 -0000 1.49
++++ string.c 20 Oct 2004 16:50:43 -0000
@@ -528,7 +528,7 @@
{
TRACE("(%s,%s)\n", debugstr_w(lpszStr), debugstr_w(lpszSearch));
@@ -81,11 +222,11 @@
Index: url.c
===================================================================
RCS file: /home/wine/wine/dlls/shlwapi/url.c,v
-retrieving revision 1.35
-diff -u -r1.35 url.c
---- url.c 4 Jul 2004 00:06:29 -0000 1.35
-+++ url.c 20 Aug 2004 07:09:36 -0000
-@@ -1386,8 +1386,8 @@
+retrieving revision 1.43
+diff -u -r1.43 url.c
+--- url.c 5 Oct 2004 18:31:41 -0000 1.43
++++ url.c 20 Oct 2004 16:50:44 -0000
+@@ -1347,8 +1347,8 @@
* Success: TRUE. lpDest is filled with the computed hash value.
* Failure: FALSE, if any argument is invalid.
*/