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