[ros-diffs] [dchapyshev] 39867: - Sync crypt32, jscript, mapi32, mlang, msctf, msvcrt20, msvcrt40, msxml3, snmpapi, urlmon with Wine head

dchapyshev at svn.reactos.org dchapyshev at svn.reactos.org
Wed Mar 4 16:29:33 CET 2009


Author: dchapyshev
Date: Wed Mar  4 18:29:32 2009
New Revision: 39867

URL: http://svn.reactos.org/svn/reactos?rev=39867&view=rev
Log:
- Sync crypt32, jscript, mapi32, mlang, msctf, msvcrt20, msvcrt40, msxml3, snmpapi, urlmon with Wine head

Added:
    trunk/reactos/dll/win32/mapi32/version.rc   (with props)
    trunk/reactos/dll/win32/urlmon/protocol.c   (with props)
Modified:
    trunk/reactos/dll/win32/crypt32/chain.c
    trunk/reactos/dll/win32/crypt32/decode.c
    trunk/reactos/dll/win32/jscript/jsutils.c
    trunk/reactos/dll/win32/mapi32/mapi32.rbuild
    trunk/reactos/dll/win32/mlang/mlang.c
    trunk/reactos/dll/win32/msctf/categorymgr.c
    trunk/reactos/dll/win32/msctf/inputprocessor.c
    trunk/reactos/dll/win32/msvcrt20/msvcrt20.spec
    trunk/reactos/dll/win32/msvcrt40/msvcrt40.c
    trunk/reactos/dll/win32/msvcrt40/msvcrt40.spec
    trunk/reactos/dll/win32/msxml3/node.c
    trunk/reactos/dll/win32/snmpapi/main.c
    trunk/reactos/dll/win32/urlmon/binding.c
    trunk/reactos/dll/win32/urlmon/ftp.c
    trunk/reactos/dll/win32/urlmon/http.c
    trunk/reactos/dll/win32/urlmon/umon.c
    trunk/reactos/dll/win32/urlmon/urlmon.rbuild
    trunk/reactos/dll/win32/urlmon/urlmon_main.h

Modified: trunk/reactos/dll/win32/crypt32/chain.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/crypt32/chain.c?rev=39867&r1=39866&r2=39867&view=diff
==============================================================================
--- trunk/reactos/dll/win32/crypt32/chain.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/crypt32/chain.c [iso-8859-1] Wed Mar  4 18:29:32 2009
@@ -306,7 +306,13 @@
                  = 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;

Modified: trunk/reactos/dll/win32/crypt32/decode.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/crypt32/decode.c?rev=39867&r1=39866&r2=39867&view=diff
==============================================================================
--- trunk/reactos/dll/win32/crypt32/decode.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/crypt32/decode.c [iso-8859-1] Wed Mar  4 18:29:32 2009
@@ -1724,9 +1724,8 @@
                 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;
                 }

Modified: trunk/reactos/dll/win32/jscript/jsutils.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/jscript/jsutils.c?rev=39867&r1=39866&r2=39867&view=diff
==============================================================================
--- trunk/reactos/dll/win32/jscript/jsutils.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/jscript/jsutils.c [iso-8859-1] Wed Mar  4 18:29:32 2009
@@ -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 @@
 }
 
 #define MIN_BLOCK_SIZE  128
+#define ARENA_FREE_FILLER  0xaa
 
 static inline DWORD block_size(DWORD block)
 {
@@ -83,25 +85,25 @@
         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;
@@ -139,7 +141,15 @@
         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)

Modified: trunk/reactos/dll/win32/mapi32/mapi32.rbuild
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/mapi32/mapi32.rbuild?rev=39867&r1=39866&r2=39867&view=diff
==============================================================================
--- trunk/reactos/dll/win32/mapi32/mapi32.rbuild [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/mapi32/mapi32.rbuild [iso-8859-1] Wed Mar  4 18:29:32 2009
@@ -11,6 +11,7 @@
 	<file>prop.c</file>
 	<file>sendmail.c</file>
 	<file>util.c</file>
+	<file>version.rc</file>
 	<library>wine</library>
 	<library>shlwapi</library>
 	<library>shell32</library>

Added: trunk/reactos/dll/win32/mapi32/version.rc
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/mapi32/version.rc?rev=39867&view=auto
==============================================================================
--- trunk/reactos/dll/win32/mapi32/version.rc (added)
+++ trunk/reactos/dll/win32/mapi32/version.rc [iso-8859-1] Wed Mar  4 18:29:32 2009
@@ -1,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"

Propchange: trunk/reactos/dll/win32/mapi32/version.rc
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: trunk/reactos/dll/win32/mlang/mlang.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/mlang/mlang.c?rev=39867&r1=39866&r2=39867&view=diff
==============================================================================
--- trunk/reactos/dll/win32/mlang/mlang.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/mlang/mlang.c [iso-8859-1] Wed Mar  4 18:29:32 2009
@@ -1912,9 +1912,34 @@
         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 @@
         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,

Modified: trunk/reactos/dll/win32/msctf/categorymgr.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msctf/categorymgr.c?rev=39867&r1=39866&r2=39867&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msctf/categorymgr.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msctf/categorymgr.c [iso-8859-1] Wed Mar  4 18:29:32 2009
@@ -168,9 +168,67 @@
 static HRESULT WINAPI CategoryMgr_FindClosestCategory ( ITfCategoryMgr *iface,
         REFGUID rguid, GUID *pcatid, const GUID **ppcatidList, ULONG ulCount)
 {
-    CategoryMgr *This = (CategoryMgr*)iface;
-    FIXME("STUB:(%p)\n",This);
-    return E_NOTIMPL;
+    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;
+
+    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 (

Modified: trunk/reactos/dll/win32/msctf/inputprocessor.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msctf/inputprocessor.c?rev=39867&r1=39866&r2=39867&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msctf/inputprocessor.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msctf/inputprocessor.c [iso-8859-1] Wed Mar  4 18:29:32 2009
@@ -72,6 +72,7 @@
     DWORD   lang_index;
 
     LANGID  langid;
+    ITfCategoryMgr *catmgr;
 } EnumTfLanguageProfiles;
 
 static HRESULT ProfilesEnumGuid_Constructor(IEnumGUID **ppOut);
@@ -670,6 +671,7 @@
     RegCloseKey(This->tipkey);
     if (This->langkey)
         RegCloseKey(This->langkey);
+    ITfCategoryMgr_Release(This->catmgr);
     HeapFree(GetProcessHeap(),0,This);
 }
 
@@ -746,6 +748,9 @@
 
     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 @@
         /* 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 HRESULT EnumTfLanguageProfiles_Constructor(LANGID langid, IEnumTfLanguageProfiles **ppOut)
 {
+    HRESULT hr;
     EnumTfLanguageProfiles *This;
 
     This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EnumTfLanguageProfiles));
@@ -875,6 +884,13 @@
     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;

Modified: trunk/reactos/dll/win32/msvcrt20/msvcrt20.spec
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msvcrt20/msvcrt20.spec?rev=39867&r1=39866&r2=39867&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msvcrt20/msvcrt20.spec [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msvcrt20/msvcrt20.spec [iso-8859-1] Wed Mar  4 18:29:32 2009
@@ -437,22 +437,22 @@
 @ stub ?xsgetn at streambuf@@UAEHPADH at Z #
 @ stub ?xsputn at streambuf@@UAEHPBDH at 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

Modified: trunk/reactos/dll/win32/msvcrt40/msvcrt40.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msvcrt40/msvcrt40.c?rev=39867&r1=39866&r2=39867&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msvcrt40/msvcrt40.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msvcrt40/msvcrt40.c [iso-8859-1] Wed Mar  4 18:29:32 2009
@@ -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 )
 {

Modified: trunk/reactos/dll/win32/msvcrt40/msvcrt40.spec
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msvcrt40/msvcrt40.spec?rev=39867&r1=39866&r2=39867&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msvcrt40/msvcrt40.spec [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msvcrt40/msvcrt40.spec [iso-8859-1] Wed Mar  4 18:29:32 2009
@@ -481,22 +481,22 @@
 @ stub ?xsgetn at streambuf@@UAEHPADH at Z
 @ stub ?xsputn at streambuf@@UAEHPBDH at 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

Modified: trunk/reactos/dll/win32/msxml3/node.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/msxml3/node.c?rev=39867&r1=39866&r2=39867&view=diff
==============================================================================
--- trunk/reactos/dll/win32/msxml3/node.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/msxml3/node.c [iso-8859-1] Wed Mar  4 18:29:32 2009
@@ -387,6 +387,11 @@
 
     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;

Modified: trunk/reactos/dll/win32/snmpapi/main.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/snmpapi/main.c?rev=39867&r1=39866&r2=39867&view=diff
==============================================================================
--- trunk/reactos/dll/win32/snmpapi/main.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/snmpapi/main.c [iso-8859-1] Wed Mar  4 18:29:32 2009
@@ -19,6 +19,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include "config.h"
+
 #include <stdio.h>
 #include <stdarg.h>
 

Modified: trunk/reactos/dll/win32/urlmon/binding.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/binding.c?rev=39867&r1=39866&r2=39867&view=diff
==============================================================================
--- trunk/reactos/dll/win32/urlmon/binding.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/binding.c [iso-8859-1] Wed Mar  4 18:29:32 2009
@@ -1200,7 +1200,7 @@
 
     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)

Modified: trunk/reactos/dll/win32/urlmon/ftp.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/ftp.c?rev=39867&r1=39866&r2=39867&view=diff
==============================================================================
--- trunk/reactos/dll/win32/urlmon/ftp.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/ftp.c [iso-8859-1] Wed Mar  4 18:29:32 2009
@@ -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(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)
-
-#define PROTOCOL(x)  ((IInternetProtocol*)  &(x)->lpInternetProtocolVtbl)
 
 static HRESULT WINAPI FtpProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
 {
@@ -44,6 +94,9 @@
     }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 @@
     TRACE("(%p) ref=%d\n", This, ref);
 
     if(!ref) {
+        protocol_close_connection(&This->base);
         heap_free(This);
 
         URLMON_UnlockModule();
@@ -84,16 +138,25 @@
         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_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 @@
         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_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 @@
     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 @@
 
     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);

Modified: trunk/reactos/dll/win32/urlmon/http.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/http.c?rev=39867&r1=39866&r2=39867&view=diff
==============================================================================
--- trunk/reactos/dll/win32/urlmon/http.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/http.c [iso-8859-1] Wed Mar  4 18:29:32 2009
@@ -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;
+static LPWSTR query_http_info(HttpProtocol *This, DWORD option)
+{
+    LPWSTR ret = NULL;
+    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;
+}
+
+#define ASYNCPROTOCOL_THIS(iface) DEFINE_THIS2(HttpProtocol, base, iface)
+
+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 (num<sizeof(accept_mimes)/sizeof(accept_mimes[0]) && accept_mimes[num])
+        CoTaskMemFree(accept_mimes[num++]);
+    if (!This->base.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
-        {
-            This->flags |= FLAG_FIRST_DATA_REPORTED;
-            bscf = BSCF_FIRSTDATANOTIFICATION;
+            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;
+            }
         }
-        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)
-    {
+    }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->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)
+
+    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)
-{
-    LPWSTR ret = NULL;
-    if (string &&
-        (ret = heap_alloc((len+1)*sizeof(WCHAR))) != NULL)
-    {
-        memcpy(ret, string, len*sizeof(WCHAR));
-        ret[len] = 0;
-    }
-    return ret;
-}
-
-/*
- * Interface implementations
- */
-
-#define PROTOCOL(x)  ((IInternetProtocol*)  &(x)->lpInternetProtocolVtbl)
-#define PRIORITY(x)  ((IInternetPriority*)  &(x)->lpInternetPriorityVtbl)
+}
+
+#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 @@
     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 @@
         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;
-    }
-
-    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 (num<sizeof(accept_mimes)/sizeof(accept_mimes[0]) &&
-           accept_mimes[num])
-        CoTaskMemFree(accept_mimes[num++]);
-    CoTaskMemFree(user_agent);
-
-    heap_free(pass);
-    heap_free(user);
-    heap_free(path);
-    heap_free(host);
-
-    return hres;
+        return MK_E_SYNTAX;
+
+    return protocol_start(&This->base, 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 @@
     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 @@
         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 @@
 
     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,67 +456,10 @@
 
     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
-
-#define PRIORITY_THIS(iface) DEFINE_THIS(HttpProtocol, InternetPriority, iface)
-
-static HRESULT WINAPI HttpPriority_QueryInterface(IInternetPriority *iface, REFIID riid, void **ppv)
-{
-    HttpProtocol *This = PRIORITY_THIS(iface);
-    return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
-}
-
-static ULONG WINAPI HttpPriority_AddRef(IInternetPriority *iface)
-{
-    HttpProtocol *This = PRIORITY_THIS(iface);
-    return IInternetProtocol_AddRef(PROTOCOL(This));
-}
-
-static ULONG WINAPI HttpPriority_Release(IInternetPriority *iface)
-{
-    HttpProtocol *This = PRIORITY_THIS(iface);
-    return IInternetProtocol_Release(PROTOCOL(This));
-}
-
-static HRESULT WINAPI HttpPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
-{
-    HttpProtocol *This = PRIORITY_THIS(iface);
-
-    TRACE("(%p)->(%d)\n", This, nPriority);
-
-    This->priority = nPriority;
-    return S_OK;
-}
-
-static HRESULT WINAPI HttpPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
-{
-    HttpProtocol *This = PRIORITY_THIS(iface);
-
-    TRACE("(%p)->(%p)\n", This, pnPriority);
-
-    *pnPriority = This->priority;
-    return S_OK;
-}
-
-#undef PRIORITY_THIS
-
-static const IInternetPriorityVtbl HttpPriorityVtbl = {
-    HttpPriority_QueryInterface,
-    HttpPriority_AddRef,
-    HttpPriority_Release,
-    HttpPriority_SetPriority,
-    HttpPriority_GetPriority
-};
 
 static const IInternetProtocolVtbl HttpProtocolVtbl = {
     HttpProtocol_QueryInterface,
@@ -933,6 +477,56 @@
     HttpProtocol_UnlockRequest
 };
 
+#define PRIORITY_THIS(iface) DEFINE_THIS(HttpProtocol, InternetPriority, iface)
+
+static HRESULT WINAPI HttpPriority_QueryInterface(IInternetPriority *iface, REFIID riid, void **ppv)
+{
+    HttpProtocol *This = PRIORITY_THIS(iface);
+    return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
+}
+
+static ULONG WINAPI HttpPriority_AddRef(IInternetPriority *iface)
+{
+    HttpProtocol *This = PRIORITY_THIS(iface);
+    return IInternetProtocol_AddRef(PROTOCOL(This));
+}
+
+static ULONG WINAPI HttpPriority_Release(IInternetPriority *iface)
+{
+    HttpProtocol *This = PRIORITY_THIS(iface);
+    return IInternetProtocol_Release(PROTOCOL(This));
+}
+
+static HRESULT WINAPI HttpPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
+{
+    HttpProtocol *This = PRIORITY_THIS(iface);
+
+    TRACE("(%p)->(%d)\n", This, nPriority);
+
+    This->base.priority = nPriority;
+    return S_OK;
+}
+
+static HRESULT WINAPI HttpPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
+{
+    HttpProtocol *This = PRIORITY_THIS(iface);
+
+    TRACE("(%p)->(%p)\n", This, pnPriority);
+
+    *pnPriority = This->base.priority;
+    return S_OK;
+}
+
+#undef PRIORITY_THIS
+
+static const IInternetPriorityVtbl HttpPriorityVtbl = {
+    HttpPriority_QueryInterface,
+    HttpPriority_AddRef,
+    HttpPriority_Release,
+    HttpPriority_SetPriority,
+    HttpPriority_GetPriority
+};
+
 static HRESULT create_http_protocol(BOOL https, void **ppobj)
 {
     HttpProtocol *ret;
@@ -941,6 +535,7 @@
     if(!ret)
         return E_OUTOFMEMORY;
 
+    ret->base.vtbl = &AsyncProtocolVtbl;
     ret->lpInternetProtocolVtbl = &HttpProtocolVtbl;
     ret->lpInternetPriorityVtbl = &HttpPriorityVtbl;
 

Added: trunk/reactos/dll/win32/urlmon/protocol.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/protocol.c?rev=39867&view=auto
==============================================================================
--- trunk/reactos/dll/win32/urlmon/protocol.c (added)
+++ trunk/reactos/dll/win32/urlmon/protocol.c [iso-8859-1] Wed Mar  4 18:29:32 2009
@@ -1,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;
+}

Propchange: trunk/reactos/dll/win32/urlmon/protocol.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: trunk/reactos/dll/win32/urlmon/umon.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/umon.c?rev=39867&r1=39866&r2=39867&view=diff
==============================================================================
--- trunk/reactos/dll/win32/urlmon/umon.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/umon.c [iso-8859-1] Wed Mar  4 18:29:32 2009
@@ -532,8 +532,6 @@
             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 @@
                             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 @@
                     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 @@
                         }
                         InternetCloseHandle(bind->hrequest);
                             hres = S_OK;
+                    }else {
+                        hres = HRESULT_FROM_WIN32(GetLastError());
                     }
+
             
                     InternetCloseHandle(bind->hconnect);
                     InternetCloseHandle(bind->hinternet);
@@ -704,9 +667,7 @@
         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);

Modified: trunk/reactos/dll/win32/urlmon/urlmon.rbuild
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/urlmon.rbuild?rev=39867&r1=39866&r2=39867&view=diff
==============================================================================
--- trunk/reactos/dll/win32/urlmon/urlmon.rbuild [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/urlmon.rbuild [iso-8859-1] Wed Mar  4 18:29:32 2009
@@ -18,6 +18,7 @@
 	<file>http.c</file>
 	<file>internet.c</file>
 	<file>mk.c</file>
+	<file>protocol.c</file>
 	<file>regsvr.c</file>
 	<file>sec_mgr.c</file>
 	<file>session.c</file>

Modified: trunk/reactos/dll/win32/urlmon/urlmon_main.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/urlmon_main.h?rev=39867&r1=39866&r2=39867&view=diff
==============================================================================
--- trunk/reactos/dll/win32/urlmon/urlmon_main.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/urlmon/urlmon_main.h [iso-8859-1] Wed Mar  4 18:29:32 2009
@@ -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_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
 {	
@@ -75,6 +78,43 @@
 
 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)
 {
@@ -111,6 +151,21 @@
     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;



More information about the Ros-diffs mailing list