Sync to trunk (r44371)
authorSamuel Serapion <samuel.serapion@gmail.com>
Thu, 3 Dec 2009 07:26:32 +0000 (07:26 +0000)
committerSamuel Serapion <samuel.serapion@gmail.com>
Thu, 3 Dec 2009 07:26:32 +0000 (07:26 +0000)
svn path=/branches/ros-amd64-bringup/; revision=44372

134 files changed:
1  2 
reactos/base/applications/iexplore/iexplore.rbuild
reactos/base/setup/reactos/reactos.c
reactos/base/shell/explorer/explorer.rbuild
reactos/boot/bootdata/packages/reactos.dff
reactos/dll/3rdparty/libxslt/libxslt.rbuild
reactos/dll/3rdparty/mesa32/mesa32.rbuild
reactos/dll/cpl/main/mouse.c
reactos/dll/directx/dsound_new/enum.c
reactos/dll/nls/idndl/idndl.rbuild
reactos/dll/ntdll/ldr/utils.c
reactos/dll/ntdll/ntdll.rbuild
reactos/dll/win32/advapi32/sec/misc.c
reactos/dll/win32/browseui/shellbrowser.cpp
reactos/dll/win32/comctl32/comctl32.rbuild
reactos/dll/win32/crypt32/base64.c
reactos/dll/win32/crypt32/cert.c
reactos/dll/win32/crypt32/chain.c
reactos/dll/win32/crypt32/context.c
reactos/dll/win32/crypt32/crl.c
reactos/dll/win32/crypt32/ctl.c
reactos/dll/win32/crypt32/decode.c
reactos/dll/win32/crypt32/oid.c
reactos/dll/win32/crypt32/serialize.c
reactos/dll/win32/gdiplus/brush.c
reactos/dll/win32/gdiplus/gdiplus.c
reactos/dll/win32/gdiplus/gdiplus.rbuild
reactos/dll/win32/gdiplus/graphics.c
reactos/dll/win32/gdiplus/image.c
reactos/dll/win32/imagehlp/imagehlp.rbuild
reactos/dll/win32/kernel32/except/except.c
reactos/dll/win32/kernel32/file/rw.c
reactos/dll/win32/kernel32/kernel32.pspec
reactos/dll/win32/kernel32/misc/actctx.c
reactos/dll/win32/kernel32/misc/errormsg.c
reactos/dll/win32/kernel32/thread/thread.c
reactos/dll/win32/msafd/msafd.rbuild
reactos/dll/win32/mshtml/dispex.c
reactos/dll/win32/mshtml/htmldoc.c
reactos/dll/win32/mshtml/htmliframe.c
reactos/dll/win32/mshtml/htmllocation.c
reactos/dll/win32/mshtml/htmlnode.c
reactos/dll/win32/mshtml/htmlwindow.c
reactos/dll/win32/mshtml/mutation.c
reactos/dll/win32/mshtml/navigate.c
reactos/dll/win32/mshtml/nsio.c
reactos/dll/win32/mshtml/task.c
reactos/dll/win32/msi/action.c
reactos/dll/win32/msi/install.c
reactos/dll/win32/msi/media.c
reactos/dll/win32/msi/msi.c
reactos/dll/win32/msi/msi_main.c
reactos/dll/win32/msi/package.c
reactos/dll/win32/msvcrt/msvcrt.rbuild
reactos/dll/win32/nddeapi/nddeapi.rbuild
reactos/dll/win32/ntdsapi/ntdsapi.rbuild
reactos/dll/win32/odbc32/odbc32.rbuild
reactos/dll/win32/olecli32/olecli32.rbuild
reactos/dll/win32/pdh/pdh.rbuild
reactos/dll/win32/printui/printui.rbuild
reactos/dll/win32/setupapi/parser.c
reactos/dll/win32/shell32/drive.c
reactos/dll/win32/shell32/shell32_main.c
reactos/dll/win32/shell32/shellord.c
reactos/dll/win32/shlwapi/url.c
reactos/dll/win32/sxs/sxs.rbuild
reactos/dll/win32/user32/misc/dde.c
reactos/dll/win32/user32/windows/menu.c
reactos/dll/win32/wdmaud.drv/wdmaud.c
reactos/dll/win32/wdmaud.drv/wdmaud.rbuild
reactos/dll/win32/winfax/winfax.rbuild
reactos/dll/win32/wininet/cookie.c
reactos/dll/win32/wininet/dialogs.c
reactos/dll/win32/wininet/ftp.c
reactos/dll/win32/wininet/http.c
reactos/dll/win32/wininet/internet.c
reactos/dll/win32/wininet/internet.h
reactos/dll/win32/wininet/netconnection.c
reactos/dll/win32/wininet/urlcache.c
reactos/dll/win32/ws2_32/misc/stubs.c
reactos/dll/win32/ws2_32/ws2_32.rbuild
reactos/drivers/ksfilter/ks/event.c
reactos/drivers/network/tcpip/tcpip/dispatch.c
reactos/drivers/video/videoprt/interrupt.c
reactos/drivers/wdm/audio/backpln/portcls/dispatcher.cpp
reactos/drivers/wdm/audio/backpln/portcls/irp.cpp
reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp
reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp
reactos/drivers/wdm/audio/backpln/portcls/undoc.cpp
reactos/drivers/wdm/audio/drivers/CMIDriver/adapter.cpp
reactos/drivers/wdm/audio/drivers/directory.rbuild
reactos/drivers/wdm/audio/legacy/wdmaud/control.c
reactos/drivers/wdm/audio/legacy/wdmaud/entry.c
reactos/drivers/wdm/audio/legacy/wdmaud/interface.h
reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c
reactos/hal/hal/hal.c
reactos/hal/halarm/generic/hal.c
reactos/hal/halx86/generic/irq.S
reactos/hal/halx86/mp/mpsirql.c
reactos/include/crt/stdio.h
reactos/include/crt/stdlib.h
reactos/include/crt/time.h
reactos/include/crt/wchar.h
reactos/include/ddk/winddk.h
reactos/include/psdk/mmddk.h
reactos/include/psdk/wincrypt.h
reactos/include/psdk/windef.h
reactos/include/psdk/winternl.h
reactos/include/psdk/winuser.h
reactos/include/reactos/libs/sound/mmebuddy.h
reactos/include/reactos/win32k/ntuser.h
reactos/lib/3rdparty/bzip2/bzip2.rbuild
reactos/lib/3rdparty/mingw/mingw.rbuild
reactos/lib/atl/atlcom.h
reactos/lib/atl/atlwin.h
reactos/lib/drivers/ip/transport/tcp/tcp.c
reactos/lib/drivers/sound/mmebuddy/auxiliary/auxMessage.c
reactos/lib/drivers/sound/mmebuddy/midi/midMessage.c
reactos/lib/drivers/sound/mmebuddy/midi/modMessage.c
reactos/lib/drivers/sound/mmebuddy/mixer/mxdMessage.c
reactos/lib/drivers/sound/mmebuddy/mmewrap.c
reactos/lib/drivers/sound/mmebuddy/wave/widMessage.c
reactos/lib/drivers/sound/mmebuddy/wave/wodMessage.c
reactos/lib/drivers/sound/sound.rbuild
reactos/lib/rtl/actctx.c
reactos/lib/sdk/crt/crt.rbuild
reactos/ntoskrnl/ex/sysinfo.c
reactos/ntoskrnl/fsrtl/fastio.c
reactos/ntoskrnl/include/internal/mm.h
reactos/ntoskrnl/kd/kdmain.c
reactos/ntoskrnl/kdbg/amd64/kdb.c
reactos/ntoskrnl/mm/amd64/init.c
reactos/ntoskrnl/mm/mminit.c
reactos/ntoskrnl/mm/sysldr.c
reactos/ntoskrnl/se/semgr.c

@@@ -2,10 -2,9 +2,9 @@@
  <!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
  <module name="iexplore" type="win32gui" installbase="system32" installname="iexplore.exe" unicode="no">
        <include base="iexplore">.</include>
-       <library>kernel32</library>
        <library>user32</library>
        <library>gdi32</library>
 -      <library>shdocvw</library>
 +        <library>shdocvw</library>
        <file>main.c</file>
        <file>version.rc</file>
  </module>
@@@ -1084,112 -1084,62 +1084,62 @@@ void LoadSetupData(
          }
  
          // get computers list
-         Count = SetupGetLineCount(hTxtsetupSif, _T("Computer"));
-         if (Count > 0)
-         {
-             SetupData.pComputers = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GENENTRY) * Count);
-             if (SetupData.pComputers != NULL)
-             {
-                 SetupData.CompCount = Count;
-                 Count = 0;
-                 if (SetupFindFirstLine(hTxtsetupSif, _T("Computer"), NULL, &InfContext))
-                 {
-                     do
-                     {
-                         SetupGetStringField(&InfContext,
-                                             0,
-                                             SetupData.pComputers[Count].Id,
-                                             sizeof(SetupData.pComputers[Count].Id) / sizeof(TCHAR),
-                                             &LineLength);
-                         SetupGetStringField(&InfContext,
-                                             1,
-                                             SetupData.pComputers[Count].Value,
-                                             sizeof(SetupData.pComputers[Count].Value) / sizeof(TCHAR),
-                                             &LineLength);
-                         ++Count;
-                     }
-                     while (SetupFindNextLine(&InfContext, &InfContext) && Count < SetupData.CompCount);
-                 }
-             }
-         }
+         SetupData.CompCount = LoadGenentry(hTxtsetupSif,_T("Computer"),SetupData.pComputers,&InfContext);
  
          // get display list
-         Count = SetupGetLineCount(hTxtsetupSif, _T("Display"));
-         if (Count > 0)
-         {
-             SetupData.pDisplays = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GENENTRY) * Count);
-             if (SetupData.pDisplays != NULL)
-             {
-                 SetupData.DispCount = Count;
-                 Count = 0;
+         SetupData.DispCount = LoadGenentry(hTxtsetupSif,_T("Display"),SetupData.pDisplays,&InfContext);
  
-                 if (SetupFindFirstLine(hTxtsetupSif, _T("Display"), NULL, &InfContext))
-                 {
-                     do
-                     {
-                         SetupGetStringField(&InfContext,
-                                             0,
-                                             SetupData.pDisplays[Count].Id,
-                                             sizeof(SetupData.pDisplays[Count].Id) / sizeof(TCHAR),
-                                             &LineLength);
+         // get keyboard list
+         SetupData.KeybCount = LoadGenentry(hTxtsetupSif, _T("Keyboard"),SetupData.pKeyboards,&InfContext);
  
 -        {
 -            SetupGetStringField(&InfContext,
 -                                1,
+         // get install directory
+         if (SetupFindFirstLine(hTxtsetupSif, _T("SetupData"), _T("DefaultPath"), &InfContext))
-                                             SetupData.pDisplays[Count].Value,
-                                             sizeof(SetupData.pDisplays[Count].Value) / sizeof(TCHAR),
++                {
 +                        SetupGetStringField(&InfContext,
 +                                            1,
 -                                &LineLength);
 -        }
+                                 SetupData.InstallDir,
+                                 sizeof(SetupData.InstallDir) / sizeof(TCHAR),
-                         ++Count;
 +                                            &LineLength);
-                     while (SetupFindNextLine(&InfContext, &InfContext) && Count < SetupData.DispCount);
 +                    }
 -    }
 -}
+         SetupCloseInfFile(hTxtsetupSif);
-         }
 +                }
 +            }
  
-         // get keyboard list
-         Count = SetupGetLineCount(hTxtsetupSif, _T("Keyboard"));
-         if (Count > 0)
+ LONG LoadGenentry(HINF hinf,PCTSTR name,PGENENTRY gen,PINFCONTEXT context)
 -{
 +        {
-             SetupData.pKeyboards = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GENENTRY) * Count);
-             if (SetupData.pKeyboards != NULL)
-             {
-                 SetupData.KeybCount = Count;
-                 Count = 0;
+     LONG TotalCount;
  
-                 if (SetupFindFirstLine(hTxtsetupSif, _T("Keyboard"), NULL, &InfContext))
+     TotalCount = SetupGetLineCount(hinf, name);
+     if (TotalCount > 0)
 -    {
 +                {
+         gen = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(GENENTRY) * TotalCount);
+         if (gen != NULL)
+         {
+             if (SetupFindFirstLine(hinf, name, NULL, context))
+             {
+                 LONG Count = 0;
 -                do
 -                {
 +                    do
 +                    {
-                         SetupGetStringField(&InfContext,
+                     SetupGetStringField(context,
 -                                        0,
 +                                            0,
-                                             SetupData.pKeyboards[Count].Id,
-                                             sizeof(SetupData.pKeyboards[Count].Id) / sizeof(TCHAR),
-                                             &LineLength);
+                                         gen[Count].Id,
+                                         sizeof(gen[Count].Id) / sizeof(TCHAR),
+                                         NULL);
  
-                         SetupGetStringField(&InfContext,
+                     SetupGetStringField(context,
 -                                        1,
 +                                            1,
-                                             SetupData.pKeyboards[Count].Value,
-                                             sizeof(SetupData.pKeyboards[Count].Value) / sizeof(TCHAR),
-                                             &LineLength);
-                         ++Count;
+                                         gen[Count].Value,
+                                         sizeof(gen[Count].Value) / sizeof(TCHAR),
+                                         NULL);
+                     Count++;
 -                }
 +                    }
-                     while (SetupFindNextLine(&InfContext, &InfContext) && Count < SetupData.KeybCount);
+                 while (SetupFindNextLine(context, context) && Count < TotalCount);
 +                }
              }
          }
 -    }
  
-         // get install directory
-         if (SetupFindFirstLine(hTxtsetupSif, _T("SetupData"), _T("DefaultPath"), &InfContext))
-         {
-             SetupGetStringField(&InfContext,
-                                 1,
-                                 SetupData.InstallDir,
-                                 sizeof(SetupData.InstallDir) / sizeof(TCHAR),
-                                 &LineLength);
+     return TotalCount;
 -}
 +        }
-         SetupCloseInfFile(hTxtsetupSif);
-     }
- }
  
  BOOL isUnattendSetup()
  {
@@@ -662,14 -661,17 +662,17 @@@ media\sounds\ReactOS_LogOn.wa
  boot\bootdata\bootcdregtest\regtest.cmd             7   optional
  
  ; Subsystems
 -subsystems\win32\csrss\csrss.exe                    1
 -subsystems\win32\csrss\win32csr\win32csr.dll        1
 -subsystems\ntvdm\ntvdm.exe                          1
 -subsystems\win32\win32k\win32k.sys                  1
 +;subsystems\win32\csrss\csrss.exe                    1
 +;subsystems\win32\csrss\win32csr\win32csr.dll        1
 +;subsystems\ntvdm\ntvdm.exe                          1
 +;subsystems\win32\win32k\win32k.sys                  1
  
  ; Optional/proprietary files
- modules\optional\kvmnet.inf                         6  optional
- modules\optional\kvmnet.sys                         2  optional
+ modules\optional\DroidSansFallback.ttf              3  optional
+ modules\optional\NOTICE_for_Droid_Font.txt          4  optional
+ modules\optional\netkvm2k.inf                       6  optional
+ modules\optional\netkvm2k.cat                       6  optional
+ modules\optional\netkvm.sys                         2  optional
  modules\optional\alcxwdm.inf                        6  optional
  modules\optional\alcxwdm.sys                        2  optional
  modules\optional\mfc42.dll                          1  optional
@@@ -5,6 -5,6 +5,7 @@@
        <define name="WIN32" />
        <define name="_WINDOWS" />
        <define name="_MBCS" />
++      <define name="HAVE_STAT" />
        <define name="HAVE_WIN32_THREADS" />
        <define name="_REENTRANT" />
        <define name="_WINSOCKAPI_" />
@@@ -384,7 -384,7 +384,7 @@@ ButtonProc(IN HWND hwndDlg
                  //SetDoubleClickTime(pButtonData->g_DoubleClickSpeed);
  
  #if (WINVER >= 0x0500)
--                SystemParametersInfo(SPI_SETMOUSECLICKLOCK, 0, (PVOID)pButtonData->g_ClickLockEnabled, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
++                SystemParametersInfo(SPI_SETMOUSECLICKLOCK, 0, UlongToPtr(pButtonData->g_ClickLockEnabled), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
                  if (pButtonData->g_ClickLockEnabled)
                     SystemParametersInfo(SPI_SETMOUSECLICKLOCKTIME, pButtonData->g_ClickLockTime, NULL, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
  #endif
@@@ -1258,7 -1258,7 +1258,7 @@@ PointerProc(IN HWND hwndDlg
  //#if (WINVER >= 0x0500)
                  if (pPointerData->bOrigCursorShadow != pPointerData->bCursorShadow)
                  {
--                    SystemParametersInfo(SPI_SETCURSORSHADOW, 0, (PVOID)pPointerData->bCursorShadow, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
++                    SystemParametersInfo(SPI_SETCURSORSHADOW, 0, UlongToPtr(pPointerData->bCursorShadow), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
                      pPointerData->bOrigCursorShadow = pPointerData->bCursorShadow;
                  }
  //#endif
              else if (lppsn->hdr.code == PSN_RESET)
              {
  //#if (WINVER >= 0x0500)
--                SystemParametersInfo(SPI_SETCURSORSHADOW, 0, (PVOID)pPointerData->bOrigCursorShadow, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
++                SystemParametersInfo(SPI_SETCURSORSHADOW, 0, UlongToPtr(pPointerData->bOrigCursorShadow), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
  //#endif
              }
              break;
@@@ -91,7 -91,11 +91,11 @@@ DoDSoundCallback
          }
  
          DriverNameA[0] = 0;
 -            WideCharToMultiByte(CP_ACP, 0, ProductName, -1, DriverNameA, sizeof(DriverNameA) / sizeof(char), NULL, NULL);
+         if (ProductName)
+         {
 +        WideCharToMultiByte(CP_ACP, 0, ProductName, -1, DriverNameA, sizeof(DriverNameA) / sizeof(char), NULL, NULL);
+             DriverNameA[(sizeof(DriverNameA) / sizeof(char))-1] = 0;
+         }
  
          return lpDSEnumCallbackA(DeviceGuid, (LPSTR)Buffer, DriverNameA, lpContext);
      }
Simple merge
@@@ -699,7 -702,14 +702,14 @@@ LdrpMapDllImageFile(IN PWSTR SearchPat
                            MAX_PATH,
                            DosName,
                            NULL) == 0)
 -        return STATUS_DLL_NOT_FOUND;
+   {
+       /* try to find active context dll */
+     Status = find_actctx_dll(DllName->Buffer, DosName);
+     if(Status == STATUS_SUCCESS)
+         DPRINT("found %S for %S\n", DosName,DllName->Buffer);
+     else
 +    return STATUS_DLL_NOT_FOUND;
+   }
  
    if (!RtlDosPathNameToNtPathName_U (DosName,
                                       &FullNtFileName,
@@@ -3389,8 -3423,55 +3430,55 @@@ LdrLockLoaderLock(IN ULONG Flags
                    OUT PULONG Disposition OPTIONAL,
                    OUT PULONG Cookie OPTIONAL)
  {
-     UNIMPLEMENTED;
-     return STATUS_NOT_IMPLEMENTED;
+     NTSTATUS Status;
+     BOOLEAN Ret;
+     BOOLEAN CookieSet = FALSE;
+     if ((Flags != 0x01) && (Flags != 0x02))
+         return STATUS_INVALID_PARAMETER_1;
+     if (!Cookie) return STATUS_INVALID_PARAMETER_3;
+     /* Set some defaults for failure while verifying params */
+     _SEH2_TRY
+     {
+         *Cookie = 0;
+         CookieSet = TRUE;
+         if (Disposition) *Disposition = 0;
 -    }
++}
+     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+     {
+         if (CookieSet)
+             Status = STATUS_INVALID_PARAMETER_3;
+         else
+             Status =  STATUS_INVALID_PARAMETER_2;
+     }
+     _SEH2_END;
+     if (Flags == 0x01)
+     {
+         DPRINT1("Warning: Reporting errors with exception not supported yet!\n");
+         RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
+         Status = STATUS_SUCCESS;
+     }
+     else
+     {
+         if (!Disposition) return STATUS_INVALID_PARAMETER_2;
+         Ret = RtlTryEnterCriticalSection(NtCurrentPeb()->LoaderLock);
+         if (Ret)
+             *Disposition = 0x01;
+         else
+             *Disposition = 0x02;
+         Status = STATUS_SUCCESS;
+     }
+     /* FIXME: Cookie is based on part of the thread id */
+     *Cookie = (ULONG)NtCurrentTeb()->RealClientId.UniqueThread;
+     return Status;
  }
  
  NTSTATUS
Simple merge
@@@ -1166,49 -1167,37 +1167,37 @@@ LookupAccountSidW(LPCWSTR pSystemName
        else
        {
                ret = TRUE;
-               if ( TranslatedName )
+               
+               dwAccountName = TranslatedName->Name.Length / sizeof(WCHAR);
+               if (ReferencedDomain && ReferencedDomain->Entries > 0)
+                       dwDomainName = ReferencedDomain->Domains[0].Name.Length / sizeof(WCHAR);
+               else
+                       dwDomainName = 0;
+               
+               if (*pdwAccountName <= dwAccountName || *pdwDomainName <= dwDomainName)
                {
-                       DWORD dwSrcLen = TranslatedName->Name.Length / sizeof(WCHAR);
-                       if ( *pdwAccountName <= dwSrcLen )
-                       {
-                               *pdwAccountName = dwSrcLen + 1;
+                       /* One or two buffers are insufficient, add up a char for NULL termination */
+                       *pdwAccountName = dwAccountName + 1;
+                       *pdwDomainName = dwDomainName + 1;
 -                      ret = FALSE;
 +                              ret = FALSE;
-                       }
-                       else
+               } else
 -              {
 +                      {
-                               *pdwAccountName = dwSrcLen;
-                               if (pAccountName)
-                               {
-                                       RtlCopyMemory ( pAccountName, TranslatedName->Name.Buffer, TranslatedName->Name.Length );
-                                       pAccountName[TranslatedName->Name.Length / sizeof(WCHAR)] = L'\0';
-                               }
-                       }
+                       /* Lengths are sufficient, copy the data */
+                       if(dwAccountName)
+                               RtlCopyMemory(pAccountName, TranslatedName->Name.Buffer, dwAccountName * sizeof(WCHAR));
+                       pAccountName[dwAccountName] = L'\0';
+                       
+                       if(dwDomainName)
+                               RtlCopyMemory(pDomainName, ReferencedDomain->Domains[0].Name.Buffer, dwDomainName * sizeof(WCHAR));
+                       pDomainName[dwDomainName] = L'\0';
+                       *pdwAccountName = dwAccountName;
+                       *pdwDomainName = dwDomainName;
 -                      if (peUse)
 +                      if ( peUse )
                                *peUse = TranslatedName->Use;
                }
 -              
 +
-               if ( ReferencedDomain )
-               {
-                       if ( ReferencedDomain->Entries > 0 )
-                       {
-                               DWORD dwSrcLen = ReferencedDomain->Domains[0].Name.Length / sizeof(WCHAR);
-                               if ( *pdwDomainName <= dwSrcLen )
-                               {
-                                       *pdwDomainName = dwSrcLen + 1;
-                                       ret = FALSE;
-                               }
-                               else
-                               {
-                                       *pdwDomainName = dwSrcLen;
-                                       if (pDomainName)
-                                       {
-                                           RtlCopyMemory ( pDomainName, ReferencedDomain->Domains[0].Name.Buffer, ReferencedDomain->Domains[0].Name.Length );
-                                           pDomainName[ReferencedDomain->Domains[0].Name.Length / sizeof(WCHAR)] = L'\0';
-                                       }
-                               }
-                       }
-               }
                if ( !ret )
                        SetLastError(ERROR_INSUFFICIENT_BUFFER);
        }
@@@ -282,7 -282,7 +282,7 @@@ void CToolbarProxy::Initialize(HWND par
  
  LRESULT CToolbarProxy::OnAddBitmap(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
  {
--      LRESULT                                                                 result;
++      LONG                                                                    result;
        HRESULT                                                                 hResult;
  
        result = 0;
@@@ -97,7 -99,8 +99,8 @@@ static LONG encodeBase64A(const BYTE *i
  
      TRACE("bytes is %d, pad bytes is %d\n", bytes, pad_bytes);
      needed = bytes + pad_bytes + 1;
 -        needed += (needed / 64 + 1) * strlen(sep);
+     if (sep)
 +    needed += (needed / 64 + 1) * strlen(sep);
  
      if (needed > *out_len)
      {
              *ptr++ = '=';
              break;
      }
 -        strcpy(ptr, sep);
+     if (sep)
 +    strcpy(ptr, sep);
  
      return ERROR_SUCCESS;
  }
@@@ -198,7 -204,8 +204,8 @@@ static BOOL BinaryToBase64A(const BYTE 
  
      charsNeeded = 0;
      encodeBase64A(pbBinary, cbBinary, sep, NULL, &charsNeeded);
 -        charsNeeded += strlen(sep);
+     if (sep)
 +    charsNeeded += strlen(sep);
      if (header)
          charsNeeded += strlen(header) + strlen(sep);
      if (trailer)
          {
              strcpy(ptr, header);
              ptr += strlen(ptr);
 -                strcpy(ptr, sep);
 -                ptr += strlen(sep);
 -            }
+             if (sep)
+             {
 +            strcpy(ptr, sep);
 +            ptr += strlen(sep);
 +        }
+         }
          encodeBase64A(pbBinary, cbBinary, sep, ptr, &size);
          ptr += size - 1;
          if (trailer)
          {
              strcpy(ptr, trailer);
              ptr += strlen(ptr);
 -                strcpy(ptr, sep);
 -                ptr += strlen(sep);
 -            }
+             if (sep)
+             {
 +            strcpy(ptr, sep);
 +            ptr += strlen(sep);
 +        }
+         }
          *pcchString = charsNeeded - 1;
      }
      else if (pszString)
@@@ -1365,39 -1465,68 +1465,68 @@@ static PCCERT_CONTEXT find_cert_by_issu
          }
      }
      else
-        ret = compare_cert_by_name(pCertContext,
-         CERT_COMPARE_NAME | CERT_COMPARE_SUBJECT_CERT, dwFlags,
-         &subject->pCertInfo->Issuer);
-     return ret;
+        found = cert_compare_certs_in_store(store, prev,
+         compare_cert_by_name, CERT_COMPARE_NAME | CERT_COMPARE_SUBJECT_CERT,
+         dwFlags, &subject->pCertInfo->Issuer);
+     return found;
  }
  
- static BOOL compare_existing_cert(PCCERT_CONTEXT pCertContext, DWORD dwType,
-  DWORD dwFlags, const void *pvPara)
+ static BOOL compare_cert_by_name_str(PCCERT_CONTEXT pCertContext,
+  DWORD dwType, DWORD dwFlags, const void *pvPara)
  {
-     PCCERT_CONTEXT toCompare = pvPara;
-     return CertCompareCertificate(pCertContext->dwCertEncodingType,
-      pCertContext->pCertInfo, toCompare->pCertInfo);
+     PCERT_NAME_BLOB name;
+     DWORD len;
+     BOOL ret = FALSE;
+     if (dwType & CERT_INFO_SUBJECT_FLAG)
+         name = &pCertContext->pCertInfo->Subject;
+     else
+         name = &pCertContext->pCertInfo->Issuer;
+     len = CertNameToStrW(pCertContext->dwCertEncodingType, name,
+      CERT_SIMPLE_NAME_STR, NULL, 0);
+     if (len)
+     {
+         LPWSTR str = CryptMemAlloc(len * sizeof(WCHAR));
+         if (str)
+         {
+             LPWSTR ptr;
+             CertNameToStrW(pCertContext->dwCertEncodingType, name,
+              CERT_SIMPLE_NAME_STR, str, len);
+             for (ptr = str; *ptr; ptr++)
+                 *ptr = tolowerW(*ptr);
+             if (strstrW(str, pvPara))
+                 ret = TRUE;
+             CryptMemFree(str);
 -        }
++}
+     }
+     return ret;
  }
  
- static BOOL compare_cert_by_signature_hash(PCCERT_CONTEXT pCertContext, DWORD dwType,
-  DWORD dwFlags, const void *pvPara)
+ static PCCERT_CONTEXT find_cert_by_name_str(HCERTSTORE store, DWORD dwType,
+  DWORD dwFlags, const void *pvPara, PCCERT_CONTEXT prev)
  {
-     const CRYPT_HASH_BLOB *hash = pvPara;
-     DWORD size = 0;
-     BOOL ret;
+     PCCERT_CONTEXT found = NULL;
  
-     ret = CertGetCertificateContextProperty(pCertContext,
-      CERT_SIGNATURE_HASH_PROP_ID, NULL, &size);
-     if (ret && size == hash->cbData)
+     TRACE("%s\n", debugstr_w(pvPara));
+     if (pvPara)
      {
-         LPBYTE buf = CryptMemAlloc(size);
+         DWORD len = strlenW(pvPara);
+         LPWSTR str = CryptMemAlloc((len + 1) * sizeof(WCHAR));
  
-         if (buf)
+         if (str)
          {
-             CertGetCertificateContextProperty(pCertContext,
-              CERT_SIGNATURE_HASH_PROP_ID, buf, &size);
-             ret = !memcmp(buf, hash->pbData, size);
-             CryptMemFree(buf);
+             LPCWSTR src;
+             LPWSTR dst;
+             for (src = pvPara, dst = str; *src; src++, dst++)
+                 *dst = tolowerW(*src);
+             *dst = 0;
+            found = cert_compare_certs_in_store(store, prev,
+             compare_cert_by_name_str, dwType, dwFlags, str);
+            CryptMemFree(str);
          }
      }
      else
@@@ -1449,27 -1582,17 +1582,17 @@@ PCCERT_CONTEXT WINAPI CertFindCertifica
          break;
      default:
          FIXME("find type %08x unimplemented\n", dwType);
-         compare = NULL;
      }
  
-     if (compare)
-     {
-         BOOL matches = FALSE;
-         ret = pPrevCertContext;
-         do {
-             ret = CertEnumCertificatesInStore(hCertStore, ret);
-             if (ret)
-                 matches = compare(ret, dwType, dwFlags, pvPara);
-         } while (ret != NULL && !matches);
-         if (!ret)
-             SetLastError(CRYPT_E_NOT_FOUND);
-     }
+     if (find)
+         ret = find(hCertStore, dwFlags, dwType, pvPara, pPrevCertContext);
+     else if (compare)
+         ret = cert_compare_certs_in_store(hCertStore, pPrevCertContext,
+          compare, dwType, dwFlags, pvPara);
      else
-     {
-         SetLastError(CRYPT_E_NOT_FOUND);
          ret = NULL;
-     }
 -    if (!ret)
 -        SetLastError(CRYPT_E_NOT_FOUND);
++        if (!ret)
++            SetLastError(CRYPT_E_NOT_FOUND);
      TRACE("returning %p\n", ret);
      return ret;
  }
@@@ -2727,7 -2893,10 +2893,10 @@@ static void CRYPT_MakeCertInfo(PCERT_IN
      assert(pSubjectIssuerBlob);
      assert(pubKey);
  
 -        info->dwVersion = CERT_V3;
+     if (pExtensions && pExtensions->cExtension)
 +    info->dwVersion = CERT_V3;
+     else
+         info->dwVersion = CERT_V1;
      info->SerialNumber.cbData = pSerialNumber->cbData;
      info->SerialNumber.pbData = pSerialNumber->pbData;
      if (pSignatureAlgorithm)
@@@ -84,23 -100,11 +100,11 @@@ static BOOL CRYPT_CheckRestrictedRoot(H
              cert = CertEnumCertificatesInStore(store, cert);
              if (cert)
              {
-                 size = sizeof(hash);
-                 ret = CertGetCertificateContextProperty(cert, CERT_HASH_PROP_ID,
-                  hash, &size);
-                 if (ret)
-                 {
-                     CRYPT_HASH_BLOB blob = { sizeof(hash), hash };
-                     check = CertFindCertificateInStore(rootStore,
-                      cert->dwCertEncodingType, 0, CERT_FIND_SHA1_HASH, &blob,
-                      NULL);
-                     if (!check)
+                 if (!(check = CRYPT_FindCertInStore(rootStore, cert)))
 -                    ret = FALSE;
 -                else
 -                    CertFreeCertificateContext(check);
 -            }
 +                        ret = FALSE;
 +                    else
 +                        CertFreeCertificateContext(check);
 +                }
-             }
          } while (ret && cert);
          if (cert)
              CertFreeCertificateContext(cert);
@@@ -698,23 -797,29 +797,29 @@@ static void CRYPT_CheckChainNameConstra
          if ((nameConstraints = CRYPT_GetNameConstraints(
           chain->rgpElement[i]->pCertContext->pCertInfo)))
          {
 -                for (j = i - 1; j >= 0; j--)
 -                {
 -                    DWORD errorStatus = 0;
+             if (!CRYPT_IsValidNameConstraint(nameConstraints))
+                 chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
+                  CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT;
+             else
+             {
 +            for (j = i - 1; j >= 0; j--)
 +            {
 +                DWORD errorStatus = 0;
  
 -                    /* According to RFC 3280, self-signed certs don't have name
 -                     * constraints checked unless they're the end cert.
 -                     */
 -                    if (j == 0 || !CRYPT_IsCertificateSelfSigned(
 -                     chain->rgpElement[j]->pCertContext))
 -                    {
 -                        CRYPT_CheckNameConstraints(nameConstraints,
 +                /* According to RFC 3280, self-signed certs don't have name
 +                 * constraints checked unless they're the end cert.
 +                 */
 +                if (j == 0 || !CRYPT_IsCertificateSelfSigned(
 +                 chain->rgpElement[j]->pCertContext))
 +                {
 +                    CRYPT_CheckNameConstraints(nameConstraints,
-                      chain->rgpElement[i]->pCertContext->pCertInfo,
+                          chain->rgpElement[j]->pCertContext->pCertInfo,
 -                         &errorStatus);
 -                        chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
 -                         errorStatus;
 -                    }
 +                     &errorStatus);
 +                    chain->rgpElement[i]->TrustStatus.dwErrorStatus |=
 +                     errorStatus;
                  }
              }
++            }
              LocalFree(nameConstraints);
          }
      }
@@@ -1333,10 -1910,11 +1910,11 @@@ static PCertificateChain CRYPT_BuildAlt
      return alternate;
  }
  
- #define CHAIN_QUALITY_SIGNATURE_VALID 8
- #define CHAIN_QUALITY_TIME_VALID      4
- #define CHAIN_QUALITY_COMPLETE_CHAIN  2
+ #define CHAIN_QUALITY_SIGNATURE_VALID   0x16
+ #define CHAIN_QUALITY_TIME_VALID        8
+ #define CHAIN_QUALITY_COMPLETE_CHAIN    4
+ #define CHAIN_QUALITY_BASIC_CONSTRAINTS 2
 -#define CHAIN_QUALITY_TRUSTED_ROOT      1
 +#define CHAIN_QUALITY_TRUSTED_ROOT    1
  
  #define CHAIN_QUALITY_HIGHEST \
   CHAIN_QUALITY_SIGNATURE_VALID | CHAIN_QUALITY_TIME_VALID | \
@@@ -106,6 -106,37 +106,37 @@@ void Context_AddRef(void *context, size
      PBASE_CONTEXT baseContext = BASE_CONTEXT_FROM_CONTEXT(context, contextSize);
  
      InterlockedIncrement(&baseContext->ref);
 -        }
+     TRACE("%p's ref count is %d\n", context, baseContext->ref);
+     if (baseContext->type == ContextTypeLink)
+     {
+         void *linkedContext = Context_GetLinkedContext(context, contextSize);
+         PBASE_CONTEXT linkedBase = BASE_CONTEXT_FROM_CONTEXT(linkedContext,
+          contextSize);
+         /* Add-ref the linked contexts too */
+         while (linkedContext && linkedBase->type == ContextTypeLink)
+         {
+             InterlockedIncrement(&linkedBase->ref);
+             TRACE("%p's ref count is %d\n", linkedContext, linkedBase->ref);
+             linkedContext = Context_GetLinkedContext(linkedContext,
+              contextSize);
+             if (linkedContext)
+                 linkedBase = BASE_CONTEXT_FROM_CONTEXT(linkedContext,
+                  contextSize);
+             else
+                 linkedBase = NULL;
++}
+         if (linkedContext)
+         {
+             /* It's not a link context, so it wasn't add-ref'ed in the while
+              * loop, so add-ref it here.
+              */
+             linkedBase = BASE_CONTEXT_FROM_CONTEXT(linkedContext,
+              contextSize);
+             InterlockedIncrement(&linkedBase->ref);
+             TRACE("%p's ref count is %d\n", linkedContext, linkedBase->ref);
+         }
+     }
  }
  
  void *Context_GetExtra(const void *context, size_t contextSize)
@@@ -139,26 -170,29 +170,29 @@@ BOOL Context_Release(void *context, siz
   ContextFreeFunc dataContextFree)
  {
      PBASE_CONTEXT base = BASE_CONTEXT_FROM_CONTEXT(context, contextSize);
+     BOOL ret = TRUE;
  
-     if (InterlockedDecrement(&base->ref) == 0)
+     if (base->ref <= 0)
      {
-         TRACE("freeing %p\n", context);
-         switch (base->type)
+         ERR("%p's ref count is %d\n", context, base->ref);
+         return FALSE;
+     }
+     if (base->type == ContextTypeLink)
 -    {
 -        /* The linked context is of the same type as this, so release
 -         * it as well, using the same offset and data free function.
 -         */
 +        {
-         case ContextTypeData:
-             ContextPropertyList_Free(((PDATA_CONTEXT)base)->properties);
-             dataContextFree(context);
-             break;
-         case ContextTypeLink:
 +            /* The linked context is of the same type as this, so release
 +             * it as well, using the same offset and data free function.
 +             */
-             Context_Release(CONTEXT_FROM_BASE_CONTEXT(
+         ret = Context_Release(CONTEXT_FROM_BASE_CONTEXT(
 -         ((PLINK_CONTEXT)base)->linked, contextSize), contextSize,
 -         dataContextFree);
 -    }
 +             ((PLINK_CONTEXT)base)->linked, contextSize), contextSize,
 +             dataContextFree);
-             break;
-         default:
-             assert(0);
++        }
+     if (InterlockedDecrement(&base->ref) == 0)
+     {
+         TRACE("freeing %p\n", context);
+         if (base->type == ContextTypeData)
+         {
+             ContextPropertyList_Free(((PDATA_CONTEXT)base)->properties);
+             dataContextFree(context);
          }
          CryptMemFree(context);
      }
@@@ -278,14 -313,21 +313,21 @@@ void *ContextList_Enum(struct ContextLi
      return ret;
  }
  
void ContextList_Delete(struct ContextList *list, void *context)
BOOL ContextList_Remove(struct ContextList *list, void *context)
  {
      struct list *entry = ContextList_ContextToEntry(list, context);
+     BOOL inList = FALSE;
  
      EnterCriticalSection(&list->cs);
 -        list_remove(entry);
+     if (!list_empty(entry))
+     {
 +    list_remove(entry);
+         inList = TRUE;
+     }
      LeaveCriticalSection(&list->cs);
-     list->contextInterface->free(context);
+     if (inList)
+         list_init(entry);
+     return inList;
  }
  
  static void ContextList_Empty(struct ContextList *list)
@@@ -228,7 -228,8 +228,8 @@@ PCCRL_CONTEXT WINAPI CertGetCRLFromStor
  PCCRL_CONTEXT WINAPI CertDuplicateCRLContext(PCCRL_CONTEXT pCrlContext)
  {
      TRACE("(%p)\n", pCrlContext);
 -        Context_AddRef((void *)pCrlContext, sizeof(CRL_CONTEXT));
+     if (pCrlContext)
 +    Context_AddRef((void *)pCrlContext, sizeof(CRL_CONTEXT));
      return pCrlContext;
  }
  
@@@ -455,7 -453,8 +453,8 @@@ end
  PCCTL_CONTEXT WINAPI CertDuplicateCTLContext(PCCTL_CONTEXT pCtlContext)
  {
      TRACE("(%p)\n", pCtlContext);
 -        Context_AddRef((void *)pCtlContext, sizeof(CTL_CONTEXT));
+     if (pCtlContext)
 +    Context_AddRef((void *)pCtlContext, sizeof(CTL_CONTEXT));
      return pCtlContext;
  }
  
@@@ -361,8 -357,13 +357,13 @@@ static BOOL CRYPT_AsnDecodeSequenceItem
                           : NULL, &items[i].size, &itemDecoded);
                          if (ret)
                          {
 -                                /* Account for alignment padding */
 -                                items[i].size = ALIGN_DWORD_PTR(items[i].size);
+                             if (items[i].size < items[i].minSize)
+                                 items[i].size = items[i].minSize;
+                             else if (items[i].size > items[i].minSize)
+                             {
 +                            /* Account for alignment padding */
 +                            items[i].size = ALIGN_DWORD_PTR(items[i].size);
+                             }
                              TRACE("item %d size: %d\n", i, items[i].size);
                              if (nextData && items[i].hasPointer &&
                               items[i].size > items[i].minSize)
@@@ -1373,29 -1450,21 +1450,21 @@@ static BOOL WINAPI CRYPT_AsnDecodeExten
  {
      BOOL ret = TRUE;
  
+     TRACE("%p, %d, %08x, %p, %d\n", pbEncoded, cbEncoded, dwFlags,
+      pvStructInfo, pvStructInfo ? *pcbStructInfo : 0);
      __TRY
      {
-         ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
-          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pcbStructInfo, NULL);
-         if (ret && pvStructInfo)
-         {
-             ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
-              pcbStructInfo, *pcbStructInfo);
-             if (ret)
-             {
-                 CERT_EXTENSIONS *exts;
-                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
-                     pvStructInfo = *(BYTE **)pvStructInfo;
-                 exts = pvStructInfo;
-                 exts->rgExtension = (CERT_EXTENSION *)((BYTE *)exts +
-                  sizeof(CERT_EXTENSIONS));
-                 ret = CRYPT_AsnDecodeExtensionsInternal(pbEncoded, cbEncoded,
-                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
-                  pcbStructInfo, NULL);
+         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+          offsetof(CERT_EXTENSIONS, cExtension),
+          offsetof(CERT_EXTENSIONS, rgExtension),
+          sizeof(CERT_EXTENSIONS),
+          CRYPT_AsnDecodeExtension, sizeof(CERT_EXTENSION), TRUE,
+          offsetof(CERT_EXTENSION, pszObjId) };
+         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+          dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
 -    }
 +            }
-         }
-     }
      __EXCEPT_PAGE_FAULT
      {
          SetLastError(STATUS_ACCESS_VIOLATION);
@@@ -1833,11 -1902,34 +1902,34 @@@ static BOOL WINAPI CRYPT_AsnDecodeName(
      __TRY
      {
          struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+          offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
+          sizeof(CERT_NAME_INFO),
           CRYPT_AsnDecodeRdn, sizeof(CERT_RDN), TRUE,
           offsetof(CERT_RDN, rgRDNAttr) };
+         DWORD bytesNeeded;
+         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded,
+          NULL);
+         if (ret)
+         {
+             if (!pvStructInfo)
+                 *pcbStructInfo = bytesNeeded;
+             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+              pvStructInfo, pcbStructInfo, bytesNeeded)))
+             {
+                 CERT_NAME_INFO *info;
  
-         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
-          pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
+                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+                     pvStructInfo = *(BYTE **)pvStructInfo;
+                 info = pvStructInfo;
+                 info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
+                  sizeof(CERT_NAME_INFO));
+                 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
+                  &bytesNeeded, NULL);
 -            }
++    }
+         }
      }
      __EXCEPT_PAGE_FAULT
      {
@@@ -1905,11 -1997,34 +1997,34 @@@ static BOOL WINAPI CRYPT_AsnDecodeUnico
      __TRY
      {
          struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+          offsetof(CERT_NAME_INFO, cRDN), offsetof(CERT_NAME_INFO, rgRDN),
+          sizeof(CERT_NAME_INFO),
           CRYPT_AsnDecodeUnicodeRdn, sizeof(CERT_RDN), TRUE,
           offsetof(CERT_RDN, rgRDNAttr) };
+         DWORD bytesNeeded;
  
-         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
-          pDecodePara, pvStructInfo, pcbStructInfo, NULL, NULL);
+         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+          dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded,
+          NULL);
+         if (ret)
+         {
+             if (!pvStructInfo)
+                 *pcbStructInfo = bytesNeeded;
+             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
+              pvStructInfo, pcbStructInfo, bytesNeeded)))
+             {
+                 CERT_NAME_INFO *info;
+                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
+                     pvStructInfo = *(BYTE **)pvStructInfo;
+                 info = pvStructInfo;
+                 info->rgRDN = (CERT_RDN *)((BYTE *)pvStructInfo +
+                  sizeof(CERT_NAME_INFO));
+                 ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+                  dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
+                  &bytesNeeded, NULL);
 -            }
++    }
+         }
      }
      __EXCEPT_PAGE_FAULT
      {
@@@ -2202,35 -2338,16 +2338,16 @@@ static BOOL WINAPI CRYPT_AsnDecodeSMIME
  
      __TRY
      {
-         DWORD bytesNeeded;
-         if (!cbEncoded)
-             SetLastError(CRYPT_E_ASN1_EOD);
-         else if (pbEncoded[0] != ASN_SEQUENCEOF)
-             SetLastError(CRYPT_E_ASN1_CORRUPT);
-         else if ((ret = CRYPT_AsnDecodeSMIMECapabilitiesInternal(pbEncoded,
-          cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
-          NULL)))
-         {
-             if (!pvStructInfo)
-                 *pcbStructInfo = bytesNeeded;
-             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
-              pvStructInfo, pcbStructInfo, bytesNeeded)))
-             {
-                 PCRYPT_SMIME_CAPABILITIES capabilities;
-                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
-                     pvStructInfo = *(BYTE **)pvStructInfo;
-                 capabilities = pvStructInfo;
-                 capabilities->rgCapability =
-                  (PCRYPT_SMIME_CAPABILITY)((BYTE *)pvStructInfo +
-                  sizeof(CRYPT_SMIME_CAPABILITIES));
-                 ret = CRYPT_AsnDecodeSMIMECapabilitiesInternal(pbEncoded,
-                  cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
-                  &bytesNeeded, NULL);
+         struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
+          offsetof(CRYPT_SMIME_CAPABILITIES, cCapability),
+          offsetof(CRYPT_SMIME_CAPABILITIES, rgCapability),
+          sizeof(CRYPT_SMIME_CAPABILITIES),
+          CRYPT_AsnDecodeSMIMECapability, sizeof(CRYPT_SMIME_CAPABILITY), TRUE,
+          offsetof(CRYPT_SMIME_CAPABILITY, pszObjId) };
+         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+          dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
 -    }
 +            }
-         }
-     }
      __EXCEPT_PAGE_FAULT
      {
          SetLastError(STATUS_ACCESS_VIOLATION);
@@@ -2672,34 -2811,15 +2811,15 @@@ static BOOL WINAPI CRYPT_AsnDecodePKCSA
  
      __TRY
      {
-         DWORD bytesNeeded;
+         struct AsnArrayDescriptor arrayDesc = { ASN_CONSTRUCTOR | ASN_SETOF,
+          offsetof(CRYPT_ATTRIBUTES, cAttr), offsetof(CRYPT_ATTRIBUTES, rgAttr),
+          sizeof(CRYPT_ATTRIBUTES),
+          CRYPT_AsnDecodePKCSAttributeInternal, sizeof(CRYPT_ATTRIBUTE),
+          TRUE, offsetof(CRYPT_ATTRIBUTE, pszObjId) };
  
-         if (!cbEncoded)
-             SetLastError(CRYPT_E_ASN1_EOD);
-         else if (pbEncoded[0] != (ASN_CONSTRUCTOR | ASN_SETOF))
-             SetLastError(CRYPT_E_ASN1_CORRUPT);
-         else if ((ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
-          cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, &bytesNeeded,
-          NULL)))
-         {
-             if (!pvStructInfo)
-                 *pcbStructInfo = bytesNeeded;
-             else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
-              pvStructInfo, pcbStructInfo, bytesNeeded)))
-             {
-                 PCRYPT_ATTRIBUTES attrs;
-                 if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
-                     pvStructInfo = *(BYTE **)pvStructInfo;
-                 attrs = pvStructInfo;
-                 attrs->rgAttr = (PCRYPT_ATTRIBUTE)((BYTE *)pvStructInfo +
-                  sizeof(CRYPT_ATTRIBUTES));
-                 ret = CRYPT_AsnDecodePKCSAttributesInternal(pbEncoded,
-                  cbEncoded, dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, pvStructInfo,
-                  &bytesNeeded, NULL);
+         ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded,
+          dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
 -    }
 +            }
-         }
-     }
      __EXCEPT_PAGE_FAULT
      {
          SetLastError(STATUS_ACCESS_VIOLATION);
@@@ -2870,7 -2990,13 +2990,13 @@@ static BOOL CRYPT_AsnDecodeAltNameEntry
          case 1: /* rfc822Name */
          case 2: /* dNSName */
          case 6: /* uniformResourceIdentifier */
 -                bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
+             if (memchr(pbEncoded + 1 + lenBytes, 0, dataLen))
+             {
+                 SetLastError(CRYPT_E_ASN1_RULE);
+                 ret = FALSE;
+             }
+             else
 +            bytesNeeded += (dataLen + 1) * sizeof(WCHAR);
              break;
          case 4: /* directoryName */
          case 7: /* iPAddress */
@@@ -873,9 -873,18 +873,18 @@@ static BOOL CRYPT_RemoveStringFromMulti
      {
          DWORD len = CRYPT_GetMultiStringCharacterLen(multi);
  
 -            /* Copy remainder of string "left" */
 -            memmove(spotToRemove, spotToRemove + lstrlenW(toRemove) + 1,
 -             (len - (spotToRemove - multi)) * sizeof(WCHAR));
+         if (spotToRemove + lstrlenW(toRemove) + 2 >= multi + len)
+         {
+             /* Removing last string in list, terminate multi string directly */
+             *spotToRemove = 0;
+             *(spotToRemove + 1) = 0;
+         }
+         else
+         {
 +        /* Copy remainder of string "left" */
 +        memmove(spotToRemove, spotToRemove + lstrlenW(toRemove) + 1,
 +         (len - (spotToRemove - multi)) * sizeof(WCHAR));
+         }
          ret = TRUE;
      }
      else
@@@ -495,8 -499,18 +499,18 @@@ static BOOL CRYPT_ReadSerializedStore(v
                                   CERT_STORE_ADD_NEW, &context);
                              }
                              else
-                                 ret = CRYPT_ReadContextProp(contextInterface,
-                                  context, &propHdr, buf, read);
+                             {
+                                 if (!contextInterface)
+                                 {
+                                     WARN("prop id %d before a context id\n",
+                                      propHdr.propID);
+                                     ret = FALSE;
 -                                }
++                        }
+                                 else
+                                     ret = CRYPT_ReadContextProp(
+                                      contextInterface, context, &propHdr, buf,
+                                      read);
 -                            }
++                    }
                          }
                      }
                      else
@@@ -217,37 -252,79 +252,79 @@@ GpStatus WINGDIPAPI GdipCreateHatchBrus
      *brush = GdipAlloc(sizeof(GpHatch));
      if (!*brush) return OutOfMemory;
  
-     switch (hatchstyle)
+     if (hatchstyle < sizeof(HatchBrushes) / sizeof(HatchBrushes[0]))
      {
-         case HatchStyleHorizontal:
-         case HatchStyleVertical:
-         case HatchStyleForwardDiagonal:
-         case HatchStyleBackwardDiagonal:
-         case HatchStyleCross:
-         case HatchStyleDiagonalCross:
-             /* Brushes that map to BS_HATCHED */
-             (*brush)->brush.lb.lbStyle = BS_HATCHED;
-             (*brush)->brush.lb.lbColor = fgcol;
-             (*brush)->brush.lb.lbHatch = HatchStyleToHatch(hatchstyle);
-             break;
+         HBITMAP hbmp;
+         HDC hdc;
+         BITMAPINFOHEADER bmih;
+         DWORD* bits;
+         int x, y;
  
-         default:
+         hdc = CreateCompatibleDC(0);
+         if (hdc)
+         {
+             bmih.biSize = sizeof(bmih);
+             bmih.biWidth = 8;
+             bmih.biHeight = 8;
+             bmih.biPlanes = 1;
+             bmih.biBitCount = 32;
+             bmih.biCompression = BI_RGB;
+             bmih.biSizeImage = 0;
+             hbmp = CreateDIBSection(hdc, (BITMAPINFO*)&bmih, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
+             if (hbmp)
+             {
+                 for (y=0; y<8; y++)
+                     for (x=0; x<8; x++)
+                         if ((HatchBrushes[hatchstyle][y] & (0x80 >> x)) != 0)
+                             bits[y*8+x] = forecol;
+                         else
+                             bits[y*8+x] = backcol;
+             }
+             else
+                 stat = GenericError;
+             DeleteDC(hdc);
+         }
+         else
+             stat = GenericError;
+         if (stat == Ok)
+         {
+             (*brush)->brush.lb.lbStyle = BS_PATTERN;
+             (*brush)->brush.lb.lbColor = 0;
+             (*brush)->brush.lb.lbHatch = (ULONG_PTR)hbmp;
+             (*brush)->brush.gdibrush = CreateBrushIndirect(&(*brush)->brush.lb);
+             DeleteObject(hbmp);
+         }
+     }
+     else
+     {
 -        FIXME("Unimplemented hatch style %d\n", hatchstyle);
 +            FIXME("Unimplemented hatch style %d\n", hatchstyle);
  
 -        (*brush)->brush.lb.lbStyle = BS_SOLID;
 -        (*brush)->brush.lb.lbColor = fgcol;
 -        (*brush)->brush.lb.lbHatch = 0;
 +            (*brush)->brush.lb.lbStyle = BS_SOLID;
 +            (*brush)->brush.lb.lbColor = fgcol;
 +            (*brush)->brush.lb.lbHatch = 0;
-             break;
+         (*brush)->brush.gdibrush = CreateBrushIndirect(&(*brush)->brush.lb);
      }
  
-     (*brush)->brush.gdibrush = CreateBrushIndirect(&(*brush)->brush.lb);
+     if (stat == Ok)
+     {
 -        (*brush)->brush.bt = BrushTypeHatchFill;
 -        (*brush)->forecol = forecol;
 -        (*brush)->backcol = backcol;
 -        (*brush)->hatchstyle = hatchstyle;
 +    (*brush)->brush.bt = BrushTypeHatchFill;
 +    (*brush)->forecol = forecol;
 +    (*brush)->backcol = backcol;
 +    (*brush)->hatchstyle = hatchstyle;
+     }
+     else
+     {
+         GdipFree(*brush);
+         *brush = NULL;
+     }
  
-     return Ok;
+     return stat;
  }
  
  /******************************************************************************
@@@ -221,23 -221,21 +221,21 @@@ INT arc2polybezier(GpPointF * points, R
      /* start_angle and end_angle are the iterative variables */
      start_angle = startAngle;
  
-     for(i = 0; i < count - 1; i += 3){
+     for(i = 0; i < MAX_ARC_PTS - 1; i += 3){
          /* check if we've overshot the end angle */
          if( sweepAngle > 0.0 )
+         {
+             if (start_angle >= endAngle) break;
              end_angle = min(start_angle + M_PI_2, endAngle);
+         }
          else
+         {
+             if (start_angle <= endAngle) break;
              end_angle = max(start_angle - M_PI_2, endAngle);
+         }
  
 -            add_arc_part(&points[i], x1, y1, x2, y2, start_angle, end_angle, i == 0);
+         if (points)
 +        add_arc_part(&points[i], x1, y1, x2, y2, start_angle, end_angle, i == 0);
  
          start_angle += M_PI_2 * (sweepAngle < 0.0 ? -1.0 : 1.0);
      }
        <library>ole32</library>
        <library>user32</library>
        <library>gdi32</library>
-       <library>kernel32</library>
        <library>windowscodecs</library>
        <library>ntdll</library>
 +      <if property="ARCH" value="amd64">
 +              <library>crt</library>
 +      </if>
  </module>
  </group>
@@@ -220,7 -220,27 +220,27 @@@ static ARGB blend_line_gradient(GpLineG
          blendfac = (left_blendfac * (right_blendpos - position) +
                      right_blendfac * (position - left_blendpos)) / range;
      }
 -        return blend_colors(brush->startcolor, brush->endcolor, blendfac);
+     if (brush->pblendcount == 0)
 -    }
 +    return blend_colors(brush->startcolor, brush->endcolor, blendfac);
+     else
+     {
+         int i=1;
+         ARGB left_blendcolor, right_blendcolor;
+         REAL left_blendpos, right_blendpos;
+         /* locate the blend colors surrounding this position */
+         while (blendfac > brush->pblendpos[i])
+             i++;
+         /* interpolate between the blend colors */
+         left_blendpos = brush->pblendpos[i-1];
+         left_blendcolor = brush->pblendcolor[i-1];
+         right_blendpos = brush->pblendpos[i];
+         right_blendcolor = brush->pblendcolor[i];
+         blendfac = (blendfac - left_blendpos) / (right_blendpos - left_blendpos);
+         return blend_colors(left_blendcolor, right_blendcolor, blendfac);
++}
  }
  
  static void brush_fill_path(GpGraphics *graphics, GpBrush* brush)
@@@ -97,35 -210,207 +210,207 @@@ static inline void getpixel_64bppPARGB(
  GpStatus WINGDIPAPI GdipBitmapGetPixel(GpBitmap* bitmap, INT x, INT y,
      ARGB *color)
  {
-     static int calls;
+     BYTE r, g, b, a;
+     BYTE *row;
      TRACE("%p %d %d %p\n", bitmap, x, y, color);
  
-     if(!bitmap || !color)
+     if(!bitmap || !color ||
+        x < 0 || y < 0 || x >= bitmap->width || y >= bitmap->height)
          return InvalidParameter;
  
-     if(!(calls++))
-         FIXME("not implemented\n");
-     *color = 0xdeadbeef;
+     row = bitmap->bits+bitmap->stride*y;
  
 -            return NotImplemented;
 -    }
+     switch (bitmap->format)
+     {
+         case PixelFormat16bppGrayScale:
+             getpixel_16bppGrayScale(&r,&g,&b,&a,row,x);
+             break;
+         case PixelFormat16bppRGB555:
+             getpixel_16bppRGB555(&r,&g,&b,&a,row,x);
+             break;
+         case PixelFormat16bppRGB565:
+             getpixel_16bppRGB565(&r,&g,&b,&a,row,x);
+             break;
+         case PixelFormat16bppARGB1555:
+             getpixel_16bppARGB1555(&r,&g,&b,&a,row,x);
+             break;
+         case PixelFormat24bppRGB:
+             getpixel_24bppRGB(&r,&g,&b,&a,row,x);
+             break;
+         case PixelFormat32bppRGB:
+             getpixel_32bppRGB(&r,&g,&b,&a,row,x);
+             break;
+         case PixelFormat32bppARGB:
+             getpixel_32bppARGB(&r,&g,&b,&a,row,x);
+             break;
+         case PixelFormat32bppPARGB:
+             getpixel_32bppPARGB(&r,&g,&b,&a,row,x);
+             break;
+         case PixelFormat48bppRGB:
+             getpixel_48bppRGB(&r,&g,&b,&a,row,x);
+             break;
+         case PixelFormat64bppARGB:
+             getpixel_64bppARGB(&r,&g,&b,&a,row,x);
+             break;
+         case PixelFormat64bppPARGB:
+             getpixel_64bppPARGB(&r,&g,&b,&a,row,x);
+             break;
+         default:
+             FIXME("not implemented for format 0x%x\n", bitmap->format);
 +    return NotImplemented;
 +}
  
+     *color = a<<24|r<<16|g<<8|b;
+     return Ok;
+ }
+ static inline void setpixel_16bppGrayScale(BYTE r, BYTE g, BYTE b, BYTE a,
+     BYTE *row, UINT x)
+ {
+     *((WORD*)(row)+x) = (r+g+b)*85;
+ }
+ static inline void setpixel_16bppRGB555(BYTE r, BYTE g, BYTE b, BYTE a,
+     BYTE *row, UINT x)
+ {
+     *((WORD*)(row)+x) = (r<<7&0x7c00)|
+                         (g<<2&0x03e0)|
+                         (b>>3&0x001f);
+ }
+ static inline void setpixel_16bppRGB565(BYTE r, BYTE g, BYTE b, BYTE a,
+     BYTE *row, UINT x)
+ {
+     *((WORD*)(row)+x) = (r<<8&0xf800)|
+                          (g<<3&0x07e0)|
+                          (b>>3&0x001f);
+ }
+ static inline void setpixel_16bppARGB1555(BYTE r, BYTE g, BYTE b, BYTE a,
+     BYTE *row, UINT x)
+ {
+     *((WORD*)(row)+x) = (a<<8&0x8000)|
+                         (r<<7&0x7c00)|
+                         (g<<2&0x03e0)|
+                         (b>>3&0x001f);
+ }
+ static inline void setpixel_24bppRGB(BYTE r, BYTE g, BYTE b, BYTE a,
+     BYTE *row, UINT x)
+ {
+     row[x*3+2] = r;
+     row[x*3+1] = g;
+     row[x*3] = b;
+ }
+ static inline void setpixel_32bppRGB(BYTE r, BYTE g, BYTE b, BYTE a,
+     BYTE *row, UINT x)
+ {
+     *((DWORD*)(row)+x) = (r<<16)|(g<<8)|b;
+ }
+ static inline void setpixel_32bppARGB(BYTE r, BYTE g, BYTE b, BYTE a,
+     BYTE *row, UINT x)
+ {
+     *((DWORD*)(row)+x) = (a<<24)|(r<<16)|(g<<8)|b;
+ }
+ static inline void setpixel_32bppPARGB(BYTE r, BYTE g, BYTE b, BYTE a,
+     BYTE *row, UINT x)
+ {
+     r = r * a / 255;
+     g = g * a / 255;
+     b = b * a / 255;
+     *((DWORD*)(row)+x) = (a<<24)|(r<<16)|(g<<8)|b;
+ }
+ static inline void setpixel_48bppRGB(BYTE r, BYTE g, BYTE b, BYTE a,
+     BYTE *row, UINT x)
+ {
+     row[x*6+5] = row[x*6+4] = r;
+     row[x*6+3] = row[x*6+2] = g;
+     row[x*6+1] = row[x*6] = b;
+ }
+ static inline void setpixel_64bppARGB(BYTE r, BYTE g, BYTE b, BYTE a,
+     BYTE *row, UINT x)
+ {
+     UINT64 a64=a, r64=r, g64=g, b64=b;
+     *((UINT64*)(row)+x) = (a64<<56)|(a64<<48)|(r64<<40)|(r64<<32)|(g64<<24)|(g64<<16)|(b64<<8)|b64;
+ }
+ static inline void setpixel_64bppPARGB(BYTE r, BYTE g, BYTE b, BYTE a,
+     BYTE *row, UINT x)
+ {
+     UINT64 a64, r64, g64, b64;
+     a64 = a * 257;
+     r64 = r * a / 255;
+     g64 = g * a / 255;
+     b64 = b * a / 255;
+     *((UINT64*)(row)+x) = (a64<<48)|(r64<<32)|(g64<<16)|b64;
+ }
  GpStatus WINGDIPAPI GdipBitmapSetPixel(GpBitmap* bitmap, INT x, INT y,
      ARGB color)
  {
-     static int calls;
+     BYTE a, r, g, b;
+     BYTE *row;
      TRACE("bitmap:%p, x:%d, y:%d, color:%08x\n", bitmap, x, y, color);
  
-     if(!bitmap)
+     if(!bitmap || x < 0 || y < 0 || x >= bitmap->width || y >= bitmap->height)
          return InvalidParameter;
  
-     if(!(calls++))
-         FIXME("not implemented\n");
+     a = color>>24;
+     r = color>>16;
+     g = color>>8;
+     b = color;
+     row = bitmap->bits + bitmap->stride * y;
  
 -            return NotImplemented;
 -    }
+     switch (bitmap->format)
+     {
+         case PixelFormat16bppGrayScale:
+             setpixel_16bppGrayScale(r,g,b,a,row,x);
+             break;
+         case PixelFormat16bppRGB555:
+             setpixel_16bppRGB555(r,g,b,a,row,x);
+             break;
+         case PixelFormat16bppRGB565:
+             setpixel_16bppRGB565(r,g,b,a,row,x);
+             break;
+         case PixelFormat16bppARGB1555:
+             setpixel_16bppARGB1555(r,g,b,a,row,x);
+             break;
+         case PixelFormat24bppRGB:
+             setpixel_24bppRGB(r,g,b,a,row,x);
+             break;
+         case PixelFormat32bppRGB:
+             setpixel_32bppRGB(r,g,b,a,row,x);
+             break;
+         case PixelFormat32bppARGB:
+             setpixel_32bppARGB(r,g,b,a,row,x);
+             break;
+         case PixelFormat32bppPARGB:
+             setpixel_32bppPARGB(r,g,b,a,row,x);
+             break;
+         case PixelFormat48bppRGB:
+             setpixel_48bppRGB(r,g,b,a,row,x);
+             break;
+         case PixelFormat64bppARGB:
+             setpixel_64bppARGB(r,g,b,a,row,x);
+             break;
+         case PixelFormat64bppPARGB:
+             setpixel_64bppPARGB(r,g,b,a,row,x);
+             break;
+         default:
+             FIXME("not implemented for format 0x%x\n", bitmap->format);
 +    return NotImplemented;
 +}
  
+     return Ok;
+ }
  /* This function returns a pointer to an array of pixels that represents the
   * bitmap. The *entire* bitmap is locked according to the lock mode specified by
   * flags.  It is correct behavior that a user who calls this function with write
@@@ -1507,105 -1779,37 +1779,37 @@@ static GpStatus decode_image_icon(IStre
      return decode_image_wic(stream, &CLSID_WICIcoDecoder, image);
  }
  
- static GpStatus decode_image_jpeg(IStream* stream, REFCLSID clsid, GpImage **image)
- {
-     return decode_image_wic(stream, &CLSID_WICJpegDecoder, image);
- }
- static GpStatus decode_image_gif(IStream* stream, REFCLSID clsid, GpImage **image)
- {
-     return decode_image_wic(stream, &CLSID_WICGifDecoder, image);
- }
- static GpStatus decode_image_olepicture_bitmap(IStream* stream, REFCLSID clsid, GpImage **image)
+ static GpStatus decode_image_bmp(IStream* stream, REFCLSID clsid, GpImage **image)
  {
-     IPicture *pic;
-     BITMAPINFO *pbmi;
-     BITMAPCOREHEADER* bmch;
-     HBITMAP hbm;
-     HDC hdc;
+     GpStatus status;
+     GpBitmap* bitmap;
  
-     TRACE("%p %p\n", stream, image);
+     status = decode_image_wic(stream, &CLSID_WICBmpDecoder, image);
  
-     if(!stream || !image)
-         return InvalidParameter;
+     bitmap = (GpBitmap*)*image;
  
-     if(OleLoadPicture(stream, 0, FALSE, &IID_IPicture,
-         (LPVOID*) &pic) != S_OK){
-         TRACE("Could not load picture\n");
-         return GenericError;
+     if (status == Ok && bitmap->format == PixelFormat32bppARGB)
 -    {
++{
+         /* WIC supports bmp files with alpha, but gdiplus does not */
+         bitmap->format = PixelFormat32bppRGB;
      }
  
-     pbmi = GdipAlloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
-     if (!pbmi)
-         return OutOfMemory;
-     *image = GdipAlloc(sizeof(GpBitmap));
-     if(!*image){
-         GdipFree(pbmi);
-         return OutOfMemory;
+     return status;
 -}
 +    }
-     (*image)->type = ImageTypeBitmap;
-     (*((GpBitmap**) image))->width = ipicture_pixel_width(pic);
-     (*((GpBitmap**) image))->height = ipicture_pixel_height(pic);
  
-     /* get the pixel format */
-     IPicture_get_Handle(pic, (OLE_HANDLE*)&hbm);
-     IPicture_get_CurDC(pic, &hdc);
-     (*((GpBitmap**) image))->hbitmap = hbm;
-     (*((GpBitmap**) image))->hdc = hdc;
-     (*((GpBitmap**) image))->bits = NULL;
-     bmch = (BITMAPCOREHEADER*) (&pbmi->bmiHeader);
-     bmch->bcSize = sizeof(BITMAPCOREHEADER);
-     if(!hdc){
-         HBITMAP old;
-         hdc = CreateCompatibleDC(0);
-         old = SelectObject(hdc, hbm);
-         GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS);
-         SelectObject(hdc, old);
-         DeleteDC(hdc);
+ static GpStatus decode_image_jpeg(IStream* stream, REFCLSID clsid, GpImage **image)
+ {
+     return decode_image_wic(stream, &CLSID_WICJpegDecoder, image);
 -}
 +    }
-     else
-         GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS);
  
    switch(bmch->bcBitCount)
static GpStatus decode_image_png(IStream* stream, REFCLSID clsid, GpImage **image)
 -{
 +    {
-         case 1:
-             (*((GpBitmap**) image))->format = PixelFormat1bppIndexed;
-             break;
-         case 4:
-             (*((GpBitmap**) image))->format = PixelFormat4bppIndexed;
-             break;
-         case 8:
-             (*((GpBitmap**) image))->format = PixelFormat8bppIndexed;
-             break;
-         case 16:
-             (*((GpBitmap**) image))->format = PixelFormat16bppRGB565;
-             break;
-         case 24:
-             (*((GpBitmap**) image))->format = PixelFormat24bppRGB;
-             break;
-         case 32:
-             (*((GpBitmap**) image))->format = PixelFormat32bppRGB;
-             break;
-         case 48:
-             (*((GpBitmap**) image))->format = PixelFormat48bppRGB;
-             break;
-         default:
-             FIXME("Bit depth %d is not fully supported yet\n", bmch->bcBitCount);
-             (*((GpBitmap**) image))->format = (bmch->bcBitCount << 8) | PixelFormatGDI;
-             break;
+     return decode_image_wic(stream, &CLSID_WICPngDecoder, image);
 -}
 +    }
  
-     GdipFree(pbmi);
-     (*image)->picture = pic;
-     (*image)->flags   = ImageFlagsNone;
-     return Ok;
+ static GpStatus decode_image_gif(IStream* stream, REFCLSID clsid, GpImage **image)
+ {
+     return decode_image_wic(stream, &CLSID_WICGifDecoder, image);
  }
  
  static GpStatus decode_image_olepicture_metafile(IStream* stream, REFCLSID clsid, GpImage **image)
@@@ -1715,7 -1919,15 +1919,15 @@@ GpStatus WINGDIPAPI GdipLoadImageFromSt
      if (FAILED(hr)) return hresult_to_status(hr);
  
      /* call on the image decoder to do the real work */
-     return codec->decode_func(stream, &codec->info.Clsid, image);
+     stat = codec->decode_func(stream, &codec->info.Clsid, image);
+     /* take note of the original data format */
+     if (stat == Ok)
+     {
+         memcpy(&(*image)->format, &codec->info.FormatID, sizeof(GUID));
 -    }
++}
+     return stat;
  }
  
  /* FIXME: no ICM */
@@@ -157,7 -151,7 +157,8 @@@ static LON
  BasepCheckForReadOnlyResource(IN PVOID Ptr)
  {
      PVOID Data;
--    ULONG Size, OldProtect;
++    SIZE_T Size;
++      ULONG OldProtect;
      MEMORY_BASIC_INFORMATION mbi;
      NTSTATUS Status;
      LONG Ret = EXCEPTION_CONTINUE_SEARCH;
Simple merge
@@@ -5,21 -5,14 +5,21 @@@
  @ stdcall AddAtomW(wstr)
  @ stdcall AddConsoleAliasA(str str str) ;check
  @ stdcall AddConsoleAliasW(wstr wstr wstr) ;check
 +;@ stdcall -arch=x86_64 AddIntegrityLabelToBoundaryDescriptor ; Win 7
  @ stdcall AddLocalAlternateComputerNameA(str ptr)
  @ stdcall AddLocalAlternateComputerNameW(wstr ptr)
- ;@ stdcall AddRefActCtx(ptr)
+ @ stdcall AddRefActCtx(ptr)
 +;@ stdcall AddSIDToBoundaryDescriptor ; Win 7
 +;@ stdcall AddSecureMemoryCacheCallback ; Win 7
  @ stdcall AddVectoredContinueHandler(long ptr) ntdll.RtlAddVectoredContinueHandler
  @ stdcall AddVectoredExceptionHandler(long ptr) ntdll.RtlAddVectoredExceptionHandler
 +;@ stdcall AdjustCalendarDate ; Win 7
  @ stdcall AllocConsole()
 -@ stub AllocLSCallback ; missing in XP SP3 and 2003 R2
 +@ stub AllocLSCallback ; missing in XP SP3 and 2003 R2 and Win 7
  @ stdcall AllocateUserPhysicalPages(long ptr ptr)
 +;@ stdcall AllocateUserPhysicalPagesNuma ; Win 7
 +;@ stdcall ApplicationRecoveryFinished ; Win 7
 +;@ stdcall ApplicationRecoveryInProgress ; Win 7
  @ stdcall AreFileApisANSI()
  @ stdcall AssignProcessToJobObject(ptr ptr)
  @ stdcall AttachConsole(long)
  @ stdcall CopyFileA(str str long)
  @ stdcall CopyFileExA (str str ptr ptr ptr long)
  @ stdcall CopyFileExW (wstr wstr ptr ptr ptr long)
 +;@ stdcall CopyFileTransactedA ; Win 7
 +;@ stdcall CopyFileTransactedW ; Win 7
  @ stdcall CopyFileW(wstr wstr long)
  @ stdcall CopyLZFile(long long) LZCopy
- ;@ stdcall CreateActCtxA(ptr)
- ;@ stdcall CreateActCtxW(ptr)
+ @ stdcall CreateActCtxA(ptr)
+ @ stdcall CreateActCtxW(ptr)
 +;@ stdcall CreateBoundaryDescriptorA ; Win 7
 +;@ stdcall CreateBoundaryDescriptorW ; Win 7
  @ stdcall CreateConsoleScreenBuffer(long long ptr long ptr)
  @ stdcall CreateDirectoryA(str ptr)
  @ stdcall CreateDirectoryExA(str str ptr)
  @ stdcall CreateTimerQueue ()
  @ stdcall CreateTimerQueueTimer(ptr long ptr ptr long long long)
  @ stdcall CreateToolhelp32Snapshot(long long)
 -@ stdcall CreateVirtualBuffer(long long long)
 +;@ stdcall arch=x86_64 CreateUmsCompletionList
 +;@ stdcall arch=x86_64 CreateUmsThreadContext
 +@ stdcall CreateVirtualBuffer(long long long) ; missing in Win 7
  @ stdcall CreateWaitableTimerA(ptr long str)
 -@ stdcall CreateWaitableTimerW(ptr long wstr)
  @ stdcall CreateWaitableTimerExA (ptr str long long)
  @ stdcall CreateWaitableTimerExW (ptr wstr long long)
- @ stdcall CreateWaitableTimerW(ptr long wstr)
+ @ stdcall DeactivateActCtx(long ptr)
 +;@ stdcall CtrlRoutine ; Win 7
- ;@ stdcall DeactivateActCtx(long ptr)
  @ stdcall DebugActiveProcess(long)
  @ stdcall DebugActiveProcessStop(long)
  @ stdcall DebugBreak() ntdll.DbgBreakPoint
  @ stdcall GetConsoleTitleW(ptr long)
  @ stdcall GetConsoleWindow()
  @ stdcall GetCurrencyFormatA(long long str ptr str long)
 +;@ stdcall GetCurrencyFormatEx ; Win 7
  @ stdcall GetCurrencyFormatW(long long str ptr str long)
;@ stdcall GetCurrentActCtx(ptr)
+ @ stdcall GetCurrentActCtx(ptr)
  @ stdcall GetCurrentConsoleFont(long long ptr)
 +;@ stdcall GetCurrentConsoleFontEx ; Win 7
  @ stdcall GetCurrentDirectoryA(long ptr)
  @ stdcall GetCurrentDirectoryW(long ptr)
  @ stdcall GetCurrentProcess()
  @ stdcall LocalShrink(long long)
  @ stdcall LocalSize(long)
  @ stdcall LocalUnlock(long)
- @ stub LocaleNameToLCID ; missing in XP SP3
+ ;@ stub LocaleNameToLCID ; missing in XP SP3
 +;@ stdcall LocateExtendedFeature api-ms-win-core-xstate-l1-1-0.RtlLocateExtendedFeature ; Win 7
 +;@ stdcall LocateLegacyContext api-ms-win-core-xstate-l1-1-0.RtlLocateLegacyContext ; Win 7
  @ stdcall LockFile(long long long long long)
  @ stdcall LockFileEx(long long long long long ptr)
  @ stdcall LockResource(long)
  @ stdcall ProcessIdToSessionId(long ptr)
  @ stdcall PulseEvent(long)
  @ stdcall PurgeComm(long long)
- ;@ stdcall QueryActCtxW(long ptr ptr long ptr long ptr)
 +;@ stdcall QueryActCtxSettingsW ; Win 7
+ @ stdcall QueryActCtxW(long ptr ptr long ptr long ptr)
  @ stdcall QueryDepthSList(ptr) ntdll.RtlQueryDepthSList
  @ stdcall QueryDosDeviceA(str ptr long)
  @ stdcall QueryDosDeviceW(wstr ptr long)
  @ stdcall RegisterWaitForSingleObjectEx(long ptr ptr long long)
  @ stdcall RegisterWowBaseHandlers(long)
  @ stdcall RegisterWowExec(long)
;@ stdcall ReleaseActCtx(ptr)
+ @ stdcall ReleaseActCtx(ptr)
  @ stdcall ReleaseMutex(long)
 -@ stdcall ReleaseSemaphore(long long ptr)
 +;@ stdcall ReleaseMutexWhenCallbackReturns ntdll.TpCallbackReleaseMutexOnCompletion ; Win 7
  @ stdcall ReleaseSRWLockExclusive(ptr) ntdll.RtlReleaseSRWLockExclusive
  @ stdcall ReleaseSRWLockShared(ptr) ntdll.RtlReleaseSRWLockShared
 +@ stdcall ReleaseSemaphore(long long ptr)
 +;@ stdcall ReleaseSemaphoreWhenCallbackReturns ntdll.TpCallbackReleaseSemaphoreOnCompletion ; Win 7
  @ stdcall RemoveDirectoryA(str)
 +;@ stdcall RemoveDirectoryTransactedA ; Win 7
 +;@ stdcall RemoveDirectoryTransactedW ; Win 7
  @ stdcall RemoveDirectoryW(wstr)
  @ stdcall RemoveLocalAlternateComputerNameA(str long)
  @ stdcall RemoveLocalAlternateComputerNameW(wstr long)
  @ stdcall WriteProfileStringA(str str str)
  @ stdcall WriteProfileStringW(wstr wstr wstr)
  @ stdcall WriteTapemark(ptr long long long)
 -@ stdcall WTSGetActiveConsoleSessionId()
 +@ stdcall WTSGetActiveConsoleSessionId() ; missing in win 7
;@ stdcall ZombifyActCtx(ptr)
+ @ stdcall ZombifyActCtx(ptr)
 -@ stub _DebugOut ; missing in XP SP3
 -@ stub _DebugPrintf ; missing in XP SP3
 +;@ stdcall -arch=x86_64 __C_specific_handler ntdll.__C_specific_handler
 +;@ stdcall -arch=x86_64 __chkstk ntdll.__chkstk
 +;@ stdcall -arch=x86_64 __misaligned_access ntdll.__misaligned_access
 +@ stub _DebugOut ; missing in XP SP3 and Win 7
 +@ stub _DebugPrintf ; missing in XP SP3 and Win 7
  @ stdcall _hread(long ptr long)
  @ stdcall _hwrite(long ptr long)
  @ stdcall _lclose(long)
   *                  Eric Pouech
   *                  Jon Griffiths
   *                  Dmitry Chapyshev (dmitry@reactos.org)
+  *                  Samuel SerapiĆ³n 
   */
  
+ /* synched with wine 1.1.26 */
  #include <k32.h>
  
- #define NDEBUG
- #include <debug.h>
+ #include "wine/debug.h"
  
- #define ACTCTX_FLAGS_ALL (\
-  ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
-  ACTCTX_FLAG_LANGID_VALID |\
-  ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
-  ACTCTX_FLAG_RESOURCE_NAME_VALID |\
-  ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
-  ACTCTX_FLAG_APPLICATION_NAME_VALID |\
-  ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
-  ACTCTX_FLAG_HMODULE_VALID )
+ WINE_DEFAULT_DEBUG_CHANNEL(actctx);
  
  #define ACTCTX_FAKE_HANDLE ((HANDLE) 0xf00baa)
- #define ACTCTX_FAKE_COOKIE ((ULONG_PTR) 0xf00bad)
  
- /*
-  * @implemented
+ /***********************************************************************
+  * CreateActCtxA (KERNEL32.@)
+  *
+  * Create an activation context.
   */
- BOOL
- WINAPI
- FindActCtxSectionStringA(
-     DWORD dwFlags,
-     const GUID *lpExtensionGuid,
-     ULONG ulSectionId,
-     LPCSTR lpStringToFind,
-     PACTCTX_SECTION_KEYED_DATA ReturnedData
-     )
+ HANDLE WINAPI CreateActCtxA(PCACTCTXA pActCtx)
  {
-     BOOL bRetVal;
-     LPWSTR lpStringToFindW = NULL;
+     ACTCTXW     actw;
+     SIZE_T      len;
+     HANDLE      ret = INVALID_HANDLE_VALUE;
+     LPWSTR      src = NULL, assdir = NULL, resname = NULL, appname = NULL;
+     TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
  
-     /* Convert lpStringToFind */
-     if (lpStringToFind)
+     if (!pActCtx || pActCtx->cbSize != sizeof(*pActCtx))
      {
-         BasepAnsiStringToHeapUnicodeString(lpStringToFind,
-                                             (LPWSTR*) &lpStringToFindW);
+         SetLastError(ERROR_INVALID_PARAMETER);
+         return INVALID_HANDLE_VALUE;
      }
  
-     /* Call the Unicode function */
-     bRetVal = FindActCtxSectionStringW(dwFlags,
-                                         lpExtensionGuid,
-                                         ulSectionId,
-                                         lpStringToFindW,
-                                         ReturnedData);
-     /* Clean up */
-     if (lpStringToFindW)
-         RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR*) lpStringToFindW);
-     return bRetVal;
- }
- /*
-  * @implemented
-  */
- HANDLE
- WINAPI
- CreateActCtxA(
-     PCACTCTXA pActCtx
-     )
- {
-     ACTCTXW pActCtxW;
-     HANDLE hRetVal;
-     ZeroMemory(&pActCtxW, sizeof(ACTCTXW));
-     pActCtxW.cbSize = sizeof(ACTCTXW);
-     pActCtxW.dwFlags = pActCtx->dwFlags;
-     pActCtxW.wLangId = pActCtx->wLangId;
-     pActCtxW.hModule = pActCtx->hModule;
-     pActCtxW.wProcessorArchitecture = pActCtx->wProcessorArchitecture;
-     pActCtxW.hModule = pActCtx->hModule;
-     /* Convert ActCtx Strings */
+     actw.cbSize = sizeof(actw);
+     actw.dwFlags = pActCtx->dwFlags;
      if (pActCtx->lpSource)
      {
-         BasepAnsiStringToHeapUnicodeString(pActCtx->lpSource,
-                                           (LPWSTR*) &pActCtxW.lpSource);
+         len = MultiByteToWideChar(CP_ACP, 0, pActCtx->lpSource, -1, NULL, 0);
+         src = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+         if (!src) return INVALID_HANDLE_VALUE;
+         MultiByteToWideChar(CP_ACP, 0, pActCtx->lpSource, -1, src, len);
      }
-     if (pActCtx->lpAssemblyDirectory)
+     actw.lpSource = src;
+     if (actw.dwFlags & ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID)
+         actw.wProcessorArchitecture = pActCtx->wProcessorArchitecture;
+     if (actw.dwFlags & ACTCTX_FLAG_LANGID_VALID)
+         actw.wLangId = pActCtx->wLangId;
+     if (actw.dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID)
      {
-         BasepAnsiStringToHeapUnicodeString(pActCtx->lpAssemblyDirectory,
-                                           (LPWSTR*) &pActCtxW.lpAssemblyDirectory);
+         len = MultiByteToWideChar(CP_ACP, 0, pActCtx->lpAssemblyDirectory, -1, NULL, 0);
+         assdir = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+         if (!assdir) goto done;
+         MultiByteToWideChar(CP_ACP, 0, pActCtx->lpAssemblyDirectory, -1, assdir, len);
+         actw.lpAssemblyDirectory = assdir;
      }
-     if (HIWORD(pActCtx->lpResourceName))
+     if (actw.dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
      {
-         BasepAnsiStringToHeapUnicodeString(pActCtx->lpResourceName,
-                                           (LPWSTR*) &pActCtxW.lpResourceName);
-     }
-     else
+         if ((ULONG_PTR)pActCtx->lpResourceName >> 16)
 -        {
 +    {
-         pActCtxW.lpResourceName = (LPWSTR) pActCtx->lpResourceName;
+             len = MultiByteToWideChar(CP_ACP, 0, pActCtx->lpResourceName, -1, NULL, 0);
+             resname = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+             if (!resname) goto done;
+             MultiByteToWideChar(CP_ACP, 0, pActCtx->lpResourceName, -1, resname, len);
+             actw.lpResourceName = resname;
 -        }
 +    }
-     if (pActCtx->lpApplicationName)
+         else actw.lpResourceName = (LPCWSTR)pActCtx->lpResourceName;
+     }
+     if (actw.dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
      {
-         BasepAnsiStringToHeapUnicodeString(pActCtx->lpApplicationName,
-                                           (LPWSTR*) &pActCtxW.lpApplicationName);
+         len = MultiByteToWideChar(CP_ACP, 0, pActCtx->lpApplicationName, -1, NULL, 0);
+         appname = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+         if (!appname) goto done;
+         MultiByteToWideChar(CP_ACP, 0, pActCtx->lpApplicationName, -1, appname, len);
+         actw.lpApplicationName = appname;
      }
-     /* Call the Unicode function */
-     hRetVal = CreateActCtxW(&pActCtxW);
+     if (actw.dwFlags & ACTCTX_FLAG_HMODULE_VALID)
+         actw.hModule = pActCtx->hModule;
  
-     /* Clean up */
-     RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR*) pActCtxW.lpSource);
-     RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR*) pActCtxW.lpAssemblyDirectory);
-     if (HIWORD(pActCtx->lpResourceName))
-         RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR*) pActCtxW.lpResourceName);
-     RtlFreeHeap(GetProcessHeap(), 0, (LPWSTR*) pActCtxW.lpApplicationName);
+     ret = CreateActCtxW(&actw);
  
-     return hRetVal;
+ done:
+     HeapFree(GetProcessHeap(), 0, src);
+     HeapFree(GetProcessHeap(), 0, assdir);
+     HeapFree(GetProcessHeap(), 0, resname);
+     HeapFree(GetProcessHeap(), 0, appname);
+     return ret;
  }
  
- /*
-  * @unimplemented
+ /***********************************************************************
+  * CreateActCtxW (KERNEL32.@)
+  *
+  * Create an activation context.
   */
- BOOL
- WINAPI
- ActivateActCtx(
-     HANDLE hActCtx,
-     ULONG_PTR *ulCookie
-     )
+ HANDLE WINAPI CreateActCtxW(PCACTCTXW pActCtx)
  {
-     NTSTATUS Status;
+     NTSTATUS    status;
+     HANDLE      hActCtx;
  
-     DPRINT("ActivateActCtx(%p %p)\n", hActCtx, ulCookie );
+     TRACE("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
  
-     Status = RtlActivateActivationContext(0, hActCtx, ulCookie);
-     if (!NT_SUCCESS(Status))
+     if ((status = RtlCreateActivationContext(&hActCtx, (PVOID*)pActCtx)))
      {
-         SetLastError(RtlNtStatusToDosError(Status));
+         SetLastError(RtlNtStatusToDosError(status));
+         return INVALID_HANDLE_VALUE;
+     }
+     return hActCtx;
+ }
+ /***********************************************************************
+  * ActivateActCtx (KERNEL32.@)
+  *
+  * Activate an activation context.
+  */
+ BOOL WINAPI ActivateActCtx(HANDLE hActCtx, ULONG_PTR *ulCookie)
+ {
+     NTSTATUS status;
+     if ((status = RtlActivateActivationContext( 0, hActCtx, ulCookie )))
+     {
+         SetLastError(RtlNtStatusToDosError(status));
          return FALSE;
      }
      return TRUE;
@@@ -266,58 -247,37 +247,37 @@@ BOOL WINAPI FindActCtxSectionStringW(DW
      return TRUE;
  }
  
- /*
-  * @unimplemented
+ /***********************************************************************
+  * FindActCtxSectionGuid (KERNEL32.@)
+  *
+  * Find information about a GUID in an activation context.
   */
- BOOL
- WINAPI
- QueryActCtxW(
-     DWORD dwFlags,
-     HANDLE hActCtx,
-     PVOID pvSubInstance,
-     ULONG ulInfoClass,
-     PVOID pvBuffer,
-     SIZE_T cbBuffer OPTIONAL,
-     SIZE_T *pcbWrittenOrRequired OPTIONAL
-     )
+ BOOL WINAPI FindActCtxSectionGuid(DWORD dwFlags, const GUID* lpExtGuid,
+                                   ULONG ulId, const GUID* lpSearchGuid,
+                                   PACTCTX_SECTION_KEYED_DATA pInfo)
  {
-     DPRINT("%s() is UNIMPLEMENTED!\n", __FUNCTION__);
-     /* this makes Adobe Photoshop 7.0 happy */
+   FIXME("%08x %s %u %s %p\n", dwFlags, debugstr_guid(lpExtGuid),
+        ulId, debugstr_guid(lpSearchGuid), pInfo);
 -  SetLastError( ERROR_CALL_NOT_IMPLEMENTED);
 -  return FALSE;
 +    SetLastError( ERROR_CALL_NOT_IMPLEMENTED);
 +    return FALSE;
  }
  
- /*
-  * @unimplemented
+ /***********************************************************************
+  * QueryActCtxW (KERNEL32.@)
+  *
+  * Get information about an activation context.
   */
- VOID
- WINAPI
- ReleaseActCtx(
-     HANDLE hActCtx
-     )
+ BOOL WINAPI QueryActCtxW(DWORD dwFlags, HANDLE hActCtx, PVOID pvSubInst,
+                          ULONG ulClass, PVOID pvBuff, SIZE_T cbBuff,
+                          SIZE_T *pcbLen)
  {
-     DPRINT("ReleaseActCtx(%p)\n", hActCtx);
-     RtlReleaseActivationContext(hActCtx);
- }
+     NTSTATUS status;
  
- /*
-  * @unimplemented
-  */
- BOOL
- WINAPI
- ZombifyActCtx(
-     HANDLE hActCtx
-     )
+     if ((status = RtlQueryInformationActivationContext( dwFlags, hActCtx, pvSubInst, ulClass,
+                                                         pvBuff, cbBuff, pcbLen )))
 -    {
 +{
-     NTSTATUS Status;
-     DPRINT("ZombifyActCtx(%p)\n", hActCtx);
-     Status = RtlZombifyActivationContext(hActCtx);
-     if (!NT_SUCCESS(Status))
-     {
-         SetLastError(RtlNtStatusToDosError(Status));
+         SetLastError(RtlNtStatusToDosError(status));
          return FALSE;
      }
      return TRUE;
  }
@@@ -88,9 -87,12 +87,12 @@@ static LPWSTR load_messageW( HMODULE mo
      TRACE("module = %p, id = %08x\n", module, id );
  
      if (!module) module = GetModuleHandleW( NULL );
 -    Status = RtlFindMessage( module, (ULONG) RT_MESSAGETABLE, lang, id, &mre );
 +    Status = RtlFindMessage( module, (ULONG_PTR) RT_MESSAGETABLE, lang, id, &mre );
      if (!NT_SUCCESS(Status))
+     {
+         SetLastError( RtlNtStatusToDosError(Status) );
          return NULL;
+     }
  
      if (mre->Flags & MESSAGE_RESOURCE_UNICODE)
      {
@@@ -119,9 -124,12 +124,12 @@@ static LPSTR load_messageA( HMODULE mod
      TRACE("module = %p, id = %08x\n", module, id );
  
      if (!module) module = GetModuleHandleW( NULL );
 -    Status = RtlFindMessage( module, (ULONG) RT_MESSAGETABLE, lang, id, &mre );
 +    Status = RtlFindMessage( module, (ULONG_PTR) RT_MESSAGETABLE, lang, id, &mre );
      if (!NT_SUCCESS(Status))
+     {
+         SetLastError( RtlNtStatusToDosError(Status) );
          return NULL;
+     }
  
      if (mre->Flags & MESSAGE_RESOURCE_UNICODE)
      {
@@@ -170,36 -171,49 +171,49 @@@ CreateRemoteThread(HANDLE hProcess
  
          /* Get the TEB */
          Status = NtQueryInformationThread(hThread,
-                                           ThreadBasicIformation,
+                                           ThreadBasicInformation,
                                            &ThreadBasicInfo,
                                            sizeof(ThreadBasicInfo),
-                                           NULL);
+                                           &retLen);
+         if (NT_SUCCESS(Status))
+         {
 -            /* Allocate the Activation Context Stack */
 -            Status = RtlAllocateActivationContextStack(&ActivationContextStack);
 +        /* Allocate the Activation Context Stack */
 +        Status = RtlAllocateActivationContextStack(&ActivationContextStack);
+         }
+         if (NT_SUCCESS(Status))
+         {
 -            Teb = ThreadBasicInfo.TebBaseAddress;
 -
 -            /* Save it */
 -            Teb->ActivationContextStackPointer = ActivationContextStack;
 -
 -            /* Query the Context */
 -            Status = RtlQueryInformationActivationContext(1,
 -                                                          0,
 -                                                          NULL,
 -                                                          ActivationContextBasicInformation,
 -                                                          &ActivationCtxInfo,
 -                                                          sizeof(ActivationCtxInfo),
 +        Teb = ThreadBasicInfo.TebBaseAddress;
 +
 +        /* Save it */
 +        Teb->ActivationContextStackPointer = ActivationContextStack;
 +
 +        /* Query the Context */
 +        Status = RtlQueryInformationActivationContext(1,
 +                                                      0,
 +                                                      NULL,
 +                                                      ActivationContextBasicInformation,
 +                                                      &ActivationCtxInfo,
 +                                                      sizeof(ActivationCtxInfo),
-                                                       NULL);
+                                                           &retLen);
+             if (NT_SUCCESS(Status))
+             {
 -                /* Does it need to be activated? */
 -                if (!ActivationCtxInfo.hActCtx)
 -                {
 -                    /* Activate it */
 +        /* Does it need to be activated? */
 +        if (!ActivationCtxInfo.hActCtx)
 +        {
 +            /* Activate it */
-             Status = RtlActivateActivationContextEx(1,
-                                                     Teb,
+                     Status = RtlActivateActivationContext(1,
 -                                                          ActivationCtxInfo.hActCtx,
 -                                                          &Cookie);
 +                                                    ActivationCtxInfo.hActCtx,
 +                                                    &Cookie);
+                     if (!NT_SUCCESS(Status))
+                         DPRINT1("RtlActivateActivationContext failed %x\n", Status);
 -                }
 -            }
++        }
++    }
+             else
+                 DPRINT1("RtlQueryInformationActivationContext failed %x\n", Status);
          }
+         else
+             DPRINT1("RtlAllocateActivationContextStack failed %x\n", Status);
      }
      #endif
  
Simple merge
@@@ -794,8 -809,16 +809,16 @@@ static HRESULT WINAPI DispatchEx_Invoke
          return This->data->vtbl->invoke(This->outer, id, lcid, wFlags, pdp, pvarRes, pei, pspCaller);
  
      if(wFlags == DISPATCH_CONSTRUCT) {
-         FIXME("DISPATCH_CONSTRUCT not implemented\n");
-         return E_NOTIMPL;
+         if(id == DISPID_VALUE) {
+             if(This->data->vtbl && This->data->vtbl->value) {
+                 return This->data->vtbl->value(This->outer, lcid, wFlags, pdp,
+                         pvarRes, pei, pspCaller);
 -            }
++    }
+             FIXME("DISPATCH_CONSTRUCT flag but missing value function\n");
+             return E_FAIL;
+         }
+         FIXME("DISPATCH_CONSTRUCT flag without DISPID_VALUE\n");
+         return E_FAIL;
      }
  
      if(is_dynamic_dispid(id)) {
@@@ -1982,20 -1991,12 +1991,12 @@@ HRESULT HTMLDocument_Create(IUnknown *p
      if(FAILED(hres))
          return hres;
  
-     doc->nscontainer = NSContainer_Create(doc, NULL);
-     list_init(&doc->bindings);
-     doc->usermode = UNKNOWN_USERMODE;
-     doc->readystate = READYSTATE_UNINITIALIZED;
-     if(doc->nscontainer) {
-         nsresult nsres;
  
 -    nsres = nsIWebBrowser_GetContentDOMWindow(doc->nscontainer->webbrowser, &nswindow);
 -    if(NS_FAILED(nsres))
 -        ERR("GetContentDOMWindow failed: %08x\n", nsres);
 +        nsres = nsIWebBrowser_GetContentDOMWindow(doc->nscontainer->webbrowser, &nswindow);
 +        if(NS_FAILED(nsres))
 +            ERR("GetContentDOMWindow failed: %08x\n", nsres);
-     }
  
-     hres = HTMLWindow_Create(doc, nswindow, &doc->basedoc.window);
+     hres = HTMLWindow_Create(doc, nswindow, NULL /* FIXME */, &doc->basedoc.window);
      if(nswindow)
          nsIDOMWindow_Release(nswindow);
      if(FAILED(hres)) {
@@@ -138,53 -103,13 +103,13 @@@ static HRESULT WINAPI HTMLIFrameBase2_g
  
      TRACE("(%p)->(%p)\n", This, p);
  
-     if(!This->content_window) {
-         nsIDOMHTMLDocument *nshtmldoc;
-         HTMLDocumentNode *content_doc;
-         nsIDOMDocument *nsdoc;
-         HTMLWindow *window;
-         nsresult nsres;
-         HRESULT hres;
-         nsres = nsIDOMHTMLIFrameElement_GetContentDocument(This->nsiframe, &nsdoc);
-         if(NS_FAILED(nsres)) {
-             ERR("GetContentDocument failed: %08x\n", nsres);
-             return E_FAIL;
-         }
-         if(!nsdoc) {
-             FIXME("NULL contentDocument\n");
-             return E_FAIL;
-         }
-         nsres = nsIDOMDocument_QueryInterface(nsdoc, &IID_nsIDOMHTMLDocument, (void**)&nshtmldoc);
-         nsIDOMDocument_Release(nsdoc);
-         if(NS_FAILED(nsres)) {
-             ERR("Could not get nsIDOMHTMLDocument iface: %08x\n", nsres);
-             return E_FAIL;
-         }
-         hres = create_content_window(This, nshtmldoc, &window);
-         if(FAILED(hres)) {
-             nsIDOMHTMLDocument_Release(nshtmldoc);
-             return E_FAIL;
+     if(This->framebase.content_window) {
+         IHTMLWindow2_AddRef(HTMLWINDOW2(This->framebase.content_window));
+         *p = HTMLWINDOW2(This->framebase.content_window);
+     }else {
+         WARN("NULL content window\n");
+         *p = NULL;
 -    }
 +        }
-         hres = create_doc_from_nsdoc(nshtmldoc, This->element.node.doc->basedoc.doc_obj, window, &content_doc);
-         nsIDOMHTMLDocument_Release(nshtmldoc);
-         if(SUCCEEDED(hres))
-             window_set_docnode(window, content_doc);
-         else
-             IHTMLWindow2_Release(HTMLWINDOW2(window));
-         htmldoc_release(&content_doc->basedoc);
-         if(FAILED(hres))
-             return hres;
-         This->content_window = window;
-     }
-     IHTMLWindow2_AddRef(HTMLWINDOW2(This->content_window));
-     *p = HTMLWINDOW2(This->content_window);
      return S_OK;
  }
  
@@@ -134,8 -151,15 +151,15 @@@ static HRESULT WINAPI HTMLLocation_Invo
  static HRESULT WINAPI HTMLLocation_put_href(IHTMLLocation *iface, BSTR v)
  {
      HTMLLocation *This = HTMLLOCATION_THIS(iface);
-     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
-     return E_NOTIMPL;
+     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
+     if(!This->window || !This->window->doc) {
+         FIXME("No document available\n");
+         return E_FAIL;
 -    }
++}
+     return navigate_url(This->window->doc, v);
  }
  
  static HRESULT WINAPI HTMLLocation_get_href(IHTMLLocation *iface, BSTR *p)
      if(FAILED(hres))
          return hres;
  
-     *p = SysAllocString(url);
-     return *p ? S_OK : E_OUTOFMEMORY;
+     switch(url.nScheme) {
+     case INTERNET_SCHEME_FILE:
+         {
+             /* prepend a slash */
+             url_path = HeapAlloc(GetProcessHeap(), 0, (url.dwUrlPathLength + 1) * sizeof(WCHAR));
+             if(!url_path)
+                 return E_OUTOFMEMORY;
+             url_path[0] = '/';
+             memcpy(url_path + 1, url.lpszUrlPath, url.dwUrlPathLength * sizeof(WCHAR));
+             url.lpszUrlPath = url_path;
+             url.dwUrlPathLength = url.dwUrlPathLength + 1;
 -        }
++}
+         break;
+     case INTERNET_SCHEME_HTTP:
+     case INTERNET_SCHEME_HTTPS:
+     case INTERNET_SCHEME_FTP:
+         if(!url.dwUrlPathLength) {
+             /* add a slash if it's blank */
+             url_path = url.lpszUrlPath = HeapAlloc(GetProcessHeap(), 0, 1 * sizeof(WCHAR));
+             if(!url.lpszUrlPath)
+                 return E_OUTOFMEMORY;
+             url.lpszUrlPath[0] = '/';
+             url.dwUrlPathLength = 1;
+         }
+         break;
+     default:
+         break;
+     }
+     /* replace \ with / */
+     for(i = 0; i < url.dwUrlPathLength; ++i)
+         if(url.lpszUrlPath[i] == '\\')
+             url.lpszUrlPath[i] = '/';
+     if(InternetCreateUrlW(&url, ICU_ESCAPE, NULL, &len)) {
+         FIXME("InternetCreateUrl succeeded with NULL buffer?\n");
+         ret = E_FAIL;
+         goto cleanup;
+     }
+     if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+         FIXME("InternetCreateUrl failed with error: %08x\n", GetLastError());
+         SetLastError(0);
+         ret = E_FAIL;
+         goto cleanup;
+     }
+     SetLastError(0);
+     buf = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+     if(!buf) {
+         ret = E_OUTOFMEMORY;
+         goto cleanup;
+     }
+     if(!InternetCreateUrlW(&url, ICU_ESCAPE, buf, &len)) {
+         FIXME("InternetCreateUrl failed with error: %08x\n", GetLastError());
+         SetLastError(0);
+         ret = E_FAIL;
+         goto cleanup;
+     }
+     *p = SysAllocStringLen(buf, len);
+     if(!*p) {
+         ret = E_OUTOFMEMORY;
+         goto cleanup;
+     }
+     ret = S_OK;
+ cleanup:
+     HeapFree(GetProcessHeap(), 0, buf);
+     HeapFree(GetProcessHeap(), 0, url_path);
+     return ret;
  }
  
  static HRESULT WINAPI HTMLLocation_put_protocol(IHTMLLocation *iface, BSTR v)
@@@ -172,7 -280,23 +280,23 @@@ static HRESULT WINAPI HTMLLocation_get_
      if(!p)
          return E_POINTER;
  
 -        return E_NOTIMPL;
+     url.dwSchemeLength = 1;
+     hres = get_url_components(This, &url);
+     if(FAILED(hres))
+         return hres;
+     if(!url.dwSchemeLength) {
+         FIXME("Unexpected blank protocol\n");
 -    }
 +    return E_NOTIMPL;
+     }else {
+         WCHAR buf[url.dwSchemeLength + 1];
+         memcpy(buf, url.lpszScheme, url.dwSchemeLength * sizeof(WCHAR));
+         buf[url.dwSchemeLength] = ':';
+         *p = SysAllocStringLen(buf, url.dwSchemeLength + 1);
++}
+     if(!*p)
+         return E_OUTOFMEMORY;
+     return S_OK;
  }
  
  static HRESULT WINAPI HTMLLocation_put_host(IHTMLLocation *iface, BSTR v)
@@@ -190,7 -317,32 +317,32 @@@ static HRESULT WINAPI HTMLLocation_get_
      if(!p)
          return E_POINTER;
  
-     return E_NOTIMPL;
+     url.dwHostNameLength = 1;
+     hres = get_url_components(This, &url);
+     if(FAILED(hres))
+         return hres;
+     if(!url.dwHostNameLength){
+         *p = NULL;
+         return S_OK;
 -    }
++}
+     if(url.nPort) {
+         /* <hostname>:<port> */
+         const WCHAR format[] = {'%','d',0};
+         DWORD len = url.dwHostNameLength + 1 + 5 + 1;
+         WCHAR buf[len];
+         memcpy(buf, url.lpszHostName, url.dwHostNameLength * sizeof(WCHAR));
+         buf[url.dwHostNameLength] = ':';
+         snprintfW(buf + url.dwHostNameLength + 1, 6, format, url.nPort);
+         *p = SysAllocString(buf);
+     }else
+         *p = SysAllocStringLen(url.lpszHostName, url.dwHostNameLength);
+     if(!*p)
+         return E_OUTOFMEMORY;
+     return S_OK;
  }
  
  static HRESULT WINAPI HTMLLocation_put_hostname(IHTMLLocation *iface, BSTR v)
@@@ -208,7 -363,20 +363,20 @@@ static HRESULT WINAPI HTMLLocation_get_
      if(!p)
          return E_POINTER;
  
-     return E_NOTIMPL;
+     url.dwHostNameLength = 1;
+     hres = get_url_components(This, &url);
+     if(FAILED(hres))
+         return hres;
+     if(!url.dwHostNameLength){
+         *p = NULL;
+         return S_OK;
 -    }
++}
+     *p = SysAllocStringLen(url.lpszHostName, url.dwHostNameLength);
+     if(!*p)
+         return E_OUTOFMEMORY;
+     return S_OK;
  }
  
  static HRESULT WINAPI HTMLLocation_put_port(IHTMLLocation *iface, BSTR v)
@@@ -226,7 -397,23 +397,23 @@@ static HRESULT WINAPI HTMLLocation_get_
      if(!p)
          return E_POINTER;
  
-     return E_NOTIMPL;
+     hres = get_url_components(This, &url);
+     if(FAILED(hres))
+         return hres;
+     if(url.nPort) {
+         const WCHAR format[] = {'%','d',0};
+         WCHAR buf[6];
+         snprintfW(buf, 6, format, url.nPort);
+         *p = SysAllocString(buf);
+     }else {
+         const WCHAR empty[] = {0};
+         *p = SysAllocString(empty);
 -    }
++}
+     if(!*p)
+         return E_OUTOFMEMORY;
+     return S_OK;
  }
  
  static HRESULT WINAPI HTMLLocation_put_pathname(IHTMLLocation *iface, BSTR v)
@@@ -294,7 -469,23 +469,23 @@@ static HRESULT WINAPI HTMLLocation_get_
      if(!p)
          return E_POINTER;
  
-     return E_NOTIMPL;
+     url.dwExtraInfoLength = 1;
+     hres = get_url_components(This, &url);
+     if(FAILED(hres))
+         return hres;
+     if(!url.dwExtraInfoLength){
+         *p = NULL;
+         return S_OK;
 -    }
++}
+     url.dwExtraInfoLength = strcspnW(url.lpszExtraInfo, hash);
+     *p = SysAllocStringLen(url.lpszExtraInfo, url.dwExtraInfoLength);
+     if(!*p)
+         return E_OUTOFMEMORY;
+     return S_OK;
  }
  
  static HRESULT WINAPI HTMLLocation_put_hash(IHTMLLocation *iface, BSTR v)
@@@ -312,7 -508,24 +508,24 @@@ static HRESULT WINAPI HTMLLocation_get_
      if(!p)
          return E_POINTER;
  
-     return E_NOTIMPL;
+     url.dwExtraInfoLength = 1;
+     hres = get_url_components(This, &url);
+     if(FAILED(hres))
+         return hres;
+     if(!url.dwExtraInfoLength){
+         *p = NULL;
+         return S_OK;
 -    }
++}
+     hash_pos = strcspnW(url.lpszExtraInfo, hash);
+     url.dwExtraInfoLength -= hash_pos;
+     *p = SysAllocStringLen(url.lpszExtraInfo + hash_pos, url.dwExtraInfoLength);
+     if(!*p)
+         return E_OUTOFMEMORY;
+     return S_OK;
  }
  
  static HRESULT WINAPI HTMLLocation_reload(IHTMLLocation *iface, VARIANT_BOOL flag)
@@@ -729,8 -729,19 +729,19 @@@ static HRESULT WINAPI HTMLDOMNode_get_p
  static HRESULT WINAPI HTMLDOMNode_get_nextSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
  {
      HTMLDOMNode *This = HTMLDOMNODE_THIS(iface);
-     FIXME("(%p)->(%p)\n", This, p);
-     return E_NOTIMPL;
+     nsIDOMNode *nssibling = NULL;
+     TRACE("(%p)->(%p)\n", This, p);
+     nsIDOMNode_GetNextSibling(This->nsnode, &nssibling);
+     if(nssibling) {
+         *p = HTMLDOMNODE(get_node(This->doc, nssibling, TRUE));
+         IHTMLDOMNode_AddRef(*p);
+     }else {
+         *p = NULL;
 -    }
++}
+     return S_OK;
  }
  
  #undef HTMLDOMNODE_THIS
@@@ -825,8 -836,13 +836,13 @@@ static HRESULT WINAPI HTMLDOMNode2_get_
  
      TRACE("(%p)->(%p)\n", This, p);
  
 -        *p = (IDispatch*)HTMLDOC(&This->doc->basedoc);
 -        IDispatch_AddRef(*p);
+     /* FIXME: Better check for document node */
+     if(This == &This->doc->node) {
+         *p = NULL;
+     }else {
 +    *p = (IDispatch*)HTMLDOC(&This->doc->basedoc);
 +    IDispatch_AddRef(*p);
+     }
      return S_OK;
  }
  
@@@ -900,7 -916,8 +916,8 @@@ void HTMLDOMNode_Init(HTMLDocumentNode 
      node->ref = 1;
      node->doc = doc;
  
 -        nsIDOMNode_AddRef(nsnode);
+     if(nsnode)
 +    nsIDOMNode_AddRef(nsnode);
      node->nsnode = nsnode;
  
      node->next = doc->nodes;
@@@ -45,6 -46,58 +46,58 @@@ static void window_set_docnode(HTMLWind
      window->doc = doc_node;
      if(doc_node)
          htmldoc_addref(&doc_node->basedoc);
 -    }
+     if(window->doc_obj && window->doc_obj->basedoc.window == window) {
+         if(window->doc_obj->basedoc.doc_node)
+             htmldoc_release(&window->doc_obj->basedoc.doc_node->basedoc);
+         window->doc_obj->basedoc.doc_node = doc_node;
+         if(doc_node)
+             htmldoc_addref(&doc_node->basedoc);
++}
+ }
+ nsIDOMWindow *get_nsdoc_window(nsIDOMDocument *nsdoc)
+ {
+     nsIDOMDocumentView *nsdocview;
+     nsIDOMAbstractView *nsview;
+     nsIDOMWindow *nswindow;
+     nsresult nsres;
+     nsres = nsIDOMDocument_QueryInterface(nsdoc, &IID_nsIDOMDocumentView, (void**)&nsdocview);
+     nsIDOMDocument_Release(nsdoc);
+     if(NS_FAILED(nsres)) {
+         ERR("Could not get nsIDOMDocumentView iface: %08x\n", nsres);
+         return NULL;
+     }
+     nsres = nsIDOMDocumentView_GetDefaultView(nsdocview, &nsview);
+     nsIDOMDocumentView_Release(nsview);
+     if(NS_FAILED(nsres)) {
+         ERR("GetDefaultView failed: %08x\n", nsres);
+         return NULL;
+     }
+     nsres = nsIDOMAbstractView_QueryInterface(nsview, &IID_nsIDOMWindow, (void**)&nswindow);
+     nsIDOMAbstractView_Release(nsview);
+     if(NS_FAILED(nsres)) {
+         ERR("Coult not get nsIDOMWindow iface: %08x\n", nsres);
+         return NULL;
+     }
+     return nswindow;
+ }
+ static void release_children(HTMLWindow *This)
+ {
+     HTMLWindow *child;
+     while(!list_empty(&This->children)) {
+         child = LIST_ENTRY(list_tail(&This->children), HTMLWindow, sibling_entry);
+         list_remove(&child->sibling_entry);
+         child->parent = NULL;
+         IHTMLWindow2_Release(HTMLWINDOW2(child));
+     }
  }
  
  #define HTMLWINDOW2_THIS(iface) DEFINE_THIS(HTMLWindow, HTMLWindow2, iface)
@@@ -177,8 -242,27 +242,27 @@@ static HRESULT WINAPI HTMLWindow2_item(
  static HRESULT WINAPI HTMLWindow2_get_length(IHTMLWindow2 *iface, LONG *p)
  {
      HTMLWindow *This = HTMLWINDOW2_THIS(iface);
-     FIXME("(%p)->(%p)\n", This, p);
-     return E_NOTIMPL;
+     nsIDOMWindowCollection *nscollection;
+     PRUint32 length;
+     nsresult nsres;
+     TRACE("(%p)->(%p)\n", This, p);
+     nsres = nsIDOMWindow_GetFrames(This->nswindow, &nscollection);
+     if(NS_FAILED(nsres)) {
+         ERR("GetFrames failed: %08x\n", nsres);
+         return E_FAIL;
 -    }
++}
+     nsres = nsIDOMWindowCollection_GetLength(nscollection, &length);
+     nsIDOMWindowCollection_Release(nscollection);
+     if(NS_FAILED(nsres)) {
+         ERR("GetLength failed: %08x\n", nsres);
+         return E_FAIL;
+     }
+     *p = length;
+     return S_OK;
  }
  
  static HRESULT WINAPI HTMLWindow2_get_frames(IHTMLWindow2 *iface, IHTMLFramesCollection2 **p)
@@@ -445,8 -547,32 +547,32 @@@ static HRESULT WINAPI HTMLWindow2_put_n
  static HRESULT WINAPI HTMLWindow2_get_name(IHTMLWindow2 *iface, BSTR *p)
  {
      HTMLWindow *This = HTMLWINDOW2_THIS(iface);
-     FIXME("(%p)->(%p)\n", This, p);
-     return E_NOTIMPL;
+     nsAString name_str;
+     nsresult nsres;
+     HRESULT hres;
+     TRACE("(%p)->(%p)\n", This, p);
+     nsAString_Init(&name_str, NULL);
+     nsres = nsIDOMWindow_GetName(This->nswindow, &name_str);
+     if(NS_SUCCEEDED(nsres)) {
+         const PRUnichar *name;
+         nsAString_GetData(&name_str, &name);
+         if(*name) {
+             *p = SysAllocString(name);
+             hres = *p ? S_OK : E_OUTOFMEMORY;
+         }else {
+             *p = NULL;
+             hres = S_OK;
 -        }
++}
+     }else {
+         ERR("GetName failed: %08x\n", nsres);
+         hres = E_FAIL;
+     }
+     nsAString_Finish(&name_str);
+     return hres;
  }
  
  static HRESULT WINAPI HTMLWindow2_get_parent(IHTMLWindow2 *iface, IHTMLWindow2 **p)
@@@ -888,24 -1013,51 +1013,51 @@@ static HRESULT HTMLWindow_invoke(IUnkno
      if(idx >= This->global_prop_cnt)
          return DISP_E_MEMBERNOTFOUND;
  
-     disp = get_script_disp(This->global_props[idx].script_host);
+     prop = This->global_props+idx;
+     switch(prop->type) {
+     case GLOBAL_SCRIPTVAR: {
+         IDispatchEx *dispex;
+         IDispatch *disp;
+         disp = get_script_disp(prop->script_host);
 -        if(!disp)
 -            return E_UNEXPECTED;
 +    if(!disp)
 +        return E_UNEXPECTED;
  
 -        hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
 -        if(SUCCEEDED(hres)) {
 +    hres = IDispatch_QueryInterface(disp, &IID_IDispatchEx, (void**)&dispex);
 +    if(SUCCEEDED(hres)) {
-         TRACE("%s >>>\n", debugstr_w(This->global_props[idx].name));
-         hres = IDispatchEx_InvokeEx(dispex, This->global_props[idx].id, lcid, flags, params, res, ei, caller);
+             TRACE("%s >>>\n", debugstr_w(prop->name));
+             hres = IDispatchEx_InvokeEx(dispex, prop->id, lcid, flags, params, res, ei, caller);
 -            if(hres == S_OK)
 +        if(hres == S_OK)
-             TRACE("%s <<<\n", debugstr_w(This->global_props[idx].name));
+                 TRACE("%s <<<\n", debugstr_w(prop->name));
 -            else
 +        else
-             WARN("%s <<< %08x\n", debugstr_w(This->global_props[idx].name), hres);
+                 WARN("%s <<< %08x\n", debugstr_w(prop->name), hres);
 -            IDispatchEx_Release(dispex);
 -        }else {
 -            FIXME("No IDispatchEx\n");
 -        }
 +        IDispatchEx_Release(dispex);
 +    }else {
 +        FIXME("No IDispatchEx\n");
 +    }
+         IDispatch_Release(disp);
+         break;
+     }
+     case GLOBAL_ELEMENTVAR: {
+         IHTMLElement *elem;
+         hres = IHTMLDocument3_getElementById(HTMLDOC3(&This->doc->basedoc), prop->name, &elem);
+         if(FAILED(hres))
 -            return hres;
++    return hres;
+         if(!elem)
+             return DISP_E_MEMBERNOTFOUND;
+         V_VT(res) = VT_DISPATCH;
+         V_DISPATCH(res) = (IDispatch*)elem;
+         break;
 -    }
++}
+     default:
+         ERR("invalid type %d\n", prop->type);
+         hres = DISP_E_MEMBERNOTFOUND;
+     }
  
-     IDispatch_Release(disp);
      return hres;
  }
  
@@@ -1291,35 -1476,41 +1476,41 @@@ static HRESULT WINAPI WindowDispEx_GetD
      }
  
      if(find_global_prop(This, bstrName, grfdex, &script_host, &id)) {
-         if(This->global_prop_cnt == This->global_prop_size) {
-             global_prop_t *new_props;
-             DWORD new_size;
-             if(This->global_props) {
-                 new_size = This->global_prop_size*2;
-                 new_props = heap_realloc(This->global_props, new_size*sizeof(global_prop_t));
-             }else {
-                 new_size = 16;
-                 new_props = heap_alloc(new_size*sizeof(global_prop_t));
-             }
-             if(!new_props)
+         global_prop_t *prop;
+         prop = alloc_global_prop(This, GLOBAL_SCRIPTVAR, bstrName);
+         if(!prop)
 -            return E_OUTOFMEMORY;
 +                return E_OUTOFMEMORY;
-             This->global_props = new_props;
-             This->global_prop_size = new_size;
+         prop->script_host = script_host;
+         prop->id = id;
+         *pid = prop_to_dispid(This, prop);
+         return S_OK;
 -    }
 +        }
  
-         This->global_props[This->global_prop_cnt].name = heap_strdupW(bstrName);
-         if(!This->global_props[This->global_prop_cnt].name)
-             return E_OUTOFMEMORY;
+     hres = IDispatchEx_GetDispID(DISPATCHEX(&This->dispex), bstrName, grfdex, pid);
+     if(hres != DISP_E_UNKNOWNNAME)
+         return hres;
  
-         This->global_props[This->global_prop_cnt].script_host = script_host;
-         This->global_props[This->global_prop_cnt].id = id;
+     if(This->doc) {
+         global_prop_t *prop;
+         IHTMLElement *elem;
+         hres = IHTMLDocument3_getElementById(HTMLDOC3(&This->doc->basedoc), bstrName, &elem);
+         if(SUCCEEDED(hres) && elem) {
+             IHTMLElement_Release(elem);
+             prop = alloc_global_prop(This, GLOBAL_ELEMENTVAR, bstrName);
+             if(!prop)
 -                return E_OUTOFMEMORY;
++            return E_OUTOFMEMORY;
  
-         *pid = MSHTML_DISPID_CUSTOM_MIN + (This->global_prop_cnt++);
+             *pid = prop_to_dispid(This, prop);
 -            return S_OK;
 -        }
 +        return S_OK;
 +    }
+     }
  
-     return IDispatchEx_GetDispID(DISPATCHEX(&This->dispex), bstrName, grfdex, pid);
+     return DISP_E_UNKNOWNNAME;
  }
  
  static HRESULT WINAPI WindowDispEx_InvokeEx(IDispatchEx *iface, DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp,
@@@ -266,11 -262,12 +262,12 @@@ static void pop_mutation_queue(HTMLDocu
      if(!tmp)
          return;
  
-     nscontainer->mutation_queue = tmp->next;
+     doc->mutation_queue = tmp->next;
      if(!tmp->next)
-         nscontainer->mutation_queue_tail = NULL;
+         doc->mutation_queue_tail = NULL;
  
 -        nsISupports_Release(tmp->nsiface);
+     if(tmp->nsiface)
 +    nsISupports_Release(tmp->nsiface);
      heap_free(tmp);
  }
  
@@@ -555,7 -683,22 +683,22 @@@ static void NSAPI nsDocumentObserver_Bi
  
          push_mutation_queue(This, MUTATION_COMMENT, (nsISupports*)nscomment);
          nsIDOMComment_Release(nscomment);
-         add_script_runner(This);
+     }
+     nsres = nsISupports_QueryInterface(aContent, &IID_nsIDOMHTMLIFrameElement, (void**)&nsiframe);
+     if(NS_SUCCEEDED(nsres)) {
+         TRACE("iframe node\n");
+         push_mutation_queue(This, MUTATION_IFRAME, (nsISupports*)nsiframe);
+         nsIDOMHTMLIFrameElement_Release(nsiframe);
 -    }
++}
+     nsres = nsISupports_QueryInterface(aContent, &IID_nsIDOMHTMLFrameElement, (void**)&nsframe);
+     if(NS_SUCCEEDED(nsres)) {
+         TRACE("frame node\n");
+         push_mutation_queue(This, MUTATION_FRAME, (nsISupports*)nsframe);
+         nsIDOMHTMLFrameElement_Release(nsframe);
      }
  }
  
@@@ -606,8 -750,35 +750,35 @@@ static const nsIDocumentObserverVtbl ns
      nsDocumentObserver_DoneAddingChildren
  };
  
- void init_mutation(NSContainer *nscontainer)
+ void init_mutation(HTMLDocumentNode *doc)
+ {
+     nsIDOMNSDocument *nsdoc;
+     nsresult nsres;
+     doc->lpIDocumentObserverVtbl  = &nsDocumentObserverVtbl;
+     doc->lpIRunnableVtbl          = &nsRunnableVtbl;
+     nsres = nsIDOMHTMLDocument_QueryInterface(doc->nsdoc, &IID_nsIDOMNSDocument, (void**)&nsdoc);
+     if(NS_FAILED(nsres)) {
+         ERR("Could not get nsIDOMNSDocument: %08x\n", nsres);
+         return;
 -    }
++}
+     nsIDOMNSDocument_WineAddObserver(nsdoc, NSDOCOBS(doc));
+     nsIDOMNSDocument_Release(nsdoc);
+ }
+ void release_mutation(HTMLDocumentNode *doc)
  {
-     nscontainer->lpDocumentObserverVtbl  = &nsDocumentObserverVtbl;
-     nscontainer->lpRunnableVtbl          = &nsRunnableVtbl;
+     nsIDOMNSDocument *nsdoc;
+     nsresult nsres;
+     nsres = nsIDOMHTMLDocument_QueryInterface(doc->nsdoc, &IID_nsIDOMNSDocument, (void**)&nsdoc);
+     if(NS_FAILED(nsres)) {
+         ERR("Could not get nsIDOMNSDocument: %08x\n", nsres);
+         return;
+     }
+     nsIDOMNSDocument_WineRemoveObserver(nsdoc, NSDOCOBS(doc));
+     nsIDOMNSDocument_Release(nsdoc);
  }
@@@ -948,12 -953,9 +953,9 @@@ static HRESULT read_stream_data(nsChann
  
              on_start_nsrequest(This);
  
-             /* events are reset when a new document URI is loaded, so re-initialise them here */
-             if(This->bsc.doc && This->bsc.doc->doc_obj->bscallback == This && This->bsc.doc->doc_obj->nscontainer) {
-                 update_nsdocument(This->bsc.doc->doc_obj);
-                 init_nsevents(This->bsc.doc->doc_obj->nscontainer);
+             if(This->window)
+                 update_window_doc(This->window);
 -        }
 +            }
-         }
  
          This->bsc.readed += This->nsstream->buf_size;
  
@@@ -154,24 -154,9 +154,9 @@@ static BOOL before_async_open(nsChanne
      if(!hlnf && !exec_shldocvw_67(doc, uri))
          return FALSE;
  
-     hres = IOleClientSite_QueryInterface(doc->client, &IID_IServiceProvider,
-                                          (void**)&service_provider);
-     if(SUCCEEDED(hres)) {
-         IHlinkFrame *hlink_frame;
-         hres = IServiceProvider_QueryService(service_provider, &IID_IHlinkFrame,
-                                              &IID_IHlinkFrame, (void**)&hlink_frame);
-         IServiceProvider_Release(service_provider);
-         if(SUCCEEDED(hres)) {
-             hlink_frame_navigate(&doc->basedoc, hlink_frame, uri, channel->post_data_stream, hlnf);
-             IHlinkFrame_Release(hlink_frame);
-             return FALSE;
+     hres = hlink_frame_navigate(&doc->basedoc, uri, channel->post_data_stream, hlnf);
+     return hres != S_OK;
 -}
 +        }
-     }
-     return TRUE;
- }
  
  #define NSCHANNEL_THIS(iface) DEFINE_THIS(nsChannel, HttpChannel, iface)
  
@@@ -691,55 -675,83 +675,83 @@@ static HTMLWindow *get_window_from_load
          return NULL;
      }
  
-     nsIWineURI_GetNSContainer(wine_uri, &container);
+     nsIWineURI_GetWindow(wine_uri, &window);
      nsIWineURI_Release(wine_uri);
  
-     return container;
+     return window;
  }
  
- static nsresult async_open_doc_uri(nsChannel *This, NSContainer *container,
-         nsIStreamListener *listener, nsISupports *context, BOOL *open)
+ static HTMLWindow *get_channel_window(nsChannel *This)
  {
-     IMoniker *mon;
-     HRESULT hres;
+     nsIRequestObserver *req_observer;
+     nsIWebProgress *web_progress;
+     nsIDOMWindow *nswindow;
+     HTMLWindow *window;
+     nsresult nsres;
  
-     *open = FALSE;
+     if(!This->load_group) {
+         ERR("NULL load_group\n");
+         return NULL;
+     }
  
-     if(container->bscallback) {
-         channelbsc_set_channel(container->bscallback, This, listener, context);
+     nsres = nsILoadGroup_GetGroupObserver(This->load_group, &req_observer);
+     if(NS_FAILED(nsres) || !req_observer) {
+         ERR("GetGroupObserver failed: %08x\n", nsres);
+         return NULL;
+     }
  
-         if(container->doc && container->doc->mime) {
-             heap_free(This->content_type);
-             This->content_type = heap_strdupWtoA(container->doc->mime);
+     nsres = nsIRequestObserver_QueryInterface(req_observer, &IID_nsIWebProgress, (void**)&web_progress);
+     nsIRequestObserver_Release(req_observer);
+     if(NS_FAILED(nsres)) {
+         ERR("Could not get nsIWebProgress iface: %08x\n", nsres);
+         return NULL;
 -    }
 +        }
  
-         return NS_OK;
-     }else  {
-         BOOL cont = before_async_open(This, container);
-         if(!cont) {
-             TRACE("canceled\n");
-             return NS_ERROR_UNEXPECTED;
+     nsres = nsIWebProgress_GetDOMWindow(web_progress, &nswindow);
+     nsIWebProgress_Release(web_progress);
+     if(NS_FAILED(nsres) || !nswindow) {
+         ERR("GetDOMWindow failed: %08x\n", nsres);
+         return NULL;
 -    }
 +        }
  
-         if(!container->doc) {
-             return This->channel
-                 ?  nsIChannel_AsyncOpen(This->channel, listener, context)
-                 : NS_ERROR_UNEXPECTED;
+     window = nswindow_to_window(nswindow);
+     nsIDOMWindow_Release(nswindow);
+     if(window)
+         IHTMLWindow2_AddRef(HTMLWINDOW2(window));
+     else
+         FIXME("NULL window for %p\n", nswindow);
+     return window;
 -}
 +        }
  
-         hres = create_mon_for_nschannel(This, &mon);
-         if(FAILED(hres)) {
-             return NS_ERROR_UNEXPECTED;
+ typedef struct {
+     task_t header;
+     HTMLDocumentNode *doc;
+     nsChannelBSC *bscallback;
+ } start_binding_task_t;
+ static void start_binding_proc(task_t *_task)
+ {
+     start_binding_task_t *task = (start_binding_task_t*)_task;
+     start_binding(NULL, task->doc, (BSCallback*)task->bscallback, NULL);
 -}
 +        }
-         set_current_mon(&container->doc->basedoc, mon);
-     }
  
-     *open = TRUE;
-     return NS_OK;
+ typedef struct {
+     task_t header;
+     HTMLWindow *window;
+     nsChannelBSC *bscallback;
+ } start_doc_binding_task_t;
+ static void start_doc_binding_proc(task_t *_task)
+ {
+     start_doc_binding_task_t *task = (start_doc_binding_task_t*)_task;
+     start_binding(task->window, NULL, (BSCallback*)task->bscallback, NULL);
+     IUnknown_Release((IUnknown*)task->bscallback);
  }
  
- static nsresult async_open(nsChannel *This, NSContainer *container, nsIStreamListener *listener,
+ static nsresult async_open(nsChannel *This, HTMLWindow *window, BOOL is_doc_channel, nsIStreamListener *listener,
          nsISupports *context)
  {
      nsChannelBSC *bscallback;
  
      channelbsc_set_channel(bscallback, This, listener, context);
  
-     task = heap_alloc(sizeof(task_t));
+     if(is_doc_channel) {
+         start_doc_binding_task_t *task;
  
-     task->doc = &container->doc->basedoc;
-     task->task_id = TASK_START_BINDING;
-     task->next = NULL;
+         set_window_bscallback(window, bscallback);
+         task = heap_alloc(sizeof(start_doc_binding_task_t));
+         task->window = window;
 -        task->bscallback = bscallback;
 +    task->bscallback = bscallback;
+         push_task(&task->header, start_doc_binding_proc, window->task_magic);
+     }else {
+         start_binding_task_t *task = heap_alloc(sizeof(start_binding_task_t));
  
-     push_task(task);
+         task->doc = window->doc;
+         task->bscallback = bscallback;
+         push_task(&task->header, start_binding_proc, window->doc->basedoc.task_magic);
+     }
  
      return NS_OK;
  }
@@@ -191,179 -199,11 +199,11 @@@ HRESULT clear_task_timer(HTMLDocument *
      return S_OK;
  }
  
static void set_downloading(HTMLDocumentObj *doc)
void parse_complete(HTMLDocumentObj *doc)
  {
-     IOleCommandTarget *olecmd;
-     HRESULT hres;
      TRACE("(%p)\n", doc);
  
-     if(doc->frame)
-         IOleInPlaceFrame_SetStatusText(doc->frame, NULL /* FIXME */);
-     if(!doc->client)
-         return;
-     hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd);
-     if(SUCCEEDED(hres)) {
-         VARIANT var;
-         V_VT(&var) = VT_I4;
-         V_I4(&var) = 1;
-         IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETDOWNLOADSTATE, OLECMDEXECOPT_DONTPROMPTUSER,
-                                &var, NULL);
-         IOleCommandTarget_Release(olecmd);
-     }
-     if(doc->hostui) {
-         IDropTarget *drop_target = NULL;
-         hres = IDocHostUIHandler_GetDropTarget(doc->hostui, NULL /* FIXME */, &drop_target);
-         if(drop_target) {
-             FIXME("Use IDropTarget\n");
-             IDropTarget_Release(drop_target);
-         }
 -}
 +    }
- }
- /* Calls undocumented 69 cmd of CGID_Explorer */
- static void call_explorer_69(HTMLDocumentObj *doc)
- {
-     IOleCommandTarget *olecmd;
-     VARIANT var;
-     HRESULT hres;
-     if(!doc->client)
-         return;
-     hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&olecmd);
-     if(FAILED(hres))
-         return;
-     VariantInit(&var);
-     hres = IOleCommandTarget_Exec(olecmd, &CGID_Explorer, 69, 0, NULL, &var);
-     IOleCommandTarget_Release(olecmd);
-     if(SUCCEEDED(hres) && V_VT(&var) != VT_NULL)
-         FIXME("handle result\n");
- }
- static void set_parsecomplete(HTMLDocument *doc)
- {
-     IOleCommandTarget *olecmd = NULL;
-     TRACE("(%p)\n", doc);
-     if(doc->doc_obj->usermode == EDITMODE)
-         init_editor(doc);
-     call_explorer_69(doc->doc_obj);
-     call_property_onchanged(&doc->cp_propnotif, 1005);
-     call_explorer_69(doc->doc_obj);
-     /* FIXME: IE7 calls EnableModelless(TRUE), EnableModelless(FALSE) and sets interactive state here */
-     doc->doc_obj->readystate = READYSTATE_INTERACTIVE;
-     call_property_onchanged(&doc->cp_propnotif, DISPID_READYSTATE);
-     if(doc->doc_obj->client)
-         IOleClientSite_QueryInterface(doc->doc_obj->client, &IID_IOleCommandTarget, (void**)&olecmd);
-     if(olecmd) {
-         VARIANT state, progress;
-         V_VT(&progress) = VT_I4;
-         V_I4(&progress) = 0;
-         IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETPROGRESSPOS, OLECMDEXECOPT_DONTPROMPTUSER,
-                                &progress, NULL);
-         V_VT(&state) = VT_I4;
-         V_I4(&state) = 0;
-         IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETDOWNLOADSTATE, OLECMDEXECOPT_DONTPROMPTUSER,
-                                &state, NULL);
-         IOleCommandTarget_Exec(olecmd, &CGID_ShellDocView, 103, 0, NULL, NULL);
-         IOleCommandTarget_Exec(olecmd, &CGID_MSHTML, IDM_PARSECOMPLETE, 0, NULL, NULL);
-         IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_HTTPEQUIV_DONE, 0, NULL, NULL);
-         IOleCommandTarget_Release(olecmd);
-     }
-     doc->doc_obj->readystate = READYSTATE_COMPLETE;
-     call_property_onchanged(&doc->cp_propnotif, DISPID_READYSTATE);
-     if(doc->doc_obj->frame) {
-         static const WCHAR wszDone[] = {'D','o','n','e',0};
-         IOleInPlaceFrame_SetStatusText(doc->doc_obj->frame, wszDone);
-     }
-     update_title(doc->doc_obj);
- }
- static void set_progress(HTMLDocument *doc)
- {
-     IOleCommandTarget *olecmd = NULL;
-     HRESULT hres;
-     TRACE("(%p)\n", doc);
-     if(doc->doc_obj->client)
-         IOleClientSite_QueryInterface(doc->doc_obj->client, &IID_IOleCommandTarget, (void**)&olecmd);
-     if(olecmd) {
-         VARIANT progress_max, progress;
-         V_VT(&progress_max) = VT_I4;
-         V_I4(&progress_max) = 0; /* FIXME */
-         IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETPROGRESSMAX, OLECMDEXECOPT_DONTPROMPTUSER,
-                                &progress_max, NULL);
-         V_VT(&progress) = VT_I4;
-         V_I4(&progress) = 0; /* FIXME */
-         IOleCommandTarget_Exec(olecmd, NULL, OLECMDID_SETPROGRESSPOS, OLECMDEXECOPT_DONTPROMPTUSER,
-                                &progress, NULL);
-     }
-     if(doc->doc_obj->usermode == EDITMODE && doc->doc_obj->hostui) {
-         DOCHOSTUIINFO hostinfo;
-         memset(&hostinfo, 0, sizeof(DOCHOSTUIINFO));
-         hostinfo.cbSize = sizeof(DOCHOSTUIINFO);
-         hres = IDocHostUIHandler_GetHostInfo(doc->doc_obj->hostui, &hostinfo);
-         if(SUCCEEDED(hres))
-             /* FIXME: use hostinfo */
-             TRACE("hostinfo = {%u %08x %08x %s %s}\n",
-                     hostinfo.cbSize, hostinfo.dwFlags, hostinfo.dwDoubleClick,
-                     debugstr_w(hostinfo.pchHostCss), debugstr_w(hostinfo.pchHostNS));
-     }
- }
- static void task_start_binding(HTMLDocument *doc, BSCallback *bscallback)
- {
-     if(doc)
-         start_binding(doc, bscallback, NULL);
-     IUnknown_Release((IUnknown*)bscallback);
- }
- static void process_task(task_t *task)
- {
-     switch(task->task_id) {
-     case TASK_SETDOWNLOADSTATE:
-         set_downloading(task->doc->doc_obj);
-         break;
-     case TASK_PARSECOMPLETE:
-         set_parsecomplete(task->doc);
-         break;
-     case TASK_SETPROGRESS:
-         set_progress(task->doc);
-         break;
-     case TASK_START_BINDING:
-         task_start_binding(task->doc, (BSCallback*)task->bscallback);
-         break;
-     default:
-         ERR("Wrong task_id %d\n", task->task_id);
-     }
- }
  
  static void call_timer_disp(IDispatch *disp)
  {
@@@ -4919,20 -4918,24 +4918,24 @@@ static LONG env_set_flags( LPCWSTR *nam
          return ERROR_FUNCTION_FAILED;
      }
  
 -        if (!strncmpW(ptr, prefix, prefix_len))
 -        {
 -            *flags |= ENV_MOD_APPEND;
 -            *value += lstrlenW(prefix);
 -        }
 -        else if (lstrlenW(*value) >= prefix_len)
+     if (*value)
+     {
+         LPCWSTR ptr = *value;
 +    if (!strncmpW(ptr, prefix, prefix_len))
 +    {
 +        *flags |= ENV_MOD_APPEND;
 +        *value += lstrlenW(prefix);
 +    }
 +    else if (lstrlenW(*value) >= prefix_len)
 +    {
 +        ptr += lstrlenW(ptr) - prefix_len;
 +        if (!lstrcmpW(ptr, prefix))
          {
 -            ptr += lstrlenW(ptr) - prefix_len;
 -            if (!lstrcmpW(ptr, prefix))
 -            {
 -                *flags |= ENV_MOD_PREFIX;
 -                /* the "[~]" will be removed by deformat_string */;
 -            }
 +            *flags |= ENV_MOD_PREFIX;
 +            /* the "[~]" will be removed by deformat_string */;
          }
      }
++    }
  
      if (check_flag_combo(*flags, ENV_ACT_SETALWAYS | ENV_ACT_SETABSENT) ||
          check_flag_combo(*flags, ENV_ACT_REMOVEMATCH | ENV_ACT_SETABSENT) ||
@@@ -5079,8 -5081,13 +5081,13 @@@ static UINT ITERATE_WriteEnvironmentStr
          lstrcpyW(newval, value);
      }
  
 -        TRACE("setting %s to %s\n", debugstr_w(name), debugstr_w(newval));
 -        res = RegSetValueExW(env, name, 0, type, (LPVOID)newval, size);
+     if (newval)
+     {
 +    TRACE("setting %s to %s\n", debugstr_w(name), debugstr_w(newval));
 +    res = RegSetValueExW(env, name, 0, type, (LPVOID)newval, size);
+     }
+     else
+         res = ERROR_SUCCESS;
  
  done:
      if (env) RegCloseKey(env);
@@@ -946,12 -962,59 +962,59 @@@ UINT MSI_GetFeatureCost(MSIPACKAGE *pac
  UINT WINAPI MsiGetFeatureCostW(MSIHANDLE hInstall, LPCWSTR szFeature,
                    MSICOSTTREE iCostTree, INSTALLSTATE iState, LPINT piCost)
  {
-     FIXME("(%d %s %i %i %p): stub\n", hInstall, debugstr_w(szFeature),
+     MSIPACKAGE *package;
+     MSIFEATURE *feature;
+     UINT ret;
+     TRACE("(%d %s %i %i %p)\n", hInstall, debugstr_w(szFeature),
            iCostTree, iState, piCost);
-     if (piCost) *piCost = 0;
+     package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
+     if (!package)
+     {
+         HRESULT hr;
+         BSTR feature;
+         IWineMsiRemotePackage *remote_package;
+         remote_package = (IWineMsiRemotePackage *)msi_get_remote(hInstall);
+         if (!remote_package)
+             return ERROR_INVALID_HANDLE;
+         feature = SysAllocString(szFeature);
+         if (!feature)
+         {
+             IWineMsiRemotePackage_Release(remote_package);
+             return ERROR_OUTOFMEMORY;
+         }
+         hr = IWineMsiRemotePackage_GetFeatureCost(remote_package, feature,
+                                                   iCostTree, iState, piCost);
+         SysFreeString(feature);
+         IWineMsiRemotePackage_Release(remote_package);
+         if (FAILED(hr))
+         {
+             if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
+                 return HRESULT_CODE(hr);
+             return ERROR_FUNCTION_FAILED;
+         }
 -        return ERROR_SUCCESS;
 -    }
 +    return ERROR_SUCCESS;
 +}
  
+     feature = get_loaded_feature(package, szFeature);
+     if (feature)
+         ret = MSI_GetFeatureCost(package, feature, iCostTree, iState, piCost);
+     else
+         ret = ERROR_UNKNOWN_FEATURE;
+     msiobj_release( &package->hdr );
+     return ret;
+ }
  /***********************************************************************
   * MsiSetComponentStateA (MSI.@)
   */
@@@ -96,6 -98,13 +98,13 @@@ static UINT msi_change_media(MSIPACKAG
              gUIHandlerA(gUIContext, MB_RETRYCANCEL | INSTALLMESSAGE_ERROR, msg);
              msi_free(msg);
          }
 -        }
+         else if (gUIHandlerRecord)
+         {
+             MSIHANDLE rec = MsiCreateRecord(1);
+             MsiRecordSetStringW(rec, 0, error);
+             gUIHandlerRecord(gUIContext, MB_RETRYCANCEL | INSTALLMESSAGE_ERROR, rec);
+             MsiCloseHandle(rec);
++    }
      }
  
      msi_free(error);
@@@ -1902,10 -1902,12 +1902,12 @@@ INSTALLUI_HANDLERA WINAPI MsiSetExterna
  {
      INSTALLUI_HANDLERA prev = gUIHandlerA;
  
-     TRACE("%p %x %p\n",puiHandler, dwMessageFilter,pvContext);
+     TRACE("%p %08x %p\n", puiHandler, dwMessageFilter, pvContext);
      gUIHandlerA = puiHandler;
 -    gUIFilter   = dwMessageFilter;
 -    gUIContext  = pvContext;
+     gUIHandlerW = NULL;
 +    gUIFilter = dwMessageFilter;
 +    gUIContext = pvContext;
  
      return prev;
  }
@@@ -1915,10 -1917,12 +1917,12 @@@ INSTALLUI_HANDLERW WINAPI MsiSetExterna
  {
      INSTALLUI_HANDLERW prev = gUIHandlerW;
  
-     TRACE("%p %x %p\n",puiHandler,dwMessageFilter,pvContext);
+     TRACE("%p %08x %p\n", puiHandler, dwMessageFilter, pvContext);
+     gUIHandlerA = NULL;
      gUIHandlerW = puiHandler;
 -    gUIFilter   = dwMessageFilter;
 -    gUIContext  = pvContext;
 +    gUIFilter = dwMessageFilter;
 +    gUIContext = pvContext;
  
      return prev;
  }
@@@ -37,12 -37,13 +37,13 @@@ WINE_DEFAULT_DEBUG_CHANNEL(msi)
  static LONG dll_count;
  
  /* the UI level */
 -INSTALLUILEVEL           gUILevel         = INSTALLUILEVEL_BASIC;
 -HWND                     gUIhwnd          = 0;
 -INSTALLUI_HANDLERA       gUIHandlerA      = NULL;
 -INSTALLUI_HANDLERW       gUIHandlerW      = NULL;
 +INSTALLUILEVEL gUILevel = INSTALLUILEVEL_BASIC;
 +HWND           gUIhwnd = 0;
 +INSTALLUI_HANDLERA gUIHandlerA = NULL;
 +INSTALLUI_HANDLERW gUIHandlerW = NULL;
+ INSTALLUI_HANDLER_RECORD gUIHandlerRecord = NULL;
 -DWORD                    gUIFilter        = 0;
 -LPVOID                   gUIContext       = NULL;
 +DWORD gUIFilter = 0;
 +LPVOID gUIContext = NULL;
  WCHAR gszLogFile[MAX_PATH];
  HINSTANCE msi_hInstance;
  
@@@ -1203,20 -1203,29 +1203,29 @@@ INT MSI_ProcessMessage( MSIPACKAGE *pac
          }
      }
  
-     TRACE("(%p %x %x %s)\n", gUIHandlerA, gUIFilter, log_type,
-                              debugstr_w(message));
+     TRACE("%p %p %p %x %x %s\n", gUIHandlerA, gUIHandlerW, gUIHandlerRecord,
+           gUIFilter, log_type, debugstr_w(message));
  
      /* convert it to ASCII */
-     len = WideCharToMultiByte( CP_ACP, 0, message, -1,
-                                NULL, 0, NULL, NULL );
+     len = WideCharToMultiByte( CP_ACP, 0, message, -1, NULL, 0, NULL, NULL );
      msg = msi_alloc( len );
-     WideCharToMultiByte( CP_ACP, 0, message, -1,
-                          msg, len, NULL, NULL );
+     WideCharToMultiByte( CP_ACP, 0, message, -1, msg, len, NULL, NULL );
  
-     if (gUIHandlerA && (gUIFilter & log_type))
+     if (gUIHandlerW && (gUIFilter & log_type))
+     {
+         rc = gUIHandlerW( gUIContext, eMessageType, message );
+     }
+     else if (gUIHandlerA && (gUIFilter & log_type))
      {
 -        rc = gUIHandlerA( gUIContext, eMessageType, msg );
 +        rc = gUIHandlerA(gUIContext,eMessageType,msg);
      }
+     else if (gUIHandlerRecord && (gUIFilter & log_type))
+     {
+         MSIHANDLE rec = MsiCreateRecord( 1 );
+         MsiRecordSetStringW( rec, 0, message );
+         rc = gUIHandlerRecord( gUIContext, eMessageType, rec );
+         MsiCloseHandle( rec );
+     }
  
      if ((!rc) && (gszLogFile[0]) && !((eMessageType & 0xff000000) ==
                                        INSTALLMESSAGE_PROGRESS))
          }
      }
      msi_free( msg );
 -    msi_free( message );
 +    msi_free( message);
  
      switch (eMessageType & 0xff000000)
      {
@@@ -1,5 -1,5 +1,5 @@@
- <module name="msvcrt" type="win32dll" baseaddress="${BASEADDRESS_MSVCRT}" mangledsymbols="true" installbase="system32" installname="msvcrt.dll" iscrt="yes">
+ <module name="msvcrt" type="win32dll" baseaddress="${BASEADDRESS_MSVCRT}" installbase="system32" installname="msvcrt.dll" iscrt="yes">
 -      <importlibrary definition="msvcrt.def" />
 +      <importlibrary definition="msvcrt-$(ARCH).def" />
        <include base="msvcrt">.</include>
        <include base="crt">include</include>
        <define name="USE_MSVCRT_PREFIX" />
@@@ -1,10 -1,9 +1,9 @@@
  <module name="nddeapi" type="win32dll" baseaddress="${BASEADDRESS_NDDEAPI}" installbase="system32" installname="nddeapi.dll" allowwarnings="true" entrypoint="0">
 -      <importlibrary definition="nddeapi.spec" />
 -      <include base="nddeapi">.</include>
 -      <include base="ReactOS">include/reactos/wine</include>
 -      <define name="__WINESRC__" />
 -      <library>wine</library>
 -      <library>ntdll</library>
 -      <file>nddeapi.c</file>
 +        <importlibrary definition="nddeapi.spec" />
 +        <include base="nddeapi">.</include>
 +        <include base="ReactOS">include/reactos/wine</include>
 +        <define name="__WINESRC__" />
 +        <library>wine</library>
-         <library>kernel32</library>
 +        <library>ntdll</library>
 +        <file>nddeapi.c</file>
  </module>
@@@ -1,11 -1,10 +1,10 @@@
  <module name="ntdsapi" type="win32dll" baseaddress="${BASEADDRESS_NTDSAPI}" installbase="system32" installname="ntdsapi.dll" allowwarnings="true" entrypoint="0">
 -      <importlibrary definition="ntdsapi.spec" />
 -      <include base="ntdsapi">.</include>
 -      <include base="ReactOS">include/reactos/wine</include>
 -      <define name="__WINESRC__" />
 -      <library>wine</library>
 -      <library>user32</library>
 -      <library>ntdll</library>
 -      <file>ntdsapi.c</file>
 +        <importlibrary definition="ntdsapi.spec" />
 +        <include base="ntdsapi">.</include>
 +        <include base="ReactOS">include/reactos/wine</include>
 +        <define name="__WINESRC__" />
 +        <library>wine</library>
 +        <library>user32</library>
-         <library>kernel32</library>
 +        <library>ntdll</library>
 +        <file>ntdsapi.c</file>
  </module>
@@@ -7,8 -7,6 +7,6 @@@
        <include base="ReactOS">include/reactos/wine</include>
        <define name="__WINESRC__" />
        <library>wine</library>
-       <library>advapi32</library>
-       <library>kernel32</library>
        <file>proxyodbc.c</file>
  </module>
--</group>
++</group>
@@@ -1,16 -1,13 +1,13 @@@
  <?xml version="1.0"?>
  <!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
- <group>
  <module name="olecli32" type="win32dll" baseaddress="${BASEADDRESS_OLECLI32}" installbase="system32" installname="olecli32.dll" allowwarnings="true" entrypoint="0">
 -      <importlibrary definition="olecli32.spec" />
 -      <include base="olecli32">.</include>
 -      <include base="ReactOS">include/reactos/wine</include>
 -      <define name="__WINESRC__" />
 -      <file>olecli_main.c</file>
 -      <library>wine</library>
 -      <library>ole32</library>
 -      <library>gdi32</library>
 -      <library>ntdll</library>
 +        <importlibrary definition="olecli32.spec" />
 +        <include base="olecli32">.</include>
 +        <include base="ReactOS">include/reactos/wine</include>
 +        <define name="__WINESRC__" />
 +        <file>olecli_main.c</file>
 +        <library>wine</library>
 +        <library>ole32</library>
 +        <library>gdi32</library>
-         <library>kernel32</library>
 +        <library>ntdll</library>
  </module>
- </group>
@@@ -1,11 -1,10 +1,10 @@@
  <module name="pdh" type="win32dll" baseaddress="${BASEADDRESS_PDH}" installbase="system32" installname="pdh.dll" allowwarnings="true" entrypoint="0">
 -      <importlibrary definition="pdh.spec" />
 -      <include base="pdh">.</include>
 -      <include base="ReactOS">include/reactos/wine</include>
 -      <define name="__WINESRC__" />
 -      <redefine name="_WIN32_WINNT">0x600</redefine>
 -      <library>wine</library>
 -      <library>ntdll</library>
 -      <file>pdh_main.c</file>
 +        <importlibrary definition="pdh.spec" />
 +        <include base="pdh">.</include>
 +        <include base="ReactOS">include/reactos/wine</include>
 +        <define name="__WINESRC__" />
 +        <redefine name="_WIN32_WINNT">0x600</redefine>
 +        <library>wine</library>
-         <library>kernel32</library>
 +        <library>ntdll</library>
 +        <file>pdh_main.c</file>
  </module>
@@@ -1,12 -1,11 +1,11 @@@
  <module name="printui" type="win32dll" baseaddress="${BASEADDRESS_PRINTUI}" installbase="system32" installname="printui.dll" allowwarnings="true" entrypoint="0">
 -      <importlibrary definition="printui.spec" />
 -      <include base="printui">.</include>
 -      <include base="ReactOS">include/reactos/wine</include>
 -      <define name="__WINESRC__" />
 -      <library>wine</library>
 -      <library>shell32</library>
 -      <library>ntdll</library>
 -      <file>printui.c</file>
 -      <file>printui.rc</file>
 +        <importlibrary definition="printui.spec" />
 +        <include base="printui">.</include>
 +        <include base="ReactOS">include/reactos/wine</include>
 +        <define name="__WINESRC__" />
 +        <library>wine</library>
 +        <library>shell32</library>
-         <library>kernel32</library>
 +        <library>ntdll</library>
 +        <file>printui.c</file>
 +        <file>printui.rc</file>
  </module>
@@@ -1900,15 -1900,20 +1900,20 @@@ BOOL WINAPI SetupGetIntField( PINFCONTE
      {
          if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return FALSE;
          if (!(buffer = HeapAlloc( GetProcessHeap(), 0, required ))) return FALSE;
-         if (!SetupGetStringFieldA( context, index, buffer, required, NULL )) goto done;
+         if (!(ret = SetupGetStringFieldA( context, index, buffer, required, NULL ))) goto done;
      }
 -        res = strtol( buffer, &end, 0 );
+     /* The call to SetupGetStringFieldA succeeded. If buffer is empty we have an optional field */
+     if (!*buffer) *result = 0;
+     else
+     {
-     if (end != buffer && !*end)
 +    res = strtol( buffer, &end, 0 );
 -        {
+         if (end != buffer && !*end) *result = res;
+         else
-         *result = res;
-         ret = TRUE;
 +    {
 -        }
+             SetLastError( ERROR_INVALID_DATA );
+             ret = FALSE;
++    }
      }
-     else SetLastError( ERROR_INVALID_DATA );
  
   done:
      if (buffer != localbuff) HeapFree( GetProcessHeap(), 0, buffer );
@@@ -1178,7 -1178,7 +1178,7 @@@ FormatDrive(HWND hwndDlg, PFORMAT_DRIVE
  }
  
  
--BOOL 
++INT_PTR 
  CALLBACK 
  FormatDriveDlg(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  {
@@@ -403,7 -402,8 +402,8 @@@ DWORD_PTR WINAPI SHGetFileInfoW(LPCWST
          {
              psfi->dwAttributes = 0xffffffff;
          }
 -            IShellFolder_GetAttributesOf( psfParent, 1, (LPCITEMIDLIST*)&pidlLast,
+         if (psfParent)
 +        IShellFolder_GetAttributesOf( psfParent, 1, (LPCITEMIDLIST*)&pidlLast,
                                        &(psfi->dwAttributes) );
      }
  
                                  GetSystemMetrics( SM_CXICON),
                                  GetSystemMetrics( SM_CYICON),
                                  &psfi->hIcon, 0, 1, 0);
 -                            psfi->iIcon = icon_idx;
 -                        }
+                         if (ret != 0 && ret != 0xFFFFFFFF)
+                         {
+                             IconNotYetLoaded=FALSE;
 +                        psfi->iIcon = icon_idx;
                      }
                  }
              }
          }
++        }
          else
          {
              if (!(PidlToSicIndex(psfParent, pidlLast, !(flags & SHGFI_SMALLICON),
Simple merge
@@@ -174,11 -161,13 +161,13 @@@ HRESULT WINAPI ParseURLA(LPCSTR x, PARS
        return 0x80041001;
      }
  
-     /* found scheme, set length of remainder */
-     y->cchSuffix = lstrlenA(y->pszSuffix);
+     y->pszProtocol = x;
+     y->cchProtocol = ptr-x;
+     y->pszSuffix = ptr+1;
+     y->cchSuffix = strlen(y->pszSuffix);
  
-     len = MultiByteToWideChar(CP_ACP, 0, y->pszProtocol, y->cchProtocol,
+     len = MultiByteToWideChar(CP_ACP, 0, x, ptr-x,
 -            scheme, sizeof(scheme)/sizeof(WCHAR));
 +                              scheme, sizeof(scheme)/sizeof(WCHAR));
      y->nScheme = get_scheme_code(scheme, len);
  
      return S_OK;
@@@ -1,14 -1,11 +1,11 @@@
  <?xml version="1.0"?>
  <!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
- <group>
  <module name="sxs" type="win32dll" baseaddress="${BASEADDRESS_SXS}" installbase="system32" installname="sxs.dll" allowwarnings="true" entrypoint="0">
 -      <importlibrary definition="sxs.spec" />
 -      <include base="sxs">.</include>
 -      <include base="ReactOS">include/reactos/wine</include>
 -      <define name="__WINESRC__" />
 -      <file>sxs.c</file>
 -      <library>wine</library>
 -      <library>ntdll</library>
 +        <importlibrary definition="sxs.spec" />
 +        <include base="sxs">.</include>
 +        <include base="ReactOS">include/reactos/wine</include>
 +        <define name="__WINESRC__" />
 +        <file>sxs.c</file>
 +        <library>wine</library>
-         <library>kernel32</library>
 +        <library>ntdll</library>
  </module>
- </group>
Simple merge
@@@ -1224,8 -1224,16 +1224,16 @@@ static LPCSTR MENU_ParseResource( LPCST
      }
      else  /* Not a popup */
      {
 -        if (*str == 0)
 -          flags = MF_SEPARATOR;
+       if(!unicode)
+       {
 +      if (*str == 0)
 +        flags = MF_SEPARATOR;
+       }
+       else
+       {
+         if (*(LPCWSTR)str == 0)
+           flags = MF_SEPARATOR;
+       }
  
        if (flags & MF_SEPARATOR)
        {
Simple merge
@@@ -1,8 -1,7 +1,7 @@@
  <module name="winfax" type="win32dll" baseaddress="${BASEADDRESS_WINFAX}" installbase="system32" installname="winfax.dll" allowwarnings="true" entrypoint="0">
 -      <importlibrary definition="winfax.spec" />
 -      <include base="winfax">.</include>
 -      <library>ntdll</library>
 -      <file>winfax.c</file>
 -      <file>winfax.rc</file>
 +        <importlibrary definition="winfax.spec" />
 +        <include base="winfax">.</include>
-         <library>kernel32</library>
 +        <library>ntdll</library>
 +        <file>winfax.c</file>
 +        <file>winfax.rc</file>
- </module>
+ </module>
@@@ -178,23 -191,8 +191,8 @@@ static BOOL COOKIE_crackUrlSimple(LPCWS
      UrlComponents.dwHostNameLength = hostNameLen;
      UrlComponents.dwUrlPathLength = pathLen;
  
-     rc = InternetCrackUrlW(lpszUrl, 0, 0, &UrlComponents);
-     /* discard the webpage off the end of the path */
-     if (pathLen > 0 && path[pathLen-1] != '/')
-     {
-         LPWSTR ptr;
-         ptr = strrchrW(path,'/');
-         if (ptr)
-             *(++ptr) = 0;
-         else
-         {
-             path[0] = '/';
-             path[1] = 0;
+     return InternetCrackUrlW(lpszUrl, 0, 0, &UrlComponents);
 -}
 +        }
-     }
-     return rc;
- }
  
  /* match a domain. domain must match if the domain is not NULL. path must match if the path is not NULL */
  static BOOL COOKIE_matchDomain(LPCWSTR lpszCookieDomain, LPCWSTR lpszCookiePath,
        }
      if (lpszCookiePath)
      {
-         INT len;
          TRACE("comparing paths: %s with %s\n", debugstr_w(lpszCookiePath), debugstr_w(searchDomain->lpCookiePath));
-         /* paths match at the beginning.  so a path of  /foo would match
-          * /foobar and /foo/bar
-          */
          if (!searchDomain->lpCookiePath)
              return FALSE;
-         if (allow_partial)
-         {
-             len = lstrlenW(searchDomain->lpCookiePath);
-             if (strncmpiW(searchDomain->lpCookiePath, lpszCookiePath, len)!=0)
+         if (strcmpW(lpszCookiePath, searchDomain->lpCookiePath))
 -            return FALSE;
 -      }
 +                return FALSE;
 +        }
-         else if (strcmpW(lpszCookiePath, searchDomain->lpCookiePath))
-             return FALSE;
-       }
        return TRUE;
  }
  
@@@ -515,16 -415,7 +415,7 @@@ static BOOL set_cookie(LPCWSTR domain, 
      }
  
      if (!thisCookieDomain)
-     {
-         if (!expired)
 -        thisCookieDomain = COOKIE_addDomain(domain, path);
 +            thisCookieDomain = COOKIE_addDomain(domain, path);
-         else
-         {
-             HeapFree(GetProcessHeap(),0,data);
-             if (value != data) HeapFree(GetProcessHeap(), 0, value);
-             return TRUE;
-         }
-     }
  
      if ((thisCookie = COOKIE_findCookie(thisCookieDomain, cookie_name)))
          COOKIE_deleteCookie(thisCookie, FALSE);
@@@ -62,15 -58,14 +58,14 @@@ struct WININET_ErrorDlgParam
   */
  static BOOL WININET_GetProxyServer( HINTERNET hRequest, LPWSTR szBuf, DWORD sz )
  {
-     http_request_t *lpwhr;
-     http_session_t *lpwhs = NULL;
-     appinfo_t *hIC = NULL;
-     BOOL ret = FALSE;
+     LPWININETHTTPREQW lpwhr;
+     LPWININETHTTPSESSIONW lpwhs = NULL;
+     LPWININETAPPINFOW hIC = NULL;
      LPWSTR p;
  
-     lpwhr = (http_request_t*) WININET_GetObject( hRequest );
+     lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hRequest );
      if (NULL == lpwhr)
 -      return FALSE;
 +        return FALSE;
  
      lpwhs = lpwhr->lpHttpSession;
      if (NULL == lpwhs)
@@@ -234,62 -194,44 +194,44 @@@ static BOOL WININET_GetSetPassword( HWN
  }
  
  /***********************************************************************
-  *         WININET_SetAuthorization
+  *         WININET_SetProxyAuthorization
   */
- static BOOL WININET_SetAuthorization( HINTERNET hRequest, LPWSTR username,
-                                       LPWSTR password, BOOL proxy )
+ static BOOL WININET_SetProxyAuthorization( HINTERNET hRequest,
+                                          LPWSTR username, LPWSTR password )
  {
-     http_request_t *lpwhr;
-     http_session_t *lpwhs;
-     BOOL ret = FALSE;
-     LPWSTR p, q;
+     LPWININETHTTPREQW lpwhr;
+     LPWININETHTTPSESSIONW lpwhs;
+     LPWININETAPPINFOW hIC;
+     LPWSTR p;
  
-     lpwhr = (http_request_t*) WININET_GetObject( hRequest );
+     lpwhr = (LPWININETHTTPREQW) WININET_GetObject( hRequest );
      if( !lpwhr )
 -      return FALSE;
 -        
 +        return FALSE;
 +
      lpwhs = lpwhr->lpHttpSession;
      if (NULL == lpwhs ||  lpwhs->hdr.htype != WH_HHTTPSESSION)
      {
          INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
-         goto done;
+       return FALSE;
      }
  
-     p = heap_strdupW(username);
-     if( !p )
-         goto done;
-     q = heap_strdupW(password);
-     if( !q )
-     {
-         HeapFree(GetProcessHeap(), 0, username);
-         goto done;
-     }
+     hIC = lpwhs->lpAppInfo;
  
-     if (proxy)
-     {
-         appinfo_t *hIC = lpwhs->lpAppInfo;
+     p = HeapAlloc( GetProcessHeap(), 0, (strlenW( username ) + 1)*sizeof(WCHAR) );
+     if( !p )
+         return FALSE;
 -    
 +
-         HeapFree(GetProcessHeap(), 0, hIC->lpszProxyUsername);
+     lstrcpyW( p, username );
 -    hIC->lpszProxyUsername = p;
 +        hIC->lpszProxyUsername = p;
  
-         HeapFree(GetProcessHeap(), 0, hIC->lpszProxyPassword);
-         hIC->lpszProxyPassword = q;
-     }
-     else
-     {
-         HeapFree(GetProcessHeap(), 0, lpwhs->lpszUserName);
-         lpwhs->lpszUserName = p;
-         HeapFree(GetProcessHeap(), 0, lpwhs->lpszPassword);
-         lpwhs->lpszPassword = q;
-     }
+     p = HeapAlloc( GetProcessHeap(), 0, (strlenW( password ) + 1)*sizeof(WCHAR) );
+     if( !p )
+         return FALSE;
 -    
 +
-     ret = TRUE;
+     lstrcpyW( p, password );
+     hIC->lpszProxyPassword = p;
  
- done:
-     WININET_Release( &lpwhr->hdr );
-     return ret;
+     return TRUE;
  }
  
  /***********************************************************************
@@@ -504,23 -362,17 +362,17 @@@ DWORD WINAPI InternetErrorDlg(HWND hWnd
      switch( dwError )
      {
      case ERROR_SUCCESS:
-     case ERROR_INTERNET_INCORRECT_PASSWORD:
-         if( !dwError && !(dwFlags & FLAGS_ERROR_UI_FILTER_FOR_ERRORS ) )
+         if( !(dwFlags & FLAGS_ERROR_UI_FILTER_FOR_ERRORS ) )
              return 0;
          dwStatus = WININET_GetConnectionStatus( hRequest );
-         switch (dwStatus)
-         {
-         case HTTP_STATUS_PROXY_AUTH_REQ:
+         if( HTTP_STATUS_PROXY_AUTH_REQ != dwStatus )
+             return ERROR_SUCCESS;
 -        return DialogBoxParamW( hwininet, MAKEINTRESOURCEW( IDD_PROXYDLG ),
 -                    hWnd, WININET_ProxyPasswordDialog, (LPARAM) &params );
 +            return DialogBoxParamW( hwininet, MAKEINTRESOURCEW( IDD_PROXYDLG ),
 +                                    hWnd, WININET_ProxyPasswordDialog, (LPARAM) &params );
-         case HTTP_STATUS_DENIED:
-             return DialogBoxParamW( hwininet, MAKEINTRESOURCEW( IDD_AUTHDLG ),
-                                     hWnd, WININET_PasswordDialog, (LPARAM) &params );
-         default:
-             WARN("unhandled status %u\n", dwStatus);
-             return 0;
-         }
+     case ERROR_INTERNET_INCORRECT_PASSWORD:
+         return DialogBoxParamW( hwininet, MAKEINTRESOURCEW( IDD_PROXYDLG ),
+                     hWnd, WININET_ProxyPasswordDialog, (LPARAM) &params );
  
      case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:
      case ERROR_INTERNET_INVALID_CA:
      return bSuccess;
  }
  
 -    
+ /***********************************************************************
+  *           FtpOpenFileA (WININET.@)
+  *
+  * Open a remote file for writing or reading
+  *
+  * RETURNS
+  *    HINTERNET handle on success
+  *    NULL on failure
+  *
+  */
+ HINTERNET WINAPI FtpOpenFileA(HINTERNET hFtpSession,
+     LPCSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags,
+     DWORD_PTR dwContext)
+ {
+     LPWSTR lpwzFileName;
+     HINTERNET ret;
++
+     lpwzFileName = lpszFileName?WININET_strdup_AtoW(lpszFileName):NULL;
+     ret = FtpOpenFileW(hFtpSession, lpwzFileName, fdwAccess, dwFlags, dwContext);
+     HeapFree(GetProcessHeap(), 0, lpwzFileName);
+     return ret;
+ }
+ static void AsyncFtpOpenFileProc(WORKREQUEST *workRequest)
+ {
+     struct WORKREQ_FTPOPENFILEW const *req = &workRequest->u.FtpOpenFileW;
+     LPWININETFTPSESSIONW lpwfs = (LPWININETFTPSESSIONW) workRequest->hdr;
+     TRACE("%p\n", lpwfs);
+     FTP_FtpOpenFileW(lpwfs, req->lpszFilename,
+         req->dwAccess, req->dwFlags, req->dwContext);
+     HeapFree(GetProcessHeap(), 0, req->lpszFilename);
+ }
+ /***********************************************************************
+  *           FtpOpenFileW (WININET.@)
+  *
+  * Open a remote file for writing or reading
+  *
+  * RETURNS
+  *    HINTERNET handle on success
+  *    NULL on failure
+  *
+  */
+ HINTERNET WINAPI FtpOpenFileW(HINTERNET hFtpSession,
+     LPCWSTR lpszFileName, DWORD fdwAccess, DWORD dwFlags,
+     DWORD_PTR dwContext)
+ {
+     LPWININETFTPSESSIONW lpwfs;
+     LPWININETAPPINFOW hIC = NULL;
+     HINTERNET r = NULL;
+     
+     TRACE("(%p,%s,0x%08x,0x%08x,0x%08lx)\n", hFtpSession,
+         debugstr_w(lpszFileName), fdwAccess, dwFlags, dwContext);
+     lpwfs = (LPWININETFTPSESSIONW) WININET_GetObject( hFtpSession );
+     if (!lpwfs)
+     {
+         INTERNET_SetLastError(ERROR_INVALID_HANDLE);
+         return FALSE;
+     }
+     if (WH_HFTPSESSION != lpwfs->hdr.htype)
+     {
+         INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
+         goto lend;
+     }
+     if ((!lpszFileName) ||
+         ((fdwAccess != GENERIC_READ) && (fdwAccess != GENERIC_WRITE)) ||
+         ((dwFlags & FTP_CONDITION_MASK) > FTP_TRANSFER_TYPE_BINARY))
+     {
+         INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
+         goto lend;
+     }
+     if (lpwfs->download_in_progress != NULL)
+     {
+         INTERNET_SetLastError(ERROR_FTP_TRANSFER_IN_PROGRESS);
+         goto lend;
+     }
+     hIC = lpwfs->lpAppInfo;
+     if (hIC->hdr.dwFlags & INTERNET_FLAG_ASYNC)
+     {
+         WORKREQUEST workRequest;
+         struct WORKREQ_FTPOPENFILEW *req;
+         workRequest.asyncproc = AsyncFtpOpenFileProc;
+         workRequest.hdr = WININET_AddRef( &lpwfs->hdr );
+         req = &workRequest.u.FtpOpenFileW;
+       req->lpszFilename = WININET_strdupW(lpszFileName);
+       req->dwAccess = fdwAccess;
+       req->dwFlags = dwFlags;
+       req->dwContext = dwContext;
+       INTERNET_AsyncCall(&workRequest);
+       r = NULL;
+     }
+     else
+     {
+       r = FTP_FtpOpenFileW(lpwfs, lpszFileName, fdwAccess, dwFlags, dwContext);
+     }
+ lend:
+     WININET_Release( &lpwfs->hdr );
+     return r;
+ }
  
  /***********************************************************************
   *           FTPFILE_Destroy(internal)
@@@ -1329,15 -1345,11 +1345,11 @@@ HINTERNET FTP_FtpOpenFileW(LPWININETFTP
                  &iar, sizeof(INTERNET_ASYNC_RESULT));
        }
  
-         if(bSuccess) {
-             FTP_ReceiveRequestData(lpwh, TRUE);
-         }else {
-             iar.dwResult = 0;
-             iar.dwError = INTERNET_GetLastError();
+         iar.dwResult = (DWORD)bSuccess;
+         iar.dwError = bSuccess ? ERROR_SUCCESS : INTERNET_GetLastError();
 -        SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
 -            &iar, sizeof(INTERNET_ASYNC_RESULT));
 -    }
 +            SendAsyncCallback(&lpwfs->hdr, lpwfs->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE,
 +                    &iar, sizeof(INTERNET_ASYNC_RESULT));
 +        }
-     }
  
  lend:
      if( lpwh )
@@@ -3600,31 -3505,32 +3505,32 @@@ static BOOL FTP_ParseNextFile(INT nSock
                  05-09-03  06:02PM             12656686 2003-04-21bgm_cmd_e.rgz
          */
          else if(isdigit(pszToken[0]) && 8 == strlen(pszToken)) {
-             int mon, mday, year, hour, min;
              lpfp->permissions = 0xFFFF; /* No idea, put full permission :-) */
              
-             sscanf(pszToken, "%d-%d-%d", &mon, &mday, &year);
-             lpfp->tmLastModified.wDay   = mday;
-             lpfp->tmLastModified.wMonth = mon;
-             lpfp->tmLastModified.wYear  = year;
+             sscanf(pszToken, "%d-%d-%d",
+                 &lpfp->tmLastModified.tm_mon,
+                 &lpfp->tmLastModified.tm_mday,
+                 &lpfp->tmLastModified.tm_year);
  
              /* Hacky and bad Y2K protection :-) */
-             if (lpfp->tmLastModified.wYear < 70) lpfp->tmLastModified.wYear += 2000;
+             if (lpfp->tmLastModified.tm_year < 70)
+                 lpfp->tmLastModified.tm_year += 100;
 -            
 +
              pszToken = strtok(NULL, szSpace);
              if(!pszToken) continue;
-             sscanf(pszToken, "%d:%d", &hour, &min);
-             lpfp->tmLastModified.wHour   = hour;
-             lpfp->tmLastModified.wMinute = min;
+             sscanf(pszToken, "%d:%d",
+                 &lpfp->tmLastModified.tm_hour,
+                 &lpfp->tmLastModified.tm_min);
              if((pszToken[5] == 'P') && (pszToken[6] == 'M')) {
-                 lpfp->tmLastModified.wHour += 12;
+                 lpfp->tmLastModified.tm_hour += 12;
              }
-             lpfp->tmLastModified.wSecond = 0;
+             lpfp->tmLastModified.tm_sec = 0;
  
-             TRACE("Mod time: %02d:%02d:%02d  %04d/%02d/%02d\n",
-                   lpfp->tmLastModified.wHour, lpfp->tmLastModified.wMinute, lpfp->tmLastModified.wSecond,
-                   lpfp->tmLastModified.wYear, lpfp->tmLastModified.wMonth, lpfp->tmLastModified.wDay);
+             TRACE("Mod time: %02d:%02d:%02d  %02d/%02d/%02d\n",
+                 lpfp->tmLastModified.tm_hour, lpfp->tmLastModified.tm_min, lpfp->tmLastModified.tm_sec,
+                 (lpfp->tmLastModified.tm_year >= 100) ? lpfp->tmLastModified.tm_year - 100 : lpfp->tmLastModified.tm_year,
+                 lpfp->tmLastModified.tm_mon, lpfp->tmLastModified.tm_mday);
 -            
 +
              pszToken = strtok(NULL, szSpace);
              if(!pszToken) continue;
              if(!strcasecmp(pszToken, "<DIR>")) {
@@@ -323,26 -146,21 +146,21 @@@ static LPWSTR * HTTP_Tokenize(LPCWSTR s
      int i;
      LPCWSTR next_token;
  
-     if (string)
-     {
 -    /* empty string has no tokens */
 -    if (*string)
 -        tokens++;
 -    /* count tokens */
 -    for (i = 0; string[i]; i++)
 -        if (!strncmpW(string+i, token_string, strlenW(token_string)))
 -        {
 -            DWORD j;
 +        /* empty string has no tokens */
 +        if (*string)
              tokens++;
 -            /* we want to skip over separators, but not the null terminator */
 -            for (j = 0; j < strlenW(token_string) - 1; j++)
 -                if (!string[i+j])
 -                    break;
 -            i += j;
 -        }
 +        /* count tokens */
 +        for (i = 0; string[i]; i++)
-         {
 +            if (!strncmpW(string+i, token_string, strlenW(token_string)))
 +            {
 +                DWORD j;
 +                tokens++;
 +                /* we want to skip over separators, but not the null terminator */
 +                for (j = 0; j < strlenW(token_string) - 1; j++)
 +                    if (!string[i+j])
 +                        break;
 +                i += j;
 +            }
-         }
-     }
  
      /* add 1 for terminating NULL */
      token_array = HeapAlloc(GetProcessHeap(), 0, (tokens+1) * sizeof(*token_array));
@@@ -490,171 -309,99 +309,99 @@@ static LPWSTR HTTP_BuildHeaderRequestSt
      return requestString;
  }
  
- static void HTTP_ProcessCookies( http_request_t *lpwhr )
+ static void HTTP_ProcessCookies( LPWININETHTTPREQW lpwhr )
  {
+     static const WCHAR szSet_Cookie[] = { 'S','e','t','-','C','o','o','k','i','e',0 };
      int HeaderIndex;
-     int numCookies = 0;
      LPHTTPHEADERW setCookieHeader;
  
-     while((HeaderIndex = HTTP_GetCustomHeaderIndex(lpwhr, szSet_Cookie, numCookies, FALSE)) != -1)
-     {
+     HeaderIndex = HTTP_GetCustomHeaderIndex(lpwhr, szSet_Cookie, 0, FALSE);
+     if (HeaderIndex == -1)
+             return;
 -    setCookieHeader = &lpwhr->pCustHeaders[HeaderIndex];
 +        setCookieHeader = &lpwhr->pCustHeaders[HeaderIndex];
  
 -    if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_COOKIES) && setCookieHeader->lpszValue)
 -    {
 +        if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_COOKIES) && setCookieHeader->lpszValue)
 +        {
-             int len;
-             static const WCHAR szFmt[] = { 'h','t','t','p',':','/','/','%','s','%','s',0};
+         int nPosStart = 0, nPosEnd = 0, len;
+         static const WCHAR szFmt[] = { 'h','t','t','p',':','/','/','%','s','/',0};
+         while (setCookieHeader->lpszValue[nPosEnd] != '\0')
+         {
+             LPWSTR buf_cookie, cookie_name, cookie_data;
              LPWSTR buf_url;
+             LPWSTR domain = NULL;
              LPHTTPHEADERW Host;
  
-             Host = HTTP_GetHeader(lpwhr, hostW);
-             len = lstrlenW(Host->lpszValue) + 9 + lstrlenW(lpwhr->lpszPath);
-             buf_url = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
-             sprintfW(buf_url, szFmt, Host->lpszValue, lpwhr->lpszPath);
-             InternetSetCookieW(buf_url, NULL, setCookieHeader->lpszValue);
-             HeapFree(GetProcessHeap(), 0, buf_url);
-         }
-         numCookies++;
-     }
- }
- static void strip_spaces(LPWSTR start)
+             int nEqualPos = 0;
+             while (setCookieHeader->lpszValue[nPosEnd] != ';' && setCookieHeader->lpszValue[nPosEnd] != ',' &&
+                    setCookieHeader->lpszValue[nPosEnd] != '\0')
 -            {
 +{
-     LPWSTR str = start;
-     LPWSTR end;
-     while (*str == ' ' && *str != '\0')
-         str++;
-     if (str != start)
-         memmove(start, str, sizeof(WCHAR) * (strlenW(str) + 1));
-     end = start + strlenW(start) - 1;
-     while (end >= start && *end == ' ')
-     {
-         *end = '\0';
-         end--;
+                 nPosEnd++;
 -            }
 +    }
- }
- static inline BOOL is_basic_auth_value( LPCWSTR pszAuthValue, LPWSTR *pszRealm )
+             if (setCookieHeader->lpszValue[nPosEnd] == ';')
 -            {
 +{
-     static const WCHAR szBasic[] = {'B','a','s','i','c'}; /* Note: not nul-terminated */
-     static const WCHAR szRealm[] = {'r','e','a','l','m'}; /* Note: not nul-terminated */
-     BOOL is_basic;
-     is_basic = !strncmpiW(pszAuthValue, szBasic, ARRAYSIZE(szBasic)) &&
-         ((pszAuthValue[ARRAYSIZE(szBasic)] == ' ') || !pszAuthValue[ARRAYSIZE(szBasic)]);
-     if (is_basic && pszRealm)
+                 /* fixme: not case sensitive, strcasestr is gnu only */
+                 int nDomainPosEnd = 0;
+                 int nDomainPosStart = 0, nDomainLength = 0;
+                 static const WCHAR szDomain[] = {'d','o','m','a','i','n','=',0};
+                 LPWSTR lpszDomain = strstrW(&setCookieHeader->lpszValue[nPosEnd], szDomain);
+                 if (lpszDomain)
+                 { /* they have specified their own domain, lets use it */
+                     while (lpszDomain[nDomainPosEnd] != ';' && lpszDomain[nDomainPosEnd] != ',' &&
+                            lpszDomain[nDomainPosEnd] != '\0')
 -                    {
 +    {
-         LPCWSTR token;
-         LPCWSTR ptr = &pszAuthValue[ARRAYSIZE(szBasic)];
-         LPCWSTR realm;
-         ptr++;
-         *pszRealm=NULL;
-         token = strchrW(ptr,'=');
-         if (!token)
-             return TRUE;
-         realm = ptr;
-         while (*realm == ' ' && *realm != '\0')
-             realm++;
-         if(!strncmpiW(realm, szRealm, ARRAYSIZE(szRealm)) &&
-             (realm[ARRAYSIZE(szRealm)] == ' ' || realm[ARRAYSIZE(szRealm)] == '='))
-         {
-             token++;
-             while (*token == ' ' && *token != '\0')
-                 token++;
-             if (*token == '\0')
-                 return TRUE;
-             *pszRealm = heap_strdupW(token);
-             strip_spaces(*pszRealm);
+                         nDomainPosEnd++;
 -                    }
 +        }
+                     nDomainPosStart = strlenW(szDomain);
+                     nDomainLength = (nDomainPosEnd - nDomainPosStart) + 1;
+                     domain = HeapAlloc(GetProcessHeap(), 0, (nDomainLength + 1)*sizeof(WCHAR));
+                     lstrcpynW(domain, &lpszDomain[nDomainPosStart], nDomainLength + 1);
 -                }
 -            }
 +    }
-     return is_basic;
 +}
- static void destroy_authinfo( struct HttpAuthInfo *authinfo )
+             if (setCookieHeader->lpszValue[nPosEnd] == '\0') break;
+             buf_cookie = HeapAlloc(GetProcessHeap(), 0, ((nPosEnd - nPosStart) + 1)*sizeof(WCHAR));
+             lstrcpynW(buf_cookie, &setCookieHeader->lpszValue[nPosStart], (nPosEnd - nPosStart) + 1);
+             TRACE("%s\n", debugstr_w(buf_cookie));
+             while (buf_cookie[nEqualPos] != '=' && buf_cookie[nEqualPos] != '\0')
 -            {
 +{
-     if (!authinfo) return;
-     if (SecIsValidHandle(&authinfo->ctx))
-         DeleteSecurityContext(&authinfo->ctx);
-     if (SecIsValidHandle(&authinfo->cred))
-         FreeCredentialsHandle(&authinfo->cred);
-     HeapFree(GetProcessHeap(), 0, authinfo->auth_data);
-     HeapFree(GetProcessHeap(), 0, authinfo->scheme);
-     HeapFree(GetProcessHeap(), 0, authinfo);
+                 nEqualPos++;
 -            }
 +}
- static UINT retrieve_cached_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR *auth_data)
+             if (buf_cookie[nEqualPos] == '\0' || buf_cookie[nEqualPos + 1] == '\0')
 -            {
 +{
-     authorizationData *ad;
-     UINT rc = 0;
-     TRACE("Looking for authorization for %s:%s\n",debugstr_w(host),debugstr_w(realm));
-     EnterCriticalSection(&authcache_cs);
-     LIST_FOR_EACH_ENTRY(ad, &basicAuthorizationCache, authorizationData, entry)
-     {
-         if (!strcmpiW(host,ad->lpszwHost) && !strcmpW(realm,ad->lpszwRealm))
-         {
-             TRACE("Authorization found in cache\n");
-             *auth_data = HeapAlloc(GetProcessHeap(),0,ad->AuthorizationLen);
-             memcpy(*auth_data,ad->lpszAuthorization,ad->AuthorizationLen);
-             rc = ad->AuthorizationLen;
+                 HeapFree(GetProcessHeap(), 0, buf_cookie);
 -                break;
 -            }
 +            break;
 +        }
-     }
-     LeaveCriticalSection(&authcache_cs);
-     return rc;
- }
  
- static void cache_basic_authorization(LPWSTR host, LPWSTR realm, LPSTR auth_data, UINT auth_data_len)
- {
-     struct list *cursor;
-     authorizationData* ad = NULL;
+             cookie_name = HeapAlloc(GetProcessHeap(), 0, (nEqualPos + 1)*sizeof(WCHAR));
+             lstrcpynW(cookie_name, buf_cookie, nEqualPos + 1);
+             cookie_data = &buf_cookie[nEqualPos + 1];
  
-     TRACE("caching authorization for %s:%s = %s\n",debugstr_w(host),debugstr_w(realm),debugstr_an(auth_data,auth_data_len));
+             Host = HTTP_GetHeader(lpwhr,szHost);
+             len = lstrlenW((domain ? domain : (Host?Host->lpszValue:NULL))) + 
+                 strlenW(lpwhr->lpszPath) + 9;
+             buf_url = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
+             sprintfW(buf_url, szFmt, (domain ? domain : (Host?Host->lpszValue:NULL))); /* FIXME PATH!!! */
+             InternetSetCookieW(buf_url, cookie_name, cookie_data);
  
-     EnterCriticalSection(&authcache_cs);
-     LIST_FOR_EACH(cursor, &basicAuthorizationCache)
-     {
-         authorizationData *check = LIST_ENTRY(cursor,authorizationData,entry);
-         if (!strcmpiW(host,check->lpszwHost) && !strcmpW(realm,check->lpszwRealm))
-         {
-             ad = check;
-             break;
+             HeapFree(GetProcessHeap(), 0, buf_url);
+             HeapFree(GetProcessHeap(), 0, buf_cookie);
+             HeapFree(GetProcessHeap(), 0, cookie_name);
+             HeapFree(GetProcessHeap(), 0, domain);
+             nPosStart = nPosEnd;
          }
      }
+ }
  
    if (ad)
static inline BOOL is_basic_auth_value( LPCWSTR pszAuthValue )
 -{
 +    {
-         TRACE("Found match in cache, replacing\n");
-         HeapFree(GetProcessHeap(),0,ad->lpszAuthorization);
-         ad->lpszAuthorization = HeapAlloc(GetProcessHeap(),0,auth_data_len);
-         memcpy(ad->lpszAuthorization, auth_data, auth_data_len);
-         ad->AuthorizationLen = auth_data_len;
-     }
-     else
-     {
-         ad = HeapAlloc(GetProcessHeap(),0,sizeof(authorizationData));
-         ad->lpszwHost = heap_strdupW(host);
-         ad->lpszwRealm = heap_strdupW(realm);
-         ad->lpszAuthorization = HeapAlloc(GetProcessHeap(),0,auth_data_len);
-         memcpy(ad->lpszAuthorization, auth_data, auth_data_len);
-         ad->AuthorizationLen = auth_data_len;
-         list_add_head(&basicAuthorizationCache,&ad->entry);
-         TRACE("authorization cached\n");
+     static const WCHAR szBasic[] = {'B','a','s','i','c'}; /* Note: not nul-terminated */
+     return !strncmpiW(pszAuthValue, szBasic, ARRAYSIZE(szBasic)) &&
+         ((pszAuthValue[ARRAYSIZE(szBasic)] == ' ') || !pszAuthValue[ARRAYSIZE(szBasic)]);
 -}
 +    }
-     LeaveCriticalSection(&authcache_cs);
- }
  
- static BOOL HTTP_DoAuthorization( http_request_t *lpwhr, LPCWSTR pszAuthValue,
+ static BOOL HTTP_DoAuthorization( LPWININETHTTPREQW lpwhr, LPCWSTR pszAuthValue,
                                    struct HttpAuthInfo **ppAuthInfo,
-                                   LPWSTR domain_and_username, LPWSTR password,
-                                   LPWSTR host )
+                                   LPWSTR domain_and_username, LPWSTR password )
  {
      SECURITY_STATUS sec_status;
      struct HttpAuthInfo *pAuthInfo = *ppAuthInfo;
      {
          int userlen;
          int passlen;
-         char *auth_data = NULL;
-         UINT auth_data_len = 0;
+         char *auth_data;
  
-         TRACE("basic authentication realm %s\n",debugstr_w(szRealm));
+         TRACE("basic authentication\n");
+         /* we don't cache credentials for basic authentication, so we can't
+          * retrieve them if the application didn't pass us any credentials */
+         if (!domain_and_username) return FALSE;
  
-         if (!domain_and_username)
-         {
-             if (host && szRealm)
-                 auth_data_len = retrieve_cached_basic_authorization(host, szRealm,&auth_data);
-             if (auth_data_len == 0)
-             {
-                 HeapFree(GetProcessHeap(),0,szRealm);
-                 return FALSE;
-             }
-         }
-         else
-         {
 -        userlen = WideCharToMultiByte(CP_UTF8, 0, domain_and_username, lstrlenW(domain_and_username), NULL, 0, NULL, NULL);
 -        passlen = WideCharToMultiByte(CP_UTF8, 0, password, lstrlenW(password), NULL, 0, NULL, NULL);
 +            userlen = WideCharToMultiByte(CP_UTF8, 0, domain_and_username, lstrlenW(domain_and_username), NULL, 0, NULL, NULL);
 +            passlen = WideCharToMultiByte(CP_UTF8, 0, password, lstrlenW(password), NULL, 0, NULL, NULL);
  
 -        /* length includes a nul terminator, which will be re-used for the ':' */
 -        auth_data = HeapAlloc(GetProcessHeap(), 0, userlen + 1 + passlen);
 -        if (!auth_data)
 -            return FALSE;
 +            /* length includes a nul terminator, which will be re-used for the ':' */
 +            auth_data = HeapAlloc(GetProcessHeap(), 0, userlen + 1 + passlen);
 +            if (!auth_data)
-             {
-                 HeapFree(GetProcessHeap(),0,szRealm);
 +                return FALSE;
-             }
  
 -        WideCharToMultiByte(CP_UTF8, 0, domain_and_username, -1, auth_data, userlen, NULL, NULL);
 -        auth_data[userlen] = ':';
 -        WideCharToMultiByte(CP_UTF8, 0, password, -1, &auth_data[userlen+1], passlen, NULL, NULL);
 +            WideCharToMultiByte(CP_UTF8, 0, domain_and_username, -1, auth_data, userlen, NULL, NULL);
 +            auth_data[userlen] = ':';
 +            WideCharToMultiByte(CP_UTF8, 0, password, -1, &auth_data[userlen+1], passlen, NULL, NULL);
-             auth_data_len = userlen + 1 + passlen;
-             if (host && szRealm)
-                 cache_basic_authorization(host, szRealm, auth_data, auth_data_len);
-         }
  
          pAuthInfo->auth_data = auth_data;
-         pAuthInfo->auth_data_len = auth_data_len;
+         pAuthInfo->auth_data_len = userlen + 1 + passlen;
          pAuthInfo->finished = TRUE;
-         HeapFree(GetProcessHeap(),0,szRealm);
  
          return TRUE;
      }
@@@ -1039,74 -760,54 +760,54 @@@ BOOL WINAPI HttpAddRequestHeadersA(HINT
  BOOL WINAPI HttpEndRequestA(HINTERNET hRequest, 
          LPINTERNET_BUFFERSA lpBuffersOut, DWORD dwFlags, DWORD_PTR dwContext)
  {
-     TRACE("(%p, %p, %08x, %08lx)\n", hRequest, lpBuffersOut, dwFlags, dwContext);
+     LPINTERNET_BUFFERSA ptr;
+     LPINTERNET_BUFFERSW lpBuffersOutW,ptrW;
+     BOOL rc = FALSE;
  
-     if (lpBuffersOut)
-     {
-         INTERNET_SetLastError(ERROR_INVALID_PARAMETER);
-         return FALSE;
-     }
+     TRACE("(%p, %p, %08x, %08lx): stub\n", hRequest, lpBuffersOut, dwFlags,
+             dwContext);
  
-     return HttpEndRequestW(hRequest, NULL, dwFlags, dwContext);
- }
+     ptr = lpBuffersOut;
+     if (ptr)
+         lpBuffersOutW = (LPINTERNET_BUFFERSW)HeapAlloc(GetProcessHeap(),
+                 HEAP_ZERO_MEMORY, sizeof(INTERNET_BUFFERSW));
+     else
+         lpBuffersOutW = NULL;
  
- static BOOL HTTP_HttpEndRequestW(http_request_t *lpwhr, DWORD dwFlags, DWORD_PTR dwContext)
+     ptrW = lpBuffersOutW;
+     while (ptr)
 -    {
 +{
-     BOOL rc = FALSE;
-     INT responseLen;
-     DWORD dwBufferSize;
-     INTERNET_ASYNC_RESULT iar;
-     INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
-                   INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
+         if (ptr->lpvBuffer && ptr->dwBufferLength)
+             ptrW->lpvBuffer = HeapAlloc(GetProcessHeap(),0,ptr->dwBufferLength);
+         ptrW->dwBufferLength = ptr->dwBufferLength;
+         ptrW->dwBufferTotal= ptr->dwBufferTotal;
  
-     responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE);
-     if (responseLen)
-         rc = TRUE;
-     INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
-                   INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen, sizeof(DWORD));
+         if (ptr->Next)
+             ptrW->Next = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
+                     sizeof(INTERNET_BUFFERSW));
  
-     /* process cookies here. Is this right? */
-     HTTP_ProcessCookies(lpwhr);
+         ptr = ptr->Next;
+         ptrW = ptrW->Next;
+     }
  
-     if (!set_content_length( lpwhr )) HTTP_FinishedReading(lpwhr);
+     rc = HttpEndRequestW(hRequest, lpBuffersOutW, dwFlags, dwContext);
  
-     if (!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT))
+     if (lpBuffersOutW)
      {
-         DWORD dwCode,dwCodeLength = sizeof(DWORD);
-         if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE, &dwCode, &dwCodeLength, NULL) &&
-             (dwCode == 302 || dwCode == 301 || dwCode == 303))
+         ptrW = lpBuffersOutW;
+         while (ptrW)
          {
-             WCHAR *new_url, szNewLocation[INTERNET_MAX_URL_LENGTH];
-             dwBufferSize=sizeof(szNewLocation);
-             if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_LOCATION, szNewLocation, &dwBufferSize, NULL))
-             {
-                 if (strcmpW(lpwhr->lpszVerb, szGET) && strcmpW(lpwhr->lpszVerb, szHEAD))
-                 {
-                     HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb);
-                     lpwhr->lpszVerb = heap_strdupW(szGET);
+             LPINTERNET_BUFFERSW ptrW2;
+             FIXME("Do we need to translate info out of these buffer?\n");
+             HeapFree(GetProcessHeap(),0,ptrW->lpvBuffer);
+             ptrW2 = ptrW->Next;
+             HeapFree(GetProcessHeap(),0,ptrW);
+             ptrW = ptrW2;
 -        }
 -    }
 +                }
-                 HTTP_DrainContent(lpwhr);
-                 if ((new_url = HTTP_GetRedirectURL( lpwhr, szNewLocation )))
-                 {
-                     INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext, INTERNET_STATUS_REDIRECT,
-                                           new_url, (strlenW(new_url) + 1) * sizeof(WCHAR));
-                     rc = HTTP_HandleRedirect(lpwhr, new_url);
-                     if (rc)
-                         rc = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, TRUE);
-                     HeapFree( GetProcessHeap(), 0, new_url );
 +                }
-             }
-         }
-     }
-     iar.dwResult = (DWORD_PTR)lpwhr->hdr.hInternet;
-     iar.dwError = rc ? 0 : INTERNET_GetLastError();
  
-     INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
-                           INTERNET_STATUS_REQUEST_COMPLETE, &iar,
-                           sizeof(INTERNET_ASYNC_RESULT));
      return rc;
  }
  
@@@ -1151,27 -837,58 +837,58 @@@ BOOL WINAPI HttpEndRequestW(HINTERNET h
          INTERNET_SetLastError(ERROR_INTERNET_INCORRECT_HANDLE_TYPE);
          if (lpwhr)
              WININET_Release( &lpwhr->hdr );
 -      return FALSE;
 +        return FALSE;
      }
      lpwhr->hdr.dwFlags |= dwFlags;
+     lpwhr->hdr.dwContext = dwContext;
  
-     if (lpwhr->lpHttpSession->lpAppInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC)
-     {
-         WORKREQUEST work;
-         struct WORKREQ_HTTPENDREQUESTW *request;
+     /* We appear to do nothing with lpBuffersOut.. is that correct? */
  
-         work.asyncproc = AsyncHttpEndRequestProc;
-         work.hdr = WININET_AddRef( &lpwhr->hdr );
+     SendAsyncCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+             INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
+     responseLen = HTTP_GetResponseHeaders(lpwhr, TRUE);
+     if (responseLen)
+           rc = TRUE;
  
-         request = &work.u.HttpEndRequestW;
-         request->dwFlags = dwFlags;
-         request->dwContext = dwContext;
+     SendAsyncCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+             INTERNET_STATUS_RESPONSE_RECEIVED, &responseLen, sizeof(DWORD));
  
-         INTERNET_AsyncCall(&work);
-         INTERNET_SetLastError(ERROR_IO_PENDING);
+     /* process cookies here. Is this right? */
+     HTTP_ProcessCookies(lpwhr);
+     dwBufferSize = sizeof(lpwhr->dwContentLength);
+     if (!HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_CONTENT_LENGTH,
+                              &lpwhr->dwContentLength,&dwBufferSize,NULL))
+         lpwhr->dwContentLength = -1;
+     if (lpwhr->dwContentLength == 0)
+         HTTP_FinishedReading(lpwhr);
+     if(!(lpwhr->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT))
+     {
+         DWORD dwCode,dwCodeLength=sizeof(DWORD);
+         if(HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_FLAG_NUMBER|HTTP_QUERY_STATUS_CODE,&dwCode,&dwCodeLength,NULL) &&
+             (dwCode==302 || dwCode==301))
+         {
+             WCHAR szNewLocation[INTERNET_MAX_URL_LENGTH];
+             dwBufferSize=sizeof(szNewLocation);
+             if(HTTP_HttpQueryInfoW(lpwhr,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,NULL))
+             {
+                 /* redirects are always GETs */
+                 HeapFree(GetProcessHeap(),0,lpwhr->lpszVerb);
+                 lpwhr->lpszVerb = WININET_strdupW(szGET);
+                 HTTP_DrainContent(lpwhr);
+                 INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+                                       INTERNET_STATUS_REDIRECT, szNewLocation,
+                                       dwBufferSize);
+                 rc = HTTP_HandleRedirect(lpwhr, szNewLocation);
+                 if (rc)
+                     rc = HTTP_HttpSendRequestW(lpwhr, NULL, 0, NULL, 0, 0, TRUE);
 -            }
++    }
+         }
      }
-     else
-         rc = HTTP_HttpEndRequestW(lpwhr, dwFlags, dwContext);
  
      WININET_Release( &lpwhr->hdr );
      TRACE("%i <--\n",rc);
@@@ -1292,20 -1017,12 +1017,12 @@@ HINTERNET WINAPI HttpOpenRequestA(HINTE
          types = lpszAcceptTypes;
          while (*types)
          {
-             __TRY
-             {
 -            /* find out how many there are */
 +                /* find out how many there are */
-                 if (*types && **types)
+             if (((ULONG_PTR)*types >> 16) && **types)
 -            {
 -                TRACE("accept type: %s\n", debugstr_a(*types));
 -                acceptTypesCount++;
 -            }
 +                {
 +                    TRACE("accept type: %s\n", debugstr_a(*types));
 +                    acceptTypesCount++;
 +                }
-             }
-             __EXCEPT_PAGE_FAULT
-             {
-                 WARN("invalid accept type pointer\n");
-             }
-             __ENDTRY;
              types++;
          }
          szAcceptTypes = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR *) * (acceptTypesCount+1));
@@@ -1670,14 -1370,13 +1370,13 @@@ static void HTTPREQ_Destroy(WININETHAND
      if(lpwhr->hCacheFile)
          CloseHandle(lpwhr->hCacheFile);
  
 -        HeapFree(GetProcessHeap(), 0, lpwhr->lpszCacheFile);
+     if(lpwhr->lpszCacheFile) {
+         DeleteFileW(lpwhr->lpszCacheFile); /* FIXME */
 +    HeapFree(GetProcessHeap(), 0, lpwhr->lpszCacheFile);
+     }
  
-     DeleteCriticalSection( &lpwhr->read_section );
      WININET_Release(&lpwhr->lpHttpSession->hdr);
  
-     destroy_authinfo(lpwhr->pAuthInfo);
-     destroy_authinfo(lpwhr->pProxyAuthInfo);
      HeapFree(GetProcessHeap(), 0, lpwhr->lpszPath);
      HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb);
      HeapFree(GetProcessHeap(), 0, lpwhr->lpszRawHeaders);
@@@ -1711,105 -1402,45 +1402,45 @@@ static void HTTPREQ_CloseConnection(WIN
      if (!NETCON_connected(&lpwhr->netConnection))
          return;
  
-     INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
-                           INTERNET_STATUS_CLOSING_CONNECTION, 0, 0);
-     NETCON_close(&lpwhr->netConnection);
-     INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
-                           INTERNET_STATUS_CONNECTION_CLOSED, 0, 0);
- }
- static BOOL HTTP_GetRequestURL(http_request_t *req, LPWSTR buf)
+     if (lpwhr->pAuthInfo)
 -    {
 +{
-     LPHTTPHEADERW host_header;
-     static const WCHAR formatW[] = {'h','t','t','p',':','/','/','%','s','%','s',0};
-     host_header = HTTP_GetHeader(req, hostW);
-     if(!host_header)
-         return FALSE;
-     sprintfW(buf, formatW, host_header->lpszValue, req->lpszPath); /* FIXME */
-     return TRUE;
+         if (SecIsValidHandle(&lpwhr->pAuthInfo->ctx))
+             DeleteSecurityContext(&lpwhr->pAuthInfo->ctx);
+         if (SecIsValidHandle(&lpwhr->pAuthInfo->cred))
+             FreeCredentialsHandle(&lpwhr->pAuthInfo->cred);
+         HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo->auth_data);
+         HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo->scheme);
+         HeapFree(GetProcessHeap(), 0, lpwhr->pAuthInfo);
+         lpwhr->pAuthInfo = NULL;
 -    }
 +}
- static BOOL HTTP_KeepAlive(http_request_t *lpwhr)
+     if (lpwhr->pProxyAuthInfo)
 -    {
 +{
-     WCHAR szVersion[10];
-     WCHAR szConnectionResponse[20];
-     DWORD dwBufferSize = sizeof(szVersion);
-     BOOL keepalive = FALSE;
+         if (SecIsValidHandle(&lpwhr->pProxyAuthInfo->ctx))
+             DeleteSecurityContext(&lpwhr->pProxyAuthInfo->ctx);
+         if (SecIsValidHandle(&lpwhr->pProxyAuthInfo->cred))
+             FreeCredentialsHandle(&lpwhr->pProxyAuthInfo->cred);
  
-     /* as per RFC 2068, S8.1.2.1, if the client is HTTP/1.1 then assume that
-      * the connection is keep-alive by default */
-     if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_VERSION, szVersion,
-                              &dwBufferSize, NULL) &&
-         !strcmpiW(szVersion, g_szHttp1_1))
-     {
-         keepalive = TRUE;
+         HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo->auth_data);
+         HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo->scheme);
+         HeapFree(GetProcessHeap(), 0, lpwhr->pProxyAuthInfo);
+         lpwhr->pProxyAuthInfo = NULL;
      }
  
-     dwBufferSize = sizeof(szConnectionResponse);
-     if (HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_PROXY_CONNECTION, szConnectionResponse, &dwBufferSize, NULL) ||
-         HTTP_HttpQueryInfoW(lpwhr, HTTP_QUERY_CONNECTION, szConnectionResponse, &dwBufferSize, NULL))
-     {
-         keepalive = !strcmpiW(szConnectionResponse, szKeepAlive);
-     }
-     return keepalive;
- }
- static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
- {
-     http_request_t *req = (http_request_t*)hdr;
-     switch(option) {
-     case INTERNET_OPTION_DIAGNOSTIC_SOCKET_INFO:
-     {
-         http_session_t *lpwhs = req->lpHttpSession;
-         INTERNET_DIAGNOSTIC_SOCKET_INFO *info = buffer;
-         FIXME("INTERNET_DIAGNOSTIC_SOCKET_INFO stub\n");
+     INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+                           INTERNET_STATUS_CLOSING_CONNECTION, 0, 0);
  
-         if (*size < sizeof(INTERNET_DIAGNOSTIC_SOCKET_INFO))
-             return ERROR_INSUFFICIENT_BUFFER;
-         *size = sizeof(INTERNET_DIAGNOSTIC_SOCKET_INFO);
-         /* FIXME: can't get a SOCKET from our connection since we don't use
-          * winsock
-          */
-         info->Socket = 0;
-         /* FIXME: get source port from req->netConnection */
-         info->SourcePort = 0;
-         info->DestPort = lpwhs->nHostPort;
-         info->Flags = 0;
-         if (HTTP_KeepAlive(req))
-             info->Flags |= IDSI_FLAG_KEEP_ALIVE;
-         if (lpwhs->lpAppInfo->lpszProxy && lpwhs->lpAppInfo->lpszProxy[0] != 0)
-             info->Flags |= IDSI_FLAG_PROXY;
-         if (req->netConnection.useSSL)
-             info->Flags |= IDSI_FLAG_SECURE;
+     NETCON_close(&lpwhr->netConnection);
  
-         return ERROR_SUCCESS;
+     INTERNET_SendCallback(&lpwhr->hdr, lpwhr->hdr.dwContext,
+                           INTERNET_STATUS_CONNECTION_CLOSED, 0, 0);
 -}
 +    }
  
-     case INTERNET_OPTION_SECURITY_FLAGS:
+ static DWORD HTTPREQ_QueryOption(WININETHANDLEHEADER *hdr, DWORD option, void *buffer, DWORD *size, BOOL unicode)
 -{
 +    {
-         http_session_t *lpwhs;
-         lpwhs = req->lpHttpSession;
-         if (*size < sizeof(ULONG))
-             return ERROR_INSUFFICIENT_BUFFER;
-         *size = sizeof(DWORD);
-         if (lpwhs->hdr.dwFlags & INTERNET_FLAG_SECURE)
-             *(DWORD*)buffer = SECURITY_FLAG_SECURE;
-         else
-             *(DWORD*)buffer = 0;
-         FIXME("Semi-STUB INTERNET_OPTION_SECURITY_FLAGS: %x\n",*(DWORD*)buffer);
-         return ERROR_SUCCESS;
-     }
+     WININETHTTPREQW *req = (WININETHTTPREQW*)hdr;
  
+     switch(option) {
      case INTERNET_OPTION_HANDLE_TYPE:
          TRACE("INTERNET_OPTION_HANDLE_TYPE\n");
  
@@@ -2021,328 -1603,139 +1603,139 @@@ static DWORD HTTPREQ_SetOption(WININETH
      return ERROR_INTERNET_INVALID_OPTION;
  }
  
- /* read some more data into the read buffer (the read section must be held) */
- static BOOL read_more_data( http_request_t *req, int maxlen )
+ static DWORD HTTP_Read(WININETHTTPREQW *req, void *buffer, DWORD size, DWORD *read, BOOL sync)
  {
-     int len;
-     if (req->read_pos)
-     {
-         /* move existing data to the start of the buffer */
-         if(req->read_size)
-             memmove( req->read_buf, req->read_buf + req->read_pos, req->read_size );
-         req->read_pos = 0;
-     }
+     int bytes_read;
  
-     if (maxlen == -1) maxlen = sizeof(req->read_buf);
-     if(!NETCON_recv( &req->netConnection, req->read_buf + req->read_size,
-                      maxlen - req->read_size, 0, &len ))
-         return FALSE;
-     req->read_size += len;
-     return TRUE;
- }
+     if(!NETCON_recv(&req->netConnection, buffer, min(size, req->dwContentLength - req->dwContentRead),
+                      sync ? MSG_WAITALL : 0, &bytes_read)) {
+         if(req->dwContentLength != -1 && req->dwContentRead != req->dwContentLength)
+             ERR("not all data received %d/%d\n", req->dwContentRead, req->dwContentLength);
  
- /* remove some amount of data from the read buffer (the read section must be held) */
- static void remove_data( http_request_t *req, int count )
- {
-     if (!(req->read_size -= count)) req->read_pos = 0;
-     else req->read_pos += count;
+         /* always return success, even if the network layer returns an error */
+         *read = 0;
+         HTTP_FinishedReading(req);
+         return ERROR_SUCCESS;
 -    }
 +}
  
- static BOOL read_line( http_request_t *req, LPSTR buffer, DWORD *len )
- {
-     int count, bytes_read, pos = 0;
+     req->dwContentRead += bytes_read;
+     *read = bytes_read;
  
-     EnterCriticalSection( &req->read_section );
-     for (;;)
-     {
-         BYTE *eol = memchr( req->read_buf + req->read_pos, '\n', req->read_size );
+     if(req->lpszCacheFile) {
+         BOOL res;
+         DWORD dwBytesWritten;
  
-         if (eol)
-         {
-             count = eol - (req->read_buf + req->read_pos);
-             bytes_read = count + 1;
+         res = WriteFile(req->hCacheFile, buffer, bytes_read, &dwBytesWritten, NULL);
+         if(!res)
+             WARN("WriteFile failed: %u\n", GetLastError());
 -    }
 +        }
-         else count = bytes_read = req->read_size;
  
-         count = min( count, *len - pos );
-         memcpy( buffer + pos, req->read_buf + req->read_pos, count );
-         pos += count;
-         remove_data( req, bytes_read );
-         if (eol) break;
+     if(!bytes_read && (req->dwContentRead == req->dwContentLength))
+         HTTP_FinishedReading(req);
  
-         if (!read_more_data( req, -1 ) || !req->read_size)
-         {
-             *len = 0;
-             TRACE( "returning empty string\n" );
-             LeaveCriticalSection( &req->read_section );
-             return FALSE;
+     return ERROR_SUCCESS;
 -}
 +        }
-     }
-     LeaveCriticalSection( &req->read_section );
  
    if (pos < *len)
static DWORD get_chunk_size(const char *buffer)
 -{
 +    {
-         if (pos && buffer[pos - 1] == '\r') pos--;
-         *len = pos + 1;
-     }
-     buffer[*len - 1] = 0;
-     TRACE( "returning %s\n", debugstr_a(buffer));
-     return TRUE;
- }
+     const char *p;
+     DWORD size = 0;
  
- /* discard data contents until we reach end of line (the read section must be held) */
- static BOOL discard_eol( http_request_t *req )
+     for (p = buffer; *p; p++)
 -    {
 +{
-     do
-     {
-         BYTE *eol = memchr( req->read_buf + req->read_pos, '\n', req->read_size );
-         if (eol)
-         {
-             remove_data( req, (eol + 1) - (req->read_buf + req->read_pos) );
-             break;
+         if (*p >= '0' && *p <= '9') size = size * 16 + *p - '0';
+         else if (*p >= 'a' && *p <= 'f') size = size * 16 + *p - 'a' + 10;
+         else if (*p >= 'A' && *p <= 'F') size = size * 16 + *p - 'A' + 10;
+         else if (*p == ';') break;
 -    }
 +        }
-         req->read_pos = req->read_size = 0;  /* discard everything */
-         if (!read_more_data( req, -1 )) return FALSE;
-     } while (req->read_size);
-     return TRUE;
+     return size;
  }
  
- /* read the size of the next chunk (the read section must be held) */
- static BOOL start_next_chunk( http_request_t *req )
+ static DWORD HTTP_ReadChunked(WININETHTTPREQW *req, void *buffer, DWORD size, DWORD *read, BOOL sync)
  {
-     DWORD chunk_size = 0;
+     char reply[MAX_REPLY_LEN], *p = buffer;
+     DWORD buflen, to_read, to_write = size;
+     int bytes_read;
  
-     if (!req->dwContentLength) return TRUE;
-     if (req->dwContentLength == req->dwContentRead)
-     {
-         /* read terminator for the previous chunk */
-         if (!discard_eol( req )) return FALSE;
-         req->dwContentLength = ~0u;
-         req->dwContentRead = 0;
-     }
+     *read = 0;
      for (;;)
      {
-         while (req->read_size)
-         {
-             char ch = req->read_buf[req->read_pos];
-             if (ch >= '0' && ch <= '9') chunk_size = chunk_size * 16 + ch - '0';
-             else if (ch >= 'a' && ch <= 'f') chunk_size = chunk_size * 16 + ch - 'a' + 10;
-             else if (ch >= 'A' && ch <= 'F') chunk_size = chunk_size * 16 + ch - 'A' + 10;
-             else if (ch == ';' || ch == '\r' || ch == '\n')
-             {
-                 TRACE( "reading %u byte chunk\n", chunk_size );
-                 req->dwContentLength = chunk_size;
-                 req->dwContentRead = 0;
-                 if (!discard_eol( req )) return FALSE;
-                 return TRUE;
-             }
-             remove_data( req, 1 );
-         }
-         if (!read_more_data( req, -1 )) return FALSE;
-         if (!req->read_size)
-         {
-             req->dwContentLength = req->dwContentRead = 0;
-             return TRUE;
-         }
-     }
- }
+         if (*read == size) break;
  
- /* check if we have reached the end of the data to read (the read section must be held) */
- static BOOL end_of_read_data( http_request_t *req )
+         if (req->dwContentLength == ~0UL) /* new chunk */
 -        {
 +{
-     if (req->gzip_stream) return req->gzip_stream->end_of_data && !req->gzip_stream->buf_size;
-     if (req->read_chunked) return (req->dwContentLength == 0);
-     if (req->dwContentLength == ~0u) return FALSE;
-     return (req->dwContentLength == req->dwContentRead);
- }
+             buflen = sizeof(reply);
+             if (!NETCON_getNextLine(&req->netConnection, reply, &buflen)) break;
  
- /* fetch some more data into the read buffer (the read section must be held) */
- static BOOL refill_buffer( http_request_t *req )
+             if (!(req->dwContentLength = get_chunk_size(reply)))
 -            {
 +{
-     int len = sizeof(req->read_buf);
-     if (req->read_chunked && (req->dwContentLength == ~0u || req->dwContentLength == req->dwContentRead))
-     {
-         if (!start_next_chunk( req )) return FALSE;
+                 /* zero sized chunk marks end of transfer; read any trailing headers and return */
+                 HTTP_GetResponseHeaders(req, FALSE);
+                 break;
 -            }
 -        }
 +    }
-     if (req->dwContentLength != ~0u) len = min( len, req->dwContentLength - req->dwContentRead );
-     if (len <= req->read_size) return TRUE;
-     if (!read_more_data( req, len )) return FALSE;
-     if (!req->read_size) req->dwContentLength = req->dwContentRead = 0;
-     return TRUE;
 +}
+         to_read = min(to_write, req->dwContentLength - req->dwContentRead);
  
static DWORD read_gzip_data(http_request_t *req, BYTE *buf, int size, BOOL sync, int *read_ret)
        if (!NETCON_recv(&req->netConnection, p, to_read, sync ? MSG_WAITALL : 0, &bytes_read))
 -        {
 +{
-     DWORD ret = ERROR_SUCCESS;
-     int read = 0;
- #ifdef HAVE_ZLIB
-     z_stream *zstream = &req->gzip_stream->zstream;
-     int zres;
+             if (bytes_read != to_read)
+                 ERR("Not all data received %d/%d\n", bytes_read, to_read);
  
-     while(read < size && !req->gzip_stream->end_of_data) {
-         if(!req->read_size) {
-             if(!sync || !refill_buffer(req))
+             /* always return success, even if the network layer returns an error */
+             *read = 0;
 -            break;
 +                break;
          }
+         if (!bytes_read) break;
  
-         zstream->next_in = req->read_buf+req->read_pos;
-         zstream->avail_in = req->read_size;
-         zstream->next_out = buf+read;
-         zstream->avail_out = size-read;
-         zres = inflate(zstream, Z_FULL_FLUSH);
-         read = size - zstream->avail_out;
-         remove_data(req, req->read_size-zstream->avail_in);
-         if(zres == Z_STREAM_END) {
-             TRACE("end of data\n");
-             req->gzip_stream->end_of_data = TRUE;
-             inflateEnd(&req->gzip_stream->zstream);
-         }else if(zres != Z_OK) {
-             WARN("inflate failed %d\n", zres);
-             if(!read)
-                 ret = ERROR_INTERNET_DECODING_FAILED;
-             break;
-         }
-     }
- #endif
-     *read_ret = read;
-     return ret;
- }
+         req->dwContentRead += bytes_read;
+         to_write -= bytes_read;
+         *read += bytes_read;
  
static void refill_gzip_buffer(http_request_t *req)
        if (req->lpszCacheFile)
 -        {
 +{
-     DWORD res;
-     int len;
-     if(!req->gzip_stream || !req->read_size || req->gzip_stream->buf_size == sizeof(req->gzip_stream->buf))
-         return;
+             DWORD dwBytesWritten;
  
-     if(req->gzip_stream->buf_pos) {
-         if(req->gzip_stream->buf_size)
-             memmove(req->gzip_stream->buf, req->gzip_stream->buf + req->gzip_stream->buf_pos, req->gzip_stream->buf_size);
-         req->gzip_stream->buf_pos = 0;
+             if (!WriteFile(req->hCacheFile, p, bytes_read, &dwBytesWritten, NULL))
+                 WARN("WriteFile failed: %u\n", GetLastError());
 -        }
 +    }
+         p += bytes_read;
  
-     res = read_gzip_data(req, req->gzip_stream->buf + req->gzip_stream->buf_size,
-             sizeof(req->gzip_stream->buf) - req->gzip_stream->buf_size, FALSE, &len);
-     if(res == ERROR_SUCCESS)
-         req->gzip_stream->buf_size += len;
- }
+         if (req->dwContentRead == req->dwContentLength) /* chunk complete */
+         {
+             req->dwContentRead = 0;
+             req->dwContentLength = ~0UL;
  
- /* return the size of data available to be read immediately (the read section must be held) */
static DWORD get_avail_data( http_request_t *req )
+             buflen = sizeof(reply);
            if (!NETCON_getNextLine(&req->netConnection, reply, &buflen))
 -            {
 +{
-     if (req->gzip_stream) {
-         refill_gzip_buffer(req);
-         return req->gzip_stream->buf_size;
+                 ERR("Malformed chunk\n");
+                 *read = 0;
+                 break;
 -            }
 -        }
 +    }
-     if (req->read_chunked && (req->dwContentLength == ~0u || req->dwContentLength == req->dwContentRead))
-         return 0;
-     return min( req->read_size, req->dwContentLength - req->dwContentRead );
 +}
- static void HTTP_ReceiveRequestData(http_request_t *req, BOOL first_notif)
- {
-     INTERNET_ASYNC_RESULT iar;
-     TRACE("%p\n", req);
-     EnterCriticalSection( &req->read_section );
-     if (refill_buffer( req )) {
-         iar.dwResult = (DWORD_PTR)req->hdr.hInternet;
-         iar.dwError = first_notif ? 0 : get_avail_data(req);
-     }else {
-         iar.dwResult = 0;
-         iar.dwError = INTERNET_GetLastError();
      }
-     LeaveCriticalSection( &req->read_section );
-     INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_REQUEST_COMPLETE, &iar,
-                           sizeof(INTERNET_ASYNC_RESULT));
+     if (!*read) HTTP_FinishedReading(req);
+     return ERROR_SUCCESS;
  }
  
- /* read data from the http connection (the read section must be held) */
- static DWORD HTTPREQ_Read(http_request_t *req, void *buffer, DWORD size, DWORD *read, BOOL sync)
+ static DWORD HTTPREQ_Read(WININETHTTPREQW *req, void *buffer, DWORD size, DWORD *read, BOOL sync)
  {
-     BOOL finished_reading = FALSE;
-     int len, bytes_read = 0;
-     DWORD ret = ERROR_SUCCESS;
-     EnterCriticalSection( &req->read_section );
+     WCHAR encoding[20];
+     DWORD buflen = sizeof(encoding);
+     static const WCHAR szChunked[] = {'c','h','u','n','k','e','d',0};
  
-     if (req->read_chunked && (req->dwContentLength == ~0u || req->dwContentLength == req->dwContentRead))
+     if (HTTP_HttpQueryInfoW(req, HTTP_QUERY_TRANSFER_ENCODING, encoding, &buflen, NULL) &&
+         !strcmpiW(encoding, szChunked))
      {
-         if (!start_next_chunk( req )) goto done;
+         return HTTP_ReadChunked(req, buffer, size, read, sync);
      }
-     if(req->gzip_stream) {
-         if(req->gzip_stream->buf_size) {
-             bytes_read = min(req->gzip_stream->buf_size, size);
-             memcpy(buffer, req->gzip_stream->buf + req->gzip_stream->buf_pos, bytes_read);
-             req->gzip_stream->buf_pos += bytes_read;
-             req->gzip_stream->buf_size -= bytes_read;
-         }else if(!req->read_size && !req->gzip_stream->end_of_data) {
-             refill_buffer(req);
-         }
-         if(size > bytes_read) {
-             ret = read_gzip_data(req, (BYTE*)buffer+bytes_read, size-bytes_read, sync, &len);
-             if(ret == ERROR_SUCCESS)
-                 bytes_read += len;
-         }
-         finished_reading = req->gzip_stream->end_of_data && !req->gzip_stream->buf_size;
-     }else {
-         if (req->dwContentLength != ~0u) size = min( size, req->dwContentLength - req->dwContentRead );
-         if (req->read_size) {
-             bytes_read = min( req->read_size, size );
-             memcpy( buffer, req->read_buf + req->read_pos, bytes_read );
-             remove_data( req, bytes_read );
-         }
-         if (size > bytes_read && (!bytes_read || sync)) {
-             if (NETCON_recv( &req->netConnection, (char *)buffer + bytes_read, size - bytes_read,
-                              sync ? MSG_WAITALL : 0, &len))
-                 bytes_read += len;
-             /* always return success, even if the network layer returns an error */
+     else
+         return HTTP_Read(req, buffer, size, read, sync);
 -}
 +        }
  
-         finished_reading = !bytes_read && req->dwContentRead == req->dwContentLength;
-     }
- done:
-     req->dwContentRead += bytes_read;
-     *read = bytes_read;
-     TRACE( "retrieved %u bytes (%u/%u)\n", bytes_read, req->dwContentRead, req->dwContentLength );
-     LeaveCriticalSection( &req->read_section );
-     if(ret == ERROR_SUCCESS && req->lpszCacheFile) {
-         BOOL res;
-         DWORD dwBytesWritten;
-         res = WriteFile(req->hCacheFile, buffer, bytes_read, &dwBytesWritten, NULL);
-         if(!res)
-             WARN("WriteFile failed: %u\n", GetLastError());
-     }
-     if(finished_reading)
-         HTTP_FinishedReading(req);
-     return ret;
- }
- static DWORD HTTPREQ_ReadFile(object_header_t *hdr, void *buffer, DWORD size, DWORD *read)
+ static DWORD HTTPREQ_ReadFile(WININETHANDLEHEADER *hdr, void *buffer, DWORD size, DWORD *read)
  {
-     http_request_t *req = (http_request_t*)hdr;
+     WININETHTTPREQW *req = (WININETHTTPREQW*)hdr;
      return HTTPREQ_Read(req, buffer, size, read, TRUE);
  }
  
@@@ -2380,30 -1774,23 +1774,23 @@@ static DWORD HTTPREQ_ReadFileExA(WININE
  
      INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0);
  
-     if ((hdr->dwFlags & INTERNET_FLAG_ASYNC) && !get_avail_data(req))
+     if (hdr->dwFlags & INTERNET_FLAG_ASYNC) {
+         DWORD available = 0;
+         NETCON_query_data_available(&req->netConnection, &available);
+         if (!available)
 -        {
 -            WORKREQUEST workRequest;
 +    {
 +        WORKREQUEST workRequest;
  
-         if (TryEnterCriticalSection( &req->read_section ))
-         {
-             if (get_avail_data(req))
-             {
-                 res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength,
-                                    &buffers->dwBufferLength, FALSE);
-                 LeaveCriticalSection( &req->read_section );
-                 goto done;
-             }
-             LeaveCriticalSection( &req->read_section );
-         }
-         workRequest.asyncproc = HTTPREQ_AsyncReadFileExAProc;
+             workRequest.asyncproc = HTTPREQ_AsyncReadFileExProc;
 -            workRequest.hdr = WININET_AddRef(&req->hdr);
 -            workRequest.u.InternetReadFileExA.lpBuffersOut = buffers;
 +        workRequest.hdr = WININET_AddRef(&req->hdr);
 +        workRequest.u.InternetReadFileExA.lpBuffersOut = buffers;
  
 -            INTERNET_AsyncCall(&workRequest);
 +        INTERNET_AsyncCall(&workRequest);
  
 -            return ERROR_IO_PENDING;
 -        }
 +        return ERROR_IO_PENDING;
 +    }
+     }
  
      res = HTTPREQ_Read(req, buffers->lpvBuffer, buffers->dwBufferLength, &buffers->dwBufferLength,
              !(flags & IRF_NO_WAIT));
      return res;
  }
  
- static void HTTPREQ_AsyncReadFileExWProc(WORKREQUEST *workRequest)
+ static BOOL HTTPREQ_WriteFile(WININETHANDLEHEADER *hdr, const void *buffer, DWORD size, DWORD *written)
  {
-     struct WORKREQ_INTERNETREADFILEEXW const *data = &workRequest->u.InternetReadFileExW;
-     http_request_t *req = (http_request_t*)workRequest->hdr;
-     INTERNET_ASYNC_RESULT iar;
-     DWORD res;
-     TRACE("INTERNETREADFILEEXW %p\n", workRequest->hdr);
-     res = HTTPREQ_Read(req, data->lpBuffersOut->lpvBuffer,
-             data->lpBuffersOut->dwBufferLength, &data->lpBuffersOut->dwBufferLength, TRUE);
+     LPWININETHTTPREQW lpwhr = (LPWININETHTTPREQW)hdr;
  
-&nb