Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/combase/string.c
4389 views
1
/*
2
* Copyright 2014 Martin Storsjo
3
*
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2.1 of the License, or (at your option) any later version.
8
*
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
13
*
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17
*/
18
19
#include <string.h>
20
#include <wchar.h>
21
22
#include "windows.h"
23
#include "winerror.h"
24
#include "hstring.h"
25
#include "wine/debug.h"
26
27
WINE_DEFAULT_DEBUG_CHANNEL(winstring);
28
29
#define HSTRING_REFERENCE_FLAG 1
30
31
struct hstring_header
32
{
33
UINT32 flags;
34
UINT32 length;
35
UINT32 padding1;
36
UINT32 padding2;
37
const WCHAR *str;
38
};
39
40
struct hstring_private
41
{
42
struct hstring_header header;
43
LONG refcount;
44
WCHAR buffer[1];
45
};
46
47
static const WCHAR empty[1];
48
49
C_ASSERT(sizeof(struct hstring_header) <= sizeof(HSTRING_HEADER));
50
51
static inline struct hstring_private *impl_from_HSTRING(HSTRING string)
52
{
53
return (struct hstring_private *)string;
54
}
55
56
static inline struct hstring_private *impl_from_HSTRING_HEADER(HSTRING_HEADER *header)
57
{
58
return CONTAINING_RECORD(header, struct hstring_private, header);
59
}
60
61
static inline struct hstring_private *impl_from_HSTRING_BUFFER(HSTRING_BUFFER buffer)
62
{
63
return CONTAINING_RECORD(buffer, struct hstring_private, buffer);
64
}
65
66
static BOOL alloc_string(UINT32 len, HSTRING *out)
67
{
68
struct hstring_private *priv;
69
priv = malloc(offsetof(struct hstring_private, buffer[len+1]));
70
if (!priv)
71
return FALSE;
72
73
priv->header.flags = 0;
74
priv->header.length = len;
75
priv->header.str = priv->buffer;
76
77
priv->refcount = 1;
78
priv->buffer[len] = '\0';
79
80
*out = (HSTRING)priv;
81
return TRUE;
82
}
83
84
/***********************************************************************
85
* WindowsCreateString (combase.@)
86
*/
87
HRESULT WINAPI WindowsCreateString(LPCWSTR ptr, UINT32 len,
88
HSTRING *out)
89
{
90
struct hstring_private *priv;
91
92
TRACE("(%s, %u, %p)\n", debugstr_wn(ptr, len), len, out);
93
94
if (out == NULL)
95
return E_INVALIDARG;
96
if (len == 0)
97
{
98
*out = NULL;
99
return S_OK;
100
}
101
if (ptr == NULL)
102
return E_POINTER;
103
if (!alloc_string(len, out))
104
return E_OUTOFMEMORY;
105
priv = impl_from_HSTRING(*out);
106
memcpy(priv->buffer, ptr, len * sizeof(*priv->buffer));
107
return S_OK;
108
}
109
110
/***********************************************************************
111
* WindowsCreateStringReference (combase.@)
112
*/
113
HRESULT WINAPI WindowsCreateStringReference(LPCWSTR ptr, UINT32 len,
114
HSTRING_HEADER *header, HSTRING *out)
115
{
116
struct hstring_private *priv = impl_from_HSTRING_HEADER(header);
117
118
TRACE("(%s, %u, %p, %p)\n", debugstr_wn(ptr, len), len, header, out);
119
120
if (out == NULL || header == NULL)
121
return E_INVALIDARG;
122
if (ptr != NULL && ptr[len] != '\0')
123
return E_INVALIDARG;
124
if (len == 0)
125
{
126
*out = NULL;
127
return S_OK;
128
}
129
if (ptr == NULL)
130
return E_POINTER;
131
132
priv->header.str = ptr;
133
priv->header.length = len;
134
priv->header.flags = HSTRING_REFERENCE_FLAG;
135
136
*out = (HSTRING)priv;
137
return S_OK;
138
}
139
140
/***********************************************************************
141
* WindowsDeleteString (combase.@)
142
*/
143
HRESULT WINAPI WindowsDeleteString(HSTRING str)
144
{
145
struct hstring_private *priv = impl_from_HSTRING(str);
146
147
TRACE("(%p)\n", str);
148
149
if (str == NULL)
150
return S_OK;
151
if (priv->header.flags & HSTRING_REFERENCE_FLAG)
152
return S_OK;
153
if (InterlockedDecrement(&priv->refcount) == 0)
154
free(priv);
155
return S_OK;
156
}
157
158
/***********************************************************************
159
* WindowsDuplicateString (combase.@)
160
*/
161
HRESULT WINAPI WindowsDuplicateString(HSTRING str, HSTRING *out)
162
{
163
struct hstring_private *priv = impl_from_HSTRING(str);
164
165
TRACE("(%p, %p)\n", str, out);
166
167
if (out == NULL)
168
return E_INVALIDARG;
169
if (str == NULL)
170
{
171
*out = NULL;
172
return S_OK;
173
}
174
if (priv->header.flags & HSTRING_REFERENCE_FLAG)
175
return WindowsCreateString(priv->header.str, priv->header.length, out);
176
InterlockedIncrement(&priv->refcount);
177
*out = str;
178
return S_OK;
179
}
180
181
/***********************************************************************
182
* WindowsPreallocateStringBuffer (combase.@)
183
*/
184
HRESULT WINAPI WindowsPreallocateStringBuffer(UINT32 len, WCHAR **outptr,
185
HSTRING_BUFFER *out)
186
{
187
struct hstring_private *priv;
188
HSTRING str;
189
190
TRACE("(%u, %p, %p)\n", len, outptr, out);
191
192
if (outptr == NULL || out == NULL)
193
return E_POINTER;
194
if (len == 0)
195
{
196
*outptr = (LPWSTR)empty;
197
*out = NULL;
198
return S_OK;
199
}
200
201
if (!alloc_string(len, &str))
202
return E_OUTOFMEMORY;
203
priv = impl_from_HSTRING(str);
204
*outptr = priv->buffer;
205
*out = (HSTRING_BUFFER)&priv->buffer;
206
return S_OK;
207
}
208
209
/***********************************************************************
210
* WindowsDeleteStringBuffer (combase.@)
211
*/
212
HRESULT WINAPI WindowsDeleteStringBuffer(HSTRING_BUFFER buf)
213
{
214
struct hstring_private *priv = NULL;
215
216
TRACE("(%p)\n", buf);
217
218
if(buf)
219
priv = impl_from_HSTRING_BUFFER(buf);
220
221
return WindowsDeleteString((HSTRING)priv);
222
}
223
224
/***********************************************************************
225
* WindowsPromoteStringBuffer (combase.@)
226
*/
227
HRESULT WINAPI WindowsPromoteStringBuffer(HSTRING_BUFFER buf, HSTRING *out)
228
{
229
struct hstring_private *priv = impl_from_HSTRING_BUFFER(buf);
230
231
TRACE("(%p, %p)\n", buf, out);
232
233
if (out == NULL)
234
return E_POINTER;
235
if (buf == NULL)
236
{
237
*out = NULL;
238
return S_OK;
239
}
240
if (priv->buffer[priv->header.length] != 0 || priv->header.flags & HSTRING_REFERENCE_FLAG || priv->refcount != 1)
241
return E_INVALIDARG;
242
*out = (HSTRING)priv;
243
return S_OK;
244
}
245
246
/***********************************************************************
247
* WindowsGetStringLen (combase.@)
248
*/
249
UINT32 WINAPI WindowsGetStringLen(HSTRING str)
250
{
251
struct hstring_private *priv = impl_from_HSTRING(str);
252
253
TRACE("(%p)\n", str);
254
255
if (str == NULL)
256
return 0;
257
return priv->header.length;
258
}
259
260
/***********************************************************************
261
* WindowsGetStringRawBuffer (combase.@)
262
*/
263
LPCWSTR WINAPI WindowsGetStringRawBuffer(HSTRING str, UINT32 *len)
264
{
265
struct hstring_private *priv = impl_from_HSTRING(str);
266
267
TRACE("(%p, %p)\n", str, len);
268
269
if (str == NULL)
270
{
271
if (len)
272
*len = 0;
273
return empty;
274
}
275
if (len)
276
*len = priv->header.length;
277
return priv->header.str;
278
}
279
280
/***********************************************************************
281
* WindowsStringHasEmbeddedNull (combase.@)
282
*/
283
HRESULT WINAPI WindowsStringHasEmbeddedNull(HSTRING str, BOOL *out)
284
{
285
UINT32 i;
286
struct hstring_private *priv = impl_from_HSTRING(str);
287
288
TRACE("(%p, %p)\n", str, out);
289
290
if (out == NULL)
291
return E_INVALIDARG;
292
if (str == NULL)
293
{
294
*out = FALSE;
295
return S_OK;
296
}
297
for (i = 0; i < priv->header.length; i++)
298
{
299
if (priv->header.str[i] == '\0')
300
{
301
*out = TRUE;
302
return S_OK;
303
}
304
}
305
*out = FALSE;
306
return S_OK;
307
}
308
309
/***********************************************************************
310
* WindowsSubstring (combase.@)
311
*/
312
HRESULT WINAPI WindowsSubstring(HSTRING str, UINT32 start, HSTRING *out)
313
{
314
struct hstring_private *priv = impl_from_HSTRING(str);
315
UINT32 len = WindowsGetStringLen(str);
316
317
TRACE("(%p, %u, %p)\n", str, start, out);
318
319
if (out == NULL)
320
return E_INVALIDARG;
321
if (start > len)
322
return E_BOUNDS;
323
if (start == len)
324
{
325
*out = NULL;
326
return S_OK;
327
}
328
return WindowsCreateString(&priv->header.str[start], len - start, out);
329
}
330
331
/***********************************************************************
332
* WindowsSubstringWithSpecifiedLength (combase.@)
333
*/
334
HRESULT WINAPI WindowsSubstringWithSpecifiedLength(HSTRING str, UINT32 start, UINT32 len, HSTRING *out)
335
{
336
struct hstring_private *priv = impl_from_HSTRING(str);
337
338
TRACE("(%p, %u, %u, %p)\n", str, start, len, out);
339
340
if (out == NULL)
341
return E_INVALIDARG;
342
if (start + len < start ||
343
start + len > WindowsGetStringLen(str))
344
return E_BOUNDS;
345
if (len == 0)
346
{
347
*out = NULL;
348
return S_OK;
349
}
350
return WindowsCreateString(&priv->header.str[start], len, out);
351
}
352
353
/***********************************************************************
354
* WindowsConcatString (combase.@)
355
*/
356
HRESULT WINAPI WindowsConcatString(HSTRING str1, HSTRING str2, HSTRING *out)
357
{
358
struct hstring_private *priv1 = impl_from_HSTRING(str1);
359
struct hstring_private *priv2 = impl_from_HSTRING(str2);
360
struct hstring_private *priv;
361
362
TRACE("(%p, %p, %p)\n", str1, str2, out);
363
364
if (out == NULL)
365
return E_INVALIDARG;
366
if (str1 == NULL)
367
return WindowsDuplicateString(str2, out);
368
if (str2 == NULL)
369
return WindowsDuplicateString(str1, out);
370
if (!priv1->header.length && !priv2->header.length)
371
{
372
*out = NULL;
373
return S_OK;
374
}
375
if (!alloc_string(priv1->header.length + priv2->header.length, out))
376
return E_OUTOFMEMORY;
377
priv = impl_from_HSTRING(*out);
378
memcpy(priv->buffer, priv1->header.str, priv1->header.length * sizeof(*priv1->buffer));
379
memcpy(priv->buffer + priv1->header.length, priv2->header.str, priv2->header.length * sizeof(*priv2->buffer));
380
return S_OK;
381
}
382
383
/***********************************************************************
384
* WindowsIsStringEmpty (combase.@)
385
*/
386
BOOL WINAPI WindowsIsStringEmpty(HSTRING str)
387
{
388
struct hstring_private *priv = impl_from_HSTRING(str);
389
390
TRACE("(%p)\n", str);
391
392
if (str == NULL)
393
return TRUE;
394
return priv->header.length == 0;
395
}
396
397
/***********************************************************************
398
* WindowsCompareStringOrdinal (combase.@)
399
*/
400
HRESULT WINAPI WindowsCompareStringOrdinal(HSTRING str1, HSTRING str2, INT32 *res)
401
{
402
struct hstring_private *priv1 = impl_from_HSTRING(str1);
403
struct hstring_private *priv2 = impl_from_HSTRING(str2);
404
const WCHAR *buf1 = empty, *buf2 = empty;
405
UINT32 len1 = 0, len2 = 0;
406
407
TRACE("(%p, %p, %p)\n", str1, str2, res);
408
409
if (res == NULL)
410
return E_INVALIDARG;
411
if (str1 == str2)
412
{
413
*res = 0;
414
return S_OK;
415
}
416
if (str1)
417
{
418
buf1 = priv1->header.str;
419
len1 = priv1->header.length;
420
}
421
if (str2)
422
{
423
buf2 = priv2->header.str;
424
len2 = priv2->header.length;
425
}
426
*res = CompareStringOrdinal(buf1, len1, buf2, len2, FALSE) - CSTR_EQUAL;
427
return S_OK;
428
}
429
430
/***********************************************************************
431
* WindowsTrimStringStart (combase.@)
432
*/
433
HRESULT WINAPI WindowsTrimStringStart(HSTRING str1, HSTRING str2, HSTRING *out)
434
{
435
struct hstring_private *priv1 = impl_from_HSTRING(str1);
436
struct hstring_private *priv2 = impl_from_HSTRING(str2);
437
UINT32 start;
438
439
TRACE("(%p, %p, %p)\n", str1, str2, out);
440
441
if (!out || !str2 || !priv2->header.length)
442
return E_INVALIDARG;
443
if (!str1)
444
{
445
*out = NULL;
446
return S_OK;
447
}
448
for (start = 0; start < priv1->header.length; start++)
449
{
450
if (!wmemchr(priv2->header.str, priv1->header.str[start], priv2->header.length))
451
break;
452
}
453
return start ? WindowsCreateString(&priv1->header.str[start], priv1->header.length - start, out) :
454
WindowsDuplicateString(str1, out);
455
}
456
457
/***********************************************************************
458
* WindowsTrimStringEnd (combase.@)
459
*/
460
HRESULT WINAPI WindowsTrimStringEnd(HSTRING str1, HSTRING str2, HSTRING *out)
461
{
462
struct hstring_private *priv1 = impl_from_HSTRING(str1);
463
struct hstring_private *priv2 = impl_from_HSTRING(str2);
464
UINT32 len;
465
466
TRACE("(%p, %p, %p)\n", str1, str2, out);
467
468
if (!out || !str2 || !priv2->header.length)
469
return E_INVALIDARG;
470
if (!str1)
471
{
472
*out = NULL;
473
return S_OK;
474
}
475
for (len = priv1->header.length; len > 0; len--)
476
{
477
if (!wmemchr(priv2->header.str, priv1->header.str[len - 1], priv2->header.length))
478
break;
479
}
480
return (len < priv1->header.length) ? WindowsCreateString(priv1->header.str, len, out) :
481
WindowsDuplicateString(str1, out);
482
}
483
484