Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
3dc7bf3f
Commit
3dc7bf3f
authored
May 23, 2019
by
Nikolay Sivov
Committed by
Alexandre Julliard
May 23, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
kernelbase: Add more URL API functions from shlwapi.
Signed-off-by:
Nikolay Sivov
<
nsivov@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
c77ba713
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
856 additions
and
18 deletions
+856
-18
Makefile.in
dlls/kernelbase/Makefile.in
+1
-1
kernelbase.spec
dlls/kernelbase/kernelbase.spec
+17
-17
path.c
dlls/kernelbase/path.c
+838
-0
No files found.
dlls/kernelbase/Makefile.in
View file @
3dc7bf3f
MODULE
=
kernelbase.dll
IMPORTS
=
uuid
IMPORTS
=
uuid
advapi32
C_SRCS
=
\
main.c
\
...
...
dlls/kernelbase/kernelbase.spec
View file @
3dc7bf3f
...
...
@@ -1628,31 +1628,31 @@
# @ stub UpdatePackageStatus
# @ stub UpdatePackageStatusForUser
@ stdcall UpdateProcThreadAttribute(ptr long long ptr long ptr ptr) kernel32.UpdateProcThreadAttribute
@ stdcall UrlApplySchemeA(str ptr ptr long)
shlwapi.UrlApplySchemeA
@ stdcall UrlApplySchemeW(wstr ptr ptr long)
shlwapi.UrlApplySchemeW
@ stdcall UrlApplySchemeA(str ptr ptr long)
@ stdcall UrlApplySchemeW(wstr ptr ptr long)
@ stdcall UrlCanonicalizeA(str ptr ptr long)
@ stdcall UrlCanonicalizeW(wstr ptr ptr long)
@ stdcall UrlCombineA(str str ptr ptr long) shlwapi.UrlCombineA
@ stdcall UrlCombineW(wstr wstr ptr ptr long) shlwapi.UrlCombineW
@ stdcall UrlCompareA(str str long)
shlwapi.UrlCompareA
@ stdcall UrlCompareW(wstr wstr long)
shlwapi.UrlCompareW
@ stdcall UrlCreateFromPathA(str ptr ptr long)
shlwapi.UrlCreateFromPathA
@ stdcall UrlCreateFromPathW(wstr ptr ptr long)
shlwapi.UrlCreateFromPathW
@ stdcall UrlCompareA(str str long)
@ stdcall UrlCompareW(wstr wstr long)
@ stdcall UrlCreateFromPathA(str ptr ptr long)
@ stdcall UrlCreateFromPathW(wstr ptr ptr long)
@ stdcall UrlEscapeA(str ptr ptr long)
@ stdcall UrlEscapeW(wstr ptr ptr long)
@ stdcall UrlFixupW(wstr wstr long)
shlwapi.UrlFixupW
@ stdcall UrlGetLocationA(str)
shlwapi.UrlGetLocationA
@ stdcall UrlGetLocationW(wstr)
shlwapi.UrlGetLocationW
@ stdcall UrlGetPartA(str ptr ptr long long)
shlwapi.UrlGetPartA
@ stdcall UrlGetPartW(wstr ptr ptr long long)
shlwapi.UrlGetPartW
@ stdcall UrlFixupW(wstr wstr long)
@ stdcall UrlGetLocationA(str)
@ stdcall UrlGetLocationW(wstr)
@ stdcall UrlGetPartA(str ptr ptr long long)
@ stdcall UrlGetPartW(wstr ptr ptr long long)
@ stdcall UrlHashA(str ptr long) shlwapi.UrlHashA
@ stdcall UrlHashW(wstr ptr long) shlwapi.UrlHashW
@ stdcall UrlIsA(str long)
shlwapi.UrlIsA
@ stdcall UrlIsNoHistoryA(str)
shlwapi.UrlIsNoHistoryA
@ stdcall UrlIsNoHistoryW(wstr)
shlwapi.UrlIsNoHistoryW
@ stdcall UrlIsOpaqueA(str)
shlwapi.UrlIsOpaqueA
@ stdcall UrlIsOpaqueW(wstr)
shlwapi.UrlIsOpaqueW
@ stdcall UrlIsW(wstr long)
shlwapi.UrlIsW
@ stdcall UrlIsA(str long)
@ stdcall UrlIsNoHistoryA(str)
@ stdcall UrlIsNoHistoryW(wstr)
@ stdcall UrlIsOpaqueA(str)
@ stdcall UrlIsOpaqueW(wstr)
@ stdcall UrlIsW(wstr long)
@ stdcall UrlUnescapeA(str ptr ptr long)
@ stdcall UrlUnescapeW(wstr ptr ptr long)
@ stdcall VerFindFileA(long str str str ptr ptr ptr ptr) version.VerFindFileA
...
...
dlls/kernelbase/path.c
View file @
3dc7bf3f
...
...
@@ -36,6 +36,30 @@ WINE_DEFAULT_DEBUG_CHANNEL(path);
static
const
char
hexDigits
[]
=
"0123456789ABCDEF"
;
struct
parsed_url
{
const
WCHAR
*
scheme
;
/* [out] start of scheme */
DWORD
scheme_len
;
/* [out] size of scheme (until colon) */
const
WCHAR
*
username
;
/* [out] start of Username */
DWORD
username_len
;
/* [out] size of Username (until ":" or "@") */
const
WCHAR
*
password
;
/* [out] start of Password */
DWORD
password_len
;
/* [out] size of Password (until "@") */
const
WCHAR
*
hostname
;
/* [out] start of Hostname */
DWORD
hostname_len
;
/* [out] size of Hostname (until ":" or "/") */
const
WCHAR
*
port
;
/* [out] start of Port */
DWORD
port_len
;
/* [out] size of Port (until "/" or eos) */
const
WCHAR
*
query
;
/* [out] start of Query */
DWORD
query_len
;
/* [out] size of Query (until eos) */
};
enum
url_scan_type
{
SCHEME
,
HOST
,
PORT
,
USERPASS
,
};
static
WCHAR
*
heap_strdupAtoW
(
const
char
*
str
)
{
WCHAR
*
ret
=
NULL
;
...
...
@@ -3724,3 +3748,817 @@ HRESULT WINAPI UrlCanonicalizeW(const WCHAR *src_url, WCHAR *canonicalized, DWOR
return
hr
;
}
HRESULT
WINAPI
UrlApplySchemeA
(
const
char
*
url
,
char
*
out
,
DWORD
*
out_len
,
DWORD
flags
)
{
LPWSTR
inW
,
outW
;
HRESULT
hr
;
DWORD
len
;
TRACE
(
"%s, %p, %p:out size %d, %#x
\n
"
,
wine_dbgstr_a
(
url
),
out
,
out_len
,
out_len
?
*
out_len
:
0
,
flags
);
if
(
!
url
||
!
out
||
!
out_len
)
return
E_INVALIDARG
;
inW
=
heap_alloc
(
2
*
INTERNET_MAX_URL_LENGTH
*
sizeof
(
WCHAR
));
outW
=
inW
+
INTERNET_MAX_URL_LENGTH
;
MultiByteToWideChar
(
CP_ACP
,
0
,
url
,
-
1
,
inW
,
INTERNET_MAX_URL_LENGTH
);
len
=
INTERNET_MAX_URL_LENGTH
;
hr
=
UrlApplySchemeW
(
inW
,
outW
,
&
len
,
flags
);
if
(
hr
!=
S_OK
)
{
heap_free
(
inW
);
return
hr
;
}
len
=
WideCharToMultiByte
(
CP_ACP
,
0
,
outW
,
-
1
,
NULL
,
0
,
NULL
,
NULL
);
if
(
len
>
*
out_len
)
{
hr
=
E_POINTER
;
goto
cleanup
;
}
WideCharToMultiByte
(
CP_ACP
,
0
,
outW
,
-
1
,
out
,
*
out_len
,
NULL
,
NULL
);
len
--
;
cleanup:
*
out_len
=
len
;
heap_free
(
inW
);
return
hr
;
}
static
HRESULT
url_guess_scheme
(
const
WCHAR
*
url
,
WCHAR
*
out
,
DWORD
*
out_len
)
{
WCHAR
reg_path
[
MAX_PATH
],
value
[
MAX_PATH
],
data
[
MAX_PATH
];
DWORD
value_len
,
data_len
,
dwType
,
i
;
WCHAR
Wxx
,
Wyy
;
HKEY
newkey
;
INT
index
;
BOOL
j
;
MultiByteToWideChar
(
CP_ACP
,
0
,
"Software
\\
Microsoft
\\
Windows
\\
CurrentVersion
\\
URL
\\
Prefixes"
,
1
,
reg_path
,
MAX_PATH
);
RegOpenKeyExW
(
HKEY_LOCAL_MACHINE
,
reg_path
,
0
,
1
,
&
newkey
);
index
=
0
;
while
(
value_len
=
data_len
=
MAX_PATH
,
RegEnumValueW
(
newkey
,
index
,
value
,
&
value_len
,
0
,
&
dwType
,
(
LPVOID
)
data
,
&
data_len
)
==
0
)
{
TRACE
(
"guess %d %s is %s
\n
"
,
index
,
wine_dbgstr_w
(
value
),
wine_dbgstr_w
(
data
));
j
=
FALSE
;
for
(
i
=
0
;
i
<
value_len
;
++
i
)
{
Wxx
=
url
[
i
];
Wyy
=
value
[
i
];
/* remember that TRUE is not-equal */
j
=
ChrCmpIW
(
Wxx
,
Wyy
);
if
(
j
)
break
;
}
if
((
i
==
value_len
)
&&
!
j
)
{
if
(
strlenW
(
data
)
+
strlenW
(
url
)
+
1
>
*
out_len
)
{
*
out_len
=
strlenW
(
data
)
+
strlenW
(
url
)
+
1
;
RegCloseKey
(
newkey
);
return
E_POINTER
;
}
strcpyW
(
out
,
data
);
strcatW
(
out
,
url
);
*
out_len
=
strlenW
(
out
);
TRACE
(
"matched and set to %s
\n
"
,
wine_dbgstr_w
(
out
));
RegCloseKey
(
newkey
);
return
S_OK
;
}
index
++
;
}
RegCloseKey
(
newkey
);
return
E_FAIL
;
}
static
HRESULT
url_create_from_path
(
const
WCHAR
*
path
,
WCHAR
*
url
,
DWORD
*
url_len
)
{
static
const
WCHAR
file_colonW
[]
=
{
'f'
,
'i'
,
'l'
,
'e'
,
':'
,
0
};
static
const
WCHAR
three_slashesW
[]
=
{
'/'
,
'/'
,
'/'
,
0
};
PARSEDURLW
parsed_url
;
WCHAR
*
new_url
;
DWORD
needed
;
HRESULT
hr
;
parsed_url
.
cbSize
=
sizeof
(
parsed_url
);
if
(
ParseURLW
(
path
,
&
parsed_url
)
==
S_OK
)
{
if
(
parsed_url
.
nScheme
!=
URL_SCHEME_INVALID
&&
parsed_url
.
cchProtocol
>
1
)
{
needed
=
strlenW
(
path
);
if
(
needed
>=
*
url_len
)
{
*
url_len
=
needed
+
1
;
return
E_POINTER
;
}
else
{
*
url_len
=
needed
;
return
S_FALSE
;
}
}
}
new_url
=
heap_alloc
((
strlenW
(
path
)
+
9
)
*
sizeof
(
WCHAR
));
/* "file:///" + path length + 1 */
strcpyW
(
new_url
,
file_colonW
);
if
(
isalphaW
(
path
[
0
])
&&
path
[
1
]
==
':'
)
strcatW
(
new_url
,
three_slashesW
);
strcatW
(
new_url
,
path
);
hr
=
UrlEscapeW
(
new_url
,
url
,
url_len
,
URL_ESCAPE_PERCENT
);
heap_free
(
new_url
);
return
hr
;
}
static
HRESULT
url_apply_default_scheme
(
const
WCHAR
*
url
,
WCHAR
*
out
,
DWORD
*
length
)
{
static
const
WCHAR
prefix_keyW
[]
=
{
'S'
,
'o'
,
'f'
,
't'
,
'w'
,
'a'
,
'r'
,
'e'
,
'\\'
,
'M'
,
'i'
,
'c'
,
'r'
,
'o'
,
's'
,
'o'
,
'f'
,
't'
,
'\\'
,
'W'
,
'i'
,
'n'
,
'd'
,
'o'
,
'w'
,
's'
,
'\\'
,
'C'
,
'u'
,
'r'
,
'r'
,
'e'
,
'n'
,
't'
,
'V'
,
'e'
,
'r'
,
's'
,
'i'
,
'o'
,
'n'
,
'\\'
,
'U'
,
'R'
,
'L'
,
'\\'
,
'D'
,
'e'
,
'f'
,
'a'
,
'u'
,
'l'
,
't'
,
'P'
,
'r'
,
'e'
,
'f'
,
'i'
,
'x'
,
0
};
DWORD
data_len
,
dwType
;
WCHAR
data
[
MAX_PATH
];
HKEY
newkey
;
/* get and prepend default */
RegOpenKeyExW
(
HKEY_LOCAL_MACHINE
,
prefix_keyW
,
0
,
1
,
&
newkey
);
data_len
=
sizeof
(
data
);
RegQueryValueExW
(
newkey
,
NULL
,
0
,
&
dwType
,
(
BYTE
*
)
data
,
&
data_len
);
RegCloseKey
(
newkey
);
if
(
strlenW
(
data
)
+
strlenW
(
url
)
+
1
>
*
length
)
{
*
length
=
strlenW
(
data
)
+
strlenW
(
url
)
+
1
;
return
E_POINTER
;
}
strcpyW
(
out
,
data
);
strcatW
(
out
,
url
);
*
length
=
strlenW
(
out
);
TRACE
(
"used default %s
\n
"
,
wine_dbgstr_w
(
out
));
return
S_OK
;
}
HRESULT
WINAPI
UrlApplySchemeW
(
const
WCHAR
*
url
,
WCHAR
*
out
,
DWORD
*
length
,
DWORD
flags
)
{
PARSEDURLW
in_scheme
;
DWORD
res1
;
HRESULT
hr
;
TRACE
(
"%s, %p, %p:out size %d, %#x
\n
"
,
wine_dbgstr_w
(
url
),
out
,
length
,
length
?
*
length
:
0
,
flags
);
if
(
!
url
||
!
out
||
!
length
)
return
E_INVALIDARG
;
if
(
flags
&
URL_APPLY_GUESSFILE
)
{
if
(
*
length
>
1
&&
':'
==
url
[
1
])
{
res1
=
*
length
;
hr
=
url_create_from_path
(
url
,
out
,
&
res1
);
if
(
hr
==
S_OK
||
hr
==
E_POINTER
)
{
*
length
=
res1
;
return
hr
;
}
else
if
(
hr
==
S_FALSE
)
{
return
hr
;
}
}
}
in_scheme
.
cbSize
=
sizeof
(
in_scheme
);
/* See if the base has a scheme */
res1
=
ParseURLW
(
url
,
&
in_scheme
);
if
(
res1
)
{
/* no scheme in input, need to see if we need to guess */
if
(
flags
&
URL_APPLY_GUESSSCHEME
)
{
if
((
hr
=
url_guess_scheme
(
url
,
out
,
length
))
!=
E_FAIL
)
return
hr
;
}
}
/* If we are here, then either invalid scheme,
* or no scheme and can't/failed guess.
*/
if
((((
res1
==
0
)
&&
(
flags
&
URL_APPLY_FORCEAPPLY
))
||
((
res1
!=
0
))
)
&&
(
flags
&
URL_APPLY_DEFAULT
))
return
url_apply_default_scheme
(
url
,
out
,
length
);
return
S_FALSE
;
}
INT
WINAPI
UrlCompareA
(
const
char
*
url1
,
const
char
*
url2
,
BOOL
ignore_slash
)
{
INT
ret
,
len
,
len1
,
len2
;
if
(
!
ignore_slash
)
return
strcmp
(
url1
,
url2
);
len1
=
strlen
(
url1
);
if
(
url1
[
len1
-
1
]
==
'/'
)
len1
--
;
len2
=
strlen
(
url2
);
if
(
url2
[
len2
-
1
]
==
'/'
)
len2
--
;
if
(
len1
==
len2
)
return
strncmp
(
url1
,
url2
,
len1
);
len
=
min
(
len1
,
len2
);
ret
=
strncmp
(
url1
,
url2
,
len
);
if
(
ret
)
return
ret
;
if
(
len1
>
len2
)
return
1
;
return
-
1
;
}
INT
WINAPI
UrlCompareW
(
const
WCHAR
*
url1
,
const
WCHAR
*
url2
,
BOOL
ignore_slash
)
{
size_t
len
,
len1
,
len2
;
INT
ret
;
if
(
!
ignore_slash
)
return
strcmpW
(
url1
,
url2
);
len1
=
strlenW
(
url1
);
if
(
url1
[
len1
-
1
]
==
'/'
)
len1
--
;
len2
=
strlenW
(
url2
);
if
(
url2
[
len2
-
1
]
==
'/'
)
len2
--
;
if
(
len1
==
len2
)
return
strncmpW
(
url1
,
url2
,
len1
);
len
=
min
(
len1
,
len2
);
ret
=
strncmpW
(
url1
,
url2
,
len
);
if
(
ret
)
return
ret
;
if
(
len1
>
len2
)
return
1
;
return
-
1
;
}
HRESULT
WINAPI
UrlFixupW
(
const
WCHAR
*
url
,
WCHAR
*
translatedUrl
,
DWORD
maxChars
)
{
DWORD
srcLen
;
FIXME
(
"%s, %p, %d stub
\n
"
,
wine_dbgstr_w
(
url
),
translatedUrl
,
maxChars
);
if
(
!
url
)
return
E_FAIL
;
srcLen
=
lstrlenW
(
url
)
+
1
;
/* For now just copy the URL directly */
lstrcpynW
(
translatedUrl
,
url
,
(
maxChars
<
srcLen
)
?
maxChars
:
srcLen
);
return
S_OK
;
}
const
char
*
WINAPI
UrlGetLocationA
(
const
char
*
url
)
{
PARSEDURLA
base
;
base
.
cbSize
=
sizeof
(
base
);
if
(
ParseURLA
(
url
,
&
base
)
!=
S_OK
)
return
NULL
;
/* invalid scheme */
/* if scheme is file: then never return pointer */
if
(
!
strncmp
(
base
.
pszProtocol
,
"file"
,
min
(
4
,
base
.
cchProtocol
)))
return
NULL
;
/* Look for '#' and return its addr */
return
strchr
(
base
.
pszSuffix
,
'#'
);
}
const
WCHAR
*
WINAPI
UrlGetLocationW
(
const
WCHAR
*
url
)
{
static
const
WCHAR
fileW
[]
=
{
'f'
,
'i'
,
'l'
,
'e'
,
'\0'
};
PARSEDURLW
base
;
base
.
cbSize
=
sizeof
(
base
);
if
(
ParseURLW
(
url
,
&
base
)
!=
S_OK
)
return
NULL
;
/* invalid scheme */
/* if scheme is file: then never return pointer */
if
(
!
strncmpW
(
base
.
pszProtocol
,
fileW
,
min
(
4
,
base
.
cchProtocol
)))
return
NULL
;
/* Look for '#' and return its addr */
return
strchrW
(
base
.
pszSuffix
,
'#'
);
}
HRESULT
WINAPI
UrlGetPartA
(
const
char
*
url
,
char
*
out
,
DWORD
*
out_len
,
DWORD
part
,
DWORD
flags
)
{
LPWSTR
inW
,
outW
;
DWORD
len
,
len2
;
HRESULT
hr
;
if
(
!
url
||
!
out
||
!
out_len
||
!*
out_len
)
return
E_INVALIDARG
;
inW
=
heap_alloc
(
2
*
INTERNET_MAX_URL_LENGTH
*
sizeof
(
WCHAR
));
outW
=
inW
+
INTERNET_MAX_URL_LENGTH
;
MultiByteToWideChar
(
CP_ACP
,
0
,
url
,
-
1
,
inW
,
INTERNET_MAX_URL_LENGTH
);
len
=
INTERNET_MAX_URL_LENGTH
;
hr
=
UrlGetPartW
(
inW
,
outW
,
&
len
,
part
,
flags
);
if
(
FAILED
(
hr
))
{
heap_free
(
inW
);
return
hr
;
}
len2
=
WideCharToMultiByte
(
CP_ACP
,
0
,
outW
,
len
,
NULL
,
0
,
NULL
,
NULL
);
if
(
len2
>
*
out_len
)
{
*
out_len
=
len2
+
1
;
heap_free
(
inW
);
return
E_POINTER
;
}
len2
=
WideCharToMultiByte
(
CP_ACP
,
0
,
outW
,
len
+
1
,
out
,
*
out_len
,
NULL
,
NULL
);
*
out_len
=
len2
-
1
;
heap_free
(
inW
);
return
hr
;
}
static
const
WCHAR
*
scan_url
(
const
WCHAR
*
start
,
DWORD
*
size
,
enum
url_scan_type
type
)
{
static
DWORD
alwayszero
=
0
;
BOOL
cont
=
TRUE
;
*
size
=
0
;
switch
(
type
)
{
case
SCHEME
:
while
(
cont
)
{
if
((
islowerW
(
*
start
)
&&
isalphaW
(
*
start
))
||
isdigitW
(
*
start
)
||
*
start
==
'+'
||
*
start
==
'-'
||
*
start
==
'.'
)
{
start
++
;
(
*
size
)
++
;
}
else
cont
=
FALSE
;
}
if
(
*
start
!=
':'
)
*
size
=
0
;
break
;
case
USERPASS
:
while
(
cont
)
{
if
(
isalphaW
(
*
start
)
||
isdigitW
(
*
start
)
||
/* user/password only characters */
(
*
start
==
';'
)
||
(
*
start
==
'?'
)
||
(
*
start
==
'&'
)
||
(
*
start
==
'='
)
||
/* *extra* characters */
(
*
start
==
'!'
)
||
(
*
start
==
'*'
)
||
(
*
start
==
'\''
)
||
(
*
start
==
'('
)
||
(
*
start
==
')'
)
||
(
*
start
==
','
)
||
/* *safe* characters */
(
*
start
==
'$'
)
||
(
*
start
==
'_'
)
||
(
*
start
==
'+'
)
||
(
*
start
==
'-'
)
||
(
*
start
==
'.'
)
||
(
*
start
==
' '
))
{
start
++
;
(
*
size
)
++
;
}
else
if
(
*
start
==
'%'
)
{
if
(
isxdigitW
(
*
(
start
+
1
))
&&
isxdigitW
(
*
(
start
+
2
)))
{
start
+=
3
;
*
size
+=
3
;
}
else
cont
=
FALSE
;
}
else
cont
=
FALSE
;
}
break
;
case
PORT
:
while
(
cont
)
{
if
(
isdigitW
(
*
start
))
{
start
++
;
(
*
size
)
++
;
}
else
cont
=
FALSE
;
}
break
;
case
HOST
:
while
(
cont
)
{
if
(
isalnumW
(
*
start
)
||
*
start
==
'-'
||
*
start
==
'.'
||
*
start
==
' '
||
*
start
==
'*'
)
{
start
++
;
(
*
size
)
++
;
}
else
cont
=
FALSE
;
}
break
;
default:
FIXME
(
"unknown type %d
\n
"
,
type
);
return
(
LPWSTR
)
&
alwayszero
;
}
return
start
;
}
static
LONG
parse_url
(
const
WCHAR
*
url
,
struct
parsed_url
*
pl
)
{
const
WCHAR
*
work
;
memset
(
pl
,
0
,
sizeof
(
*
pl
));
pl
->
scheme
=
url
;
work
=
scan_url
(
pl
->
scheme
,
&
pl
->
scheme_len
,
SCHEME
);
if
(
!*
work
||
(
*
work
!=
':'
))
goto
ErrorExit
;
work
++
;
if
((
*
work
!=
'/'
)
||
(
*
(
work
+
1
)
!=
'/'
))
goto
SuccessExit
;
pl
->
username
=
work
+
2
;
work
=
scan_url
(
pl
->
username
,
&
pl
->
username_len
,
USERPASS
);
if
(
*
work
==
':'
)
{
/* parse password */
work
++
;
pl
->
password
=
work
;
work
=
scan_url
(
pl
->
password
,
&
pl
->
password_len
,
USERPASS
);
if
(
*
work
!=
'@'
)
{
/* what we just parsed must be the hostname and port
* so reset pointers and clear then let it parse */
pl
->
username_len
=
pl
->
password_len
=
0
;
work
=
pl
->
username
-
1
;
pl
->
username
=
pl
->
password
=
0
;
}
}
else
if
(
*
work
==
'@'
)
{
/* no password */
pl
->
password_len
=
0
;
pl
->
password
=
0
;
}
else
if
(
!*
work
||
*
work
==
'/'
||
*
work
==
'.'
)
{
/* what was parsed was hostname, so reset pointers and let it parse */
pl
->
username_len
=
pl
->
password_len
=
0
;
work
=
pl
->
username
-
1
;
pl
->
username
=
pl
->
password
=
0
;
}
else
goto
ErrorExit
;
/* now start parsing hostname or hostnumber */
work
++
;
pl
->
hostname
=
work
;
work
=
scan_url
(
pl
->
hostname
,
&
pl
->
hostname_len
,
HOST
);
if
(
*
work
==
':'
)
{
/* parse port */
work
++
;
pl
->
port
=
work
;
work
=
scan_url
(
pl
->
port
,
&
pl
->
port_len
,
PORT
);
}
if
(
*
work
==
'/'
)
{
/* see if query string */
pl
->
query
=
strchrW
(
work
,
'?'
);
if
(
pl
->
query
)
pl
->
query_len
=
strlenW
(
pl
->
query
);
}
SuccessExit:
TRACE
(
"parse successful: scheme=%p(%d), user=%p(%d), pass=%p(%d), host=%p(%d), port=%p(%d), query=%p(%d)
\n
"
,
pl
->
scheme
,
pl
->
scheme_len
,
pl
->
username
,
pl
->
username_len
,
pl
->
password
,
pl
->
password_len
,
pl
->
hostname
,
pl
->
hostname_len
,
pl
->
port
,
pl
->
port_len
,
pl
->
query
,
pl
->
query_len
);
return
S_OK
;
ErrorExit:
FIXME
(
"failed to parse %s
\n
"
,
debugstr_w
(
url
));
return
E_INVALIDARG
;
}
HRESULT
WINAPI
UrlGetPartW
(
const
WCHAR
*
url
,
WCHAR
*
out
,
DWORD
*
out_len
,
DWORD
part
,
DWORD
flags
)
{
DWORD
scheme
,
size
,
schsize
;
LPCWSTR
addr
,
schaddr
;
struct
parsed_url
pl
;
HRESULT
hr
;
TRACE
(
"%s, %p, %p(%d), %#x, %#x
\n
"
,
wine_dbgstr_w
(
url
),
out
,
out_len
,
*
out_len
,
part
,
flags
);
if
(
!
url
||
!
out
||
!
out_len
||
!*
out_len
)
return
E_INVALIDARG
;
*
out
=
'\0'
;
addr
=
strchrW
(
url
,
':'
);
if
(
!
addr
)
scheme
=
URL_SCHEME_UNKNOWN
;
else
scheme
=
get_scheme_code
(
url
,
addr
-
url
);
hr
=
parse_url
(
url
,
&
pl
);
switch
(
part
)
{
case
URL_PART_SCHEME
:
if
(
!
pl
.
scheme_len
)
{
*
out_len
=
0
;
return
S_FALSE
;
}
addr
=
pl
.
scheme
;
size
=
pl
.
scheme_len
;
break
;
case
URL_PART_HOSTNAME
:
switch
(
scheme
)
{
case
URL_SCHEME_FTP
:
case
URL_SCHEME_HTTP
:
case
URL_SCHEME_GOPHER
:
case
URL_SCHEME_TELNET
:
case
URL_SCHEME_FILE
:
case
URL_SCHEME_HTTPS
:
break
;
default:
*
out_len
=
0
;
return
E_FAIL
;
}
if
(
scheme
==
URL_SCHEME_FILE
&&
(
!
pl
.
hostname_len
||
(
pl
.
hostname_len
==
1
&&
*
(
pl
.
hostname
+
1
)
==
':'
)))
{
*
out_len
=
0
;
return
S_FALSE
;
}
if
(
!
pl
.
hostname_len
)
{
*
out_len
=
0
;
return
S_FALSE
;
}
addr
=
pl
.
hostname
;
size
=
pl
.
hostname_len
;
break
;
case
URL_PART_USERNAME
:
if
(
!
pl
.
username_len
)
{
*
out_len
=
0
;
return
S_FALSE
;
}
addr
=
pl
.
username
;
size
=
pl
.
username_len
;
break
;
case
URL_PART_PASSWORD
:
if
(
!
pl
.
password_len
)
{
*
out_len
=
0
;
return
S_FALSE
;
}
addr
=
pl
.
password
;
size
=
pl
.
password_len
;
break
;
case
URL_PART_PORT
:
if
(
!
pl
.
port_len
)
{
*
out_len
=
0
;
return
S_FALSE
;
}
addr
=
pl
.
port
;
size
=
pl
.
port_len
;
break
;
case
URL_PART_QUERY
:
if
(
!
pl
.
query_len
)
{
*
out_len
=
0
;
return
S_FALSE
;
}
addr
=
pl
.
query
;
size
=
pl
.
query_len
;
break
;
default:
*
out_len
=
0
;
return
E_INVALIDARG
;
}
if
(
flags
==
URL_PARTFLAG_KEEPSCHEME
)
{
if
(
!
pl
.
scheme
||
!
pl
.
scheme_len
)
{
*
out_len
=
0
;
return
E_FAIL
;
}
schaddr
=
pl
.
scheme
;
schsize
=
pl
.
scheme_len
;
if
(
*
out_len
<
schsize
+
size
+
2
)
{
*
out_len
=
schsize
+
size
+
2
;
return
E_POINTER
;
}
memcpy
(
out
,
schaddr
,
schsize
*
sizeof
(
WCHAR
));
out
[
schsize
]
=
':'
;
memcpy
(
out
+
schsize
+
1
,
addr
,
size
*
sizeof
(
WCHAR
));
out
[
schsize
+
1
+
size
]
=
0
;
*
out_len
=
schsize
+
1
+
size
;
}
else
{
if
(
*
out_len
<
size
+
1
)
{
*
out_len
=
size
+
1
;
return
E_POINTER
;
}
memcpy
(
out
,
addr
,
size
*
sizeof
(
WCHAR
));
out
[
size
]
=
0
;
*
out_len
=
size
;
}
TRACE
(
"len=%d %s
\n
"
,
*
out_len
,
wine_dbgstr_w
(
out
));
return
hr
;
}
BOOL
WINAPI
UrlIsA
(
const
char
*
url
,
URLIS
Urlis
)
{
const
char
*
last
;
PARSEDURLA
base
;
TRACE
(
"%s, %d
\n
"
,
debugstr_a
(
url
),
Urlis
);
if
(
!
url
)
return
FALSE
;
switch
(
Urlis
)
{
case
URLIS_OPAQUE
:
base
.
cbSize
=
sizeof
(
base
);
if
(
ParseURLA
(
url
,
&
base
)
!=
S_OK
)
return
FALSE
;
/* invalid scheme */
switch
(
base
.
nScheme
)
{
case
URL_SCHEME_MAILTO
:
case
URL_SCHEME_SHELL
:
case
URL_SCHEME_JAVASCRIPT
:
case
URL_SCHEME_VBSCRIPT
:
case
URL_SCHEME_ABOUT
:
return
TRUE
;
}
return
FALSE
;
case
URLIS_FILEURL
:
return
(
CompareStringA
(
LOCALE_INVARIANT
,
NORM_IGNORECASE
,
url
,
5
,
"file:"
,
5
)
==
CSTR_EQUAL
);
case
URLIS_DIRECTORY
:
last
=
url
+
strlen
(
url
)
-
1
;
return
(
last
>=
url
&&
(
*
last
==
'/'
||
*
last
==
'\\'
));
case
URLIS_URL
:
return
PathIsURLA
(
url
);
case
URLIS_NOHISTORY
:
case
URLIS_APPLIABLE
:
case
URLIS_HASQUERY
:
default:
FIXME
(
"(%s %d): stub
\n
"
,
debugstr_a
(
url
),
Urlis
);
}
return
FALSE
;
}
BOOL
WINAPI
UrlIsW
(
const
WCHAR
*
url
,
URLIS
Urlis
)
{
static
const
WCHAR
file_colon
[]
=
{
'f'
,
'i'
,
'l'
,
'e'
,
':'
,
0
};
const
WCHAR
*
last
;
PARSEDURLW
base
;
TRACE
(
"%s, %d
\n
"
,
debugstr_w
(
url
),
Urlis
);
if
(
!
url
)
return
FALSE
;
switch
(
Urlis
)
{
case
URLIS_OPAQUE
:
base
.
cbSize
=
sizeof
(
base
);
if
(
ParseURLW
(
url
,
&
base
)
!=
S_OK
)
return
FALSE
;
/* invalid scheme */
switch
(
base
.
nScheme
)
{
case
URL_SCHEME_MAILTO
:
case
URL_SCHEME_SHELL
:
case
URL_SCHEME_JAVASCRIPT
:
case
URL_SCHEME_VBSCRIPT
:
case
URL_SCHEME_ABOUT
:
return
TRUE
;
}
return
FALSE
;
case
URLIS_FILEURL
:
return
(
CompareStringW
(
LOCALE_INVARIANT
,
NORM_IGNORECASE
,
url
,
5
,
file_colon
,
5
)
==
CSTR_EQUAL
);
case
URLIS_DIRECTORY
:
last
=
url
+
strlenW
(
url
)
-
1
;
return
(
last
>=
url
&&
(
*
last
==
'/'
||
*
last
==
'\\'
));
case
URLIS_URL
:
return
PathIsURLW
(
url
);
case
URLIS_NOHISTORY
:
case
URLIS_APPLIABLE
:
case
URLIS_HASQUERY
:
default:
FIXME
(
"(%s %d): stub
\n
"
,
debugstr_w
(
url
),
Urlis
);
}
return
FALSE
;
}
BOOL
WINAPI
UrlIsOpaqueA
(
const
char
*
url
)
{
return
UrlIsA
(
url
,
URLIS_OPAQUE
);
}
BOOL
WINAPI
UrlIsOpaqueW
(
const
WCHAR
*
url
)
{
return
UrlIsW
(
url
,
URLIS_OPAQUE
);
}
BOOL
WINAPI
UrlIsNoHistoryA
(
const
char
*
url
)
{
return
UrlIsA
(
url
,
URLIS_NOHISTORY
);
}
BOOL
WINAPI
UrlIsNoHistoryW
(
const
WCHAR
*
url
)
{
return
UrlIsW
(
url
,
URLIS_NOHISTORY
);
}
HRESULT
WINAPI
UrlCreateFromPathA
(
const
char
*
path
,
char
*
url
,
DWORD
*
url_len
,
DWORD
reserved
)
{
WCHAR
bufW
[
INTERNET_MAX_URL_LENGTH
];
DWORD
lenW
=
ARRAY_SIZE
(
bufW
),
lenA
;
UNICODE_STRING
pathW
;
WCHAR
*
urlW
=
bufW
;
HRESULT
hr
;
if
(
!
RtlCreateUnicodeStringFromAsciiz
(
&
pathW
,
path
))
return
E_INVALIDARG
;
if
((
hr
=
UrlCreateFromPathW
(
pathW
.
Buffer
,
urlW
,
&
lenW
,
reserved
))
==
E_POINTER
)
{
urlW
=
heap_alloc
(
lenW
*
sizeof
(
WCHAR
));
hr
=
UrlCreateFromPathW
(
pathW
.
Buffer
,
urlW
,
&
lenW
,
reserved
);
}
if
(
SUCCEEDED
(
hr
))
{
RtlUnicodeToMultiByteSize
(
&
lenA
,
urlW
,
lenW
*
sizeof
(
WCHAR
));
if
(
*
url_len
>
lenA
)
{
RtlUnicodeToMultiByteN
(
url
,
*
url_len
-
1
,
&
lenA
,
urlW
,
lenW
*
sizeof
(
WCHAR
));
url
[
lenA
]
=
0
;
*
url_len
=
lenA
;
}
else
{
*
url_len
=
lenA
+
1
;
hr
=
E_POINTER
;
}
}
if
(
urlW
!=
bufW
)
heap_free
(
urlW
);
RtlFreeUnicodeString
(
&
pathW
);
return
hr
;
}
HRESULT
WINAPI
UrlCreateFromPathW
(
const
WCHAR
*
path
,
WCHAR
*
url
,
DWORD
*
url_len
,
DWORD
reserved
)
{
HRESULT
hr
;
TRACE
(
"%s, %p, %p, %#x
\n
"
,
debugstr_w
(
path
),
url
,
url_len
,
reserved
);
if
(
reserved
||
!
url
||
!
url_len
)
return
E_INVALIDARG
;
hr
=
url_create_from_path
(
path
,
url
,
url_len
);
if
(
hr
==
S_FALSE
)
strcpyW
(
url
,
path
);
return
hr
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment