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 */
19 typedef void WINAPI COM_ERROR_HANDLER(HRESULT, IErrorInfo *);
20 static COM_ERROR_HANDLER *com_error_handler;
21
_com_raise_error(HRESULT hr,IErrorInfo * perrinfo)22 void WINAPI _com_raise_error(HRESULT hr, IErrorInfo *perrinfo)
23 {
24 throw _com_error(hr, perrinfo);
25 }
26
_set_com_error_handler(COM_ERROR_HANDLER * phandler)27 void WINAPI _set_com_error_handler(COM_ERROR_HANDLER *phandler)
28 {
29 com_error_handler = phandler;
30 }
31
_com_issue_error(HRESULT hr)32 void WINAPI _com_issue_error(HRESULT hr)
33 {
34 com_error_handler(hr, NULL);
35 }
36
_com_issue_errorex(HRESULT hr,IUnknown * punk,REFIID riid)37 void 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
56 namespace _com_util
57 {
58
ConvertStringToBSTR(const char * pSrc)59 BSTR 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
ConvertBSTRToString(BSTR pSrc)93 char* 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 }
137