Created
October 26, 2014 08:22
-
-
Save SaitoAtsushi/aa975a93646f6a7b4334 to your computer and use it in GitHub Desktop.
同期モードなら大丈夫なのに非同期にすると status 1 のときにしかハンドラが呼ばれない
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define sync_mode true // 非同期モード。 これを false にすると動く。 | |
#include <windows.h> | |
#include <msxml2.h> | |
#include <comutil.h> | |
#include <cstdio> | |
#include <iostream> | |
#pragma comment(lib, "oleaut32.lib") | |
#pragma comment(lib, "msxml2.lib") | |
#pragma comment(lib, "user32.lib") | |
#pragma comment(lib, "ole32.lib") | |
#pragma comment(lib, "comsuppw.lib") | |
class MetadataRequest :public IDispatch { | |
private: | |
long count; | |
IXMLHttpRequest* req; | |
IXMLHttpRequest* createInstance(void); | |
public: | |
STDMETHODIMP QueryInterface(REFIID, void**) override; | |
ULONG STDMETHODCALLTYPE AddRef(void) override; | |
ULONG STDMETHODCALLTYPE Release(void) override; | |
STDMETHODIMP GetTypeInfoCount(UINT*) override; | |
STDMETHODIMP GetTypeInfo(UINT, LCID, ITypeInfo**) override; | |
STDMETHODIMP GetIDsOfNames(REFIID, LPOLESTR *, UINT, LCID, DISPID*) override; | |
STDMETHODIMP Invoke(DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT *, | |
EXCEPINFO *, UINT*) override; | |
HANDLE completedEvent; | |
MetadataRequest(BSTR) throw(HRESULT); | |
virtual ~MetadataRequest(void); | |
}; | |
ULONG STDMETHODCALLTYPE MetadataRequest::AddRef(void) { | |
return count++; | |
} | |
ULONG STDMETHODCALLTYPE MetadataRequest::Release(void) { | |
if (--count == 0) { | |
req->Release(); | |
delete this; | |
return 0; | |
} | |
return count; | |
} | |
STDMETHODIMP MetadataRequest::QueryInterface(REFIID riid, void** ppvObj) { | |
*ppvObj = NULL; | |
if (IsEqualIID(riid, IID_IUnknown)) | |
*ppvObj = dynamic_cast<IUnknown*>(this); | |
if (IsEqualIID(riid, IID_IDispatch)) | |
*ppvObj = dynamic_cast<IDispatch*>(this); | |
else | |
return E_NOINTERFACE; | |
AddRef(); | |
return S_OK; | |
} | |
STDMETHODIMP MetadataRequest::GetTypeInfoCount(unsigned int FAR* pctinfo) { | |
*pctinfo=1; | |
return NOERROR; | |
} | |
STDMETHODIMP | |
MetadataRequest::GetTypeInfo(unsigned int, LCID, ITypeInfo FAR* FAR*) { | |
return NOERROR; | |
} | |
STDMETHODIMP | |
MetadataRequest::GetIDsOfNames(REFIID, OLECHAR FAR* FAR*, | |
unsigned int, LCID, DISPID FAR*) { | |
return NOERROR; | |
} | |
IXMLHttpRequest* MetadataRequest::createInstance(void) { | |
IXMLHttpRequest* pReq; | |
HRESULT hr = CoCreateInstance(CLSID_XMLHTTP30, | |
NULL, | |
CLSCTX_ALL, | |
IID_IXMLHttpRequest, | |
reinterpret_cast<PVOID*>(&pReq)); | |
if(FAILED(hr)) throw hr; | |
return pReq; | |
} | |
MetadataRequest::MetadataRequest(BSTR url) | |
: req(createInstance()), | |
count(1), | |
completedEvent(CreateEvent(NULL, FALSE, FALSE, NULL)) { | |
_bstr_t method = L"GET"; | |
_variant_t async = sync_mode; | |
HRESULT hr = req->open(method, url, async, _variant_t(), _variant_t()); | |
if(FAILED(hr)) throw hr; | |
req->put_onreadystatechange(this); | |
if(FAILED(hr)) throw hr; | |
hr = req->send(_variant_t()); | |
if(FAILED(hr)) throw hr; | |
} | |
MetadataRequest::~MetadataRequest(void) { | |
req->Release(); | |
} | |
STDMETHODIMP | |
MetadataRequest::Invoke(DISPID dispIdMember, const IID &riid, LCID lcid, | |
WORD wFlags, DISPPARAMS *pDispParams, | |
VARIANT *pVarResult, EXCEPINFO *pExcepInfo, | |
UINT *puArgErr) { | |
if(dispIdMember != DISPID_VALUE) return DISP_E_MEMBERNOTFOUND; | |
long state; | |
req->get_readyState(&state); | |
std::wcout << L"state" << state << std::endl; | |
if(state == 4) { | |
long status; | |
req->get_status(&status); | |
if(status==200) { | |
_bstr_t body; | |
req->get_responseText(body.GetAddress()); | |
std::wcout << body << std::endl; | |
SetEvent(completedEvent); | |
} | |
} | |
return S_OK; | |
} | |
int main(void) { | |
CoInitializeEx(0, COINIT_APARTMENTTHREADED); | |
MetadataRequest* req = nullptr; | |
try { | |
_bstr_t url = "https://www.google.co.jp/"; | |
req = new MetadataRequest(url); | |
WaitForSingleObject(req->completedEvent, INFINITE); | |
req->Release(); | |
} catch(HRESULT hr) { | |
printf("result = %d\n", hr); | |
} | |
CoUninitialize(); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment