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
d91f985e
Commit
d91f985e
authored
Oct 25, 2016
by
Hans Leidekker
Committed by
Alexandre Julliard
Oct 25, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
webservices: Implement WsCall.
Signed-off-by:
Hans Leidekker
<
hans@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
5eb0971b
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
575 additions
and
22 deletions
+575
-22
msg.c
dlls/webservices/msg.c
+59
-19
proxy.c
dlls/webservices/proxy.c
+152
-2
reader.c
dlls/webservices/reader.c
+104
-0
proxy.c
dlls/webservices/tests/proxy.c
+208
-0
webservices_private.h
dlls/webservices/webservices_private.h
+11
-0
writer.c
dlls/webservices/writer.c
+41
-1
No files found.
dlls/webservices/msg.c
View file @
d91f985e
...
...
@@ -64,24 +64,26 @@ struct header
struct
msg
{
WS_MESSAGE_INITIALIZATION
init
;
WS_MESSAGE_STATE
state
;
GUID
id
;
WS_ENVELOPE_VERSION
version_env
;
WS_ADDRESSING_VERSION
version_addr
;
BOOL
is_addressed
;
WS_STRING
addr
;
WS_STRING
action
;
WS_HEAP
*
heap
;
WS_XML_BUFFER
*
buf
;
WS_XML_WRITER
*
writer
;
WS_XML_WRITER
*
writer_body
;
WS_XML_READER
*
reader_body
;
ULONG
header_count
;
ULONG
header_size
;
struct
header
**
header
;
ULONG
prop_count
;
struct
prop
prop
[
sizeof
(
msg_props
)
/
sizeof
(
msg_props
[
0
])];
WS_MESSAGE_INITIALIZATION
init
;
WS_MESSAGE_STATE
state
;
GUID
id
;
WS_ENVELOPE_VERSION
version_env
;
WS_ADDRESSING_VERSION
version_addr
;
BOOL
is_addressed
;
WS_STRING
addr
;
WS_STRING
action
;
WS_HEAP
*
heap
;
WS_XML_BUFFER
*
buf
;
WS_XML_WRITER
*
writer
;
WS_XML_WRITER
*
writer_body
;
WS_XML_READER
*
reader_body
;
ULONG
header_count
;
ULONG
header_size
;
struct
header
**
header
;
WS_PROXY_MESSAGE_CALLBACK_CONTEXT
ctx_send
;
WS_PROXY_MESSAGE_CALLBACK_CONTEXT
ctx_receive
;
ULONG
prop_count
;
struct
prop
prop
[
sizeof
(
msg_props
)
/
sizeof
(
msg_props
[
0
])];
};
#define HEADER_ARRAY_SIZE 2
...
...
@@ -953,7 +955,7 @@ static HRESULT build_mapped_header( const WS_XML_STRING *name, WS_TYPE type, WS_
* WsAddMappedHeader [webservices.@]
*/
HRESULT
WINAPI
WsAddMappedHeader
(
WS_MESSAGE
*
handle
,
const
WS_XML_STRING
*
name
,
WS_TYPE
type
,
WS_WRITE_OPTION
option
,
const
void
*
value
,
ULONG
size
,
WS_ERROR
*
error
)
WS_WRITE_OPTION
option
,
const
void
*
value
,
ULONG
size
,
WS_ERROR
*
error
)
{
struct
msg
*
msg
=
(
struct
msg
*
)
handle
;
struct
header
*
header
;
...
...
@@ -1209,6 +1211,44 @@ HRESULT message_insert_http_headers( WS_MESSAGE *handle, HINTERNET req )
return
S_OK
;
}
void
message_set_send_context
(
WS_MESSAGE
*
handle
,
const
WS_PROXY_MESSAGE_CALLBACK_CONTEXT
*
ctx
)
{
struct
msg
*
msg
=
(
struct
msg
*
)
handle
;
msg
->
ctx_send
.
callback
=
ctx
->
callback
;
msg
->
ctx_send
.
state
=
ctx
->
state
;
}
void
message_set_receive_context
(
WS_MESSAGE
*
handle
,
const
WS_PROXY_MESSAGE_CALLBACK_CONTEXT
*
ctx
)
{
struct
msg
*
msg
=
(
struct
msg
*
)
handle
;
msg
->
ctx_receive
.
callback
=
ctx
->
callback
;
msg
->
ctx_receive
.
state
=
ctx
->
state
;
}
void
message_do_send_callback
(
WS_MESSAGE
*
handle
)
{
struct
msg
*
msg
=
(
struct
msg
*
)
handle
;
if
(
msg
->
ctx_send
.
callback
)
{
HRESULT
hr
;
TRACE
(
"executing callback %p
\n
"
,
msg
->
ctx_send
.
callback
);
hr
=
msg
->
ctx_send
.
callback
(
handle
,
msg
->
heap
,
msg
->
ctx_send
.
state
,
NULL
);
TRACE
(
"callback %p returned %08x
\n
"
,
msg
->
ctx_send
.
callback
,
hr
);
}
}
void
message_do_receive_callback
(
WS_MESSAGE
*
handle
)
{
struct
msg
*
msg
=
(
struct
msg
*
)
handle
;
if
(
msg
->
ctx_receive
.
callback
)
{
HRESULT
hr
;
TRACE
(
"executing callback %p
\n
"
,
msg
->
ctx_receive
.
callback
);
hr
=
msg
->
ctx_receive
.
callback
(
handle
,
msg
->
heap
,
msg
->
ctx_receive
.
state
,
NULL
);
TRACE
(
"callback %p returned %08x
\n
"
,
msg
->
ctx_receive
.
callback
,
hr
);
}
}
HRESULT
message_set_action
(
WS_MESSAGE
*
handle
,
const
WS_XML_STRING
*
action
)
{
struct
msg
*
msg
=
(
struct
msg
*
)
handle
;
...
...
dlls/webservices/proxy.c
View file @
d91f985e
...
...
@@ -245,6 +245,127 @@ HRESULT WINAPI WsAbortServiceProxy( WS_SERVICE_PROXY *handle, WS_ERROR *error )
return
E_NOTIMPL
;
}
static
HRESULT
set_send_context
(
WS_MESSAGE
*
msg
,
const
WS_CALL_PROPERTY
*
props
,
ULONG
count
)
{
ULONG
i
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
if
(
props
[
i
].
id
==
WS_CALL_PROPERTY_SEND_MESSAGE_CONTEXT
)
{
if
(
props
[
i
].
valueSize
!=
sizeof
(
WS_PROXY_MESSAGE_CALLBACK_CONTEXT
))
return
E_INVALIDARG
;
message_set_send_context
(
msg
,
props
[
i
].
value
);
break
;
}
}
return
S_OK
;
}
static
HRESULT
set_receive_context
(
WS_MESSAGE
*
msg
,
const
WS_CALL_PROPERTY
*
props
,
ULONG
count
)
{
ULONG
i
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
if
(
props
[
i
].
id
==
WS_CALL_PROPERTY_RECEIVE_MESSAGE_CONTEXT
)
{
if
(
props
[
i
].
valueSize
!=
sizeof
(
WS_PROXY_MESSAGE_CALLBACK_CONTEXT
))
return
E_INVALIDARG
;
message_set_receive_context
(
msg
,
props
[
i
].
value
);
break
;
}
}
return
S_OK
;
}
static
HRESULT
write_message
(
WS_MESSAGE
*
msg
,
WS_XML_WRITER
*
writer
,
const
WS_ELEMENT_DESCRIPTION
*
desc
,
const
WS_PARAMETER_DESCRIPTION
*
params
,
ULONG
count
,
const
void
**
args
)
{
HRESULT
hr
;
message_do_send_callback
(
msg
);
if
((
hr
=
WsWriteEnvelopeStart
(
msg
,
writer
,
NULL
,
NULL
,
NULL
))
!=
S_OK
)
return
hr
;
if
((
hr
=
write_input_params
(
writer
,
desc
,
params
,
count
,
args
))
!=
S_OK
)
return
hr
;
return
WsWriteEnvelopeEnd
(
msg
,
NULL
);
}
static
HRESULT
send_message
(
WS_CHANNEL
*
channel
,
WS_MESSAGE
*
msg
,
WS_MESSAGE_DESCRIPTION
*
desc
,
WS_PARAMETER_DESCRIPTION
*
params
,
ULONG
count
,
const
void
**
args
)
{
WS_XML_WRITER
*
writer
;
HRESULT
hr
;
if
((
hr
=
message_set_action
(
msg
,
desc
->
action
))
!=
S_OK
)
return
hr
;
if
((
hr
=
WsCreateWriter
(
NULL
,
0
,
&
writer
,
NULL
))
!=
S_OK
)
return
hr
;
if
((
hr
=
set_output
(
writer
))
!=
S_OK
)
goto
done
;
if
((
hr
=
write_message
(
msg
,
writer
,
desc
->
bodyElementDescription
,
params
,
count
,
args
))
!=
S_OK
)
goto
done
;
hr
=
channel_send_message
(
channel
,
msg
);
done:
WsFreeWriter
(
writer
);
return
hr
;
}
static
HRESULT
read_message
(
WS_MESSAGE
*
msg
,
WS_XML_READER
*
reader
,
WS_HEAP
*
heap
,
const
WS_ELEMENT_DESCRIPTION
*
desc
,
const
WS_PARAMETER_DESCRIPTION
*
params
,
ULONG
count
,
const
void
**
args
)
{
HRESULT
hr
;
if
((
hr
=
WsReadEnvelopeStart
(
msg
,
reader
,
NULL
,
NULL
,
NULL
))
!=
S_OK
)
return
hr
;
message_do_receive_callback
(
msg
);
if
((
hr
=
read_output_params
(
reader
,
heap
,
desc
,
params
,
count
,
args
))
!=
S_OK
)
return
hr
;
return
WsReadEnvelopeEnd
(
msg
,
NULL
);
}
static
HRESULT
receive_message
(
WS_CHANNEL
*
channel
,
WS_MESSAGE
*
msg
,
WS_MESSAGE_DESCRIPTION
*
desc
,
WS_PARAMETER_DESCRIPTION
*
params
,
ULONG
count
,
WS_HEAP
*
heap
,
const
void
**
args
)
{
WS_XML_READER
*
reader
;
char
*
buf
;
ULONG
len
;
HRESULT
hr
;
if
((
hr
=
message_set_action
(
msg
,
desc
->
action
))
!=
S_OK
)
return
hr
;
if
((
hr
=
channel_receive_message
(
channel
,
&
buf
,
&
len
))
!=
S_OK
)
return
hr
;
if
((
hr
=
WsCreateReader
(
NULL
,
0
,
&
reader
,
NULL
))
!=
S_OK
)
goto
done
;
if
((
hr
=
set_input
(
reader
,
buf
,
len
))
!=
S_OK
)
goto
done
;
hr
=
read_message
(
msg
,
reader
,
heap
,
desc
->
bodyElementDescription
,
params
,
count
,
args
);
done:
WsFreeReader
(
reader
);
heap_free
(
buf
);
return
hr
;
}
static
HRESULT
create_input_message
(
WS_CHANNEL
*
channel
,
const
WS_CALL_PROPERTY
*
properties
,
ULONG
count
,
WS_MESSAGE
**
ret
)
{
WS_MESSAGE
*
msg
;
HRESULT
hr
;
if
((
hr
=
WsCreateMessageForChannel
(
channel
,
NULL
,
0
,
&
msg
,
NULL
))
!=
S_OK
)
return
hr
;
if
((
hr
=
WsInitializeMessage
(
msg
,
WS_REQUEST_MESSAGE
,
NULL
,
NULL
))
!=
S_OK
||
(
hr
=
set_send_context
(
msg
,
properties
,
count
))
!=
S_OK
)
{
WsFreeMessage
(
msg
);
return
hr
;
}
*
ret
=
msg
;
return
S_OK
;
}
static
HRESULT
create_output_message
(
WS_CHANNEL
*
channel
,
const
WS_CALL_PROPERTY
*
properties
,
ULONG
count
,
WS_MESSAGE
**
ret
)
{
WS_MESSAGE
*
msg
;
HRESULT
hr
;
if
((
hr
=
WsCreateMessageForChannel
(
channel
,
NULL
,
0
,
&
msg
,
NULL
))
!=
S_OK
)
return
hr
;
if
((
hr
=
set_receive_context
(
msg
,
properties
,
count
))
!=
S_OK
)
{
WsFreeMessage
(
msg
);
return
hr
;
}
*
ret
=
msg
;
return
S_OK
;
}
/**************************************************************************
* WsCall [webservices.@]
*/
...
...
@@ -252,6 +373,35 @@ HRESULT WINAPI WsCall( WS_SERVICE_PROXY *handle, const WS_OPERATION_DESCRIPTION
WS_HEAP
*
heap
,
const
WS_CALL_PROPERTY
*
properties
,
const
ULONG
count
,
const
WS_ASYNC_CONTEXT
*
ctx
,
WS_ERROR
*
error
)
{
FIXME
(
"%p %p %p %p %p %u %p %p
\n
"
,
handle
,
desc
,
args
,
heap
,
properties
,
count
,
ctx
,
error
);
return
E_NOTIMPL
;
struct
proxy
*
proxy
=
(
struct
proxy
*
)
handle
;
WS_MESSAGE
*
msg
;
HRESULT
hr
;
ULONG
i
;
TRACE
(
"%p %p %p %p %p %u %p %p
\n
"
,
handle
,
desc
,
args
,
heap
,
properties
,
count
,
ctx
,
error
);
if
(
error
)
FIXME
(
"ignoring error parameter
\n
"
);
if
(
ctx
)
FIXME
(
"ignoring ctx parameter
\n
"
);
for
(
i
=
0
;
i
<
count
;
i
++
)
{
if
(
properties
[
i
].
id
!=
WS_CALL_PROPERTY_SEND_MESSAGE_CONTEXT
&&
properties
[
i
].
id
!=
WS_CALL_PROPERTY_RECEIVE_MESSAGE_CONTEXT
)
{
FIXME
(
"unimplemented call property %u
\n
"
,
properties
[
i
].
id
);
return
E_NOTIMPL
;
}
}
if
(
!
handle
||
!
desc
||
(
desc
->
parameterCount
&&
!
args
))
return
E_INVALIDARG
;
if
((
hr
=
create_input_message
(
proxy
->
channel
,
properties
,
count
,
&
msg
))
!=
S_OK
)
return
hr
;
hr
=
send_message
(
proxy
->
channel
,
msg
,
desc
->
inputMessageDescription
,
desc
->
parameterDescription
,
desc
->
parameterCount
,
args
);
WsFreeMessage
(
msg
);
if
(
hr
!=
S_OK
)
return
hr
;
if
((
hr
=
create_output_message
(
proxy
->
channel
,
properties
,
count
,
&
msg
))
!=
S_OK
)
return
hr
;
hr
=
receive_message
(
proxy
->
channel
,
msg
,
desc
->
outputMessageDescription
,
desc
->
parameterDescription
,
desc
->
parameterCount
,
heap
,
args
);
WsFreeMessage
(
msg
);
return
hr
;
}
dlls/webservices/reader.c
View file @
d91f985e
...
...
@@ -4665,3 +4665,107 @@ HRESULT WINAPI WsReadCharsUtf8( WS_XML_READER *handle, BYTE *bytes, ULONG max_co
return
S_OK
;
}
HRESULT
get_param_desc
(
const
WS_STRUCT_DESCRIPTION
*
desc
,
USHORT
index
,
const
WS_FIELD_DESCRIPTION
**
ret
)
{
if
(
index
>=
desc
->
fieldCount
)
return
E_INVALIDARG
;
*
ret
=
desc
->
fields
[
index
];
return
S_OK
;
}
static
ULONG
get_field_size
(
const
WS_FIELD_DESCRIPTION
*
desc
)
{
WS_READ_OPTION
option
;
ULONG
size
;
switch
((
option
=
get_field_read_option
(
desc
->
type
,
desc
->
options
)))
{
case
WS_READ_REQUIRED_POINTER
:
case
WS_READ_OPTIONAL_POINTER
:
case
WS_READ_NILLABLE_POINTER
:
size
=
sizeof
(
void
*
);
break
;
case
WS_READ_REQUIRED_VALUE
:
case
WS_READ_NILLABLE_VALUE
:
size
=
get_type_size
(
desc
->
type
,
desc
->
typeDescription
);
break
;
default:
WARN
(
"unhandled option %u
\n
"
,
option
);
return
0
;
}
return
size
;
}
static
HRESULT
read_param
(
struct
reader
*
reader
,
const
WS_FIELD_DESCRIPTION
*
desc
,
WS_HEAP
*
heap
,
void
*
ret
)
{
if
(
!
ret
&&
!
(
ret
=
ws_alloc_zero
(
heap
,
get_field_size
(
desc
)
)))
return
WS_E_QUOTA_EXCEEDED
;
return
read_type_struct_field
(
reader
,
desc
,
heap
,
ret
,
0
);
}
static
HRESULT
read_param_array
(
struct
reader
*
reader
,
const
WS_FIELD_DESCRIPTION
*
desc
,
WS_HEAP
*
heap
,
void
**
ret
,
ULONG
*
count
)
{
if
(
!
ret
&&
!
(
ret
=
ws_alloc_zero
(
heap
,
sizeof
(
void
**
)
)))
return
WS_E_QUOTA_EXCEEDED
;
return
read_type_repeating_element
(
reader
,
desc
,
heap
,
ret
,
count
);
}
static
void
set_array_len
(
const
WS_PARAMETER_DESCRIPTION
*
params
,
ULONG
count
,
ULONG
index
,
ULONG
len
,
const
void
**
args
)
{
ULONG
i
,
*
ptr
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
if
(
params
[
i
].
outputMessageIndex
!=
index
||
params
[
i
].
parameterType
!=
WS_PARAMETER_TYPE_ARRAY_COUNT
)
continue
;
if
((
ptr
=
*
(
ULONG
**
)
args
[
i
]))
*
ptr
=
len
;
break
;
}
}
HRESULT
read_output_params
(
WS_XML_READER
*
handle
,
WS_HEAP
*
heap
,
const
WS_ELEMENT_DESCRIPTION
*
desc
,
const
WS_PARAMETER_DESCRIPTION
*
params
,
ULONG
count
,
const
void
**
args
)
{
struct
reader
*
reader
=
(
struct
reader
*
)
handle
;
const
WS_STRUCT_DESCRIPTION
*
desc_struct
;
const
WS_FIELD_DESCRIPTION
*
desc_field
;
ULONG
i
,
len
;
HRESULT
hr
;
if
(
desc
->
type
!=
WS_STRUCT_TYPE
||
!
(
desc_struct
=
desc
->
typeDescription
))
return
E_INVALIDARG
;
if
((
hr
=
start_mapping
(
reader
,
WS_ELEMENT_TYPE_MAPPING
,
desc
->
elementLocalName
,
desc
->
elementNs
))
!=
S_OK
)
return
hr
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
if
(
params
[
i
].
outputMessageIndex
==
INVALID_PARAMETER_INDEX
)
continue
;
if
(
params
[
i
].
parameterType
==
WS_PARAMETER_TYPE_MESSAGES
)
{
FIXME
(
"messages type not supported
\n
"
);
return
E_NOTIMPL
;
}
if
((
hr
=
get_param_desc
(
desc_struct
,
params
[
i
].
outputMessageIndex
,
&
desc_field
))
!=
S_OK
)
return
hr
;
if
(
params
[
i
].
parameterType
==
WS_PARAMETER_TYPE_NORMAL
)
{
void
*
ptr
=
*
(
void
**
)
args
[
i
];
if
((
hr
=
read_param
(
reader
,
desc_field
,
heap
,
ptr
))
!=
S_OK
)
return
hr
;
}
else
if
(
params
[
i
].
parameterType
==
WS_PARAMETER_TYPE_ARRAY
)
{
void
**
ptr
=
*
(
void
***
)
args
[
i
];
if
((
hr
=
read_param_array
(
reader
,
desc_field
,
heap
,
ptr
,
&
len
))
!=
S_OK
)
return
hr
;
set_array_len
(
params
,
count
,
params
[
i
].
outputMessageIndex
,
len
,
args
);
}
}
if
(
desc_struct
->
structOptions
&
WS_STRUCT_IGNORE_TRAILING_ELEMENT_CONTENT
)
{
struct
node
*
parent
=
find_parent
(
reader
);
parent
->
flags
|=
NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
;
}
return
end_mapping
(
reader
,
WS_ELEMENT_TYPE_MAPPING
);
}
dlls/webservices/tests/proxy.c
View file @
d91f985e
...
...
@@ -249,6 +249,211 @@ static void test_WsReceiveMessage( int port )
WsFreeMessage
(
msg
);
}
static
HRESULT
create_proxy
(
int
port
,
WS_SERVICE_PROXY
**
ret
)
{
static
const
WCHAR
fmt
[]
=
{
'h'
,
't'
,
't'
,
'p'
,
':'
,
'/'
,
'/'
,
'1'
,
'2'
,
'7'
,
'.'
,
'0'
,
'.'
,
'0'
,
'.'
,
'1'
,
':'
,
'%'
,
'u'
,
'/'
,
0
};
WS_ENVELOPE_VERSION
env_version
;
WS_ADDRESSING_VERSION
addr_version
;
WS_CHANNEL_PROPERTY
prop
[
2
];
WS_ENDPOINT_ADDRESS
addr
;
WS_SERVICE_PROXY
*
proxy
;
WCHAR
url
[
64
];
HRESULT
hr
;
env_version
=
WS_ENVELOPE_VERSION_SOAP_1_1
;
prop
[
0
].
id
=
WS_CHANNEL_PROPERTY_ENVELOPE_VERSION
;
prop
[
0
].
value
=
&
env_version
;
prop
[
0
].
valueSize
=
sizeof
(
env_version
);
addr_version
=
WS_ADDRESSING_VERSION_TRANSPORT
;
prop
[
1
].
id
=
WS_CHANNEL_PROPERTY_ADDRESSING_VERSION
;
prop
[
1
].
value
=
&
addr_version
;
prop
[
1
].
valueSize
=
sizeof
(
addr_version
);
*
ret
=
NULL
;
hr
=
WsCreateServiceProxy
(
WS_CHANNEL_TYPE_REQUEST
,
WS_HTTP_CHANNEL_BINDING
,
NULL
,
NULL
,
0
,
prop
,
sizeof
(
prop
)
/
sizeof
(
prop
[
0
]),
&
proxy
,
NULL
);
if
(
hr
!=
S_OK
)
return
hr
;
addr
.
url
.
length
=
wsprintfW
(
url
,
fmt
,
port
);
addr
.
url
.
chars
=
url
;
addr
.
headers
=
NULL
;
addr
.
extensions
=
NULL
;
addr
.
identity
=
NULL
;
hr
=
WsOpenServiceProxy
(
proxy
,
&
addr
,
NULL
,
NULL
);
if
(
hr
==
S_OK
)
*
ret
=
proxy
;
else
WsFreeServiceProxy
(
proxy
);
return
hr
;
}
static
const
char
req_test2
[]
=
"<s:Envelope xmlns:s=
\"
http://schemas.xmlsoap.org/soap/envelope/
\"
><s:Body>"
"<req_test2 xmlns=
\"
ns
\"
><val>1</val></req_test2>"
"</s:Body></s:Envelope>"
;
static
const
char
resp_test2
[]
=
"<s:Envelope xmlns:s=
\"
http://schemas.xmlsoap.org/soap/envelope/
\"
><s:Body>"
"<resp_test2 xmlns=
\"
ns
\"
><str>test</str><val>1</val><val>2</val></resp_test2>"
"</s:Body></s:Envelope>"
;
static
void
test_WsCall
(
int
port
)
{
static
WCHAR
testW
[]
=
{
't'
,
'e'
,
's'
,
't'
,
0
};
WS_XML_STRING
str
=
{
3
,
(
BYTE
*
)
"str"
};
WS_XML_STRING
req
=
{
3
,
(
BYTE
*
)
"req"
};
WS_XML_STRING
resp
=
{
4
,
(
BYTE
*
)
"resp"
};
WS_XML_STRING
req_elem
=
{
9
,
(
BYTE
*
)
"req_test2"
};
WS_XML_STRING
resp_elem
=
{
10
,
(
BYTE
*
)
"resp_test2"
};
WS_XML_STRING
req_action
=
{
9
,
(
BYTE
*
)
"req_test2"
};
WS_XML_STRING
resp_action
=
{
10
,
(
BYTE
*
)
"resp_test2"
};
WS_XML_STRING
val
=
{
3
,
(
BYTE
*
)
"val"
};
WS_XML_STRING
ns
=
{
2
,
(
BYTE
*
)
"ns"
};
HRESULT
hr
;
WS_SERVICE_PROXY
*
proxy
;
WS_OPERATION_DESCRIPTION
op
;
WS_MESSAGE_DESCRIPTION
input_msg
,
output_msg
;
WS_ELEMENT_DESCRIPTION
input_elem
,
output_elem
;
WS_STRUCT_DESCRIPTION
input_struct
,
output_struct
;
WS_FIELD_DESCRIPTION
f
,
f2
,
f3
,
*
fields
[
2
],
*
fields2
[
2
];
WS_PARAMETER_DESCRIPTION
param
[
4
];
const
void
*
args
[
4
];
WS_HEAP
*
heap
;
INT32
**
val_ptr
;
WCHAR
**
str_ptr
;
ULONG
*
count_ptr
;
struct
input
{
INT32
val
;
}
in
;
struct
output
{
WCHAR
*
str
;
ULONG
count
;
INT32
*
val
;
}
out
;
hr
=
WsCreateHeap
(
1
<<
16
,
0
,
NULL
,
0
,
&
heap
,
NULL
);
ok
(
hr
==
S_OK
,
"got %08x
\n
"
,
hr
);
hr
=
WsCall
(
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
0
,
NULL
,
NULL
);
ok
(
hr
==
E_INVALIDARG
,
"got %08x
\n
"
,
hr
);
hr
=
create_proxy
(
port
,
&
proxy
);
ok
(
hr
==
S_OK
,
"got %08x
\n
"
,
hr
);
hr
=
WsCall
(
proxy
,
NULL
,
NULL
,
NULL
,
NULL
,
0
,
NULL
,
NULL
);
ok
(
hr
==
E_INVALIDARG
,
"got %08x
\n
"
,
hr
);
memset
(
&
f
,
0
,
sizeof
(
f
)
);
f
.
mapping
=
WS_ELEMENT_FIELD_MAPPING
;
f
.
localName
=
&
val
;
f
.
ns
=
&
ns
;
f
.
type
=
WS_INT32_TYPE
;
fields
[
0
]
=
&
f
;
memset
(
&
input_struct
,
0
,
sizeof
(
input_struct
)
);
input_struct
.
size
=
sizeof
(
struct
input
);
input_struct
.
alignment
=
TYPE_ALIGNMENT
(
struct
input
);
input_struct
.
fields
=
fields
;
input_struct
.
fieldCount
=
1
;
input_struct
.
typeLocalName
=
&
req
;
input_struct
.
typeNs
=
&
ns
;
input_elem
.
elementLocalName
=
&
req_elem
;
input_elem
.
elementNs
=
&
ns
;
input_elem
.
type
=
WS_STRUCT_TYPE
;
input_elem
.
typeDescription
=
&
input_struct
;
input_msg
.
action
=
&
req_action
;
input_msg
.
bodyElementDescription
=
&
input_elem
;
memset
(
&
f2
,
0
,
sizeof
(
f2
)
);
f2
.
mapping
=
WS_ELEMENT_FIELD_MAPPING
;
f2
.
localName
=
&
str
;
f2
.
ns
=
&
ns
;
f2
.
type
=
WS_WSZ_TYPE
;
f2
.
offset
=
FIELD_OFFSET
(
struct
output
,
str
);
fields2
[
0
]
=
&
f2
;
memset
(
&
f3
,
0
,
sizeof
(
f3
)
);
f3
.
mapping
=
WS_REPEATING_ELEMENT_FIELD_MAPPING
;
f3
.
type
=
WS_INT32_TYPE
;
f3
.
offset
=
FIELD_OFFSET
(
struct
output
,
val
);
f3
.
countOffset
=
FIELD_OFFSET
(
struct
output
,
count
);
f3
.
itemLocalName
=
&
val
;
f3
.
itemNs
=
&
ns
;
fields2
[
1
]
=
&
f3
;
memset
(
&
output_struct
,
0
,
sizeof
(
output_struct
)
);
output_struct
.
size
=
sizeof
(
struct
output
);
output_struct
.
alignment
=
TYPE_ALIGNMENT
(
struct
output
);
output_struct
.
fields
=
fields2
;
output_struct
.
fieldCount
=
2
;
output_struct
.
typeLocalName
=
&
resp
;
output_struct
.
typeNs
=
&
ns
;
output_elem
.
elementLocalName
=
&
resp_elem
;
output_elem
.
elementNs
=
&
ns
;
output_elem
.
type
=
WS_STRUCT_TYPE
;
output_elem
.
typeDescription
=
&
output_struct
;
output_msg
.
action
=
&
resp_action
;
output_msg
.
bodyElementDescription
=
&
output_elem
;
param
[
0
].
parameterType
=
WS_PARAMETER_TYPE_NORMAL
;
param
[
0
].
inputMessageIndex
=
0
;
param
[
0
].
outputMessageIndex
=
0xffff
;
param
[
1
].
parameterType
=
WS_PARAMETER_TYPE_NORMAL
;
param
[
1
].
inputMessageIndex
=
0xffff
;
param
[
1
].
outputMessageIndex
=
0
;
param
[
2
].
parameterType
=
WS_PARAMETER_TYPE_ARRAY
;
param
[
2
].
inputMessageIndex
=
0xffff
;
param
[
2
].
outputMessageIndex
=
1
;
param
[
3
].
parameterType
=
WS_PARAMETER_TYPE_ARRAY_COUNT
;
param
[
3
].
inputMessageIndex
=
0xffff
;
param
[
3
].
outputMessageIndex
=
1
;
op
.
versionInfo
=
1
;
op
.
inputMessageDescription
=
&
input_msg
;
op
.
outputMessageDescription
=
&
output_msg
;
op
.
inputMessageOptions
=
0
;
op
.
outputMessageOptions
=
0
;
op
.
parameterCount
=
4
;
op
.
parameterDescription
=
param
;
op
.
stubCallback
=
NULL
;
op
.
style
=
0
;
hr
=
WsCall
(
proxy
,
&
op
,
NULL
,
NULL
,
NULL
,
0
,
NULL
,
NULL
);
ok
(
hr
==
E_INVALIDARG
,
"got %08x
\n
"
,
hr
);
in
.
val
=
1
;
args
[
0
]
=
&
in
.
val
;
out
.
str
=
NULL
;
out
.
count
=
0
;
out
.
val
=
0
;
str_ptr
=
&
out
.
str
;
val_ptr
=
&
out
.
val
;
count_ptr
=
&
out
.
count
;
args
[
1
]
=
&
str_ptr
;
args
[
2
]
=
&
val_ptr
;
args
[
3
]
=
&
count_ptr
;
hr
=
WsCall
(
proxy
,
&
op
,
args
,
heap
,
NULL
,
0
,
NULL
,
NULL
);
ok
(
hr
==
S_OK
,
"got %08x
\n
"
,
hr
);
ok
(
!
lstrcmpW
(
out
.
str
,
testW
),
"wrong data
\n
"
);
ok
(
out
.
count
==
2
,
"got %u
\n
"
,
out
.
count
);
ok
(
out
.
val
[
0
]
==
1
,
"got %u
\n
"
,
out
.
val
[
0
]
);
ok
(
out
.
val
[
1
]
==
2
,
"got %u
\n
"
,
out
.
val
[
1
]
);
hr
=
WsCloseServiceProxy
(
proxy
,
NULL
,
NULL
);
ok
(
hr
==
S_OK
,
"got %08x
\n
"
,
hr
);
WsFreeServiceProxy
(
proxy
);
WsFreeHeap
(
heap
);
}
static
const
struct
{
const
char
*
req_action
;
...
...
@@ -261,6 +466,7 @@ static const struct
tests
[]
=
{
{
"req_test1"
,
req_test1
,
sizeof
(
req_test1
)
-
1
,
"resp_test1"
,
resp_test1
,
sizeof
(
resp_test1
)
-
1
},
{
"req_test2"
,
req_test2
,
sizeof
(
req_test2
)
-
1
,
"resp_test2"
,
resp_test2
,
sizeof
(
resp_test2
)
-
1
},
};
static
void
send_response
(
int
c
,
const
char
*
action
,
const
char
*
data
,
unsigned
int
len
)
...
...
@@ -349,6 +555,7 @@ static DWORD CALLBACK server_proc( void *arg )
ok
(
!
memcmp
(
tests
[
j
].
req_data
,
buf
,
tests
[
j
].
req_len
),
"%u: unexpected data
\n
"
,
j
);
}
send_response
(
c
,
tests
[
j
].
resp_action
,
tests
[
j
].
resp_data
,
tests
[
j
].
resp_len
);
break
;
}
}
...
...
@@ -383,6 +590,7 @@ START_TEST(proxy)
test_WsSendMessage
(
info
.
port
,
&
test1
);
test_WsReceiveMessage
(
info
.
port
);
test_WsCall
(
info
.
port
);
test_WsSendMessage
(
info
.
port
,
&
quit
);
WaitForSingleObject
(
thread
,
3000
);
...
...
dlls/webservices/webservices_private.h
View file @
d91f985e
...
...
@@ -41,6 +41,13 @@ HRESULT set_output( WS_XML_WRITER * ) DECLSPEC_HIDDEN;
HRESULT
set_input
(
WS_XML_READER
*
,
char
*
,
ULONG
)
DECLSPEC_HIDDEN
;
ULONG
get_type_size
(
WS_TYPE
,
const
WS_STRUCT_DESCRIPTION
*
)
DECLSPEC_HIDDEN
;
#define INVALID_PARAMETER_INDEX 0xffff
HRESULT
get_param_desc
(
const
WS_STRUCT_DESCRIPTION
*
,
USHORT
,
const
WS_FIELD_DESCRIPTION
**
)
DECLSPEC_HIDDEN
;
HRESULT
write_input_params
(
WS_XML_WRITER
*
,
const
WS_ELEMENT_DESCRIPTION
*
,
const
WS_PARAMETER_DESCRIPTION
*
,
ULONG
,
const
void
**
)
DECLSPEC_HIDDEN
;
HRESULT
read_output_params
(
WS_XML_READER
*
,
WS_HEAP
*
,
const
WS_ELEMENT_DESCRIPTION
*
,
const
WS_PARAMETER_DESCRIPTION
*
,
ULONG
,
const
void
**
)
DECLSPEC_HIDDEN
;
enum
node_flag
{
NODE_FLAG_IGNORE_TRAILING_ELEMENT_CONTENT
=
0x1
,
...
...
@@ -100,6 +107,10 @@ HRESULT prop_set( const struct prop *, ULONG, ULONG, const void *, ULONG ) DECLS
HRESULT
prop_get
(
const
struct
prop
*
,
ULONG
,
ULONG
,
void
*
,
ULONG
)
DECLSPEC_HIDDEN
;
HRESULT
message_set_action
(
WS_MESSAGE
*
,
const
WS_XML_STRING
*
)
DECLSPEC_HIDDEN
;
void
message_set_send_context
(
WS_MESSAGE
*
,
const
WS_PROXY_MESSAGE_CALLBACK_CONTEXT
*
)
DECLSPEC_HIDDEN
;
void
message_set_receive_context
(
WS_MESSAGE
*
,
const
WS_PROXY_MESSAGE_CALLBACK_CONTEXT
*
)
DECLSPEC_HIDDEN
;
void
message_do_send_callback
(
WS_MESSAGE
*
)
DECLSPEC_HIDDEN
;
void
message_do_receive_callback
(
WS_MESSAGE
*
)
DECLSPEC_HIDDEN
;
HRESULT
message_insert_http_headers
(
WS_MESSAGE
*
,
HINTERNET
)
DECLSPEC_HIDDEN
;
HRESULT
channel_send_message
(
WS_CHANNEL
*
,
WS_MESSAGE
*
)
DECLSPEC_HIDDEN
;
...
...
dlls/webservices/writer.c
View file @
d91f985e
...
...
@@ -2107,7 +2107,7 @@ static HRESULT write_type_struct( struct writer *writer, WS_TYPE_MAPPING mapping
if
(
!
desc
)
return
E_INVALIDARG
;
if
(
desc
->
structOptions
)
FIXME
(
"struct options 0x%x not supported
\n
"
,
desc
->
structOptions
);
if
((
hr
=
get_value_ptr
(
option
,
value
,
size
,
desc
->
size
,
(
const
void
**
)
&
ptr
))
!=
S_OK
)
return
hr
;
if
((
hr
=
get_value_ptr
(
option
,
value
,
size
,
desc
->
size
,
&
ptr
))
!=
S_OK
)
return
hr
;
for
(
i
=
0
;
i
<
desc
->
fieldCount
;
i
++
)
{
...
...
@@ -2792,3 +2792,43 @@ HRESULT WINAPI WsCopyNode( WS_XML_WRITER *handle, WS_XML_READER *reader, WS_ERRO
writer
->
current
=
current
;
return
S_OK
;
}
static
HRESULT
write_param
(
struct
writer
*
writer
,
const
WS_FIELD_DESCRIPTION
*
desc
,
const
void
*
value
)
{
return
write_type_struct_field
(
writer
,
desc
,
value
,
get_field_size
(
desc
)
);
}
HRESULT
write_input_params
(
WS_XML_WRITER
*
handle
,
const
WS_ELEMENT_DESCRIPTION
*
desc
,
const
WS_PARAMETER_DESCRIPTION
*
params
,
ULONG
count
,
const
void
**
args
)
{
struct
writer
*
writer
=
(
struct
writer
*
)
handle
;
const
WS_STRUCT_DESCRIPTION
*
desc_struct
;
const
WS_FIELD_DESCRIPTION
*
desc_field
;
HRESULT
hr
;
ULONG
i
;
if
(
desc
->
type
!=
WS_STRUCT_TYPE
||
!
(
desc_struct
=
desc
->
typeDescription
))
return
E_INVALIDARG
;
if
((
hr
=
write_element_node
(
writer
,
NULL
,
desc
->
elementLocalName
,
desc
->
elementNs
))
!=
S_OK
)
return
hr
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
if
(
params
[
i
].
inputMessageIndex
==
INVALID_PARAMETER_INDEX
)
continue
;
if
(
params
[
i
].
parameterType
==
WS_PARAMETER_TYPE_MESSAGES
)
{
FIXME
(
"messages type not supported
\n
"
);
return
E_NOTIMPL
;
}
if
((
hr
=
get_param_desc
(
desc_struct
,
params
[
i
].
inputMessageIndex
,
&
desc_field
))
!=
S_OK
)
return
hr
;
if
(
params
[
i
].
parameterType
==
WS_PARAMETER_TYPE_NORMAL
)
{
if
((
hr
=
write_param
(
writer
,
desc_field
,
args
[
i
]
))
!=
S_OK
)
return
hr
;
}
else
if
(
params
[
i
].
parameterType
==
WS_PARAMETER_TYPE_ARRAY
)
{
FIXME
(
"no support for writing array parameters
\n
"
);
}
}
return
write_endelement_node
(
writer
);
}
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