Annotation of embedaddon/expat/xmlwf/xmlwin32url.cxx, revision 1.1.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>