/* * $Id: CimWinHttp.cpp,v 1.5 2008/12/12 00:51:59 tyreld Exp $ * * CimWinHttp.cpp * * (C) Copyright IBM Corp. 2004, 2008 * * THIS FILE IS PROVIDED UNDER THE TERMS OF THE ECLIPSE PUBLIC LICENSE * ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE * CONSTITUTES RECIPIENTS ACCEPTANCE OF THE AGREEMENT. * * You can obtain a current copy of the Eclipse Public License from * http://www.opensource.org/licenses/eclipse-1.0.php * * Author: Adrian Schuur <schuur@de.ibm.com> * Contributors: Viktor Mihajlovski <mihajlov@de.ibm.com> * Markus Mueller <markus_mueller@de.ibm.com> * Steve Shepherd <steve.shepherd@configuresoft.com> * Heidi Neumann <heidineu@de.ibm.com> * * Description: Line command interface to DMTF conforming WBEM servers */ #include "stdafx.h" #include "CimWinHttp.h" //////////////////////////////////////////////////////////////////////// // // CimomWinHttp::CimomWinHttp( ) // CimomWinHttp::~CimomWinHttp( ) // // Default constructor & destructor. // //////////////////////////////////////////////////////////////////////// extern int useNl; CimomWinHttp::CimomWinHttp() { m_hSession = NULL; m_hConnect = NULL; m_hRequest = NULL; m_lpPayload = NULL; m_dwPayloadSize = 0; } CimomWinHttp::~CimomWinHttp() { if (m_lpPayload) delete m_lpPayload; if (m_hRequest) ::WinHttpCloseHandle(m_hRequest); if (m_hConnect) ::WinHttpCloseHandle(m_hConnect); if (m_hSession) ::WinHttpCloseHandle(m_hSession); } //////////////////////////////////////////////////////////////////////// // // CimomWinHttp::SetTimeouts( ) // // Change the timeouts for HTTP messages. // //////////////////////////////////////////////////////////////////////// bool CimomWinHttp::SetTimeouts(int Connect, int Send, int Receive) { bool bReturn = false; if (m_hSession) { if (WinHttpSetTimeouts(m_hSession, 0, Connect, Send, Receive)) { bReturn = true; } } return bReturn; } //////////////////////////////////////////////////////////////////////// // // CimomWinHttp::addPayload( ) // // Add the message payload to the HTTP message. // //////////////////////////////////////////////////////////////////////// void CimomWinHttp::addPayload(char *pl) { addPayload(pl, strlen(pl)); } void CimomWinHttp::addPayload(LPCVOID lpPayload, DWORD dwSize) { if (m_lpPayload) delete m_lpPayload; m_lpPayload = new char[dwSize]; m_dwPayloadSize = dwSize; if (m_lpPayload) { memcpy(m_lpPayload, lpPayload, dwSize); } else { throw("addPayload failed: could not allocate a buffer."); } } //////////////////////////////////////////////////////////////////////// // // CimomWinHttp::genRequest( ) // // Create the HTTP message. // //////////////////////////////////////////////////////////////////////// void CimomWinHttp::genRequest(URL &url, const char *op, bool cls, bool keys) { if (!supportsSSL() && url.scheme == "https") throw HttpException("WinHttp does not support https urls."); DWORD dwLen, dwMBLen; WCHAR pszSingle[512]; BOOL bResult = FALSE; LPCWSTR sHeaders = L"Content-type: application/xml; charset=\"utf-8\"\r\n" L"Connection: Keep-Alive, TE\r\n" L"CIMProtocolVersion: 1.0\r\n" L"CIMOperation: MethodCall\r\n"; m_hSession = ::WinHttpOpen(L"EcmXpdTool", WINHTTP_ACCESS_TYPE_NO_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); if (!m_hSession) { throw("::WinHttpOpen failed"); } INTERNET_PORT iPort; if (sscanf(url.port, "%hui", &iPort) != 1) { iPort = 5988; } dwLen = strlen(url.host) + 1; wchar_t *wpHost = static_cast<wchar_t*>(malloc((dwLen+1)*sizeof(wchar_t))); if (!wpHost) { throw("Insufficient memory available"); } dwMBLen = MultiByteToWideChar(CP_UTF8, 0, url.host, dwLen, wpHost, dwLen); m_hConnect = ::WinHttpConnect(m_hSession, wpHost, iPort, 0); free(wpHost); if (!m_hConnect || dwMBLen == 0) { throw("::WinHttpConnect failed"); } // Create an HTTP Request handle. m_hRequest = ::WinHttpOpenRequest(m_hConnect, L"POST", L"/cimom", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0); if (!m_hRequest) { throw("::WinHttpOpenRequest failed"); } bResult = ::WinHttpAddRequestHeaders(m_hRequest, sHeaders, ULONG_MAX, WINHTTP_ADDREQ_FLAG_ADD); dwLen = strlen(op) + 1; wchar_t *wpCimOp = static_cast<wchar_t*>(malloc((dwLen+1)*sizeof(wchar_t))); if (!wpCimOp) { throw("Insufficient memory available"); } dwMBLen = MultiByteToWideChar(CP_UTF8, 0, op, dwLen, wpCimOp, dwLen); memset(pszSingle, '\0', sizeof(pszSingle)); wcscat(pszSingle, L"CIMMethod: "); wcscat(pszSingle, wpCimOp); wcscat(pszSingle, L"\r\n"); free(wpCimOp); bResult = ::WinHttpAddRequestHeaders(m_hRequest, pszSingle, ULONG_MAX, WINHTTP_ADDREQ_FLAG_ADD); string sb; url.ns.toStringBuffer(sb,"%2F"); if (cls) { sb = sb + "%3A" + url.cName; if (keys) { char sep = '.'; int t=useNl; useNl=0; for ( unsigned i = 0 ; i < url.keys.size() ; i++ ) { string sk; url.keys[i].toStringBuffer(sk, ""); sb = sb + sep + sk; sep = ','; } useNl=t; } } dwLen = strlen(sb.c_str()) + 1; wchar_t *wpNS = static_cast<wchar_t*>(malloc((dwLen+1)*sizeof(wchar_t))); if (!wpNS) { throw("Insufficient memory available"); } dwMBLen = MultiByteToWideChar(CP_UTF8, 0, sb.c_str(), dwLen, wpNS, dwLen); memset(pszSingle, '\0', sizeof(pszSingle)); wcscat(pszSingle, L"CIMObject: "); wcscat(pszSingle, wpNS); wcscat(pszSingle, L"\r\n"); free(wpNS); bResult = ::WinHttpAddRequestHeaders(m_hRequest, pszSingle, ULONG_MAX, WINHTTP_ADDREQ_FLAG_ADD); dwLen = strlen(url.password) + 1; wchar_t *wpPswd = static_cast<wchar_t*>(malloc((dwLen+1)*sizeof(wchar_t))); if (!wpPswd) { throw("Insufficient memory available"); } dwMBLen = MultiByteToWideChar(CP_UTF8, 0, url.password, dwLen, wpPswd, dwLen); dwLen = strlen(url.user) + 1; wchar_t *wpUser = static_cast<wchar_t*>(malloc((dwLen+1)*sizeof(wchar_t))); if (!wpUser) { throw("Insufficient memory available"); } dwMBLen = MultiByteToWideChar(CP_UTF8, 0, url.user, dwLen, wpUser, dwLen); bResult = WinHttpSetCredentials(m_hRequest, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, wpUser, wpPswd, NULL); free(wpPswd); free(wpUser); } //////////////////////////////////////////////////////////////////////// // // CimomWinHttp::getResponse( ) // // Send the message and get the response. // //////////////////////////////////////////////////////////////////////// #ifdef OLD string CimomWinHttp::getResponse() { BOOL bResult; LPSTR pszOutBuffer = NULL; if (m_hRequest) { bResult = WinHttpSendRequest(m_hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, m_dwPayloadSize, 0); // Write data to the server. if (bResult) { DWORD dwBytesWritten = 0; bResult = WinHttpWriteData(m_hRequest, m_lpPayload, m_dwPayloadSize, &dwBytesWritten); } // End the request. if (bResult) { bResult = WinHttpReceiveResponse(m_hRequest, NULL); } // Keep checking for data until there is nothing left. if (bResult) { DWORD dwContentLength = 0; DWORD dwCLSize = sizeof(dwContentLength); if (!WinHttpQueryHeaders(m_hRequest, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &dwContentLength, &dwCLSize, WINHTTP_NO_HEADER_INDEX)) { DWORD dwLastError = ::GetLastError(); LPVOID lpvMessageBuffer = NULL; DWORD dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM; if (::FormatMessage(dwFlags, m_hRequest, dwLastError, 0, (LPTSTR)&lpvMessageBuffer, 10, NULL) > 0) { throw((char *)lpvMessageBuffer); } else { throw("WinHttpQueryHeaders() failed"); } } if (dwContentLength > 0) { DWORD dwSize = 0; DWORD dwTotal = 0; // Allocate space for the buffer. pszOutBuffer = new char[dwContentLength+1]; if (!pszOutBuffer) { throw("Out of memory"); } else { ::ZeroMemory(pszOutBuffer, dwContentLength+1); do { // Check for available data. dwSize = 0; if (!WinHttpQueryDataAvailable(m_hRequest, &dwSize)) { throw("WinHttpQueryDataAvailable failed"); } // Read the Data. DWORD dwDownloaded = 0; if (!WinHttpReadData(m_hRequest, (LPVOID)(pszOutBuffer+dwTotal), dwSize, &dwDownloaded)) { throw("WinHttpReadData failed"); } else { dwTotal += dwSize; } } while (dwSize>0); // NULL terminate pszOutBuffer[dwTotal] = '\0'; } } } // Report any errors. if (!bResult) { throw("GetResponse failed"); } } else { throw("GetResponse failed: Request object not prepared."); } return (char *)(pszOutBuffer ? pszOutBuffer : ""); } #endif /* OLD */ //////////////////////////////////////////////////////////////////////// // // CimomWinHttp::getResponse( ) // // Send the message and get the response. // //////////////////////////////////////////////////////////////////////// string CimomWinHttp::getResponse() { BOOL bResult; LPSTR pszOutBuffer = NULL; if (m_hRequest) { bResult = WinHttpSendRequest(m_hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, m_dwPayloadSize, 0); // Write data to the server. if (bResult) { DWORD dwBytesWritten = 0; bResult = WinHttpWriteData(m_hRequest, m_lpPayload, m_dwPayloadSize, &dwBytesWritten); } // End the request. if (bResult) { bResult = WinHttpReceiveResponse(m_hRequest, NULL); } // Keep checking for data until there is nothing left. if (bResult) { DWORD dwSize = 0; DWORD dwTotal = 0; do { // Check for available data. dwSize = 0; if (!WinHttpQueryDataAvailable(m_hRequest, &dwSize)) { throw("WinHttpQueryDataAvailable failed"); } if (dwSize <= 0) { continue; } // Allocate space for the buffer. LPSTR pszNewBuffer = new char[dwSize + 1]; if (!pszNewBuffer) { throw("Out of memory"); } else { DWORD dwDownloaded = 0; // Read the Data. ::ZeroMemory(pszNewBuffer, dwSize + 1); if (!WinHttpReadData(m_hRequest, (LPVOID)pszNewBuffer, dwSize, &dwDownloaded)) { throw("WinHttpReadData failed"); } if (!pszOutBuffer) { pszOutBuffer = pszNewBuffer; } else { LPSTR pszTmpBuffer = new char[dwTotal + dwSize + 1]; if (!pszTmpBuffer) { throw("Out of memory"); } ::CopyMemory(pszTmpBuffer, pszOutBuffer, dwTotal); ::CopyMemory(pszTmpBuffer + dwTotal, pszNewBuffer, dwSize); delete [] pszOutBuffer; delete [] pszNewBuffer; pszOutBuffer = pszTmpBuffer; } dwTotal += dwSize; } } while (dwSize > 0); } // Report any errors. if (!bResult) { throw("GetResponse failed"); } } else { throw("GetResponse failed: Request object not prepared."); } return (char *)(pszOutBuffer ? pszOutBuffer : ""); } void CimomWinHttp::setClientCertificates(const char * cacert, int noverify, const char * certificate, const char * key) { if (!supportsSSL()) throw HttpException("CimWinHttp does not support https urls."); }