[ATL][ATL_APITEST] Implement some basic functionality for CComVariant + tests. CORE...
[reactos.git] / reactos / sdk / lib / atl / atlcomcli.h
1 /*
2 * ReactOS ATL
3 *
4 * Copyright 2009 Andrew Hill <ash77@reactos.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #pragma once
22
23 #include "atlcore.h"
24
25
26 #ifdef _MSC_VER
27 // It is common to use this in ATL constructors. They only store this for later use, so the usage is safe.
28 #pragma warning(disable:4355)
29 #endif
30
31 #ifndef _ATL_PACKING
32 #define _ATL_PACKING 8
33 #endif
34
35 #ifndef _ATL_FREE_THREADED
36 #ifndef _ATL_APARTMENT_THREADED
37 #ifndef _ATL_SINGLE_THREADED
38 #define _ATL_FREE_THREADED
39 #endif
40 #endif
41 #endif
42
43 #ifndef ATLTRY
44 #define ATLTRY(x) x;
45 #endif
46
47 #ifdef _ATL_DISABLE_NO_VTABLE
48 #define ATL_NO_VTABLE
49 #else
50 #define ATL_NO_VTABLE __declspec(novtable)
51 #endif
52
53 namespace ATL
54 {
55
56
57 template<class T>
58 class CComPtr
59 {
60 public:
61 T *p;
62 public:
63 CComPtr()
64 {
65 p = NULL;
66 }
67
68 CComPtr(T *lp)
69 {
70 p = lp;
71 if (p != NULL)
72 p->AddRef();
73 }
74
75 CComPtr(const CComPtr<T> &lp)
76 {
77 p = lp.p;
78 if (p != NULL)
79 p->AddRef();
80 }
81
82 ~CComPtr()
83 {
84 if (p != NULL)
85 p->Release();
86 }
87
88 T *operator = (T *lp)
89 {
90 if (p != NULL)
91 p->Release();
92 p = lp;
93 if (p != NULL)
94 p->AddRef();
95 return *this;
96 }
97
98 T *operator = (const CComPtr<T> &lp)
99 {
100 if (p != NULL)
101 p->Release();
102 p = lp.p;
103 if (p != NULL)
104 p->AddRef();
105 return *this;
106 }
107
108 void Release()
109 {
110 if (p != NULL)
111 {
112 p->Release();
113 p = NULL;
114 }
115 }
116
117 void Attach(T *lp)
118 {
119 if (p != NULL)
120 p->Release();
121 p = lp;
122 }
123
124 T *Detach()
125 {
126 T *saveP;
127
128 saveP = p;
129 p = NULL;
130 return saveP;
131 }
132
133 T **operator & ()
134 {
135 ATLASSERT(p == NULL);
136 return &p;
137 }
138
139 operator T * ()
140 {
141 return p;
142 }
143
144 T *operator -> ()
145 {
146 ATLASSERT(p != NULL);
147 return p;
148 }
149 };
150
151
152 class CComBSTR
153 {
154 public:
155 BSTR m_str;
156 public:
157 CComBSTR() :
158 m_str(NULL)
159 {
160 }
161
162 CComBSTR(LPCOLESTR pSrc)
163 {
164 if (pSrc == NULL)
165 m_str = NULL;
166 else
167 m_str = ::SysAllocString(pSrc);
168 }
169
170 CComBSTR(int length)
171 {
172 if (length == 0)
173 m_str = NULL;
174 else
175 m_str = ::SysAllocStringLen(NULL, length);
176 }
177
178 CComBSTR(int length, LPCOLESTR pSrc)
179 {
180 if (length == 0)
181 m_str = NULL;
182 else
183 m_str = ::SysAllocStringLen(pSrc, length);
184 }
185
186 CComBSTR(PCSTR pSrc)
187 {
188 if (pSrc)
189 {
190 int len = MultiByteToWideChar(CP_THREAD_ACP, 0, pSrc, -1, NULL, 0);
191 m_str = ::SysAllocStringLen(NULL, len - 1);
192 if (m_str)
193 {
194 int res = MultiByteToWideChar(CP_THREAD_ACP, 0, pSrc, -1, m_str, len);
195 ATLASSERT(res == len);
196 if (res != len)
197 {
198 ::SysFreeString(m_str);
199 m_str = NULL;
200 }
201 }
202 }
203 else
204 {
205 m_str = NULL;
206 }
207 }
208
209 CComBSTR(const CComBSTR &other)
210 {
211 m_str = other.Copy();
212 }
213
214 CComBSTR(REFGUID guid)
215 {
216 OLECHAR szGuid[40];
217 ::StringFromGUID2(guid, szGuid, 40);
218 m_str = ::SysAllocString(szGuid);
219 }
220
221 ~CComBSTR()
222 {
223 ::SysFreeString(m_str);
224 m_str = NULL;
225 }
226
227 operator BSTR () const
228 {
229 return m_str;
230 }
231
232 BSTR *operator & ()
233 {
234 return &m_str;
235 }
236
237 CComBSTR &operator = (const CComBSTR &other)
238 {
239 ::SysFreeString(m_str);
240 m_str = other.Copy();
241 return *this;
242 }
243
244 BSTR Detach()
245 {
246 BSTR str = m_str;
247 m_str = NULL;
248 return str;
249 }
250
251 BSTR Copy() const
252 {
253 if (!m_str)
254 return NULL;
255 return ::SysAllocStringLen(m_str, ::SysStringLen(m_str));
256 }
257
258 HRESULT CopyTo(BSTR *other) const
259 {
260 if (!other)
261 return E_POINTER;
262 *other = Copy();
263 return S_OK;
264 }
265
266 bool LoadString(HMODULE module, DWORD uID)
267 {
268 ::SysFreeString(m_str);
269 m_str = NULL;
270 const wchar_t *ptr = NULL;
271 int len = ::LoadStringW(module, uID, (PWSTR)&ptr, 0);
272 if (len)
273 m_str = ::SysAllocStringLen(ptr, len);
274 return m_str != NULL;
275 }
276
277 unsigned int Length() const
278 {
279 return ::SysStringLen(m_str);
280 }
281
282 unsigned int ByteLength() const
283 {
284 return ::SysStringByteLen(m_str);
285 }
286 };
287
288
289 class CComVariant : public tagVARIANT
290 {
291 public:
292 CComVariant()
293 {
294 ::VariantInit(this);
295 }
296
297 CComVariant(const CComVariant& other)
298 {
299 V_VT(this) = VT_EMPTY;
300 Copy(&other);
301 }
302
303 ~CComVariant()
304 {
305 Clear();
306 }
307
308 CComVariant(LPCOLESTR lpStr)
309 {
310 V_VT(this) = VT_BSTR;
311 V_BSTR(this) = ::SysAllocString(lpStr);
312 }
313
314 CComVariant(LPCSTR lpStr)
315 {
316 V_VT(this) = VT_BSTR;
317 CComBSTR str(lpStr);
318 V_BSTR(this) = str.Detach();
319 }
320
321 CComVariant(bool value)
322 {
323 V_VT(this) = VT_BOOL;
324 V_BOOL(this) = value ? VARIANT_TRUE : VARIANT_FALSE;
325 }
326
327 CComVariant(char value)
328 {
329 V_VT(this) = VT_I1;
330 V_I1(this) = value;
331 }
332
333 CComVariant(BYTE value)
334 {
335 V_VT(this) = VT_UI1;
336 V_UI1(this) = value;
337 }
338
339 CComVariant(short value)
340 {
341 V_VT(this) = VT_I2;
342 V_I2(this) = value;
343 }
344
345 CComVariant(unsigned short value)
346 {
347 V_VT(this) = VT_UI2;
348 V_UI2(this) = value;
349 }
350
351 CComVariant(int value, VARENUM type = VT_I4)
352 {
353 if (type == VT_I4 || type == VT_INT)
354 {
355 V_VT(this) = type;
356 V_I4(this) = value;
357 }
358 else
359 {
360 V_VT(this) = VT_ERROR;
361 V_ERROR(this) = E_INVALIDARG;
362 }
363 }
364
365 CComVariant(unsigned int value, VARENUM type = VT_UI4)
366 {
367 if (type == VT_UI4 || type == VT_UINT)
368 {
369 V_VT(this) = type;
370 V_UI4(this) = value;
371 }
372 else
373 {
374 V_VT(this) = VT_ERROR;
375 V_ERROR(this) = E_INVALIDARG;
376 }
377 }
378
379 CComVariant(long value, VARENUM type = VT_I4)
380 {
381 if (type == VT_I4 || type == VT_ERROR)
382 {
383 V_VT(this) = type;
384 V_I4(this) = value;
385 }
386 else
387 {
388 V_VT(this) = VT_ERROR;
389 V_ERROR(this) = E_INVALIDARG;
390 }
391 }
392
393 CComVariant(unsigned long value)
394 {
395 V_VT(this) = VT_UI4;
396 V_UI4(this) = value;
397 }
398
399 CComVariant(float value)
400 {
401 V_VT(this) = VT_R4;
402 V_R4(this) = value;
403 }
404
405 CComVariant(double value, VARENUM type = VT_R8)
406 {
407 if (type == VT_R8 || type == VT_DATE)
408 {
409 V_VT(this) = type;
410 V_R8(this) = value;
411 }
412 else
413 {
414 V_VT(this) = VT_ERROR;
415 V_ERROR(this) = E_INVALIDARG;
416 }
417 }
418
419 CComVariant(const LONGLONG& value)
420 {
421 V_VT(this) = VT_I8;
422 V_I8(this) = value;
423 }
424
425 CComVariant(const ULONGLONG& value)
426 {
427 V_VT(this) = VT_UI8;
428 V_UI8(this) = value;
429 }
430
431 CComVariant(const CY& value)
432 {
433 V_VT(this) = VT_CY;
434 V_I8(this) = value.int64;
435 }
436
437
438 HRESULT Clear()
439 {
440 return ::VariantClear(this);
441 }
442
443 HRESULT Copy(_In_ const VARIANT* src)
444 {
445 return ::VariantCopy(this, const_cast<VARIANT*>(src));
446 }
447
448 HRESULT ChangeType(_In_ VARTYPE newType, _In_opt_ const LPVARIANT src = NULL)
449 {
450 const LPVARIANT lpSrc = src ? src : this;
451 return ::VariantChangeType(this, lpSrc, 0, newType);
452 }
453 };
454
455
456
457 }; // namespace ATL
458
459 #ifndef _ATL_NO_AUTOMATIC_NAMESPACE
460 using namespace ATL;
461 #endif //!_ATL_NO_AUTOMATIC_NAMESPACE
462