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
503d152b
Commit
503d152b
authored
Oct 04, 2016
by
Hans Leidekker
Committed by
Alexandre Julliard
Oct 04, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
webservices: Add support for writing WS_DATETIME values.
Signed-off-by:
Hans Leidekker
<
hans@codeweavers.com
>
Signed-off-by:
Alexandre Julliard
<
julliard@winehq.org
>
parent
bacc6882
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
212 additions
and
21 deletions
+212
-21
reader.c
dlls/webservices/reader.c
+2
-21
writer.c
dlls/webservices/tests/writer.c
+88
-0
webservices_private.h
dlls/webservices/webservices_private.h
+18
-0
writer.c
dlls/webservices/writer.c
+98
-0
webservices.h
include/webservices.h
+6
-0
No files found.
dlls/webservices/reader.c
View file @
503d152b
...
...
@@ -2468,32 +2468,15 @@ static HRESULT str_to_guid( const unsigned char *str, ULONG len, GUID *ret )
return
S_OK
;
}
#define TICKS_PER_SEC 10000000
#define TICKS_PER_MIN (60 * (ULONGLONG)TICKS_PER_SEC)
#define TICKS_PER_HOUR (3600 * (ULONGLONG)TICKS_PER_SEC)
#define TICKS_PER_DAY (86400 * (ULONGLONG)TICKS_PER_SEC)
#define TICKS_MAX 3155378975999999999
static
const
int
month_offsets
[
2
][
12
]
=
{
{
0
,
31
,
59
,
90
,
120
,
151
,
181
,
212
,
243
,
273
,
304
,
334
},
{
0
,
31
,
60
,
91
,
121
,
152
,
182
,
213
,
244
,
274
,
305
,
335
}
};
static
const
int
month_days
[
2
][
12
]
=
{
{
31
,
28
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
},
{
31
,
29
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
}
};
static
inline
int
is_leap_year
(
int
year
)
{
return
!
(
year
%
4
)
&&
(
year
%
100
||
!
(
year
%
400
));
}
static
inline
int
valid_day
(
int
year
,
int
month
,
int
day
)
{
return
day
>
0
&&
day
<=
month_days
[
is_
leap_year
(
year
)][
month
-
1
];
return
day
>
0
&&
day
<=
month_days
[
leap_year
(
year
)][
month
-
1
];
}
static
inline
int
leap_days_before
(
int
year
)
...
...
@@ -2585,7 +2568,7 @@ static HRESULT str_to_datetime( const unsigned char *bytes, ULONG len, WS_DATETI
else
return
WS_E_INVALID_FORMAT
;
ret
->
ticks
=
((
year
-
1
)
*
365
+
leap_days_before
(
year
))
*
TICKS_PER_DAY
;
ret
->
ticks
+=
month_offsets
[
is_
leap_year
(
year
)][
month
-
1
]
*
TICKS_PER_DAY
;
ret
->
ticks
+=
month_offsets
[
leap_year
(
year
)][
month
-
1
]
*
TICKS_PER_DAY
;
ret
->
ticks
+=
(
day
-
1
)
*
TICKS_PER_DAY
;
ret
->
ticks
+=
hour
*
TICKS_PER_HOUR
;
ret
->
ticks
+=
min
*
TICKS_PER_MIN
;
...
...
@@ -2610,8 +2593,6 @@ static HRESULT str_to_datetime( const unsigned char *bytes, ULONG len, WS_DATETI
return
S_OK
;
}
#define TICKS_1601_01_01 504911232000000000
/**************************************************************************
* WsDateTimeToFileTime [webservices.@]
*/
...
...
dlls/webservices/tests/writer.c
View file @
503d152b
...
...
@@ -2547,6 +2547,93 @@ static void test_write_option(void)
WsFreeWriter
(
writer
);
}
static
BOOL
check_result
(
WS_XML_WRITER
*
writer
,
const
char
*
expected
)
{
WS_BYTES
bytes
;
ULONG
size
=
sizeof
(
bytes
);
int
len
=
strlen
(
expected
);
memset
(
&
bytes
,
0
,
sizeof
(
bytes
)
);
WsGetWriterProperty
(
writer
,
WS_XML_WRITER_PROPERTY_BYTES
,
&
bytes
,
size
,
NULL
);
if
(
bytes
.
length
!=
len
)
return
FALSE
;
return
!
memcmp
(
bytes
.
bytes
,
expected
,
len
);
}
static
void
test_datetime
(
void
)
{
WS_XML_STRING
localname
=
{
1
,
(
BYTE
*
)
"t"
},
ns
=
{
0
,
NULL
};
static
const
struct
{
unsigned
__int64
ticks
;
WS_DATETIME_FORMAT
format
;
HRESULT
hr
;
const
char
*
result
;
const
char
*
result2
;
}
tests
[]
=
{
{
0
,
WS_DATETIME_FORMAT_UTC
,
S_OK
,
"<t>0001-01-01T00:00:00Z</t>"
},
{
0
,
WS_DATETIME_FORMAT_LOCAL
,
S_OK
,
"<t>0001-01-01T00:00:00+00:00</t>"
},
{
0
,
WS_DATETIME_FORMAT_NONE
,
S_OK
,
"<t>0001-01-01T00:00:00</t>"
},
{
1
,
WS_DATETIME_FORMAT_UTC
,
S_OK
,
"<t>0001-01-01T00:00:00.0000001Z</t>"
},
{
1
,
WS_DATETIME_FORMAT_LOCAL
,
S_OK
,
"<t>0001-01-01T00:00:00.0000001+00:00</t>"
},
{
1
,
WS_DATETIME_FORMAT_NONE
,
S_OK
,
"<t>0001-01-01T00:00:00.0000001</t>"
},
{
0x23c34600
,
WS_DATETIME_FORMAT_LOCAL
,
S_OK
,
"<t>0001-01-01T00:01:00+00:00</t>"
},
{
0x861c46800
,
WS_DATETIME_FORMAT_LOCAL
,
S_OK
,
"<t>0001-01-01T01:00:00+00:00</t>"
},
{
0x430e234000
,
WS_DATETIME_FORMAT_LOCAL
,
S_OK
,
"<t>0001-01-01T08:00:00+00:00</t>"
},
{
0x4b6fe7a800
,
WS_DATETIME_FORMAT_LOCAL
,
S_OK
,
"<t>0001-01-01T09:00:00+00:00</t>"
},
{
0x989680
,
WS_DATETIME_FORMAT_NONE
,
S_OK
,
"<t>0001-01-01T00:00:01</t>"
},
{
0x23c34600
,
WS_DATETIME_FORMAT_NONE
,
S_OK
,
"<t>0001-01-01T00:01:00</t>"
},
{
0x861c46800
,
WS_DATETIME_FORMAT_NONE
,
S_OK
,
"<t>0001-01-01T01:00:00</t>"
},
{
0xc92a69c000
,
WS_DATETIME_FORMAT_NONE
,
S_OK
,
"<t>0001-01-02T00:00:00</t>"
},
{
0x11ed178c6c000
,
WS_DATETIME_FORMAT_NONE
,
S_OK
,
"<t>0002-01-01T00:00:00</t>"
},
{
0x2bca2875f4373fff
,
WS_DATETIME_FORMAT_UTC
,
S_OK
,
"<t>9999-12-31T23:59:59.9999999Z</t>"
},
{
0x2bca2875f4373fff
,
WS_DATETIME_FORMAT_LOCAL
,
S_OK
,
"<t>9999-12-31T15:59:59.9999999-08:00</t>"
,
"<t>9999-12-31T17:59:59.9999999-06:00</t>"
/* win7 */
},
{
0x2bca2875f4373fff
,
WS_DATETIME_FORMAT_NONE
,
S_OK
,
"<t>9999-12-31T23:59:59.9999999</t>"
},
{
0x2bca2875f4374000
,
WS_DATETIME_FORMAT_UTC
,
WS_E_INVALID_FORMAT
},
{
0x2bca2875f4374000
,
WS_DATETIME_FORMAT_LOCAL
,
WS_E_INVALID_FORMAT
},
{
0x2bca2875f4374000
,
WS_DATETIME_FORMAT_NONE
,
WS_E_INVALID_FORMAT
},
{
0x8d3123e7df74000
,
WS_DATETIME_FORMAT_LOCAL
,
S_OK
,
"<t>2015-12-31T16:00:00-08:00</t>"
,
"<t>2015-12-31T18:00:00-06:00</t>"
/* win7 */
},
{
0x701ce1722770000
,
WS_DATETIME_FORMAT_LOCAL
,
S_OK
,
"<t>1601-01-01T00:00:00+00:00</t>"
},
{
0x701ce5a309a4000
,
WS_DATETIME_FORMAT_LOCAL
,
S_OK
,
"<t>1601-01-01T00:00:00-08:00</t>"
,
"<t>1601-01-01T02:00:00-06:00</t>"
/* win7 */
},
{
0x701ce5e617c7400
,
WS_DATETIME_FORMAT_LOCAL
,
S_OK
,
"<t>1601-01-01T00:30:00-08:00</t>"
,
"<t>1601-01-01T02:30:00-06:00</t>"
/* win7 */
},
{
0x701ce51ced5d800
,
WS_DATETIME_FORMAT_LOCAL
,
S_OK
,
"<t>1601-01-01T07:00:00+00:00</t>"
,
"<t>1601-01-01T01:00:00-06:00</t>"
/* win7 */
},
{
0
,
WS_DATETIME_FORMAT_NONE
+
1
,
WS_E_INVALID_FORMAT
},
};
HRESULT
hr
;
WS_XML_WRITER
*
writer
;
WS_DATETIME
date
;
ULONG
i
;
hr
=
WsCreateWriter
(
NULL
,
0
,
&
writer
,
NULL
);
ok
(
hr
==
S_OK
,
"got %08x
\n
"
,
hr
);
for
(
i
=
0
;
i
<
sizeof
(
tests
)
/
sizeof
(
tests
[
0
]);
i
++
)
{
hr
=
set_output
(
writer
);
ok
(
hr
==
S_OK
,
"got %08x
\n
"
,
hr
);
date
.
ticks
=
tests
[
i
].
ticks
;
date
.
format
=
tests
[
i
].
format
;
WsWriteStartElement
(
writer
,
NULL
,
&
localname
,
&
ns
,
NULL
);
hr
=
WsWriteType
(
writer
,
WS_ELEMENT_TYPE_MAPPING
,
WS_DATETIME_TYPE
,
NULL
,
WS_WRITE_REQUIRED_VALUE
,
&
date
,
sizeof
(
date
),
NULL
);
WsWriteEndElement
(
writer
,
NULL
);
ok
(
hr
==
tests
[
i
].
hr
,
"%u: got %08x
\n
"
,
i
,
hr
);
if
(
hr
==
S_OK
)
{
ok
(
check_result
(
writer
,
tests
[
i
].
result
)
||
broken
(
check_result
(
writer
,
tests
[
i
].
result2
)),
"%u: wrong result
\n
"
,
i
);
}
}
WsFreeWriter
(
writer
);
}
START_TEST
(
writer
)
{
test_WsCreateWriter
();
...
...
@@ -2578,4 +2665,5 @@ START_TEST(writer)
test_WsWriteArray
();
test_escapes
();
test_write_option
();
test_datetime
();
}
dlls/webservices/webservices_private.h
View file @
503d152b
...
...
@@ -100,6 +100,24 @@ HRESULT message_insert_http_headers( WS_MESSAGE *, HINTERNET ) DECLSPEC_HIDDEN;
HRESULT
channel_send_message
(
WS_CHANNEL
*
,
WS_MESSAGE
*
)
DECLSPEC_HIDDEN
;
HRESULT
channel_receive_message
(
WS_CHANNEL
*
,
char
**
,
ULONG
*
)
DECLSPEC_HIDDEN
;
#define TICKS_PER_SEC 10000000
#define TICKS_PER_MIN (60 * (ULONGLONG)TICKS_PER_SEC)
#define TICKS_PER_HOUR (3600 * (ULONGLONG)TICKS_PER_SEC)
#define TICKS_PER_DAY (86400 * (ULONGLONG)TICKS_PER_SEC)
#define TICKS_MAX 3155378975999999999
#define TICKS_1601_01_01 504911232000000000
static
const
int
month_days
[
2
][
12
]
=
{
{
31
,
28
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
},
{
31
,
29
,
31
,
30
,
31
,
30
,
31
,
31
,
30
,
31
,
30
,
31
}
};
static
inline
int
leap_year
(
int
year
)
{
return
!
(
year
%
4
)
&&
(
year
%
100
||
!
(
year
%
400
));
}
static
inline
BOOL
is_nil_value
(
const
char
*
value
,
ULONG
size
)
{
ULONG
i
;
...
...
dlls/webservices/writer.c
View file @
503d152b
...
...
@@ -1187,6 +1187,68 @@ static ULONG format_double( const double *ptr, unsigned char *buf )
#endif
}
static
inline
int
year_size
(
int
year
)
{
return
leap_year
(
year
)
?
366
:
365
;
}
#define TZ_OFFSET 8
static
ULONG
format_datetime
(
const
WS_DATETIME
*
ptr
,
unsigned
char
*
buf
)
{
static
const
char
fmt
[]
=
"%04u-%02u-%02uT%02u:%02u:%02u"
;
int
day
,
hour
,
min
,
sec
,
sec_frac
,
month
=
1
,
year
=
1
,
tz_hour
;
unsigned
__int64
ticks
,
day_ticks
;
ULONG
len
;
if
(
ptr
->
format
==
WS_DATETIME_FORMAT_LOCAL
&&
ptr
->
ticks
>=
TICKS_1601_01_01
+
TZ_OFFSET
*
TICKS_PER_HOUR
)
{
ticks
=
ptr
->
ticks
-
TZ_OFFSET
*
TICKS_PER_HOUR
;
tz_hour
=
TZ_OFFSET
;
}
else
{
ticks
=
ptr
->
ticks
;
tz_hour
=
0
;
}
day
=
ticks
/
TICKS_PER_DAY
;
day_ticks
=
ticks
%
TICKS_PER_DAY
;
hour
=
day_ticks
/
TICKS_PER_HOUR
;
min
=
(
day_ticks
%
TICKS_PER_HOUR
)
/
TICKS_PER_MIN
;
sec
=
(
day_ticks
%
TICKS_PER_MIN
)
/
TICKS_PER_SEC
;
sec_frac
=
day_ticks
%
TICKS_PER_SEC
;
while
(
day
>=
year_size
(
year
))
{
day
-=
year_size
(
year
);
year
++
;
}
while
(
day
>=
month_days
[
leap_year
(
year
)][
month
])
{
day
-=
month_days
[
leap_year
(
year
)][
month
];
month
++
;
}
day
++
;
len
=
sprintf
(
(
char
*
)
buf
,
fmt
,
year
,
month
,
day
,
hour
,
min
,
sec
);
if
(
sec_frac
)
{
static
const
char
fmt_frac
[]
=
".%07u"
;
len
+=
sprintf
(
(
char
*
)
buf
+
len
,
fmt_frac
,
sec_frac
);
}
if
(
ptr
->
format
==
WS_DATETIME_FORMAT_UTC
)
{
buf
[
len
++
]
=
'Z'
;
}
else
if
(
ptr
->
format
==
WS_DATETIME_FORMAT_LOCAL
)
{
static
const
char
fmt_tz
[]
=
"%c%02u:00"
;
len
+=
sprintf
(
(
char
*
)
buf
+
len
,
fmt_tz
,
tz_hour
?
'-'
:
'+'
,
tz_hour
);
}
return
len
;
}
static
ULONG
format_guid
(
const
GUID
*
ptr
,
unsigned
char
*
buf
)
{
static
const
char
fmt
[]
=
"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"
;
...
...
@@ -1284,6 +1346,13 @@ static HRESULT text_to_utf8text( const WS_XML_TEXT *text, WS_XML_UTF8_TEXT **ret
(
*
ret
)
->
value
.
length
=
format_urn
(
&
id
->
value
,
(
*
ret
)
->
value
.
bytes
);
return
S_OK
;
}
case
WS_XML_TEXT_TYPE_DATETIME
:
{
const
WS_XML_DATETIME_TEXT
*
dt
=
(
const
WS_XML_DATETIME_TEXT
*
)
text
;
if
(
!
(
*
ret
=
alloc_utf8_text
(
NULL
,
34
)))
return
E_OUTOFMEMORY
;
(
*
ret
)
->
value
.
length
=
format_datetime
(
&
dt
->
value
,
(
*
ret
)
->
value
.
bytes
);
return
S_OK
;
}
default:
FIXME
(
"unhandled text type %u
\n
"
,
text
->
textType
);
return
E_NOTIMPL
;
...
...
@@ -1666,6 +1735,32 @@ static HRESULT write_type_uint64( struct writer *writer, WS_TYPE_MAPPING mapping
return
write_type_text
(
writer
,
mapping
,
&
utf8
.
text
);
}
static
HRESULT
write_type_datetime
(
struct
writer
*
writer
,
WS_TYPE_MAPPING
mapping
,
const
WS_DATETIME_DESCRIPTION
*
desc
,
WS_WRITE_OPTION
option
,
const
void
*
value
,
ULONG
size
)
{
WS_XML_UTF8_TEXT
utf8
;
unsigned
char
buf
[
34
];
/* "0000-00-00T00:00:00.0000000-00:00" */
const
WS_DATETIME
*
ptr
;
HRESULT
hr
;
if
(
desc
)
{
FIXME
(
"description not supported
\n
"
);
return
E_NOTIMPL
;
}
if
(
!
option
||
option
==
WS_WRITE_NILLABLE_VALUE
)
return
E_INVALIDARG
;
if
((
hr
=
get_value_ptr
(
option
,
value
,
size
,
sizeof
(
WS_DATETIME
),
(
const
void
**
)
&
ptr
))
!=
S_OK
)
return
hr
;
if
(
option
==
WS_WRITE_NILLABLE_POINTER
&&
!
ptr
)
return
write_add_nil_attribute
(
writer
);
if
(
ptr
->
ticks
>
TICKS_MAX
||
ptr
->
format
>
WS_DATETIME_FORMAT_NONE
)
return
WS_E_INVALID_FORMAT
;
utf8
.
text
.
textType
=
WS_XML_TEXT_TYPE_UTF8
;
utf8
.
value
.
bytes
=
buf
;
utf8
.
value
.
length
=
format_datetime
(
ptr
,
buf
);
return
write_type_text
(
writer
,
mapping
,
&
utf8
.
text
);
}
static
HRESULT
write_type_guid
(
struct
writer
*
writer
,
WS_TYPE_MAPPING
mapping
,
const
WS_GUID_DESCRIPTION
*
desc
,
WS_WRITE_OPTION
option
,
const
void
*
value
,
ULONG
size
)
...
...
@@ -1931,6 +2026,9 @@ static HRESULT write_type( struct writer *writer, WS_TYPE_MAPPING mapping, WS_TY
case
WS_UINT64_TYPE
:
return
write_type_uint64
(
writer
,
mapping
,
desc
,
option
,
value
,
size
);
case
WS_DATETIME_TYPE
:
return
write_type_datetime
(
writer
,
mapping
,
desc
,
option
,
value
,
size
);
case
WS_GUID_TYPE
:
return
write_type_guid
(
writer
,
mapping
,
desc
,
option
,
value
,
size
);
...
...
include/webservices.h
View file @
503d152b
...
...
@@ -58,6 +58,7 @@ typedef struct _WS_OPERATION_CONTEXT WS_OPERATION_CONTEXT;
typedef
struct
_WS_CALL_PROPERTY
WS_CALL_PROPERTY
;
typedef
struct
_WS_DOUBLE_DESCRIPTION
WS_DOUBLE_DESCRIPTION
;
typedef
struct
_WS_DATETIME
WS_DATETIME
;
typedef
struct
_WS_XML_DATETIME_TEXT
WS_XML_DATETIME_TEXT
;
typedef
struct
_WS_DATETIME_DESCRIPTION
WS_DATETIME_DESCRIPTION
;
typedef
struct
_WS_GUID_DESCRIPTION
WS_GUID_DESCRIPTION
;
typedef
struct
_WS_UNIQUE_ID_DESCRIPTION
WS_UNIQUE_ID_DESCRIPTION
;
...
...
@@ -1106,6 +1107,11 @@ struct _WS_DATETIME_DESCRIPTION {
WS_DATETIME
maxValue
;
};
struct
_WS_XML_DATETIME_TEXT
{
WS_XML_TEXT
text
;
WS_DATETIME
value
;
};
typedef
enum
{
WS_URL_HTTP_SCHEME_TYPE
,
WS_URL_HTTPS_SCHEME_TYPE
,
...
...
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