Sync with trunk r63270.
authorDavid Quintana <gigaherz@gmail.com>
Tue, 13 May 2014 12:11:12 +0000 (12:11 +0000)
committerDavid Quintana <gigaherz@gmail.com>
Tue, 13 May 2014 12:11:12 +0000 (12:11 +0000)
svn path=/branches/shell-experiments/; revision=63271

439 files changed:
1  2 
base/applications/dxdiag/lang/tr-TR.rc
base/applications/games/solitaire/lang/tr-TR.rc
base/applications/msconfig/lang/tr-TR.rc
base/applications/mscutils/devmgmt/lang/cs-CZ.rc
base/applications/mscutils/eventvwr/eventvwr.rc
base/applications/mscutils/eventvwr/lang/cs-CZ.rc
base/applications/mscutils/servman/lang/cs-CZ.rc
base/applications/mscutils/servman/lang/tr-TR.rc
base/applications/mscutils/servman/servman.rc
base/applications/rapps/lang/cs-CZ.rc
base/applications/rapps/lang/tr-TR.rc
base/applications/rapps/rapps/abiword.txt
base/applications/rapps/rapps/abiword26.txt
base/applications/rapps/rapps/abyss.txt
base/applications/rapps/rapps/ac97forvirtualbox.txt
base/applications/rapps/rapps/alreader.txt
base/applications/rapps/rapps/ants.txt
base/applications/rapps/rapps/audiograbber.txt
base/applications/rapps/rapps/bittorrent.txt
base/applications/rapps/rapps/bochs.txt
base/applications/rapps/rapps/boswars.txt
base/applications/rapps/rapps/boundaround.txt
base/applications/rapps/rapps/christmasbound.txt
base/applications/rapps/rapps/chromium.txt
base/applications/rapps/rapps/cnt.txt
base/applications/rapps/rapps/codeblocks.txt
base/applications/rapps/rapps/codeblocks_gcc.txt
base/applications/rapps/rapps/codeblocks_gcc_2.txt
base/applications/rapps/rapps/comctl32ocx.txt
base/applications/rapps/rapps/devcpp_mingw32.txt
base/applications/rapps/rapps/devcpp_tdm_gcc_x64.txt
base/applications/rapps/rapps/diablo2.txt
base/applications/rapps/rapps/dosblaster.txt
base/applications/rapps/rapps/dosbox.txt
base/applications/rapps/rapps/doublecommander.txt
base/applications/rapps/rapps/dplus.txt
base/applications/rapps/rapps/dvdwritenow.txt
base/applications/rapps/rapps/excelview.txt
base/applications/rapps/rapps/fap.txt
base/applications/rapps/rapps/fira.txt
base/applications/rapps/rapps/firefox.txt
base/applications/rapps/rapps/firefox2.txt
base/applications/rapps/rapps/firefox3.txt
base/applications/rapps/rapps/firefox36.txt
base/applications/rapps/rapps/freebasic.txt
base/applications/rapps/rapps/glidewrapzbag.txt
base/applications/rapps/rapps/globulation2.txt
base/applications/rapps/rapps/hover.txt
base/applications/rapps/rapps/hxd.txt
base/applications/rapps/rapps/indiftpd.txt
base/applications/rapps/rapps/irfanview.txt
base/applications/rapps/rapps/irfanviewplugins.txt
base/applications/rapps/rapps/kdewin.txt
base/applications/rapps/rapps/kyodai.txt
base/applications/rapps/rapps/lazaruside.txt
base/applications/rapps/rapps/lbreakout2.txt
base/applications/rapps/rapps/lgeneral.txt
base/applications/rapps/rapps/libreoffice.txt
base/applications/rapps/rapps/lmarbles.txt
base/applications/rapps/rapps/mcwin32.txt
base/applications/rapps/rapps/mfc40.txt
base/applications/rapps/rapps/mirandaim.txt
base/applications/rapps/rapps/mirc.txt
base/applications/rapps/rapps/mirc6.txt
base/applications/rapps/rapps/mono2.txt
base/applications/rapps/rapps/mpc.txt
base/applications/rapps/rapps/mpxplay.txt
base/applications/rapps/rapps/msxml3.txt
base/applications/rapps/rapps/net11.txt
base/applications/rapps/rapps/net20.txt
base/applications/rapps/rapps/net20sp2.txt
base/applications/rapps/rapps/npp.txt
base/applications/rapps/rapps/offbyone.txt
base/applications/rapps/rapps/opencodecs.txt
base/applications/rapps/rapps/openoffice.txt
base/applications/rapps/rapps/openoffice2.4.txt
base/applications/rapps/rapps/openttd.txt
base/applications/rapps/rapps/opera.txt
base/applications/rapps/rapps/opera9.txt
base/applications/rapps/rapps/peazip.txt
base/applications/rapps/rapps/pengupop.txt
base/applications/rapps/rapps/photofiltre.txt
base/applications/rapps/rapps/pingus.txt
base/applications/rapps/rapps/pptview.txt
base/applications/rapps/rapps/pspad.txt
base/applications/rapps/rapps/ptanks.txt
base/applications/rapps/rapps/putty.txt
base/applications/rapps/rapps/python.txt
base/applications/rapps/rapps/python2.txt
base/applications/rapps/rapps/qb64sdl.txt
base/applications/rapps/rapps/qmmp.txt
base/applications/rapps/rapps/remood.txt
base/applications/rapps/rapps/reshack.txt
base/applications/rapps/rapps/rocks.txt
base/applications/rapps/rapps/rosbe.txt
base/applications/rapps/rapps/rosbeamd64.txt
base/applications/rapps/rapps/rosbearm.txt
base/applications/rapps/rapps/sambatng.txt
base/applications/rapps/rapps/sbforvmware.txt
base/applications/rapps/rapps/scite.txt
base/applications/rapps/rapps/scummvm.txt
base/applications/rapps/rapps/sdl_mixer.txt
base/applications/rapps/rapps/sdl_runtime.txt
base/applications/rapps/rapps/seamonkey.txt
base/applications/rapps/rapps/smplayer.txt
base/applications/rapps/rapps/snoopy.txt
base/applications/rapps/rapps/stamina.txt
base/applications/rapps/rapps/steam.txt
base/applications/rapps/rapps/sumatrapdf.txt
base/applications/rapps/rapps/summerbound.txt
base/applications/rapps/rapps/superdxb.txt
base/applications/rapps/rapps/superfinder.txt
base/applications/rapps/rapps/supertux.txt
base/applications/rapps/rapps/tahoma.txt
base/applications/rapps/rapps/thunderbird.txt
base/applications/rapps/rapps/thunderbird3.txt
base/applications/rapps/rapps/tileworld.txt
base/applications/rapps/rapps/totalcommander.txt
base/applications/rapps/rapps/tuxpaint.txt
base/applications/rapps/rapps/ultravnc.txt
base/applications/rapps/rapps/utorrent.txt
base/applications/rapps/rapps/vb5run.txt
base/applications/rapps/rapps/vb6run.txt
base/applications/rapps/rapps/vc2005sp1run.txt
base/applications/rapps/rapps/vc2008sp1run.txt
base/applications/rapps/rapps/vc2010run.txt
base/applications/rapps/rapps/vc6run.txt
base/applications/rapps/rapps/vlc.txt
base/applications/rapps/rapps/winboard.txt
base/applications/rapps/rapps/wme9.txt
base/applications/rapps/rapps/wordview.txt
base/applications/rapps/rapps/zaz.txt
base/applications/regedit/lang/tr-TR.rc
base/applications/sndvol32/lang/tr-TR.rc
base/applications/taskmgr/lang/tr-TR.rc
base/setup/reactos/lang/tr-TR.rc
base/setup/reactos/reactos.rc
base/setup/usetup/bootsup.c
base/setup/usetup/bootsup.h
base/setup/usetup/chkdsk.c
base/setup/usetup/drivesup.c
base/setup/usetup/drivesup.h
base/setup/usetup/filequeue.c
base/setup/usetup/filequeue.h
base/setup/usetup/filesup.c
base/setup/usetup/filesup.h
base/setup/usetup/format.c
base/setup/usetup/fslist.c
base/setup/usetup/fslist.h
base/setup/usetup/genlist.c
base/setup/usetup/genlist.h
base/setup/usetup/host.h
base/setup/usetup/inffile.c
base/setup/usetup/inffile.h
base/setup/usetup/inicache.c
base/setup/usetup/inicache.h
base/setup/usetup/mui.c
base/setup/usetup/mui.h
base/setup/usetup/muilanguages.h
base/setup/usetup/progress.c
base/setup/usetup/progress.h
base/setup/usetup/registry.c
base/setup/usetup/registry.h
base/setup/usetup/settings.c
base/setup/usetup/settings.h
base/setup/usetup/usetup.h
base/setup/vmwinst/lang/tr-TR.rc
base/setup/vmwinst/vmwinst.rc
base/setup/welcome/lang/tr-TR.rc
base/setup/welcome/welcome.rc
base/shell/cmd/copy.c
base/shell/cmd/replace.c
base/shell/explorer-new/lang/tr-TR.rc
base/shell/explorer/explorer-cz.rc
base/shell/explorer/explorer.rc
base/system/rundll32/lang/tr-TR.rc
base/system/rundll32/rundll32.rc
base/system/runonce/lang/tr-TR.rc
base/system/runonce/runonce.rc
base/system/userinit/lang/tr-TR.rc
base/system/userinit/userinit.rc
base/system/winlogon/lang/tr-TR.rc
base/system/winlogon/winlogon.rc
cmake/msvc.cmake
dll/cpl/access/access.rc
dll/cpl/access/lang/cs-CZ.rc
dll/cpl/hdwwiz/hdwwiz.rc
dll/cpl/hdwwiz/lang/cs-CZ.rc
dll/cpl/inetcpl/inetcpl.rc
dll/cpl/inetcpl/lang/cs-CZ.rc
dll/cpl/joy/joy.rc
dll/cpl/joy/lang/cs-CZ.rc
dll/cpl/mmsys/lang/cs-CZ.rc
dll/cpl/mmsys/mmsys.rc
dll/cpl/powercfg/lang/cs-CZ.rc
dll/cpl/powercfg/powercfg.rc
dll/cpl/timedate/lang/cs-CZ.rc
dll/cpl/timedate/timedate.rc
dll/cpl/usrmgr/lang/cs-CZ.rc
dll/cpl/usrmgr/usrmgr.rc
dll/directx/wine/msdmo/dmoreg.c
dll/directx/wine/quartz/avisplit.c
dll/ntdll/CMakeLists.txt
dll/ntdll/csr/capture.c
dll/ntdll/def/ntdll.spec
dll/ntdll/rtl/libsupp.c
dll/win32/atl/CMakeLists.txt
dll/win32/comctl32/treeview.c
dll/win32/icmp/icmp_main.c
dll/win32/ieframe/shelluihelper.c
dll/win32/kernel32/client/proc.c
dll/win32/kernel32/client/time.c
dll/win32/kernel32/client/vdm.c
dll/win32/kernel32/include/vdm.h
dll/win32/kernel32/k32.h
dll/win32/kernel32/wine/actctx.c
dll/win32/mshtml/CMakeLists.txt
dll/win32/mshtml/msvc.S
dll/win32/msvcrt/msvcrt.spec
dll/win32/rpcrt4/rpc_transport.c
dll/win32/rpcrt4/rpcrt4_ros.diff
dll/win32/setupapi/CMakeLists.txt
dll/win32/setupapi/install.c
dll/win32/setupapi/misc.c
dll/win32/setupapi/setupapi.spec
dll/win32/setupapi/setupapi_private.h
dll/win32/shell32/folders/cpanel.cpp
dll/win32/shell32/lang/cs-CZ.rc
dll/win32/shell32/shlexec.cpp
dll/win32/shlwapi/path.c
dll/win32/syssetup/lang/cs-CZ.rc
drivers/base/kdcom/kdserial.c
drivers/bus/acpi/compbatt/compmisc.c
drivers/crypto/ksecdd/random.c
drivers/filters/mountmgr/device.c
drivers/ksfilter/ks/api.c
drivers/ksfilter/ks/event.c
drivers/ksfilter/ks/ksfunc.h
drivers/ksfilter/ks/methods.c
drivers/ksfilter/ks/misc.c
drivers/ksfilter/ks/pin.c
drivers/ksfilter/ks/property.c
drivers/ksfilter/ks/swenum.c
drivers/ksfilter/ks/topology.c
drivers/network/afd/afd/bind.c
drivers/network/afd/afd/select.c
drivers/network/afd/afd/tdi.c
drivers/network/tcpip/tcpip/dispatch.c
drivers/storage/floppy/floppy.c
drivers/wdm/audio/legacy/wdmaud/control.c
drivers/wdm/audio/legacy/wdmaud/deviface.c
drivers/wdm/audio/legacy/wdmaud/mmixer.c
drivers/wdm/audio/legacy/wdmaud/sup.c
drivers/wdm/audio/sysaudio/deviface.c
drivers/wdm/audio/sysaudio/pin.c
drivers/wmi/CMakeLists.txt
include/ddk/isvbop.h
include/ddk/isvbop.inc
include/ddk/nt_vdd.h
include/ddk/ntddk.h
include/ddk/ntifs.h
include/ddk/vddsvc.h
include/ddk/wdm.h
include/ndk/rtlfuncs.h
include/psdk/ks.h
include/reactos/libs/fast486/fast486.h
include/reactos/libs/pseh/pseh3.h
include/reactos/subsys/win/vdm.h
include/reactos/wine/port.h
include/xdk/ccfuncs.h
include/xdk/extypes.h
include/xdk/fsrtlfuncs.h
include/xdk/haltypes.h
include/xdk/ia64/ke.h
include/xdk/iotypes.h
include/xdk/kdfuncs.h
include/xdk/ketypes.h
include/xdk/mmtypes.h
include/xdk/ntifs.template.h
include/xdk/obtypes.h
include/xdk/rtltypes.h
include/xdk/sefuncs.h
include/xdk/wdm.template.h
lib/CMakeLists.txt
lib/fast486/CMakeLists.txt
lib/fast486/COPYING
lib/fast486/common.c
lib/fast486/common.h
lib/fast486/common.inl
lib/fast486/extraops.c
lib/fast486/extraops.h
lib/fast486/fast486.c
lib/fast486/fpu.c
lib/fast486/fpu.h
lib/fast486/opcodes.c
lib/fast486/opcodes.h
lib/fast486/opgroups.c
lib/fast486/opgroups.h
lib/rtl/actctx.c
lib/rtl/nls.c
lib/rtl/rtlp.h
lib/sdk/cpprt/amd64/cpprt.s
lib/sdk/crt/include/internal/safecrt.h
lib/sdk/crt/printf/_sxprintf.c
lib/sdk/crt/stdio/file.c
lib/sdk/crt/stdio/stat64.c
lib/sdk/crt/stdlib/errno.c
lib/sdk/crt/stdlib/senv.c
lib/sdk/crt/string/_tsplitpath_x.h
lib/sdk/crt/string/itoa.c
lib/sdk/crt/string/itow.c
lib/sdk/crt/string/strerror.c
lib/sdk/crt/string/wcs.c
lib/sdk/crt/time/gmtime.c
lib/sdk/crt/wine/heap.c
media/doc/README.WINE
media/inf/audio.inf
media/inf/battery.inf
media/inf/bth.inf
media/inf/cdrom.inf
media/inf/disk.inf
media/inf/display.inf
media/inf/flpydisk.inf
media/inf/hal.inf
media/inf/hdc.inf
media/inf/input.inf
media/inf/keyboard.inf
media/inf/legcydrv.inf
media/inf/machine.inf
media/inf/monitor.inf
media/inf/shortcuts.inf
media/inf/unknown.inf
media/inf/usb.inf
ntoskrnl/ex/event.c
ntoskrnl/ex/sem.c
ntoskrnl/ex/sysinfo.c
ntoskrnl/fsrtl/fsrtlpc.c
ntoskrnl/include/internal/amd64/mm.h
ntoskrnl/include/internal/fsrtl.h
ntoskrnl/include/internal/kd.h
ntoskrnl/include/internal/kd64.h
ntoskrnl/include/ntoskrnl.h
ntoskrnl/kd64/kdapi.c
ntoskrnl/kd64/kddata.c
ntoskrnl/kd64/kdinit.c
ntoskrnl/ke/time.c
ntoskrnl/mm/section.c
ntoskrnl/ntoskrnl.spec
ntoskrnl/ps/quota.c
subsystems/CMakeLists.txt
subsystems/ntvdm/CMakeLists.txt
subsystems/ntvdm/bios/bios.c
subsystems/ntvdm/bios/bios.h
subsystems/ntvdm/bios/bios32/bios32.c
subsystems/ntvdm/bios/bios32/bios32.h
subsystems/ntvdm/bios/bios32/bios32p.h
subsystems/ntvdm/bios/bios32/kbdbios32.c
subsystems/ntvdm/bios/bios32/kbdbios32.h
subsystems/ntvdm/bios/bios32/vidbios32.c
subsystems/ntvdm/bios/bios32/vidbios32.h
subsystems/ntvdm/bios/kbdbios.c
subsystems/ntvdm/bios/kbdbios.h
subsystems/ntvdm/bios/rom.c
subsystems/ntvdm/bios/rom.h
subsystems/ntvdm/bios/vidbios.c
subsystems/ntvdm/bios/vidbios.h
subsystems/ntvdm/bop.c
subsystems/ntvdm/bop.h
subsystems/ntvdm/callback.c
subsystems/ntvdm/callback.h
subsystems/ntvdm/clock.c
subsystems/ntvdm/clock.h
subsystems/ntvdm/dos/dem.c
subsystems/ntvdm/dos/dem.h
subsystems/ntvdm/dos/dos32krnl/bios.c
subsystems/ntvdm/dos/dos32krnl/dos.c
subsystems/ntvdm/dos/dos32krnl/dos.h
subsystems/ntvdm/dos/dos32krnl/dosfiles.c
subsystems/ntvdm/emulator.c
subsystems/ntvdm/emulator.h
subsystems/ntvdm/hardware/cmos.c
subsystems/ntvdm/hardware/cmos.h
subsystems/ntvdm/hardware/pic.c
subsystems/ntvdm/hardware/pic.h
subsystems/ntvdm/hardware/ps2.c
subsystems/ntvdm/hardware/ps2.h
subsystems/ntvdm/hardware/speaker.c
subsystems/ntvdm/hardware/speaker.h
subsystems/ntvdm/hardware/timer.c
subsystems/ntvdm/hardware/timer.h
subsystems/ntvdm/hardware/vga.c
subsystems/ntvdm/hardware/vga.h
subsystems/ntvdm/int32.c
subsystems/ntvdm/int32.h
subsystems/ntvdm/io.c
subsystems/ntvdm/io.h
subsystems/ntvdm/lang/cs-CZ.rc
subsystems/ntvdm/lang/de-DE.rc
subsystems/ntvdm/lang/en-US.rc
subsystems/ntvdm/lang/es-ES.rc
subsystems/ntvdm/lang/fr-FR.rc
subsystems/ntvdm/lang/it-IT.rc
subsystems/ntvdm/lang/pl-PL.rc
subsystems/ntvdm/ntvdm.c
subsystems/ntvdm/ntvdm.h
subsystems/ntvdm/ntvdm.rc
subsystems/ntvdm/ntvdm.spec
subsystems/ntvdm/registers.c
subsystems/ntvdm/registers.h
subsystems/ntvdm/res/ntvdm.ico
subsystems/ntvdm/resource.h
subsystems/ntvdm/utils.c
subsystems/ntvdm/utils.h
subsystems/ntvdm/vddsup.c
subsystems/ntvdm/vddsup.h
subsystems/win/basesrv/basesrv.h
subsystems/win/basesrv/init.c
subsystems/win/basesrv/proc.c
subsystems/win/basesrv/vdm.c
subsystems/win/basesrv/vdm.h
subsystems/win32/csrsrv/procsup.c
win32ss/drivers/videoprt/child.c
win32ss/gdi/eng/engevent.c
win32ss/gdi/eng/mem.c
win32ss/include/ntuser.h
win32ss/user/ntuser/accelerator.c
win32ss/user/ntuser/main.c
win32ss/user/ntuser/menu.c
win32ss/user/ntuser/menu.h
win32ss/user/ntuser/message.c
win32ss/user/ntuser/misc.c
win32ss/user/ntuser/misc/rtlstr.c
win32ss/user/ntuser/userfuncs.h
win32ss/user/ntuser/window.c
win32ss/user/ntuser/winpos.c
win32ss/user/user32/windows/accel.c
win32ss/user/user32/windows/mdi.c
win32ss/user/user32/windows/menu.c
win32ss/w32ksvc.h

Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,6684727..6684727
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,96d2228..96d2228
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 8e022a1,0000000..b1614e3
mode 100644,000000..100644
--- /dev/null
@@@ -1,2165 -1,0 +1,2169 @@@
-     dwCreationFlags = CREATE_UNICODE_ENVIRONMENT;
-     if (psei->fMask & SEE_MASK_NO_CONSOLE)
-         dwCreationFlags |= CREATE_NEW_CONSOLE;
 +/*
 + *          Shell Library Functions
 + *
 + * Copyright 1998 Marcus Meissner
 + * Copyright 2002 Eric Pouech
 + *
 + * This library is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * This library is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with this library; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 + */
 +
 +#include "precomp.h"
 +
 +WINE_DEFAULT_DEBUG_CHANNEL(exec);
 +
 +static const WCHAR wszOpen[] = L"open";
 +static const WCHAR wszExe[] = L".exe";
 +
 +#define SEE_MASK_CLASSALL (SEE_MASK_CLASSNAME | SEE_MASK_CLASSKEY)
 +
 +static void ParseNoTildeEffect(PWSTR &res, LPCWSTR &args, DWORD &len, DWORD &used, int argNum)
 +{
 +    bool firstCharQuote = false;
 +    bool quotes_opened = false;
 +    bool backslash_encountered = false;
 +
 +    for (int curArg = 0; curArg <= argNum && *args; ++curArg)
 +    {
 +        firstCharQuote = false;
 +        if (*args == '"')
 +        {
 +            quotes_opened = true;
 +            firstCharQuote = true;
 +            args++;
 +        }
 +
 +        while(*args)
 +        {
 +            if (*args == '\\')
 +            {
 +                // if we found a backslash then flip the variable
 +                backslash_encountered = !backslash_encountered;
 +            }
 +            else if (*args == '"')
 +            {
 +                if (quotes_opened)
 +                {
 +                    if (*(args + 1) != '"')
 +                    {
 +                        quotes_opened = false;
 +                        args++;
 +                        break;
 +                    }
 +                    else
 +                    {
 +                        args++;
 +                    }
 +                }
 +                else
 +                {
 +                    quotes_opened = true;
 +                }
 +
 +                backslash_encountered = false;
 +            }
 +            else
 +            {
 +                backslash_encountered = false;
 +                if (*args == ' ' && !firstCharQuote)
 +                    break;
 +            }
 +
 +            if (curArg == argNum)
 +            {
 +                used++;
 +                if (used < len)
 +                    *res++ = *args;
 +            }
 +
 +            args++;
 +        }
 +
 +        while(*args == ' ')
 +            ++args;
 +    }
 +}
 +
 +static void ParseTildeEffect(PWSTR &res, LPCWSTR &args, DWORD &len, DWORD &used, int argNum)
 +{
 +    bool quotes_opened = false;
 +    bool backslash_encountered = false;
 +
 +    for (int curArg = 0; curArg <= argNum && *args; ++curArg)
 +    {
 +        while(*args)
 +        {
 +            if (*args == '\\')
 +            {
 +                // if we found a backslash then flip the variable
 +                backslash_encountered = !backslash_encountered;
 +            }
 +            else if (*args == '"')
 +            {
 +                if (quotes_opened)
 +                {
 +                    if (*(args + 1) != '"')
 +                    {
 +                        quotes_opened = false;
 +                    }
 +                    else
 +                    {
 +                        args++;
 +                    }
 +                }
 +                else
 +                {
 +                    quotes_opened = true;
 +                }
 +
 +                backslash_encountered = false;
 +            }
 +            else
 +            {
 +                backslash_encountered = false;
 +                if (*args == ' ' && !quotes_opened && curArg != argNum)
 +                    break;
 +            }
 +
 +            if (curArg == argNum)
 +            {
 +                used++;
 +                if (used < len)
 +                    *res++ = *args;
 +            }
 +
 +            args++;
 +        }
 +    }
 +}
 +
 +/***********************************************************************
 + * SHELL_ArgifyW [Internal]
 + *
 + * this function is supposed to expand the escape sequences found in the registry
 + * some diving reported that the following were used:
 + * + %1, %2...  seem to report to parameter of index N in ShellExecute pmts
 + * %1 file
 + * %2 printer
 + * %3 driver
 + * %4 port
 + * %I address of a global item ID (explorer switch /idlist)
 + * %L seems to be %1 as long filename followed by the 8+3 variation
 + * %S ???
 + * %* all following parameters (see batfile)
 + *
 + * The way we parse the command line arguments was determined through extensive
 + * testing and can be summed up by the following rules"
 + *
 + * - %2
 + *     - if first letter is " break on first non literal " and include any white spaces
 + *     - if first letter is NOT " break on first " or white space
 + *     - if " is opened any pair of consecutive " results in ONE literal "
 + *
 + * - %~2
 + *     - use rules from here http://www.autohotkey.net/~deleyd/parameters/parameters.htm
 + */
 +
 +static BOOL SHELL_ArgifyW(WCHAR* out, DWORD len, const WCHAR* fmt, const WCHAR* lpFile, LPITEMIDLIST pidl, LPCWSTR args, DWORD* out_len)
 +{
 +    WCHAR   xlpFile[1024];
 +    BOOL    done = FALSE;
 +    BOOL    found_p1 = FALSE;
 +    PWSTR   res = out;
 +    PCWSTR  cmd;
 +    DWORD   used = 0;
 +    bool    tildeEffect = false;
 +
 +    TRACE("Before parsing: %p, %d, %s, %s, %p, %p\n", out, len, debugstr_w(fmt),
 +          debugstr_w(lpFile), pidl, args);
 +
 +    while (*fmt)
 +    {
 +        if (*fmt == '%')
 +        {
 +            switch (*++fmt)
 +            {
 +                case '\0':
 +                case '%':
 +                {
 +                    used++;
 +                    if (used < len)
 +                        *res++ = '%';
 +                };
 +                break;
 +
 +                case '*':
 +                {
 +                    if (args)
 +                    {
 +                        if (*fmt == '*')
 +                        {
 +                            used++;
 +                            while(*args)
 +                            {
 +                                used++;
 +                                if (used < len)
 +                                    *res++ = *args++;
 +                                else
 +                                    args++;
 +                            }
 +                            used++;
 +                            break;
 +                        }
 +                    }
 +                };
 +                break;
 +
 +                case '~':
 +
 +                case '2':
 +                case '3':
 +                case '4':
 +                case '5':
 +                case '6':
 +                case '7':
 +                case '8':
 +                case '9':
 +                    //case '0':
 +                {
 +                    if (*fmt == '~')
 +                    {
 +                        fmt++;
 +                        tildeEffect = true;
 +                    }
 +
 +                    if (args)
 +                    {
 +                        if (tildeEffect)
 +                        {
 +                            ParseTildeEffect(res, args, len, used, *fmt - '2');
 +                            tildeEffect = false;
 +                        }
 +                        else
 +                        {
 +                            ParseNoTildeEffect(res, args, len, used, *fmt - '2');
 +                        }
 +                    }
 +                };
 +                break;
 +
 +                case '1':
 +                    if (!done || (*fmt == '1'))
 +                    {
 +                        /*FIXME Is the call to SearchPathW() really needed? We already have separated out the parameter string in args. */
 +                        if (SearchPathW(NULL, lpFile, wszExe, sizeof(xlpFile) / sizeof(WCHAR), xlpFile, NULL))
 +                            cmd = xlpFile;
 +                        else
 +                            cmd = lpFile;
 +
 +                        used += wcslen(cmd);
 +                        if (used < len)
 +                        {
 +                            wcscpy(res, cmd);
 +                            res += wcslen(cmd);
 +                        }
 +                    }
 +                    found_p1 = TRUE;
 +                    break;
 +
 +                    /*
 +                     * IE uses this a lot for activating things such as windows media
 +                     * player. This is not verified to be fully correct but it appears
 +                     * to work just fine.
 +                     */
 +                case 'l':
 +                case 'L':
 +                    if (lpFile)
 +                    {
 +                        used += wcslen(lpFile);
 +                        if (used < len)
 +                        {
 +                            wcscpy(res, lpFile);
 +                            res += wcslen(lpFile);
 +                        }
 +                    }
 +                    found_p1 = TRUE;
 +                    break;
 +
 +                case 'i':
 +                case 'I':
 +                    if (pidl)
 +                    {
 +                        DWORD chars = 0;
 +                        /* %p should not exceed 8, maybe 16 when looking forward to 64bit.
 +                            * allowing a buffer of 100 should more than exceed all needs */
 +                        WCHAR buf[100];
 +                        LPVOID  pv;
 +                        HGLOBAL hmem = SHAllocShared(pidl, ILGetSize(pidl), 0);
 +                        pv = SHLockShared(hmem, 0);
 +                        chars = swprintf(buf, L":%p", pv);
 +
 +                        if (chars >= sizeof(buf) / sizeof(WCHAR))
 +                            ERR("pidl format buffer too small!\n");
 +
 +                        used += chars;
 +
 +                        if (used < len)
 +                        {
 +                            wcscpy(res, buf);
 +                            res += chars;
 +                        }
 +                        SHUnlockShared(pv);
 +                    }
 +                    found_p1 = TRUE;
 +                    break;
 +
 +                default:
 +                    /*
 +                     * Check if this is an env-variable here...
 +                     */
 +
 +                    /* Make sure that we have at least one more %.*/
 +                    if (strchrW(fmt, '%'))
 +                    {
 +                        WCHAR   tmpBuffer[1024];
 +                        PWSTR   tmpB = tmpBuffer;
 +                        WCHAR   tmpEnvBuff[MAX_PATH];
 +                        DWORD   envRet;
 +
 +                        while (*fmt != '%')
 +                            *tmpB++ = *fmt++;
 +                        *tmpB++ = 0;
 +
 +                        TRACE("Checking %s to be an env-var\n", debugstr_w(tmpBuffer));
 +
 +                        envRet = GetEnvironmentVariableW(tmpBuffer, tmpEnvBuff, MAX_PATH);
 +                        if (envRet == 0 || envRet > MAX_PATH)
 +                        {
 +                            used += wcslen(tmpBuffer);
 +                            if (used < len)
 +                            {
 +                                wcscpy( res, tmpBuffer );
 +                                res += wcslen(tmpBuffer);
 +                            }
 +                        }
 +                        else
 +                        {
 +                            used += wcslen(tmpEnvBuff);
 +                            if (used < len)
 +                            {
 +                                wcscpy( res, tmpEnvBuff );
 +                                res += wcslen(tmpEnvBuff);
 +                            }
 +                        }
 +                    }
 +                    done = TRUE;
 +                    break;
 +            }
 +            /* Don't skip past terminator (catch a single '%' at the end) */
 +            if (*fmt != '\0')
 +            {
 +                fmt++;
 +            }
 +        }
 +        else
 +        {
 +            used ++;
 +            if (used < len)
 +                *res++ = *fmt++;
 +            else
 +                fmt++;
 +        }
 +    }
 +
 +    *res = '\0';
 +    TRACE("used %i of %i space\n", used, len);
 +    if (out_len)
 +        *out_len = used;
 +
 +    TRACE("After parsing: %p, %d, %s, %s, %p, %p\n", out, len, debugstr_w(fmt),
 +          debugstr_w(lpFile), pidl, args);
 +
 +    return found_p1;
 +}
 +
 +static HRESULT SHELL_GetPathFromIDListForExecuteW(LPCITEMIDLIST pidl, LPWSTR pszPath, UINT uOutSize)
 +{
 +    STRRET strret;
 +    IShellFolder *desktop;
 +
 +    HRESULT hr = SHGetDesktopFolder(&desktop);
 +
 +    if (SUCCEEDED(hr))
 +    {
 +        hr = desktop->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &strret);
 +
 +        if (SUCCEEDED(hr))
 +            StrRetToStrNW(pszPath, uOutSize, &strret, pidl);
 +
 +        desktop->Release();
 +    }
 +
 +    return hr;
 +}
 +
 +/*************************************************************************
 + *    SHELL_ExecuteW [Internal]
 + *
 + */
 +static UINT_PTR SHELL_ExecuteW(const WCHAR *lpCmd, WCHAR *env, BOOL shWait,
 +                               const SHELLEXECUTEINFOW *psei, LPSHELLEXECUTEINFOW psei_out)
 +{
 +    STARTUPINFOW  startup;
 +    PROCESS_INFORMATION info;
 +    UINT_PTR retval = SE_ERR_NOASSOC;
 +    UINT gcdret = 0;
 +    WCHAR curdir[MAX_PATH];
 +    DWORD dwCreationFlags;
 +    const WCHAR *lpDirectory = NULL;
 +
 +    TRACE("Execute %s from directory %s\n", debugstr_w(lpCmd), debugstr_w(psei->lpDirectory));
 +
 +    /* make sure we don't fail the CreateProcess if the calling app passes in
 +     * a bad working directory */
 +    if (psei->lpDirectory && psei->lpDirectory[0])
 +    {
 +        DWORD attr = GetFileAttributesW(psei->lpDirectory);
 +        if (attr != INVALID_FILE_ATTRIBUTES && attr & FILE_ATTRIBUTE_DIRECTORY)
 +            lpDirectory = psei->lpDirectory;
 +    }
 +
 +    /* ShellExecute specifies the command from psei->lpDirectory
 +     * if present. Not from the current dir as CreateProcess does */
 +    if (lpDirectory)
 +        if ((gcdret = GetCurrentDirectoryW( MAX_PATH, curdir)))
 +            if (!SetCurrentDirectoryW( lpDirectory))
 +                ERR("cannot set directory %s\n", debugstr_w(lpDirectory));
 +
 +    ZeroMemory(&startup, sizeof(STARTUPINFOW));
 +    startup.cb = sizeof(STARTUPINFOW);
 +    startup.dwFlags = STARTF_USESHOWWINDOW;
 +    startup.wShowWindow = psei->nShow;
++    dwCreationFlags = CREATE_UNICODE_ENVIRONMENT;
++   if (psei->fMask & SEE_MASK_NO_CONSOLE)
++        dwCreationFlags |= CREATE_NEW_CONSOLE;    
 +    startup.lpTitle = (LPWSTR)(psei->fMask & (SEE_MASK_HASLINKNAME | SEE_MASK_HASTITLE) ? psei->lpClass : NULL);
 +
 +    if (psei->fMask & SEE_MASK_HASLINKNAME)
 +        startup.dwFlags |= STARTF_TITLEISLINKNAME;
 +
 +    if (CreateProcessW(NULL, (LPWSTR)lpCmd, NULL, NULL, FALSE, dwCreationFlags, env,
 +                       lpDirectory, &startup, &info))
 +    {
 +        /* Give 30 seconds to the app to come up, if desired. Probably only needed
 +           when starting app immediately before making a DDE connection. */
 +        if (shWait)
 +            if (WaitForInputIdle(info.hProcess, 30000) == WAIT_FAILED)
 +                WARN("WaitForInputIdle failed: Error %d\n", GetLastError() );
 +        retval = 33;
 +
 +        if (psei->fMask & SEE_MASK_NOCLOSEPROCESS)
 +            psei_out->hProcess = info.hProcess;
 +        else
 +            CloseHandle( info.hProcess );
 +        CloseHandle( info.hThread );
 +    }
 +    else if ((retval = GetLastError()) >= 32)
 +    {
 +        WARN("CreateProcess returned error %ld\n", retval);
 +        retval = ERROR_BAD_FORMAT;
 +    }
 +
 +    TRACE("returning %lu\n", retval);
 +
 +    psei_out->hInstApp = (HINSTANCE)retval;
 +
 +    if (gcdret)
 +        if (!SetCurrentDirectoryW(curdir))
 +            ERR("cannot return to directory %s\n", debugstr_w(curdir));
 +
 +    return retval;
 +}
 +
 +
 +/***********************************************************************
 + *           SHELL_BuildEnvW    [Internal]
 + *
 + * Build the environment for the new process, adding the specified
 + * path to the PATH variable. Returned pointer must be freed by caller.
 + */
 +static LPWSTR SHELL_BuildEnvW( const WCHAR *path )
 +{
 +    static const WCHAR wPath[] = L"PATH=";
 +    WCHAR *strings, *new_env;
 +    WCHAR *p, *p2;
 +    int total = wcslen(path) + 1;
 +    BOOL got_path = FALSE;
 +
 +    if (!(strings = GetEnvironmentStringsW())) return NULL;
 +    p = strings;
 +    while (*p)
 +    {
 +        int len = wcslen(p) + 1;
 +        if (!_wcsnicmp( p, wPath, 5 )) got_path = TRUE;
 +        total += len;
 +        p += len;
 +    }
 +    if (!got_path) total += 5;  /* we need to create PATH */
 +    total++;  /* terminating null */
 +
 +    if (!(new_env = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, total * sizeof(WCHAR))))
 +    {
 +        FreeEnvironmentStringsW(strings);
 +        return NULL;
 +    }
 +    p = strings;
 +    p2 = new_env;
 +    while (*p)
 +    {
 +        int len = wcslen(p) + 1;
 +        memcpy(p2, p, len * sizeof(WCHAR));
 +        if (!_wcsnicmp( p, wPath, 5 ))
 +        {
 +            p2[len - 1] = ';';
 +            wcscpy( p2 + len, path );
 +            p2 += wcslen(path) + 1;
 +        }
 +        p += len;
 +        p2 += len;
 +    }
 +    if (!got_path)
 +    {
 +        wcscpy(p2, wPath);
 +        wcscat(p2, path);
 +        p2 += wcslen(p2) + 1;
 +    }
 +    *p2 = 0;
 +    FreeEnvironmentStringsW(strings);
 +    return new_env;
 +}
 +
 +
 +/***********************************************************************
 + *           SHELL_TryAppPathW    [Internal]
 + *
 + * Helper function for SHELL_FindExecutable
 + * @param lpResult - pointer to a buffer of size MAX_PATH
 + * On entry: szName is a filename (probably without path separators).
 + * On exit: if szName found in "App Path", place full path in lpResult, and return true
 + */
 +static BOOL SHELL_TryAppPathW( LPCWSTR szName, LPWSTR lpResult, WCHAR **env)
 +{
 +    HKEY hkApp = 0;
 +    WCHAR buffer[1024];
 +    LONG len;
 +    LONG res;
 +    BOOL found = FALSE;
 +
 +    if (env) *env = NULL;
 +    wcscpy(buffer, L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\");
 +    wcscat(buffer, szName);
 +    res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, buffer, 0, KEY_READ, &hkApp);
 +    if (res) goto end;
 +
 +    len = MAX_PATH * sizeof(WCHAR);
 +    res = RegQueryValueW(hkApp, NULL, lpResult, &len);
 +    if (res) goto end;
 +    found = TRUE;
 +
 +    if (env)
 +    {
 +        DWORD count = sizeof(buffer);
 +        if (!RegQueryValueExW(hkApp, L"Path", NULL, NULL, (LPBYTE)buffer, &count) && buffer[0])
 +            *env = SHELL_BuildEnvW(buffer);
 +    }
 +
 +end:
 +    if (hkApp) RegCloseKey(hkApp);
 +    return found;
 +}
 +
 +static UINT SHELL_FindExecutableByOperation(LPCWSTR lpOperation, LPWSTR key, LPWSTR filetype, LPWSTR command, LONG commandlen)
 +{
 +    static const WCHAR wCommand[] = L"\\command";
 +    HKEY hkeyClass;
 +    WCHAR verb[MAX_PATH];
 +
 +    if (RegOpenKeyExW(HKEY_CLASSES_ROOT, filetype, 0, 0x02000000, &hkeyClass))
 +        return SE_ERR_NOASSOC;
 +    if (!HCR_GetDefaultVerbW(hkeyClass, lpOperation, verb, sizeof(verb) / sizeof(verb[0])))
 +        return SE_ERR_NOASSOC;
 +    RegCloseKey(hkeyClass);
 +
 +    /* Looking for ...buffer\shell\<verb>\command */
 +    wcscat(filetype, L"\\shell\\");
 +    wcscat(filetype, verb);
 +    wcscat(filetype, wCommand);
 +
 +    if (RegQueryValueW(HKEY_CLASSES_ROOT, filetype, command,
 +                       &commandlen) == ERROR_SUCCESS)
 +    {
 +        commandlen /= sizeof(WCHAR);
 +        if (key) wcscpy(key, filetype);
 +#if 0
 +        LPWSTR tmp;
 +        WCHAR param[256];
 +        LONG paramlen = sizeof(param);
 +        static const WCHAR wSpace[] = {' ', 0};
 +
 +        /* FIXME: it seems all Windows version don't behave the same here.
 +         * the doc states that this ddeexec information can be found after
 +         * the exec names.
 +         * on Win98, it doesn't appear, but I think it does on Win2k
 +         */
 +        /* Get the parameters needed by the application
 +           from the associated ddeexec key */
 +        tmp = strstrW(filetype, wCommand);
 +        tmp[0] = '\0';
 +        wcscat(filetype, wDdeexec);
 +        if (RegQueryValueW(HKEY_CLASSES_ROOT, filetype, param,
 +                           &paramlen) == ERROR_SUCCESS)
 +        {
 +            paramlen /= sizeof(WCHAR);
 +            wcscat(command, wSpace);
 +            wcscat(command, param);
 +            commandlen += paramlen;
 +        }
 +#endif
 +
 +        command[commandlen] = '\0';
 +
 +        return 33; /* FIXME see SHELL_FindExecutable() */
 +    }
 +
 +    return SE_ERR_NOASSOC;
 +}
 +
 +/*************************************************************************
 + *    SHELL_FindExecutable [Internal]
 + *
 + * Utility for code sharing between FindExecutable and ShellExecute
 + * in:
 + *      lpFile the name of a file
 + *      lpOperation the operation on it (open)
 + * out:
 + *      lpResult a buffer, big enough :-(, to store the command to do the
 + *              operation on the file
 + *      key a buffer, big enough, to get the key name to do actually the
 + *              command (it'll be used afterwards for more information
 + *              on the operation)
 + */
 +static UINT SHELL_FindExecutable(LPCWSTR lpPath, LPCWSTR lpFile, LPCWSTR lpOperation,
 +                                 LPWSTR lpResult, DWORD resultLen, LPWSTR key, WCHAR **env, LPITEMIDLIST pidl, LPCWSTR args)
 +{
 +    WCHAR *extension = NULL; /* pointer to file extension */
 +    WCHAR filetype[256];     /* registry name for this filetype */
 +    LONG  filetypelen = sizeof(filetype); /* length of above */
 +    WCHAR command[1024];     /* command from registry */
 +    WCHAR wBuffer[256];      /* Used to GetProfileString */
 +    UINT  retval = SE_ERR_NOASSOC;
 +    WCHAR *tok;              /* token pointer */
 +    WCHAR xlpFile[256];      /* result of SearchPath */
 +    DWORD attribs;           /* file attributes */
 +
 +    TRACE("%s\n", debugstr_w(lpFile));
 +
 +    if (!lpResult)
 +        return ERROR_INVALID_PARAMETER;
 +
 +    xlpFile[0] = '\0';
 +    lpResult[0] = '\0'; /* Start off with an empty return string */
 +    if (key) *key = '\0';
 +
 +    /* trap NULL parameters on entry */
 +    if (!lpFile)
 +    {
 +        WARN("(lpFile=%s,lpResult=%s): NULL parameter\n",
 +             debugstr_w(lpFile), debugstr_w(lpResult));
 +        return ERROR_FILE_NOT_FOUND; /* File not found. Close enough, I guess. */
 +    }
 +
 +    if (SHELL_TryAppPathW( lpFile, lpResult, env ))
 +    {
 +        TRACE("found %s via App Paths\n", debugstr_w(lpResult));
 +        return 33;
 +    }
 +
 +    if (SearchPathW(lpPath, lpFile, wszExe, sizeof(xlpFile) / sizeof(WCHAR), xlpFile, NULL))
 +    {
 +        TRACE("SearchPathW returned non-zero\n");
 +        lpFile = xlpFile;
 +        /* Hey, isn't this value ignored?  Why make this call?  Shouldn't we return here?  --dank*/
 +    }
++    else if (lpPath && SearchPathW(NULL, lpFile, wszExe, sizeof(xlpFile)/sizeof(WCHAR), xlpFile, NULL))
++    {
++        TRACE("SearchPathW returned non-zero\n");
++        lpFile = xlpFile;
++        /* The file was found in one of the directories in the system-wide search path */
++    }
++    
 +    attribs = GetFileAttributesW(lpFile);
 +    if (attribs != INVALID_FILE_ATTRIBUTES && (attribs & FILE_ATTRIBUTE_DIRECTORY))
 +    {
 +        wcscpy(filetype, L"Folder");
 +        filetypelen = 6;    /* strlen("Folder") */
 +    }
 +    else
 +    {
 +        /* Did we get something? Anything? */
 +        if (xlpFile[0] == 0)
 +        {
 +            TRACE("Returning SE_ERR_FNF\n");
 +            return SE_ERR_FNF;
 +        }
 +        /* First thing we need is the file's extension */
 +        extension = wcsrchr(xlpFile, '.'); /* Assume last "." is the one; */
 +        /* File->Run in progman uses */
 +        /* .\FILE.EXE :( */
 +        TRACE("xlpFile=%s,extension=%s\n", debugstr_w(xlpFile), debugstr_w(extension));
 +
 +        if (extension == NULL || extension[1] == 0)
 +        {
 +            WARN("Returning SE_ERR_NOASSOC\n");
 +            return SE_ERR_NOASSOC;
 +        }
 +
 +        /* Three places to check: */
 +        /* 1. win.ini, [windows], programs (NB no leading '.') */
 +        /* 2. Registry, HKEY_CLASS_ROOT\<filetype>\shell\open\command */
 +        /* 3. win.ini, [extensions], extension (NB no leading '.' */
 +        /* All I know of the order is that registry is checked before */
 +        /* extensions; however, it'd make sense to check the programs */
 +        /* section first, so that's what happens here. */
 +
 +        /* See if it's a program - if GetProfileString fails, we skip this
 +         * section. Actually, if GetProfileString fails, we've probably
 +         * got a lot more to worry about than running a program... */
 +        if (GetProfileStringW(L"windows", L"programs", L"exe pif bat cmd com", wBuffer, sizeof(wBuffer) / sizeof(WCHAR)) > 0)
 +        {
 +            CharLowerW(wBuffer);
 +            tok = wBuffer;
 +            while (*tok)
 +            {
 +                WCHAR *p = tok;
 +                while (*p && *p != ' ' && *p != '\t') p++;
 +                if (*p)
 +                {
 +                    *p++ = 0;
 +                    while (*p == ' ' || *p == '\t') p++;
 +                }
 +
 +                if (wcsicmp(tok, &extension[1]) == 0) /* have to skip the leading "." */
 +                {
 +                    wcscpy(lpResult, xlpFile);
 +                    /* Need to perhaps check that the file has a path
 +                     * attached */
 +                    TRACE("found %s\n", debugstr_w(lpResult));
 +                    return 33;
 +                    /* Greater than 32 to indicate success */
 +                }
 +                tok = p;
 +            }
 +        }
 +
 +        /* Check registry */
 +        if (RegQueryValueW(HKEY_CLASSES_ROOT, extension, filetype,
 +                           &filetypelen) == ERROR_SUCCESS)
 +        {
 +            filetypelen /= sizeof(WCHAR);
 +            if (filetypelen == sizeof(filetype) / sizeof(WCHAR))
 +                filetypelen--;
 +
 +            filetype[filetypelen] = '\0';
 +            TRACE("File type: %s\n", debugstr_w(filetype));
 +        }
 +        else
 +        {
 +            *filetype = '\0';
 +            filetypelen = 0;
 +        }
 +    }
 +
 +    if (*filetype)
 +    {
 +        /* pass the operation string to SHELL_FindExecutableByOperation() */
 +        filetype[filetypelen] = '\0';
 +        retval = SHELL_FindExecutableByOperation(lpOperation, key, filetype, command, sizeof(command));
 +
 +        if (retval > 32)
 +        {
 +            DWORD finishedLen;
 +            SHELL_ArgifyW(lpResult, resultLen, command, xlpFile, pidl, args, &finishedLen);
 +            if (finishedLen > resultLen)
 +                ERR("Argify buffer not large enough.. truncated\n");
 +            /* Remove double quotation marks and command line arguments */
 +            if (*lpResult == '"')
 +            {
 +                WCHAR *p = lpResult;
 +                while (*(p + 1) != '"')
 +                {
 +                    *p = *(p + 1);
 +                    p++;
 +                }
 +                *p = '\0';
 +            }
 +            else
 +            {
 +                /* Truncate on first space */
 +                WCHAR *p = lpResult;
 +                while (*p != ' ' && *p != '\0')
 +                    p++;
 +                *p = '\0';
 +            }
 +        }
 +    }
 +    else /* Check win.ini */
 +    {
 +        /* Toss the leading dot */
 +        extension++;
 +        if (GetProfileStringW(L"extensions", extension, L"", command, sizeof(command) / sizeof(WCHAR)) > 0)
 +        {
 +            if (wcslen(command) != 0)
 +            {
 +                wcscpy(lpResult, command);
 +                tok = wcschr(lpResult, '^'); /* should be ^.extension? */
 +                if (tok != NULL)
 +                {
 +                    tok[0] = '\0';
 +                    wcscat(lpResult, xlpFile); /* what if no dir in xlpFile? */
 +                    tok = wcschr(command, '^'); /* see above */
 +                    if ((tok != NULL) && (wcslen(tok) > 5))
 +                    {
 +                        wcscat(lpResult, &tok[5]);
 +                    }
 +                }
 +                retval = 33; /* FIXME - see above */
 +            }
 +        }
 +    }
 +
 +    TRACE("returning %s\n", debugstr_w(lpResult));
 +    return retval;
 +}
 +
 +/******************************************************************
 + *        dde_cb
 + *
 + * callback for the DDE connection. not really useful
 + */
 +static HDDEDATA CALLBACK dde_cb(UINT uType, UINT uFmt, HCONV hConv,
 +                                HSZ hsz1, HSZ hsz2, HDDEDATA hData,
 +                                ULONG_PTR dwData1, ULONG_PTR dwData2)
 +{
 +    TRACE("dde_cb: %04x, %04x, %p, %p, %p, %p, %08lx, %08lx\n",
 +          uType, uFmt, hConv, hsz1, hsz2, hData, dwData1, dwData2);
 +    return NULL;
 +}
 +
 +/******************************************************************
 + *        dde_connect
 + *
 + * ShellExecute helper. Used to do an operation with a DDE connection
 + *
 + * Handles both the direct connection (try #1), and if it fails,
 + * launching an application and trying (#2) to connect to it
 + *
 + */
 +static unsigned dde_connect(const WCHAR* key, const WCHAR* start, WCHAR* ddeexec,
 +                            const WCHAR* lpFile, WCHAR *env,
 +                            LPCWSTR szCommandline, LPITEMIDLIST pidl, SHELL_ExecuteW32 execfunc,
 +                            const SHELLEXECUTEINFOW *psei, LPSHELLEXECUTEINFOW psei_out)
 +{
 +    WCHAR       regkey[256];
 +    WCHAR *     endkey = regkey + wcslen(key);
 +    WCHAR       app[256], topic[256], ifexec[256], res[256];
 +    LONG        applen, topiclen, ifexeclen;
 +    WCHAR *     exec;
 +    DWORD       ddeInst = 0;
 +    DWORD       tid;
 +    DWORD       resultLen;
 +    HSZ         hszApp, hszTopic;
 +    HCONV       hConv;
 +    HDDEDATA    hDdeData;
 +    unsigned    ret = SE_ERR_NOASSOC;
 +    BOOL unicode = !(GetVersion() & 0x80000000);
 +
 +    wcscpy(regkey, key);
 +    wcscpy(endkey, L"\\application");
 +    applen = sizeof(app);
 +    if (RegQueryValueW(HKEY_CLASSES_ROOT, regkey, app, &applen) != ERROR_SUCCESS)
 +    {
 +        WCHAR command[1024], fullpath[MAX_PATH];
 +        static const WCHAR wSo[] = L".so";
 +        DWORD sizeSo = sizeof(wSo) / sizeof(WCHAR);
 +        LPWSTR ptr = NULL;
 +        DWORD ret = 0;
 +
 +        /* Get application command from start string and find filename of application */
 +        if (*start == '"')
 +        {
 +            wcscpy(command, start + 1);
 +            if ((ptr = wcschr(command, '"')))
 +                * ptr = 0;
 +            ret = SearchPathW(NULL, command, wszExe, sizeof(fullpath) / sizeof(WCHAR), fullpath, &ptr);
 +        }
 +        else
 +        {
 +            LPWSTR p, space;
 +            for (p = (LPWSTR)start; (space = const_cast<LPWSTR>(strchrW(p, ' '))); p = space + 1)
 +            {
 +                int idx = space - start;
 +                memcpy(command, start, idx * sizeof(WCHAR));
 +                command[idx] = '\0';
 +                if ((ret = SearchPathW(NULL, command, wszExe, sizeof(fullpath) / sizeof(WCHAR), fullpath, &ptr)))
 +                    break;
 +            }
 +            if (!ret)
 +                ret = SearchPathW(NULL, start, wszExe, sizeof(fullpath) / sizeof(WCHAR), fullpath, &ptr);
 +        }
 +
 +        if (!ret)
 +        {
 +            ERR("Unable to find application path for command %s\n", debugstr_w(start));
 +            return ERROR_ACCESS_DENIED;
 +        }
 +        wcscpy(app, ptr);
 +
 +        /* Remove extensions (including .so) */
 +        ptr = app + wcslen(app) - (sizeSo - 1);
 +        if (wcslen(app) >= sizeSo &&
 +                !wcscmp(ptr, wSo))
 +            *ptr = 0;
 +
 +        ptr = const_cast<LPWSTR>(strrchrW(app, '.'));
 +        assert(ptr);
 +        *ptr = 0;
 +    }
 +
 +    wcscpy(endkey, L"\\topic");
 +    topiclen = sizeof(topic);
 +    if (RegQueryValueW(HKEY_CLASSES_ROOT, regkey, topic, &topiclen) != ERROR_SUCCESS)
 +    {
 +        wcscpy(topic, L"System");
 +    }
 +
 +    if (unicode)
 +    {
 +        if (DdeInitializeW(&ddeInst, dde_cb, APPCMD_CLIENTONLY, 0L) != DMLERR_NO_ERROR)
 +            return 2;
 +    }
 +    else
 +    {
 +        if (DdeInitializeA(&ddeInst, dde_cb, APPCMD_CLIENTONLY, 0L) != DMLERR_NO_ERROR)
 +            return 2;
 +    }
 +
 +    hszApp = DdeCreateStringHandleW(ddeInst, app, CP_WINUNICODE);
 +    hszTopic = DdeCreateStringHandleW(ddeInst, topic, CP_WINUNICODE);
 +
 +    hConv = DdeConnect(ddeInst, hszApp, hszTopic, NULL);
 +    exec = ddeexec;
 +    if (!hConv)
 +    {
 +        TRACE("Launching %s\n", debugstr_w(start));
 +        ret = execfunc(start, env, TRUE, psei, psei_out);
 +        if (ret <= 32)
 +        {
 +            TRACE("Couldn't launch\n");
 +            goto error;
 +        }
 +        hConv = DdeConnect(ddeInst, hszApp, hszTopic, NULL);
 +        if (!hConv)
 +        {
 +            TRACE("Couldn't connect. ret=%d\n", ret);
 +            DdeUninitialize(ddeInst);
 +            SetLastError(ERROR_DDE_FAIL);
 +            return 30; /* whatever */
 +        }
 +        strcpyW(endkey, L"\\ifexec");
 +        ifexeclen = sizeof(ifexec);
 +        if (RegQueryValueW(HKEY_CLASSES_ROOT, regkey, ifexec, &ifexeclen) == ERROR_SUCCESS)
 +        {
 +            exec = ifexec;
 +        }
 +    }
 +
 +    SHELL_ArgifyW(res, sizeof(res) / sizeof(WCHAR), exec, lpFile, pidl, szCommandline, &resultLen);
 +    if (resultLen > sizeof(res) / sizeof(WCHAR))
 +        ERR("Argify buffer not large enough, truncated\n");
 +    TRACE("%s %s => %s\n", debugstr_w(exec), debugstr_w(lpFile), debugstr_w(res));
 +
 +    /* It's documented in the KB 330337 that IE has a bug and returns
 +     * error DMLERR_NOTPROCESSED on XTYP_EXECUTE request.
 +     */
 +    if (unicode)
 +        hDdeData = DdeClientTransaction((LPBYTE)res, (strlenW(res) + 1) * sizeof(WCHAR), hConv, 0L, 0, XTYP_EXECUTE, 30000, &tid);
 +    else
 +    {
 +        DWORD lenA = WideCharToMultiByte(CP_ACP, 0, res, -1, NULL, 0, NULL, NULL);
 +        char *resA = (LPSTR)HeapAlloc(GetProcessHeap(), 0, lenA);
 +        WideCharToMultiByte(CP_ACP, 0, res, -1, resA, lenA, NULL, NULL);
 +        hDdeData = DdeClientTransaction( (LPBYTE)resA, lenA, hConv, 0L, 0,
 +                                         XTYP_EXECUTE, 10000, &tid );
 +        HeapFree(GetProcessHeap(), 0, resA);
 +    }
 +    if (hDdeData)
 +        DdeFreeDataHandle(hDdeData);
 +    else
 +        WARN("DdeClientTransaction failed with error %04x\n", DdeGetLastError(ddeInst));
 +    ret = 33;
 +
 +    DdeDisconnect(hConv);
 +
 +error:
 +    DdeUninitialize(ddeInst);
 +
 +    return ret;
 +}
 +
 +/*************************************************************************
 + *    execute_from_key [Internal]
 + */
 +static UINT_PTR execute_from_key(LPCWSTR key, LPCWSTR lpFile, WCHAR *env,
 +                                 LPCWSTR szCommandline, LPCWSTR executable_name,
 +                                 SHELL_ExecuteW32 execfunc,
 +                                 LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out)
 +{
 +    WCHAR cmd[256], param[1024], ddeexec[256];
 +    DWORD cmdlen = sizeof(cmd), ddeexeclen = sizeof(ddeexec);
 +    UINT_PTR retval = SE_ERR_NOASSOC;
 +    DWORD resultLen;
 +    LPWSTR tmp;
 +
 +    TRACE("%s %s %s %s %s\n", debugstr_w(key), debugstr_w(lpFile), debugstr_w(env),
 +          debugstr_w(szCommandline), debugstr_w(executable_name));
 +
 +    cmd[0] = '\0';
 +    param[0] = '\0';
 +
 +    /* Get the application from the registry */
 +    if (RegQueryValueW(HKEY_CLASSES_ROOT, key, cmd, (LONG *)&cmdlen) == ERROR_SUCCESS)
 +    {
 +        TRACE("got cmd: %s\n", debugstr_w(cmd));
 +
 +        /* Is there a replace() function anywhere? */
 +        cmdlen /= sizeof(WCHAR);
 +        if (cmdlen >= sizeof(cmd) / sizeof(WCHAR))
 +            cmdlen = sizeof(cmd) / sizeof(WCHAR) - 1;
 +        cmd[cmdlen] = '\0';
 +        SHELL_ArgifyW(param, sizeof(param) / sizeof(WCHAR), cmd, lpFile, (LPITEMIDLIST)psei->lpIDList, szCommandline, &resultLen);
 +        if (resultLen > sizeof(param) / sizeof(WCHAR))
 +            ERR("Argify buffer not large enough, truncating\n");
 +    }
 +
 +    /* Get the parameters needed by the application
 +       from the associated ddeexec key */
 +    tmp = const_cast<LPWSTR>(strstrW(key, L"command"));
 +    assert(tmp);
 +    wcscpy(tmp, L"ddeexec");
 +
 +    if (RegQueryValueW(HKEY_CLASSES_ROOT, key, ddeexec, (LONG *)&ddeexeclen) == ERROR_SUCCESS)
 +    {
 +        TRACE("Got ddeexec %s => %s\n", debugstr_w(key), debugstr_w(ddeexec));
 +        if (!param[0]) strcpyW(param, executable_name);
 +        retval = dde_connect(key, param, ddeexec, lpFile, env, szCommandline, (LPITEMIDLIST)psei->lpIDList, execfunc, psei, psei_out);
 +    }
 +    else if (param[0])
 +    {
 +        TRACE("executing: %s\n", debugstr_w(param));
 +        retval = execfunc(param, env, FALSE, psei, psei_out);
 +    }
 +    else
 +        WARN("Nothing appropriate found for %s\n", debugstr_w(key));
 +
 +    return retval;
 +}
 +
 +/*************************************************************************
 + * FindExecutableA            [SHELL32.@]
 + */
 +HINSTANCE WINAPI FindExecutableA(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult)
 +{
 +    HINSTANCE retval;
 +    WCHAR *wFile = NULL, *wDirectory = NULL;
 +    WCHAR wResult[MAX_PATH];
 +
 +    if (lpFile) __SHCloneStrAtoW(&wFile, lpFile);
 +    if (lpDirectory) __SHCloneStrAtoW(&wDirectory, lpDirectory);
 +
 +    retval = FindExecutableW(wFile, wDirectory, wResult);
 +    WideCharToMultiByte(CP_ACP, 0, wResult, -1, lpResult, MAX_PATH, NULL, NULL);
 +    SHFree(wFile);
 +    SHFree(wDirectory);
 +
 +    TRACE("returning %s\n", lpResult);
 +    return retval;
 +}
 +
 +/*************************************************************************
 + * FindExecutableW            [SHELL32.@]
 + *
 + * This function returns the executable associated with the specified file
 + * for the default verb.
 + *
 + * PARAMS
 + *  lpFile   [I] The file to find the association for. This must refer to
 + *               an existing file otherwise FindExecutable fails and returns
 + *               SE_ERR_FNF.
 + *  lpResult [O] Points to a buffer into which the executable path is
 + *               copied. This parameter must not be NULL otherwise
 + *               FindExecutable() segfaults. The buffer must be of size at
 + *               least MAX_PATH characters.
 + *
 + * RETURNS
 + *  A value greater than 32 on success, less than or equal to 32 otherwise.
 + *  See the SE_ERR_* constants.
 + *
 + * NOTES
 + *  On Windows XP and 2003, FindExecutable() seems to first convert the
 + *  filename into 8.3 format, thus taking into account only the first three
 + *  characters of the extension, and expects to find an association for those.
 + *  However other Windows versions behave sanely.
 + */
 +HINSTANCE WINAPI FindExecutableW(LPCWSTR lpFile, LPCWSTR lpDirectory, LPWSTR lpResult)
 +{
 +    UINT_PTR retval = SE_ERR_NOASSOC;
 +    WCHAR old_dir[1024];
 +
 +    TRACE("File %s, Dir %s\n", debugstr_w(lpFile), debugstr_w(lpDirectory));
 +
 +    lpResult[0] = '\0'; /* Start off with an empty return string */
 +    if (lpFile == NULL)
 +        return (HINSTANCE)SE_ERR_FNF;
 +
 +    if (lpDirectory)
 +    {
 +        GetCurrentDirectoryW(sizeof(old_dir) / sizeof(WCHAR), old_dir);
 +        SetCurrentDirectoryW(lpDirectory);
 +    }
 +
 +    retval = SHELL_FindExecutable(lpDirectory, lpFile, wszOpen, lpResult, MAX_PATH, NULL, NULL, NULL, NULL);
 +
 +    TRACE("returning %s\n", debugstr_w(lpResult));
 +    if (lpDirectory)
 +        SetCurrentDirectoryW(old_dir);
 +    return (HINSTANCE)retval;
 +}
 +
 +/* FIXME: is this already implemented somewhere else? */
 +static HKEY ShellExecute_GetClassKey(const SHELLEXECUTEINFOW *sei)
 +{
 +    LPCWSTR ext = NULL, lpClass = NULL;
 +    LPWSTR cls = NULL;
 +    DWORD type = 0, sz = 0;
 +    HKEY hkey = 0;
 +    LONG r;
 +
 +    if (sei->fMask & SEE_MASK_CLASSALL)
 +        return sei->hkeyClass;
 +
 +    if (sei->fMask & SEE_MASK_CLASSNAME)
 +        lpClass = sei->lpClass;
 +    else
 +    {
 +        ext = PathFindExtensionW(sei->lpFile);
 +        TRACE("ext = %s\n", debugstr_w(ext));
 +        if (!ext)
 +            return hkey;
 +
 +        r = RegOpenKeyW(HKEY_CLASSES_ROOT, ext, &hkey);
 +        if (r != ERROR_SUCCESS)
 +            return hkey;
 +
 +        r = RegQueryValueExW(hkey, NULL, 0, &type, NULL, &sz);
 +        if (r == ERROR_SUCCESS && type == REG_SZ)
 +        {
 +            sz += sizeof (WCHAR);
 +            cls = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, sz);
 +            cls[0] = 0;
 +            RegQueryValueExW(hkey, NULL, 0, &type, (LPBYTE) cls, &sz);
 +        }
 +
 +        RegCloseKey( hkey );
 +        lpClass = cls;
 +    }
 +
 +    TRACE("class = %s\n", debugstr_w(lpClass));
 +
 +    hkey = 0;
 +    if (lpClass)
 +        RegOpenKeyW( HKEY_CLASSES_ROOT, lpClass, &hkey);
 +
 +    HeapFree(GetProcessHeap(), 0, cls);
 +
 +    return hkey;
 +}
 +
 +static IDataObject *shellex_get_dataobj( LPSHELLEXECUTEINFOW sei )
 +{
 +    LPCITEMIDLIST pidllast = NULL;
 +    IDataObject *dataobj = NULL;
 +    IShellFolder *shf = NULL;
 +    LPITEMIDLIST pidl = NULL;
 +    HRESULT r;
 +
 +    if (sei->fMask & SEE_MASK_CLASSALL)
 +        pidl = (LPITEMIDLIST)sei->lpIDList;
 +    else
 +    {
 +        WCHAR fullpath[MAX_PATH];
 +        BOOL ret;
 +
 +        fullpath[0] = 0;
 +        ret = GetFullPathNameW(sei->lpFile, MAX_PATH, fullpath, NULL);
 +        if (!ret)
 +            goto end;
 +
 +        pidl = ILCreateFromPathW(fullpath);
 +    }
 +
 +    r = SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &shf), &pidllast);
 +    if (FAILED(r))
 +        goto end;
 +
 +    shf->GetUIObjectOf(NULL, 1, &pidllast, IID_NULL_PPV_ARG(IDataObject, &dataobj));
 +
 +end:
 +    if (pidl != sei->lpIDList)
 +        ILFree(pidl);
 +    if (shf)
 +        shf->Release();
 +    return dataobj;
 +}
 +
 +static HRESULT shellex_run_context_menu_default(IShellExtInit *obj,
 +        LPSHELLEXECUTEINFOW sei)
 +{
 +    IContextMenu *cm = NULL;
 +    CMINVOKECOMMANDINFOEX ici;
 +    MENUITEMINFOW info;
 +    WCHAR string[0x80];
 +    INT i, n, def = -1;
 +    HMENU hmenu = 0;
 +    HRESULT r;
 +
 +    TRACE("%p %p\n", obj, sei);
 +
 +    r = obj->QueryInterface(IID_PPV_ARG(IContextMenu, &cm));
 +    if (FAILED(r))
 +        return r;
 +
 +    hmenu = CreateMenu();
 +    if (!hmenu)
 +        goto end;
 +
 +    /* the number of the last menu added is returned in r */
 +    r = cm->QueryContextMenu(hmenu, 0, 0x20, 0x7fff, CMF_DEFAULTONLY);
 +    if (FAILED(r))
 +        goto end;
 +
 +    n = GetMenuItemCount(hmenu);
 +    for (i = 0; i < n; i++)
 +    {
 +        memset(&info, 0, sizeof(info));
 +        info.cbSize = sizeof info;
 +        info.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE | MIIM_DATA | MIIM_ID;
 +        info.dwTypeData = string;
 +        info.cch = sizeof string;
 +        string[0] = 0;
 +        GetMenuItemInfoW(hmenu, i, TRUE, &info);
 +
 +        TRACE("menu %d %s %08x %08lx %08x %08x\n", i, debugstr_w(string),
 +              info.fState, info.dwItemData, info.fType, info.wID);
 +        if ((!sei->lpVerb && (info.fState & MFS_DEFAULT)) ||
 +            (sei->lpVerb && !lstrcmpiW(sei->lpVerb, string)))
 +        {
 +            def = i;
 +            break;
 +        }
 +    }
 +
 +    r = E_FAIL;
 +    if (def == -1)
 +        goto end;
 +
 +    memset(&ici, 0, sizeof ici);
 +    ici.cbSize = sizeof ici;
 +    ici.fMask = CMIC_MASK_UNICODE | (sei->fMask & (SEE_MASK_NOASYNC | SEE_MASK_ASYNCOK | SEE_MASK_FLAG_NO_UI));
 +    ici.nShow = sei->nShow;
 +    ici.lpVerb = MAKEINTRESOURCEA(def);
 +    ici.hwnd = sei->hwnd;
 +    ici.lpParametersW = sei->lpParameters;
 +
 +    r = cm->InvokeCommand((LPCMINVOKECOMMANDINFO)&ici);
 +
 +    TRACE("invoke command returned %08x\n", r);
 +
 +end:
 +    if (hmenu)
 +        DestroyMenu( hmenu );
 +    if (cm)
 +        cm->Release();
 +    return r;
 +}
 +
 +static HRESULT shellex_load_object_and_run(HKEY hkey, LPCGUID guid, LPSHELLEXECUTEINFOW sei)
 +{
 +    IDataObject *dataobj = NULL;
 +    IObjectWithSite *ows = NULL;
 +    IShellExtInit *obj = NULL;
 +    HRESULT r;
 +
 +    TRACE("%p %s %p\n", hkey, debugstr_guid(guid), sei);
 +
 +    r = CoInitialize(NULL);
 +    if (FAILED(r))
 +        goto end;
 +
 +    r = CoCreateInstance(*guid, NULL, CLSCTX_INPROC_SERVER,
 +                         IID_PPV_ARG(IShellExtInit, &obj));
 +    if (FAILED(r))
 +    {
 +        ERR("failed %08x\n", r);
 +        goto end;
 +    }
 +
 +    dataobj = shellex_get_dataobj(sei);
 +    if (!dataobj)
 +    {
 +        ERR("failed to get data object\n");
 +        goto end;
 +    }
 +
 +    r = obj->Initialize(NULL, dataobj, hkey);
 +    if (FAILED(r))
 +        goto end;
 +
 +    r = obj->QueryInterface(IID_PPV_ARG(IObjectWithSite, &ows));
 +    if (FAILED(r))
 +        goto end;
 +
 +    ows->SetSite(NULL);
 +
 +    r = shellex_run_context_menu_default(obj, sei);
 +
 +end:
 +    if (ows)
 +        ows->Release();
 +    if (dataobj)
 +        dataobj->Release();
 +    if (obj)
 +        obj->Release();
 +    CoUninitialize();
 +    return r;
 +}
 +
 +
 +/*************************************************************************
 + *    ShellExecute_FromContextMenu [Internal]
 + */
 +static LONG ShellExecute_FromContextMenu( LPSHELLEXECUTEINFOW sei )
 +{
 +    HKEY hkey, hkeycm = 0;
 +    WCHAR szguid[39];
 +    HRESULT hr;
 +    GUID guid;
 +    DWORD i;
 +    LONG r;
 +
 +    TRACE("%s\n", debugstr_w(sei->lpFile));
 +
 +    hkey = ShellExecute_GetClassKey(sei);
 +    if (!hkey)
 +        return ERROR_FUNCTION_FAILED;
 +
 +    r = RegOpenKeyW(hkey, L"shellex\\ContextMenuHandlers", &hkeycm);
 +    if (r == ERROR_SUCCESS)
 +    {
 +        i = 0;
 +        while (1)
 +        {
 +            r = RegEnumKeyW(hkeycm, i++, szguid, sizeof(szguid) / sizeof(szguid[0]));
 +            if (r != ERROR_SUCCESS)
 +                break;
 +
 +            hr = CLSIDFromString(szguid, &guid);
 +            if (SUCCEEDED(hr))
 +            {
 +                /* stop at the first one that succeeds in running */
 +                hr = shellex_load_object_and_run(hkey, &guid, sei);
 +                if (SUCCEEDED(hr))
 +                    break;
 +            }
 +        }
 +        RegCloseKey(hkeycm);
 +    }
 +
 +    if (hkey != sei->hkeyClass)
 +        RegCloseKey(hkey);
 +    return r;
 +}
 +
 +static UINT_PTR SHELL_execute_class(LPCWSTR wszApplicationName, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
 +{
 +    WCHAR execCmd[1024], wcmd[1024];
 +    /* launch a document by fileclass like 'WordPad.Document.1' */
 +    /* the Commandline contains 'c:\Path\wordpad.exe "%1"' */
 +    /* FIXME: wcmd should not be of a fixed size. Fixed to 1024, MAX_PATH is way too short! */
 +    ULONG cmask = (psei->fMask & SEE_MASK_CLASSALL);
 +    DWORD resultLen;
 +    BOOL done;
 +
 +    HCR_GetExecuteCommandW((cmask == SEE_MASK_CLASSKEY) ? psei->hkeyClass : NULL,
 +                           (cmask == SEE_MASK_CLASSNAME) ? psei->lpClass : NULL,
 +                           psei->lpVerb,
 +                           execCmd, sizeof(execCmd));
 +
 +    /* FIXME: get the extension of lpFile, check if it fits to the lpClass */
 +    TRACE("SEE_MASK_CLASSNAME->%s, doc->%s\n", debugstr_w(execCmd), debugstr_w(wszApplicationName));
 +
 +    wcmd[0] = '\0';
 +    done = SHELL_ArgifyW(wcmd, sizeof(wcmd) / sizeof(WCHAR), execCmd, wszApplicationName, (LPITEMIDLIST)psei->lpIDList, NULL, &resultLen);
 +    if (!done && wszApplicationName[0])
 +    {
 +        strcatW(wcmd, L" ");
 +        strcatW(wcmd, wszApplicationName);
 +    }
 +    if (resultLen > sizeof(wcmd) / sizeof(WCHAR))
 +        ERR("Argify buffer not large enough... truncating\n");
 +    return execfunc(wcmd, NULL, FALSE, psei, psei_out);
 +}
 +
 +static BOOL SHELL_translate_idlist(LPSHELLEXECUTEINFOW sei, LPWSTR wszParameters, DWORD parametersLen, LPWSTR wszApplicationName, DWORD dwApplicationNameLen)
 +{
 +    static const WCHAR wExplorer[] = L"explorer.exe";
 +    WCHAR buffer[MAX_PATH];
 +    BOOL appKnownSingular = FALSE;
 +
 +    /* last chance to translate IDList: now also allow CLSID paths */
 +    if (SUCCEEDED(SHELL_GetPathFromIDListForExecuteW((LPCITEMIDLIST)sei->lpIDList, buffer, sizeof(buffer)))) {
 +        if (buffer[0] == ':' && buffer[1] == ':') {
 +            /* open shell folder for the specified class GUID */
 +            if (strlenW(buffer) + 1 > parametersLen)
 +                ERR("parameters len exceeds buffer size (%i > %i), truncating\n",
 +                    lstrlenW(buffer) + 1, parametersLen);
 +            lstrcpynW(wszParameters, buffer, parametersLen);
 +            if (strlenW(wExplorer) > dwApplicationNameLen)
 +                ERR("application len exceeds buffer size (%i > %i), truncating\n",
 +                    lstrlenW(wExplorer) + 1, dwApplicationNameLen);
 +            lstrcpynW(wszApplicationName, wExplorer, dwApplicationNameLen);
 +            appKnownSingular = TRUE;
 +
 +            sei->fMask &= ~SEE_MASK_INVOKEIDLIST;
 +        } else {
 +            WCHAR target[MAX_PATH];
 +            DWORD attribs;
 +            DWORD resultLen;
 +            /* Check if we're executing a directory and if so use the
 +               handler for the Folder class */
 +            strcpyW(target, buffer);
 +            attribs = GetFileAttributesW(buffer);
 +            if (attribs != INVALID_FILE_ATTRIBUTES &&
 +                    (attribs & FILE_ATTRIBUTE_DIRECTORY) &&
 +                    HCR_GetExecuteCommandW(0, L"Folder",
 +                                           sei->lpVerb,
 +                                           buffer, sizeof(buffer))) {
 +                SHELL_ArgifyW(wszApplicationName, dwApplicationNameLen,
 +                              buffer, target, (LPITEMIDLIST)sei->lpIDList, NULL, &resultLen);
 +                if (resultLen > dwApplicationNameLen)
 +                    ERR("Argify buffer not large enough... truncating\n");
 +                appKnownSingular = FALSE;
 +            }
 +            sei->fMask &= ~SEE_MASK_INVOKEIDLIST;
 +        }
 +    }
 +    return appKnownSingular;
 +}
 +
 +static UINT_PTR SHELL_quote_and_execute(LPCWSTR wcmd, LPCWSTR wszParameters, LPCWSTR lpstrProtocol, LPCWSTR wszApplicationName, LPWSTR env, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
 +{
 +    UINT_PTR retval;
 +    DWORD len;
 +    WCHAR *wszQuotedCmd;
 +
 +    /* Length of quotes plus length of command plus NULL terminator */
 +    len = 2 + lstrlenW(wcmd) + 1;
 +    if (wszParameters[0])
 +    {
 +        /* Length of space plus length of parameters */
 +        len += 1 + lstrlenW(wszParameters);
 +    }
 +    wszQuotedCmd = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
 +    /* Must quote to handle case where cmd contains spaces,
 +     * else security hole if malicious user creates executable file "C:\\Program"
 +     */
 +    strcpyW(wszQuotedCmd, L"\"");
 +    strcatW(wszQuotedCmd, wcmd);
 +    strcatW(wszQuotedCmd, L"\"");
 +    if (wszParameters[0])
 +    {
 +        strcatW(wszQuotedCmd, L" ");
 +        strcatW(wszQuotedCmd, wszParameters);
 +    }
 +
 +    TRACE("%s/%s => %s/%s\n", debugstr_w(wszApplicationName), debugstr_w(psei->lpVerb), debugstr_w(wszQuotedCmd), debugstr_w(lpstrProtocol));
 +
 +    if (*lpstrProtocol)
 +        retval = execute_from_key(lpstrProtocol, wszApplicationName, env, psei->lpParameters, wcmd, execfunc, psei, psei_out);
 +    else
 +        retval = execfunc(wszQuotedCmd, env, FALSE, psei, psei_out);
 +    HeapFree(GetProcessHeap(), 0, wszQuotedCmd);
 +    return retval;
 +}
 +
 +static UINT_PTR SHELL_execute_url(LPCWSTR lpFile, LPCWSTR wFile, LPCWSTR wcmd, LPSHELLEXECUTEINFOW psei, LPSHELLEXECUTEINFOW psei_out, SHELL_ExecuteW32 execfunc)
 +{
 +    static const WCHAR wShell[] = L"\\shell\\";
 +    static const WCHAR wCommand[] = L"\\command";
 +    UINT_PTR retval;
 +    WCHAR *lpstrProtocol;
 +    LPCWSTR lpstrRes;
 +    INT iSize;
 +    DWORD len;
 +
 +    lpstrRes = strchrW(lpFile, ':');
 +    if (lpstrRes)
 +        iSize = lpstrRes - lpFile;
 +    else
 +        iSize = strlenW(lpFile);
 +
 +    TRACE("Got URL: %s\n", debugstr_w(lpFile));
 +    /* Looking for ...protocol\shell\lpOperation\command */
 +    len = iSize + lstrlenW(wShell) + lstrlenW(wCommand) + 1;
 +    if (psei->lpVerb)
 +        len += lstrlenW(psei->lpVerb);
 +    else
 +        len += lstrlenW(wszOpen);
 +    lpstrProtocol = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
 +    memcpy(lpstrProtocol, lpFile, iSize * sizeof(WCHAR));
 +    lpstrProtocol[iSize] = '\0';
 +    strcatW(lpstrProtocol, wShell);
 +    strcatW(lpstrProtocol, psei->lpVerb ? psei->lpVerb : wszOpen);
 +    strcatW(lpstrProtocol, wCommand);
 +
 +    /* Remove File Protocol from lpFile */
 +    /* In the case file://path/file     */
 +    if (!strncmpiW(lpFile, wFile, iSize))
 +    {
 +        lpFile += iSize;
 +        while (*lpFile == ':') lpFile++;
 +    }
 +    retval = execute_from_key(lpstrProtocol, lpFile, NULL, psei->lpParameters,
 +                              wcmd, execfunc, psei, psei_out);
 +    HeapFree(GetProcessHeap(), 0, lpstrProtocol);
 +    return retval;
 +}
 +
 +void do_error_dialog(UINT_PTR retval, HWND hwnd, WCHAR* filename)
 +{
 +    WCHAR msg[2048];
 +    DWORD_PTR msgArguments[3]  = { (DWORD_PTR)filename, 0, 0 };
 +    DWORD error_code;
 +
 +    error_code = GetLastError();
 +
 +    if (retval == SE_ERR_NOASSOC)
 +        LoadStringW(shell32_hInstance, IDS_SHLEXEC_NOASSOC, msg, sizeof(msg) / sizeof(WCHAR));
 +    else
 +        FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY,
 +                       NULL,
 +                       error_code,
 +                       LANG_USER_DEFAULT,
 +                       msg,
 +                       sizeof(msg) / sizeof(WCHAR),
 +                       (va_list*)msgArguments);
 +
 +    MessageBoxW(hwnd, msg, NULL, MB_ICONERROR);
 +}
 +
 +/*************************************************************************
 + *    SHELL_execute [Internal]
 + */
 +BOOL SHELL_execute(LPSHELLEXECUTEINFOW sei, SHELL_ExecuteW32 execfunc)
 +{
 +    static const DWORD unsupportedFlags =
 +        SEE_MASK_INVOKEIDLIST  | SEE_MASK_ICON         | SEE_MASK_HOTKEY |
 +        SEE_MASK_CONNECTNETDRV | SEE_MASK_FLAG_DDEWAIT |
 +        SEE_MASK_UNICODE       | SEE_MASK_ASYNCOK      | SEE_MASK_HMONITOR;
 +
 +    WCHAR parametersBuffer[1024], dirBuffer[MAX_PATH], wcmdBuffer[1024];
 +    WCHAR *wszApplicationName, *wszParameters, *wszDir, *wcmd;
 +    DWORD dwApplicationNameLen = MAX_PATH + 2;
 +    DWORD parametersLen = sizeof(parametersBuffer) / sizeof(WCHAR);
 +    DWORD dirLen = sizeof(dirBuffer) / sizeof(WCHAR);
 +    DWORD wcmdLen = sizeof(wcmdBuffer) / sizeof(WCHAR);
 +    DWORD len;
 +    SHELLEXECUTEINFOW sei_tmp;    /* modifiable copy of SHELLEXECUTEINFO struct */
 +    WCHAR wfileName[MAX_PATH];
 +    WCHAR *env;
 +    WCHAR lpstrProtocol[256];
 +    LPCWSTR lpFile;
 +    UINT_PTR retval = SE_ERR_NOASSOC;
 +    BOOL appKnownSingular = FALSE;
 +
 +    /* make a local copy of the LPSHELLEXECUTEINFO structure and work with this from now on */
 +    sei_tmp = *sei;
 +
 +    TRACE("mask=0x%08x hwnd=%p verb=%s file=%s parm=%s dir=%s show=0x%08x class=%s\n",
 +          sei_tmp.fMask, sei_tmp.hwnd, debugstr_w(sei_tmp.lpVerb),
 +          debugstr_w(sei_tmp.lpFile), debugstr_w(sei_tmp.lpParameters),
 +          debugstr_w(sei_tmp.lpDirectory), sei_tmp.nShow,
 +          ((sei_tmp.fMask & SEE_MASK_CLASSALL) == SEE_MASK_CLASSNAME) ?
 +          debugstr_w(sei_tmp.lpClass) : "not used");
 +
 +    sei->hProcess = NULL;
 +
 +    /* make copies of all path/command strings */
 +    if (!sei_tmp.lpFile)
 +    {
 +        wszApplicationName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwApplicationNameLen * sizeof(WCHAR));
 +        *wszApplicationName = '\0';
 +    }
 +    else if (*sei_tmp.lpFile == '\"')
 +    {
 +        DWORD l = strlenW(sei_tmp.lpFile + 1);
 +        if(l >= dwApplicationNameLen)
 +            dwApplicationNameLen = l + 1;
 +
 +        wszApplicationName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwApplicationNameLen * sizeof(WCHAR));
 +        memcpy(wszApplicationName, sei_tmp.lpFile + 1, (l + 1)*sizeof(WCHAR));
 +
 +        if (wszApplicationName[l-1] == L'\"')
 +            wszApplicationName[l-1] = L'\0';
 +        appKnownSingular = TRUE;
 +
 +        TRACE("wszApplicationName=%s\n", debugstr_w(wszApplicationName));
 +    }
 +    else
 +    {
 +        DWORD l = strlenW(sei_tmp.lpFile) + 1;
 +        if(l > dwApplicationNameLen) dwApplicationNameLen = l + 1;
 +        wszApplicationName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwApplicationNameLen * sizeof(WCHAR));
 +        memcpy(wszApplicationName, sei_tmp.lpFile, l * sizeof(WCHAR));
 +    }
 +
 +    wszParameters = parametersBuffer;
 +    if (sei_tmp.lpParameters)
 +    {
 +        len = lstrlenW(sei_tmp.lpParameters) + 1;
 +        if (len > parametersLen)
 +        {
 +            wszParameters = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
 +            parametersLen = len;
 +        }
 +        strcpyW(wszParameters, sei_tmp.lpParameters);
 +    }
 +    else
 +        *wszParameters = L'\0';
 +
 +    wszDir = dirBuffer;
 +    if (sei_tmp.lpDirectory)
 +    {
 +        len = lstrlenW(sei_tmp.lpDirectory) + 1;
 +        if (len > dirLen)
 +        {
 +            wszDir = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
 +            dirLen = len;
 +        }
 +        strcpyW(wszDir, sei_tmp.lpDirectory);
 +    }
 +    else
 +        *wszDir = L'\0';
 +
 +    /* adjust string pointers to point to the new buffers */
 +    sei_tmp.lpFile = wszApplicationName;
 +    sei_tmp.lpParameters = wszParameters;
 +    sei_tmp.lpDirectory = wszDir;
 +
 +    if (sei_tmp.fMask & unsupportedFlags)
 +    {
 +        FIXME("flags ignored: 0x%08x\n", sei_tmp.fMask & unsupportedFlags);
 +    }
 +
 +    /* process the IDList */
 +    if (sei_tmp.fMask & SEE_MASK_IDLIST)
 +    {
 +        IShellExecuteHookW* pSEH;
 +
 +        HRESULT hr = SHBindToParent((LPCITEMIDLIST)sei_tmp.lpIDList, IID_PPV_ARG(IShellExecuteHookW, &pSEH), NULL);
 +
 +        if (SUCCEEDED(hr))
 +        {
 +            hr = pSEH->Execute(&sei_tmp);
 +
 +            pSEH->Release();
 +
 +            if (hr == S_OK)
 +            {
 +                HeapFree(GetProcessHeap(), 0, wszApplicationName);
 +                if (wszParameters != parametersBuffer)
 +                    HeapFree(GetProcessHeap(), 0, wszParameters);
 +                if (wszDir != dirBuffer)
 +                    HeapFree(GetProcessHeap(), 0, wszDir);
 +                return TRUE;
 +            }
 +        }
 +
 +        SHGetPathFromIDListW((LPCITEMIDLIST)sei_tmp.lpIDList, wszApplicationName);
 +        appKnownSingular = TRUE;
 +        TRACE("-- idlist=%p (%s)\n", sei_tmp.lpIDList, debugstr_w(wszApplicationName));
 +    }
 +
 +    if (ERROR_SUCCESS == ShellExecute_FromContextMenu(&sei_tmp))
 +    {
 +        sei->hInstApp = (HINSTANCE) 33;
 +        HeapFree(GetProcessHeap(), 0, wszApplicationName);
 +        if (wszParameters != parametersBuffer)
 +            HeapFree(GetProcessHeap(), 0, wszParameters);
 +        if (wszDir != dirBuffer)
 +            HeapFree(GetProcessHeap(), 0, wszDir);
 +        return TRUE;
 +    }
 +
 +    if (sei_tmp.fMask & SEE_MASK_CLASSALL)
 +    {
 +        retval = SHELL_execute_class(wszApplicationName, &sei_tmp, sei, execfunc);
 +        if (retval <= 32 && !(sei_tmp.fMask & SEE_MASK_FLAG_NO_UI))
 +        {
 +            OPENASINFO Info;
 +
 +            //FIXME
 +            // need full path
 +
 +            Info.pcszFile = wszApplicationName;
 +            Info.pcszClass = NULL;
 +            Info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_EXEC;
 +
 +            //if (SHOpenWithDialog(sei_tmp.hwnd, &Info) != S_OK)
 +            do_error_dialog(retval, sei_tmp.hwnd, wszApplicationName);
 +        }
 +        HeapFree(GetProcessHeap(), 0, wszApplicationName);
 +        if (wszParameters != parametersBuffer)
 +            HeapFree(GetProcessHeap(), 0, wszParameters);
 +        if (wszDir != dirBuffer)
 +            HeapFree(GetProcessHeap(), 0, wszDir);
 +        return retval > 32;
 +    }
 +
 +    /* Has the IDList not yet been translated? */
 +    if (sei_tmp.fMask & SEE_MASK_IDLIST)
 +    {
 +        appKnownSingular = SHELL_translate_idlist( &sei_tmp, wszParameters,
 +                           parametersLen,
 +                           wszApplicationName,
 +                           dwApplicationNameLen );
 +    }
 +
 +    /* expand environment strings */
 +    len = ExpandEnvironmentStringsW(sei_tmp.lpFile, NULL, 0);
 +    if (len > 0)
 +    {
 +        LPWSTR buf;
 +        buf = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
 +
 +        ExpandEnvironmentStringsW(sei_tmp.lpFile, buf, len + 1);
 +        HeapFree(GetProcessHeap(), 0, wszApplicationName);
 +        dwApplicationNameLen = len + 1;
 +        wszApplicationName = buf;
 +        /* appKnownSingular unmodified */
 +
 +        sei_tmp.lpFile = wszApplicationName;
 +    }
 +
 +    if (*sei_tmp.lpParameters)
 +    {
 +        len = ExpandEnvironmentStringsW(sei_tmp.lpParameters, NULL, 0);
 +        if (len > 0)
 +        {
 +            LPWSTR buf;
 +            len++;
 +            buf = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
 +            ExpandEnvironmentStringsW(sei_tmp.lpParameters, buf, len);
 +            if (wszParameters != parametersBuffer)
 +                HeapFree(GetProcessHeap(), 0, wszParameters);
 +            wszParameters = buf;
 +            parametersLen = len;
 +            sei_tmp.lpParameters = wszParameters;
 +        }
 +    }
 +
 +    if (*sei_tmp.lpDirectory)
 +    {
 +        len = ExpandEnvironmentStringsW(sei_tmp.lpDirectory, NULL, 0);
 +        if (len > 0)
 +        {
 +            LPWSTR buf;
 +            len++;
 +            buf = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
 +            ExpandEnvironmentStringsW(sei_tmp.lpDirectory, buf, len);
 +            if (wszDir != dirBuffer)
 +                HeapFree(GetProcessHeap(), 0, wszDir);
 +            wszDir = buf;
 +            sei_tmp.lpDirectory = wszDir;
 +        }
 +    }
 +
 +    /* Else, try to execute the filename */
 +    TRACE("execute: %s,%s,%s\n", debugstr_w(wszApplicationName), debugstr_w(wszParameters), debugstr_w(wszDir));
 +
 +    /* separate out command line arguments from executable file name */
 +    if (!*sei_tmp.lpParameters && !appKnownSingular)
 +    {
 +        /* If the executable path is quoted, handle the rest of the command line as parameters. */
 +        if (sei_tmp.lpFile[0] == L'"')
 +        {
 +            LPWSTR src = wszApplicationName/*sei_tmp.lpFile*/ + 1;
 +            LPWSTR dst = wfileName;
 +            LPWSTR end;
 +
 +            /* copy the unquoted executable path to 'wfileName' */
 +            while(*src && *src != L'"')
 +                *dst++ = *src++;
 +
 +            *dst = L'\0';
 +
 +            if (*src == L'"')
 +            {
 +                end = ++src;
 +
 +                while(isspace(*src))
 +                    ++src;
 +            }
 +            else
 +                end = src;
 +
 +            /* copy the parameter string to 'wszParameters' */
 +            strcpyW(wszParameters, src);
 +
 +            /* terminate previous command string after the quote character */
 +            *end = L'\0';
 +        }
 +        else
 +        {
 +            /* If the executable name is not quoted, we have to use this search loop here,
 +               that in CreateProcess() is not sufficient because it does not handle shell links. */
 +            WCHAR buffer[MAX_PATH], xlpFile[MAX_PATH];
 +            LPWSTR space, s;
 +
 +            LPWSTR beg = wszApplicationName/*sei_tmp.lpFile*/;
 +            for(s = beg; (space = const_cast<LPWSTR>(strchrW(s, L' '))); s = space + 1)
 +            {
 +                int idx = space - sei_tmp.lpFile;
 +                memcpy(buffer, sei_tmp.lpFile, idx * sizeof(WCHAR));
 +                buffer[idx] = '\0';
 +
 +                /*FIXME This finds directory paths if the targeted file name contains spaces. */
 +                if (SearchPathW(*sei_tmp.lpDirectory ? sei_tmp.lpDirectory : NULL, buffer, wszExe, sizeof(xlpFile) / sizeof(xlpFile[0]), xlpFile, NULL))
 +                {
 +                    /* separate out command from parameter string */
 +                    LPCWSTR p = space + 1;
 +
 +                    while(isspaceW(*p))
 +                        ++p;
 +
 +                    strcpyW(wszParameters, p);
 +                    *space = L'\0';
 +
 +                    break;
 +                }
 +            }
 +
 +            lstrcpynW(wfileName, sei_tmp.lpFile, sizeof(wfileName) / sizeof(WCHAR));
 +        }
 +    }
 +    else
 +        lstrcpynW(wfileName, sei_tmp.lpFile, sizeof(wfileName) / sizeof(WCHAR));
 +
 +    lpFile = wfileName;
 +
 +    wcmd = wcmdBuffer;
 +    len = lstrlenW(wszApplicationName) + 3;
 +    if (sei_tmp.lpParameters[0])
 +        len += 1 + lstrlenW(wszParameters);
 +    if (len > wcmdLen)
 +    {
 +        wcmd = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
 +        wcmdLen = len;
 +    }
 +    swprintf(wcmd, L"\"%s\"", wszApplicationName);
 +    if (sei_tmp.lpParameters[0])
 +    {
 +        strcatW(wcmd, L" ");
 +        strcatW(wcmd, wszParameters);
 +    }
 +
 +    retval = execfunc(wcmd, NULL, FALSE, &sei_tmp, sei);
 +    if (retval > 32)
 +    {
 +        HeapFree(GetProcessHeap(), 0, wszApplicationName);
 +        if (wszParameters != parametersBuffer)
 +            HeapFree(GetProcessHeap(), 0, wszParameters);
 +        if (wszDir != dirBuffer)
 +            HeapFree(GetProcessHeap(), 0, wszDir);
 +        if (wcmd != wcmdBuffer)
 +            HeapFree(GetProcessHeap(), 0, wcmd);
 +        return TRUE;
 +    }
 +
 +    /* Else, try to find the executable */
 +    wcmd[0] = L'\0';
 +    retval = SHELL_FindExecutable(sei_tmp.lpDirectory, lpFile, sei_tmp.lpVerb, wcmd, wcmdLen, lpstrProtocol, &env, (LPITEMIDLIST)sei_tmp.lpIDList, sei_tmp.lpParameters);
 +    if (retval > 32)  /* Found */
 +    {
 +        retval = SHELL_quote_and_execute(wcmd, wszParameters, lpstrProtocol,
 +                                         wszApplicationName, env, &sei_tmp,
 +                                         sei, execfunc);
 +        HeapFree(GetProcessHeap(), 0, env);
 +    }
 +    else if (PathIsDirectoryW(lpFile))
 +    {
 +        WCHAR wExec[MAX_PATH];
 +        WCHAR * lpQuotedFile = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * (strlenW(lpFile) + 3));
 +
 +        if (lpQuotedFile)
 +        {
 +            retval = SHELL_FindExecutable(sei_tmp.lpDirectory, L"explorer",
 +                                          wszOpen, wExec, MAX_PATH,
 +                                          NULL, &env, NULL, NULL);
 +            if (retval > 32)
 +            {
 +                swprintf(lpQuotedFile, L"\"%s\"", lpFile);
 +                retval = SHELL_quote_and_execute(wExec, lpQuotedFile,
 +                                                 lpstrProtocol,
 +                                                 wszApplicationName, env,
 +                                                 &sei_tmp, sei, execfunc);
 +                HeapFree(GetProcessHeap(), 0, env);
 +            }
 +            HeapFree(GetProcessHeap(), 0, lpQuotedFile);
 +        }
 +        else
 +            retval = 0; /* Out of memory */
 +    }
 +    else if (PathIsURLW(lpFile))    /* File not found, check for URL */
 +    {
 +        retval = SHELL_execute_url(lpFile, L"file", wcmd, &sei_tmp, sei, execfunc );
 +    }
 +    /* Check if file specified is in the form www.??????.*** */
 +    else if (!strncmpiW(lpFile, L"www", 3))
 +    {
 +        /* if so, append lpFile http:// and call ShellExecute */
 +        WCHAR lpstrTmpFile[256];
 +        strcpyW(lpstrTmpFile, L"http://");
 +        strcatW(lpstrTmpFile, lpFile);
 +        retval = (UINT_PTR)ShellExecuteW(sei_tmp.hwnd, sei_tmp.lpVerb, lpstrTmpFile, NULL, NULL, 0);
 +    }
 +
 +    TRACE("retval %lu\n", retval);
 +
 +    if (retval <= 32 && !(sei_tmp.fMask & SEE_MASK_FLAG_NO_UI))
 +    {
 +        OPENASINFO Info;
 +
 +        //FIXME
 +        // need full path
 +
 +        Info.pcszFile = wszApplicationName;
 +        Info.pcszClass = NULL;
 +        Info.oaifInFlags = OAIF_ALLOW_REGISTRATION | OAIF_EXEC;
 +
 +        //if (SHOpenWithDialog(sei_tmp.hwnd, &Info) != S_OK)
 +        do_error_dialog(retval, sei_tmp.hwnd, wszApplicationName);
 +    }
 +
 +    HeapFree(GetProcessHeap(), 0, wszApplicationName);
 +    if (wszParameters != parametersBuffer)
 +        HeapFree(GetProcessHeap(), 0, wszParameters);
 +    if (wszDir != dirBuffer)
 +        HeapFree(GetProcessHeap(), 0, wszDir);
 +    if (wcmd != wcmdBuffer)
 +        HeapFree(GetProcessHeap(), 0, wcmd);
 +
 +    sei->hInstApp = (HINSTANCE)(retval > 32 ? 33 : retval);
 +
 +    return retval > 32;
 +}
 +
 +/*************************************************************************
 + * ShellExecuteA            [SHELL32.290]
 + */
 +HINSTANCE WINAPI ShellExecuteA(HWND hWnd, LPCSTR lpOperation, LPCSTR lpFile,
 +                               LPCSTR lpParameters, LPCSTR lpDirectory, INT iShowCmd)
 +{
 +    SHELLEXECUTEINFOA sei;
 +
 +    TRACE("%p,%s,%s,%s,%s,%d\n",
 +          hWnd, debugstr_a(lpOperation), debugstr_a(lpFile),
 +          debugstr_a(lpParameters), debugstr_a(lpDirectory), iShowCmd);
 +
 +    sei.cbSize = sizeof(sei);
 +    sei.fMask = SEE_MASK_FLAG_NO_UI;
 +    sei.hwnd = hWnd;
 +    sei.lpVerb = lpOperation;
 +    sei.lpFile = lpFile;
 +    sei.lpParameters = lpParameters;
 +    sei.lpDirectory = lpDirectory;
 +    sei.nShow = iShowCmd;
 +    sei.lpIDList = 0;
 +    sei.lpClass = 0;
 +    sei.hkeyClass = 0;
 +    sei.dwHotKey = 0;
 +    sei.hProcess = 0;
 +
 +    ShellExecuteExA(&sei);
 +    return sei.hInstApp;
 +}
 +
 +/*************************************************************************
 + * ShellExecuteExA                [SHELL32.292]
 + *
 + */
 +BOOL
 +WINAPI
 +DECLSPEC_HOTPATCH
 +ShellExecuteExA(LPSHELLEXECUTEINFOA sei)
 +{
 +    SHELLEXECUTEINFOW seiW;
 +    BOOL ret;
 +    WCHAR *wVerb = NULL, *wFile = NULL, *wParameters = NULL, *wDirectory = NULL, *wClass = NULL;
 +
 +    TRACE("%p\n", sei);
 +
 +    memcpy(&seiW, sei, sizeof(SHELLEXECUTEINFOW));
 +
 +    if (sei->lpVerb)
 +        seiW.lpVerb = __SHCloneStrAtoW(&wVerb, sei->lpVerb);
 +
 +    if (sei->lpFile)
 +        seiW.lpFile = __SHCloneStrAtoW(&wFile, sei->lpFile);
 +
 +    if (sei->lpParameters)
 +        seiW.lpParameters = __SHCloneStrAtoW(&wParameters, sei->lpParameters);
 +
 +    if (sei->lpDirectory)
 +        seiW.lpDirectory = __SHCloneStrAtoW(&wDirectory, sei->lpDirectory);
 +
 +    if ((sei->fMask & SEE_MASK_CLASSALL) == SEE_MASK_CLASSNAME && sei->lpClass)
 +        seiW.lpClass = __SHCloneStrAtoW(&wClass, sei->lpClass);
 +    else
 +        seiW.lpClass = NULL;
 +
 +    ret = SHELL_execute(&seiW, SHELL_ExecuteW);
 +
 +    sei->hInstApp = seiW.hInstApp;
 +
 +    if (sei->fMask & SEE_MASK_NOCLOSEPROCESS)
 +        sei->hProcess = seiW.hProcess;
 +
 +    SHFree(wVerb);
 +    SHFree(wFile);
 +    SHFree(wParameters);
 +    SHFree(wDirectory);
 +    SHFree(wClass);
 +
 +    return ret;
 +}
 +
 +/*************************************************************************
 + * ShellExecuteExW                [SHELL32.293]
 + *
 + */
 +BOOL
 +WINAPI
 +DECLSPEC_HOTPATCH
 +ShellExecuteExW(LPSHELLEXECUTEINFOW sei)
 +{
 +    return SHELL_execute(sei, SHELL_ExecuteW);
 +}
 +
 +/*************************************************************************
 + * ShellExecuteW            [SHELL32.294]
 + * from shellapi.h
 + * WINSHELLAPI HINSTANCE APIENTRY ShellExecuteW(HWND hwnd, LPCWSTR lpOperation,
 + * LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd);
 + */
 +HINSTANCE WINAPI ShellExecuteW(HWND hwnd, LPCWSTR lpOperation, LPCWSTR lpFile,
 +                               LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd)
 +{
 +    SHELLEXECUTEINFOW sei;
 +
 +    TRACE("\n");
 +    sei.cbSize = sizeof(sei);
 +    sei.fMask = SEE_MASK_FLAG_NO_UI;
 +    sei.hwnd = hwnd;
 +    sei.lpVerb = lpOperation;
 +    sei.lpFile = lpFile;
 +    sei.lpParameters = lpParameters;
 +    sei.lpDirectory = lpDirectory;
 +    sei.nShow = nShowCmd;
 +    sei.lpIDList = 0;
 +    sei.lpClass = 0;
 +    sei.hkeyClass = 0;
 +    sei.dwHotKey = 0;
 +    sei.hProcess = 0;
 +
 +    SHELL_execute(&sei, SHELL_ExecuteW);
 +    return sei.hInstApp;
 +}
 +
 +/*************************************************************************
 + * WOWShellExecute            [SHELL32.@]
 + *
 + * FIXME: the callback function most likely doesn't work the same way on Windows.
 + */
 +EXTERN_C HINSTANCE WINAPI WOWShellExecute(HWND hWnd, LPCSTR lpOperation, LPCSTR lpFile,
 +        LPCSTR lpParameters, LPCSTR lpDirectory, INT iShowCmd, void *callback)
 +{
 +    SHELLEXECUTEINFOW seiW;
 +    WCHAR *wVerb = NULL, *wFile = NULL, *wParameters = NULL, *wDirectory = NULL;
 +    HANDLE hProcess = 0;
 +
 +    seiW.lpVerb = lpOperation ? __SHCloneStrAtoW(&wVerb, lpOperation) : NULL;
 +    seiW.lpFile = lpFile ? __SHCloneStrAtoW(&wFile, lpFile) : NULL;
 +    seiW.lpParameters = lpParameters ? __SHCloneStrAtoW(&wParameters, lpParameters) : NULL;
 +    seiW.lpDirectory = lpDirectory ? __SHCloneStrAtoW(&wDirectory, lpDirectory) : NULL;
 +
 +    seiW.cbSize = sizeof(seiW);
 +    seiW.fMask = 0;
 +    seiW.hwnd = hWnd;
 +    seiW.nShow = iShowCmd;
 +    seiW.lpIDList = 0;
 +    seiW.lpClass = 0;
 +    seiW.hkeyClass = 0;
 +    seiW.dwHotKey = 0;
 +    seiW.hProcess = hProcess;
 +
 +    SHELL_execute(&seiW, (SHELL_ExecuteW32)callback);
 +
 +    SHFree(wVerb);
 +    SHFree(wFile);
 +    SHFree(wParameters);
 +    SHFree(wDirectory);
 +    return seiW.hInstApp;
 +}
 +
 +/*************************************************************************
 + * OpenAs_RunDLLA          [SHELL32.@]
 + */
 +EXTERN_C void WINAPI OpenAs_RunDLLA(HWND hwnd, HINSTANCE hinst, LPCSTR cmdline, int cmdshow)
 +{
 +    FIXME("%p, %p, %s, %d\n", hwnd, hinst, debugstr_a(cmdline), cmdshow);
 +}
 +
 +/*************************************************************************
 + * OpenAs_RunDLLW          [SHELL32.@]
 + */
 +EXTERN_C void WINAPI OpenAs_RunDLLW(HWND hwnd, HINSTANCE hinst, LPCWSTR cmdline, int cmdshow)
 +{
 +    FIXME("%p, %p, %s, %d\n", hwnd, hinst, debugstr_w(cmdline), cmdshow);
 +}
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,088e9e6..088e9e6
mode 000000,100644..100644
--- /dev/null
index 0000000,7a13b4b..7a13b4b
mode 000000,100644..100644
--- /dev/null
index 0000000,b4b6c7d..b4b6c7d
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
index 0000000,451a2c4..451a2c4
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,e493dcd..e493dcd
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,2fbdb31..2fbdb31
mode 000000,100644..100644
--- /dev/null
index 0000000,d159169..d159169
mode 000000,100644..100644
--- /dev/null
index 0000000,36f026e..36f026e
mode 000000,100644..100644
--- /dev/null
index 0000000,1bfdb31..1bfdb31
mode 000000,100644..100644
--- /dev/null
index 0000000,fff8fc0..fff8fc0
mode 000000,100644..100644
--- /dev/null
index 0000000,f9fe386..f9fe386
mode 000000,100644..100644
--- /dev/null
index 0000000,eab8e28..eab8e28
mode 000000,100644..100644
--- /dev/null
index 0000000,c47814b..c47814b
mode 000000,100644..100644
--- /dev/null
index 0000000,18f4a89..18f4a89
mode 000000,100644..100644
--- /dev/null
index 0000000,63128a4..63128a4
mode 000000,100644..100644
--- /dev/null
index 0000000,3dffdaa..3dffdaa
mode 000000,100644..100644
--- /dev/null
index 0000000,3d29e47..3d29e47
mode 000000,100644..100644
--- /dev/null
index 0000000,264fa66..264fa66
mode 000000,100644..100644
--- /dev/null
index 0000000,bf55cce..bf55cce
mode 000000,100644..100644
--- /dev/null
Simple merge
diff --cc lib/rtl/nls.c
Simple merge
diff --cc lib/rtl/rtlp.h
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 9841771,b197c0e..b197c0e
Binary files differ
index cb5ae49,55b259d..55b259d
Binary files differ
index 4a61fae,bff8acc..bff8acc
Binary files differ
index 967b5ff,7e50b19..7e50b19
Binary files differ
index 7650e5f,e580e93..e580e93
Binary files differ
index c9fa74f,abff970..abff970
Binary files differ
index 6a1aeeb,0000000..a6e0177
mode 100644,000000..100644
Binary files differ
index 25f902d,2686870..2686870
Binary files differ
index d72b07f,98738eb..98738eb
Binary files differ
index f1e79d1,789bef3..789bef3
Binary files differ
index 93d08dc,8fe2e0b..8fe2e0b
Binary files differ
index f2296d1,a30b2da..a30b2da
Binary files differ
index e64177f,8938bd8..8938bd8
Binary files differ
index 4916939,4415a11..4415a11
Binary files differ
index 013a54e,8d7ff54..8d7ff54
Binary files differ
index 6a32d97,9bc33ce..9bc33ce
Binary files differ
index 75b348c,e7e701f..e7e701f
Binary files differ
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,12066b5..12066b5
mode 000000,100644..100644
--- /dev/null
index 0000000,cc1bb94..cc1bb94
mode 000000,100644..100644
--- /dev/null
index 0000000,7255086..7255086
mode 000000,100644..100644
--- /dev/null
index 0000000,1d8798a..1d8798a
mode 000000,100644..100644
--- /dev/null
index 0000000,e4dbc6b..e4dbc6b
mode 000000,100644..100644
--- /dev/null
index 0000000,01f95e8..01f95e8
mode 000000,100644..100644
--- /dev/null
index 0000000,41d22d3..41d22d3
mode 000000,100644..100644
--- /dev/null
index 0000000,5e29147..5e29147
mode 000000,100644..100644
--- /dev/null
index 0000000,4070042..4070042
mode 000000,100644..100644
--- /dev/null
index 0000000,a936d1f..a936d1f
mode 000000,100644..100644
--- /dev/null
index 0000000,0cffdfd..0cffdfd
mode 000000,100644..100644
--- /dev/null
index 0000000,c29ef9c..c29ef9c
mode 000000,100644..100644
--- /dev/null
index 0000000,74e1fe4..74e1fe4
mode 000000,100644..100644
--- /dev/null
index 0000000,53927d2..53927d2
mode 000000,100644..100644
--- /dev/null
index 0000000,f0b251d..f0b251d
mode 000000,100644..100644
--- /dev/null
index 0000000,1e5f2de..1e5f2de
mode 000000,100644..100644
--- /dev/null
index 0000000,094d156..094d156
mode 000000,100644..100644
--- /dev/null
index 0000000,1b1337f..1b1337f
mode 000000,100644..100644
--- /dev/null
index 0000000,4f86467..4f86467
mode 000000,100644..100644
--- /dev/null
index 0000000,f84d27c..f84d27c
mode 000000,100644..100644
--- /dev/null
index 0000000,a5b068c..a5b068c
mode 000000,100644..100644
--- /dev/null
index 0000000,03d7dd1..03d7dd1
mode 000000,100644..100644
--- /dev/null
index 0000000,c98d32e..c98d32e
mode 000000,100644..100644
--- /dev/null
index 0000000,119e9bd..119e9bd
mode 000000,100644..100644
--- /dev/null
index 0000000,87f6863..87f6863
mode 000000,100644..100644
--- /dev/null
index 0000000,21f7f8e..21f7f8e
mode 000000,100644..100644
--- /dev/null
index 0000000,590ff05..590ff05
mode 000000,100644..100644
--- /dev/null
index 0000000,ca6de8d..ca6de8d
mode 000000,100644..100644
--- /dev/null
index 0000000,e139c85..e139c85
mode 000000,100644..100644
--- /dev/null
index 0000000,d6cced2..d6cced2
mode 000000,100644..100644
--- /dev/null
index 0000000,9a85a11..9a85a11
mode 000000,100644..100644
--- /dev/null
index 0000000,9ed80ec..9ed80ec
mode 000000,100644..100644
--- /dev/null
diff --cc <