Annotation of embedaddon/expat/xmlwf/xmlwin32url.cxx, revision 1.1

1.1     ! misho       1: #include "expat.h"
        !             2: #ifdef XML_UNICODE
        !             3: #define UNICODE
        !             4: #endif
        !             5: #include <windows.h>
        !             6: #include <urlmon.h>
        !             7: #include <wininet.h>
        !             8: #include <stdio.h>
        !             9: #include <tchar.h>
        !            10: #include "xmlurl.h"
        !            11: #include "xmlmime.h"
        !            12: 
        !            13: static int
        !            14: processURL(XML_Parser parser, IMoniker *baseMoniker, const XML_Char *url);
        !            15: 
        !            16: typedef void (*StopHandler)(void *, HRESULT);
        !            17: 
        !            18: class Callback : public IBindStatusCallback {
        !            19: public:
        !            20:   // IUnknown methods
        !            21:   STDMETHODIMP QueryInterface(REFIID,void **);
        !            22:   STDMETHODIMP_(ULONG) AddRef();
        !            23:   STDMETHODIMP_(ULONG) Release();
        !            24:   // IBindStatusCallback methods
        !            25:   STDMETHODIMP OnStartBinding(DWORD, IBinding *);
        !            26:   STDMETHODIMP GetPriority(LONG *);
        !            27:   STDMETHODIMP OnLowResource(DWORD);
        !            28:   STDMETHODIMP OnProgress(ULONG, ULONG, ULONG, LPCWSTR);
        !            29:   STDMETHODIMP OnStopBinding(HRESULT, LPCWSTR);
        !            30:   STDMETHODIMP GetBindInfo(DWORD *, BINDINFO *);
        !            31:   STDMETHODIMP OnDataAvailable(DWORD, DWORD, FORMATETC *, STGMEDIUM *);
        !            32:   STDMETHODIMP OnObjectAvailable(REFIID, IUnknown *);
        !            33:   Callback(XML_Parser, IMoniker *, StopHandler, void *);
        !            34:   ~Callback();
        !            35:   int externalEntityRef(const XML_Char *context,
        !            36:                         const XML_Char *systemId, const XML_Char *publicId);
        !            37: private:
        !            38:   XML_Parser parser_;
        !            39:   IMoniker *baseMoniker_;
        !            40:   DWORD totalRead_;
        !            41:   ULONG ref_;
        !            42:   IBinding *pBinding_;
        !            43:   StopHandler stopHandler_;
        !            44:   void *stopArg_;
        !            45: };
        !            46: 
        !            47: STDMETHODIMP_(ULONG)
        !            48: Callback::AddRef()
        !            49: { 
        !            50:   return ref_++;
        !            51: }
        !            52: 
        !            53: STDMETHODIMP_(ULONG)
        !            54: Callback::Release()
        !            55: { 
        !            56:   if (--ref_ == 0) {
        !            57:     delete this;
        !            58:     return 0;
        !            59:   }
        !            60:   return ref_;
        !            61: }
        !            62: 
        !            63: STDMETHODIMP
        !            64: Callback::QueryInterface(REFIID riid, void** ppv)
        !            65: { 
        !            66:   if (IsEqualGUID(riid, IID_IUnknown))
        !            67:     *ppv = (IUnknown *)this;
        !            68:   else if (IsEqualGUID(riid, IID_IBindStatusCallback))
        !            69:     *ppv = (IBindStatusCallback *)this;
        !            70:   else
        !            71:     return E_NOINTERFACE;
        !            72:   ((LPUNKNOWN)*ppv)->AddRef();
        !            73:   return S_OK;
        !            74: }
        !            75: 
        !            76: STDMETHODIMP
        !            77: Callback::OnStartBinding(DWORD, IBinding* pBinding)
        !            78: {
        !            79:   pBinding_ = pBinding;
        !            80:   pBinding->AddRef();
        !            81:   return S_OK;
        !            82: }
        !            83: 
        !            84: STDMETHODIMP
        !            85: Callback::GetPriority(LONG *)
        !            86: {
        !            87:   return E_NOTIMPL;
        !            88: }
        !            89: 
        !            90: STDMETHODIMP
        !            91: Callback::OnLowResource(DWORD)
        !            92: {
        !            93:   return E_NOTIMPL;
        !            94: }
        !            95: 
        !            96: STDMETHODIMP
        !            97: Callback::OnProgress(ULONG, ULONG, ULONG, LPCWSTR)
        !            98: {
        !            99:   return S_OK;
        !           100: }
        !           101: 
        !           102: STDMETHODIMP
        !           103: Callback::OnStopBinding(HRESULT hr, LPCWSTR szError)
        !           104: {
        !           105:   if (pBinding_) {
        !           106:     pBinding_->Release();
        !           107:     pBinding_ = 0;
        !           108:   }
        !           109:   if (baseMoniker_) {
        !           110:     baseMoniker_->Release();
        !           111:     baseMoniker_ = 0;
        !           112:   }
        !           113:   stopHandler_(stopArg_, hr);
        !           114:   return S_OK;
        !           115: }
        !           116: 
        !           117: STDMETHODIMP
        !           118: Callback::GetBindInfo(DWORD* pgrfBINDF, BINDINFO* pbindinfo)
        !           119: {
        !           120:   *pgrfBINDF = BINDF_ASYNCHRONOUS;
        !           121:   return S_OK;
        !           122: }
        !           123: 
        !           124: static void
        !           125: reportError(XML_Parser parser)
        !           126: {
        !           127:   int code = XML_GetErrorCode(parser);
        !           128:   const XML_Char *message = XML_ErrorString(code);
        !           129:   if (message)
        !           130:     _ftprintf(stderr, _T("%s:%d:%ld: %s\n"),
        !           131:             XML_GetBase(parser),
        !           132:             XML_GetErrorLineNumber(parser),
        !           133:             XML_GetErrorColumnNumber(parser),
        !           134:             message);
        !           135:   else
        !           136:     _ftprintf(stderr, _T("%s: (unknown message %d)\n"),
        !           137:               XML_GetBase(parser), code);
        !           138: }
        !           139: 
        !           140: STDMETHODIMP
        !           141: Callback::OnDataAvailable(DWORD grfBSCF,
        !           142:                           DWORD dwSize,
        !           143:                           FORMATETC *pfmtetc,
        !           144:                           STGMEDIUM* pstgmed)
        !           145: {
        !           146:   if (grfBSCF & BSCF_FIRSTDATANOTIFICATION) {
        !           147:     IWinInetHttpInfo *hp;
        !           148:     HRESULT hr = pBinding_->QueryInterface(IID_IWinInetHttpInfo,
        !           149:                                            (void **)&hp);
        !           150:     if (SUCCEEDED(hr)) {
        !           151:       char contentType[1024];
        !           152:       DWORD bufSize = sizeof(contentType);
        !           153:       DWORD flags = 0;
        !           154:       contentType[0] = 0;
        !           155:       hr = hp->QueryInfo(HTTP_QUERY_CONTENT_TYPE, contentType,
        !           156:                          &bufSize, 0, NULL);
        !           157:       if (SUCCEEDED(hr)) {
        !           158:        char charset[CHARSET_MAX];
        !           159:        getXMLCharset(contentType, charset);
        !           160:        if (charset[0]) {
        !           161: #ifdef XML_UNICODE
        !           162:          XML_Char wcharset[CHARSET_MAX];
        !           163:          XML_Char *p1 = wcharset;
        !           164:          const char *p2 = charset;
        !           165:          while ((*p1++ = (unsigned char)*p2++) != 0)
        !           166:            ;
        !           167:          XML_SetEncoding(parser_, wcharset);
        !           168: #else
        !           169:          XML_SetEncoding(parser_, charset);
        !           170: #endif
        !           171:        }
        !           172:       }
        !           173:       hp->Release();
        !           174:     }
        !           175:   }
        !           176:   if (!parser_)
        !           177:     return E_ABORT;
        !           178:   if (pstgmed->tymed == TYMED_ISTREAM) {
        !           179:     while (totalRead_ < dwSize) {
        !           180: #define READ_MAX (64*1024)
        !           181:       DWORD nToRead = dwSize - totalRead_;
        !           182:       if (nToRead > READ_MAX)
        !           183:        nToRead = READ_MAX;
        !           184:       void *buf = XML_GetBuffer(parser_, nToRead);
        !           185:       if (!buf) {
        !           186:        _ftprintf(stderr, _T("out of memory\n"));
        !           187:        return E_ABORT;
        !           188:       }
        !           189:       DWORD nRead;
        !           190:       HRESULT hr = pstgmed->pstm->Read(buf, nToRead, &nRead);
        !           191:       if (SUCCEEDED(hr)) {
        !           192:        totalRead_ += nRead;
        !           193:        if (!XML_ParseBuffer(parser_,
        !           194:                             nRead,
        !           195:                             (grfBSCF & BSCF_LASTDATANOTIFICATION) != 0
        !           196:                             && totalRead_ == dwSize)) {
        !           197:          reportError(parser_);
        !           198:          return E_ABORT;
        !           199:        }
        !           200:       }
        !           201:     }
        !           202:   }
        !           203:   return S_OK;
        !           204: }
        !           205: 
        !           206: STDMETHODIMP
        !           207: Callback::OnObjectAvailable(REFIID, IUnknown *)
        !           208: {
        !           209:   return S_OK;
        !           210: }
        !           211: 
        !           212: int
        !           213: Callback::externalEntityRef(const XML_Char *context,
        !           214:                             const XML_Char *systemId,
        !           215:                             const XML_Char *publicId)
        !           216: {
        !           217:   XML_Parser entParser = XML_ExternalEntityParserCreate(parser_, context, 0);
        !           218:   XML_SetBase(entParser, systemId);
        !           219:   int ret = processURL(entParser, baseMoniker_, systemId);
        !           220:   XML_ParserFree(entParser);
        !           221:   return ret;
        !           222: }
        !           223: 
        !           224: Callback::Callback(XML_Parser parser, IMoniker *baseMoniker,
        !           225:                    StopHandler stopHandler, void *stopArg)
        !           226: : parser_(parser),
        !           227:   baseMoniker_(baseMoniker),
        !           228:   ref_(0),
        !           229:   pBinding_(0),
        !           230:   totalRead_(0),
        !           231:   stopHandler_(stopHandler),
        !           232:   stopArg_(stopArg)
        !           233: {
        !           234:   if (baseMoniker_)
        !           235:     baseMoniker_->AddRef();
        !           236: }
        !           237: 
        !           238: Callback::~Callback()
        !           239: {
        !           240:   if (pBinding_)
        !           241:     pBinding_->Release();
        !           242:   if (baseMoniker_)
        !           243:     baseMoniker_->Release();
        !           244: }
        !           245: 
        !           246: static int
        !           247: externalEntityRef(void *arg,
        !           248:                   const XML_Char *context,
        !           249:                   const XML_Char *base,
        !           250:                   const XML_Char *systemId,
        !           251:                   const XML_Char *publicId)
        !           252: {
        !           253:   return ((Callback *)arg)->externalEntityRef(context, systemId, publicId);
        !           254: }
        !           255: 
        !           256: 
        !           257: static HRESULT
        !           258: openStream(XML_Parser parser,
        !           259:            IMoniker *baseMoniker,
        !           260:            const XML_Char *uri,
        !           261:            StopHandler stopHandler, void *stopArg)
        !           262: {
        !           263:   if (!XML_SetBase(parser, uri))
        !           264:     return E_OUTOFMEMORY;
        !           265:   HRESULT hr;
        !           266:   IMoniker *m;
        !           267: #ifdef XML_UNICODE
        !           268:   hr = CreateURLMoniker(0, uri, &m);
        !           269: #else
        !           270:   LPWSTR uriw = new wchar_t[strlen(uri) + 1];
        !           271:   for (int i = 0;; i++) {
        !           272:     uriw[i] = uri[i];
        !           273:     if (uriw[i] == 0)
        !           274:       break;
        !           275:   }
        !           276:   hr = CreateURLMoniker(baseMoniker, uriw, &m);
        !           277:   delete [] uriw;
        !           278: #endif
        !           279:   if (FAILED(hr))
        !           280:     return hr;
        !           281:   IBindStatusCallback *cb = new Callback(parser, m, stopHandler, stopArg);
        !           282:   XML_SetExternalEntityRefHandler(parser, externalEntityRef);
        !           283:   XML_SetExternalEntityRefHandlerArg(parser, cb);
        !           284:   cb->AddRef();
        !           285:   IBindCtx *b;
        !           286:   if (FAILED(hr = CreateAsyncBindCtx(0, cb, 0, &b))) {
        !           287:     cb->Release();
        !           288:     m->Release();
        !           289:     return hr;
        !           290:   }
        !           291:   cb->Release();
        !           292:   IStream *pStream;
        !           293:   hr = m->BindToStorage(b, 0, IID_IStream, (void **)&pStream);
        !           294:   if (SUCCEEDED(hr)) {
        !           295:     if (pStream)
        !           296:       pStream->Release();
        !           297:   }
        !           298:   if (hr == MK_S_ASYNCHRONOUS)
        !           299:     hr = S_OK;
        !           300:   m->Release();
        !           301:   b->Release();
        !           302:   return hr;
        !           303: }
        !           304: 
        !           305: struct QuitInfo {
        !           306:   const XML_Char *url;
        !           307:   HRESULT hr;
        !           308:   int stop;
        !           309: };
        !           310: 
        !           311: static void
        !           312: winPerror(const XML_Char *url, HRESULT hr)
        !           313: {
        !           314:   LPVOID buf;
        !           315:   if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
        !           316:                    | FORMAT_MESSAGE_FROM_HMODULE,
        !           317:                    GetModuleHandleA("urlmon.dll"),
        !           318:                    hr,
        !           319:                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        !           320:                    (LPTSTR) &buf,
        !           321:                    0,
        !           322:                    NULL)
        !           323:       || FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER
        !           324:                      | FORMAT_MESSAGE_FROM_SYSTEM,
        !           325:                      0,
        !           326:                      hr,
        !           327:                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        !           328:                      (LPTSTR) &buf,
        !           329:                      0,
        !           330:                      NULL)) {
        !           331:     /* The system error messages seem to end with a newline. */
        !           332:     _ftprintf(stderr, _T("%s: %s"), url, buf);
        !           333:     fflush(stderr);
        !           334:     LocalFree(buf);
        !           335:   }
        !           336:   else
        !           337:     _ftprintf(stderr, _T("%s: error %x\n"), url, hr);
        !           338: }
        !           339: 
        !           340: static void
        !           341: threadQuit(void *p, HRESULT hr)
        !           342: {
        !           343:   QuitInfo *qi = (QuitInfo *)p;
        !           344:   qi->hr = hr;
        !           345:   qi->stop = 1;
        !           346: }
        !           347: 
        !           348: extern "C"
        !           349: int
        !           350: XML_URLInit(void)
        !           351: {
        !           352:   return SUCCEEDED(CoInitialize(0));
        !           353: }
        !           354: 
        !           355: extern "C"
        !           356: void
        !           357: XML_URLUninit(void)
        !           358: {
        !           359:   CoUninitialize();
        !           360: }
        !           361: 
        !           362: static int
        !           363: processURL(XML_Parser parser, IMoniker *baseMoniker,
        !           364:            const XML_Char *url)
        !           365: {
        !           366:   QuitInfo qi;
        !           367:   qi.stop = 0;
        !           368:   qi.url = url;
        !           369: 
        !           370:   XML_SetBase(parser, url);
        !           371:   HRESULT hr = openStream(parser, baseMoniker, url, threadQuit, &qi);
        !           372:   if (FAILED(hr)) {
        !           373:     winPerror(url, hr);
        !           374:     return 0;
        !           375:   }
        !           376:   else if (FAILED(qi.hr)) {
        !           377:     winPerror(url, qi.hr);
        !           378:     return 0;
        !           379:   }
        !           380:   MSG msg;
        !           381:   while (!qi.stop && GetMessage (&msg, NULL, 0, 0)) {
        !           382:     TranslateMessage (&msg);
        !           383:     DispatchMessage (&msg);
        !           384:   }
        !           385:   return 1;
        !           386: }
        !           387: 
        !           388: extern "C"
        !           389: int
        !           390: XML_ProcessURL(XML_Parser parser,
        !           391:                const XML_Char *url,
        !           392:                unsigned flags)
        !           393: {
        !           394:   return processURL(parser, 0, url);
        !           395: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>