XMLHTTPRequest.cpp
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:29k
源码类别:

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  * 
  4.  * Copyright (c) 1999-2000 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  * 
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  * 
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer. 
  13.  * 
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  * 
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:  
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  * 
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written 
  29.  *    permission, please contact apache@apache.org.
  30.  * 
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  * 
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  * 
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 1999, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Log: XMLHTTPRequest.cpp,v $
  58.  * Revision 1.3  2000/06/03 00:29:03  andyh
  59.  * COM Wrapper changes from Curt Arnold
  60.  *
  61.  * Revision 1.2  2000/03/30 02:00:09  abagchi
  62.  * Initial checkin of working code with Copyright Notice
  63.  *
  64.  */
  65. #include "stdafx.h"
  66. #include "xml4com.h"
  67. #include "XMLHttpRequest.h"
  68. #include "XMLDOMDocument.h"
  69. // I need to make sure the file is registered with long filenames
  70. HRESULT WINAPI CXMLHttpRequest::UpdateRegistry(BOOL bRegister)
  71. {
  72. USES_CONVERSION;
  73. TCHAR file[MAX_PATH];
  74. if (::GetModuleFileName(_Module.m_hInst, file, MAX_PATH)) {
  75. WIN32_FIND_DATA d;
  76. memset(&d,0,sizeof(WIN32_FIND_DATA));
  77. HANDLE h = FindFirstFile(file,&d);
  78. if (h != INVALID_HANDLE_VALUE) {
  79. TCHAR  *name = _tcsrchr(file,_T('\'));
  80. TCHAR newFile[MAX_PATH] = _T("");
  81. _tcsncpy(newFile,file,name-file);
  82. _tcscat(newFile,_T("\"));
  83. _tcscat(newFile,d.cFileName);
  84. FindClose(h);
  85. _ATL_REGMAP_ENTRY regmap[2] = {{NULL,NULL},{NULL,NULL}};
  86. regmap[0].szKey  = OLESTR("XMLMODULE");
  87. regmap[0].szData = T2OLE(newFile);
  88. return _Module.UpdateRegistryFromResource((UINT) IDR_XMLHTTPREQUEST, bRegister,regmap);
  89. }
  90. }
  91. return E_FAIL;
  92. }
  93. CXMLHttpRequest::CXMLHttpRequest()
  94. :m_pOnReadyStateChange (NULL)
  95. ,m_bAbort (false)
  96. ,m_hThread (NULL)
  97. ,m_lReadyState (0)
  98. ,m_bAsync (false)
  99. ,m_Method (_T(""))
  100. ,m_HostName (_T(""))
  101. ,m_Port (INTERNET_DEFAULT_HTTP_PORT)
  102. ,m_URLPath (_T(""))
  103. ,m_User (_T(""))
  104. ,m_Password (_T(""))
  105. ,m_dwStatus (0)
  106. ,m_StatusText (_T(""))
  107. ,m_ResponseHeaders (_T(""))
  108. ,m_HwndParent (NULL)
  109. ,m_pBody (NULL)
  110. ,m_lBodyLength (0)
  111. ,m_pResponseBody (NULL)
  112. ,m_lResponseBodyLength (0)
  113. ,m_Error (_T(""))
  114. ,m_bSuccess (true)
  115. {
  116. }
  117. HRESULT CXMLHttpRequest::FinalConstruct()
  118. {
  119. // create monitor window
  120. RECT rc;
  121.     memset(&rc,0,sizeof(RECT));
  122. if (NULL == Create(NULL, rc, _T("XML HTTP Request Monitor Window"), 0))
  123. return E_FAIL;
  124. return S_OK;
  125. }
  126. void CXMLHttpRequest::FinalRelease()
  127. {
  128. if (NULL != m_hThread) {
  129. m_bAbort = true;
  130. ::WaitForSingleObject(m_hThread, INFINITE);
  131. ::CloseHandle(m_hThread);
  132. m_hThread = NULL;
  133. }
  134. if (m_pOnReadyStateChange != NULL) {
  135. m_pOnReadyStateChange->Release();
  136. m_pOnReadyStateChange = NULL;
  137. }
  138. DestroyWindow();
  139. delete [] m_pBody;
  140. m_pBody = NULL;
  141. m_lBodyLength = 0;
  142. delete [] m_pResponseBody;
  143. m_pResponseBody = NULL;
  144. m_lResponseBodyLength = 0;
  145. }
  146. LRESULT CXMLHttpRequest::OnReadyStateChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
  147. {
  148. ATLTRACE(_T("CXMLHttpRequest::OnReadyStateChangen"));
  149. bHandled = TRUE;
  150. m_lReadyState = wParam;
  151. if (NULL != m_pOnReadyStateChange) {
  152. CComVariant varResult;
  153. DISPPARAMS disp = { NULL, NULL, 0, 0 };
  154. m_pOnReadyStateChange->Invoke(DISPID_VALUE, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
  155. }
  156. return 1L;
  157. }
  158. STDMETHODIMP CXMLHttpRequest::InterfaceSupportsErrorInfo(REFIID riid)
  159. {
  160. if (IsEqualGUID(IID_IXMLHttpRequest,riid))
  161. return S_OK;
  162. return S_FALSE;
  163. }
  164. STDMETHODIMP CXMLHttpRequest::open(BSTR bstrMethod, BSTR bstrUrl,VARIANT varAsync,VARIANT bstrUser,VARIANT bstrPassword)
  165. {
  166. ATLTRACE(_T("CXMLHttpRequest::openn"));
  167. // do not open if there is a send active  
  168. if (NULL != m_hThread) {
  169. DWORD exitCode = 0;
  170. BOOL rc = ::GetExitCodeThread(m_hThread, &exitCode);
  171. if (!rc || STILL_ACTIVE == exitCode) 
  172. return E_FAIL;
  173. ::CloseHandle(m_hThread);
  174. m_hThread = NULL;
  175. }
  176. if (V_VT(&varAsync) != VT_BOOL)
  177. return E_INVALIDARG;
  178. _bstr_t method = bstrMethod;
  179. if (0 == method.length())
  180. return E_INVALIDARG;
  181. _bstr_t url = bstrUrl;
  182. if (0 == url.length())
  183. return E_INVALIDARG;
  184. TCHAR hostName[INTERNET_MAX_PATH_LENGTH] = _T("");
  185. TCHAR strPathName[INTERNET_MAX_PATH_LENGTH] = _T("");
  186. URL_COMPONENTS urlComponents;
  187. memset(&urlComponents, 0, sizeof(URL_COMPONENTS)); 
  188. urlComponents.dwStructSize = sizeof(URL_COMPONENTS);
  189. urlComponents.lpszHostName = hostName;
  190. urlComponents.dwHostNameLength = INTERNET_MAX_PATH_LENGTH;
  191. urlComponents.lpszUrlPath   = strPathName;
  192. urlComponents.dwUrlPathLength = INTERNET_MAX_PATH_LENGTH;
  193. if (!InternetCrackUrl(url, url.length(), 0, &urlComponents)) 
  194. return E_INVALIDARG;
  195. m_Method = method;
  196. m_HostName = hostName;
  197. if (urlComponents.nPort != 0)
  198. m_Port = urlComponents.nPort; 
  199. m_URLPath = strPathName;
  200. m_bAsync = (VARIANT_TRUE == V_BOOL(&varAsync)) ? true : false; 
  201. if (VT_BSTR == V_VT(&bstrUser))
  202. m_User = V_BSTR(&bstrUser);
  203. else
  204. m_User = _T("");
  205. if (VT_BSTR == V_VT(&bstrPassword) && m_User.length() > 0)
  206. m_Password = V_BSTR(&bstrPassword);
  207. else
  208. m_Password = _T(""); 
  209. return S_OK;
  210. }
  211. STDMETHODIMP CXMLHttpRequest::setRequestHeader(BSTR bstrHeader,  BSTR bstrValue)
  212. {
  213. ATLTRACE(_T("CXMLHttpRequest::setRequestHeadern"));
  214. if (NULL == bstrHeader || NULL == bstrValue)
  215. return E_INVALIDARG;
  216. // check if there is a send active  
  217. if (NULL != m_hThread) {
  218. DWORD exitCode = 0;
  219. BOOL rc = ::GetExitCodeThread(m_hThread, &exitCode);
  220. if (!rc || STILL_ACTIVE == exitCode) 
  221. return E_PENDING;
  222. ::CloseHandle(m_hThread);
  223. m_hThread = NULL;
  224. }
  225. m_RequestHeaderMap.Remove(bstrHeader);
  226. m_RequestHeaderMap.Add(bstrHeader,bstrValue);
  227. return S_OK;
  228. }
  229. STDMETHODIMP CXMLHttpRequest::getResponseHeader(BSTR bstrHeader, BSTR * pbstrValue)
  230. {
  231. ATLTRACE(_T("CXMLHttpRequest::getResponseHeadern"));
  232. if (NULL == pbstrValue)
  233. return E_POINTER;
  234. *pbstrValue = NULL;
  235. if (NULL == bstrHeader)
  236. return E_INVALIDARG;
  237. // check if there is a send active  
  238. if (NULL != m_hThread) {
  239. DWORD exitCode = 0;
  240. BOOL rc = ::GetExitCodeThread(m_hThread, &exitCode);
  241. if (!rc || STILL_ACTIVE == exitCode) 
  242. return E_PENDING;
  243. ::CloseHandle(m_hThread);
  244. m_hThread = NULL;
  245. }
  246. if (0 == m_ResponseHeaders.length())
  247. return S_FALSE;
  248. _bstr_t value;
  249. _bstr_t header(bstrHeader);
  250. header += _T(": ");
  251. _tcslwr(header);
  252. TCHAR *pHeaders = new TCHAR[m_ResponseHeaders.length() + sizeof(TCHAR)];
  253. _tcscpy(pHeaders,m_ResponseHeaders);
  254. _tcslwr(pHeaders);
  255. TCHAR *pStart = _tcsstr(pHeaders,header);
  256. if (pStart) {
  257. pStart += header.length();
  258. TCHAR *pEnd = _tcsstr(pStart,_T("rn"));
  259. if (pEnd) {
  260. TCHAR *pHeader = new TCHAR[pEnd-pStart + sizeof(TCHAR)];
  261. _tcsncpy(pHeader,static_cast<LPCTSTR> (m_ResponseHeaders) + (pStart-pHeaders),pEnd-pStart);
  262. value = pHeader;
  263. delete [] pHeader;
  264. }
  265. }
  266. delete[] pHeaders;
  267. if (0 == value.length())
  268. return S_FALSE;
  269. *pbstrValue = value.copy();
  270. return S_OK;
  271. }
  272. STDMETHODIMP CXMLHttpRequest::getAllResponseHeaders(BSTR * pbstrHeaders)
  273. {
  274. ATLTRACE(_T("CXMLHttpRequest::getAllResponseHeadersn"));
  275. if (NULL == pbstrHeaders)
  276. return E_POINTER;
  277. *pbstrHeaders = NULL;
  278. if (NULL == pbstrHeaders)
  279. return E_INVALIDARG;
  280. // check if there is a send active  
  281. if (NULL != m_hThread) {
  282. DWORD exitCode = 0;
  283. BOOL rc = ::GetExitCodeThread(m_hThread, &exitCode);
  284. if (!rc || STILL_ACTIVE == exitCode) 
  285. return E_PENDING;
  286. ::CloseHandle(m_hThread);
  287. m_hThread = NULL;
  288. }
  289. *pbstrHeaders = m_ResponseHeaders.copy();
  290. return S_OK;
  291. }
  292. STDMETHODIMP CXMLHttpRequest::send(VARIANT varBody)
  293. {
  294. ATLTRACE(_T("CXMLHttpRequest::sendn"));
  295. if (V_VT(&varBody) != VT_BSTR && 
  296. V_VT(&varBody) != VT_DISPATCH &&
  297. V_VT(&varBody) != (VT_ARRAY | VT_VARIANT) &&
  298. V_VT(&varBody) != (VT_ARRAY | VT_UI1) &&
  299. V_VT(&varBody) != VT_UNKNOWN)
  300. return E_INVALIDARG;
  301. // do not start another thread if there is another active  
  302. if (NULL != m_hThread) {
  303. DWORD exitCode = 0;
  304. BOOL rc = ::GetExitCodeThread(m_hThread, &exitCode);
  305. if (!rc || STILL_ACTIVE == exitCode) 
  306. return E_PENDING;
  307. ::CloseHandle(m_hThread);
  308. m_hThread = NULL;
  309. }
  310. HRESULT hr = S_OK;
  311. m_bSuccess = true;
  312. m_bAbort = false;
  313. delete [] m_pBody;
  314. m_pBody = NULL;
  315. m_lBodyLength = 0;
  316. delete [] m_pResponseBody;
  317. m_pResponseBody = NULL;
  318. m_lResponseBodyLength = 0;
  319. m_dwStatus  = 0;
  320. m_StatusText = _T("");
  321. m_ResponseHeaders = _T("");
  322. if (V_VT(&varBody) == VT_BSTR) {
  323. _bstr_t body = V_BSTR(&varBody);
  324. m_lBodyLength = body.length() + 1;
  325. m_pBody = new BYTE[m_lBodyLength];
  326. memset(m_pBody,0,m_lBodyLength);
  327. memcpy(m_pBody,static_cast<char*> (body),body.length());
  328. }
  329. else
  330. if (V_VT(&varBody) == VT_UNKNOWN) {
  331. CComQIPtr<IStream,&IID_IStream> pS(V_UNKNOWN(&varBody));
  332. if (!pS)
  333. return E_INVALIDARG;
  334. CComBSTR b;
  335. hr = b.ReadFromStream(pS);
  336. if (S_OK != hr)
  337. return hr;
  338. _bstr_t body = b;
  339. m_lBodyLength = body.length() + 1;
  340. m_pBody = new BYTE[m_lBodyLength];
  341. memset(m_pBody,0,m_lBodyLength);
  342. memcpy(m_pBody,static_cast<char*> (body),body.length());
  343. }
  344. else
  345. if (V_VT(&varBody) == VT_DISPATCH) {
  346. CComQIPtr<IXMLDOMDocument,&IID_IXMLDOMDocument> pDoc(V_DISPATCH(&varBody));
  347. if (!pDoc)
  348. return E_INVALIDARG;
  349. BSTR b = NULL;
  350. hr = pDoc->get_xml(&b);
  351. if (S_OK != hr)
  352. return hr;
  353. _bstr_t body = b;
  354. ::SysFreeString(b);
  355. m_lBodyLength = body.length() + 1;
  356. m_pBody = new BYTE[m_lBodyLength];
  357. memset(m_pBody,0,m_lBodyLength);
  358. memcpy(m_pBody,static_cast<char*> (body),body.length());
  359. }
  360. else
  361. if (V_VT(&varBody) == (VT_ARRAY | VT_VARIANT)) {
  362. SAFEARRAY *pArray = reinterpret_cast<SAFEARRAY *> (varBody.byref);
  363. if (NULL == pArray)
  364. return E_INVALIDARG;
  365. long lLBoundVar = 0;
  366. long lUBoundVar = 0;
  367. UINT dims = ::SafeArrayGetDim(pArray);
  368. if (dims == 0)
  369. return E_INVALIDARG;
  370. hr = ::SafeArrayGetLBound(pArray, dims, &lLBoundVar);
  371. if (S_OK != hr)
  372. return hr;
  373. hr = ::SafeArrayGetUBound(pArray, dims, &lUBoundVar);
  374. if (S_OK != hr)
  375. return hr;
  376. if (lUBoundVar >= lLBoundVar) {
  377. VARIANT *pIndex = NULL; 
  378. hr = ::SafeArrayAccessData(pArray, reinterpret_cast<void **> (&pIndex));
  379. if (S_OK != hr)
  380. return hr;
  381. m_lBodyLength = lUBoundVar-lLBoundVar+1;
  382. m_pBody = new BYTE[m_lBodyLength];
  383. for (long i = 0; i <= lUBoundVar-lLBoundVar; ++i) {
  384. VARIANT var = pIndex[i];
  385. if (V_VT(&var) != VT_UI1) {
  386. hr = E_INVALIDARG;
  387. break;
  388. }
  389. m_pBody[i] = V_UI1(&var); 
  390. }
  391. ::SafeArrayUnaccessData(pArray);
  392. if (S_OK != hr) {
  393. delete [] m_pBody;
  394. m_pBody = NULL;
  395. m_lBodyLength = 0;
  396. return hr;
  397. }
  398. }
  399. }
  400. else
  401. if (V_VT(&varBody) == (VT_ARRAY | VT_UI1)) {
  402. SAFEARRAY *pArray = reinterpret_cast<SAFEARRAY *> (varBody.byref);
  403. if (NULL == pArray)
  404. return E_INVALIDARG;
  405. long lLBoundVar = 0;
  406. long lUBoundVar = 0;
  407. UINT dims = ::SafeArrayGetDim(pArray);
  408. if (dims == 0)
  409. return E_INVALIDARG;
  410. hr = ::SafeArrayGetLBound(pArray, dims, &lLBoundVar);
  411. if (S_OK != hr)
  412. return hr;
  413. hr = ::SafeArrayGetUBound(pArray, dims, &lUBoundVar);
  414. if (S_OK != hr)
  415. return hr;
  416. if (lUBoundVar >= lLBoundVar) {
  417. BYTE *pIndex = NULL; 
  418. hr = ::SafeArrayAccessData(pArray, reinterpret_cast<void **> (&pIndex));
  419. if (S_OK != hr)
  420. return hr;
  421. m_lBodyLength = lUBoundVar-lLBoundVar+1;
  422. m_pBody = new BYTE[m_lBodyLength];
  423. for (long i = 0; i <= lUBoundVar-lLBoundVar; ++i)
  424. m_pBody[i] = pIndex[i]; 
  425. ::SafeArrayUnaccessData(pArray);
  426. }
  427. }
  428. m_HwndParent = GetParentWindow();
  429. UINT nthreadID = 0;
  430. m_hThread = reinterpret_cast<HANDLE> (_beginthreadex(NULL,
  431.  0,
  432.      CXMLHttpRequest::SendThread,
  433.  (void *) this, 
  434.  0,
  435.  &nthreadID));
  436. if (NULL == m_hThread) 
  437. return E_FAIL;
  438. if (m_bAsync) 
  439. return S_OK;
  440. bool bWait = true;
  441. while (bWait) {
  442. DWORD dwEvt = MsgWaitForMultipleObjects(1,&m_hThread,FALSE,INFINITE,QS_ALLINPUT);
  443. switch(dwEvt) {
  444. case WAIT_OBJECT_0:
  445. bWait = false;
  446. break;
  447. case WAIT_OBJECT_0 + 1:
  448. {
  449. MSG msg;
  450. while(::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { 
  451. if (WM_CLOSE == msg.message || WM_QUIT == msg.message) {
  452.  bWait = false;
  453.  m_bAbort = true;
  454.  break;
  455. }
  456. else {
  457. PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
  458. TranslateMessage(&msg);  
  459. DispatchMessage(&msg);
  460. }
  461. }
  462. break;
  463. }
  464. default:
  465. m_bAbort = true;
  466. bWait = false;
  467. break;
  468. }
  469. }
  470. return S_OK;
  471. }
  472. UINT APIENTRY CXMLHttpRequest::SendThread(void *pParm)
  473. {
  474. ATLTRACE(_T("CXMLHttpRequest::SendThreadn"));
  475. CXMLHttpRequest *pCtx = reinterpret_cast<CXMLHttpRequest *> (pParm);
  476. if (NULL == pCtx)
  477. return 0;
  478. HINTERNET hOpen    = NULL;
  479. HINTERNET hConnect = NULL; 
  480. HINTERNET hRequest = NULL; 
  481. hOpen = InternetOpen(_T("XMLHTTP/1.0"),INTERNET_OPEN_TYPE_PRECONFIG,
  482. NULL,NULL,0);
  483. if (NULL == hOpen) {
  484. DWORD res = GetLastError();
  485. pCtx->m_Error = CXMLHttpRequest::GetErrorMsg(res);
  486. pCtx->m_bSuccess = false;
  487. }
  488. if (!pCtx->m_bAbort && pCtx->m_bSuccess) {
  489. if (INTERNET_INVALID_STATUS_CALLBACK == InternetSetStatusCallback(hOpen,
  490. CXMLHttpRequest::InternetStatusCallback)) {
  491. pCtx->m_Error = _T("Invalid Internet Status Callback function.");
  492. pCtx->m_bSuccess = false;
  493. }
  494. }
  495. bool bPromptForAuthentication = true;
  496. if (!pCtx->m_bAbort && pCtx->m_bSuccess) {
  497. LPTSTR lpszUserName = NULL;
  498. LPTSTR lpszPassword = NULL;
  499. if (pCtx->m_User.length() > 0) {
  500. bPromptForAuthentication = false;
  501. lpszUserName = pCtx->m_User; 
  502. if (pCtx->m_Password.length() > 0) 
  503. lpszPassword = pCtx->m_Password;
  504. }    
  505. hConnect = InternetConnect(hOpen,pCtx->m_HostName,pCtx->m_Port,lpszUserName,lpszPassword,
  506. INTERNET_SERVICE_HTTP,0,reinterpret_cast<DWORD> (pCtx));
  507. if (NULL == hConnect) {
  508. DWORD res = GetLastError();
  509. pCtx->m_Error = CXMLHttpRequest::GetErrorMsg(res);
  510. pCtx->m_bSuccess = false;
  511. }
  512. }
  513. if (!pCtx->m_bAbort && pCtx->m_bSuccess) {
  514. DWORD dwFlags = (443 == pCtx->m_Port) ? INTERNET_FLAG_SECURE : 0;
  515. dwFlags |= INTERNET_FLAG_NO_CACHE_WRITE;
  516. hRequest = HttpOpenRequest(hConnect,pCtx->m_Method,
  517. pCtx->m_URLPath,NULL,NULL,NULL,
  518. dwFlags,reinterpret_cast<DWORD> (pCtx));
  519. if (NULL == hRequest) {
  520. DWORD res = GetLastError();
  521. pCtx->m_bSuccess = false;
  522. pCtx->m_Error = CXMLHttpRequest::GetErrorMsg(res);
  523. }
  524. }
  525. BOOL rc = TRUE;
  526. if (!pCtx->m_bAbort && pCtx->m_bSuccess && pCtx->m_RequestHeaderMap.GetSize() > 0) {
  527. _bstr_t requestHeaders;
  528. for (int i = 0 ; i < pCtx->m_RequestHeaderMap.GetSize(); ++i) {
  529. requestHeaders += pCtx->m_RequestHeaderMap.GetKeyAt(i);
  530. requestHeaders += _T(": ");
  531. requestHeaders += pCtx->m_RequestHeaderMap.GetValueAt(i);
  532. requestHeaders += _T("rn");
  533. }
  534. rc = HttpAddRequestHeaders(hRequest,requestHeaders,-1,HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE);
  535. if (!rc) {
  536. DWORD res = GetLastError();
  537. pCtx->m_bSuccess = false;
  538. pCtx->m_Error = CXMLHttpRequest::GetErrorMsg(res);
  539. }
  540. }
  541. DWORD dwLen = 0;
  542. DWORD dwError = ERROR_SUCCESS; 
  543. do {
  544. if (!pCtx->m_bAbort && pCtx->m_bSuccess) {
  545. rc = HttpSendRequest(hRequest,NULL,0,pCtx->m_pBody,pCtx->m_lBodyLength);
  546. if (!rc) {
  547. DWORD res = GetLastError();
  548. pCtx->m_bSuccess = false;
  549. pCtx->m_Error = CXMLHttpRequest::GetErrorMsg(res);
  550. break;
  551. }
  552. }
  553. if (!pCtx->m_bAbort && pCtx->m_bSuccess) {
  554. dwLen = sizeof(DWORD);
  555. rc = HttpQueryInfo(hRequest,
  556.    HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
  557.    &pCtx->m_dwStatus,&dwLen,NULL);
  558. if (!rc) {
  559. DWORD res = GetLastError();
  560. pCtx->m_bSuccess = false;
  561. pCtx->m_Error = CXMLHttpRequest::GetErrorMsg(res);
  562. break;
  563. }
  564. }
  565. if (!pCtx->m_bAbort && pCtx->m_bSuccess &&
  566. bPromptForAuthentication &&
  567. (HTTP_STATUS_PROXY_AUTH_REQ == pCtx->m_dwStatus ||
  568.  HTTP_STATUS_DENIED     == pCtx->m_dwStatus)) 
  569.     dwError = InternetErrorDlg(pCtx->m_HwndParent,
  570.    hRequest,
  571.    ERROR_INTERNET_INCORRECT_PASSWORD,
  572.    FLAGS_ERROR_UI_FILTER_FOR_ERRORS    |
  573.    FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS |
  574.    FLAGS_ERROR_UI_FLAGS_GENERATE_DATA,
  575.    NULL);
  576. else
  577. break;
  578. } while (ERROR_INTERNET_FORCE_RETRY == dwError &&
  579.  !pCtx->m_bAbort && pCtx->m_bSuccess); 
  580. if (!pCtx->m_bAbort && pCtx->m_bSuccess) {
  581. dwLen = 1024;
  582. TCHAR *pBuff = new TCHAR[dwLen];
  583. rc = HttpQueryInfo(hRequest,HTTP_QUERY_RAW_HEADERS_CRLF,pBuff,&dwLen,NULL);
  584. if (!rc) {
  585. DWORD res = GetLastError();
  586. if (ERROR_INSUFFICIENT_BUFFER == res) {
  587. delete [] pBuff;
  588. pBuff = new TCHAR[dwLen];
  589. rc = HttpQueryInfo(hRequest,HTTP_QUERY_RAW_HEADERS_CRLF,pBuff,&dwLen,NULL);
  590. if (!rc) {
  591. res = GetLastError();
  592. pCtx->m_bSuccess = false;
  593. pCtx->m_Error = CXMLHttpRequest::GetErrorMsg(res);
  594. }
  595. }
  596. else {
  597. pCtx->m_bSuccess = false;
  598. pCtx->m_Error = CXMLHttpRequest::GetErrorMsg(res);
  599. }
  600. }
  601. if (rc)
  602.  pCtx->m_ResponseHeaders = pBuff;
  603. delete [] pBuff;
  604. }
  605. if (!pCtx->m_bAbort && pCtx->m_bSuccess) {
  606. dwLen = 1024;
  607. TCHAR *pBuff = new TCHAR[dwLen];
  608. rc = HttpQueryInfo(hRequest,HTTP_QUERY_STATUS_TEXT,pBuff,&dwLen,NULL);
  609. if (!rc) {
  610. DWORD res = GetLastError();
  611. if (ERROR_INSUFFICIENT_BUFFER == res) {
  612. delete [] pBuff;
  613. pBuff = new TCHAR[dwLen];
  614. rc = HttpQueryInfo(hRequest,HTTP_QUERY_STATUS_TEXT,pBuff,&dwLen,NULL);
  615. if (!rc) 
  616. _tcscpy(pBuff,_T("Unknown"));
  617. }
  618. else 
  619. _tcscpy(pBuff,_T("Unknown"));
  620. }
  621. pCtx->m_StatusText = pBuff; 
  622. delete [] pBuff;
  623. if (HTTP_STATUS_OK != pCtx->m_dwStatus) {
  624. TCHAR errBuff[MAX_PATH] = _T("");
  625. wsprintf(errBuff,_T("HTTP Status Code: %d, Reason: "),pCtx->m_dwStatus);
  626. pCtx->m_Error = errBuff;
  627. pCtx->m_Error += pCtx->m_StatusText;
  628. pCtx->m_bSuccess = false;
  629. }
  630. }
  631. if (!pCtx->m_bAbort && pCtx->m_bSuccess) {
  632. PBYTE buffer[255];
  633. DWORD dwRead = 0;
  634. delete [] pCtx->m_pResponseBody;
  635. pCtx->m_pResponseBody = NULL;
  636. pCtx->m_lResponseBodyLength = 0;
  637. while (rc = InternetReadFile(hRequest,buffer,255,&dwRead)) {
  638. if (!rc || pCtx->m_bAbort || 0 == dwRead) 
  639. break;
  640. PBYTE tmp = new BYTE[pCtx->m_lResponseBodyLength + dwRead];
  641. if (pCtx->m_pResponseBody) {
  642. memcpy(tmp,pCtx->m_pResponseBody,pCtx->m_lResponseBodyLength);
  643. delete [] pCtx->m_pResponseBody;
  644. }
  645. memcpy(tmp+pCtx->m_lResponseBodyLength,buffer,dwRead);
  646. pCtx->m_pResponseBody = tmp;
  647. pCtx->m_lResponseBodyLength += dwRead;
  648. }
  649. if (!rc) {
  650. DWORD res = GetLastError();
  651. pCtx->m_Error = _T("Error reading response: ") + CXMLHttpRequest::GetErrorMsg(res);
  652. pCtx->m_bSuccess = false;
  653. }
  654. }
  655. if (hRequest != NULL)
  656. InternetCloseHandle(hRequest);
  657. if (hConnect != NULL) 
  658. InternetCloseHandle(hConnect);
  659. if (hOpen)
  660. InternetCloseHandle(hOpen);
  661. if (!pCtx->m_bAbort && pCtx->m_bAsync)
  662. ::PostMessage(pCtx->m_hWnd,MSG_READY_STATE_CHANGE,4,0); 
  663.   
  664. return 0;
  665. }
  666. HWND CXMLHttpRequest::GetParentWindow()
  667. {
  668. HWND hWnd = GetDesktopWindow();
  669. CComPtr<IServiceProvider> pSP;
  670. HRESULT hr = GetSite(IID_IServiceProvider, reinterpret_cast<LPVOID *> (&pSP));
  671.     if (S_OK != hr)
  672. return hWnd;
  673. CComPtr<IWebBrowser2> pWB;
  674.     hr = pSP->QueryService(SID_SWebBrowserApp,IID_IWebBrowser2,
  675.                                  reinterpret_cast<LPVOID *> (&pWB));
  676. if (S_OK != hr)
  677. return hWnd;
  678. long lWnd = 0;
  679. hr = pWB->get_HWND(&lWnd);
  680. if (S_OK != hr)
  681. return hWnd;
  682. return reinterpret_cast<HWND> (lWnd);
  683. }
  684. void CALLBACK  CXMLHttpRequest::InternetStatusCallback(HINTERNET hInternet,
  685. DWORD dwContext,
  686. DWORD dwInternetStatus,
  687. LPVOID lpvStatusInformation,
  688. DWORD dwStatusInformationLength)
  689. {
  690. ATLTRACE(_T("CXMLHttpRequest::InternetStatusCallback - dwInternetStatus %dn"),dwInternetStatus);
  691. }
  692. STDMETHODIMP CXMLHttpRequest::abort()
  693. {
  694. ATLTRACE(_T("CXMLHttpRequest::abortn"));
  695. m_bAbort = true;
  696. return S_OK;
  697. }
  698. STDMETHODIMP CXMLHttpRequest::get_status(long * plStatus)
  699. {
  700. ATLTRACE(_T("CXMLHttpRequest::get_statusn"));
  701. if (NULL == plStatus)
  702. return E_POINTER;
  703. *plStatus = 0;
  704. // check if there is a send active  
  705. if (NULL != m_hThread) {
  706. DWORD exitCode = 0;
  707. BOOL rc = ::GetExitCodeThread(m_hThread, &exitCode);
  708. if (!rc || STILL_ACTIVE == exitCode) 
  709. return E_PENDING;
  710. ::CloseHandle(m_hThread);
  711. m_hThread = NULL;
  712. }
  713. *plStatus = m_dwStatus;
  714. return S_OK;
  715. }
  716. STDMETHODIMP CXMLHttpRequest::get_statusText( BSTR * pbstrStatus)
  717. {
  718. ATLTRACE(_T("CXMLHttpRequest::get_statusTextn"));
  719. if (NULL == pbstrStatus)
  720. return E_POINTER;
  721. *pbstrStatus = NULL;
  722. // check if there is a send active  
  723. if (NULL != m_hThread) {
  724. DWORD exitCode = 0;
  725. BOOL rc = ::GetExitCodeThread(m_hThread, &exitCode);
  726. if (!rc || STILL_ACTIVE == exitCode) 
  727. return E_PENDING;
  728. ::CloseHandle(m_hThread);
  729. m_hThread = NULL;
  730. }
  731. *pbstrStatus = m_StatusText.copy();
  732. return S_OK;
  733. }
  734. STDMETHODIMP CXMLHttpRequest::get_responseXML(IDispatch **ppBody)
  735. {
  736. ATLTRACE(_T("CXMLHttpRequest::get_responseXMLn"));
  737. if (NULL == ppBody)
  738. return E_POINTER;
  739. *ppBody = NULL;
  740. // check if there is a send active 
  741. if (NULL != m_hThread) {
  742. DWORD exitCode = 0;
  743. BOOL rc = ::GetExitCodeThread(m_hThread, &exitCode);
  744. if (!rc || STILL_ACTIVE == exitCode) 
  745. return E_PENDING;
  746. ::CloseHandle(m_hThread);
  747. m_hThread = NULL;
  748. }
  749. BSTR text = NULL;
  750. HRESULT hr = get_responseText(&text);
  751. if (S_OK != hr || NULL == text)
  752. return hr;
  753. CXMLDOMDocumentObj *pObj = NULL;
  754. hr = CXMLDOMDocumentObj::CreateInstance(&pObj);
  755. if (S_OK == hr) {
  756. pObj->AddRef();
  757. VARIANT_BOOL isSuccessful = VARIANT_FALSE;
  758. hr = pObj->loadXML(text, &isSuccessful);
  759. if (S_OK == hr && VARIANT_TRUE == isSuccessful) {
  760. *ppBody = pObj;
  761. (*ppBody)->AddRef();
  762. }
  763. pObj->Release();
  764. }
  765. ::SysFreeString(text);
  766. return hr;
  767. }
  768. STDMETHODIMP CXMLHttpRequest::get_responseText(BSTR *pVal)
  769. {
  770. ATLTRACE(_T("CXMLHttpRequest::get_responseTextn"));
  771. if (NULL == pVal)
  772. return E_POINTER;
  773. *pVal = NULL;
  774. // check if there is a send active 
  775. if (NULL != m_hThread) {
  776. DWORD exitCode = 0;
  777. BOOL rc = ::GetExitCodeThread(m_hThread, &exitCode);
  778. if (!rc || STILL_ACTIVE == exitCode) 
  779. return E_PENDING;
  780. ::CloseHandle(m_hThread);
  781. m_hThread = NULL;
  782. }
  783. if (NULL == m_pResponseBody)
  784. return S_OK;
  785. TCHAR *psz = new TCHAR[m_lResponseBodyLength+1];
  786. ZeroMemory(psz,m_lResponseBodyLength+1);
  787. CopyMemory(psz,m_pResponseBody,m_lResponseBodyLength);
  788.   
  789. *pVal =  SysAllocStringByteLen(psz,m_lResponseBodyLength); 
  790. delete [] psz;
  791.  
  792. return S_OK;
  793. }
  794. STDMETHODIMP CXMLHttpRequest::get_responseBody(VARIANT *pVal)
  795. {
  796. ATLTRACE(_T("CXMLHttpRequest::get_responseBodyn"));
  797. if (NULL == pVal)
  798. return E_POINTER;
  799. ::VariantInit(pVal);
  800. V_VT(pVal) = VT_NULL;
  801. // check if there is a send active 
  802. if (NULL != m_hThread) {
  803. DWORD exitCode = 0;
  804. BOOL rc = ::GetExitCodeThread(m_hThread, &exitCode);
  805. if (!rc || STILL_ACTIVE == exitCode) 
  806. return E_PENDING;
  807. ::CloseHandle(m_hThread);
  808. m_hThread = NULL;
  809. }
  810. if (NULL == m_pResponseBody)
  811. return S_OK;
  812. return CXMLHttpRequest::InitializeVarFromByte(*pVal, m_pResponseBody,m_lResponseBodyLength);
  813. }
  814. STDMETHODIMP CXMLHttpRequest::get_responseStream(VARIANT *pVal)
  815. {
  816. ATLTRACE(_T("CXMLHttpRequest::get_responseStreamn"));
  817. if (NULL == pVal)
  818. return E_POINTER;
  819. ::VariantInit(pVal);
  820. V_VT(pVal) = VT_NULL;
  821. // check if there is a send active 
  822. if (NULL != m_hThread) {
  823. DWORD exitCode = 0;
  824. BOOL rc = ::GetExitCodeThread(m_hThread, &exitCode);
  825. if (!rc || STILL_ACTIVE == exitCode) 
  826. return E_PENDING;
  827. ::CloseHandle(m_hThread);
  828. m_hThread = NULL;
  829. }
  830. if (NULL == m_pResponseBody)
  831. return S_OK;
  832. //Create an IStream from global memory
  833. CComPtr<IStream> pStm;
  834.     HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, &pStm);
  835.     if (S_OK != hr) 
  836. return hr;
  837. hr = pStm->Write(m_pResponseBody, m_lResponseBodyLength, NULL);
  838. if (S_OK != hr) 
  839. return hr;
  840. LARGE_INTEGER dlibMove;
  841. memset(&dlibMove,0,sizeof(LARGE_INTEGER));
  842. hr = pStm->Seek(dlibMove,STREAM_SEEK_SET,NULL);    
  843. if (S_OK != hr) 
  844. return hr;
  845. V_VT(pVal) = VT_UNKNOWN;
  846. V_UNKNOWN(pVal) = pStm.Detach(); 
  847. return S_OK;
  848. }
  849. STDMETHODIMP CXMLHttpRequest::get_readyState(long *pVal)
  850. {
  851. ATLTRACE(_T("CXMLHttpRequest::get_readyStaten"));
  852. if (NULL == pVal)
  853. return E_POINTER;
  854. *pVal = m_lReadyState;
  855. return S_OK;
  856. }
  857. STDMETHODIMP CXMLHttpRequest::put_onreadystatechange(IDispatch * pReadyStateSink)
  858. {
  859. ATLTRACE(_T("CXMLHttpRequest::put_onreadystatechangen"));
  860. if (m_pOnReadyStateChange != NULL) {
  861. m_pOnReadyStateChange->Release();
  862. m_pOnReadyStateChange = NULL;
  863. }
  864. m_pOnReadyStateChange = pReadyStateSink;
  865. if (m_pOnReadyStateChange != NULL) 
  866. m_pOnReadyStateChange->AddRef();
  867. return S_OK;
  868. }
  869. _bstr_t CXMLHttpRequest::GetErrorMsg(DWORD rc)
  870. {
  871. _bstr_t msg(_T(""));
  872. TCHAR *lpBuffer = NULL;
  873. if (ERROR_INTERNET_EXTENDED_ERROR == rc) {
  874. DWORD dwError  = 0;
  875. DWORD dwLength = 0; 
  876. InternetGetLastResponseInfo (&dwError, NULL, &dwLength);
  877.         if (dwLength > 0) {
  878. lpBuffer = (TCHAR *) LocalAlloc(LPTR,dwLength);
  879. if (!lpBuffer) {
  880. msg = _T("Unable to allocate memory to display Internet extended error: ");
  881.                 rc = GetLastError();
  882.            }
  883. else {
  884.                 if (!InternetGetLastResponseInfo(&dwError,lpBuffer,&dwLength)) {
  885.     msg = _T("Unable to get Internet extended error: ");
  886.                     rc = GetLastError();
  887. LocalFree(lpBuffer);
  888.                 }
  889. else {
  890. int len = lstrlen(lpBuffer);
  891. for (int i=0; i < len; ++i) {
  892. if (_istcntrl(lpBuffer[i])) 
  893. lpBuffer[i] = _T(' ');
  894. }
  895. msg = lpBuffer;
  896. LocalFree(lpBuffer);
  897. return msg;
  898.   }
  899. }
  900. }
  901.     }
  902. lpBuffer = NULL;
  903. HMODULE hModule = NULL; // default to system source
  904.     
  905. if (rc >= INTERNET_ERROR_BASE) 
  906.  hModule = LoadLibraryEx(_T("wininet.dll"),NULL,LOAD_LIBRARY_AS_DATAFILE);
  907.     
  908. ::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  909. FORMAT_MESSAGE_IGNORE_INSERTS |
  910. FORMAT_MESSAGE_FROM_SYSTEM |
  911. ((hModule != NULL) ? FORMAT_MESSAGE_FROM_HMODULE : 0),
  912. hModule, 
  913. rc,
  914. MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
  915. (LPTSTR)&lpBuffer, 0, NULL);
  916. if (lpBuffer) {
  917. int len = lstrlen(lpBuffer);
  918. for (int i=0; i < len; ++i) {
  919. if (_istcntrl(lpBuffer[i])) 
  920. lpBuffer[i] = _T(' ');
  921. }
  922. }
  923. msg += lpBuffer;
  924. LocalFree(lpBuffer);
  925. if (hModule != NULL)
  926.     FreeLibrary(hModule);
  927. return msg;
  928. }
  929. HRESULT CXMLHttpRequest::InitializeVarFromByte(VARIANT &varOut, const PBYTE pByte, long lSize)
  930. {
  931. ::VariantInit(&varOut);
  932. V_VT(&varOut) = VT_NULL;
  933. HRESULT hr = S_OK;
  934. SAFEARRAYBOUND rgsabound[1];
  935. rgsabound[0].cElements = lSize;
  936. rgsabound[0].lLbound   = 0;
  937. SAFEARRAY *psa = ::SafeArrayCreate( VT_VARIANT, 1, rgsabound);
  938. if (psa == NULL)
  939. return E_FAIL;
  940. if (pByte != NULL) {
  941. long ix[1];
  942. for (ULONG i = 0; i < rgsabound[0].cElements; ++i) {
  943. ix[0] = i;
  944. VARIANT var;
  945. ::VariantInit(&var);
  946. V_VT(&var)   = VT_UI1;
  947. V_UI1(&var)  = pByte[i];
  948. hr = ::SafeArrayPutElement(psa, ix, &var);
  949. if (S_OK != hr) {
  950. ::SafeArrayDestroy(psa);
  951. break;
  952. }
  953. }
  954. }
  955. if (S_OK == hr) {
  956. V_VT(&varOut)  = VT_ARRAY | VT_VARIANT;
  957. V_ARRAY(&varOut) = psa;
  958. }
  959. return hr;
  960. }