combase: Implement functions for HSTRING_BUFFER.
[wine.git] / dlls / combase / string.c
blob5fe4321ed9b21c1ded9512f3a92f86daaeafecf3
1 /*
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
19 #include <string.h>
21 #include "windows.h"
22 #include "winerror.h"
23 #include "hstring.h"
24 #include "wine/debug.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(combase);
28 struct hstring_private
30 LPWSTR buffer;
31 UINT32 length;
32 BOOL reference;
33 LONG refcount;
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));
59 if (!priv)
60 return FALSE;
61 priv->buffer = (LPWSTR)(priv + 1);
62 priv->length = len;
63 priv->reference = FALSE;
64 priv->refcount = 1;
65 priv->buffer[len] = '\0';
66 *out = (HSTRING)priv;
67 return TRUE;
70 /***********************************************************************
71 * WindowsCreateString (combase.@)
73 HRESULT WINAPI WindowsCreateString(LPCWSTR ptr, UINT32 len,
74 HSTRING *out)
76 struct hstring_private *priv;
77 if (out == NULL)
78 return E_INVALIDARG;
79 if (ptr == NULL && len > 0)
80 return E_POINTER;
81 if (len == 0)
83 *out = NULL;
84 return S_OK;
86 if (!alloc_string(len, out))
87 return E_OUTOFMEMORY;
88 priv = impl_from_HSTRING(*out);
89 memcpy(priv->buffer, ptr, len * sizeof(*priv->buffer));
90 return S_OK;
93 /***********************************************************************
94 * WindowsCreateStringReference (combase.@)
96 HRESULT WINAPI WindowsCreateStringReference(LPCWSTR ptr, UINT32 len,
97 HSTRING_HEADER *header, HSTRING *out)
99 struct hstring_private *priv = impl_from_HSTRING_HEADER(header);
100 if (out == NULL || header == NULL)
101 return E_INVALIDARG;
102 if (ptr == NULL && len > 0)
103 return E_POINTER;
104 if (ptr[len] != '\0')
105 return E_INVALIDARG;
106 if (len == 0)
108 *out = NULL;
109 return S_OK;
111 priv->buffer = (LPWSTR)ptr;
112 priv->length = len;
113 priv->reference = TRUE;
114 *out = (HSTRING)header;
115 return S_OK;
118 /***********************************************************************
119 * WindowsDeleteString (combase.@)
121 HRESULT WINAPI WindowsDeleteString(HSTRING str)
123 struct hstring_private *priv = impl_from_HSTRING(str);
124 if (str == NULL)
125 return S_OK;
126 if (priv->reference)
127 return S_OK;
128 if (InterlockedDecrement(&priv->refcount) == 0)
129 HeapFree(GetProcessHeap(), 0, priv);
130 return S_OK;
133 /***********************************************************************
134 * WindowsDuplicateString (combase.@)
136 HRESULT WINAPI WindowsDuplicateString(HSTRING str, HSTRING *out)
138 struct hstring_private *priv = impl_from_HSTRING(str);
139 if (out == NULL)
140 return E_INVALIDARG;
141 if (str == NULL)
143 *out = NULL;
144 return S_OK;
146 if (priv->reference)
147 return WindowsCreateString(priv->buffer, priv->length, out);
148 InterlockedIncrement(&priv->refcount);
149 *out = str;
150 return S_OK;
153 /***********************************************************************
154 * WindowsPreallocateStringBuffer (combase.@)
156 HRESULT WINAPI WindowsPreallocateStringBuffer(UINT32 len, WCHAR **outptr,
157 HSTRING_BUFFER *out)
159 struct hstring_private *priv;
160 HSTRING str;
161 if (outptr == NULL || out == NULL)
162 return E_POINTER;
163 if (len == 0)
165 *outptr = (LPWSTR)empty;
166 *out = NULL;
167 return S_OK;
170 if (!alloc_string(len, &str))
171 return E_OUTOFMEMORY;
172 priv = impl_from_HSTRING(str);
173 *outptr = priv->buffer;
174 *out = (HSTRING_BUFFER)str;
175 return S_OK;
178 /***********************************************************************
179 * WindowsDeleteStringBuffer (combase.@)
181 HRESULT WINAPI WindowsDeleteStringBuffer(HSTRING_BUFFER buf)
183 return WindowsDeleteString((HSTRING)buf);
186 /***********************************************************************
187 * WindowsPromoteStringBuffer (combase.@)
189 HRESULT WINAPI WindowsPromoteStringBuffer(HSTRING_BUFFER buf, HSTRING *out)
191 struct hstring_private *priv = impl_from_HSTRING_BUFFER(buf);
192 if (out == NULL)
193 return E_POINTER;
194 if (buf == NULL)
196 *out = NULL;
197 return S_OK;
199 if (priv->buffer[priv->length] != 0 || priv->reference || priv->refcount != 1)
200 return E_INVALIDARG;
201 *out = (HSTRING)buf;
202 return S_OK;
205 /***********************************************************************
206 * WindowsGetStringLen (combase.@)
208 UINT32 WINAPI WindowsGetStringLen(HSTRING str)
210 struct hstring_private *priv = impl_from_HSTRING(str);
211 if (str == NULL)
212 return 0;
213 return priv->length;
216 /***********************************************************************
217 * WindowsGetStringRawBuffer (combase.@)
219 LPCWSTR WINAPI WindowsGetStringRawBuffer(HSTRING str, UINT32 *len)
221 struct hstring_private *priv = impl_from_HSTRING(str);
222 if (str == NULL)
224 if (len)
225 *len = 0;
226 return empty;
228 if (len)
229 *len = priv->length;
230 return priv->buffer;
233 /***********************************************************************
234 * WindowsStringHasEmbeddedNull (combase.@)
236 HRESULT WINAPI WindowsStringHasEmbeddedNull(HSTRING str, BOOL *out)
238 UINT32 i;
239 struct hstring_private *priv = impl_from_HSTRING(str);
240 if (out == NULL)
241 return E_INVALIDARG;
242 if (str == NULL)
244 *out = FALSE;
245 return S_OK;
247 for (i = 0; i < priv->length; i++)
249 if (priv->buffer[i] == '\0')
251 *out = TRUE;
252 return S_OK;
255 *out = FALSE;
256 return S_OK;
259 /***********************************************************************
260 * WindowsIsStringEmpty (combase.@)
262 BOOL WINAPI WindowsIsStringEmpty(HSTRING str)
264 struct hstring_private *priv = impl_from_HSTRING(str);
265 if (str == NULL)
266 return TRUE;
267 return priv->length == 0;