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