2 * Copyright 2014 Martin Storsjo
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.
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.
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
24 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(winstring
);
28 struct hstring_private
36 static const WCHAR empty
[1];
38 C_ASSERT(sizeof(struct hstring_private
) <= sizeof(HSTRING_HEADER
));
40 static inline struct hstring_private
*impl_from_HSTRING(HSTRING string
)
42 return (struct hstring_private
*)string
;
45 static inline struct hstring_private
*impl_from_HSTRING_HEADER(HSTRING_HEADER
*header
)
47 return (struct hstring_private
*)header
;
50 static inline struct hstring_private
*impl_from_HSTRING_BUFFER(HSTRING_BUFFER buffer
)
52 return (struct hstring_private
*)buffer
;
55 static BOOL
alloc_string(UINT32 len
, HSTRING
*out
)
57 struct hstring_private
*priv
;
58 priv
= HeapAlloc(GetProcessHeap(), 0, sizeof(*priv
) + (len
+ 1) * sizeof(*priv
->buffer
));
61 priv
->buffer
= (LPWSTR
)(priv
+ 1);
63 priv
->reference
= FALSE
;
65 priv
->buffer
[len
] = '\0';
70 /***********************************************************************
71 * WindowsCreateString (combase.@)
73 HRESULT WINAPI
WindowsCreateString(LPCWSTR ptr
, UINT32 len
,
76 struct hstring_private
*priv
;
78 TRACE("(%s, %u, %p)\n", debugstr_wn(ptr
, len
), len
, out
);
89 if (!alloc_string(len
, out
))
91 priv
= impl_from_HSTRING(*out
);
92 memcpy(priv
->buffer
, ptr
, len
* sizeof(*priv
->buffer
));
96 /***********************************************************************
97 * WindowsCreateStringReference (combase.@)
99 HRESULT WINAPI
WindowsCreateStringReference(LPCWSTR ptr
, UINT32 len
,
100 HSTRING_HEADER
*header
, HSTRING
*out
)
102 struct hstring_private
*priv
= impl_from_HSTRING_HEADER(header
);
104 TRACE("(%s, %u, %p, %p)\n", debugstr_wn(ptr
, len
), len
, header
, out
);
106 if (out
== NULL
|| header
== NULL
)
108 if (ptr
!= NULL
&& ptr
[len
] != '\0')
117 priv
->buffer
= (LPWSTR
)ptr
;
119 priv
->reference
= TRUE
;
120 *out
= (HSTRING
)header
;
124 /***********************************************************************
125 * WindowsDeleteString (combase.@)
127 HRESULT WINAPI
WindowsDeleteString(HSTRING str
)
129 struct hstring_private
*priv
= impl_from_HSTRING(str
);
131 TRACE("(%p)\n", str
);
137 if (InterlockedDecrement(&priv
->refcount
) == 0)
138 HeapFree(GetProcessHeap(), 0, priv
);
142 /***********************************************************************
143 * WindowsDuplicateString (combase.@)
145 HRESULT WINAPI
WindowsDuplicateString(HSTRING str
, HSTRING
*out
)
147 struct hstring_private
*priv
= impl_from_HSTRING(str
);
149 TRACE("(%p, %p)\n", str
, out
);
159 return WindowsCreateString(priv
->buffer
, priv
->length
, out
);
160 InterlockedIncrement(&priv
->refcount
);
165 /***********************************************************************
166 * WindowsPreallocateStringBuffer (combase.@)
168 HRESULT WINAPI
WindowsPreallocateStringBuffer(UINT32 len
, WCHAR
**outptr
,
171 struct hstring_private
*priv
;
174 TRACE("(%u, %p, %p)\n", len
, outptr
, out
);
176 if (outptr
== NULL
|| out
== NULL
)
180 *outptr
= (LPWSTR
)empty
;
185 if (!alloc_string(len
, &str
))
186 return E_OUTOFMEMORY
;
187 priv
= impl_from_HSTRING(str
);
188 *outptr
= priv
->buffer
;
189 *out
= (HSTRING_BUFFER
)str
;
193 /***********************************************************************
194 * WindowsDeleteStringBuffer (combase.@)
196 HRESULT WINAPI
WindowsDeleteStringBuffer(HSTRING_BUFFER buf
)
198 TRACE("(%p)\n", buf
);
200 return WindowsDeleteString((HSTRING
)buf
);
203 /***********************************************************************
204 * WindowsPromoteStringBuffer (combase.@)
206 HRESULT WINAPI
WindowsPromoteStringBuffer(HSTRING_BUFFER buf
, HSTRING
*out
)
208 struct hstring_private
*priv
= impl_from_HSTRING_BUFFER(buf
);
210 TRACE("(%p, %p)\n", buf
, out
);
219 if (priv
->buffer
[priv
->length
] != 0 || priv
->reference
|| priv
->refcount
!= 1)
225 /***********************************************************************
226 * WindowsGetStringLen (combase.@)
228 UINT32 WINAPI
WindowsGetStringLen(HSTRING str
)
230 struct hstring_private
*priv
= impl_from_HSTRING(str
);
232 TRACE("(%p)\n", str
);
239 /***********************************************************************
240 * WindowsGetStringRawBuffer (combase.@)
242 LPCWSTR WINAPI
WindowsGetStringRawBuffer(HSTRING str
, UINT32
*len
)
244 struct hstring_private
*priv
= impl_from_HSTRING(str
);
246 TRACE("(%p, %p)\n", str
, len
);
259 /***********************************************************************
260 * WindowsStringHasEmbeddedNull (combase.@)
262 HRESULT WINAPI
WindowsStringHasEmbeddedNull(HSTRING str
, BOOL
*out
)
265 struct hstring_private
*priv
= impl_from_HSTRING(str
);
267 TRACE("(%p, %p)\n", str
, out
);
276 for (i
= 0; i
< priv
->length
; i
++)
278 if (priv
->buffer
[i
] == '\0')
288 /***********************************************************************
289 * WindowsSubstring (combase.@)
291 HRESULT WINAPI
WindowsSubstring(HSTRING str
, UINT32 start
, HSTRING
*out
)
293 struct hstring_private
*priv
= impl_from_HSTRING(str
);
294 UINT32 len
= WindowsGetStringLen(str
);
296 TRACE("(%p, %u, %p)\n", str
, start
, out
);
307 return WindowsCreateString(&priv
->buffer
[start
], len
- start
, out
);
310 /***********************************************************************
311 * WindowsSubstringWithSpecifiedLength (combase.@)
313 HRESULT WINAPI
WindowsSubstringWithSpecifiedLength(HSTRING str
, UINT32 start
, UINT32 len
, HSTRING
*out
)
315 struct hstring_private
*priv
= impl_from_HSTRING(str
);
317 TRACE("(%p, %u, %u, %p)\n", str
, start
, len
, out
);
321 if (start
+ len
< start
||
322 start
+ len
> WindowsGetStringLen(str
))
329 return WindowsCreateString(&priv
->buffer
[start
], len
, out
);
332 /***********************************************************************
333 * WindowsConcatString (combase.@)
335 HRESULT WINAPI
WindowsConcatString(HSTRING str1
, HSTRING str2
, HSTRING
*out
)
337 struct hstring_private
*priv1
= impl_from_HSTRING(str1
);
338 struct hstring_private
*priv2
= impl_from_HSTRING(str2
);
339 struct hstring_private
*priv
;
341 TRACE("(%p, %p, %p)\n", str1
, str2
, out
);
346 return WindowsDuplicateString(str2
, out
);
348 return WindowsDuplicateString(str1
, out
);
349 if (!priv1
->length
&& !priv2
->length
)
354 if (!alloc_string(priv1
->length
+ priv2
->length
, out
))
355 return E_OUTOFMEMORY
;
356 priv
= impl_from_HSTRING(*out
);
357 memcpy(priv
->buffer
, priv1
->buffer
, priv1
->length
* sizeof(*priv1
->buffer
));
358 memcpy(priv
->buffer
+ priv1
->length
, priv2
->buffer
, priv2
->length
* sizeof(*priv2
->buffer
));
362 /***********************************************************************
363 * WindowsIsStringEmpty (combase.@)
365 BOOL WINAPI
WindowsIsStringEmpty(HSTRING str
)
367 struct hstring_private
*priv
= impl_from_HSTRING(str
);
369 TRACE("(%p)\n", str
);
373 return priv
->length
== 0;