diff --git a/reactos/dll/win32/crypt32/chain.c b/reactos/dll/win32/crypt32/chain.c index 5943117ddda..2e414cdddf8 100644 --- a/reactos/dll/win32/crypt32/chain.c +++ b/reactos/dll/win32/crypt32/chain.c @@ -306,7 +306,13 @@ static BOOL CRYPT_AddCertToSimpleChain(PCertificateChainEngine engine, = subjectInfoStatus; /* FIXME: initialize the rest of element */ if (!(chain->cElement % engine->CycleDetectionModulus)) + { CRYPT_CheckSimpleChainForCycles(chain); + /* Reinitialize the element pointer in case the chain is + * cyclic, in which case the chain is truncated. + */ + element = chain->rgpElement[chain->cElement - 1]; + } CRYPT_CombineTrustStatus(&chain->TrustStatus, &element->TrustStatus); ret = TRUE; diff --git a/reactos/dll/win32/crypt32/decode.c b/reactos/dll/win32/crypt32/decode.c index cda8b62aed1..2c2b543e852 100644 --- a/reactos/dll/win32/crypt32/decode.c +++ b/reactos/dll/win32/crypt32/decode.c @@ -1724,9 +1724,8 @@ static BOOL CRYPT_AsnDecodeUnicodeNameValueInternal(const BYTE *pbEncoded, case ASN_UTF8STRING: value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pbEncoded + 1 + lenBytes, dataLen, - str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2; - value->Value.pbData[value->Value.cbData / sizeof(WCHAR)] - = 0; + str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * sizeof(WCHAR); + *(WCHAR *)(value->Value.pbData + value->Value.cbData) = 0; value->Value.cbData += sizeof(WCHAR); break; } diff --git a/reactos/dll/win32/jscript/jsutils.c b/reactos/dll/win32/jscript/jsutils.c index defddd4b0cd..73bac94d7e8 100644 --- a/reactos/dll/win32/jscript/jsutils.c +++ b/reactos/dll/win32/jscript/jsutils.c @@ -27,6 +27,7 @@ #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(jscript); +WINE_DECLARE_DEBUG_CHANNEL(heap); const char *debugstr_variant(const VARIANT *v) { @@ -51,6 +52,7 @@ const char *debugstr_variant(const VARIANT *v) } #define MIN_BLOCK_SIZE 128 +#define ARENA_FREE_FILLER 0xaa static inline DWORD block_size(DWORD block) { @@ -83,26 +85,26 @@ void *jsheap_alloc(jsheap_t *heap, DWORD size) heap->block_cnt = 1; } - if(heap->offset + size < block_size(heap->last_block)) { + if(heap->offset + size <= block_size(heap->last_block)) { tmp = ((BYTE*)heap->blocks[heap->last_block])+heap->offset; heap->offset += size; return tmp; } - if(size < block_size(heap->last_block+1)) { + if(size <= block_size(heap->last_block+1)) { if(heap->last_block+1 == heap->block_cnt) { tmp = heap_realloc(heap->blocks, (heap->block_cnt+1)*sizeof(void*)); if(!tmp) return NULL; + heap->blocks = tmp; + heap->blocks[heap->block_cnt] = heap_alloc(block_size(heap->block_cnt)); + if(!heap->blocks[heap->block_cnt]) + return NULL; + + heap->block_cnt++; } - tmp = heap_alloc(block_size(heap->block_cnt+1)); - if(!tmp) - return NULL; - - heap->blocks[heap->block_cnt++] = tmp; - heap->last_block++; heap->offset = size; return heap->blocks[heap->last_block]; @@ -139,7 +141,15 @@ void jsheap_clear(jsheap_t *heap) heap_free(tmp); } + if(WARN_ON(heap)) { + DWORD i; + + for(i=0; i < heap->block_cnt; i++) + memset(heap->blocks[i], ARENA_FREE_FILLER, block_size(i)); + } + heap->last_block = heap->offset = 0; + heap->mark = FALSE; } void jsheap_free(jsheap_t *heap) diff --git a/reactos/dll/win32/mapi32/mapi32.rbuild b/reactos/dll/win32/mapi32/mapi32.rbuild index 39e527d1a8c..1c73d3ad8a4 100644 --- a/reactos/dll/win32/mapi32/mapi32.rbuild +++ b/reactos/dll/win32/mapi32/mapi32.rbuild @@ -11,6 +11,7 @@ prop.c sendmail.c util.c + version.rc wine shlwapi shell32 diff --git a/reactos/dll/win32/mapi32/version.rc b/reactos/dll/win32/mapi32/version.rc new file mode 100644 index 00000000000..0f955162b37 --- /dev/null +++ b/reactos/dll/win32/mapi32/version.rc @@ -0,0 +1,22 @@ +/* + * Copyright 2009 Vincent Povirk for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define WINE_FILEDESCRIPTION_STR "Wine Messaging API" +#define WINE_FILENAME_STR "mapi32.dll" + +#include "wine/wine_common_ver.rc" diff --git a/reactos/dll/win32/mlang/mlang.c b/reactos/dll/win32/mlang/mlang.c index 11fa366c5e8..f9c3f8e9baa 100644 --- a/reactos/dll/win32/mlang/mlang.c +++ b/reactos/dll/win32/mlang/mlang.c @@ -1912,9 +1912,34 @@ static HRESULT WINAPI fnIMLangFontLink_GetStrCodePages( DWORD* pdwCodePages, long* pcchCodePages) { - FIXME("(pszSrc=%s, cchSrc=%ld, dwPriorityCodePages=%d) stub\n", debugstr_w(pszSrc), cchSrc, dwPriorityCodePages); - *pdwCodePages = 0; - *pcchCodePages = 1; + long i; + DWORD cps = 0; + + TRACE("(%p)->%s %ld %x %p %p\n", iface, debugstr_wn(pszSrc,cchSrc),cchSrc,dwPriorityCodePages,pdwCodePages,pcchCodePages); + + if (pdwCodePages) *pdwCodePages = 0; + if (pcchCodePages) *pcchCodePages = 0; + + if (!pszSrc || !cchSrc || cchSrc < 0) + return E_INVALIDARG; + + for (i = 0; i < cchSrc; i++) + { + DWORD cp; + HRESULT ret; + + ret = fnIMLangFontLink_GetCharCodePages(iface, pszSrc[i], &cp); + if (ret != S_OK) return E_FAIL; + + if (!cps) cps = cp; + else cps &= cp; + + /* FIXME: not tested */ + if (dwPriorityCodePages & cps) break; + } + + if (pdwCodePages) *pdwCodePages = cps; + if (pcchCodePages) *pcchCodePages = i; return S_OK; } @@ -3179,10 +3204,8 @@ static HRESULT WINAPI fnIMLangFontLink2_GetStrCodePages( IMLangFontLink2* This, const WCHAR *pszSrc, long cchSrc, DWORD dwPriorityCodePages, DWORD *pdwCodePages, long *pcchCodePages) { - FIXME("(%p)->%s %li %x %p %p\n",This, debugstr_wn(pszSrc,cchSrc),cchSrc,dwPriorityCodePages,pdwCodePages,pcchCodePages); - *pdwCodePages = 0; - *pcchCodePages = 1; - return S_OK; + return fnIMLangFontLink_GetStrCodePages((IMLangFontLink *)This, + pszSrc, cchSrc, dwPriorityCodePages, pdwCodePages, pcchCodePages); } static HRESULT WINAPI fnIMLangFontLink2_CodePageToCodePages(IMLangFontLink2* This, diff --git a/reactos/dll/win32/msctf/categorymgr.c b/reactos/dll/win32/msctf/categorymgr.c index 23580724286..648352af85a 100644 --- a/reactos/dll/win32/msctf/categorymgr.c +++ b/reactos/dll/win32/msctf/categorymgr.c @@ -168,9 +168,67 @@ static HRESULT WINAPI CategoryMgr_EnumItemsInCategory ( ITfCategoryMgr *iface, static HRESULT WINAPI CategoryMgr_FindClosestCategory ( ITfCategoryMgr *iface, REFGUID rguid, GUID *pcatid, const GUID **ppcatidList, ULONG ulCount) { + static const WCHAR fmt[] = { '%','s','\\','%','s','\\','C','a','t','e','g','o','r','y','\\','I','t','e','m','\\','%','s',0}; + + WCHAR fullkey[110]; + WCHAR buf[39]; + HKEY key; + HRESULT hr = S_FALSE; + INT index = 0; CategoryMgr *This = (CategoryMgr*)iface; - FIXME("STUB:(%p)\n",This); - return E_NOTIMPL; + + TRACE("(%p)\n",This); + + if (!pcatid || (ulCount && ppcatidList == NULL)) + return E_INVALIDARG; + + StringFromGUID2(rguid, buf, 39); + sprintfW(fullkey,fmt,szwSystemTIPKey,buf,buf); + *pcatid = GUID_NULL; + + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, KEY_READ, &key ) != + ERROR_SUCCESS) + return S_FALSE; + + while (1) + { + HRESULT hr2; + ULONG res; + GUID guid; + WCHAR catid[39]; + DWORD cName; + + cName = 39; + res = RegEnumKeyExW(key, index, catid, &cName, NULL, NULL, NULL, NULL); + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break; + index ++; + + hr2 = CLSIDFromString(catid, &guid); + if (FAILED(hr2)) continue; + + if (ulCount) + { + int j; + BOOL found = FALSE; + for (j = 0; j < ulCount; j++) + if (IsEqualGUID(&guid, ppcatidList[j])) + { + found = TRUE; + *pcatid = guid; + hr = S_OK; + break; + } + if (found) break; + } + else + { + *pcatid = guid; + hr = S_OK; + break; + } + } + + return hr; } static HRESULT WINAPI CategoryMgr_RegisterGUIDDescription ( diff --git a/reactos/dll/win32/msctf/inputprocessor.c b/reactos/dll/win32/msctf/inputprocessor.c index de39af977a5..7df55753360 100644 --- a/reactos/dll/win32/msctf/inputprocessor.c +++ b/reactos/dll/win32/msctf/inputprocessor.c @@ -72,6 +72,7 @@ typedef struct tagEnumTfLanguageProfiles { DWORD lang_index; LANGID langid; + ITfCategoryMgr *catmgr; } EnumTfLanguageProfiles; static HRESULT ProfilesEnumGuid_Constructor(IEnumGUID **ppOut); @@ -670,6 +671,7 @@ static void EnumTfLanguageProfiles_Destructor(EnumTfLanguageProfiles *This) RegCloseKey(This->tipkey); if (This->langkey) RegCloseKey(This->langkey); + ITfCategoryMgr_Release(This->catmgr); HeapFree(GetProcessHeap(),0,This); } @@ -746,6 +748,9 @@ static INT next_LanguageProfile(EnumTfLanguageProfiles *This, CLSID clsid, TF_LA if (tflp) { + static const GUID * tipcats[3] = { &GUID_TFCAT_TIP_KEYBOARD, + &GUID_TFCAT_TIP_SPEECH, + &GUID_TFCAT_TIP_HANDWRITING }; res = CLSIDFromString(profileid, &profile); if (FAILED(res)) return 0; @@ -754,7 +759,10 @@ static INT next_LanguageProfile(EnumTfLanguageProfiles *This, CLSID clsid, TF_LA /* FIXME */ tflp->fActive = FALSE; tflp->guidProfile = profile; - /* FIXME set catid */ + if (ITfCategoryMgr_FindClosestCategory(This->catmgr, &clsid, + &tflp->catid, tipcats, 3) != S_OK) + ITfCategoryMgr_FindClosestCategory(This->catmgr, &clsid, + &tflp->catid, NULL, 0); } return 1; @@ -865,6 +873,7 @@ static const IEnumTfLanguageProfilesVtbl IEnumTfLanguageProfiles_Vtbl ={ static HRESULT EnumTfLanguageProfiles_Constructor(LANGID langid, IEnumTfLanguageProfiles **ppOut) { + HRESULT hr; EnumTfLanguageProfiles *This; This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EnumTfLanguageProfiles)); @@ -875,6 +884,13 @@ static HRESULT EnumTfLanguageProfiles_Constructor(LANGID langid, IEnumTfLanguage This->refCount = 1; This->langid = langid; + hr = CategoryMgr_Constructor(NULL,(IUnknown**)&This->catmgr); + if (FAILED(hr)) + { + HeapFree(GetProcessHeap(),0,This); + return hr; + } + if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szwSystemTIPKey, 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &This->tipkey, NULL) != ERROR_SUCCESS) return E_FAIL; diff --git a/reactos/dll/win32/msvcrt20/msvcrt20.spec b/reactos/dll/win32/msvcrt20/msvcrt20.spec index 339cb1c063f..56f961ca3df 100644 --- a/reactos/dll/win32/msvcrt20/msvcrt20.spec +++ b/reactos/dll/win32/msvcrt20/msvcrt20.spec @@ -437,22 +437,22 @@ @ stub ?xsgetn@streambuf@@UAEHPADH@Z # @ stub ?xsputn@streambuf@@UAEHPBDH@Z # @ stub $I10_OUTPUT # -@ cdecl _CIacos() msvcrt._CIacos -@ cdecl _CIasin() msvcrt._CIasin -@ cdecl _CIatan() msvcrt._CIatan -@ cdecl _CIatan2() msvcrt._CIatan2 -@ cdecl _CIcos() msvcrt._CIcos -@ cdecl _CIcosh() msvcrt._CIcosh -@ cdecl _CIexp() msvcrt._CIexp -@ cdecl _CIfmod() msvcrt._CIfmod -@ cdecl _CIlog() msvcrt._CIlog -@ cdecl _CIlog10() msvcrt._CIlog10 -@ cdecl _CIpow() msvcrt._CIpow -@ cdecl _CIsin() msvcrt._CIsin -@ cdecl _CIsinh() msvcrt._CIsinh -@ cdecl _CIsqrt() msvcrt._CIsqrt -@ cdecl _CItan() msvcrt._CItan -@ cdecl _CItanh() msvcrt._CItanh +@ cdecl -arch=i386 _CIacos() msvcrt._CIacos +@ cdecl -arch=i386 _CIasin() msvcrt._CIasin +@ cdecl -arch=i386 _CIatan() msvcrt._CIatan +@ cdecl -arch=i386 _CIatan2() msvcrt._CIatan2 +@ cdecl -arch=i386 _CIcos() msvcrt._CIcos +@ cdecl -arch=i386 _CIcosh() msvcrt._CIcosh +@ cdecl -arch=i386 _CIexp() msvcrt._CIexp +@ cdecl -arch=i386 _CIfmod() msvcrt._CIfmod +@ cdecl -arch=i386 _CIlog() msvcrt._CIlog +@ cdecl -arch=i386 _CIlog10() msvcrt._CIlog10 +@ cdecl -arch=i386 _CIpow() msvcrt._CIpow +@ cdecl -arch=i386 _CIsin() msvcrt._CIsin +@ cdecl -arch=i386 _CIsinh() msvcrt._CIsinh +@ cdecl -arch=i386 _CIsqrt() msvcrt._CIsqrt +@ cdecl -arch=i386 _CItan() msvcrt._CItan +@ cdecl -arch=i386 _CItanh() msvcrt._CItanh @ cdecl _CxxThrowException(long long) msvcrt._CxxThrowException @ extern _HUGE msvcrt._HUGE @ cdecl _XcptFilter(long ptr) msvcrt._XcptFilter @@ -471,32 +471,32 @@ @ cdecl __iscsymf(long) msvcrt.__iscsymf @ cdecl __lconv_init() msvcrt.__lconv_init @ extern __mb_cur_max msvcrt.__mb_cur_max -@ cdecl __p___argc() msvcrt.__p___argc -@ cdecl __p___argv() msvcrt.__p___argv -@ cdecl __p___initenv() msvcrt.__p___initenv -@ cdecl __p___mb_cur_max() msvcrt.__p___mb_cur_max -@ cdecl __p___wargv() msvcrt.__p___wargv -@ cdecl __p___winitenv() msvcrt.__p___winitenv -@ cdecl __p__acmdln() msvcrt.__p__acmdln -@ cdecl __p__amblksiz() msvcrt.__p__amblksiz -@ cdecl __p__commode() msvcrt.__p__commode -@ cdecl __p__daylight() msvcrt.__p__daylight -@ cdecl __p__environ() msvcrt.__p__environ -@ cdecl __p__fmode() msvcrt.__p__fmode -@ cdecl __p__iob() msvcrt.__p__iob -@ cdecl __p__mbctype() msvcrt.__p__mbctype -@ cdecl __p__osver() msvcrt.__p__osver -@ cdecl __p__pctype() msvcrt.__p__pctype -@ cdecl __p__pgmptr() msvcrt.__p__pgmptr -@ cdecl __p__pwctype() msvcrt.__p__pwctype -@ cdecl __p__timezone() msvcrt.__p__timezone -@ cdecl __p__tzname() msvcrt.__p__tzname -@ cdecl __p__wcmdln() msvcrt.__p__wcmdln -@ cdecl __p__wenviron() msvcrt.__p__wenviron -@ cdecl __p__winmajor() msvcrt.__p__winmajor -@ cdecl __p__winminor() msvcrt.__p__winminor -@ cdecl __p__winver() msvcrt.__p__winver -@ cdecl __p__wpgmptr() msvcrt.__p__wpgmptr +@ cdecl -arch=i386 __p___argc() msvcrt.__p___argc +@ cdecl -arch=i386 __p___argv() msvcrt.__p___argv +@ cdecl -arch=i386 __p___initenv() msvcrt.__p___initenv +@ cdecl -arch=i386 __p___mb_cur_max() msvcrt.__p___mb_cur_max +@ cdecl -arch=i386 __p___wargv() msvcrt.__p___wargv +@ cdecl -arch=i386 __p___winitenv() msvcrt.__p___winitenv +@ cdecl -arch=i386 __p__acmdln() msvcrt.__p__acmdln +@ cdecl -arch=i386 __p__amblksiz() msvcrt.__p__amblksiz +@ cdecl -arch=i386 __p__commode() msvcrt.__p__commode +@ cdecl -arch=i386 __p__daylight() msvcrt.__p__daylight +@ cdecl -arch=i386 __p__environ() msvcrt.__p__environ +@ cdecl -arch=i386 __p__fmode() msvcrt.__p__fmode +@ cdecl -arch=i386 __p__iob() msvcrt.__p__iob +@ cdecl -arch=i386 __p__mbctype() msvcrt.__p__mbctype +@ cdecl -arch=i386 __p__osver() msvcrt.__p__osver +@ cdecl -arch=i386 __p__pctype() msvcrt.__p__pctype +@ cdecl -arch=i386 __p__pgmptr() msvcrt.__p__pgmptr +@ cdecl -arch=i386 __p__pwctype() msvcrt.__p__pwctype +@ cdecl -arch=i386 __p__timezone() msvcrt.__p__timezone +@ cdecl -arch=i386 __p__tzname() msvcrt.__p__tzname +@ cdecl -arch=i386 __p__wcmdln() msvcrt.__p__wcmdln +@ cdecl -arch=i386 __p__wenviron() msvcrt.__p__wenviron +@ cdecl -arch=i386 __p__winmajor() msvcrt.__p__winmajor +@ cdecl -arch=i386 __p__winminor() msvcrt.__p__winminor +@ cdecl -arch=i386 __p__winver() msvcrt.__p__winver +@ cdecl -arch=i386 __p__wpgmptr() msvcrt.__p__wpgmptr @ cdecl __pxcptinfoptrs() msvcrt.__pxcptinfoptrs @ cdecl __threadhandle() msvcrt.__threadhandle @ cdecl __threadid() msvcrt.__threadid diff --git a/reactos/dll/win32/msvcrt40/msvcrt40.c b/reactos/dll/win32/msvcrt40/msvcrt40.c index 48e4af0da59..f178ea0bafa 100644 --- a/reactos/dll/win32/msvcrt40/msvcrt40.c +++ b/reactos/dll/win32/msvcrt40/msvcrt40.c @@ -22,9 +22,6 @@ #include "windef.h" #include "winbase.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(msvcrt40); BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved ) { diff --git a/reactos/dll/win32/msvcrt40/msvcrt40.spec b/reactos/dll/win32/msvcrt40/msvcrt40.spec index e46b157d544..fd2559a7a45 100644 --- a/reactos/dll/win32/msvcrt40/msvcrt40.spec +++ b/reactos/dll/win32/msvcrt40/msvcrt40.spec @@ -481,22 +481,22 @@ @ stub ?xsgetn@streambuf@@UAEHPADH@Z @ stub ?xsputn@streambuf@@UAEHPBDH@Z @ cdecl $I10_OUTPUT() msvcrt.$I10_OUTPUT -@ cdecl _CIacos() msvcrt._CIacos -@ cdecl _CIasin() msvcrt._CIasin -@ cdecl _CIatan() msvcrt._CIatan -@ cdecl _CIatan2() msvcrt._CIatan2 -@ cdecl _CIcos() msvcrt._CIcos -@ cdecl _CIcosh() msvcrt._CIcosh -@ cdecl _CIexp() msvcrt._CIexp -@ cdecl _CIfmod() msvcrt._CIfmod -@ cdecl _CIlog() msvcrt._CIlog -@ cdecl _CIlog10() msvcrt._CIlog10 -@ cdecl _CIpow() msvcrt._CIpow -@ cdecl _CIsin() msvcrt._CIsin -@ cdecl _CIsinh() msvcrt._CIsinh -@ cdecl _CIsqrt() msvcrt._CIsqrt -@ cdecl _CItan() msvcrt._CItan -@ cdecl _CItanh() msvcrt._CItanh +@ cdecl -arch=i386 _CIacos() msvcrt._CIacos +@ cdecl -arch=i386 _CIasin() msvcrt._CIasin +@ cdecl -arch=i386 _CIatan() msvcrt._CIatan +@ cdecl -arch=i386 _CIatan2() msvcrt._CIatan2 +@ cdecl -arch=i386 _CIcos() msvcrt._CIcos +@ cdecl -arch=i386 _CIcosh() msvcrt._CIcosh +@ cdecl -arch=i386 _CIexp() msvcrt._CIexp +@ cdecl -arch=i386 _CIfmod() msvcrt._CIfmod +@ cdecl -arch=i386 _CIlog() msvcrt._CIlog +@ cdecl -arch=i386 _CIlog10() msvcrt._CIlog10 +@ cdecl -arch=i386 _CIpow() msvcrt._CIpow +@ cdecl -arch=i386 _CIsin() msvcrt._CIsin +@ cdecl -arch=i386 _CIsinh() msvcrt._CIsinh +@ cdecl -arch=i386 _CIsqrt() msvcrt._CIsqrt +@ cdecl -arch=i386 _CItan() msvcrt._CItan +@ cdecl -arch=i386 _CItanh() msvcrt._CItanh @ cdecl _CxxThrowException(long long) msvcrt._CxxThrowException @ cdecl -i386 _EH_prolog() msvcrt._EH_prolog @ extern _HUGE msvcrt._HUGE @@ -519,33 +519,33 @@ @ cdecl __iscsymf(long) msvcrt.__iscsymf @ cdecl __lconv_init() msvcrt.__lconv_init @ extern __mb_cur_max msvcrt.__mb_cur_max -@ cdecl __p___argc() msvcrt.__p___argc -@ cdecl __p___argv() msvcrt.__p___argv -@ cdecl __p___initenv() msvcrt.__p___initenv -@ cdecl __p___mb_cur_max() msvcrt.__p___mb_cur_max -@ cdecl __p___wargv() msvcrt.__p___wargv -@ cdecl __p___winitenv() msvcrt.__p___winitenv -@ cdecl __p__acmdln() msvcrt.__p__acmdln -@ cdecl __p__amblksiz() msvcrt.__p__amblksiz -@ cdecl __p__commode() msvcrt.__p__commode -@ cdecl __p__daylight() msvcrt.__p__daylight -@ cdecl __p__dstbias() msvcrt.__p__dstbias -@ cdecl __p__environ() msvcrt.__p__environ -@ cdecl __p__fmode() msvcrt.__p__fmode -@ cdecl __p__iob() msvcrt.__p__iob -@ cdecl __p__mbctype() msvcrt.__p__mbctype -@ cdecl __p__osver() msvcrt.__p__osver -@ cdecl __p__pctype() msvcrt.__p__pctype -@ cdecl __p__pgmptr() msvcrt.__p__pgmptr -@ cdecl __p__pwctype() msvcrt.__p__pwctype -@ cdecl __p__timezone() msvcrt.__p__timezone -@ cdecl __p__tzname() msvcrt.__p__tzname -@ cdecl __p__wcmdln() msvcrt.__p__wcmdln -@ cdecl __p__wenviron() msvcrt.__p__wenviron -@ cdecl __p__winmajor() msvcrt.__p__winmajor -@ cdecl __p__winminor() msvcrt.__p__winminor -@ cdecl __p__winver() msvcrt.__p__winver -@ cdecl __p__wpgmptr() msvcrt.__p__wpgmptr +@ cdecl -arch=i386 __p___argc() msvcrt.__p___argc +@ cdecl -arch=i386 __p___argv() msvcrt.__p___argv +@ cdecl -arch=i386 __p___initenv() msvcrt.__p___initenv +@ cdecl -arch=i386 __p___mb_cur_max() msvcrt.__p___mb_cur_max +@ cdecl -arch=i386 __p___wargv() msvcrt.__p___wargv +@ cdecl -arch=i386 __p___winitenv() msvcrt.__p___winitenv +@ cdecl -arch=i386 __p__acmdln() msvcrt.__p__acmdln +@ cdecl -arch=i386 __p__amblksiz() msvcrt.__p__amblksiz +@ cdecl -arch=i386 __p__commode() msvcrt.__p__commode +@ cdecl -arch=i386 __p__daylight() msvcrt.__p__daylight +@ cdecl -arch=i386 __p__dstbias() msvcrt.__p__dstbias +@ cdecl -arch=i386 __p__environ() msvcrt.__p__environ +@ cdecl -arch=i386 __p__fmode() msvcrt.__p__fmode +@ cdecl -arch=i386 __p__iob() msvcrt.__p__iob +@ cdecl -arch=i386 __p__mbctype() msvcrt.__p__mbctype +@ cdecl -arch=i386 __p__osver() msvcrt.__p__osver +@ cdecl -arch=i386 __p__pctype() msvcrt.__p__pctype +@ cdecl -arch=i386 __p__pgmptr() msvcrt.__p__pgmptr +@ cdecl -arch=i386 __p__pwctype() msvcrt.__p__pwctype +@ cdecl -arch=i386 __p__timezone() msvcrt.__p__timezone +@ cdecl -arch=i386 __p__tzname() msvcrt.__p__tzname +@ cdecl -arch=i386 __p__wcmdln() msvcrt.__p__wcmdln +@ cdecl -arch=i386 __p__wenviron() msvcrt.__p__wenviron +@ cdecl -arch=i386 __p__winmajor() msvcrt.__p__winmajor +@ cdecl -arch=i386 __p__winminor() msvcrt.__p__winminor +@ cdecl -arch=i386 __p__winver() msvcrt.__p__winver +@ cdecl -arch=i386 __p__wpgmptr() msvcrt.__p__wpgmptr @ cdecl __pxcptinfoptrs() msvcrt.__pxcptinfoptrs @ cdecl __set_app_type(long) msvcrt.__set_app_type @ cdecl __setusermatherr(ptr) msvcrt.__setusermatherr diff --git a/reactos/dll/win32/msxml3/node.c b/reactos/dll/win32/msxml3/node.c index 7baef30823d..72cc61e4c15 100644 --- a/reactos/dll/win32/msxml3/node.c +++ b/reactos/dll/win32/msxml3/node.c @@ -387,6 +387,11 @@ static HRESULT get_node( if ( !out ) return E_INVALIDARG; + + /* if we dont have a doc, use our parent. */ + if(node && !node->doc && node->parent) + node->doc = node->parent->doc; + *out = create_node( node ); if (!*out) return S_FALSE; diff --git a/reactos/dll/win32/snmpapi/main.c b/reactos/dll/win32/snmpapi/main.c index f8d65150f33..0fabba444b6 100644 --- a/reactos/dll/win32/snmpapi/main.c +++ b/reactos/dll/win32/snmpapi/main.c @@ -19,6 +19,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#include "config.h" + #include #include diff --git a/reactos/dll/win32/urlmon/binding.c b/reactos/dll/win32/urlmon/binding.c index 41fa677bc28..fb30367954a 100644 --- a/reactos/dll/win32/urlmon/binding.c +++ b/reactos/dll/win32/urlmon/binding.c @@ -1200,7 +1200,7 @@ static void report_data(Binding *This, DWORD bscf, ULONG progress, ULONG progres TRACE("(%p)->(%d %u %u)\n", This, bscf, progress, progress_max); - if(This->download_state == END_DOWNLOAD) + if(This->download_state == END_DOWNLOAD || (This->state & BINDING_STOPPED)) return; if(GetCurrentThreadId() != This->apartment_thread) diff --git a/reactos/dll/win32/urlmon/ftp.c b/reactos/dll/win32/urlmon/ftp.c index 7b528adb8e2..dbdd7a7fd37 100644 --- a/reactos/dll/win32/urlmon/ftp.c +++ b/reactos/dll/win32/urlmon/ftp.c @@ -1,5 +1,5 @@ /* - * Copyright 2005 Jacek Caban + * Copyright 2005-2009 Jacek Caban for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -22,13 +22,63 @@ WINE_DEFAULT_DEBUG_CHANNEL(urlmon); typedef struct { + Protocol base; + const IInternetProtocolVtbl *lpInternetProtocolVtbl; + const IInternetPriorityVtbl *lpInternetPriorityVtbl; + LONG ref; } FtpProtocol; -#define PROTOCOL_THIS(iface) DEFINE_THIS(FtpProtocol, InternetProtocol, iface) - #define PROTOCOL(x) ((IInternetProtocol*) &(x)->lpInternetProtocolVtbl) +#define PRIORITY(x) ((IInternetPriority*) &(x)->lpInternetPriorityVtbl) + +#define ASYNCPROTOCOL_THIS(iface) DEFINE_THIS2(FtpProtocol, base, iface) + +static HRESULT FtpProtocol_open_request(Protocol *prot, LPCWSTR url, DWORD request_flags, + IInternetBindInfo *bind_info) +{ + FtpProtocol *This = ASYNCPROTOCOL_THIS(prot); + + This->base.request = InternetOpenUrlW(This->base.internet, url, NULL, 0, + request_flags|INTERNET_FLAG_EXISTING_CONNECT|INTERNET_FLAG_PASSIVE, + (DWORD_PTR)&This->base); + if (!This->base.request && GetLastError() != ERROR_IO_PENDING) { + WARN("InternetOpenUrl failed: %d\n", GetLastError()); + return INET_E_RESOURCE_NOT_FOUND; + } + + return S_OK; +} + +static HRESULT FtpProtocol_start_downloading(Protocol *prot) +{ + FtpProtocol *This = ASYNCPROTOCOL_THIS(prot); + DWORD size; + BOOL res; + + res = FtpGetFileSize(This->base.request, &size); + if(res) + This->base.content_length = size; + else + WARN("FtpGetFileSize failed: %d\n", GetLastError()); + + return S_OK; +} + +static void FtpProtocol_close_connection(Protocol *prot) +{ +} + +#undef ASYNCPROTOCOL_THIS + +static const ProtocolVtbl AsyncProtocolVtbl = { + FtpProtocol_open_request, + FtpProtocol_start_downloading, + FtpProtocol_close_connection +}; + +#define PROTOCOL_THIS(iface) DEFINE_THIS(FtpProtocol, InternetProtocol, iface) static HRESULT WINAPI FtpProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv) { @@ -44,6 +94,9 @@ static HRESULT WINAPI FtpProtocol_QueryInterface(IInternetProtocol *iface, REFII }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) { TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv); *ppv = PROTOCOL(This); + }else if(IsEqualGUID(&IID_IInternetPriority, riid)) { + TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv); + *ppv = PRIORITY(This); } if(*ppv) { @@ -71,6 +124,7 @@ static ULONG WINAPI FtpProtocol_Release(IInternetProtocol *iface) TRACE("(%p) ref=%d\n", This, ref); if(!ref) { + protocol_close_connection(&This->base); heap_free(This); URLMON_UnlockModule(); @@ -84,16 +138,25 @@ static HRESULT WINAPI FtpProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl, DWORD grfPI, DWORD dwReserved) { FtpProtocol *This = PROTOCOL_THIS(iface); - FIXME("(%p)->(%s %p %p %08x %d)\n", This, debugstr_w(szUrl), pOIProtSink, - pOIBindInfo, grfPI, dwReserved); - return E_NOTIMPL; + + static const WCHAR ftpW[] = {'f','t','p',':'}; + + TRACE("(%p)->(%s %p %p %08x %d)\n", This, debugstr_w(szUrl), pOIProtSink, + pOIBindInfo, grfPI, dwReserved); + + if(strncmpW(szUrl, ftpW, sizeof(ftpW)/sizeof(WCHAR))) + return MK_E_SYNTAX; + + return protocol_start(&This->base, PROTOCOL(This), szUrl, pOIProtSink, pOIBindInfo); } static HRESULT WINAPI FtpProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData) { FtpProtocol *This = PROTOCOL_THIS(iface); - FIXME("(%p)->(%p)\n", This, pProtocolData); - return E_NOTIMPL; + + TRACE("(%p)->(%p)\n", This, pProtocolData); + + return protocol_continue(&This->base, pProtocolData); } static HRESULT WINAPI FtpProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason, @@ -107,8 +170,11 @@ static HRESULT WINAPI FtpProtocol_Abort(IInternetProtocol *iface, HRESULT hrReas static HRESULT WINAPI FtpProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions) { FtpProtocol *This = PROTOCOL_THIS(iface); - FIXME("(%p)->(%08x)\n", This, dwOptions); - return E_NOTIMPL; + + TRACE("(%p)->(%08x)\n", This, dwOptions); + + protocol_close_connection(&This->base); + return S_OK; } static HRESULT WINAPI FtpProtocol_Suspend(IInternetProtocol *iface) @@ -129,8 +195,10 @@ static HRESULT WINAPI FtpProtocol_Read(IInternetProtocol *iface, void *pv, ULONG cb, ULONG *pcbRead) { FtpProtocol *This = PROTOCOL_THIS(iface); - FIXME("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead); - return E_NOTIMPL; + + TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead); + + return protocol_read(&This->base, pv, cb, pcbRead); } static HRESULT WINAPI FtpProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove, @@ -144,15 +212,19 @@ static HRESULT WINAPI FtpProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER d static HRESULT WINAPI FtpProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions) { FtpProtocol *This = PROTOCOL_THIS(iface); - FIXME("(%p)->(%08x)\n", This, dwOptions); - return E_NOTIMPL; + + TRACE("(%p)->(%08x)\n", This, dwOptions); + + return protocol_lock_request(&This->base); } static HRESULT WINAPI FtpProtocol_UnlockRequest(IInternetProtocol *iface) { FtpProtocol *This = PROTOCOL_THIS(iface); - FIXME("(%p)\n", This); - return E_NOTIMPL; + + TRACE("(%p)\n", This); + + return protocol_unlock_request(&This->base); } #undef PROTOCOL_THIS @@ -173,6 +245,56 @@ static const IInternetProtocolVtbl FtpProtocolVtbl = { FtpProtocol_UnlockRequest }; +#define PRIORITY_THIS(iface) DEFINE_THIS(FtpProtocol, InternetPriority, iface) + +static HRESULT WINAPI FtpPriority_QueryInterface(IInternetPriority *iface, REFIID riid, void **ppv) +{ + FtpProtocol *This = PRIORITY_THIS(iface); + return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv); +} + +static ULONG WINAPI FtpPriority_AddRef(IInternetPriority *iface) +{ + FtpProtocol *This = PRIORITY_THIS(iface); + return IInternetProtocol_AddRef(PROTOCOL(This)); +} + +static ULONG WINAPI FtpPriority_Release(IInternetPriority *iface) +{ + FtpProtocol *This = PRIORITY_THIS(iface); + return IInternetProtocol_Release(PROTOCOL(This)); +} + +static HRESULT WINAPI FtpPriority_SetPriority(IInternetPriority *iface, LONG nPriority) +{ + FtpProtocol *This = PRIORITY_THIS(iface); + + TRACE("(%p)->(%d)\n", This, nPriority); + + This->base.priority = nPriority; + return S_OK; +} + +static HRESULT WINAPI FtpPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority) +{ + FtpProtocol *This = PRIORITY_THIS(iface); + + TRACE("(%p)->(%p)\n", This, pnPriority); + + *pnPriority = This->base.priority; + return S_OK; +} + +#undef PRIORITY_THIS + +static const IInternetPriorityVtbl FtpPriorityVtbl = { + FtpPriority_QueryInterface, + FtpPriority_AddRef, + FtpPriority_Release, + FtpPriority_SetPriority, + FtpPriority_GetPriority +}; + HRESULT FtpProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) { FtpProtocol *ret; @@ -181,9 +303,11 @@ HRESULT FtpProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) URLMON_LockModule(); - ret = heap_alloc(sizeof(FtpProtocol)); + ret = heap_alloc_zero(sizeof(FtpProtocol)); + ret->base.vtbl = &AsyncProtocolVtbl; ret->lpInternetProtocolVtbl = &FtpProtocolVtbl; + ret->lpInternetPriorityVtbl = &FtpPriorityVtbl; ret->ref = 1; *ppobj = PROTOCOL(ret); diff --git a/reactos/dll/win32/urlmon/http.c b/reactos/dll/win32/urlmon/http.c index 9bb4ffafb91..80eefbed204 100644 --- a/reactos/dll/win32/urlmon/http.c +++ b/reactos/dll/win32/urlmon/http.c @@ -29,215 +29,283 @@ WINE_DEFAULT_DEBUG_CHANNEL(urlmon); -/* Flags are needed for, among other things, return HRESULTs from the Read function - * to conform to native. For example, Read returns: - * - * 1. E_PENDING if called before the request has completed, - * (flags = 0) - * 2. S_FALSE after all data has been read and S_OK has been reported, - * (flags = FLAG_REQUEST_COMPLETE | FLAG_ALL_DATA_READ | FLAG_RESULT_REPORTED) - * 3. INET_E_DATA_NOT_AVAILABLE if InternetQueryDataAvailable fails. The first time - * this occurs, INET_E_DATA_NOT_AVAILABLE will also be reported to the sink, - * (flags = FLAG_REQUEST_COMPLETE) - * but upon subsequent calls to Read no reporting will take place, yet - * InternetQueryDataAvailable will still be called, and, on failure, - * INET_E_DATA_NOT_AVAILABLE will still be returned. - * (flags = FLAG_REQUEST_COMPLETE | FLAG_RESULT_REPORTED) - * - * FLAG_FIRST_DATA_REPORTED and FLAG_LAST_DATA_REPORTED are needed for proper - * ReportData reporting. For example, if OnResponse returns S_OK, Continue will - * report BSCF_FIRSTDATANOTIFICATION, and when all data has been read Read will - * report BSCF_INTERMEDIATEDATANOTIFICATION|BSCF_LASTDATANOTIFICATION. However, - * if OnResponse does not return S_OK, Continue will not report data, and Read - * will report BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION when all - * data has been read. - */ -#define FLAG_REQUEST_COMPLETE 0x1 -#define FLAG_FIRST_CONTINUE_COMPLETE 0x2 -#define FLAG_FIRST_DATA_REPORTED 0x4 -#define FLAG_ALL_DATA_READ 0x8 -#define FLAG_LAST_DATA_REPORTED 0x10 -#define FLAG_RESULT_REPORTED 0x20 - typedef struct { + Protocol base; + const IInternetProtocolVtbl *lpInternetProtocolVtbl; const IInternetPriorityVtbl *lpInternetPriorityVtbl; BOOL https; - DWORD flags, grfBINDF; - BINDINFO bind_info; - IInternetProtocolSink *protocol_sink; IHttpNegotiate *http_negotiate; - HINTERNET internet, connect, request; LPWSTR full_header; - HANDLE lock; - ULONG current_position, content_length, available_bytes; - LONG priority; LONG ref; } HttpProtocol; +#define PROTOCOL(x) ((IInternetProtocol*) &(x)->lpInternetProtocolVtbl) +#define PRIORITY(x) ((IInternetPriority*) &(x)->lpInternetPriorityVtbl) + /* Default headers from native */ static const WCHAR wszHeaders[] = {'A','c','c','e','p','t','-','E','n','c','o','d','i','n','g', ':',' ','g','z','i','p',',',' ','d','e','f','l','a','t','e',0}; -/* - * Helpers - */ - -static void HTTPPROTOCOL_ReportResult(HttpProtocol *This, HRESULT hres) -{ - if (!(This->flags & FLAG_RESULT_REPORTED) && - This->protocol_sink) - { - This->flags |= FLAG_RESULT_REPORTED; - IInternetProtocolSink_ReportResult(This->protocol_sink, hres, 0, NULL); - } -} - -static void HTTPPROTOCOL_ReportData(HttpProtocol *This) -{ - DWORD bscf; - if (!(This->flags & FLAG_LAST_DATA_REPORTED) && - This->protocol_sink) - { - if (This->flags & FLAG_FIRST_DATA_REPORTED) - { - bscf = BSCF_INTERMEDIATEDATANOTIFICATION; - } - else - { - This->flags |= FLAG_FIRST_DATA_REPORTED; - bscf = BSCF_FIRSTDATANOTIFICATION; - } - if (This->flags & FLAG_ALL_DATA_READ && - !(This->flags & FLAG_LAST_DATA_REPORTED)) - { - This->flags |= FLAG_LAST_DATA_REPORTED; - bscf |= BSCF_LASTDATANOTIFICATION; - } - IInternetProtocolSink_ReportData(This->protocol_sink, bscf, - This->current_position+This->available_bytes, - This->content_length); - } -} - -static void HTTPPROTOCOL_AllDataRead(HttpProtocol *This) -{ - if (!(This->flags & FLAG_ALL_DATA_READ)) - This->flags |= FLAG_ALL_DATA_READ; - HTTPPROTOCOL_ReportData(This); - HTTPPROTOCOL_ReportResult(This, S_OK); -} - -static void HTTPPROTOCOL_Close(HttpProtocol *This) -{ - if (This->http_negotiate) - { - IHttpNegotiate_Release(This->http_negotiate); - This->http_negotiate = 0; - } - if (This->request) - InternetCloseHandle(This->request); - if (This->connect) - InternetCloseHandle(This->connect); - if (This->internet) - { - InternetCloseHandle(This->internet); - This->internet = 0; - } - if (This->full_header) - { - if (This->full_header != wszHeaders) - heap_free(This->full_header); - This->full_header = 0; - } - This->flags = 0; -} - -static void CALLBACK HTTPPROTOCOL_InternetStatusCallback( - HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, - LPVOID lpvStatusInformation, DWORD dwStatusInformationLength) -{ - HttpProtocol *This = (HttpProtocol *)dwContext; - PROTOCOLDATA data; - ULONG ulStatusCode; - - switch (dwInternetStatus) - { - case INTERNET_STATUS_RESOLVING_NAME: - ulStatusCode = BINDSTATUS_FINDINGRESOURCE; - break; - case INTERNET_STATUS_CONNECTING_TO_SERVER: - ulStatusCode = BINDSTATUS_CONNECTING; - break; - case INTERNET_STATUS_SENDING_REQUEST: - ulStatusCode = BINDSTATUS_SENDINGREQUEST; - break; - case INTERNET_STATUS_REQUEST_COMPLETE: - This->flags |= FLAG_REQUEST_COMPLETE; - /* PROTOCOLDATA same as native */ - memset(&data, 0, sizeof(data)); - data.dwState = 0xf1000000; - if (This->flags & FLAG_FIRST_CONTINUE_COMPLETE) - data.pData = (LPVOID)BINDSTATUS_ENDDOWNLOADCOMPONENTS; - else - data.pData = (LPVOID)BINDSTATUS_DOWNLOADINGDATA; - if (This->grfBINDF & BINDF_FROMURLMON) - IInternetProtocolSink_Switch(This->protocol_sink, &data); - else - IInternetProtocol_Continue((IInternetProtocol *)This, &data); - return; - case INTERNET_STATUS_HANDLE_CREATED: - IInternetProtocol_AddRef((IInternetProtocol *)This); - return; - case INTERNET_STATUS_HANDLE_CLOSING: - if (*(HINTERNET *)lpvStatusInformation == This->connect) - { - This->connect = 0; - } - else if (*(HINTERNET *)lpvStatusInformation == This->request) - { - This->request = 0; - if (This->protocol_sink) - { - IInternetProtocolSink_Release(This->protocol_sink); - This->protocol_sink = 0; - } - if (This->bind_info.cbSize) - { - ReleaseBindInfo(&This->bind_info); - memset(&This->bind_info, 0, sizeof(This->bind_info)); - } - } - IInternetProtocol_Release((IInternetProtocol *)This); - return; - default: - WARN("Unhandled Internet status callback %d\n", dwInternetStatus); - return; - } - - IInternetProtocolSink_ReportProgress(This->protocol_sink, ulStatusCode, (LPWSTR)lpvStatusInformation); -} - -static inline LPWSTR strndupW(LPCWSTR string, int len) +static LPWSTR query_http_info(HttpProtocol *This, DWORD option) { LPWSTR ret = NULL; - if (string && - (ret = heap_alloc((len+1)*sizeof(WCHAR))) != NULL) - { - memcpy(ret, string, len*sizeof(WCHAR)); - ret[len] = 0; + DWORD len = 0; + BOOL res; + + res = HttpQueryInfoW(This->base.request, option, NULL, &len, NULL); + if (!res && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + ret = heap_alloc(len); + res = HttpQueryInfoW(This->base.request, option, ret, &len, NULL); } + if(!res) { + TRACE("HttpQueryInfoW(%d) failed: %08x\n", option, GetLastError()); + heap_free(ret); + return NULL; + } + return ret; } -/* - * Interface implementations - */ +#define ASYNCPROTOCOL_THIS(iface) DEFINE_THIS2(HttpProtocol, base, iface) -#define PROTOCOL(x) ((IInternetProtocol*) &(x)->lpInternetProtocolVtbl) -#define PRIORITY(x) ((IInternetPriority*) &(x)->lpInternetPriorityVtbl) +static HRESULT HttpProtocol_open_request(Protocol *prot, LPCWSTR url, DWORD request_flags, + IInternetBindInfo *bind_info) +{ + HttpProtocol *This = ASYNCPROTOCOL_THIS(prot); + LPWSTR addl_header = NULL, post_cookie = NULL, optional = NULL; + IServiceProvider *service_provider = NULL; + IHttpNegotiate2 *http_negotiate2 = NULL; + LPWSTR host, user, pass, path; + LPOLESTR accept_mimes[257]; + URL_COMPONENTSW url_comp; + BYTE security_id[512]; + DWORD len = 0; + ULONG num = 0; + BOOL res; + HRESULT hres; + + static const WCHAR wszBindVerb[BINDVERB_CUSTOM][5] = + {{'G','E','T',0}, + {'P','O','S','T',0}, + {'P','U','T',0}}; + + memset(&url_comp, 0, sizeof(url_comp)); + url_comp.dwStructSize = sizeof(url_comp); + url_comp.dwSchemeLength = url_comp.dwHostNameLength = url_comp.dwUrlPathLength = + url_comp.dwUserNameLength = url_comp.dwPasswordLength = 1; + if (!InternetCrackUrlW(url, 0, 0, &url_comp)) + return MK_E_SYNTAX; + + if(!url_comp.nPort) + url_comp.nPort = This->https ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT; + + host = heap_strndupW(url_comp.lpszHostName, url_comp.dwHostNameLength); + user = heap_strndupW(url_comp.lpszUserName, url_comp.dwUserNameLength); + pass = heap_strndupW(url_comp.lpszPassword, url_comp.dwPasswordLength); + This->base.connection = InternetConnectW(This->base.internet, host, url_comp.nPort, user, pass, + INTERNET_SERVICE_HTTP, This->https ? INTERNET_FLAG_SECURE : 0, (DWORD_PTR)&This->base); + heap_free(pass); + heap_free(user); + heap_free(host); + if(!This->base.connection) { + WARN("InternetConnect failed: %d\n", GetLastError()); + return INET_E_CANNOT_CONNECT; + } + + num = sizeof(accept_mimes)/sizeof(accept_mimes[0])-1; + hres = IInternetBindInfo_GetBindString(bind_info, BINDSTRING_ACCEPT_MIMES, accept_mimes, num, &num); + if(hres != S_OK) { + WARN("GetBindString BINDSTRING_ACCEPT_MIMES failed: %08x\n", hres); + return INET_E_NO_VALID_MEDIA; + } + accept_mimes[num] = 0; + + path = heap_strndupW(url_comp.lpszUrlPath, url_comp.dwUrlPathLength); + if(This->https) + request_flags |= INTERNET_FLAG_SECURE; + This->base.request = HttpOpenRequestW(This->base.connection, + This->base.bind_info.dwBindVerb < BINDVERB_CUSTOM + ? wszBindVerb[This->base.bind_info.dwBindVerb] : This->base.bind_info.szCustomVerb, + path, NULL, NULL, (LPCWSTR *)accept_mimes, request_flags, (DWORD_PTR)&This->base); + heap_free(path); + while (numbase.request) { + WARN("HttpOpenRequest failed: %d\n", GetLastError()); + return INET_E_RESOURCE_NOT_FOUND; + } + + hres = IInternetProtocolSink_QueryInterface(This->base.protocol_sink, &IID_IServiceProvider, + (void **)&service_provider); + if (hres != S_OK) { + WARN("IInternetProtocolSink_QueryInterface IID_IServiceProvider failed: %08x\n", hres); + return hres; + } + + hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate, + &IID_IHttpNegotiate, (void **)&This->http_negotiate); + if (hres != S_OK) { + WARN("IServiceProvider_QueryService IID_IHttpNegotiate failed: %08x\n", hres); + return hres; + } + + hres = IHttpNegotiate_BeginningTransaction(This->http_negotiate, url, wszHeaders, + 0, &addl_header); + if(hres != S_OK) { + WARN("IHttpNegotiate_BeginningTransaction failed: %08x\n", hres); + IServiceProvider_Release(service_provider); + return hres; + } + + if(addl_header) { + int len_addl_header = strlenW(addl_header); + + This->full_header = heap_alloc(len_addl_header*sizeof(WCHAR)+sizeof(wszHeaders)); + + lstrcpyW(This->full_header, addl_header); + lstrcpyW(&This->full_header[len_addl_header], wszHeaders); + CoTaskMemFree(addl_header); + }else { + This->full_header = (LPWSTR)wszHeaders; + } + + hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate2, + &IID_IHttpNegotiate2, (void **)&http_negotiate2); + IServiceProvider_Release(service_provider); + if(hres != S_OK) { + WARN("IServiceProvider_QueryService IID_IHttpNegotiate2 failed: %08x\n", hres); + /* No goto done as per native */ + }else { + len = sizeof(security_id)/sizeof(security_id[0]); + hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, security_id, &len, 0); + IHttpNegotiate2_Release(http_negotiate2); + if (hres != S_OK) + WARN("IHttpNegotiate2_GetRootSecurityId failed: %08x\n", hres); + } + + /* FIXME: Handle security_id. Native calls undocumented function IsHostInProxyBypassList. */ + + if(This->base.bind_info.dwBindVerb == BINDVERB_POST) { + num = 0; + hres = IInternetBindInfo_GetBindString(bind_info, BINDSTRING_POST_COOKIE, &post_cookie, 1, &num); + if(hres == S_OK && num) { + if(!InternetSetOptionW(This->base.request, INTERNET_OPTION_SECONDARY_CACHE_KEY, + post_cookie, lstrlenW(post_cookie))) + WARN("InternetSetOption INTERNET_OPTION_SECONDARY_CACHE_KEY failed: %d\n", GetLastError()); + CoTaskMemFree(post_cookie); + } + } + + if(This->base.bind_info.dwBindVerb != BINDVERB_GET) { + /* Native does not use GlobalLock/GlobalUnlock, so we won't either */ + if (This->base.bind_info.stgmedData.tymed != TYMED_HGLOBAL) + WARN("Expected This->base.bind_info.stgmedData.tymed to be TYMED_HGLOBAL, not %d\n", + This->base.bind_info.stgmedData.tymed); + else + optional = (LPWSTR)This->base.bind_info.stgmedData.u.hGlobal; + } + + res = HttpSendRequestW(This->base.request, This->full_header, lstrlenW(This->full_header), + optional, optional ? This->base.bind_info.cbstgmedData : 0); + if(!res && GetLastError() != ERROR_IO_PENDING) { + WARN("HttpSendRequest failed: %d\n", GetLastError()); + return INET_E_DOWNLOAD_FAILURE; + } + + return S_OK; +} + +static HRESULT HttpProtocol_start_downloading(Protocol *prot) +{ + HttpProtocol *This = ASYNCPROTOCOL_THIS(prot); + LPWSTR content_type = 0, content_length = 0; + DWORD len = sizeof(DWORD); + DWORD status_code; + BOOL res; + HRESULT hres; + + static const WCHAR wszDefaultContentType[] = + {'t','e','x','t','/','h','t','m','l',0}; + + if(!This->http_negotiate) { + WARN("Expected IHttpNegotiate pointer to be non-NULL\n"); + return S_OK; + } + + res = HttpQueryInfoW(This->base.request, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, + &status_code, &len, NULL); + if(res) { + LPWSTR response_headers = query_http_info(This, HTTP_QUERY_RAW_HEADERS_CRLF); + if(response_headers) { + hres = IHttpNegotiate_OnResponse(This->http_negotiate, status_code, response_headers, + NULL, NULL); + heap_free(response_headers); + if (hres != S_OK) { + WARN("IHttpNegotiate_OnResponse failed: %08x\n", hres); + return S_OK; + } + } + }else { + WARN("HttpQueryInfo failed: %d\n", GetLastError()); + } + + if(This->https) + IInternetProtocolSink_ReportProgress(This->base.protocol_sink, BINDSTATUS_ACCEPTRANGES, NULL); + + content_type = query_http_info(This, HTTP_QUERY_CONTENT_TYPE); + if(content_type) { + /* remove the charset, if present */ + LPWSTR p = strchrW(content_type, ';'); + if (p) *p = '\0'; + + IInternetProtocolSink_ReportProgress(This->base.protocol_sink, + (This->base.bindf & BINDF_FROMURLMON) + ? BINDSTATUS_MIMETYPEAVAILABLE : BINDSTATUS_RAWMIMETYPE, + content_type); + heap_free(content_type); + }else { + WARN("HttpQueryInfo failed: %d\n", GetLastError()); + IInternetProtocolSink_ReportProgress(This->base.protocol_sink, + (This->base.bindf & BINDF_FROMURLMON) + ? BINDSTATUS_MIMETYPEAVAILABLE : BINDSTATUS_RAWMIMETYPE, + wszDefaultContentType); + } + + content_length = query_http_info(This, HTTP_QUERY_CONTENT_LENGTH); + if(content_length) { + This->base.content_length = atoiW(content_length); + heap_free(content_length); + } + + return S_OK; +} + +static void HttpProtocol_close_connection(Protocol *prot) +{ + HttpProtocol *This = ASYNCPROTOCOL_THIS(prot); + + if(This->http_negotiate) { + IHttpNegotiate_Release(This->http_negotiate); + This->http_negotiate = 0; + } + + if(This->full_header) { + if(This->full_header != wszHeaders) + heap_free(This->full_header); + This->full_header = 0; + } +} + +#undef ASYNCPROTOCOL_THIS + +static const ProtocolVtbl AsyncProtocolVtbl = { + HttpProtocol_open_request, + HttpProtocol_start_downloading, + HttpProtocol_close_connection +}; #define PROTOCOL_THIS(iface) DEFINE_THIS(HttpProtocol, InternetProtocol, iface) @@ -285,7 +353,7 @@ static ULONG WINAPI HttpProtocol_Release(IInternetProtocol *iface) TRACE("(%p) ref=%d\n", This, ref); if(!ref) { - HTTPPROTOCOL_Close(This); + protocol_close_connection(&This->base); heap_free(This); URLMON_UnlockModule(); @@ -299,422 +367,28 @@ static HRESULT WINAPI HttpProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl DWORD grfPI, DWORD dwReserved) { HttpProtocol *This = PROTOCOL_THIS(iface); - URL_COMPONENTSW url; - DWORD len = 0, request_flags = INTERNET_FLAG_KEEP_CONNECTION; - ULONG num = 0; - IServiceProvider *service_provider = 0; - IHttpNegotiate2 *http_negotiate2 = 0; - LPWSTR host = 0, path = 0, user = 0, pass = 0, addl_header = 0, - post_cookie = 0, optional = 0; - BYTE security_id[512]; - LPOLESTR user_agent = NULL, accept_mimes[257]; - HRESULT hres; static const WCHAR httpW[] = {'h','t','t','p',':'}; static const WCHAR httpsW[] = {'h','t','t','p','s',':'}; - static const WCHAR wszBindVerb[BINDVERB_CUSTOM][5] = - {{'G','E','T',0}, - {'P','O','S','T',0}, - {'P','U','T',0}}; TRACE("(%p)->(%s %p %p %08x %d)\n", This, debugstr_w(szUrl), pOIProtSink, pOIBindInfo, grfPI, dwReserved); - IInternetProtocolSink_AddRef(pOIProtSink); - This->protocol_sink = pOIProtSink; - - memset(&This->bind_info, 0, sizeof(This->bind_info)); - This->bind_info.cbSize = sizeof(BINDINFO); - hres = IInternetBindInfo_GetBindInfo(pOIBindInfo, &This->grfBINDF, &This->bind_info); - if (hres != S_OK) - { - WARN("GetBindInfo failed: %08x\n", hres); - goto done; - } - if(This->https ? strncmpW(szUrl, httpsW, sizeof(httpsW)/sizeof(WCHAR)) : strncmpW(szUrl, httpW, sizeof(httpW)/sizeof(WCHAR))) - { - hres = MK_E_SYNTAX; - goto done; - } + return MK_E_SYNTAX; - memset(&url, 0, sizeof(url)); - url.dwStructSize = sizeof(url); - url.dwSchemeLength = url.dwHostNameLength = url.dwUrlPathLength = url.dwUserNameLength = - url.dwPasswordLength = 1; - if (!InternetCrackUrlW(szUrl, 0, 0, &url)) - { - hres = MK_E_SYNTAX; - goto done; - } - host = strndupW(url.lpszHostName, url.dwHostNameLength); - path = strndupW(url.lpszUrlPath, url.dwUrlPathLength); - user = strndupW(url.lpszUserName, url.dwUserNameLength); - pass = strndupW(url.lpszPassword, url.dwPasswordLength); - if (!url.nPort) - url.nPort = This->https ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT; - - if(!(This->grfBINDF & BINDF_FROMURLMON)) - IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_DIRECTBIND, NULL); - - hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_USER_AGENT, &user_agent, - 1, &num); - if (hres != S_OK || !num) - { - CHAR null_char = 0; - LPSTR user_agenta = NULL; - len = 0; - if ((hres = ObtainUserAgentString(0, &null_char, &len)) != E_OUTOFMEMORY) - { - WARN("ObtainUserAgentString failed: %08x\n", hres); - } - else if (!(user_agenta = heap_alloc(len*sizeof(CHAR)))) - { - WARN("Out of memory\n"); - } - else if ((hres = ObtainUserAgentString(0, user_agenta, &len)) != S_OK) - { - WARN("ObtainUserAgentString failed: %08x\n", hres); - } - else - { - if (!(user_agent = CoTaskMemAlloc((len)*sizeof(WCHAR)))) - WARN("Out of memory\n"); - else - MultiByteToWideChar(CP_ACP, 0, user_agenta, -1, user_agent, len); - } - heap_free(user_agenta); - } - - This->internet = InternetOpenW(user_agent, 0, NULL, NULL, INTERNET_FLAG_ASYNC); - if (!This->internet) - { - WARN("InternetOpen failed: %d\n", GetLastError()); - hres = INET_E_NO_SESSION; - goto done; - } - - /* Native does not check for success of next call, so we won't either */ - InternetSetStatusCallbackW(This->internet, HTTPPROTOCOL_InternetStatusCallback); - - This->connect = InternetConnectW(This->internet, host, url.nPort, user, - pass, INTERNET_SERVICE_HTTP, - This->https ? INTERNET_FLAG_SECURE : 0, - (DWORD_PTR)This); - if (!This->connect) - { - WARN("InternetConnect failed: %d\n", GetLastError()); - hres = INET_E_CANNOT_CONNECT; - goto done; - } - - num = sizeof(accept_mimes)/sizeof(accept_mimes[0])-1; - hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_ACCEPT_MIMES, - accept_mimes, - num, &num); - if (hres != S_OK) - { - WARN("GetBindString BINDSTRING_ACCEPT_MIMES failed: %08x\n", hres); - hres = INET_E_NO_VALID_MEDIA; - goto done; - } - accept_mimes[num] = 0; - - if (This->grfBINDF & BINDF_NOWRITECACHE) - request_flags |= INTERNET_FLAG_NO_CACHE_WRITE; - if (This->grfBINDF & BINDF_NEEDFILE) - request_flags |= INTERNET_FLAG_NEED_FILE; - if (This->https) - request_flags |= INTERNET_FLAG_SECURE; - This->request = HttpOpenRequestW(This->connect, This->bind_info.dwBindVerb < BINDVERB_CUSTOM ? - wszBindVerb[This->bind_info.dwBindVerb] : - This->bind_info.szCustomVerb, - path, NULL, NULL, (LPCWSTR *)accept_mimes, - request_flags, (DWORD_PTR)This); - if (!This->request) - { - WARN("HttpOpenRequest failed: %d\n", GetLastError()); - hres = INET_E_RESOURCE_NOT_FOUND; - goto done; - } - - hres = IInternetProtocolSink_QueryInterface(This->protocol_sink, &IID_IServiceProvider, - (void **)&service_provider); - if (hres != S_OK) - { - WARN("IInternetProtocolSink_QueryInterface IID_IServiceProvider failed: %08x\n", hres); - goto done; - } - - hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate, - &IID_IHttpNegotiate, (void **)&This->http_negotiate); - if (hres != S_OK) - { - WARN("IServiceProvider_QueryService IID_IHttpNegotiate failed: %08x\n", hres); - goto done; - } - - hres = IHttpNegotiate_BeginningTransaction(This->http_negotiate, szUrl, wszHeaders, - 0, &addl_header); - if (hres != S_OK) - { - WARN("IHttpNegotiate_BeginningTransaction failed: %08x\n", hres); - goto done; - } - else if (addl_header == NULL) - { - This->full_header = (LPWSTR)wszHeaders; - } - else - { - int len_addl_header = lstrlenW(addl_header); - This->full_header = heap_alloc(len_addl_header*sizeof(WCHAR)+sizeof(wszHeaders)); - if (!This->full_header) - { - WARN("Out of memory\n"); - hres = E_OUTOFMEMORY; - goto done; - } - lstrcpyW(This->full_header, addl_header); - lstrcpyW(&This->full_header[len_addl_header], wszHeaders); - } - - hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate2, - &IID_IHttpNegotiate2, (void **)&http_negotiate2); - if (hres != S_OK) - { - WARN("IServiceProvider_QueryService IID_IHttpNegotiate2 failed: %08x\n", hres); - /* No goto done as per native */ - } - else - { - len = sizeof(security_id)/sizeof(security_id[0]); - hres = IHttpNegotiate2_GetRootSecurityId(http_negotiate2, security_id, &len, 0); - if (hres != S_OK) - { - WARN("IHttpNegotiate2_GetRootSecurityId failed: %08x\n", hres); - /* No goto done as per native */ - } - } - - /* FIXME: Handle security_id. Native calls undocumented function IsHostInProxyBypassList. */ - - if (This->bind_info.dwBindVerb == BINDVERB_POST) - { - num = 0; - hres = IInternetBindInfo_GetBindString(pOIBindInfo, BINDSTRING_POST_COOKIE, &post_cookie, - 1, &num); - if (hres == S_OK && num && - !InternetSetOptionW(This->request, INTERNET_OPTION_SECONDARY_CACHE_KEY, - post_cookie, lstrlenW(post_cookie))) - { - WARN("InternetSetOption INTERNET_OPTION_SECONDARY_CACHE_KEY failed: %d\n", - GetLastError()); - } - } - - if (This->bind_info.dwBindVerb != BINDVERB_GET) - { - /* Native does not use GlobalLock/GlobalUnlock, so we won't either */ - if (This->bind_info.stgmedData.tymed != TYMED_HGLOBAL) - WARN("Expected This->bind_info.stgmedData.tymed to be TYMED_HGLOBAL, not %d\n", - This->bind_info.stgmedData.tymed); - else - optional = (LPWSTR)This->bind_info.stgmedData.u.hGlobal; - } - if (!HttpSendRequestW(This->request, This->full_header, lstrlenW(This->full_header), - optional, - optional ? This->bind_info.cbstgmedData : 0) && - GetLastError() != ERROR_IO_PENDING) - { - WARN("HttpSendRequest failed: %d\n", GetLastError()); - hres = INET_E_DOWNLOAD_FAILURE; - goto done; - } - - hres = S_OK; -done: - if (hres != S_OK) - { - IInternetProtocolSink_ReportResult(This->protocol_sink, hres, 0, NULL); - HTTPPROTOCOL_Close(This); - } - - CoTaskMemFree(post_cookie); - CoTaskMemFree(addl_header); - if (http_negotiate2) - IHttpNegotiate2_Release(http_negotiate2); - if (service_provider) - IServiceProvider_Release(service_provider); - - while (numbase, PROTOCOL(This), szUrl, pOIProtSink, pOIBindInfo); } static HRESULT WINAPI HttpProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData) { HttpProtocol *This = PROTOCOL_THIS(iface); - DWORD len = sizeof(DWORD), status_code; - LPWSTR response_headers = 0, content_type = 0, content_length = 0; - - static const WCHAR wszDefaultContentType[] = - {'t','e','x','t','/','h','t','m','l',0}; TRACE("(%p)->(%p)\n", This, pProtocolData); - if (!pProtocolData) - { - WARN("Expected pProtocolData to be non-NULL\n"); - return S_OK; - } - else if (!This->request) - { - WARN("Expected request to be non-NULL\n"); - return S_OK; - } - else if (!This->http_negotiate) - { - WARN("Expected IHttpNegotiate pointer to be non-NULL\n"); - return S_OK; - } - else if (!This->protocol_sink) - { - WARN("Expected IInternetProtocolSink pointer to be non-NULL\n"); - return S_OK; - } - - if (pProtocolData->pData == (LPVOID)BINDSTATUS_DOWNLOADINGDATA) - { - if (!HttpQueryInfoW(This->request, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, - &status_code, &len, NULL)) - { - WARN("HttpQueryInfo failed: %d\n", GetLastError()); - } - else - { - len = 0; - if ((!HttpQueryInfoW(This->request, HTTP_QUERY_RAW_HEADERS_CRLF, response_headers, &len, - NULL) && - GetLastError() != ERROR_INSUFFICIENT_BUFFER) || - !(response_headers = heap_alloc(len)) || - !HttpQueryInfoW(This->request, HTTP_QUERY_RAW_HEADERS_CRLF, response_headers, &len, - NULL)) - { - WARN("HttpQueryInfo failed: %d\n", GetLastError()); - } - else - { - HRESULT hres = IHttpNegotiate_OnResponse(This->http_negotiate, status_code, - response_headers, NULL, NULL); - if (hres != S_OK) - { - WARN("IHttpNegotiate_OnResponse failed: %08x\n", hres); - goto done; - } - } - } - - if(This->https) - IInternetProtocolSink_ReportProgress(This->protocol_sink, BINDSTATUS_ACCEPTRANGES, NULL); - - len = 0; - if ((!HttpQueryInfoW(This->request, HTTP_QUERY_CONTENT_TYPE, content_type, &len, NULL) && - GetLastError() != ERROR_INSUFFICIENT_BUFFER) || - !(content_type = heap_alloc(len)) || - !HttpQueryInfoW(This->request, HTTP_QUERY_CONTENT_TYPE, content_type, &len, NULL)) - { - WARN("HttpQueryInfo failed: %d\n", GetLastError()); - IInternetProtocolSink_ReportProgress(This->protocol_sink, - (This->grfBINDF & BINDF_FROMURLMON) ? - BINDSTATUS_MIMETYPEAVAILABLE : - BINDSTATUS_RAWMIMETYPE, - wszDefaultContentType); - } - else - { - /* remove the charset, if present */ - LPWSTR p = strchrW(content_type, ';'); - if (p) *p = '\0'; - - IInternetProtocolSink_ReportProgress(This->protocol_sink, - (This->grfBINDF & BINDF_FROMURLMON) ? - BINDSTATUS_MIMETYPEAVAILABLE : - BINDSTATUS_RAWMIMETYPE, - content_type); - } - - len = 0; - if ((!HttpQueryInfoW(This->request, HTTP_QUERY_CONTENT_LENGTH, content_length, &len, NULL) && - GetLastError() != ERROR_INSUFFICIENT_BUFFER) || - !(content_length = heap_alloc(len)) || - !HttpQueryInfoW(This->request, HTTP_QUERY_CONTENT_LENGTH, content_length, &len, NULL)) - { - WARN("HttpQueryInfo failed: %d\n", GetLastError()); - This->content_length = 0; - } - else - { - This->content_length = atoiW(content_length); - } - - if(This->grfBINDF & BINDF_NEEDFILE) { - WCHAR cache_file[MAX_PATH]; - DWORD buflen = sizeof(cache_file); - - if(InternetQueryOptionW(This->request, INTERNET_OPTION_DATAFILE_NAME, - cache_file, &buflen)) - { - IInternetProtocolSink_ReportProgress(This->protocol_sink, - BINDSTATUS_CACHEFILENAMEAVAILABLE, - cache_file); - }else { - FIXME("Could not get cache file\n"); - } - } - - This->flags |= FLAG_FIRST_CONTINUE_COMPLETE; - } - - if (pProtocolData->pData >= (LPVOID)BINDSTATUS_DOWNLOADINGDATA) - { - /* InternetQueryDataAvailable may immediately fork and perform its asynchronous - * read, so clear the flag _before_ calling so it does not incorrectly get cleared - * after the status callback is called */ - This->flags &= ~FLAG_REQUEST_COMPLETE; - if (!InternetQueryDataAvailable(This->request, &This->available_bytes, 0, 0)) - { - if (GetLastError() != ERROR_IO_PENDING) - { - This->flags |= FLAG_REQUEST_COMPLETE; - WARN("InternetQueryDataAvailable failed: %d\n", GetLastError()); - HTTPPROTOCOL_ReportResult(This, INET_E_DATA_NOT_AVAILABLE); - } - } - else - { - This->flags |= FLAG_REQUEST_COMPLETE; - HTTPPROTOCOL_ReportData(This); - } - } - -done: - heap_free(response_headers); - heap_free(content_type); - heap_free(content_length); - - /* Returns S_OK on native */ - return S_OK; + return protocol_continue(&This->base, pProtocolData); } static HRESULT WINAPI HttpProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason, @@ -730,8 +404,8 @@ static HRESULT WINAPI HttpProtocol_Terminate(IInternetProtocol *iface, DWORD dwO HttpProtocol *This = PROTOCOL_THIS(iface); TRACE("(%p)->(%08x)\n", This, dwOptions); - HTTPPROTOCOL_Close(This); + protocol_close_connection(&This->base); return S_OK; } @@ -753,80 +427,10 @@ static HRESULT WINAPI HttpProtocol_Read(IInternetProtocol *iface, void *pv, ULONG cb, ULONG *pcbRead) { HttpProtocol *This = PROTOCOL_THIS(iface); - ULONG read = 0, len = 0; - HRESULT hres = S_FALSE; TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead); - if (!(This->flags & FLAG_REQUEST_COMPLETE)) - { - hres = E_PENDING; - } - else while (!(This->flags & FLAG_ALL_DATA_READ) && - read < cb) - { - if (This->available_bytes == 0) - { - /* InternetQueryDataAvailable may immediately fork and perform its asynchronous - * read, so clear the flag _before_ calling so it does not incorrectly get cleared - * after the status callback is called */ - This->flags &= ~FLAG_REQUEST_COMPLETE; - if (!InternetQueryDataAvailable(This->request, &This->available_bytes, 0, 0)) - { - if (GetLastError() == ERROR_IO_PENDING) - { - hres = E_PENDING; - } - else - { - WARN("InternetQueryDataAvailable failed: %d\n", GetLastError()); - hres = INET_E_DATA_NOT_AVAILABLE; - HTTPPROTOCOL_ReportResult(This, hres); - } - goto done; - } - else if (This->available_bytes == 0) - { - HTTPPROTOCOL_AllDataRead(This); - } - } - else - { - if (!InternetReadFile(This->request, ((BYTE *)pv)+read, - This->available_bytes > cb-read ? - cb-read : This->available_bytes, &len)) - { - WARN("InternetReadFile failed: %d\n", GetLastError()); - hres = INET_E_DOWNLOAD_FAILURE; - HTTPPROTOCOL_ReportResult(This, hres); - goto done; - } - else if (len == 0) - { - HTTPPROTOCOL_AllDataRead(This); - } - else - { - read += len; - This->current_position += len; - This->available_bytes -= len; - } - } - } - - /* Per MSDN this should be if (read == cb), but native returns S_OK - * if any bytes were read, so we will too */ - if (read) - hres = S_OK; - -done: - if (pcbRead) - *pcbRead = read; - - if (hres != E_PENDING) - This->flags |= FLAG_REQUEST_COMPLETE; - - return hres; + return protocol_read(&This->base, pv, cb, pcbRead); } static HRESULT WINAPI HttpProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove, @@ -843,10 +447,7 @@ static HRESULT WINAPI HttpProtocol_LockRequest(IInternetProtocol *iface, DWORD d TRACE("(%p)->(%08x)\n", This, dwOptions); - if (!InternetLockRequestFile(This->request, &This->lock)) - WARN("InternetLockRequest failed: %d\n", GetLastError()); - - return S_OK; + return protocol_lock_request(&This->base); } static HRESULT WINAPI HttpProtocol_UnlockRequest(IInternetProtocol *iface) @@ -855,18 +456,27 @@ static HRESULT WINAPI HttpProtocol_UnlockRequest(IInternetProtocol *iface) TRACE("(%p)\n", This); - if (This->lock) - { - if (!InternetUnlockRequestFile(This->lock)) - WARN("InternetUnlockRequest failed: %d\n", GetLastError()); - This->lock = 0; - } - - return S_OK; + return protocol_unlock_request(&This->base); } #undef PROTOCOL_THIS +static const IInternetProtocolVtbl HttpProtocolVtbl = { + HttpProtocol_QueryInterface, + HttpProtocol_AddRef, + HttpProtocol_Release, + HttpProtocol_Start, + HttpProtocol_Continue, + HttpProtocol_Abort, + HttpProtocol_Terminate, + HttpProtocol_Suspend, + HttpProtocol_Resume, + HttpProtocol_Read, + HttpProtocol_Seek, + HttpProtocol_LockRequest, + HttpProtocol_UnlockRequest +}; + #define PRIORITY_THIS(iface) DEFINE_THIS(HttpProtocol, InternetPriority, iface) static HRESULT WINAPI HttpPriority_QueryInterface(IInternetPriority *iface, REFIID riid, void **ppv) @@ -893,7 +503,7 @@ static HRESULT WINAPI HttpPriority_SetPriority(IInternetPriority *iface, LONG nP TRACE("(%p)->(%d)\n", This, nPriority); - This->priority = nPriority; + This->base.priority = nPriority; return S_OK; } @@ -903,7 +513,7 @@ static HRESULT WINAPI HttpPriority_GetPriority(IInternetPriority *iface, LONG *p TRACE("(%p)->(%p)\n", This, pnPriority); - *pnPriority = This->priority; + *pnPriority = This->base.priority; return S_OK; } @@ -917,22 +527,6 @@ static const IInternetPriorityVtbl HttpPriorityVtbl = { HttpPriority_GetPriority }; -static const IInternetProtocolVtbl HttpProtocolVtbl = { - HttpProtocol_QueryInterface, - HttpProtocol_AddRef, - HttpProtocol_Release, - HttpProtocol_Start, - HttpProtocol_Continue, - HttpProtocol_Abort, - HttpProtocol_Terminate, - HttpProtocol_Suspend, - HttpProtocol_Resume, - HttpProtocol_Read, - HttpProtocol_Seek, - HttpProtocol_LockRequest, - HttpProtocol_UnlockRequest -}; - static HRESULT create_http_protocol(BOOL https, void **ppobj) { HttpProtocol *ret; @@ -941,6 +535,7 @@ static HRESULT create_http_protocol(BOOL https, void **ppobj) if(!ret) return E_OUTOFMEMORY; + ret->base.vtbl = &AsyncProtocolVtbl; ret->lpInternetProtocolVtbl = &HttpProtocolVtbl; ret->lpInternetPriorityVtbl = &HttpPriorityVtbl; diff --git a/reactos/dll/win32/urlmon/protocol.c b/reactos/dll/win32/urlmon/protocol.c new file mode 100644 index 00000000000..b3d979e95f4 --- /dev/null +++ b/reactos/dll/win32/urlmon/protocol.c @@ -0,0 +1,430 @@ +/* + * Copyright 2007 Misha Koshelev + * Copyright 2009 Jacek Caban for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "urlmon_main.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(urlmon); + +/* Flags are needed for, among other things, return HRESULTs from the Read function + * to conform to native. For example, Read returns: + * + * 1. E_PENDING if called before the request has completed, + * (flags = 0) + * 2. S_FALSE after all data has been read and S_OK has been reported, + * (flags = FLAG_REQUEST_COMPLETE | FLAG_ALL_DATA_READ | FLAG_RESULT_REPORTED) + * 3. INET_E_DATA_NOT_AVAILABLE if InternetQueryDataAvailable fails. The first time + * this occurs, INET_E_DATA_NOT_AVAILABLE will also be reported to the sink, + * (flags = FLAG_REQUEST_COMPLETE) + * but upon subsequent calls to Read no reporting will take place, yet + * InternetQueryDataAvailable will still be called, and, on failure, + * INET_E_DATA_NOT_AVAILABLE will still be returned. + * (flags = FLAG_REQUEST_COMPLETE | FLAG_RESULT_REPORTED) + * + * FLAG_FIRST_DATA_REPORTED and FLAG_LAST_DATA_REPORTED are needed for proper + * ReportData reporting. For example, if OnResponse returns S_OK, Continue will + * report BSCF_FIRSTDATANOTIFICATION, and when all data has been read Read will + * report BSCF_INTERMEDIATEDATANOTIFICATION|BSCF_LASTDATANOTIFICATION. However, + * if OnResponse does not return S_OK, Continue will not report data, and Read + * will report BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION when all + * data has been read. + */ +#define FLAG_REQUEST_COMPLETE 0x0001 +#define FLAG_FIRST_CONTINUE_COMPLETE 0x0002 +#define FLAG_FIRST_DATA_REPORTED 0x0004 +#define FLAG_ALL_DATA_READ 0x0008 +#define FLAG_LAST_DATA_REPORTED 0x0010 +#define FLAG_RESULT_REPORTED 0x0020 + +static inline HRESULT report_progress(Protocol *protocol, ULONG status_code, LPCWSTR status_text) +{ + return IInternetProtocolSink_ReportProgress(protocol->protocol_sink, status_code, status_text); +} + +static inline HRESULT report_result(Protocol *protocol, HRESULT hres) +{ + if (!(protocol->flags & FLAG_RESULT_REPORTED) && protocol->protocol_sink) { + protocol->flags |= FLAG_RESULT_REPORTED; + IInternetProtocolSink_ReportResult(protocol->protocol_sink, hres, 0, NULL); + } + + return hres; +} + +static void report_data(Protocol *protocol) +{ + DWORD bscf; + + if((protocol->flags & FLAG_LAST_DATA_REPORTED) || !protocol->protocol_sink) + return; + + if(protocol->flags & FLAG_FIRST_DATA_REPORTED) { + bscf = BSCF_INTERMEDIATEDATANOTIFICATION; + }else { + protocol->flags |= FLAG_FIRST_DATA_REPORTED; + bscf = BSCF_FIRSTDATANOTIFICATION; + } + + if(protocol->flags & FLAG_ALL_DATA_READ && !(protocol->flags & FLAG_LAST_DATA_REPORTED)) { + protocol->flags |= FLAG_LAST_DATA_REPORTED; + bscf |= BSCF_LASTDATANOTIFICATION; + } + + IInternetProtocolSink_ReportData(protocol->protocol_sink, bscf, + protocol->current_position+protocol->available_bytes, + protocol->content_length); +} + +static void all_data_read(Protocol *protocol) +{ + protocol->flags |= FLAG_ALL_DATA_READ; + + report_data(protocol); + report_result(protocol, S_OK); +} + +static void request_complete(Protocol *protocol, INTERNET_ASYNC_RESULT *ar) +{ + PROTOCOLDATA data; + + if(!ar->dwResult) { + WARN("request failed: %d\n", ar->dwError); + return; + } + + protocol->flags |= FLAG_REQUEST_COMPLETE; + + if(!protocol->request) { + TRACE("setting request handle %p\n", (HINTERNET)ar->dwResult); + protocol->request = (HINTERNET)ar->dwResult; + } + + /* PROTOCOLDATA same as native */ + memset(&data, 0, sizeof(data)); + data.dwState = 0xf1000000; + if(protocol->flags & FLAG_FIRST_CONTINUE_COMPLETE) + data.pData = (LPVOID)BINDSTATUS_ENDDOWNLOADCOMPONENTS; + else + data.pData = (LPVOID)BINDSTATUS_DOWNLOADINGDATA; + + if (protocol->bindf & BINDF_FROMURLMON) + IInternetProtocolSink_Switch(protocol->protocol_sink, &data); + else + protocol_continue(protocol, &data); +} + +static void WINAPI internet_status_callback(HINTERNET internet, DWORD_PTR context, + DWORD internet_status, LPVOID status_info, DWORD status_info_len) +{ + Protocol *protocol = (Protocol*)context; + + switch(internet_status) { + case INTERNET_STATUS_RESOLVING_NAME: + TRACE("%p INTERNET_STATUS_RESOLVING_NAME\n", protocol); + report_progress(protocol, BINDSTATUS_FINDINGRESOURCE, (LPWSTR)status_info); + break; + + case INTERNET_STATUS_CONNECTING_TO_SERVER: + TRACE("%p INTERNET_STATUS_CONNECTING_TO_SERVER\n", protocol); + report_progress(protocol, BINDSTATUS_CONNECTING, (LPWSTR)status_info); + break; + + case INTERNET_STATUS_SENDING_REQUEST: + TRACE("%p INTERNET_STATUS_SENDING_REQUEST\n", protocol); + report_progress(protocol, BINDSTATUS_SENDINGREQUEST, (LPWSTR)status_info); + break; + + case INTERNET_STATUS_REQUEST_COMPLETE: + request_complete(protocol, status_info); + break; + + case INTERNET_STATUS_HANDLE_CREATED: + TRACE("%p INTERNET_STATUS_HANDLE_CREATED\n", protocol); + IInternetProtocol_AddRef(protocol->protocol); + break; + + case INTERNET_STATUS_HANDLE_CLOSING: + TRACE("%p INTERNET_STATUS_HANDLE_CLOSING\n", protocol); + + if(*(HINTERNET *)status_info == protocol->request) { + protocol->request = NULL; + if(protocol->protocol_sink) { + IInternetProtocolSink_Release(protocol->protocol_sink); + protocol->protocol_sink = NULL; + } + + if(protocol->bind_info.cbSize) { + ReleaseBindInfo(&protocol->bind_info); + memset(&protocol->bind_info, 0, sizeof(protocol->bind_info)); + } + }else if(*(HINTERNET *)status_info == protocol->connection) { + protocol->connection = NULL; + } + + IInternetProtocol_Release(protocol->protocol); + break; + + default: + WARN("Unhandled Internet status callback %d\n", internet_status); + } +} + +HRESULT protocol_start(Protocol *protocol, IInternetProtocol *prot, LPCWSTR url, + IInternetProtocolSink *protocol_sink, IInternetBindInfo *bind_info) +{ + LPOLESTR user_agent = NULL; + DWORD request_flags; + ULONG size = 0; + HRESULT hres; + + protocol->protocol = prot; + + IInternetProtocolSink_AddRef(protocol_sink); + protocol->protocol_sink = protocol_sink; + + memset(&protocol->bind_info, 0, sizeof(protocol->bind_info)); + protocol->bind_info.cbSize = sizeof(BINDINFO); + hres = IInternetBindInfo_GetBindInfo(bind_info, &protocol->bindf, &protocol->bind_info); + if(hres != S_OK) { + WARN("GetBindInfo failed: %08x\n", hres); + return report_result(protocol, hres); + } + + if(!(protocol->bindf & BINDF_FROMURLMON)) + report_progress(protocol, BINDSTATUS_DIRECTBIND, NULL); + + hres = IInternetBindInfo_GetBindString(bind_info, BINDSTRING_USER_AGENT, &user_agent, 1, &size); + if (hres != S_OK || !size) { + DWORD len; + CHAR null_char = 0; + LPSTR user_agenta = NULL; + + len = 0; + if ((hres = ObtainUserAgentString(0, &null_char, &len)) != E_OUTOFMEMORY) { + WARN("ObtainUserAgentString failed: %08x\n", hres); + }else if (!(user_agenta = heap_alloc(len*sizeof(CHAR)))) { + WARN("Out of memory\n"); + }else if ((hres = ObtainUserAgentString(0, user_agenta, &len)) != S_OK) { + WARN("ObtainUserAgentString failed: %08x\n", hres); + }else { + if(!(user_agent = CoTaskMemAlloc((len)*sizeof(WCHAR)))) + WARN("Out of memory\n"); + else + MultiByteToWideChar(CP_ACP, 0, user_agenta, -1, user_agent, len); + } + heap_free(user_agenta); + } + + protocol->internet = InternetOpenW(user_agent, 0, NULL, NULL, INTERNET_FLAG_ASYNC); + CoTaskMemFree(user_agent); + if(!protocol->internet) { + WARN("InternetOpen failed: %d\n", GetLastError()); + return report_result(protocol, INET_E_NO_SESSION); + } + + /* Native does not check for success of next call, so we won't either */ + InternetSetStatusCallbackW(protocol->internet, internet_status_callback); + + request_flags = INTERNET_FLAG_KEEP_CONNECTION; + if(protocol->bindf & BINDF_NOWRITECACHE) + request_flags |= INTERNET_FLAG_NO_CACHE_WRITE; + if(protocol->bindf & BINDF_NEEDFILE) + request_flags |= INTERNET_FLAG_NEED_FILE; + + hres = protocol->vtbl->open_request(protocol, url, request_flags, bind_info); + if(FAILED(hres)) { + protocol_close_connection(protocol); + return report_result(protocol, hres); + } + + return S_OK; +} + +HRESULT protocol_continue(Protocol *protocol, PROTOCOLDATA *data) +{ + HRESULT hres; + + if (!data) { + WARN("Expected pProtocolData to be non-NULL\n"); + return S_OK; + } + + if(!protocol->request) { + WARN("Expected request to be non-NULL\n"); + return S_OK; + } + + if(!protocol->protocol_sink) { + WARN("Expected IInternetProtocolSink pointer to be non-NULL\n"); + return S_OK; + } + + if(data->pData == (LPVOID)BINDSTATUS_DOWNLOADINGDATA) { + hres = protocol->vtbl->start_downloading(protocol); + if(FAILED(hres)) { + protocol_close_connection(protocol); + report_result(protocol, hres); + return S_OK; + } + + if(protocol->bindf & BINDF_NEEDFILE) { + WCHAR cache_file[MAX_PATH]; + DWORD buflen = sizeof(cache_file); + + if(InternetQueryOptionW(protocol->request, INTERNET_OPTION_DATAFILE_NAME, + cache_file, &buflen)) { + report_progress(protocol, BINDSTATUS_CACHEFILENAMEAVAILABLE, cache_file); + }else { + FIXME("Could not get cache file\n"); + } + } + + protocol->flags |= FLAG_FIRST_CONTINUE_COMPLETE; + } + + if(data->pData >= (LPVOID)BINDSTATUS_DOWNLOADINGDATA) { + BOOL res; + + /* InternetQueryDataAvailable may immediately fork and perform its asynchronous + * read, so clear the flag _before_ calling so it does not incorrectly get cleared + * after the status callback is called */ + protocol->flags &= ~FLAG_REQUEST_COMPLETE; + res = InternetQueryDataAvailable(protocol->request, &protocol->available_bytes, 0, 0); + if(res) { + protocol->flags |= FLAG_REQUEST_COMPLETE; + report_data(protocol); + }else if(GetLastError() != ERROR_IO_PENDING) { + protocol->flags |= FLAG_REQUEST_COMPLETE; + WARN("InternetQueryDataAvailable failed: %d\n", GetLastError()); + report_result(protocol, INET_E_DATA_NOT_AVAILABLE); + } + } + + return S_OK; +} + +HRESULT protocol_read(Protocol *protocol, void *buf, ULONG size, ULONG *read_ret) +{ + ULONG read = 0; + BOOL res; + HRESULT hres = S_FALSE; + + if(!(protocol->flags & FLAG_REQUEST_COMPLETE)) { + *read_ret = 0; + return E_PENDING; + } + + if(protocol->flags & FLAG_ALL_DATA_READ) { + *read_ret = 0; + return S_FALSE; + } + + while(read < size) { + if(protocol->available_bytes) { + ULONG len; + + res = InternetReadFile(protocol->request, ((BYTE *)buf)+read, + protocol->available_bytes > size-read ? size-read : protocol->available_bytes, &len); + if(!res) { + WARN("InternetReadFile failed: %d\n", GetLastError()); + hres = INET_E_DOWNLOAD_FAILURE; + report_result(protocol, hres); + break; + } + + if(!len) { + all_data_read(protocol); + break; + } + + read += len; + protocol->current_position += len; + protocol->available_bytes -= len; + }else { + /* InternetQueryDataAvailable may immediately fork and perform its asynchronous + * read, so clear the flag _before_ calling so it does not incorrectly get cleared + * after the status callback is called */ + protocol->flags &= ~FLAG_REQUEST_COMPLETE; + res = InternetQueryDataAvailable(protocol->request, &protocol->available_bytes, 0, 0); + if(!res) { + if (GetLastError() == ERROR_IO_PENDING) { + hres = E_PENDING; + }else { + WARN("InternetQueryDataAvailable failed: %d\n", GetLastError()); + hres = INET_E_DATA_NOT_AVAILABLE; + report_result(protocol, hres); + } + break; + } + + if(!protocol->available_bytes) { + all_data_read(protocol); + break; + } + } + } + + *read_ret = read; + + if (hres != E_PENDING) + protocol->flags |= FLAG_REQUEST_COMPLETE; + if(FAILED(hres)) + return hres; + + return read ? S_OK : S_FALSE; +} + +HRESULT protocol_lock_request(Protocol *protocol) +{ + if (!InternetLockRequestFile(protocol->request, &protocol->lock)) + WARN("InternetLockRequest failed: %d\n", GetLastError()); + + return S_OK; +} + +HRESULT protocol_unlock_request(Protocol *protocol) +{ + if(!protocol->lock) + return S_OK; + + if(!InternetUnlockRequestFile(protocol->lock)) + WARN("InternetUnlockRequest failed: %d\n", GetLastError()); + protocol->lock = 0; + + return S_OK; +} + +void protocol_close_connection(Protocol *protocol) +{ + protocol->vtbl->close_connection(protocol); + + if(protocol->request) + InternetCloseHandle(protocol->request); + + if(protocol->connection) + InternetCloseHandle(protocol->connection); + + if(protocol->internet) { + InternetCloseHandle(protocol->internet); + protocol->internet = 0; + } + + protocol->flags = 0; +} diff --git a/reactos/dll/win32/urlmon/umon.c b/reactos/dll/win32/urlmon/umon.c index bbaed5b7a2a..c338b1505db 100644 --- a/reactos/dll/win32/urlmon/umon.c +++ b/reactos/dll/win32/urlmon/umon.c @@ -532,8 +532,6 @@ static HRESULT URLMonikerImpl_BindToStorage_hack(LPCWSTR URLName, IBindCtx* pbc, if(SUCCEEDED(hres)) { URL_COMPONENTSW url; WCHAR *host, *path, *user, *pass; - DWORD dwService = 0; - BOOL bSuccess; TRACE("got bindinfo. bindf = %08x extrainfo = %s bindinfof = %08x bindverb = %08x iid %s\n", bindf, debugstr_w(bi.szExtraInfo), bi.grfBindInfoF, bi.dwBindVerb, debugstr_guid(&bi.iid)); @@ -583,23 +581,10 @@ static HRESULT URLMonikerImpl_BindToStorage_hack(LPCWSTR URLName, IBindCtx* pbc, break; } - switch ((DWORD) url.nScheme) - { - case INTERNET_SCHEME_FTP: - if (!url.nPort) - url.nPort = INTERNET_DEFAULT_FTP_PORT; - dwService = INTERNET_SERVICE_FTP; - break; - - case INTERNET_SCHEME_GOPHER: - if (!url.nPort) - url.nPort = INTERNET_DEFAULT_GOPHER_PORT; - dwService = INTERNET_SERVICE_GOPHER; - break; - } - + if (!url.nPort) + url.nPort = INTERNET_DEFAULT_GOPHER_PORT; bind->hconnect = InternetConnectW(bind->hinternet, host, url.nPort, user, pass, - dwService, 0, (DWORD_PTR)bind); + INTERNET_SERVICE_GOPHER, 0, (DWORD_PTR)bind); if (!bind->hconnect) { hres = HRESULT_FROM_WIN32(GetLastError()); @@ -612,37 +597,12 @@ static HRESULT URLMonikerImpl_BindToStorage_hack(LPCWSTR URLName, IBindCtx* pbc, hres = IBindStatusCallback_OnProgress(bind->pbscb, 0, 0, BINDSTATUS_CONNECTING, NULL); hres = IBindStatusCallback_OnProgress(bind->pbscb, 0, 0, BINDSTATUS_SENDINGREQUEST, NULL); - bSuccess = FALSE; - - switch (dwService) - { - case INTERNET_SERVICE_GOPHER: - bind->hrequest = GopherOpenFileW(bind->hconnect, - path, - 0, - INTERNET_FLAG_RELOAD, - 0); - if (bind->hrequest) - bSuccess = TRUE; - else - hres = HRESULT_FROM_WIN32(GetLastError()); - break; - - case INTERNET_SERVICE_FTP: - bind->hrequest = FtpOpenFileW(bind->hconnect, - path, - GENERIC_READ, - FTP_TRANSFER_TYPE_BINARY | - INTERNET_FLAG_TRANSFER_BINARY | - INTERNET_FLAG_RELOAD, - 0); - if (bind->hrequest) - bSuccess = TRUE; - else - hres = HRESULT_FROM_WIN32(GetLastError()); - break; - } - if(bSuccess) + bind->hrequest = GopherOpenFileW(bind->hconnect, + path, + 0, + INTERNET_FLAG_RELOAD, + 0); + if (bind->hrequest) { TRACE("res = %d gle = %u url len = %d\n", hres, GetLastError(), bind->expected_size); @@ -660,7 +620,10 @@ static HRESULT URLMonikerImpl_BindToStorage_hack(LPCWSTR URLName, IBindCtx* pbc, } InternetCloseHandle(bind->hrequest); hres = S_OK; + }else { + hres = HRESULT_FROM_WIN32(GetLastError()); } + InternetCloseHandle(bind->hconnect); InternetCloseHandle(bind->hinternet); @@ -704,9 +667,7 @@ static HRESULT WINAPI URLMonikerImpl_BindToStorage(IMoniker* iface, return E_FAIL; } - if(IsEqualGUID(&IID_IStream, riid) && - ( url.nScheme == INTERNET_SCHEME_FTP - || url.nScheme == INTERNET_SCHEME_GOPHER)) + if(IsEqualGUID(&IID_IStream, riid) && url.nScheme == INTERNET_SCHEME_GOPHER) return URLMonikerImpl_BindToStorage_hack(This->URLName, pbc, ppvObject); TRACE("(%p)->(%p %p %s %p)\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppvObject); diff --git a/reactos/dll/win32/urlmon/urlmon.rbuild b/reactos/dll/win32/urlmon/urlmon.rbuild index 0699b9ab3a0..6828cffa6ba 100644 --- a/reactos/dll/win32/urlmon/urlmon.rbuild +++ b/reactos/dll/win32/urlmon/urlmon.rbuild @@ -18,6 +18,7 @@ http.c internet.c mk.c + protocol.c regsvr.c sec_mgr.c session.c diff --git a/reactos/dll/win32/urlmon/urlmon_main.h b/reactos/dll/win32/urlmon/urlmon_main.h index 17cbd7637ad..10776f9193a 100644 --- a/reactos/dll/win32/urlmon/urlmon_main.h +++ b/reactos/dll/win32/urlmon/urlmon_main.h @@ -1,5 +1,6 @@ /* * Copyright 2002 Huw D M Davies for CodeWeavers + * Copyright 2009 Jacek Caban for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -30,6 +31,7 @@ #include "winuser.h" #include "ole2.h" #include "urlmon.h" +#include "wininet.h" #include "wine/unicode.h" @@ -50,7 +52,8 @@ static inline void URLMON_LockModule(void) { InterlockedIncrement( &URLMON_refCo static inline void URLMON_UnlockModule(void) { InterlockedDecrement( &URLMON_refCount ); } #define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field)) -#define DEFINE_THIS(cls,ifc,iface) ((cls*)((BYTE*)(iface)-offsetof(cls,lp ## ifc ## Vtbl))) +#define DEFINE_THIS2(cls,ifc,iface) ((cls*)((BYTE*)(iface)-offsetof(cls,ifc))) +#define DEFINE_THIS(cls,ifc,iface) DEFINE_THIS2(cls,lp ## ifc ## Vtbl,iface) typedef struct { @@ -76,6 +79,43 @@ HRESULT bind_to_object(IMoniker *mon, LPCWSTR url, IBindCtx *pbc, REFIID riid, v HRESULT create_binding_protocol(LPCWSTR url, BOOL from_urlmon, IInternetProtocol **protocol); void set_binding_sink(IInternetProtocol *bind_protocol, IInternetProtocolSink *sink); +typedef struct ProtocolVtbl ProtocolVtbl; + +typedef struct { + const ProtocolVtbl *vtbl; + + IInternetProtocol *protocol; + IInternetProtocolSink *protocol_sink; + + DWORD bindf; + BINDINFO bind_info; + + HINTERNET internet; + HINTERNET request; + HINTERNET connection; + DWORD flags; + HANDLE lock; + + ULONG current_position; + ULONG content_length; + ULONG available_bytes; + + LONG priority; +} Protocol; + +struct ProtocolVtbl { + HRESULT (*open_request)(Protocol*,LPCWSTR,DWORD,IInternetBindInfo*); + HRESULT (*start_downloading)(Protocol*); + void (*close_connection)(Protocol*); +}; + +HRESULT protocol_start(Protocol*,IInternetProtocol*,LPCWSTR,IInternetProtocolSink*,IInternetBindInfo*); +HRESULT protocol_continue(Protocol*,PROTOCOLDATA*); +HRESULT protocol_read(Protocol*,void*,ULONG,ULONG*); +HRESULT protocol_lock_request(Protocol*); +HRESULT protocol_unlock_request(Protocol*); +void protocol_close_connection(Protocol*); + static inline void *heap_alloc(size_t len) { return HeapAlloc(GetProcessHeap(), 0, len); @@ -111,6 +151,21 @@ static inline LPWSTR heap_strdupW(LPCWSTR str) return ret; } +static inline LPWSTR heap_strndupW(LPCWSTR str, int len) +{ + LPWSTR ret = NULL; + + if(str) { + ret = heap_alloc((len+1)*sizeof(WCHAR)); + if(ret) { + memcpy(ret, str, len*sizeof(WCHAR)); + ret[len] = 0; + } + } + + return ret; +} + static inline LPWSTR heap_strdupAtoW(const char *str) { LPWSTR ret = NULL;