Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/combase/tests/string.c
4394 views
1
/*
2
* Unit tests for Windows String functions
3
*
4
* Copyright (c) 2014 Martin Storsjo
5
*
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 of the License, or (at your option) any later version.
10
*
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
15
*
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with this library; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19
*/
20
21
#include <stdarg.h>
22
23
#include "windef.h"
24
#include "winbase.h"
25
#include "winerror.h"
26
#include "winstring.h"
27
28
#include "wine/test.h"
29
30
#define check_string(str, content, length, has_null) _check_string(__LINE__, str, content, length, has_null)
31
static void _check_string(int line, HSTRING str, LPCWSTR content, UINT32 length, BOOL has_null)
32
{
33
BOOL out_null;
34
BOOL empty = length == 0;
35
UINT32 out_length;
36
LPCWSTR ptr;
37
38
ok_(__FILE__, line)(WindowsIsStringEmpty(str) == empty, "WindowsIsStringEmpty failed\n");
39
ok_(__FILE__, line)(WindowsStringHasEmbeddedNull(str, &out_null) == S_OK, "WindowsStringHasEmbeddedNull failed\n");
40
ok_(__FILE__, line)(out_null == has_null, "WindowsStringHasEmbeddedNull failed\n");
41
ok_(__FILE__, line)(WindowsGetStringLen(str) == length, "WindowsGetStringLen failed\n");
42
ptr = WindowsGetStringRawBuffer(str, &out_length);
43
/* WindowsGetStringRawBuffer should return a non-null, null terminated empty string
44
* even if str is NULL. */
45
ok_(__FILE__, line)(ptr != NULL, "WindowsGetStringRawBuffer returned null\n");
46
ok_(__FILE__, line)(out_length == length, "WindowsGetStringRawBuffer returned incorrect length\n");
47
ptr = WindowsGetStringRawBuffer(str, NULL);
48
ok_(__FILE__, line)(ptr != NULL, "WindowsGetStringRawBuffer returned null\n");
49
ok_(__FILE__, line)(ptr[length] == '\0', "WindowsGetStringRawBuffer doesn't return a null terminated buffer\n");
50
ok_(__FILE__, line)(memcmp(ptr, content, sizeof(*content) * length) == 0, "Incorrect string content\n");
51
}
52
53
static const WCHAR input_string[] = L"abcdef\0";
54
static const WCHAR input_string1[] = L"abc";
55
static const WCHAR input_string2[] = L"def";
56
static const WCHAR input_embed_null[] = L"a\0c\0ef";
57
static const WCHAR output_substring[] = L"cdef";
58
59
static void test_create_delete(void)
60
{
61
HSTRING str;
62
HSTRING_HEADER header;
63
64
/* Test normal creation of a string */
65
ok(WindowsCreateString(input_string, 6, &str) == S_OK, "Failed to create string\n");
66
check_string(str, input_string, 6, FALSE);
67
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string\n");
68
/* Test error handling in WindowsCreateString */
69
ok(WindowsCreateString(input_string, 6, NULL) == E_INVALIDARG, "Incorrect error handling\n");
70
ok(WindowsCreateString(NULL, 6, &str) == E_POINTER, "Incorrect error handling\n");
71
72
/* Test handling of a NULL string */
73
ok(WindowsDeleteString(NULL) == S_OK, "Failed to delete null string\n");
74
75
/* Test creation of a string reference */
76
ok(WindowsCreateStringReference(input_string, 6, &header, &str) == S_OK, "Failed to create string ref\n");
77
check_string(str, input_string, 6, FALSE);
78
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string ref\n");
79
80
/* Test error handling in WindowsCreateStringReference */
81
/* Strings to CreateStringReference must be null terminated with the correct
82
* length. According to MSDN this should be E_INVALIDARG, but it returns
83
* 0x80000017 in practice. */
84
ok(FAILED(WindowsCreateStringReference(input_string, 5, &header, &str)), "Incorrect error handling\n");
85
/* If the input string is non-null, it must be null-terminated even if the
86
* length is zero. */
87
ok(FAILED(WindowsCreateStringReference(input_string, 0, &header, &str)), "Incorrect error handling\n");
88
ok(WindowsCreateStringReference(input_string, 6, NULL, &str) == E_INVALIDARG, "Incorrect error handling\n");
89
ok(WindowsCreateStringReference(input_string, 6, &header, NULL) == E_INVALIDARG, "Incorrect error handling\n");
90
ok(WindowsCreateStringReference(NULL, 6, &header, &str) == E_POINTER, "Incorrect error handling\n");
91
92
/* Test creating a string without a null-termination at the specified length */
93
ok(WindowsCreateString(input_string, 3, &str) == S_OK, "Failed to create string\n");
94
check_string(str, input_string, 3, FALSE);
95
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string\n");
96
97
/* Test an empty string */
98
ok(WindowsCreateString(L"", 0, &str) == S_OK, "Failed to create string\n");
99
ok(str == NULL, "Empty string not a null string\n");
100
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string\n");
101
102
ok(WindowsCreateString(input_string, 0, &str) == S_OK, "Failed to create string\n");
103
ok(str == NULL, "Empty string not a null string\n");
104
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string\n");
105
106
ok(WindowsCreateStringReference(L"", 0, &header, &str) == S_OK, "Failed to create string\n");
107
ok(str == NULL, "Empty string not a null string\n");
108
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string\n");
109
110
ok(WindowsCreateString(NULL, 0, &str) == S_OK, "Failed to create string\n");
111
ok(str == NULL, "Empty string not a null string\n");
112
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string\n");
113
114
ok(WindowsCreateStringReference(NULL, 0, &header, &str) == S_OK, "Failed to create string\n");
115
ok(str == NULL, "Empty string not a null string\n");
116
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string\n");
117
}
118
119
static void test_duplicate(void)
120
{
121
HSTRING str, str2;
122
HSTRING_HEADER header;
123
ok(WindowsCreateString(input_string, 6, &str) == S_OK, "Failed to create string\n");
124
ok(WindowsDuplicateString(str, NULL) == E_INVALIDARG, "Incorrect error handling\n");
125
ok(WindowsDuplicateString(str, &str2) == S_OK, "Failed to duplicate string\n");
126
ok(str == str2, "Duplicated string created new string\n");
127
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string\n");
128
ok(WindowsDeleteString(str2) == S_OK, "Failed to delete string\n");
129
130
ok(WindowsCreateStringReference(input_string, 6, &header, &str) == S_OK, "Failed to create string ref\n");
131
ok(WindowsDuplicateString(str, &str2) == S_OK, "Failed to duplicate string\n");
132
ok(str != str2, "Duplicated string ref didn't create new string\n");
133
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string\n");
134
ok(WindowsDeleteString(str2) == S_OK, "Failed to delete string ref\n");
135
136
ok(WindowsDuplicateString(NULL, &str2) == S_OK, "Failed to duplicate NULL string\n");
137
ok(str2 == NULL, "Duplicated string created new string\n");
138
ok(WindowsDeleteString(str2) == S_OK, "Failed to delete string\n");
139
}
140
141
static void test_access(void)
142
{
143
HSTRING str;
144
HSTRING_HEADER header;
145
146
/* Test handling of a NULL string */
147
check_string(NULL, NULL, 0, FALSE);
148
149
/* Test strings with embedded null chars */
150
ok(WindowsCreateString(input_embed_null, 6, &str) == S_OK, "Failed to create string\n");
151
check_string(str, input_embed_null, 6, TRUE);
152
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string\n");
153
154
ok(WindowsCreateStringReference(input_embed_null, 6, &header, &str) == S_OK, "Failed to create string ref\n");
155
check_string(str, input_embed_null, 6, TRUE);
156
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string ref\n");
157
158
/* Test normal creation of a string with trailing null */
159
ok(WindowsCreateString(input_string, 7, &str) == S_OK, "Failed to create string\n");
160
check_string(str, input_string, 7, TRUE);
161
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string\n");
162
163
ok(WindowsCreateStringReference(input_string, 7, &header, &str) == S_OK, "Failed to create string ref\n");
164
check_string(str, input_string, 7, TRUE);
165
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string ref\n");
166
}
167
168
static void test_string_buffer(void)
169
{
170
/* Initialize ptr to NULL to make sure it actually is set in the first
171
* test below. */
172
HSTRING_BUFFER buf = NULL;
173
WCHAR *ptr = NULL;
174
HSTRING str;
175
176
/* Test creation of an empty buffer */
177
ok(WindowsPreallocateStringBuffer(0, &ptr, &buf) == S_OK, "Failed to preallocate string buffer\n");
178
ok(ptr != NULL, "Empty string didn't return a buffer pointer\n");
179
ok(WindowsPromoteStringBuffer(buf, &str) == S_OK, "Failed to promote string buffer\n");
180
ok(str == NULL, "Empty string isn't a null string\n");
181
check_string(str, L"", 0, FALSE);
182
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string\n");
183
184
ok(WindowsDeleteStringBuffer(NULL) == S_OK, "Failed to delete null string buffer\n");
185
186
/* Test creation and deletion of string buffers */
187
ok(WindowsPreallocateStringBuffer(6, &ptr, &buf) == S_OK, "Failed to preallocate string buffer\n");
188
ok(WindowsDeleteStringBuffer(buf) == S_OK, "Failed to delete string buffer\n");
189
190
/* Test creation and promotion of string buffers */
191
ok(WindowsPreallocateStringBuffer(6, &ptr, &buf) == S_OK, "Failed to preallocate string buffer\n");
192
ok(ptr[6] == '\0', "Preallocated string buffer didn't have null termination\n");
193
memcpy(ptr, input_string, 6 * sizeof(*input_string));
194
ok(WindowsPromoteStringBuffer(buf, NULL) == E_POINTER, "Incorrect error handling\n");
195
ok(WindowsPromoteStringBuffer(buf, &str) == S_OK, "Failed to promote string buffer\n");
196
check_string(str, input_string, 6, FALSE);
197
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string\n");
198
199
/* Test error handling in preallocation */
200
ok(WindowsPreallocateStringBuffer(6, NULL, &buf) == E_POINTER, "Incorrect error handling\n");
201
ok(WindowsPreallocateStringBuffer(6, &ptr, NULL) == E_POINTER, "Incorrect error handling\n");
202
203
ok(WindowsPreallocateStringBuffer(6, &ptr, &buf) == S_OK, "Failed to preallocate string buffer\n");
204
ptr[6] = 'a'; /* Overwrite the buffer's null termination, promotion should fail */
205
ok(WindowsPromoteStringBuffer(buf, &str) == E_INVALIDARG, "Incorrect error handling\n");
206
ok(WindowsDeleteStringBuffer(buf) == S_OK, "Failed to delete string buffer\n");
207
208
/* Test strings with trailing null chars */
209
ok(WindowsPreallocateStringBuffer(7, &ptr, &buf) == S_OK, "Failed to preallocate string buffer\n");
210
memcpy(ptr, input_string, 7 * sizeof(*input_string));
211
ok(WindowsPromoteStringBuffer(buf, &str) == S_OK, "Failed to promote string buffer\n");
212
check_string(str, input_string, 7, TRUE);
213
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string\n");
214
}
215
216
static void test_substring(void)
217
{
218
HSTRING str, substr;
219
HSTRING_HEADER header;
220
221
/* Test substring of string buffers */
222
ok(WindowsCreateString(input_string, 6, &str) == S_OK, "Failed to create string\n");
223
ok(WindowsSubstring(str, 2, &substr) == S_OK, "Failed to create substring\n");
224
check_string(substr, output_substring, 4, FALSE);
225
ok(WindowsDeleteString(substr) == S_OK, "Failed to delete string\n");
226
ok(WindowsSubstringWithSpecifiedLength(str, 2, 3, &substr) == S_OK, "Failed to create substring\n");
227
check_string(substr, output_substring, 3, FALSE);
228
ok(WindowsDeleteString(substr) == S_OK, "Failed to delete string\n");
229
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string\n");
230
231
/* Test duplication of string using substring */
232
ok(WindowsCreateString(input_string, 6, &str) == S_OK, "Failed to create string\n");
233
ok(WindowsSubstring(str, 0, &substr) == S_OK, "Failed to create substring\n");
234
ok(str != substr, "Duplicated string didn't create new string\n");
235
check_string(substr, input_string, 6, FALSE);
236
ok(WindowsDeleteString(substr) == S_OK, "Failed to delete string\n");
237
ok(WindowsSubstringWithSpecifiedLength(str, 0, 6, &substr) == S_OK, "Failed to create substring\n");
238
ok(str != substr, "Duplicated string didn't create new string\n");
239
check_string(substr, input_string, 6, FALSE);
240
ok(WindowsDeleteString(substr) == S_OK, "Failed to delete string\n");
241
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string\n");
242
243
/* Test substring of string reference */
244
ok(WindowsCreateStringReference(input_string, 6, &header, &str) == S_OK, "Failed to create string ref\n");
245
ok(WindowsSubstring(str, 2, &substr) == S_OK, "Failed to create substring of string ref\n");
246
check_string(substr, output_substring, 4, FALSE);
247
ok(WindowsDeleteString(substr) == S_OK, "Failed to delete string\n");
248
ok(WindowsSubstringWithSpecifiedLength(str, 2, 3, &substr) == S_OK, "Failed to create substring of string ref\n");
249
check_string(substr, output_substring, 3, FALSE);
250
ok(WindowsDeleteString(substr) == S_OK, "Failed to delete string\n");
251
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string ref\n");
252
253
/* Test duplication of string reference using substring */
254
ok(WindowsCreateStringReference(input_string, 6, &header, &str) == S_OK, "Failed to create string ref\n");
255
ok(WindowsSubstring(str, 0, &substr) == S_OK, "Failed to create substring of string ref\n");
256
ok(str != substr, "Duplicated string ref didn't create new string\n");
257
check_string(substr, input_string, 6, FALSE);
258
ok(WindowsDeleteString(substr) == S_OK, "Failed to delete string\n");
259
ok(WindowsSubstringWithSpecifiedLength(str, 0, 6, &substr) == S_OK, "Failed to create substring of string ref\n");
260
ok(str != substr, "Duplicated string ref didn't create new string\n");
261
check_string(substr, input_string, 6, FALSE);
262
ok(WindowsDeleteString(substr) == S_OK, "Failed to delete string\n");
263
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string ref\n");
264
265
/* Test get substring of empty string */
266
ok(WindowsSubstring(NULL, 0, &substr) == S_OK, "Failed to duplicate NULL string\n");
267
ok(substr == NULL, "Substring created new string\n");
268
ok(WindowsSubstringWithSpecifiedLength(NULL, 0, 0, &substr) == S_OK, "Failed to duplicate NULL string\n");
269
ok(substr == NULL, "Substring created new string\n");
270
271
/* Test get empty substring of string */
272
ok(WindowsCreateString(input_string, 6, &str) == S_OK, "Failed to create string\n");
273
ok(WindowsSubstring(str, 6, &substr) == S_OK, "Failed to create substring\n");
274
ok(substr == NULL, "Substring created new string\n");
275
ok(WindowsSubstringWithSpecifiedLength(str, 6, 0, &substr) == S_OK, "Failed to create substring\n");
276
ok(substr == NULL, "Substring created new string\n");
277
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string\n");
278
279
/* Test handling of using too high start index or length */
280
ok(WindowsCreateString(input_string, 6, &str) == S_OK, "Failed to create string\n");
281
ok(WindowsSubstring(str, 7, &substr) == E_BOUNDS, "Incorrect error handling\n");
282
ok(WindowsSubstringWithSpecifiedLength(str, 7, 0, &substr) == E_BOUNDS, "Incorrect error handling\n");
283
ok(WindowsSubstringWithSpecifiedLength(str, 6, 1, &substr) == E_BOUNDS, "Incorrect error handling\n");
284
ok(WindowsSubstringWithSpecifiedLength(str, 7, ~0U, &substr) == E_BOUNDS, "Incorrect error handling\n");
285
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string\n");
286
287
/* Test handling of a NULL string */
288
ok(WindowsCreateString(input_string, 6, &str) == S_OK, "Failed to create string\n");
289
ok(WindowsSubstring(str, 7, NULL) == E_INVALIDARG, "Incorrect error handling\n");
290
ok(WindowsSubstringWithSpecifiedLength(str, 7, 0, NULL) == E_INVALIDARG, "Incorrect error handling\n");
291
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string\n");
292
}
293
294
static void test_concat(void)
295
{
296
HSTRING str1, str2, concat;
297
HSTRING_HEADER header1, header2;
298
299
/* Test concatenation of string buffers */
300
ok(WindowsCreateString(input_string1, 3, &str1) == S_OK, "Failed to create string\n");
301
ok(WindowsCreateString(input_string2, 3, &str2) == S_OK, "Failed to create string\n");
302
303
ok(WindowsConcatString(str1, NULL, NULL) == E_INVALIDARG, "Incorrect error handling\n");
304
ok(WindowsConcatString(str1, NULL, &concat) == S_OK, "Failed to concatenate string\n");
305
ok(str1 == concat, "Concatenate created new string\n");
306
check_string(concat, input_string1, 3, FALSE);
307
ok(WindowsDeleteString(concat) == S_OK, "Failed to delete string\n");
308
309
ok(WindowsConcatString(NULL, str2, NULL) == E_INVALIDARG, "Incorrect error handling\n");
310
ok(WindowsConcatString(NULL, str2, &concat) == S_OK, "Failed to concatenate string\n");
311
ok(str2 == concat, "Concatenate created new string\n");
312
check_string(concat, input_string2, 3, FALSE);
313
ok(WindowsDeleteString(concat) == S_OK, "Failed to delete string\n");
314
315
ok(WindowsConcatString(str1, str2, NULL) == E_INVALIDARG, "Incorrect error handling\n");
316
ok(WindowsConcatString(str1, str2, &concat) == S_OK, "Failed to concatenate string\n");
317
check_string(concat, input_string, 6, FALSE);
318
ok(WindowsDeleteString(concat) == S_OK, "Failed to delete string\n");
319
320
ok(WindowsDeleteString(str2) == S_OK, "Failed to delete string\n");
321
ok(WindowsDeleteString(str1) == S_OK, "Failed to delete string\n");
322
323
/* Test concatenation of string references */
324
ok(WindowsCreateStringReference(input_string1, 3, &header1, &str1) == S_OK, "Failed to create string ref\n");
325
ok(WindowsCreateStringReference(input_string2, 3, &header2, &str2) == S_OK, "Failed to create string ref\n");
326
327
ok(WindowsConcatString(str1, NULL, &concat) == S_OK, "Failed to concatenate string\n");
328
ok(str1 != concat, "Concatenate string ref didn't create new string\n");
329
check_string(concat, input_string1, 3, FALSE);
330
ok(WindowsDeleteString(concat) == S_OK, "Failed to delete string\n");
331
332
ok(WindowsConcatString(NULL, str2, &concat) == S_OK, "Failed to concatenate string\n");
333
ok(str2 != concat, "Concatenate string ref didn't create new string\n");
334
check_string(concat, input_string2, 3, FALSE);
335
ok(WindowsDeleteString(concat) == S_OK, "Failed to delete string\n");
336
337
ok(WindowsConcatString(str1, str2, &concat) == S_OK, "Failed to concatenate string\n");
338
check_string(concat, input_string, 6, FALSE);
339
ok(WindowsDeleteString(concat) == S_OK, "Failed to delete string\n");
340
341
ok(WindowsDeleteString(str2) == S_OK, "Failed to delete string ref\n");
342
ok(WindowsDeleteString(str1) == S_OK, "Failed to delete string ref\n");
343
344
/* Test concatenation of two empty strings */
345
ok(WindowsConcatString(NULL, NULL, NULL) == E_INVALIDARG, "Incorrect error handling\n");
346
ok(WindowsConcatString(NULL, NULL, &concat) == S_OK, "Failed to concatenate string\n");
347
ok(concat == NULL, "Concatenate created new string\n");
348
}
349
350
static void test_compare(void)
351
{
352
HSTRING str1, str2;
353
HSTRING_HEADER header1, header2;
354
INT32 res;
355
356
/* Test comparison of string buffers */
357
ok(WindowsCreateString(input_string1, 3, &str1) == S_OK, "Failed to create string\n");
358
ok(WindowsCreateString(input_string2, 3, &str2) == S_OK, "Failed to create string\n");
359
360
ok(WindowsCompareStringOrdinal(str1, str1, &res) == S_OK, "Failed to compare string\n");
361
ok(res == 0, "Expected 0, got %d\n", res);
362
ok(WindowsCompareStringOrdinal(str1, str2, &res) == S_OK, "Failed to compare string\n");
363
ok(res == -1, "Expected -1, got %d\n", res);
364
ok(WindowsCompareStringOrdinal(str2, str1, &res) == S_OK, "Failed to compare string\n");
365
ok(res == 1, "Expected 1, got %d\n", res);
366
ok(WindowsCompareStringOrdinal(str2, str2, &res) == S_OK, "Failed to compare string\n");
367
ok(res == 0, "Expected 0, got %d\n", res);
368
ok(WindowsCompareStringOrdinal(str1, NULL, &res) == S_OK, "Failed to compare string\n");
369
ok(res == 1, "Expected 1, got %d\n", res);
370
ok(WindowsCompareStringOrdinal(NULL, str1, &res) == S_OK, "Failed to compare string\n");
371
ok(res == -1, "Expected -1, got %d\n", res);
372
ok(WindowsCompareStringOrdinal(str2, NULL, &res) == S_OK, "Failed to compare string\n");
373
ok(res == 1, "Expected 1, got %d\n", res);
374
ok(WindowsCompareStringOrdinal(NULL, str2, &res) == S_OK, "Failed to compare string\n");
375
ok(res == -1, "Expected -1, got %d\n", res);
376
377
ok(WindowsDeleteString(str2) == S_OK, "Failed to delete string\n");
378
ok(WindowsDeleteString(str1) == S_OK, "Failed to delete string\n");
379
380
/* Test comparison of string references */
381
ok(WindowsCreateStringReference(input_string1, 3, &header1, &str1) == S_OK, "Failed to create string ref\n");
382
ok(WindowsCreateStringReference(input_string2, 3, &header2, &str2) == S_OK, "Failed to create string ref\n");
383
384
ok(WindowsCompareStringOrdinal(str1, str1, &res) == S_OK, "Failed to compare string\n");
385
ok(res == 0, "Expected 0, got %d\n", res);
386
ok(WindowsCompareStringOrdinal(str1, str2, &res) == S_OK, "Failed to compare string\n");
387
ok(res == -1, "Expected -1, got %d\n", res);
388
ok(WindowsCompareStringOrdinal(str2, str1, &res) == S_OK, "Failed to compare string\n");
389
ok(res == 1, "Expected 1, got %d\n", res);
390
ok(WindowsCompareStringOrdinal(str2, str2, &res) == S_OK, "Failed to compare string\n");
391
ok(res == 0, "Expected 0, got %d\n", res);
392
ok(WindowsCompareStringOrdinal(str1, NULL, &res) == S_OK, "Failed to compare string\n");
393
ok(res == 1, "Expected 1, got %d\n", res);
394
ok(WindowsCompareStringOrdinal(NULL, str1, &res) == S_OK, "Failed to compare string\n");
395
ok(res == -1, "Expected -1, got %d\n", res);
396
ok(WindowsCompareStringOrdinal(str2, NULL, &res) == S_OK, "Failed to compare string\n");
397
ok(res == 1, "Expected 1, got %d\n", res);
398
ok(WindowsCompareStringOrdinal(NULL, str2, &res) == S_OK, "Failed to compare string\n");
399
ok(res == -1, "Expected -1, got %d\n", res);
400
401
ok(WindowsDeleteString(str2) == S_OK, "Failed to delete string ref\n");
402
ok(WindowsDeleteString(str1) == S_OK, "Failed to delete string ref\n");
403
404
/* Test comparison of two empty strings */
405
ok(WindowsCompareStringOrdinal(NULL, NULL, NULL) == E_INVALIDARG, "Incorrect error handling\n");
406
ok(WindowsCompareStringOrdinal(NULL, NULL, &res) == S_OK, "Failed to compare NULL string\n");
407
ok(res == 0, "Expected 0, got %d\n", res);
408
}
409
410
static void test_trim(void)
411
{
412
HSTRING str1, str2, trimmed;
413
HSTRING_HEADER header1, header2;
414
415
/* Test trimming of string buffers */
416
ok(WindowsCreateString(input_string, 6, &str1) == S_OK, "Failed to create string\n");
417
ok(WindowsCreateString(input_string1, 3, &str2) == S_OK, "Failed to create string\n");
418
419
ok(WindowsTrimStringStart(str1, str2, &trimmed) == S_OK, "Failed to trim string\n");
420
check_string(trimmed, input_string2, 3, FALSE);
421
ok(WindowsDeleteString(trimmed) == S_OK, "Failed to delete string\n");
422
ok(WindowsTrimStringEnd(str1, str2, &trimmed) == S_OK, "Failed to trim string\n");
423
ok(trimmed == str1, "Trimmed string created new string\n");
424
check_string(trimmed, input_string, 6, FALSE);
425
ok(WindowsDeleteString(trimmed) == S_OK, "Failed to delete string\n");
426
427
ok(WindowsDeleteString(str2) == S_OK, "Failed to delete string\n");
428
ok(WindowsCreateString(input_string2, 3, &str2) == S_OK, "Failed to create string\n");
429
430
ok(WindowsTrimStringStart(str1, str2, &trimmed) == S_OK, "Failed to trim string\n");
431
ok(trimmed == str1, "Trimmed string created new string\n");
432
check_string(trimmed, input_string, 6, FALSE);
433
ok(WindowsDeleteString(trimmed) == S_OK, "Failed to delete string\n");
434
ok(WindowsTrimStringEnd(str1, str2, &trimmed) == S_OK, "Failed to trim string\n");
435
check_string(trimmed, input_string1, 3, FALSE);
436
ok(WindowsDeleteString(trimmed) == S_OK, "Failed to delete string\n");
437
438
ok(WindowsDeleteString(str2) == S_OK, "Failed to delete string\n");
439
ok(WindowsDeleteString(str1) == S_OK, "Failed to delete string\n");
440
441
/* Test trimming of string references */
442
ok(WindowsCreateStringReference(input_string, 6, &header1, &str1) == S_OK, "Failed to create string ref\n");
443
ok(WindowsCreateStringReference(input_string1, 3, &header2, &str2) == S_OK, "Failed to create string ref\n");
444
445
ok(WindowsTrimStringStart(str1, str2, &trimmed) == S_OK, "Failed to trim string\n");
446
check_string(trimmed, input_string2, 3, FALSE);
447
ok(WindowsDeleteString(trimmed) == S_OK, "Failed to delete string\n");
448
ok(WindowsTrimStringEnd(str1, str2, &trimmed) == S_OK, "Failed to trim string\n");
449
ok(trimmed != str1, "Trimmed string ref didn't create new string\n");
450
check_string(trimmed, input_string, 6, FALSE);
451
ok(WindowsDeleteString(trimmed) == S_OK, "Failed to delete string\n");
452
453
ok(WindowsDeleteString(str2) == S_OK, "Failed to delete string ref\n");
454
ok(WindowsCreateStringReference(input_string2, 3, &header2, &str2) == S_OK, "Failed to create string ref\n");
455
456
ok(WindowsTrimStringStart(str1, str2, &trimmed) == S_OK, "Failed to trim string\n");
457
ok(trimmed != str1, "Trimmed string ref didn't create new string\n");
458
check_string(trimmed, input_string, 6, FALSE);
459
ok(WindowsDeleteString(trimmed) == S_OK, "Failed to delete string\n");
460
ok(WindowsTrimStringEnd(str1, str2, &trimmed) == S_OK, "Failed to trim string\n");
461
check_string(trimmed, input_string1, 3, FALSE);
462
ok(WindowsDeleteString(trimmed) == S_OK, "Failed to delete string\n");
463
464
ok(WindowsDeleteString(str2) == S_OK, "Failed to delete string ref\n");
465
ok(WindowsDeleteString(str1) == S_OK, "Failed to delete string ref\n");
466
467
/* Test handling of NULL strings */
468
ok(WindowsCreateString(input_string, 6, &str1) == S_OK, "Failed to create string\n");
469
ok(WindowsTrimStringStart(NULL, NULL, NULL) == E_INVALIDARG, "Incorrect error handling\n");
470
ok(WindowsTrimStringStart(NULL, str1, NULL) == E_INVALIDARG, "Incorrect error handling\n");
471
ok(WindowsTrimStringStart(NULL, NULL, &trimmed) == E_INVALIDARG, "Incorrect error handling\n");
472
ok(WindowsTrimStringStart(NULL, str1, &trimmed) == S_OK, "Failed to trim empty string\n");
473
ok(trimmed == NULL, "Trimming created new string\n");
474
ok(WindowsTrimStringEnd(NULL, NULL, NULL) == E_INVALIDARG, "Incorrect error handling\n");
475
ok(WindowsTrimStringEnd(NULL, str1, NULL) == E_INVALIDARG, "Incorrect error handling\n");
476
ok(WindowsTrimStringEnd(NULL, NULL, &trimmed) == E_INVALIDARG, "Incorrect error handling\n");
477
ok(WindowsTrimStringEnd(NULL, str1, &trimmed) == S_OK, "Failed to trim empty string\n");
478
ok(trimmed == NULL, "Trimming created new string\n");
479
ok(WindowsDeleteString(str1) == S_OK, "Failed to delete string\n");
480
}
481
482
static void test_hstring_struct(void)
483
{
484
struct hstring_header
485
{
486
UINT32 flags;
487
UINT32 length;
488
UINT32 padding1;
489
UINT32 padding2;
490
const WCHAR *str;
491
};
492
493
struct hstring_private
494
{
495
struct hstring_header header;
496
LONG refcount;
497
WCHAR buffer[1];
498
};
499
500
HSTRING str;
501
HSTRING str2;
502
HSTRING_HEADER hdr;
503
struct hstring_private* prv;
504
struct hstring_private* prv2;
505
506
BOOL arch64 = (sizeof(void*) == 8);
507
508
ok(arch64 ? (sizeof(prv->header) == 24) : (sizeof(prv->header) == 20), "hstring_header size incorrect.\n");
509
510
ok(WindowsCreateString(input_string, 6, &str) == S_OK, "Failed to create string.\n");
511
512
prv = CONTAINING_RECORD(str, struct hstring_private, header);
513
514
ok(prv->header.flags == 0, "Expected 0 in flags field, got %#x.\n", prv->header.flags);
515
ok(prv->header.length == 6, "Expected 6 in length field, got %u.\n", prv->header.length);
516
ok(prv->header.str == prv->buffer, "Expected str to point at buffer, instead pointing at %p.\n", prv->header.str);
517
ok(prv->refcount == 1, "Expected 1 in refcount, got %lu.\n", prv->refcount);
518
ok(wcscmp(input_string, prv->buffer) == 0, "Expected strings to match.\n");
519
ok(prv->buffer[prv->header.length] == '\0', "Expected buffer to be null terminated.\n");
520
521
ok(WindowsDuplicateString(str, &str2) == S_OK, "Failed to duplicate string.\n");
522
523
prv2 = CONTAINING_RECORD(str2, struct hstring_private, header);
524
525
ok(prv->refcount == 2, "Expected 2 in refcount, got %lu.\n", prv->refcount);
526
ok(prv2->refcount == 2, "Expected 2 in refcount, got %lu.\n", prv2->refcount);
527
ok(wcscmp(input_string, prv2->buffer) == 0, "Expected strings to match.\n");
528
529
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string.\n");
530
531
ok(prv->refcount == 1, "Expected 1 in refcount, got %lu.\n", prv->refcount);
532
533
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string.\n");
534
535
ok(WindowsCreateStringReference(input_string, 6, &hdr, &str) == S_OK, "Failed to create string ref.\n");
536
537
prv = CONTAINING_RECORD(&hdr, struct hstring_private, header);
538
prv2 = CONTAINING_RECORD(str, struct hstring_private, header);
539
540
ok(prv == prv2, "Pointers not identical.\n");
541
ok(prv2->header.flags == 1, "Expected HSTRING_REFERENCE_FLAG to be set, got %#x.\n", prv2->header.flags);
542
ok(prv2->header.length == 6, "Expected 6 in length field, got %u.\n", prv2->header.length);
543
ok(prv2->header.str == input_string, "Expected str to point at input_string, instead pointing at %p.\n", prv2->header.str);
544
545
ok(WindowsDeleteString(str) == S_OK, "Failed to delete string ref.\n");
546
}
547
548
static void * WINAPI user_allocate(SIZE_T size)
549
{
550
ok(0, "unexpected user_allocate call\n");
551
return CoTaskMemAlloc(size);
552
}
553
554
static void WINAPI user_free(void *p)
555
{
556
ok(0, "unexpected user_free call\n");
557
CoTaskMemFree(p);
558
}
559
560
static void init_user_marshal_cb(USER_MARSHAL_CB *umcb,
561
PMIDL_STUB_MESSAGE stub_msg,
562
PRPC_MESSAGE rpc_msg, unsigned char *buffer,
563
unsigned int size, MSHCTX context)
564
{
565
memset(rpc_msg, 0, sizeof(*rpc_msg));
566
rpc_msg->Buffer = buffer;
567
rpc_msg->BufferLength = size;
568
569
memset(stub_msg, 0, sizeof(*stub_msg));
570
stub_msg->RpcMsg = rpc_msg;
571
stub_msg->Buffer = buffer;
572
stub_msg->pfnAllocate = user_allocate;
573
stub_msg->pfnFree = user_free;
574
575
memset(umcb, 0, sizeof(*umcb));
576
umcb->Flags = MAKELONG(context, NDR_LOCAL_DATA_REPRESENTATION);
577
umcb->pStubMsg = stub_msg;
578
umcb->Signature = USER_MARSHAL_CB_SIGNATURE;
579
umcb->CBType = buffer ? USER_MARSHAL_CB_UNMARSHALL : USER_MARSHAL_CB_BUFFER_SIZE;
580
}
581
582
#define ALIGNED_LENGTH(_Len, _Align) (((_Len)+(_Align))&~(_Align))
583
#define ALIGNED_POINTER(_Ptr, _Align) ((LPVOID)ALIGNED_LENGTH((ULONG_PTR)(_Ptr), _Align))
584
585
static void test_marshal(void)
586
{
587
struct hstring_wire_inproc
588
{
589
ULONG context;
590
HSTRING str;
591
};
592
593
struct hstring_wire_local
594
{
595
ULONG context;
596
ULONG size;
597
WCHAR data[1];
598
};
599
600
const ULONG exp_context = sizeof(void *) == 8 ? WDT_INPROC64_CALL : WDT_INPROC_CALL;
601
static const WCHAR str_buf[] = L"marshal_test1";
602
static const ULONG str_len = ARRAY_SIZE(str_buf) - 1;
603
static const ULONG str_bytes = str_len * sizeof(WCHAR);
604
HSTRING str, str_empty = NULL, str2 = NULL;
605
struct hstring_wire_inproc *inproc;
606
struct hstring_wire_local *local;
607
MIDL_STUB_MESSAGE stub_msg;
608
USER_MARSHAL_CB umcb;
609
ULONG size, exp_size;
610
RPC_MESSAGE rpc_msg;
611
BYTE *next, *buffer;
612
INT32 result = -1;
613
HRESULT hr;
614
615
buffer = calloc(1, 80);
616
617
hr = WindowsCreateString(str_buf, wcslen(str_buf), &str);
618
ok(hr == S_OK, "got hr %#lx\n", hr);
619
620
/* INPROC marshaling */
621
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC);
622
size = HSTRING_UserSize(&umcb.Flags, 0, &str);
623
exp_size = sizeof(*inproc);
624
ok(size == exp_size, "got size %lu != %lu\n", size, exp_size);
625
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_INPROC);
626
next = HSTRING_UserMarshal(&umcb.Flags, buffer, &str);
627
ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]);
628
inproc = (struct hstring_wire_inproc *)buffer;
629
ok(inproc->context == exp_context, "got unexpected prefix %#lx != %#lx\n", inproc->context, exp_context);
630
/* INPROC marshaling just consists of increasing the refcount and copying the address. */
631
ok(inproc->str == str, "got unexpected address %p\n", inproc->str);
632
inproc->context = 0xdeadbeef; /* The context value is not validated. */
633
next = HSTRING_UserUnmarshal(&umcb.Flags, buffer, &str2);
634
ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]);
635
ok(str2 == str, "got str2 %p != %p\n", str2, str);
636
HSTRING_UserFree(&umcb.Flags, &str2);
637
638
/* Test alignment */
639
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC);
640
size = HSTRING_UserSize(&umcb.Flags, 1, &str);
641
exp_size = ALIGNED_LENGTH(1 + sizeof(*inproc), 7);
642
ok(size == exp_size, "got size %lu != %lu\n", size, exp_size);
643
memset(buffer, 0, 80);
644
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_INPROC);
645
next = HSTRING_UserMarshal(&umcb.Flags, &buffer[1], &str);
646
ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]);
647
inproc = ALIGNED_POINTER(&buffer[1], 7);
648
ok(inproc->context == exp_context, "got unexpected prefix %#lx != %#lx\n", inproc->context, exp_context);
649
ok(inproc->str == str, "got unexpected address %p\n", inproc->str);
650
next = HSTRING_UserUnmarshal(&umcb.Flags, &buffer[1], &str2);
651
ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]);
652
ok(str2 == str, "got str2 %p != %p\n", str2, str);
653
HSTRING_UserFree(&umcb.Flags, &str2);
654
655
/* INPROC marshaling with empty/NULL HSTRING */
656
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_INPROC);
657
size = HSTRING_UserSize(&umcb.Flags, 0, &str_empty);
658
exp_size = sizeof(*inproc);
659
ok(size == exp_size, "got size %lu != %lu\n", size, exp_size);
660
memset(buffer, 0xff, 80);
661
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_INPROC);
662
next = HSTRING_UserMarshal(&umcb.Flags, buffer, &str_empty);
663
ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]);
664
inproc = (struct hstring_wire_inproc *)buffer;
665
ok(inproc->context == exp_context, "got unexpected prefix %#lx != %#lx\n", inproc->context, exp_context);
666
ok(!inproc->str, "got unexpected address %p\n", inproc->str);
667
str2 = NULL;
668
next = HSTRING_UserUnmarshal(&umcb.Flags, buffer, &str2);
669
ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]);
670
ok(!str2, "got str2 %p\n", str2);
671
HSTRING_UserFree(&umcb.Flags, &str2);
672
673
/* Out of process marshaling */
674
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
675
size = HSTRING_UserSize(&umcb.Flags, 0, &str);
676
exp_size = offsetof(struct hstring_wire_local, data[str_len]);
677
ok(size == exp_size, "got size %lu != %lu\n", size, exp_size);
678
memset(buffer, 0, 80);
679
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
680
next = HSTRING_UserMarshal(&umcb.Flags, buffer, &str);
681
ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]);
682
local = (struct hstring_wire_local *)buffer;
683
ok(local->size == str_bytes, "got buf.size %lu != %lu\n", local->size, str_bytes);
684
ok(local->context == exp_context, "got unexpected prefix %#lx != %#lx\n", local->context, exp_context);
685
ok(!memcmp(local->data, str_buf, str_bytes), "got buf.data %s\n", debugstr_wn(local->data, str_bytes));
686
str2 = NULL;
687
local->context = 0xdeadbeef; /* The context value is not validated. */
688
next = HSTRING_UserUnmarshal(&umcb.Flags, buffer, &str2);
689
ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]);
690
/* A new HSTRING should be allocated */
691
ok(str2 != str, "got str2 %p\n", str2);
692
hr = WindowsCompareStringOrdinal(str2, str, &result);
693
ok(hr == S_OK, "got hr %#lx\n", hr);
694
ok(!result, "got str2 %s != %s\n", debugstr_hstring(str2), debugstr_hstring(str));
695
HSTRING_UserFree(&umcb.Flags, &str2);
696
697
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
698
size = HSTRING_UserSize(&umcb.Flags, 1, &str);
699
exp_size = ALIGNED_LENGTH(1, 7) + offsetof(struct hstring_wire_local, data[str_len]);
700
ok(size == exp_size, "got size %lu != %lu\n", size, exp_size);
701
memset(buffer, 0, 80);
702
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
703
next = HSTRING_UserMarshal(&umcb.Flags, &buffer[1], &str);
704
ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]);
705
local = ALIGNED_POINTER(&buffer[1], 7);
706
ok(local->size == str_bytes, "got buf.size %lu != %lu\n", local->size, str_bytes);
707
ok(local->context == exp_context, "got unexpected prefix %#lx != %#lx\n", local->context, exp_context);
708
ok(!memcmp(local->data, str_buf, str_bytes), "got buf.data %s\n", debugstr_wn(local->data, str_bytes));
709
next = HSTRING_UserUnmarshal(&umcb.Flags, &buffer[1], &str2);
710
ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]);
711
ok(str2 != str, "got str2 %p\n", str2);
712
result = -1;
713
hr = WindowsCompareStringOrdinal(str2, str, &result);
714
ok(hr == S_OK, "got hr %#lx\n", hr);
715
ok(!result, "got str2 %s != %s\n", debugstr_hstring(str2), debugstr_hstring(str));
716
HSTRING_UserFree(&umcb.Flags, &str2);
717
718
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, NULL, 0, MSHCTX_LOCAL);
719
size = HSTRING_UserSize(&umcb.Flags, 0, &str_empty);
720
exp_size = offsetof(struct hstring_wire_local, data[0]);
721
ok(size == exp_size, "got size %lu != %lu\n", size, exp_size);
722
memset(buffer, 0xff, 80);
723
init_user_marshal_cb(&umcb, &stub_msg, &rpc_msg, buffer, size, MSHCTX_LOCAL);
724
next = HSTRING_UserMarshal(&umcb.Flags, buffer, &str_empty);
725
ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]);
726
local = (struct hstring_wire_local *)buffer;
727
ok(local->context == exp_context, "got unexpected prefix %#lx != %#lx\n", local->context, exp_context);
728
ok(!local->size, "got buf.size %lu\n", local->size);
729
str2 = NULL;
730
next = HSTRING_UserUnmarshal(&umcb.Flags, buffer, &str2);
731
ok(next == &buffer[size], "got next %p != %p\n", next, &buffer[size]);
732
ok(!str2, "got str2 %p\n", str2);
733
HSTRING_UserFree(&umcb.Flags, &str2);
734
735
WindowsDeleteString(str);
736
free(buffer);
737
}
738
739
START_TEST(string)
740
{
741
test_create_delete();
742
test_duplicate();
743
test_access();
744
test_string_buffer();
745
test_substring();
746
test_concat();
747
test_compare();
748
test_trim();
749
test_hstring_struct();
750
test_marshal();
751
}
752
753