XMLHTTPRequest.cpp
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:30k
源码类别:

词法分析

开发平台:

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