msvfw32: Fix the size of previous compressed buffer.
[wine.git] / dlls / combase / string.c
blob7054af69cae4d715394324350e743a338c352406
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"
26 struct hstring_private
28 LPWSTR buffer;
29 UINT32 length;
30 BOOL reference;
31 LONG refcount;
34 static const WCHAR empty[1];
36 C_ASSERT(sizeof(struct hstring_private) <= sizeof(HSTRING_HEADER));
38 static inline struct hstring_private *impl_from_HSTRING(HSTRING string)
40 return (struct hstring_private *)string;
43 static inline struct hstring_private *impl_from_HSTRING_HEADER(HSTRING_HEADER *header)
45 return (struct hstring_private *)header;
48 static inline struct hstring_private *impl_from_HSTRING_BUFFER(HSTRING_BUFFER buffer)
50 return (struct hstring_private *)buffer;
53 static BOOL alloc_string(UINT32 len, HSTRING *out)
55 struct hstring_private *priv;
56 priv = HeapAlloc(GetProcessHeap(), 0, sizeof(*priv) + (len + 1) * sizeof(*priv->buffer));
57 if (!priv)
58 return FALSE;
59 priv->buffer = (LPWSTR)(priv + 1);
60 priv->length = len;
61 priv->reference = FALSE;
62 priv->refcount = 1;
63 priv->buffer[len] = '\0';
64 *out = (HSTRING)priv;
65 return TRUE;
68 /***********************************************************************
69 * WindowsCreateString (combase.@)
71 HRESULT WINAPI WindowsCreateString(LPCWSTR ptr, UINT32 len,
72 HSTRING *out)
74 struct hstring_private *priv;
75 if (out == NULL)
76 return E_INVALIDARG;
77 if (ptr == NULL && len > 0)
78 return E_POINTER;
79 if (len == 0)
81 *out = NULL;
82 return S_OK;
84 if (!alloc_string(len, out))
85 return E_OUTOFMEMORY;
86 priv = impl_from_HSTRING(*out);
87 memcpy(priv->buffer, ptr, len * sizeof(*priv->buffer));
88 return S_OK;
91 /***********************************************************************
92 * WindowsCreateStringReference (combase.@)
94 HRESULT WINAPI WindowsCreateStringReference(LPCWSTR ptr, UINT32 len,
95 HSTRING_HEADER *header, HSTRING *out)
97 struct hstring_private *priv = impl_from_HSTRING_HEADER(header);
98 if (out == NULL || header == NULL)
99 return E_INVALIDARG;
100 if (ptr == NULL && len > 0)
101 return E_POINTER;
102 if (len == 0)
104 *out = NULL;
105 return S_OK;
107 if (ptr[len] != '\0')
108 return E_INVALIDARG;
109 priv->buffer = (LPWSTR)ptr;
110 priv->length = len;
111 priv->reference = TRUE;
112 *out = (HSTRING)header;
113 return S_OK;
116 /***********************************************************************
117 * WindowsDeleteString (combase.@)
119 HRESULT WINAPI WindowsDeleteString(HSTRING str)
121 struct hstring_private *priv = impl_from_HSTRING(str);
122 if (str == NULL)
123 return S_OK;
124 if (priv->reference)
125 return S_OK;
126 if (InterlockedDecrement(&priv->refcount) == 0)
127 HeapFree(GetProcessHeap(), 0, priv);
128 return S_OK;
131 /***********************************************************************
132 * WindowsDuplicateString (combase.@)
134 HRESULT WINAPI WindowsDuplicateString(HSTRING str, HSTRING *out)
136 struct hstring_private *priv = impl_from_HSTRING(str);
137 if (out == NULL)
138 return E_INVALIDARG;
139 if (str == NULL)
141 *out = NULL;
142 return S_OK;
144 if (priv->reference)
145 return WindowsCreateString(priv->buffer, priv->length, out);
146 InterlockedIncrement(&priv->refcount);
147 *out = str;
148 return S_OK;
151 /***********************************************************************
152 * WindowsPreallocateStringBuffer (combase.@)
154 HRESULT WINAPI WindowsPreallocateStringBuffer(UINT32 len, WCHAR **outptr,
155 HSTRING_BUFFER *out)
157 struct hstring_private *priv;
158 HSTRING str;
159 if (outptr == NULL || out == NULL)
160 return E_POINTER;
161 if (len == 0)
163 *outptr = (LPWSTR)empty;
164 *out = NULL;
165 return S_OK;
168 if (!alloc_string(len, &str))
169 return E_OUTOFMEMORY;
170 priv = impl_from_HSTRING(str);
171 *outptr = priv->buffer;
172 *out = (HSTRING_BUFFER)str;
173 return S_OK;
176 /***********************************************************************
177 * WindowsDeleteStringBuffer (combase.@)
179 HRESULT WINAPI WindowsDeleteStringBuffer(HSTRING_BUFFER buf)
181 return WindowsDeleteString((HSTRING)buf);
184 /***********************************************************************
185 * WindowsPromoteStringBuffer (combase.@)
187 HRESULT WINAPI WindowsPromoteStringBuffer(HSTRING_BUFFER buf, HSTRING *out)
189 struct hstring_private *priv = impl_from_HSTRING_BUFFER(buf);
190 if (out == NULL)
191 return E_POINTER;
192 if (buf == NULL)
194 *out = NULL;
195 return S_OK;
197 if (priv->buffer[priv->length] != 0 || priv->reference || priv->refcount != 1)
198 return E_INVALIDARG;
199 *out = (HSTRING)buf;
200 return S_OK;
203 /***********************************************************************
204 * WindowsGetStringLen (combase.@)
206 UINT32 WINAPI WindowsGetStringLen(HSTRING str)
208 struct hstring_private *priv = impl_from_HSTRING(str);
209 if (str == NULL)
210 return 0;
211 return priv->length;
214 /***********************************************************************
215 * WindowsGetStringRawBuffer (combase.@)
217 LPCWSTR WINAPI WindowsGetStringRawBuffer(HSTRING str, UINT32 *len)
219 struct hstring_private *priv = impl_from_HSTRING(str);
220 if (str == NULL)
222 if (len)
223 *len = 0;
224 return empty;
226 if (len)
227 *len = priv->length;
228 return priv->buffer;
231 /***********************************************************************
232 * WindowsStringHasEmbeddedNull (combase.@)
234 HRESULT WINAPI WindowsStringHasEmbeddedNull(HSTRING str, BOOL *out)
236 UINT32 i;
237 struct hstring_private *priv = impl_from_HSTRING(str);
238 if (out == NULL)
239 return E_INVALIDARG;
240 if (str == NULL)
242 *out = FALSE;
243 return S_OK;
245 for (i = 0; i < priv->length; i++)
247 if (priv->buffer[i] == '\0')
249 *out = TRUE;
250 return S_OK;
253 *out = FALSE;
254 return S_OK;
257 /***********************************************************************
258 * WindowsIsStringEmpty (combase.@)
260 BOOL WINAPI WindowsIsStringEmpty(HSTRING str)
262 struct hstring_private *priv = impl_from_HSTRING(str);
263 if (str == NULL)
264 return TRUE;
265 return priv->length == 0;