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 22 void WINAPI _com_raise_error(HRESULT hr, IErrorInfo *perrinfo) 23 { 24 throw _com_error(hr, perrinfo); 25 } 26 27 void WINAPI _set_com_error_handler(COM_ERROR_HANDLER *phandler) 28 { 29 com_error_handler = phandler; 30 } 31 32 void WINAPI _com_issue_error(HRESULT hr) 33 { 34 com_error_handler(hr, NULL); 35 } 36 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 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 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