Sync with trunk (r48123)
authorJérôme Gardou <jerome.gardou@reactos.org>
Tue, 20 Jul 2010 20:09:43 +0000 (20:09 +0000)
committerJérôme Gardou <jerome.gardou@reactos.org>
Tue, 20 Jul 2010 20:09:43 +0000 (20:09 +0000)
svn path=/branches/reactos-yarotows/; revision=48145

114 files changed:
1  2 
dll/cpl/appwiz/createlink.c
dll/win32/advapi32/crypt/crypt.c
dll/win32/advapi32/crypt/ros_diff.patch
dll/win32/advapi32/sec/lsa.c
dll/win32/advapi32/sec/misc.c
dll/win32/kernel32/debug/debugger.c
dll/win32/kernel32/except/except.c
dll/win32/kernel32/include/kernel32.h
dll/win32/kernel32/kernel32.pspec
dll/win32/kernel32/kernel32.rbuild
dll/win32/kernel32/mem/procmem.c
dll/win32/kernel32/misc/dllmain.c
dll/win32/kernel32/misc/toolhelp.c
dll/win32/kernel32/misc/utils.c
dll/win32/kernel32/process/proc.c
dll/win32/kernel32/process/procsup.c
dll/win32/kernel32/process/session.c
dll/win32/kernel32/thread/amd64/fiber.S
dll/win32/kernel32/thread/amd64/thread.S
dll/win32/kernel32/thread/fiber.c
dll/win32/kernel32/thread/thread.c
dll/win32/lsasrv/lsarpc.c
dll/win32/lsasrv/privileges.c
dll/win32/user32/windows/font.c
dll/win32/ws2_32/misc/dllmain.c
drivers/bus/pcix/arb/ar_busno.c
drivers/bus/pcix/arb/ar_memio.c
drivers/bus/pcix/arb/arb_comn.c
drivers/bus/pcix/arb/tr_irq.c
drivers/bus/pcix/debug.c
drivers/bus/pcix/device.c
drivers/bus/pcix/dispatch.c
drivers/bus/pcix/enum.c
drivers/bus/pcix/fdo.c
drivers/bus/pcix/intrface/agpintrf.c
drivers/bus/pcix/intrface/busintrf.c
drivers/bus/pcix/intrface/cardbus.c
drivers/bus/pcix/intrface/devhere.c
drivers/bus/pcix/intrface/intrface.c
drivers/bus/pcix/intrface/lddintrf.c
drivers/bus/pcix/intrface/locintrf.c
drivers/bus/pcix/intrface/pmeintf.c
drivers/bus/pcix/intrface/routintf.c
drivers/bus/pcix/pci.h
drivers/bus/pcix/pci/config.c
drivers/bus/pcix/pci/id.c
drivers/bus/pcix/pci/ppbridge.c
drivers/bus/pcix/pci/state.c
drivers/bus/pcix/pcivrify.c
drivers/bus/pcix/pcix.rbuild
drivers/bus/pcix/pdo.c
drivers/bus/pcix/power.c
drivers/bus/pcix/utils.c
drivers/video/videoprt/interrupt.c
hal/halx86/generic/acpi/busemul.c
include/crt/conio.h
include/crt/msc/intrin.h
include/ndk/amd64/ketypes.h
include/ndk/halfuncs.h
include/psdk/ksuuids.h
include/psdk/netevent.h
include/psdk/ntddndis.h
include/psdk/ntddstor.h
include/psdk/ntdef.h
include/psdk/winioctl.h
include/reactos/drivers/pci/pci.h
lib/3rdparty/mingw/crt0_c.c
lib/3rdparty/mingw/crt0_w.c
lib/3rdparty/mingw/crtexe.c
lib/3rdparty/mingw/dllentry.c
lib/3rdparty/mingw/dllmain.c
lib/3rdparty/mingw/tlsthrd.c
lib/rtl/amd64/debug_asm.S
lib/rtl/amd64/except_asm.S
lib/rtl/amd64/rtlmem.S
lib/rtl/amd64/slist.S
lib/rtl/amd64/unwind.c
lib/sdk/crt/misc/assert.c
ntoskrnl/cc/copy.c
ntoskrnl/cc/view.c
ntoskrnl/include/internal/amd64/mm.h
ntoskrnl/include/internal/ke.h
ntoskrnl/include/internal/mm.h
ntoskrnl/io/iomgr/iocomp.c
ntoskrnl/io/iomgr/irp.c
ntoskrnl/ke/bug.c
ntoskrnl/mm/ARM3/contmem.c
ntoskrnl/mm/ARM3/iosup.c
ntoskrnl/mm/ARM3/mdlsup.c
ntoskrnl/mm/ARM3/miarm.h
ntoskrnl/mm/ARM3/mmdbg.c
ntoskrnl/mm/ARM3/mminit.c
ntoskrnl/mm/ARM3/ncache.c
ntoskrnl/mm/ARM3/pagfault.c
ntoskrnl/mm/ARM3/pool.c
ntoskrnl/mm/ARM3/procsup.c
ntoskrnl/mm/ARM3/virtual.c
ntoskrnl/mm/anonmem.c
ntoskrnl/mm/arm/page.c
ntoskrnl/mm/arm/stubs.c
ntoskrnl/mm/balance.c
ntoskrnl/mm/freelist.c
ntoskrnl/mm/i386/page.c
ntoskrnl/mm/i386/pagepae.c
ntoskrnl/mm/marea.c
ntoskrnl/mm/mmfault.c
ntoskrnl/mm/mminit.c
ntoskrnl/mm/pagefile.c
ntoskrnl/mm/powerpc/page.c
ntoskrnl/mm/ppool.c
ntoskrnl/mm/rmap.c
ntoskrnl/mm/section.c
ntoskrnl/rtl/libsupp.c
subsystems/win32/win32k/ntuser/cursoricon.c

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,1991b64..1991b64
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
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 e1e8a26,0000000..1eecc93
mode 100644,000000..100644
--- /dev/null
@@@ -1,1539 -1,0 +1,1540 @@@
-         for (i = 0; i < cyHeight; i++)
 +/*
 + *  ReactOS W32 Subsystem
 + *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
 + *
 + *  This program is free software; you can redistribute it and/or modify
 + *  it under the terms of the GNU General Public License as published by
 + *  the Free Software Foundation; either version 2 of the License, or
 + *  (at your option) any later version.
 + *
 + *  This program 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 General Public License for more details.
 + *
 + *  You should have received a copy of the GNU General Public License along
 + *  with this program; if not, write to the Free Software Foundation, Inc.,
 + *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + */
 +
 +/*
 + * We handle two types of cursors/icons:
 + * - Private
 + *   Loaded without LR_SHARED flag
 + *   Private to a process
 + *   Can be deleted by calling NtDestroyCursorIcon()
 + *   CurIcon->hModule, CurIcon->hRsrc and CurIcon->hGroupRsrc set to NULL
 + * - Shared
 + *   Loaded with LR_SHARED flag
 + *   Possibly shared by multiple processes
 + *   Immune to NtDestroyCursorIcon()
 + *   CurIcon->hModule, CurIcon->hRsrc and CurIcon->hGroupRsrc are valid
 + * There's a M:N relationship between processes and (shared) cursor/icons.
 + * A process can have multiple cursor/icons and a cursor/icon can be used
 + * by multiple processes. To keep track of this we keep a list of all
 + * cursor/icons (CurIconList) and per cursor/icon we keep a list of
 + * CURICON_PROCESS structs starting at CurIcon->ProcessList.
 + */
 +
 +#include <win32k.h>
 +
 +#define NDEBUG
 +#include <debug.h>
 +
 +static PAGED_LOOKASIDE_LIST gProcessLookasideList;
 +static LIST_ENTRY gCurIconList;
 +
 +SYSTEM_CURSORINFO gSysCursorInfo;
 +
 +BOOL
 +InitCursorImpl()
 +{
 +    ExInitializePagedLookasideList(&gProcessLookasideList,
 +                                   NULL,
 +                                   NULL,
 +                                   0,
 +                                   sizeof(CURICON_PROCESS),
 +                                   TAG_DIB,
 +                                   128);
 +    InitializeListHead(&gCurIconList);
 +
 +     gSysCursorInfo.Enabled = FALSE;
 +     gSysCursorInfo.ButtonsDown = 0;
 +     gSysCursorInfo.CursorClipInfo.IsClipped = FALSE;
 +     gSysCursorInfo.LastBtnDown = 0;
 +     gSysCursorInfo.CurrentCursorObject = NULL;
 +     gSysCursorInfo.ShowingCursor = 0;
 +     gSysCursorInfo.ClickLockActive = FALSE;
 +     gSysCursorInfo.ClickLockTime = 0;
 +
 +    return TRUE;
 +}
 +
 +PSYSTEM_CURSORINFO
 +IntGetSysCursorInfo()
 +{
 +    return &gSysCursorInfo;
 +}
 +
 +/* This function creates a reference for the object! */
 +PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon)
 +{
 +    PCURICON_OBJECT CurIcon;
 +
 +    if (!hCurIcon)
 +    {
 +        SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE);
 +        return NULL;
 +    }
 +
 +    CurIcon = (PCURICON_OBJECT)UserReferenceObjectByHandle(hCurIcon, otCursorIcon);
 +    if (!CurIcon)
 +    {
 +        /* we never set ERROR_INVALID_ICON_HANDLE. lets hope noone ever checks for it */
 +        SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE);
 +        return NULL;
 +    }
 +
 +    ASSERT(CurIcon->head.cLockObj >= 1);
 +    return CurIcon;
 +}
 +
 +HCURSOR
 +FASTCALL
 +UserSetCursor(
 +    PCURICON_OBJECT NewCursor,
 +    BOOL ForceChange)
 +{
 +    PSYSTEM_CURSORINFO CurInfo;
 +    PCURICON_OBJECT OldCursor;
 +    HCURSOR hOldCursor = (HCURSOR)0;
 +    HDC hdcScreen;
 +    BOOL bResult;
 +
 +      CurInfo = IntGetSysCursorInfo();
 +
 +    OldCursor = CurInfo->CurrentCursorObject;
 +    if (OldCursor)
 +    {
 +        hOldCursor = (HCURSOR)OldCursor->Self;
 +    }
 +
 +    /* Is the new cursor the same as the old cursor? */
 +    if (OldCursor == NewCursor)
 +    {
 +        /* Nothing to to do in this case */
 +        return hOldCursor;
 +    }
 +
 +    /* Get the screen DC */
 +    if(!(hdcScreen = IntGetScreenDC()))
 +    {
 +        return (HCURSOR)0;
 +    }
 +
 +    /* Do we have a new cursor? */
 +    if (NewCursor)
 +    {
 +        UserReferenceObject(NewCursor);
 +
 +        CurInfo->ShowingCursor = 1;
 +        CurInfo->CurrentCursorObject = NewCursor;
 +
 +        /* Call GDI to set the new screen cursor */
 +        bResult = GreSetPointerShape(hdcScreen,
 +                                     NewCursor->IconInfo.hbmMask,
 +                                     NewCursor->IconInfo.hbmColor,
 +                                     NewCursor->IconInfo.xHotspot,
 +                                     NewCursor->IconInfo.yHotspot,
 +                                     gpsi->ptCursor.x,
 +                                     gpsi->ptCursor.y);
 +
 +
 +    }
 +    else
 +    {
 +        /* Check if were diplaying a cursor */
 +        if (OldCursor && CurInfo->ShowingCursor)
 +        {
 +            /* Remove the cursor */
 +            GreMovePointer(hdcScreen, -1, -1);
 +            DPRINT("Removing pointer!\n");
 +        }
 +
 +        CurInfo->CurrentCursorObject = NULL;
 +        CurInfo->ShowingCursor = 0;
 +    }
 +
 +    /* OldCursor is not in use anymore */
 +    if (OldCursor)
 +    {
 +        UserDereferenceObject(OldCursor);
 +    }
 +
 +    /* Return handle of the old cursor */
 +    return hOldCursor;
 +}
 +
 +BOOL UserSetCursorPos( INT x, INT y, BOOL SendMouseMoveMsg)
 +{
 +    PWINDOW_OBJECT DesktopWindow;
 +    PSYSTEM_CURSORINFO CurInfo;
 +    HDC hDC;
 +    MSG Msg;
 +
 +    if(!(hDC = IntGetScreenDC()))
 +    {
 +        return FALSE;
 +    }
 +
 +    CurInfo = IntGetSysCursorInfo();
 +
 +    DesktopWindow = UserGetDesktopWindow();
 +
 +    if (DesktopWindow)
 +    {
 +        if(x >= DesktopWindow->Wnd->rcClient.right)
 +            x = DesktopWindow->Wnd->rcClient.right - 1;
 +        if(y >= DesktopWindow->Wnd->rcClient.bottom)
 +            y = DesktopWindow->Wnd->rcClient.bottom - 1;
 +    }
 +
 +    if(x < 0)
 +        x = 0;
 +    if(y < 0)
 +        y = 0;
 +
 +    //Clip cursor position
 +    if(CurInfo->CursorClipInfo.IsClipped)
 +    {
 +       if(x >= (LONG)CurInfo->CursorClipInfo.Right)
 +           x = (LONG)CurInfo->CursorClipInfo.Right - 1;
 +       if(x < (LONG)CurInfo->CursorClipInfo.Left)
 +           x = (LONG)CurInfo->CursorClipInfo.Left;
 +       if(y >= (LONG)CurInfo->CursorClipInfo.Bottom)
 +           y = (LONG)CurInfo->CursorClipInfo.Bottom - 1;
 +       if(y < (LONG)CurInfo->CursorClipInfo.Top)
 +           y = (LONG)CurInfo->CursorClipInfo.Top;
 +    }
 +
 +    //Store the new cursor position
 +    gpsi->ptCursor.x = x;
 +    gpsi->ptCursor.y = y;
 +
 +    //Move the mouse pointer
 +    GreMovePointer(hDC, x, y);
 +
 +    if (!SendMouseMoveMsg)
 +       return TRUE;
 +
 +    //Generate a mouse move message
 +    Msg.message = WM_MOUSEMOVE;
 +    Msg.wParam = CurInfo->ButtonsDown;
 +    Msg.lParam = MAKELPARAM(x, y);
 +    Msg.pt = gpsi->ptCursor;
 +    MsqInsertSystemMessage(&Msg);
 +
 +    return TRUE;
 +}
 +
 +/* Called from NtUserCallOneParam with Routine ONEPARAM_ROUTINE_SHOWCURSOR
 + * User32 macro NtUserShowCursor */
 +int UserShowCursor(BOOL bShow)
 +{
 +    PSYSTEM_CURSORINFO CurInfo = IntGetSysCursorInfo();
 +    HDC hdcScreen;
 +
 +    if (!(hdcScreen = IntGetScreenDC()))
 +    {
 +        return 0; /* No mouse */
 +    }
 +
 +    if (bShow == FALSE)
 +    {
 +        /* Check if were diplaying a cursor */
 +        if (CurInfo->ShowingCursor == 1)
 +        {
 +            /* Remove the pointer */
 +            GreMovePointer(hdcScreen, -1, -1);
 +            DPRINT("Removing pointer!\n");
 +        }
 +        CurInfo->ShowingCursor--;
 +    }
 +    else
 +    {
 +        if (CurInfo->ShowingCursor == 0)
 +        {
 +            /*Show the pointer*/
 +            GreMovePointer(hdcScreen, gpsi->ptCursor.x, gpsi->ptCursor.y);
 +        }
 +        CurInfo->ShowingCursor++;
 +    }
 +
 +    return CurInfo->ShowingCursor;
 +}
 +
 +/*
 + * We have to register that this object is in use by the current
 + * process. The only way to do that seems to be to walk the list
 + * of cursor/icon objects starting at W32Process->CursorIconListHead.
 + * If the object is already present in the list, we don't have to do
 + * anything, if it's not present we add it and inc the ProcessCount
 + * in the object. Having to walk the list kind of sucks, but that's
 + * life...
 + */
 +static BOOLEAN FASTCALL
 +ReferenceCurIconByProcess(PCURICON_OBJECT CurIcon)
 +{
 +    PPROCESSINFO Win32Process;
 +    PCURICON_PROCESS Current;
 +
 +    Win32Process = PsGetCurrentProcessWin32Process();
 +
 +    LIST_FOR_EACH(Current, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
 +    {
 +        if (Current->Process == Win32Process)
 +        {
 +            /* Already registered for this process */
 +            return TRUE;
 +        }
 +    }
 +
 +    /* Not registered yet */
 +    Current = ExAllocateFromPagedLookasideList(&gProcessLookasideList);
 +    if (NULL == Current)
 +    {
 +        return FALSE;
 +    }
 +    InsertHeadList(&CurIcon->ProcessList, &Current->ListEntry);
 +    Current->Process = Win32Process;
 +
 +    return TRUE;
 +}
 +
 +PCURICON_OBJECT FASTCALL
 +IntFindExistingCurIconObject(HMODULE hModule,
 +                             HRSRC hRsrc, LONG cx, LONG cy)
 +{
 +    PCURICON_OBJECT CurIcon;
 +
 +    LIST_FOR_EACH(CurIcon, &gCurIconList, CURICON_OBJECT, ListEntry)
 +    {
 +
 +        //    if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon))) //<- huh????
 +//      UserReferenceObject(  CurIcon);
 +//      {
 +        if ((CurIcon->hModule == hModule) && (CurIcon->hRsrc == hRsrc))
 +        {
 +            if (cx && ((cx != CurIcon->Size.cx) || (cy != CurIcon->Size.cy)))
 +            {
 +//               UserDereferenceObject(CurIcon);
 +                continue;
 +            }
 +            if (! ReferenceCurIconByProcess(CurIcon))
 +            {
 +                return NULL;
 +            }
 +
 +            return CurIcon;
 +        }
 +//      }
 +//      UserDereferenceObject(CurIcon);
 +
 +    }
 +
 +    return NULL;
 +}
 +
 +PCURICON_OBJECT
 +IntCreateCurIconHandle()
 +{
 +    PCURICON_OBJECT CurIcon;
 +    HANDLE hCurIcon;
 +
 +    CurIcon = UserCreateObject(gHandleTable, NULL, &hCurIcon, otCursorIcon, sizeof(CURICON_OBJECT));
 +
 +    if (!CurIcon)
 +    {
 +        SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
 +        return FALSE;
 +    }
 +
 +    CurIcon->Self = hCurIcon;
 +    InitializeListHead(&CurIcon->ProcessList);
 +
 +    if (! ReferenceCurIconByProcess(CurIcon))
 +    {
 +        DPRINT1("Failed to add process\n");
 +        UserDeleteObject(hCurIcon, otCursorIcon);
 +        UserDereferenceObject(CurIcon);
 +        return NULL;
 +    }
 +
 +    InsertHeadList(&gCurIconList, &CurIcon->ListEntry);
 +
 +    return CurIcon;
 +}
 +
 +BOOLEAN FASTCALL
 +IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, BOOL ProcessCleanup)
 +{
 +    PSYSTEM_CURSORINFO CurInfo;
 +    HBITMAP bmpMask, bmpColor;
 +    BOOLEAN Ret;
 +    PCURICON_PROCESS Current = NULL;
 +    PPROCESSINFO W32Process = PsGetCurrentProcessWin32Process();
 +
 +    /* Private objects can only be destroyed by their own process */
 +    if (NULL == CurIcon->hModule)
 +    {
 +        ASSERT(CurIcon->ProcessList.Flink->Flink == &CurIcon->ProcessList);
 +        Current = CONTAINING_RECORD(CurIcon->ProcessList.Flink, CURICON_PROCESS, ListEntry);
 +        if (Current->Process != W32Process)
 +        {
 +            DPRINT1("Trying to destroy private icon/cursor of another process\n");
 +            return FALSE;
 +        }
 +    }
 +    else if (! ProcessCleanup)
 +    {
 +        DPRINT("Trying to destroy shared icon/cursor\n");
 +        return FALSE;
 +    }
 +
 +    /* Now find this process in the list of processes referencing this object and
 +       remove it from that list */
 +    LIST_FOR_EACH(Current, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
 +    {
 +        if (Current->Process == W32Process)
 +        {
 +            RemoveEntryList(&Current->ListEntry);
 +            break;
 +        }
 +    }
 +
 +    ExFreeToPagedLookasideList(&gProcessLookasideList, Current);
 +
 +    /* If there are still processes referencing this object we can't destroy it yet */
 +    if (! IsListEmpty(&CurIcon->ProcessList))
 +    {
 +        return TRUE;
 +    }
 +
 +
 +    if (! ProcessCleanup)
 +    {
 +        RemoveEntryList(&CurIcon->ListEntry);
 +    }
 +
 +    CurInfo = IntGetSysCursorInfo();
 +
 +    if (CurInfo->CurrentCursorObject == CurIcon)
 +    {
 +        /* Hide the cursor if we're destroying the current cursor */
 +        UserSetCursor(NULL, TRUE);
 +    }
 +
 +    bmpMask = CurIcon->IconInfo.hbmMask;
 +    bmpColor = CurIcon->IconInfo.hbmColor;
 +
 +    /* delete bitmaps */
 +    if (bmpMask)
 +    {
 +        GDIOBJ_SetOwnership(bmpMask, PsGetCurrentProcess());
 +        GreDeleteObject(bmpMask);
 +        CurIcon->IconInfo.hbmMask = NULL;
 +    }
 +    if (bmpColor)
 +    {
 +        GDIOBJ_SetOwnership(bmpColor, PsGetCurrentProcess());
 +        GreDeleteObject(bmpColor);
 +        CurIcon->IconInfo.hbmColor = NULL;
 +    }
 +
 +    /* We were given a pointer, no need to keep the reference anylonger! */
 +    UserDereferenceObject(CurIcon);
 +    Ret = UserDeleteObject(CurIcon->Self, otCursorIcon);
 +
 +    return Ret;
 +}
 +
 +VOID FASTCALL
 +IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process)
 +{
 +    PCURICON_OBJECT CurIcon, tmp;
 +    PCURICON_PROCESS ProcessData;
 +
 +    LIST_FOR_EACH_SAFE(CurIcon, tmp, &gCurIconList, CURICON_OBJECT, ListEntry)
 +    {
 +        UserReferenceObject(CurIcon);
 +        //    if(NT_SUCCESS(UserReferenceObjectByPointer(Object, otCursorIcon)))
 +        {
 +            LIST_FOR_EACH(ProcessData, &CurIcon->ProcessList, CURICON_PROCESS, ListEntry)
 +            {
 +                if (Win32Process == ProcessData->Process)
 +                {
 +                    RemoveEntryList(&CurIcon->ListEntry);
 +                    IntDestroyCurIconObject(CurIcon, TRUE);
 +                    CurIcon = NULL;
 +                    break;
 +                }
 +            }
 +
 +//         UserDereferenceObject(Object);
 +        }
 +
 +        if (CurIcon)
 +        {
 +            UserDereferenceObject(CurIcon);
 +        }
 +    }
 +
 +}
 +
 +
 +/*
 + * @implemented
 + */
 +BOOL
 +APIENTRY
 +NtUserGetIconInfo(
 +    HANDLE hCurIcon,
 +    PICONINFO IconInfo,
 +    PUNICODE_STRING lpInstName, // optional
 +    PUNICODE_STRING lpResName,  // optional
 +    LPDWORD pbpp,               // optional
 +    BOOL bInternal)
 +{
 +    ICONINFO ii;
 +    PCURICON_OBJECT CurIcon;
 +    NTSTATUS Status = STATUS_SUCCESS;
 +    BOOL Ret = FALSE;
 +    DWORD colorBpp = 0;
 +
 +    DPRINT("Enter NtUserGetIconInfo\n");
 +    UserEnterExclusive();
 +
 +    if (!IconInfo)
 +    {
 +        SetLastWin32Error(ERROR_INVALID_PARAMETER);
 +        goto leave;
 +    }
 +
 +    if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
 +    {
 +        goto leave;
 +    }
 +
 +    RtlCopyMemory(&ii, &CurIcon->IconInfo, sizeof(ICONINFO));
 +
 +    /* Copy bitmaps */
 +    ii.hbmMask = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmMask);
 +    ii.hbmColor = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmColor);
 +
 +    if (pbpp)
 +    {
 +        PSURFACE psurfBmp;
 +
 +        psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmColor);
 +        if (psurfBmp)
 +        {
 +            colorBpp = BitsPerFormat(psurfBmp->SurfObj.iBitmapFormat);
 +            SURFACE_UnlockSurface(psurfBmp);
 +        }
 +    }
 +
 +    /* Copy fields */
 +    _SEH2_TRY
 +    {
 +        ProbeForWrite(IconInfo, sizeof(ICONINFO), 1);
 +        RtlCopyMemory(IconInfo, &ii, sizeof(ICONINFO));
 +
 +        if (pbpp)
 +        {
 +            ProbeForWrite(pbpp, sizeof(DWORD), 1);
 +            *pbpp = colorBpp;
 +        }
 +    }
 +    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +    {
 +        Status = _SEH2_GetExceptionCode();
 +    }
 +    _SEH2_END
 +
 +    if (NT_SUCCESS(Status))
 +        Ret = TRUE;
 +    else
 +        SetLastNtError(Status);
 +
 +    UserDereferenceObject(CurIcon);
 +
 +leave:
 +    DPRINT("Leave NtUserGetIconInfo, ret=%i\n", Ret);
 +    UserLeave();
 +
 +    return Ret;
 +}
 +
 +
 +/*
 + * @implemented
 + */
 +BOOL
 +APIENTRY
 +NtUserGetIconSize(
 +    HANDLE hCurIcon,
 +    UINT istepIfAniCur,
 +    PLONG plcx,       // &size.cx
 +    PLONG plcy)       // &size.cy
 +{
 +    PCURICON_OBJECT CurIcon;
 +    NTSTATUS Status = STATUS_SUCCESS;
 +    BOOL bRet = FALSE;
 +
 +    DPRINT("Enter NtUserGetIconSize\n");
 +    UserEnterExclusive();
 +
 +    if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
 +    {
 +        goto cleanup;
 +    }
 +
 +    _SEH2_TRY
 +    {
 +        ProbeForWrite(plcx, sizeof(LONG), 1);
 +        RtlCopyMemory(plcx, &CurIcon->Size.cx, sizeof(LONG));
 +        ProbeForWrite(plcy, sizeof(LONG), 1);
 +        RtlCopyMemory(plcy, &CurIcon->Size.cy, sizeof(LONG));
 +    }
 +    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +    {
 +        Status = _SEH2_GetExceptionCode();
 +    }
 +    _SEH2_END
 +
 +    if (NT_SUCCESS(Status))
 +        bRet = TRUE;
 +    else
 +        SetLastNtError(Status); // maybe not, test this
 +
 +    UserDereferenceObject(CurIcon);
 +
 +cleanup:
 +    DPRINT("Leave NtUserGetIconSize, ret=%i\n", bRet);
 +    UserLeave();
 +    return bRet;
 +}
 +
 +
 +/*
 + * @unimplemented
 + */
 +DWORD
 +APIENTRY
 +NtUserGetCursorFrameInfo(
 +    DWORD Unknown0,
 +    DWORD Unknown1,
 +    DWORD Unknown2,
 +    DWORD Unknown3)
 +{
 +    UNIMPLEMENTED
 +
 +    return 0;
 +}
 +
 +
 +/*
 + * @implemented
 + */
 +BOOL
 +APIENTRY
 +NtUserGetCursorInfo(
 +    PCURSORINFO pci)
 +{
 +    CURSORINFO SafeCi;
 +    PSYSTEM_CURSORINFO CurInfo;
 +    NTSTATUS Status = STATUS_SUCCESS;
 +    PCURICON_OBJECT CurIcon;
 +    BOOL Ret = FALSE;
 +    DECLARE_RETURN(BOOL);
 +
 +    DPRINT("Enter NtUserGetCursorInfo\n");
 +    UserEnterExclusive();
 +
 +    CurInfo = IntGetSysCursorInfo();
 +    CurIcon = (PCURICON_OBJECT)CurInfo->CurrentCursorObject;
 +
 +    SafeCi.cbSize = sizeof(CURSORINFO);
 +    SafeCi.flags = ((CurInfo->ShowingCursor && CurIcon) ? CURSOR_SHOWING : 0);
 +    SafeCi.hCursor = (CurIcon ? (HCURSOR)CurIcon->Self : (HCURSOR)0);
 +
 +    SafeCi.ptScreenPos = gpsi->ptCursor;
 +
 +    _SEH2_TRY
 +    {
 +        if (pci->cbSize == sizeof(CURSORINFO))
 +        {
 +            ProbeForWrite(pci, sizeof(CURSORINFO), 1);
 +            RtlCopyMemory(pci, &SafeCi, sizeof(CURSORINFO));
 +            Ret = TRUE;
 +        }
 +        else
 +        {
 +            SetLastWin32Error(ERROR_INVALID_PARAMETER);
 +        }
 +    }
 +    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +    {
 +        Status = _SEH2_GetExceptionCode();
 +    }
 +    _SEH2_END;
 +    if (!NT_SUCCESS(Status))
 +    {
 +        SetLastNtError(Status);
 +    }
 +
 +    RETURN(Ret);
 +
 +CLEANUP:
 +    DPRINT("Leave NtUserGetCursorInfo, ret=%i\n",_ret_);
 +    UserLeave();
 +    END_CLEANUP;
 +}
 +
 +BOOL
 +APIENTRY
 +UserClipCursor(
 +    RECTL *prcl)
 +{
 +    /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
 +    PSYSTEM_CURSORINFO CurInfo;
 +    PWINDOW_OBJECT DesktopWindow = NULL;
 +
 +    CurInfo = IntGetSysCursorInfo();
 +
 +    DesktopWindow = UserGetDesktopWindow();
 +
 +    if (prcl != NULL &&
 +       (prcl->right > prcl->left) &&
 +       (prcl->bottom > prcl->top) &&
 +        DesktopWindow != NULL)
 +    {
 +        CurInfo->CursorClipInfo.IsClipped = TRUE;
 +        CurInfo->CursorClipInfo.Left = max(prcl->left, DesktopWindow->Wnd->rcWindow.left);
 +        CurInfo->CursorClipInfo.Top = max(prcl->top, DesktopWindow->Wnd->rcWindow.top);
 +        CurInfo->CursorClipInfo.Right = min(prcl->right, DesktopWindow->Wnd->rcWindow.right);
 +        CurInfo->CursorClipInfo.Bottom = min(prcl->bottom, DesktopWindow->Wnd->rcWindow.bottom);
 +
 +        UserSetCursorPos(gpsi->ptCursor.x, gpsi->ptCursor.y, FALSE);
 +    }
 +    else
 +    {
 +        CurInfo->CursorClipInfo.IsClipped = FALSE;
 +    }
 +
 +    return TRUE;
 +}
 +
 +/*
 + * @implemented
 + */
 +BOOL
 +APIENTRY
 +NtUserClipCursor(
 +    RECTL *prcl)
 +{
 +    /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
 +    RECTL rclLocal;
 +    BOOL bResult;
 +
 +    if (prcl)
 +    {
 +        _SEH2_TRY
 +        {
 +            /* Probe and copy rect */
 +            ProbeForRead(prcl, sizeof(RECTL), 1);
 +            rclLocal = *prcl;
 +        }
 +        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +        {
 +            SetLastWin32Error(ERROR_INVALID_PARAMETER);
 +            _SEH2_YIELD(return FALSE;)
 +        }
 +        _SEH2_END
 +
 +        prcl = &rclLocal;
 +    }
 +
 +    UserEnterExclusive();
 +
 +    /* Call the internal function */
 +    bResult = UserClipCursor(prcl);
 +
 +    UserLeave();
 +
 +    return bResult;
 +}
 +
 +
 +/*
 + * @implemented
 + */
 +BOOL
 +APIENTRY
 +NtUserDestroyCursor(
 +    HANDLE hCurIcon,
 +    DWORD Unknown)
 +{
 +    PCURICON_OBJECT CurIcon;
 +    BOOL ret;
 +    DECLARE_RETURN(BOOL);
 +
 +    DPRINT("Enter NtUserDestroyCursorIcon\n");
 +    UserEnterExclusive();
 +
 +    if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
 +    {
 +        RETURN(FALSE);
 +    }
 +
 +    ret = IntDestroyCurIconObject(CurIcon, FALSE);
 +    /* Note: IntDestroyCurIconObject will remove our reference for us! */
 +
 +    RETURN(ret);
 +
 +CLEANUP:
 +    DPRINT("Leave NtUserDestroyCursorIcon, ret=%i\n",_ret_);
 +    UserLeave();
 +    END_CLEANUP;
 +}
 +
 +
 +/*
 + * @implemented
 + */
 +HICON
 +APIENTRY
 +NtUserFindExistingCursorIcon(
 +    HMODULE hModule,
 +    HRSRC hRsrc,
 +    LONG cx,
 +    LONG cy)
 +{
 +    PCURICON_OBJECT CurIcon;
 +    HANDLE Ret = (HANDLE)0;
 +    DECLARE_RETURN(HICON);
 +
 +    DPRINT("Enter NtUserFindExistingCursorIcon\n");
 +    UserEnterExclusive();
 +
 +    CurIcon = IntFindExistingCurIconObject(hModule, hRsrc, cx, cy);
 +    if (CurIcon)
 +    {
 +        Ret = CurIcon->Self;
 +
 +//      IntReleaseCurIconObject(CurIcon);//faxme: is this correct? does IntFindExistingCurIconObject add a ref?
 +        RETURN(Ret);
 +    }
 +
 +    SetLastWin32Error(ERROR_INVALID_CURSOR_HANDLE);
 +    RETURN((HANDLE)0);
 +
 +CLEANUP:
 +    DPRINT("Leave NtUserFindExistingCursorIcon, ret=%i\n",_ret_);
 +    UserLeave();
 +    END_CLEANUP;
 +}
 +
 +
 +/*
 + * @implemented
 + */
 +BOOL
 +APIENTRY
 +NtUserGetClipCursor(
 +    RECTL *lpRect)
 +{
 +    /* FIXME - check if process has WINSTA_READATTRIBUTES */
 +    PSYSTEM_CURSORINFO CurInfo;
 +    RECTL Rect;
 +    NTSTATUS Status;
 +    DECLARE_RETURN(BOOL);
 +
 +    DPRINT("Enter NtUserGetClipCursor\n");
 +    UserEnterExclusive();
 +
 +    if (!lpRect)
 +        RETURN(FALSE);
 +
 +    CurInfo = IntGetSysCursorInfo();
 +    if (CurInfo->CursorClipInfo.IsClipped)
 +    {
 +        Rect.left = CurInfo->CursorClipInfo.Left;
 +        Rect.top = CurInfo->CursorClipInfo.Top;
 +        Rect.right = CurInfo->CursorClipInfo.Right;
 +        Rect.bottom = CurInfo->CursorClipInfo.Bottom;
 +    }
 +    else
 +    {
 +        Rect.left = 0;
 +        Rect.top = 0;
 +        Rect.right = UserGetSystemMetrics(SM_CXSCREEN);
 +        Rect.bottom = UserGetSystemMetrics(SM_CYSCREEN);
 +    }
 +
 +    Status = MmCopyToCaller(lpRect, &Rect, sizeof(RECT));
 +    if (!NT_SUCCESS(Status))
 +    {
 +        SetLastNtError(Status);
 +        RETURN(FALSE);
 +    }
 +
 +    RETURN(TRUE);
 +
 +CLEANUP:
 +    DPRINT("Leave NtUserGetClipCursor, ret=%i\n",_ret_);
 +    UserLeave();
 +    END_CLEANUP;
 +}
 +
 +
 +/*
 + * @implemented
 + */
 +HCURSOR
 +APIENTRY
 +NtUserSetCursor(
 +    HCURSOR hCursor)
 +{
 +    PCURICON_OBJECT CurIcon;
 +    HICON OldCursor;
 +    DECLARE_RETURN(HCURSOR);
 +
 +    DPRINT("Enter NtUserSetCursor\n");
 +    UserEnterExclusive();
 +
 +    if (hCursor)
 +    {
 +        if (!(CurIcon = UserGetCurIconObject(hCursor)))
 +        {
 +            RETURN(NULL);
 +        }
 +    }
 +    else
 +    {
 +        CurIcon = NULL;
 +    }
 +
 +    OldCursor = UserSetCursor(CurIcon, FALSE);
 +
 +    if (CurIcon)
 +    {
 +        UserDereferenceObject(CurIcon);
 +    }
 +
 +    RETURN(OldCursor);
 +
 +CLEANUP:
 +    DPRINT("Leave NtUserSetCursor, ret=%i\n",_ret_);
 +    UserLeave();
 +    END_CLEANUP;
 +}
 +
 +
 +/*
 + * @implemented
 + */
 +BOOL
 +APIENTRY
 +NtUserSetCursorContents(
 +    HANDLE hCurIcon,
 +    PICONINFO UnsafeIconInfo)
 +{
 +    PCURICON_OBJECT CurIcon;
 +    ICONINFO IconInfo;
 +    PSURFACE psurfBmp;
 +    NTSTATUS Status;
 +    BOOL Ret = FALSE;
 +    DECLARE_RETURN(BOOL);
 +
 +    DPRINT("Enter NtUserSetCursorContents\n");
 +    UserEnterExclusive();
 +
 +    if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
 +    {
 +        RETURN(FALSE);
 +    }
 +
 +    /* Copy fields */
 +    Status = MmCopyFromCaller(&IconInfo, UnsafeIconInfo, sizeof(ICONINFO));
 +    if (!NT_SUCCESS(Status))
 +    {
 +        SetLastNtError(Status);
 +        goto done;
 +    }
 +
 +    /* Delete old bitmaps */
 +    if ((CurIcon->IconInfo.hbmColor)
 +                      && (CurIcon->IconInfo.hbmColor != IconInfo.hbmColor))
 +    {
 +        GreDeleteObject(CurIcon->IconInfo.hbmColor);
 +    }
 +    if ((CurIcon->IconInfo.hbmMask)
 +                      && CurIcon->IconInfo.hbmMask != IconInfo.hbmMask)
 +    {
 +        GreDeleteObject(CurIcon->IconInfo.hbmMask);
 +    }
 +
 +    /* Copy new IconInfo field */
 +    CurIcon->IconInfo = IconInfo;
 +
 +    psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmColor);
 +    if (psurfBmp)
 +    {
 +        CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
 +        CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy;
 +        SURFACE_UnlockSurface(psurfBmp);
 +        GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmColor, NULL);
 +    }
 +    else
 +    {
 +        psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmMask);
 +        if (!psurfBmp)
 +            goto done;
 +
 +        CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
 +        CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy / 2;
 +
 +        SURFACE_UnlockSurface(psurfBmp);
 +        GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmMask, NULL);
 +    }
 +
 +    Ret = TRUE;
 +
 +done:
 +
 +    if (CurIcon)
 +    {
 +        UserDereferenceObject(CurIcon);
 +    }
 +    RETURN(Ret);
 +
 +CLEANUP:
 +    DPRINT("Leave NtUserSetCursorContents, ret=%i\n",_ret_);
 +    UserLeave();
 +    END_CLEANUP;
 +}
 +
 +
 +/*
 + * @implemented
 + */
 +#if 0
 +BOOL
 +APIENTRY
 +NtUserSetCursorIconData(
 +    HANDLE Handle,
 +    HMODULE hModule,
 +    PUNICODE_STRING pstrResName,
 +    PICONINFO pIconInfo)
 +{
 +    PCURICON_OBJECT CurIcon;
 +    PSURFACE psurfBmp;
 +    NTSTATUS Status = STATUS_SUCCESS;
 +    BOOL Ret = FALSE;
 +    DECLARE_RETURN(BOOL);
 +
 +    DPRINT("Enter NtUserSetCursorIconData\n");
 +    UserEnterExclusive();
 +
 +    if (!(CurIcon = UserGetCurIconObject(Handle)))
 +    {
 +        RETURN(FALSE);
 +    }
 +
 +    CurIcon->hModule = hModule;
 +    CurIcon->hRsrc = NULL; //hRsrc;
 +    CurIcon->hGroupRsrc = NULL; //hGroupRsrc;
 +
 +    _SEH2_TRY
 +    {
 +        ProbeForRead(pIconInfo, sizeof(ICONINFO), 1);
 +        RtlCopyMemory(&CurIcon->IconInfo, pIconInfo, sizeof(ICONINFO));
 +
 +        CurIcon->IconInfo.hbmMask = BITMAP_CopyBitmap(pIconInfo->hbmMask);
 +        CurIcon->IconInfo.hbmColor = BITMAP_CopyBitmap(pIconInfo->hbmColor);
 +
 +        if (CurIcon->IconInfo.hbmColor)
 +        {
 +            if ((psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmColor)))
 +            {
 +                CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
 +                CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy;
 +                SURFACE_UnlockSurface(psurfBmp);
 +                GDIOBJ_SetOwnership(GdiHandleTable, CurIcon->IconInfo.hbmMask, NULL);
 +            }
 +        }
 +        if (CurIcon->IconInfo.hbmMask)
 +        {
 +            if (CurIcon->IconInfo.hbmColor == NULL)
 +            {
 +                if ((psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmMask)))
 +                {
 +                    CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx;
 +                    CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy;
 +                    SURFACE_UnlockSurface(psurfBmp);
 +                }
 +            }
 +            GDIOBJ_SetOwnership(GdiHandleTable, CurIcon->IconInfo.hbmMask, NULL);
 +        }
 +    }
 +    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +    {
 +        Status = _SEH2_GetExceptionCode();
 +    }
 +    _SEH2_END
 +
 +    if (!NT_SUCCESS(Status))
 +        SetLastNtError(Status);
 +    else
 +        Ret = TRUE;
 +
 +    UserDereferenceObject(CurIcon);
 +    RETURN(Ret);
 +
 +CLEANUP:
 +    DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_);
 +    UserLeave();
 +    END_CLEANUP;
 +}
 +#else
 +BOOL
 +APIENTRY
 +NtUserSetCursorIconData(
 +    HANDLE hCurIcon,
 +    PBOOL fIcon,
 +    POINT *Hotspot,
 +    HMODULE hModule,
 +    HRSRC hRsrc,
 +    HRSRC hGroupRsrc)
 +{
 +    PCURICON_OBJECT CurIcon;
 +    NTSTATUS Status;
 +    POINT SafeHotspot;
 +    BOOL Ret = FALSE;
 +    DECLARE_RETURN(BOOL);
 +
 +    DPRINT("Enter NtUserSetCursorIconData\n");
 +    UserEnterExclusive();
 +
 +    if (!(CurIcon = UserGetCurIconObject(hCurIcon)))
 +    {
 +        RETURN(FALSE);
 +    }
 +
 +    CurIcon->hModule = hModule;
 +    CurIcon->hRsrc = hRsrc;
 +    CurIcon->hGroupRsrc = hGroupRsrc;
 +
 +    /* Copy fields */
 +    if (fIcon)
 +    {
 +        Status = MmCopyFromCaller(&CurIcon->IconInfo.fIcon, fIcon, sizeof(BOOL));
 +        if (!NT_SUCCESS(Status))
 +        {
 +            SetLastNtError(Status);
 +            goto done;
 +        }
 +    }
 +    else
 +    {
 +        if (!Hotspot)
 +            Ret = TRUE;
 +    }
 +
 +    if (Hotspot)
 +    {
 +        Status = MmCopyFromCaller(&SafeHotspot, Hotspot, sizeof(POINT));
 +        if (NT_SUCCESS(Status))
 +        {
 +            CurIcon->IconInfo.xHotspot = SafeHotspot.x;
 +            CurIcon->IconInfo.yHotspot = SafeHotspot.y;
 +
 +            Ret = TRUE;
 +        }
 +        else
 +            SetLastNtError(Status);
 +    }
 +
 +    if (!fIcon && !Hotspot)
 +    {
 +        Ret = TRUE;
 +    }
 +
 +done:
 +      if(Ret)
 +      {
 +              /* This icon is shared now */
 +              GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmMask, NULL);
 +              if(CurIcon->IconInfo.hbmColor)
 +              {
 +                      GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmColor, NULL);
 +              }
 +      }
 +    UserDereferenceObject(CurIcon);
 +    RETURN(Ret);
 +
 +
 +CLEANUP:
 +    DPRINT("Leave NtUserSetCursorIconData, ret=%i\n",_ret_);
 +    UserLeave();
 +    END_CLEANUP;
 +}
 +#endif
 +
 +/*
 + * @unimplemented
 + */
 +BOOL
 +APIENTRY
 +NtUserSetSystemCursor(
 +    HCURSOR hcur,
 +    DWORD id)
 +{
 +    return FALSE;
 +}
 +
 +/* Mostly inspired from wine code */
 +BOOL
 +UserDrawIconEx(
 +    HDC hDc,
 +    INT xLeft,
 +    INT yTop,
 +    PCURICON_OBJECT pIcon,
 +    INT cxWidth,
 +    INT cyHeight,
 +    UINT istepIfAniCur,
 +    HBRUSH hbrFlickerFreeDraw,
 +    UINT diFlags)
 +{
 +    BOOL Ret = FALSE;
 +    HBITMAP hbmMask, hbmColor;
 +    BITMAP bmpColor, bm;
 +    BOOL DoFlickerFree;
 +    INT iOldBkColor = 0, iOldTxtColor = 0;
 +
 +    HDC hMemDC, hDestDC = hDc;
 +    HGDIOBJ hOldOffBrush = 0;
 +    HGDIOBJ hOldOffBmp = 0;
 +    HBITMAP hTmpBmp = 0, hOffBmp = 0;
 +    BOOL bAlpha = FALSE;
 +    INT x=xLeft, y=yTop;
 +
 +    hbmMask = pIcon->IconInfo.hbmMask;
 +    hbmColor = pIcon->IconInfo.hbmColor;
 +
 +    if (istepIfAniCur)
 +        DPRINT1("NtUserDrawIconEx: istepIfAniCur is not supported!\n");
 +
 +    if (!hbmMask || !IntGdiGetObject(hbmMask, sizeof(BITMAP), (PVOID)&bm))
 +    {
 +        return FALSE;
 +    }
 +
 +    if (hbmColor && !IntGdiGetObject(hbmColor, sizeof(BITMAP), (PVOID)&bmpColor))
 +    {
 +        return FALSE;
 +    }
 +
 +    if(!(hMemDC = NtGdiCreateCompatibleDC(hDc)))
 +    {
 +        DPRINT1("NtGdiCreateCompatibleDC failed!\n");
 +        return FALSE;
 +    }
 +
 +    /* Check for alpha */
 +    if (hbmColor
 +            && (bmpColor.bmBitsPixel == 32)
 +            && (diFlags & DI_IMAGE))
 +    {
 +        SURFACE *psurfOff = NULL;
 +        PFN_DIB_GetPixel fnSource_GetPixel = NULL;
 +        INT i, j;
 +
 +        /* In order to correctly display 32 bit icons Windows first scans the image,
 +           because information about transparency is not stored in any image's headers */
 +        psurfOff = SURFACE_LockSurface(hbmColor);
 +        if (psurfOff)
 +        {
 +            fnSource_GetPixel = DibFunctionsForBitmapFormat[psurfOff->SurfObj.iBitmapFormat].DIB_GetPixel;
 +            if (fnSource_GetPixel)
 +            {
 +                for (i = 0; i < psurfOff->SurfObj.sizlBitmap.cx; i++)
 +                {
 +                    for (j = 0; j < psurfOff->SurfObj.sizlBitmap.cy; j++)
 +                    {
 +                        bAlpha = ((BYTE)(fnSource_GetPixel(&psurfOff->SurfObj, i, j) >> 24) & 0xff);
 +                        if (bAlpha)
 +                            break;
 +                    }
 +                    if (bAlpha)
 +                        break;
 +                }
 +            }
 +            SURFACE_UnlockSurface(psurfOff);
 +        }
 +    }
 +
 +    if (!cxWidth)
 +        cxWidth = ((diFlags & DI_DEFAULTSIZE) ?
 +                   UserGetSystemMetrics(SM_CXICON) : pIcon->Size.cx);
 +
 +    if (!cyHeight)
 +        cyHeight = ((diFlags & DI_DEFAULTSIZE) ?
 +                    UserGetSystemMetrics(SM_CYICON) : pIcon->Size.cy);
 +
 +    DoFlickerFree = (hbrFlickerFreeDraw &&
 +                     (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) == GDI_OBJECT_TYPE_BRUSH));
 +
 +    if (DoFlickerFree)
 +    {
 +        hDestDC = NtGdiCreateCompatibleDC(hDc);
 +        if(!hDestDC)
 +        {
 +            DPRINT1("NtGdiCreateCompatibleDC failed!\n");
 +            Ret = FALSE;
 +            goto Cleanup ;
 +        }
 +        hOffBmp = NtGdiCreateCompatibleBitmap(hDc, cxWidth, cyHeight);
 +        if(!hOffBmp)
 +        {
 +            DPRINT1("NtGdiCreateCompatibleBitmap failed!\n");
 +            goto Cleanup ;
 +        }
 +        hOldOffBmp = NtGdiSelectBitmap(hDestDC, hOffBmp);
 +        hOldOffBrush = NtGdiSelectBrush(hDestDC, hbrFlickerFreeDraw);
 +        NtGdiPatBlt(hDestDC, 0, 0, cxWidth, cyHeight, PATCOPY);
 +        NtGdiSelectBrush(hDestDC, hOldOffBrush);
 +        x=y=0;
 +    }
 +
 +    /* Set Background/foreground colors */
 +    iOldTxtColor = IntGdiSetTextColor(hDc, 0); //black
 +    iOldBkColor = IntGdiSetBkColor(hDc, 0x00FFFFFF); //white
 +
 +      if(bAlpha && (diFlags & DI_IMAGE))
 +      {
 +              BLENDFUNCTION pixelblend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
 +        DWORD Pixel;
 +        BYTE Red, Green, Blue, Alpha;
 +        DWORD Count = 0;
 +        INT i, j;
 +        PSURFACE psurf;
 +        PBYTE pBits ;
 +        HBITMAP hMemBmp = NULL;
 +
 +        pBits = ExAllocatePoolWithTag(PagedPool,
 +                                      bmpColor.bmWidthBytes * abs(bmpColor.bmHeight),
 +                                      TAG_BITMAP);
 +        if (pBits == NULL)
 +        {
 +            Ret = FALSE;
 +            goto CleanupAlpha;
 +        }
 +
 +        hMemBmp = BITMAP_CopyBitmap(hbmColor);
 +        if(!hMemBmp)
 +        {
 +            DPRINT1("BITMAP_CopyBitmap failed!");
 +            goto CleanupAlpha;
 +        }
 +
 +        psurf = SURFACE_LockSurface(hMemBmp);
 +        if(!psurf)
 +        {
 +            DPRINT1("SURFACE_LockSurface failed!\n");
 +            goto CleanupAlpha;
 +        }
 +        /* get color bits */
 +        IntGetBitmapBits(psurf,
 +                         bmpColor.bmWidthBytes * abs(bmpColor.bmHeight),
 +                         pBits);
 +
 +        /* premultiply with the alpha channel value */
-             for (j = 0; j < cxWidth; j++)
++        for (i = 0; i < abs(bmpColor.bmHeight); i++)
 +        {
++                      Count = i*bmpColor.bmWidthBytes;
++            for (j = 0; j < bmpColor.bmWidth; j++)
 +            {
 +                Pixel = *(DWORD *)(pBits + Count);
 +
 +                Alpha = ((BYTE)(Pixel >> 24) & 0xff);
 +
 +                Red   = (((BYTE)(Pixel >>  0)) * Alpha) / 0xff;
 +                Green = (((BYTE)(Pixel >>  8)) * Alpha) / 0xff;
 +                Blue  = (((BYTE)(Pixel >> 16)) * Alpha) / 0xff;
 +
 +                *(DWORD *)(pBits + Count) = (DWORD)(Red | (Green << 8) | (Blue << 16) | (Alpha << 24));
 +
 +                Count += sizeof(DWORD);
 +            }
 +        }
 +
 +        /* set mem bits */
 +        IntSetBitmapBits(psurf,
 +                         bmpColor.bmWidthBytes * abs(bmpColor.bmHeight),
 +                         pBits);
 +        SURFACE_UnlockSurface(psurf);
 +
 +        hTmpBmp = NtGdiSelectBitmap(hMemDC, hMemBmp);
 +
 +        Ret = NtGdiAlphaBlend(hDestDC,
 +                                                x,
 +                                                    y,
 +                              cxWidth,
 +                              cyHeight,
 +                              hMemDC,
 +                              0,
 +                              0,
 +                              pIcon->Size.cx,
 +                              pIcon->Size.cy,
 +                              pixelblend,
 +                              NULL);
 +        NtGdiSelectBitmap(hMemDC, hTmpBmp);
 +    CleanupAlpha:
 +        if(pBits) ExFreePoolWithTag(pBits, TAG_BITMAP);
 +        if(hMemBmp) NtGdiDeleteObjectApp(hMemBmp);
 +              if(Ret) goto done;
 +    }
 +
 +
 +    if (diFlags & DI_MASK)
 +    {
 +        hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmMask);
 +        NtGdiStretchBlt(hDestDC,
 +                        x,
 +                        y,
 +                        cxWidth,
 +                        cyHeight,
 +                        hMemDC,
 +                        0,
 +                        0,
 +                        pIcon->Size.cx,
 +                        pIcon->Size.cy,
 +                        SRCAND,
 +                        0);
 +        NtGdiSelectBitmap(hMemDC, hTmpBmp);
 +    }
 +
 +    if(diFlags & DI_IMAGE)
 +    {
 +              if (hbmColor)
 +        {
 +            DWORD rop = (diFlags & DI_MASK) ? SRCINVERT : SRCCOPY ;
 +            hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmColor);
 +            NtGdiStretchBlt(hDestDC,
 +                            x,
 +                            y,
 +                            cxWidth,
 +                            cyHeight,
 +                            hMemDC,
 +                            0,
 +                            0,
 +                            pIcon->Size.cx,
 +                            pIcon->Size.cy,
 +                            rop,
 +                            0);
 +            NtGdiSelectBitmap(hMemDC, hTmpBmp);
 +        }
 +        else
 +        {
 +            /* Mask bitmap holds the information in its second half */
 +            DWORD rop = (diFlags & DI_MASK) ? SRCINVERT : SRCCOPY ;
 +            hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmMask);
 +            NtGdiStretchBlt(hDestDC,
 +                            x,
 +                            y,
 +                            cxWidth,
 +                            cyHeight,
 +                            hMemDC,
 +                            0,
 +                            pIcon->Size.cy,
 +                            pIcon->Size.cx,
 +                            pIcon->Size.cy,
 +                            rop,
 +                            0);
 +            NtGdiSelectBitmap(hMemDC, hTmpBmp);
 +        }
 +    }
 +
 +done:
 +    if(hDestDC != hDc)
 +    {
 +        NtGdiBitBlt(hDc, xLeft, yTop, cxWidth, cyHeight, hDestDC, 0, 0, SRCCOPY, 0, 0);
 +    }
 +
 +    /* Restore foreground and background colors */
 +    IntGdiSetBkColor(hDc, iOldBkColor);
 +    IntGdiSetTextColor(hDc, iOldTxtColor);
 +
 +    Ret = TRUE ;
 +
 +Cleanup:
 +    NtGdiDeleteObjectApp(hMemDC);
 +    if(hDestDC != hDc)
 +    {
 +        if(hOldOffBmp) NtGdiSelectBitmap(hDestDC, hOldOffBmp);
 +        NtGdiDeleteObjectApp(hDestDC);
 +        if(hOffBmp) NtGdiDeleteObjectApp(hOffBmp);
 +    }
 +
 +    return Ret;
 +}
 +
 +/*
 + * @implemented
 + */
 +BOOL
 +APIENTRY
 +NtUserDrawIconEx(
 +    HDC hdc,
 +    int xLeft,
 +    int yTop,
 +    HICON hIcon,
 +    int cxWidth,
 +    int cyHeight,
 +    UINT istepIfAniCur,
 +    HBRUSH hbrFlickerFreeDraw,
 +    UINT diFlags,
 +    BOOL bMetaHDC, // When TRUE, GDI functions need to be handled in User32!
 +    PVOID pDIXData)
 +{
 +    PCURICON_OBJECT pIcon;
 +    BOOL Ret;
 +
 +    DPRINT("Enter NtUserDrawIconEx\n");
 +    UserEnterExclusive();
 +
 +    if (!(pIcon = UserGetCurIconObject(hIcon)))
 +    {
 +        DPRINT1("UserGetCurIconObject() failed!\n");
 +        UserLeave();
 +        return FALSE;
 +    }
 +
 +    Ret = UserDrawIconEx(hdc,
 +                         xLeft,
 +                         yTop,
 +                         pIcon,
 +                         cxWidth,
 +                         cyHeight,
 +                         istepIfAniCur,
 +                         hbrFlickerFreeDraw,
 +                         diFlags);
 +
 +    UserDereferenceObject(pIcon);
 +
 +    UserLeave();
 +    return Ret;
 +}
 +