Reactos
1/*
2 * PROJECT: ReactOS crt library
3 * LICENSE: BSD-2-Clause (https://spdx.org/licenses/BSD-2-Clause)
4 * PURPOSE: Compiler support for COM
5 * COPYRIGHT: Copyright 2013 Thomas Faber (thomas.faber@reactos.org)
6 * Copyright 2015 Hermès Bélusca-Maïto (hermes.belusca-maito@reactos.org)
7 */
8
9#include <stdarg.h>
10
11#define WIN32_NO_STATUS
12#define _INC_WINDOWS
13
14#include <windef.h>
15#include <winbase.h>
16#include <comdef.h>
17
18/* comdef.h */
19typedef void WINAPI COM_ERROR_HANDLER(HRESULT, IErrorInfo *);
20static COM_ERROR_HANDLER *com_error_handler;
21
22void WINAPI _com_raise_error(HRESULT hr, IErrorInfo *perrinfo)
23{
24 throw _com_error(hr, perrinfo);
25}
26
27void WINAPI _set_com_error_handler(COM_ERROR_HANDLER *phandler)
28{
29 com_error_handler = phandler;
30}
31
32void WINAPI _com_issue_error(HRESULT hr)
33{
34 com_error_handler(hr, NULL);
35}
36
37void WINAPI _com_issue_errorex(HRESULT hr, IUnknown *punk, REFIID riid)
38{
39 void *pv;
40 IErrorInfo *perrinfo = NULL;
41
42 if (SUCCEEDED(punk->QueryInterface(riid, &pv)))
43 {
44 ISupportErrorInfo *pserrinfo = static_cast<ISupportErrorInfo *>(pv);
45 if (pserrinfo->InterfaceSupportsErrorInfo(riid) == S_OK)
46 (void)GetErrorInfo(0, &perrinfo);
47 pserrinfo->Release();
48 }
49
50 com_error_handler(hr, perrinfo);
51}
52
53/* comutil.h */
54_variant_t vtMissing(DISP_E_PARAMNOTFOUND, VT_ERROR);
55
56namespace _com_util
57{
58
59BSTR WINAPI ConvertStringToBSTR(const char *pSrc)
60{
61 DWORD cwch;
62 BSTR wsOut(NULL);
63
64 if (!pSrc) return NULL;
65
66 /* Compute the needed size with the NULL terminator */
67 cwch = ::MultiByteToWideChar(CP_ACP, 0, pSrc, -1, NULL, 0);
68 if (cwch == 0) return NULL;
69
70 /* Allocate the BSTR (without the NULL terminator) */
71 wsOut = ::SysAllocStringLen(NULL, cwch - 1);
72 if (!wsOut)
73 {
74 ::_com_issue_error(HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY));
75 return NULL;
76 }
77
78 /* Convert the string */
79 if (::MultiByteToWideChar(CP_ACP, 0, pSrc, -1, wsOut, cwch) == 0)
80 {
81 /* We failed, clean everything up */
82 cwch = ::GetLastError();
83
84 ::SysFreeString(wsOut);
85 wsOut = NULL;
86
87 ::_com_issue_error(!IS_ERROR(cwch) ? HRESULT_FROM_WIN32(cwch) : cwch);
88 }
89
90 return wsOut;
91}
92
93char* WINAPI ConvertBSTRToString(BSTR pSrc)
94{
95 DWORD cb, cwch;
96 char *szOut = NULL;
97
98 if (!pSrc) return NULL;
99
100 /* Retrieve the size of the BSTR with the NULL terminator */
101 cwch = ::SysStringLen(pSrc) + 1;
102
103 /* Compute the needed size with the NULL terminator */
104 cb = ::WideCharToMultiByte(CP_ACP, 0, pSrc, cwch, NULL, 0, NULL, NULL);
105 if (cb == 0)
106 {
107 cwch = ::GetLastError();
108 ::_com_issue_error(!IS_ERROR(cwch) ? HRESULT_FROM_WIN32(cwch) : cwch);
109 return NULL;
110 }
111
112 /* Allocate the string */
113 szOut = (char*)::operator new(cb * sizeof(char));
114 if (!szOut)
115 {
116 ::_com_issue_error(HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY));
117 return NULL;
118 }
119
120 /* Convert the string and NULL-terminate */
121 szOut[cb - 1] = '\0';
122 if (::WideCharToMultiByte(CP_ACP, 0, pSrc, cwch, szOut, cb, NULL, NULL) == 0)
123 {
124 /* We failed, clean everything up */
125 cwch = ::GetLastError();
126
127 ::operator delete(szOut);
128 szOut = NULL;
129
130 ::_com_issue_error(!IS_ERROR(cwch) ? HRESULT_FROM_WIN32(cwch) : cwch);
131 }
132
133 return szOut;
134}
135
136}