combase: Implement functions for accessing HSTRING objects.
[wine/multimedia.git] / dlls / combase / string.c
blob09519a118d7f1724d284f8d7f4d11d6312f2c657
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 BOOL alloc_string(UINT32 len, HSTRING *out)
52 struct hstring_private *priv;
53 priv = HeapAlloc(GetProcessHeap(), 0, sizeof(*priv) + (len + 1) * sizeof(*priv->buffer));
54 if (!priv)
55 return FALSE;
56 priv->buffer = (LPWSTR)(priv + 1);
57 priv->length = len;
58 priv->reference = FALSE;
59 priv->refcount = 1;
60 priv->buffer[len] = '\0';
61 *out = (HSTRING)priv;
62 return TRUE;
65 /***********************************************************************
66 * WindowsCreateString (combase.@)
68 HRESULT WINAPI WindowsCreateString(LPCWSTR ptr, UINT32 len,
69 HSTRING *out)
71 struct hstring_private *priv;
72 if (out == NULL)
73 return E_INVALIDARG;
74 if (ptr == NULL && len > 0)
75 return E_POINTER;
76 if (len == 0)
78 *out = NULL;
79 return S_OK;
81 if (!alloc_string(len, out))
82 return E_OUTOFMEMORY;
83 priv = impl_from_HSTRING(*out);
84 memcpy(priv->buffer, ptr, len * sizeof(*priv->buffer));
85 return S_OK;
88 /***********************************************************************
89 * WindowsCreateStringReference (combase.@)
91 HRESULT WINAPI WindowsCreateStringReference(LPCWSTR ptr, UINT32 len,
92 HSTRING_HEADER *header, HSTRING *out)
94 struct hstring_private *priv = impl_from_HSTRING_HEADER(header);
95 if (out == NULL || header == NULL)
96 return E_INVALIDARG;
97 if (ptr == NULL && len > 0)
98 return E_POINTER;
99 if (ptr[len] != '\0')
100 return E_INVALIDARG;
101 if (len == 0)
103 *out = NULL;
104 return S_OK;
106 priv->buffer = (LPWSTR)ptr;
107 priv->length = len;
108 priv->reference = TRUE;
109 *out = (HSTRING)header;
110 return S_OK;
113 /***********************************************************************
114 * WindowsDeleteString (combase.@)
116 HRESULT WINAPI WindowsDeleteString(HSTRING str)
118 struct hstring_private *priv = impl_from_HSTRING(str);
119 if (str == NULL)
120 return S_OK;
121 if (priv->reference)
122 return S_OK;
123 if (InterlockedDecrement(&priv->refcount) == 0)
124 HeapFree(GetProcessHeap(), 0, priv);
125 return S_OK;
128 /***********************************************************************
129 * WindowsDuplicateString (combase.@)
131 HRESULT WINAPI WindowsDuplicateString(HSTRING str, HSTRING *out)
133 struct hstring_private *priv = impl_from_HSTRING(str);
134 if (out == NULL)
135 return E_INVALIDARG;
136 if (str == NULL)
138 *out = NULL;
139 return S_OK;
141 if (priv->reference)
142 return WindowsCreateString(priv->buffer, priv->length, out);
143 InterlockedIncrement(&priv->refcount);
144 *out = str;
145 return S_OK;
148 /***********************************************************************
149 * WindowsGetStringLen (combase.@)
151 UINT32 WINAPI WindowsGetStringLen(HSTRING str)
153 struct hstring_private *priv = impl_from_HSTRING(str);
154 if (str == NULL)
155 return 0;
156 return priv->length;
159 /***********************************************************************
160 * WindowsGetStringRawBuffer (combase.@)
162 LPCWSTR WINAPI WindowsGetStringRawBuffer(HSTRING str, UINT32 *len)
164 struct hstring_private *priv = impl_from_HSTRING(str);
165 if (str == NULL)
167 if (len)
168 *len = 0;
169 return empty;
171 if (len)
172 *len = priv->length;
173 return priv->buffer;
176 /***********************************************************************
177 * WindowsStringHasEmbeddedNull (combase.@)
179 HRESULT WINAPI WindowsStringHasEmbeddedNull(HSTRING str, BOOL *out)
181 UINT32 i;
182 struct hstring_private *priv = impl_from_HSTRING(str);
183 if (out == NULL)
184 return E_INVALIDARG;
185 if (str == NULL)
187 *out = FALSE;
188 return S_OK;
190 for (i = 0; i < priv->length; i++)
192 if (priv->buffer[i] == '\0')
194 *out = TRUE;
195 return S_OK;
198 *out = FALSE;
199 return S_OK;
202 /***********************************************************************
203 * WindowsIsStringEmpty (combase.@)
205 BOOL WINAPI WindowsIsStringEmpty(HSTRING str)
207 struct hstring_private *priv = impl_from_HSTRING(str);
208 if (str == NULL)
209 return TRUE;
210 return priv->length == 0;