Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
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-winehq
Commits
57e69a6b
Commit
57e69a6b
authored
May 26, 2016
by
Hans Leidekker
Committed by
Alexandre Julliard
May 26, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
webservices: Implement WsEncodeUrl.
Signed-off-by:
Hans Leidekker
<
hans@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
24bdad63
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
380 additions
and
1 deletion
+380
-1
url.c
dlls/webservices/tests/url.c
+110
-0
url.c
dlls/webservices/url.c
+269
-0
webservices.spec
dlls/webservices/webservices.spec
+1
-1
No files found.
dlls/webservices/tests/url.c
View file @
57e69a6b
...
@@ -188,7 +188,117 @@ static void test_WsDecodeUrl(void)
...
@@ -188,7 +188,117 @@ static void test_WsDecodeUrl(void)
WsFreeHeap
(
heap
);
WsFreeHeap
(
heap
);
}
}
static
void
test_WsEncodeUrl
(
void
)
{
static
WCHAR
host
[]
=
{
'h'
,
'o'
,
's'
,
't'
};
static
WCHAR
host2
[]
=
{
'h'
,
'o'
,
's'
,
't'
,
' '
,
'2'
};
static
WCHAR
path
[]
=
{
'/'
,
'p'
,
'a'
,
't'
,
'h'
};
static
WCHAR
path2
[]
=
{
'/'
,
'p'
,
'a'
,
't'
,
'h'
,
' '
,
'2'
};
static
WCHAR
query
[]
=
{
'q'
,
'u'
,
'e'
,
'r'
,
'y'
};
static
WCHAR
query2
[]
=
{
'q'
,
'u'
,
'e'
,
'r'
,
'y'
,
' '
,
'2'
};
static
WCHAR
frag
[]
=
{
'f'
,
'r'
,
'a'
,
'g'
};
static
WCHAR
frag2
[]
=
{
'f'
,
'r'
,
'a'
,
'g'
,
' '
,
'2'
};
static
WCHAR
port
[]
=
{
'8'
,
'0'
,
'8'
,
'0'
};
static
WCHAR
port2
[]
=
{
'6'
,
'5'
,
'5'
,
'3'
,
'6'
};
static
const
WCHAR
url1
[]
=
{
'h'
,
't'
,
't'
,
'p'
,
':'
,
'/'
,
'/'
,
'h'
,
'o'
,
's'
,
't'
};
static
const
WCHAR
url2
[]
=
{
'h'
,
't'
,
't'
,
'p'
,
':'
,
'/'
,
'/'
};
static
const
WCHAR
url3
[]
=
{
'h'
,
't'
,
't'
,
'p'
,
':'
,
'/'
,
'/'
,
'/'
,
'p'
,
'a'
,
't'
,
'h'
};
static
const
WCHAR
url4
[]
=
{
'h'
,
't'
,
't'
,
'p'
,
':'
,
'/'
,
'/'
,
'?'
,
'q'
,
'u'
,
'e'
,
'r'
,
'y'
};
static
const
WCHAR
url5
[]
=
{
'h'
,
't'
,
't'
,
'p'
,
':'
,
'/'
,
'/'
,
'#'
,
'f'
,
'r'
,
'a'
,
'g'
};
static
const
WCHAR
url6
[]
=
{
'h'
,
't'
,
't'
,
'p'
,
':'
,
'/'
,
'/'
,
'h'
,
'o'
,
's'
,
't'
,
':'
,
'8'
,
'0'
,
'8'
,
'0'
,
'/'
,
'p'
,
'a'
,
't'
,
'h'
,
'?'
,
'q'
,
'u'
,
'e'
,
'r'
,
'y'
,
'#'
,
'f'
,
'r'
,
'a'
,
'g'
};
static
const
WCHAR
url7
[]
=
{
'h'
,
't'
,
't'
,
'p'
,
':'
,
'/'
,
'/'
,
':'
,
'8'
,
'0'
,
'8'
,
'0'
};
static
const
WCHAR
url8
[]
=
{
'h'
,
't'
,
't'
,
'p'
,
':'
,
'/'
,
'/'
};
static
const
WCHAR
url9
[]
=
{
'h'
,
't'
,
't'
,
'p'
,
':'
,
'/'
,
'/'
,
'/'
,
'p'
,
'a'
,
't'
,
'h'
,
'%'
,
'2'
,
'0'
,
'2'
};
static
const
WCHAR
url10
[]
=
{
'h'
,
't'
,
't'
,
'p'
,
':'
,
'/'
,
'/'
,
'?'
,
'q'
,
'u'
,
'e'
,
'r'
,
'y'
,
'%'
,
'2'
,
'0'
,
'2'
};
static
const
WCHAR
url11
[]
=
{
'h'
,
't'
,
't'
,
'p'
,
':'
,
'/'
,
'/'
,
'#'
,
'f'
,
'r'
,
'a'
,
'g'
,
'%'
,
'2'
,
'0'
,
'2'
};
static
const
WCHAR
url12
[]
=
{
'h'
,
't'
,
't'
,
'p'
,
':'
,
'/'
,
'/'
,
'h'
,
'o'
,
's'
,
't'
,
'%'
,
'2'
,
'0'
,
'2'
};
static
const
struct
{
WS_URL_SCHEME_TYPE
scheme
;
WCHAR
*
host
;
ULONG
host_len
;
USHORT
port
;
WCHAR
*
port_str
;
ULONG
port_len
;
WCHAR
*
path
;
ULONG
path_len
;
WCHAR
*
query
;
ULONG
query_len
;
WCHAR
*
fragment
;
ULONG
fragment_len
;
HRESULT
hr
;
ULONG
len
;
const
WCHAR
*
chars
;
}
tests
[]
=
{
{
WS_URL_HTTP_SCHEME_TYPE
,
host
,
4
,
0
,
NULL
,
0
,
NULL
,
0
,
NULL
,
0
,
NULL
,
0
,
S_OK
,
11
,
url1
},
{
WS_URL_HTTP_SCHEME_TYPE
,
NULL
,
0
,
0
,
NULL
,
0
,
NULL
,
0
,
NULL
,
0
,
NULL
,
0
,
S_OK
,
7
,
url2
},
{
WS_URL_HTTP_SCHEME_TYPE
,
NULL
,
0
,
0
,
NULL
,
0
,
path
,
5
,
NULL
,
0
,
NULL
,
0
,
S_OK
,
12
,
url3
},
{
WS_URL_HTTP_SCHEME_TYPE
,
NULL
,
0
,
0
,
NULL
,
0
,
NULL
,
0
,
query
,
5
,
NULL
,
0
,
S_OK
,
13
,
url4
},
{
WS_URL_HTTP_SCHEME_TYPE
,
NULL
,
0
,
0
,
NULL
,
0
,
NULL
,
0
,
NULL
,
0
,
frag
,
4
,
S_OK
,
12
,
url5
},
{
WS_URL_HTTP_SCHEME_TYPE
,
host
,
4
,
0
,
port
,
4
,
path
,
5
,
query
,
5
,
frag
,
4
,
S_OK
,
32
,
url6
},
{
WS_URL_HTTP_SCHEME_TYPE
,
NULL
,
0
,
8080
,
NULL
,
0
,
NULL
,
0
,
NULL
,
0
,
NULL
,
0
,
S_OK
,
12
,
url7
},
{
WS_URL_HTTP_SCHEME_TYPE
,
NULL
,
0
,
0
,
port
,
4
,
NULL
,
0
,
NULL
,
0
,
NULL
,
0
,
S_OK
,
12
,
url7
},
{
WS_URL_HTTP_SCHEME_TYPE
,
NULL
,
0
,
8080
,
port
,
4
,
NULL
,
0
,
NULL
,
0
,
NULL
,
0
,
S_OK
,
12
,
url7
},
{
WS_URL_HTTP_SCHEME_TYPE
,
NULL
,
0
,
8181
,
port
,
4
,
NULL
,
0
,
NULL
,
0
,
NULL
,
0
,
E_INVALIDARG
,
0
,
NULL
},
{
WS_URL_HTTP_SCHEME_TYPE
,
NULL
,
0
,
0
,
port2
,
5
,
NULL
,
0
,
NULL
,
0
,
NULL
,
0
,
WS_E_INVALID_FORMAT
,
0
,
NULL
},
{
WS_URL_HTTP_SCHEME_TYPE
,
NULL
,
0
,
80
,
NULL
,
0
,
NULL
,
0
,
NULL
,
0
,
NULL
,
0
,
S_OK
,
7
,
url8
},
{
WS_URL_HTTP_SCHEME_TYPE
,
NULL
,
0
,
0
,
NULL
,
0
,
path2
,
7
,
NULL
,
0
,
NULL
,
0
,
S_OK
,
16
,
url9
},
{
WS_URL_HTTP_SCHEME_TYPE
,
NULL
,
0
,
0
,
NULL
,
0
,
NULL
,
0
,
query2
,
7
,
NULL
,
0
,
S_OK
,
17
,
url10
},
{
WS_URL_HTTP_SCHEME_TYPE
,
NULL
,
0
,
0
,
NULL
,
0
,
NULL
,
0
,
NULL
,
0
,
frag2
,
6
,
S_OK
,
16
,
url11
},
{
WS_URL_HTTP_SCHEME_TYPE
,
host2
,
6
,
0
,
NULL
,
0
,
NULL
,
0
,
NULL
,
0
,
NULL
,
0
,
S_OK
,
15
,
url12
},
};
WS_HEAP
*
heap
;
WS_STRING
str
;
WS_HTTP_URL
url
;
HRESULT
hr
;
UINT
i
;
hr
=
WsCreateHeap
(
1
<<
16
,
0
,
NULL
,
0
,
&
heap
,
NULL
);
ok
(
hr
==
S_OK
,
"got %08x
\n
"
,
hr
);
hr
=
WsEncodeUrl
(
NULL
,
0
,
heap
,
&
str
,
NULL
);
ok
(
hr
==
E_INVALIDARG
,
"got %08x
\n
"
,
hr
);
hr
=
WsEncodeUrl
(
(
const
WS_URL
*
)
&
url
,
0
,
NULL
,
&
str
,
NULL
);
ok
(
hr
==
E_INVALIDARG
,
"got %08x
\n
"
,
hr
);
hr
=
WsEncodeUrl
(
(
const
WS_URL
*
)
&
url
,
0
,
heap
,
NULL
,
NULL
);
ok
(
hr
==
E_INVALIDARG
,
"got %08x
\n
"
,
hr
);
for
(
i
=
0
;
i
<
sizeof
(
tests
)
/
sizeof
(
tests
[
0
]);
i
++
)
{
memset
(
&
url
,
0
,
sizeof
(
url
)
);
url
.
url
.
scheme
=
tests
[
i
].
scheme
;
url
.
host
.
chars
=
tests
[
i
].
host
;
url
.
host
.
length
=
tests
[
i
].
host_len
;
url
.
port
=
tests
[
i
].
port
;
url
.
portAsString
.
chars
=
tests
[
i
].
port_str
;
url
.
portAsString
.
length
=
tests
[
i
].
port_len
;
url
.
path
.
chars
=
tests
[
i
].
path
;
url
.
path
.
length
=
tests
[
i
].
path_len
;
url
.
query
.
chars
=
tests
[
i
].
query
;
url
.
query
.
length
=
tests
[
i
].
query_len
;
url
.
fragment
.
chars
=
tests
[
i
].
fragment
;
url
.
fragment
.
length
=
tests
[
i
].
fragment_len
;
memset
(
&
str
,
0
,
sizeof
(
str
)
);
hr
=
WsEncodeUrl
(
(
const
WS_URL
*
)
&
url
,
0
,
heap
,
&
str
,
NULL
);
ok
(
hr
==
tests
[
i
].
hr
,
"%u: got %08x
\n
"
,
i
,
hr
);
if
(
hr
!=
S_OK
)
continue
;
ok
(
str
.
length
==
tests
[
i
].
len
,
"%u: got %u
\n
"
,
i
,
str
.
length
);
ok
(
!
memcmp
(
str
.
chars
,
tests
[
i
].
chars
,
tests
[
i
].
len
*
sizeof
(
WCHAR
)
),
"%u: wrong url %s
\n
"
,
i
,
wine_dbgstr_wn
(
str
.
chars
,
str
.
length
)
);
}
WsFreeHeap
(
heap
);
}
START_TEST
(
url
)
START_TEST
(
url
)
{
{
test_WsDecodeUrl
();
test_WsDecodeUrl
();
test_WsEncodeUrl
();
}
}
dlls/webservices/url.c
View file @
57e69a6b
...
@@ -212,3 +212,272 @@ error:
...
@@ -212,3 +212,272 @@ error:
ws_free
(
heap
,
url
);
ws_free
(
heap
,
url
);
return
hr
;
return
hr
;
}
}
static
const
WCHAR
*
scheme_str
(
WS_URL_SCHEME_TYPE
scheme
,
ULONG
*
len
)
{
switch
(
scheme
)
{
case
WS_URL_HTTP_SCHEME_TYPE
:
*
len
=
sizeof
(
http
)
/
sizeof
(
http
[
0
]);
return
http
;
case
WS_URL_HTTPS_SCHEME_TYPE
:
*
len
=
sizeof
(
https
)
/
sizeof
(
https
[
0
]);
return
https
;
case
WS_URL_NETTCP_SCHEME_TYPE
:
*
len
=
sizeof
(
nettcp
)
/
sizeof
(
nettcp
[
0
]);
return
nettcp
;
case
WS_URL_SOAPUDP_SCHEME_TYPE
:
*
len
=
sizeof
(
soapudp
)
/
sizeof
(
soapudp
[
0
]);
return
soapudp
;
case
WS_URL_NETPIPE_SCHEME_TYPE
:
*
len
=
sizeof
(
netpipe
)
/
sizeof
(
netpipe
[
0
]);
return
netpipe
;
default:
ERR
(
"unhandled scheme %u
\n
"
,
scheme
);
return
NULL
;
}
}
static
inline
ULONG
escape_size
(
unsigned
char
ch
,
const
char
*
except
)
{
const
char
*
p
=
except
;
while
(
*
p
)
{
if
(
*
p
==
ch
)
return
1
;
p
++
;
}
if
((
ch
>=
'a'
&&
ch
<=
'z'
)
||
(
ch
>=
'A'
&&
ch
<=
'Z'
)
||
(
ch
>=
'0'
&&
ch
<=
'9'
))
return
1
;
if
(
ch
<
33
||
ch
>
126
)
return
3
;
switch
(
ch
)
{
case
'/'
:
case
'?'
:
case
'"'
:
case
'#'
:
case
'%'
:
case
'<'
:
case
'>'
:
case
'\\'
:
case
'['
:
case
']'
:
case
'^'
:
case
'`'
:
case
'{'
:
case
'|'
:
case
'}'
:
return
3
;
default:
return
1
;
}
}
static
char
*
strdup_utf8
(
const
WCHAR
*
str
,
ULONG
len
,
ULONG
*
ret_len
)
{
char
*
ret
;
*
ret_len
=
WideCharToMultiByte
(
CP_UTF8
,
0
,
str
,
len
,
NULL
,
0
,
NULL
,
NULL
);
if
((
ret
=
heap_alloc
(
*
ret_len
)))
WideCharToMultiByte
(
CP_UTF8
,
0
,
str
,
len
,
ret
,
*
ret_len
,
NULL
,
NULL
);
return
ret
;
}
static
HRESULT
url_encode_size
(
const
WCHAR
*
str
,
ULONG
len
,
const
char
*
except
,
ULONG
*
ret_len
)
{
ULONG
i
,
len_utf8
;
BOOL
convert
=
FALSE
;
char
*
utf8
;
*
ret_len
=
0
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
if
(
str
[
i
]
>
159
)
{
convert
=
TRUE
;
break
;
}
*
ret_len
+=
escape_size
(
str
[
i
],
except
);
}
if
(
!
convert
)
return
S_OK
;
*
ret_len
=
0
;
if
(
!
(
utf8
=
strdup_utf8
(
str
,
len
,
&
len_utf8
)))
return
E_OUTOFMEMORY
;
for
(
i
=
0
;
i
<
len_utf8
;
i
++
)
*
ret_len
+=
escape_size
(
utf8
[
i
],
except
);
heap_free
(
utf8
);
return
S_OK
;
}
static
ULONG
url_encode_byte
(
unsigned
char
byte
,
const
char
*
except
,
WCHAR
*
buf
)
{
static
const
WCHAR
hex
[]
=
{
'0'
,
'1'
,
'2'
,
'3'
,
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
'9'
,
'A'
,
'B'
,
'C'
,
'D'
,
'E'
,
'F'
};
switch
(
escape_size
(
byte
,
except
))
{
case
3
:
buf
[
0
]
=
'%'
;
buf
[
1
]
=
hex
[(
byte
>>
4
)
&
0xf
];
buf
[
2
]
=
hex
[
byte
&
0xf
];
return
3
;
case
1
:
buf
[
0
]
=
byte
;
return
1
;
default:
ERR
(
"unhandled escape size
\n
"
);
return
0
;
}
}
static
HRESULT
url_encode
(
const
WCHAR
*
str
,
ULONG
len
,
WCHAR
*
buf
,
const
char
*
except
,
ULONG
*
ret_len
)
{
HRESULT
hr
=
S_OK
;
ULONG
i
,
len_utf8
,
len_enc
;
BOOL
convert
=
FALSE
;
WCHAR
*
p
=
buf
;
char
*
utf8
;
*
ret_len
=
0
;
for
(
i
=
0
;
i
<
len
;
i
++
)
{
if
(
str
[
i
]
>
159
)
{
convert
=
TRUE
;
break
;
}
len_enc
=
url_encode_byte
(
str
[
i
],
except
,
p
);
*
ret_len
+=
len_enc
;
p
+=
len_enc
;
}
if
(
!
convert
)
return
S_OK
;
p
=
buf
;
*
ret_len
=
0
;
if
(
!
(
utf8
=
strdup_utf8
(
str
,
len
,
&
len_utf8
)))
return
E_OUTOFMEMORY
;
for
(
i
=
0
;
i
<
len_utf8
;
i
++
)
{
len_enc
=
url_encode_byte
(
utf8
[
i
],
except
,
p
);
*
ret_len
+=
len_enc
;
p
+=
len_enc
;
}
heap_free
(
utf8
);
return
hr
;
}
/**************************************************************************
* WsEncodeUrl [webservices.@]
*/
HRESULT
WINAPI
WsEncodeUrl
(
const
WS_URL
*
base
,
ULONG
flags
,
WS_HEAP
*
heap
,
WS_STRING
*
ret
,
WS_ERROR
*
error
)
{
static
const
WCHAR
fmtW
[]
=
{
':'
,
'%'
,
'u'
,
0
};
ULONG
len
=
0
,
len_scheme
,
len_enc
;
const
WS_HTTP_URL
*
url
=
(
const
WS_HTTP_URL
*
)
base
;
const
WCHAR
*
scheme
;
WCHAR
*
str
,
*
p
,
*
q
;
ULONG
port
=
0
;
HRESULT
hr
;
TRACE
(
"%p %08x %p %p %p
\n
"
,
base
,
flags
,
heap
,
ret
,
error
);
if
(
error
)
FIXME
(
"ignoring error parameter
\n
"
);
if
(
!
url
||
!
heap
||
!
ret
)
return
E_INVALIDARG
;
if
(
flags
)
{
FIXME
(
"unimplemented flags %08x
\n
"
,
flags
);
return
E_NOTIMPL
;
}
if
(
!
(
scheme
=
scheme_str
(
url
->
url
.
scheme
,
&
len_scheme
)))
return
WS_E_INVALID_FORMAT
;
len
=
len_scheme
+
3
;
/* '://' */
len
+=
6
;
/* ':65535' */
if
((
hr
=
url_encode_size
(
url
->
host
.
chars
,
url
->
host
.
length
,
""
,
&
len_enc
))
!=
S_OK
)
return
hr
;
len
+=
len_enc
;
if
((
hr
=
url_encode_size
(
url
->
path
.
chars
,
url
->
path
.
length
,
"/"
,
&
len_enc
))
!=
S_OK
)
return
hr
;
len
+=
len_enc
;
if
((
hr
=
url_encode_size
(
url
->
query
.
chars
,
url
->
query
.
length
,
"/?"
,
&
len_enc
))
!=
S_OK
)
return
hr
;
len
+=
len_enc
+
1
;
/* '?' */
if
((
hr
=
url_encode_size
(
url
->
fragment
.
chars
,
url
->
fragment
.
length
,
"/?"
,
&
len_enc
))
!=
S_OK
)
return
hr
;
len
+=
len_enc
+
1
;
/* '#' */
if
(
!
(
str
=
ws_alloc
(
heap
,
len
*
sizeof
(
WCHAR
)
)))
return
WS_E_QUOTA_EXCEEDED
;
memcpy
(
str
,
scheme
,
len_scheme
*
sizeof
(
WCHAR
)
);
p
=
str
+
len_scheme
;
p
[
0
]
=
':'
;
p
[
1
]
=
p
[
2
]
=
'/'
;
p
+=
3
;
if
((
hr
=
url_encode
(
url
->
host
.
chars
,
url
->
host
.
length
,
p
,
""
,
&
len_enc
))
!=
S_OK
)
goto
error
;
p
+=
len_enc
;
if
(
url
->
portAsString
.
length
)
{
q
=
url
->
portAsString
.
chars
;
len
=
url
->
portAsString
.
length
;
while
(
len
&&
isdigitW
(
*
q
))
{
if
((
port
=
port
*
10
+
*
q
-
'0'
)
>
65535
)
{
hr
=
WS_E_INVALID_FORMAT
;
goto
error
;
}
q
++
;
len
--
;
}
if
(
url
->
port
&&
port
!=
url
->
port
)
{
hr
=
E_INVALIDARG
;
goto
error
;
}
}
else
port
=
url
->
port
;
if
(
port
==
default_port
(
url
->
url
.
scheme
))
port
=
0
;
if
(
port
)
{
WCHAR
buf
[
7
];
len
=
sprintfW
(
buf
,
fmtW
,
port
);
memcpy
(
p
,
buf
,
len
*
sizeof
(
WCHAR
)
);
p
+=
len
;
}
if
((
hr
=
url_encode
(
url
->
path
.
chars
,
url
->
path
.
length
,
p
,
"/"
,
&
len_enc
))
!=
S_OK
)
goto
error
;
p
+=
len_enc
;
if
(
url
->
query
.
length
)
{
*
p
++
=
'?'
;
if
((
hr
=
url_encode
(
url
->
query
.
chars
,
url
->
query
.
length
,
p
,
"/?"
,
&
len_enc
))
!=
S_OK
)
goto
error
;
p
+=
len_enc
;
}
if
(
url
->
fragment
.
length
)
{
*
p
++
=
'#'
;
if
((
hr
=
url_encode
(
url
->
fragment
.
chars
,
url
->
fragment
.
length
,
p
,
"/?"
,
&
len_enc
))
!=
S_OK
)
goto
error
;
p
+=
len_enc
;
}
ret
->
length
=
p
-
str
;
ret
->
chars
=
str
;
return
S_OK
;
error:
ws_free
(
heap
,
str
);
return
hr
;
}
dlls/webservices/webservices.spec
View file @
57e69a6b
...
@@ -39,7 +39,7 @@
...
@@ -39,7 +39,7 @@
@ stub WsCreateXmlSecurityToken
@ stub WsCreateXmlSecurityToken
@ stdcall WsDateTimeToFileTime(ptr ptr ptr)
@ stdcall WsDateTimeToFileTime(ptr ptr ptr)
@ stdcall WsDecodeUrl(ptr long ptr ptr ptr)
@ stdcall WsDecodeUrl(ptr long ptr ptr ptr)
@ st
ub WsEncodeUrl
@ st
dcall WsEncodeUrl(ptr long ptr ptr ptr)
@ stub WsEndReaderCanonicalization
@ stub WsEndReaderCanonicalization
@ stub WsEndWriterCanonicalization
@ stub WsEndWriterCanonicalization
@ stdcall WsFileTimeToDateTime(ptr ptr ptr)
@ stdcall WsFileTimeToDateTime(ptr ptr ptr)
...
...
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