Synchronize with trunk's revision r57652.

svn path=/branches/ros-csrss/; revision=57653
This commit is contained in:
Hermès Bélusca-Maïto 2012-10-31 00:26:38 +00:00
commit 509461cd33
19 changed files with 2524 additions and 133 deletions

View file

@ -41,7 +41,6 @@
#include <win/basemsg.h>
#include <win/conmsg.h>
#include <win/winmsg.h>
//#include <csr/csrss.h> // FIXME: data header.
/* C Headers */
#include <ctype.h>

View file

@ -1,5 +1,6 @@
set(USE_DIBLIB FALSE)
set(USE_NEW_CURSORICON FALSE)
# Give WIN32 subsystem its own project.
PROJECT(WIN32SS)
@ -103,7 +104,6 @@ list(APPEND SOURCE
user/ntuser/class.c
user/ntuser/clipboard.c
user/ntuser/csr.c
user/ntuser/cursoricon.c
user/ntuser/defwnd.c
user/ntuser/desktop.c
user/ntuser/display.c
@ -190,6 +190,13 @@ else()
${GENDIB_FILES})
endif()
if(USE_NEW_CURSORICON)
add_definitions(-DNEW_CURSORICON)
list(APPEND SOURCE user/ntuser/cursoricon_new.c)
else()
list(APPEND SOURCE user/ntuser/cursoricon.c)
endif()
if(ARCH STREQUAL "i386")
list(APPEND SOURCE
gdi/dib/i386/dib24bpp_hline.s

View file

@ -163,6 +163,6 @@ BOOL NTAPI W32kDosPathNameToNtPathName(PCWSTR, PUNICODE_STRING);
#define LIST_FOR_EACH_SAFE(cursor, cursor2, list, type, field) \
for ((cursor) = CONTAINING_RECORD((list)->Flink, type, field), \
(cursor2) = CONTAINING_RECORD((cursor)->field.Flink, type, field); \
&(cursor)->field != (list) && ((&((cursor)->field)) != NULL); \
&(cursor)->field != (list); \
(cursor) = (cursor2), \
(cursor2) = CONTAINING_RECORD((cursor)->field.Flink, type, field))

View file

@ -200,7 +200,6 @@ typedef struct tagHOOK
struct _DESKTOP *rpdesk;
/* ReactOS */
LIST_ENTRY Chain; /* Hook chain entry */
struct _ETHREAD* Thread; /* Thread owning the hook */
HOOKPROC Proc; /* Hook function */
BOOLEAN Ansi; /* Is it an Ansi hook? */
UNICODE_STRING ModuleName; /* Module name for global hooks */
@ -2739,14 +2738,24 @@ NtUserSetCursorContents(
HANDLE Handle,
PICONINFO IconInfo);
#if 0 // Correct type.
#ifdef NEW_CURSORICON
BOOL
NTAPI
NtUserSetCursorIconData(
HCURSOR hCursor,
PUNICODE_STRING ModuleName,
PUNICODE_STRING ResourceName,
PCURSORDATA pCursorData);
_In_ HCURSOR hCursor,
_In_ HINSTANCE hinst,
_In_ HRSRC hrsrc,
_In_ PICONINFO pii);
#else
BOOL
NTAPI
NtUserSetCursorIconData(
HANDLE Handle,
PBOOL fIcon,
POINT *Hotspot,
HMODULE hModule,
HRSRC hRsrc,
HRSRC hGroupRsrc);
#endif
DWORD
@ -3361,16 +3370,6 @@ NtUserMonitorFromWindow(
IN HWND hWnd,
IN DWORD dwFlags);
BOOL
NTAPI
NtUserSetCursorIconData(
HANDLE Handle,
PBOOL fIcon,
POINT *Hotspot,
HMODULE hModule,
HRSRC hRsrc,
HRSRC hGroupRsrc);
typedef struct _SETSCROLLBARINFO
{
int nTrackPos;

View file

@ -46,6 +46,9 @@ CreateCallProc(IN PDESKTOP Desktop,
NewCallProc->spcpdNext = NULL;
}
/* Release the extra reference (UserCreateObject added 2 references) */
UserDereferenceObject(NewCallProc);
return NewCallProc;
}

View file

@ -211,6 +211,9 @@ IntSynthesizeDib(
/* Add the clipboard data */
IntAddFormatedData(pWinStaObj, CF_DIB, hMem, TRUE, TRUE);
/* Release the extra reference (UserCreateObject added 2 references) */
UserDereferenceObject(pClipboardData);
cleanup:
UserReleaseDC(NULL, hdc, FALSE);
}
@ -302,6 +305,9 @@ IntAddSynthesizedFormats(PWINSTATION_OBJECT pWinStaObj)
*((LCID*)pMemObj->Data) = NtCurrentTeb()->CurrentLocale;
IntAddFormatedData(pWinStaObj, CF_LOCALE, hMem, TRUE, TRUE);
}
/* Release the extra reference (UserCreateObject added 2 references) */
UserDereferenceObject(pMemObj);
}
/* Add CF_TEXT. Note: it is synthesized in user32.dll */
@ -1099,6 +1105,9 @@ NtUserConvertMemHandle(
}
_SEH2_END;
/* Release the extra reference (UserCreateObject added 2 references) */
UserDereferenceObject(pMemObj);
/* If we failed to copy data, remove handle */
if (!pMemObj)
{

View file

@ -234,55 +234,54 @@ IntCreateCurIconHandle()
}
BOOLEAN FASTCALL
IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, BOOL ProcessCleanup)
IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi)
{
PSYSTEM_CURSORINFO CurInfo;
HBITMAP bmpMask, bmpColor;
BOOLEAN Ret;
BOOLEAN Ret, bListEmpty, bFound = FALSE;
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)
{
ERR("Trying to destroy private icon/cursor of another process\n");
return FALSE;
}
}
else if (! ProcessCleanup)
{
TRACE("Trying to destroy shared icon/cursor\n");
return FALSE;
}
/* For handles created without any data (error handling) */
if(IsListEmpty(&CurIcon->ProcessList))
goto emptyList;
/* 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)
if (Current->Process == ppi)
{
RemoveEntryList(&Current->ListEntry);
bFound = TRUE;
bListEmpty = RemoveEntryList(&Current->ListEntry);
break;
}
}
if(!bFound)
{
/* This object doesn't belong to this process */
EngSetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
ExFreeToPagedLookasideList(pgProcessLookasideList, Current);
/* If there are still processes referencing this object we can't destroy it yet */
if (! IsListEmpty(&CurIcon->ProcessList))
if (!bListEmpty)
{
if(CurIcon->head.ppi == ppi)
{
/* Set the first process of the list as owner */
Current = CONTAINING_RECORD(CurIcon->ProcessList.Flink, CURICON_PROCESS, ListEntry);
UserSetObjectOwner(CurIcon, otCursorIcon, Current->Process);
}
UserDereferenceObject(CurIcon);
return TRUE;
}
if (! ProcessCleanup)
{
RemoveEntryList(&CurIcon->ListEntry);
}
emptyList:
/* Remove it from the list */
RemoveEntryList(&CurIcon->ListEntry);
CurInfo = IntGetSysCursorInfo();
@ -320,33 +319,13 @@ VOID FASTCALL
IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process)
{
PCURICON_OBJECT CurIcon, tmp;
PCURICON_PROCESS ProcessData;
/* Run through the list of icon objects */
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);
}
IntDestroyCurIconObject(CurIcon, Win32Process);
}
}
@ -649,7 +628,7 @@ NtUserDestroyCursor(
RETURN(FALSE);
}
ret = IntDestroyCurIconObject(CurIcon, FALSE);
ret = IntDestroyCurIconObject(CurIcon, PsGetCurrentProcessWin32Process());
/* Note: IntDestroyCurIconObject will remove our reference for us! */
RETURN(ret);

View file

@ -8,6 +8,31 @@ typedef struct tagCURICON_PROCESS
PPROCESSINFO Process;
} CURICON_PROCESS, *PCURICON_PROCESS;
#ifdef NEW_CURSORICON
typedef struct _CURICON_FRAME
{
HBITMAP hbmMask;
HBITMAP hbmColor;
HBITMAP hbmAlpha;
} CURICON_FRAME, *PCURICON_FRAME;
typedef struct _CURICON_OBJECT
{
PROCMARKHEAD head;
LIST_ENTRY ListEntry;
HANDLE Self;
LIST_ENTRY ProcessList;
HMODULE hModule;
HRSRC hRsrc;
SIZE Size;
BYTE Shadow;
BOOL bIcon;
POINTL ptlHotspot;
CURICON_FRAME aFrame[1];
} CURICON_OBJECT, *PCURICON_OBJECT;
#else
typedef struct _CURICON_OBJECT
{
PROCMARKHEAD head;
@ -21,6 +46,7 @@ typedef struct _CURICON_OBJECT
BYTE Shadow;
ICONINFO IconInfo;
} CURICON_OBJECT, *PCURICON_OBJECT;
#endif
typedef struct _CURSORACCELERATION_INFO
{

File diff suppressed because it is too large Load diff

View file

@ -250,8 +250,8 @@ co_IntCallLowLevelHook(PHOOK Hook,
BOOL Block = FALSE;
ULONG_PTR uResult = 0;
if (Hook->Thread)
pti = Hook->Thread->Tcb.Win32Thread;
if (Hook->ptiHooked)
pti = Hook->ptiHooked;
else
pti = Hook->head.pti;
@ -990,9 +990,9 @@ IntGetNextHook(PHOOK Hook)
PLIST_ENTRY pLastHead, pElem;
PTHREADINFO pti;
if (Hook->Thread)
if (Hook->ptiHooked)
{
pti = ((PTHREADINFO)Hook->Thread->Tcb.Win32Thread);
pti = Hook->ptiHooked;
pLastHead = &pti->aphkStart[HOOKID_TO_INDEX(HookId)];
}
else
@ -1035,9 +1035,9 @@ IntRemoveHook(PHOOK Hook)
HookId = Hook->HookId;
if (Hook->Thread) // Local
if (Hook->ptiHooked) // Local
{
pti = ((PTHREADINFO)Hook->Thread->Tcb.Win32Thread);
pti = Hook->ptiHooked;
IntFreeHook( Hook);
@ -1496,8 +1496,6 @@ NtUserSetWindowsHookEx( HINSTANCE Mod,
ptiHook = Thread->Tcb.Win32Thread;
ObDereferenceObject(Thread);
if ( ptiHook->rpdesk != pti->rpdesk) // gptiCurrent->rpdesk)
{
ERR("Local hook wrong desktop HookId: %d\n",HookId);
@ -1577,7 +1575,6 @@ NtUserSetWindowsHookEx( HINSTANCE Mod,
}
Hook->ihmod = (INT)Mod; // Module Index from atom table, Do this for now.
Hook->Thread = Thread; /* Set Thread, Null is Global. */
Hook->HookId = HookId;
Hook->rpdesk = ptiHook->rpdesk;
Hook->phkNext = NULL; /* Dont use as a chain! Use link lists for chaining. */
@ -1684,6 +1681,7 @@ NtUserSetWindowsHookEx( HINSTANCE Mod,
CLEANUP:
TRACE("Leave NtUserSetWindowsHookEx, ret=%i\n",_ret_);
if (Thread) ObDereferenceObject(Thread);
UserLeave();
END_CLEANUP;
}

View file

@ -145,6 +145,15 @@ UserSetCursor(
if (NewCursor)
{
/* Call GDI to set the new screen cursor */
#ifdef NEW_CURSORICON
GreSetPointerShape(hdcScreen,
NewCursor->aFrame[0].hbmMask,
NewCursor->aFrame[0].hbmColor,
NewCursor->ptlHotspot.x,
NewCursor->ptlHotspot.y,
gpsi->ptCursor.x,
gpsi->ptCursor.y);
#else
GreSetPointerShape(hdcScreen,
NewCursor->IconInfo.hbmMask,
NewCursor->IconInfo.hbmColor,
@ -152,6 +161,7 @@ UserSetCursor(
NewCursor->IconInfo.yHotspot,
gpsi->ptCursor.x,
gpsi->ptCursor.y);
#endif
}
else /* Note: OldCursor != NewCursor so we have to hide cursor */
{
@ -571,13 +581,23 @@ co_MsqInsertMouseMessage(MSG* Msg, DWORD flags, ULONG_PTR dwExtraInfo, BOOL Hook
if(CurInfo->CurrentCursorObject != MessageQueue->CursorObject)
{
/* Call GDI to set the new screen cursor */
#ifdef NEW_CURSORICON
GreSetPointerShape(hdcScreen,
MessageQueue->CursorObject->aFrame[0].hbmMask,
MessageQueue->CursorObject->aFrame[0].hbmColor,
MessageQueue->CursorObject->ptlHotspot.x,
MessageQueue->CursorObject->ptlHotspot.y,
gpsi->ptCursor.x,
gpsi->ptCursor.y);
#else
GreSetPointerShape(hdcScreen,
MessageQueue->CursorObject->IconInfo.hbmMask,
MessageQueue->CursorObject->IconInfo.hbmColor,
MessageQueue->CursorObject->IconInfo.xHotspot,
MessageQueue->CursorObject->IconInfo.yHotspot,
gpsi->ptCursor.x,
gpsi->ptCursor.y);
#endif
} else
GreMovePointer(hdcScreen, Msg->pt.x, Msg->pt.y);
}

View file

@ -516,6 +516,38 @@ UserReferenceObjectByHandle(HANDLE handle, USER_OBJECT_TYPE type)
return object;
}
VOID
FASTCALL
UserSetObjectOwner(PVOID obj, USER_OBJECT_TYPE type, PVOID owner)
{
PUSER_HANDLE_ENTRY entry = handle_to_entry(gHandleTable, ((PHEAD)obj)->h );
PPROCESSINFO ppi, oldppi;
/* This must be called with a valid object */
ASSERT(entry);
/* For now, only supported for CursorIcon object */
switch(type)
{
case otCursorIcon:
ppi = (PPROCESSINFO)owner;
entry->pi = ppi;
oldppi = ((PPROCMARKHEAD)obj)->ppi;
((PPROCMARKHEAD)obj)->ppi = ppi;
break;
default:
ASSERT(FALSE);
return;
}
oldppi->UserHandleCount--;
ppi->UserHandleCount++;
#if DBG
oldppi->DbgHandleCount[type]--;
ppi->DbgHandleCount[type]++;
#endif
}
/*
* NtUserValidateHandleSecure
*

View file

@ -40,6 +40,7 @@ PVOID UserGetObjectNoErr(PUSER_HANDLE_TABLE, HANDLE, USER_OBJECT_TYPE);
BOOL FASTCALL UserCreateHandleTable(VOID);
BOOL FASTCALL UserObjectInDestroy(HANDLE);
void DbgUserDumpHandleTable();
VOID FASTCALL UserSetObjectOwner(PVOID obj, USER_OBJECT_TYPE type, PVOID owner);
static __inline VOID
UserRefObjectCo(PVOID obj, PUSER_REFERENCE_ENTRY UserReferenceEntry)

View file

@ -2003,6 +2003,7 @@ BOOL UserDrawCaption(
LONG x = Rect.left - cx/2 + 1 + (Rect.bottom - Rect.top)/2; // this is really what Window does
LONG y = (Rect.top + Rect.bottom)/2 - cy/2; // center
UserDrawIconEx(hDc, x, y, pIcon, cx, cy, 0, NULL, DI_NORMAL);
UserDereferenceObject(pIcon);
}
}

View file

@ -526,7 +526,7 @@ NtUserCloseWindowStation(
if (hWinSta == UserGetProcessWindowStation())
{
ERR("Attempted to close process window station");
ERR("Attempted to close process window station\n");
return FALSE;
}
@ -612,19 +612,13 @@ NtUserGetObjectInformation(
/* try windowstation */
TRACE("Trying to open window station 0x%x\n", hObject);
Status = IntValidateWindowStationHandle(
Status = ObReferenceObjectByHandle(
hObject,
UserMode,
0,
&WinStaObject);
if (!NT_SUCCESS(Status) && Status != STATUS_OBJECT_TYPE_MISMATCH)
{
TRACE("Failed: 0x%x\n", Status);
SetLastNtError(Status);
return FALSE;
}
ExWindowStationObjectType,
UserMode,
(PVOID*)&WinStaObject,
NULL);
if (Status == STATUS_OBJECT_TYPE_MISMATCH)
{
@ -635,13 +629,15 @@ NtUserGetObjectInformation(
UserMode,
0,
&DesktopObject);
if (!NT_SUCCESS(Status))
{
TRACE("Failed: 0x%x\n", Status);
SetLastNtError(Status);
return FALSE;
}
}
if (!NT_SUCCESS(Status))
{
ERR("Failed: 0x%x\n", Status);
SetLastNtError(Status);
return FALSE;
}
TRACE("WinSta or Desktop opened!!\n");
/* get data */
@ -713,8 +709,13 @@ NtUserGetObjectInformation(
if (DesktopObject != NULL)
ObDereferenceObject(DesktopObject);
SetLastNtError(Status);
return NT_SUCCESS(Status);
if (!NT_SUCCESS(Status))
{
SetLastNtError(Status);
return FALSE;
}
return TRUE;
}
/*

View file

@ -41,7 +41,7 @@ list(APPEND SOURCE
windows/caret.c
windows/class.c
windows/clipboard.c
windows/cursoricon.c
# windows/cursoricon.c
windows/dc.c
windows/defwnd.c
windows/dialog.c
@ -64,6 +64,12 @@ list(APPEND SOURCE
user32.rc
${CMAKE_CURRENT_BINARY_DIR}/user32.def)
if(USE_NEW_CURSORICON)
list(APPEND SOURCE windows/cursoricon_new.c)
else()
list(APPEND SOURCE windows/cursoricon.c)
endif()
add_library(user32 SHARED ${SOURCE})
set_module_type(user32 win32dll UNICODE)

View file

@ -30,30 +30,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(icon);
#include "pshpack1.h"
typedef struct
{
BYTE bWidth; /* Width, in pixels, of the image */
BYTE bHeight; /* Height, in pixels, of the image */
BYTE bColorCount; /* Number of colors in image (0 if >=8bpp) */
BYTE bReserved; /* Reserved ( must be 0) */
WORD wPlanes; /* Color Planes */
WORD wBitCount; /* Bits per pixel */
DWORD dwBytesInRes; /* How many bytes in this resource? */
DWORD dwImageOffset; /* Where in the file is this image? */
} icoICONDIRENTRY, *LPicoICONDIRENTRY;
typedef struct
{
WORD idReserved; /* Reserved (must be 0) */
WORD idType; /* Resource Type (RES_ICON or RES_CURSOR) */
WORD idCount; /* How many images */
icoICONDIRENTRY idEntries[1]; /* An entry for each image (idCount of 'em) */
} icoICONDIR, *LPicoICONDIR;
#include "poppack.h"
#if 0
static void dumpIcoDirEnty ( LPicoICONDIRENTRY entry )
{

View file

@ -48,7 +48,8 @@ GetUserObjectInformationA(
LPDWORD lpnLengthNeeded)
{
LPWSTR buffer;
BOOL ret = TRUE;
BOOL ret = FALSE;
DWORD LengthNeeded;
TRACE("GetUserObjectInformationA(%x %d %x %d %x)\n", hObj, nIndex,
pvInfo, nLength, lpnLengthNeeded);
@ -65,17 +66,16 @@ GetUserObjectInformationA(
}
/* get unicode string */
if (!GetUserObjectInformationW(hObj, nIndex, buffer, nLength*2, lpnLengthNeeded))
ret = FALSE;
*lpnLengthNeeded /= 2;
if (ret)
if (GetUserObjectInformationW(hObj, nIndex, buffer, nLength*2, lpnLengthNeeded))
{
/* convert string */
if (WideCharToMultiByte(CP_THREAD_ACP, 0, buffer, -1,
pvInfo, nLength, NULL, NULL) == 0)
LengthNeeded = WideCharToMultiByte(CP_THREAD_ACP, 0, buffer, -1,
pvInfo, nLength, NULL, NULL);
if (LengthNeeded != 0)
{
ret = FALSE;
*lpnLengthNeeded = LengthNeeded;
ret = TRUE;
}
}

View file

@ -0,0 +1,756 @@
/*
* PROJECT: ReactOS user32.dll
* COPYRIGHT: GPL - See COPYING in the top level directory
* FILE: dll/win32/user32/windows/class.c
* PURPOSE: Window classes
* PROGRAMMER: Jérôme Gardou (jerome.gardou@reactos.org)
*/
#include <user32.h>
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(cursor);
//WINE_DECLARE_DEBUG_CHANNEL(icon);
//WINE_DECLARE_DEBUG_CHANNEL(resource);
/************* USER32 INTERNAL FUNCTIONS **********/
/* This callback routine is called directly after switching to gui mode */
NTSTATUS
WINAPI
User32SetupDefaultCursors(PVOID Arguments,
ULONG ArgumentLength)
{
BOOL *DefaultCursor = (BOOL*)Arguments;
HCURSOR hCursor;
if(*DefaultCursor)
{
/* set default cursor */
hCursor = LoadCursorW(0, (LPCWSTR)IDC_ARROW);
SetCursor(hCursor);
}
else
{
/* FIXME load system cursor scheme */
SetCursor(0);
hCursor = LoadCursorW(0, (LPCWSTR)IDC_ARROW);
SetCursor(hCursor);
}
return(ZwCallbackReturn(&hCursor, sizeof(HCURSOR), STATUS_SUCCESS));
}
BOOL get_icon_size(HICON hIcon, SIZE *size)
{
return NtUserGetIconSize(hIcon, 0, &size->cx, &size->cy);
}
HCURSOR CursorIconToCursor(HICON hIcon, BOOL SemiTransparent)
{
UNIMPLEMENTED;
return NULL;
}
/************* IMPLEMENTATION HELPERS ******************/
static int get_dib_image_size( int width, int height, int depth )
{
return (((width * depth + 31) / 8) & ~3) * abs( height );
}
static BOOL is_dib_monochrome( const BITMAPINFO* info )
{
if (info->bmiHeader.biBitCount != 1) return FALSE;
if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
const RGBTRIPLE *rgb = ((const BITMAPCOREINFO*)info)->bmciColors;
/* Check if the first color is black */
if ((rgb->rgbtRed == 0) && (rgb->rgbtGreen == 0) && (rgb->rgbtBlue == 0))
{
rgb++;
/* Check if the second color is white */
return ((rgb->rgbtRed == 0xff) && (rgb->rgbtGreen == 0xff)
&& (rgb->rgbtBlue == 0xff));
}
else return FALSE;
}
else /* assume BITMAPINFOHEADER */
{
const RGBQUAD *rgb = info->bmiColors;
/* Check if the first color is black */
if ((rgb->rgbRed == 0) && (rgb->rgbGreen == 0) &&
(rgb->rgbBlue == 0) && (rgb->rgbReserved == 0))
{
rgb++;
/* Check if the second color is white */
return ((rgb->rgbRed == 0xff) && (rgb->rgbGreen == 0xff)
&& (rgb->rgbBlue == 0xff) && (rgb->rgbReserved == 0));
}
else return FALSE;
}
}
static int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
{
unsigned int colors, size, masks = 0;
if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
return sizeof(BITMAPCOREHEADER) + colors *
((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
}
else /* assume BITMAPINFOHEADER */
{
colors = info->bmiHeader.biClrUsed;
if (colors > 256) /* buffer overflow otherwise */
colors = 256;
if (!colors && (info->bmiHeader.biBitCount <= 8))
colors = 1 << info->bmiHeader.biBitCount;
if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
}
}
/************* IMPLEMENTATION CORE ****************/
static BOOL CURSORICON_GetIconInfoFromBMI(
_Inout_ ICONINFO* pii,
_In_ const BITMAPINFO *pbmi,
_In_ int cxDesired,
_In_ int cyDesired
)
{
UINT ubmiSize = bitmap_info_size(pbmi, DIB_RGB_COLORS);
BOOL monochrome = is_dib_monochrome(pbmi);
HDC hdc, hdcScreen;
BITMAPINFO* pbmiCopy;
HBITMAP hbmpOld = NULL;
BOOL bResult = FALSE;
const VOID *pvColor, *pvMask;
/* Check for invalid data */
if ( (pbmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER) &&
pbmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER)) ||
pbmi->bmiHeader.biCompression != BI_RGB )
{
WARN("Invalid resource bitmap header.\n");
return FALSE;
}
/* Fix the hotspot coords */
if(cxDesired != pbmi->bmiHeader.biWidth)
pii->xHotspot = (pii->xHotspot * cxDesired) / pbmi->bmiHeader.biWidth;
if(cxDesired != (pbmi->bmiHeader.biHeight/2))
pii->yHotspot = (pii->yHotspot * cyDesired * 2) / pbmi->bmiHeader.biHeight;
hdcScreen = CreateDCW(L"DISPLAY", NULL, NULL, NULL);
if(!hdcScreen)
return FALSE;
hdc = CreateCompatibleDC(hdcScreen);
if(!hdc)
{
DeleteDC(hdcScreen);
return FALSE;
}
pbmiCopy = HeapAlloc(GetProcessHeap(), 0, max(ubmiSize, FIELD_OFFSET(BITMAPINFO, bmiColors[3])));
if(!pbmiCopy)
goto done;
RtlCopyMemory(pbmiCopy, pbmi, ubmiSize);
pbmiCopy->bmiHeader.biHeight /= 2;
pvColor = (const char*)pbmi + ubmiSize;
pvMask = (const char*)pvColor +
get_dib_image_size(pbmi->bmiHeader.biWidth, pbmiCopy->bmiHeader.biHeight, pbmi->bmiHeader.biBitCount );
/* Set XOR bits */
if(monochrome)
{
/* Create the 1bpp bitmap which will contain everything */
pii->hbmColor = NULL;
pii->hbmMask = CreateCompatibleBitmap(hdc, cxDesired, cyDesired * 2);
if(!pii->hbmMask)
goto done;
hbmpOld = SelectObject(hdc, pii->hbmMask);
if(!hbmpOld)
goto done;
if(!StretchDIBits(hdc, 0, cyDesired, cxDesired, cyDesired,
0, 0, pbmiCopy->bmiHeader.biWidth, pbmiCopy->bmiHeader.biHeight,
pvColor, pbmiCopy, DIB_RGB_COLORS, SRCCOPY))
goto done;
}
else
{
/* Create the bitmap. It has to be compatible with the screen surface */
pii->hbmColor = CreateCompatibleBitmap(hdcScreen, cxDesired, cyDesired);
if(!pii->hbmColor)
goto done;
/* Create the 1bpp mask bitmap */
pii->hbmMask = CreateCompatibleBitmap(hdc, cxDesired, cyDesired);
if(!pii->hbmMask)
goto done;
hbmpOld = SelectObject(hdc, pii->hbmColor);
if(!hbmpOld)
goto done;
if(!StretchDIBits(hdc, 0, 0, cxDesired, cyDesired,
0, 0, pbmiCopy->bmiHeader.biWidth, pbmiCopy->bmiHeader.biHeight,
pvColor, pbmiCopy, DIB_RGB_COLORS, SRCCOPY))
goto done;
/* Now convert the info to monochrome for the mask bits */
pbmiCopy->bmiHeader.biBitCount = 1;
/* Handle the CORE/INFO difference */
if (pbmiCopy->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
{
RGBQUAD *rgb = pbmiCopy->bmiColors;
pbmiCopy->bmiHeader.biClrUsed = pbmiCopy->bmiHeader.biClrImportant = 2;
rgb[0].rgbBlue = rgb[0].rgbGreen = rgb[0].rgbRed = 0x00;
rgb[1].rgbBlue = rgb[1].rgbGreen = rgb[1].rgbRed = 0xff;
rgb[0].rgbReserved = rgb[1].rgbReserved = 0;
}
else
{
RGBTRIPLE *rgb = (RGBTRIPLE *)(((BITMAPCOREHEADER *)pbmiCopy) + 1);
rgb[0].rgbtBlue = rgb[0].rgbtGreen = rgb[0].rgbtRed = 0x00;
rgb[1].rgbtBlue = rgb[1].rgbtGreen = rgb[1].rgbtRed = 0xff;
}
}
/* Set the mask bits */
if(!SelectObject(hdc, pii->hbmMask))
goto done;
bResult = StretchDIBits(hdc, 0, 0, cxDesired, cyDesired,
0, 0, pbmiCopy->bmiHeader.biWidth, pbmiCopy->bmiHeader.biHeight,
pvMask, pbmiCopy, DIB_RGB_COLORS, SRCCOPY) != 0;
done:
DeleteDC(hdcScreen);
if(hbmpOld) SelectObject(hdc, hbmpOld);
DeleteDC(hdc);
if(pbmiCopy) HeapFree(GetProcessHeap(), 0, pbmiCopy);
/* Clean up in case of failure */
if(!bResult)
{
if(pii->hbmMask) DeleteObject(pii->hbmMask);
if(pii->hbmColor) DeleteObject(pii->hbmColor);
}
return bResult;
}
static
HANDLE
BITMAP_LoadImageW(
_In_opt_ HINSTANCE hinst,
_In_ LPCWSTR lpszName,
_In_ int cxDesired,
_In_ int cyDesired,
_In_ UINT fuLoad
)
{
UNIMPLEMENTED;
return NULL;
}
static
HANDLE
CURSORICON_LoadImageW(
_In_opt_ HINSTANCE hinst,
_In_ LPCWSTR lpszName,
_In_ int cxDesired,
_In_ int cyDesired,
_In_ UINT fuLoad,
_In_ BOOL bIcon
)
{
HRSRC hrsrc, hrsrc2;
HANDLE handle, hCurIcon;
CURSORICONDIR* dir;
WORD wResId;
LPBYTE bits;
ICONINFO ii;
BOOL bStatus;
if(fuLoad & LR_LOADFROMFILE)
{
UNIMPLEMENTED;
return NULL;
}
/* Check if caller wants OEM icons */
if(!hinst)
hinst = User32Instance;
/* Find resource ID */
hrsrc = FindResourceW(
hinst,
lpszName,
(LPWSTR)(bIcon ? RT_GROUP_ICON : RT_GROUP_CURSOR));
/* We let FindResource, LoadResource, etc. call SetLastError */
if(!hrsrc)
return NULL;
/* Fix width/height */
if(fuLoad & LR_DEFAULTSIZE)
{
if(!cxDesired) cxDesired = GetSystemMetrics(bIcon ? SM_CXICON : SM_CXCURSOR);
if(!cyDesired) cyDesired = GetSystemMetrics(bIcon ? SM_CYICON : SM_CYCURSOR);
}
/* If LR_SHARED is set, we must check for the cache */
hCurIcon = NtUserFindExistingCursorIcon(hinst, hrsrc, cxDesired, cyDesired);
if(hCurIcon)
return hCurIcon;
handle = LoadResource(hinst, hrsrc);
if(!handle)
return NULL;
dir = LockResource(handle);
if(!dir) return NULL;
/* For now, take the first entry */
wResId = dir->idEntries[0].wResId;
FreeResource(handle);
/* Get the relevant resource pointer */
hrsrc2 = FindResourceW(
hinst,
MAKEINTRESOURCEW(wResId),
(LPWSTR)(bIcon ? RT_ICON : RT_CURSOR));
if(!hrsrc2)
return NULL;
handle = LoadResource(hinst, hrsrc2);
if(!handle)
return NULL;
bits = LockResource(handle);
if(!bits)
{
FreeResource(handle);
return NULL;
}
/* Get the hospot */
if(bIcon)
{
ii.xHotspot = cxDesired/2;
ii.yHotspot = cyDesired/2;
}
else
{
SHORT* ptr = (SHORT*)bits;
ii.xHotspot = ptr[0];
ii.yHotspot = ptr[1];
bits += 2*sizeof(SHORT);
}
ii.fIcon = bIcon;
/* Get the bitmaps */
bStatus = CURSORICON_GetIconInfoFromBMI(
&ii,
(BITMAPINFO*)bits,
cxDesired,
cyDesired);
FreeResource( handle );
if(!bStatus)
return NULL;
/* Create the handle */
hCurIcon = NtUserxCreateEmptyCurObject(bIcon ? 0 : 1);
if(!hCurIcon)
return NULL;
/* Tell win32k */
if(fuLoad & LR_SHARED)
bStatus = NtUserSetCursorIconData(hCurIcon, hinst, hrsrc, &ii);
else
bStatus = NtUserSetCursorIconData(hCurIcon, NULL, NULL, &ii);
if(!bStatus)
{
NtUserDestroyCursor(hCurIcon, TRUE);
hCurIcon = NULL;
}
DeleteObject(ii.hbmMask);
DeleteObject(ii.hbmColor);
return hCurIcon;
}
/************* PUBLIC FUNCTIONS *******************/
HANDLE WINAPI CopyImage(
_In_ HANDLE hImage,
_In_ UINT uType,
_In_ int cxDesired,
_In_ int cyDesired,
_In_ UINT fuFlags
)
{
UNIMPLEMENTED;
return NULL;
}
HICON WINAPI CopyIcon(
_In_ HICON hIcon
)
{
UNIMPLEMENTED;
return NULL;
}
BOOL WINAPI DrawIcon(
_In_ HDC hDC,
_In_ int X,
_In_ int Y,
_In_ HICON hIcon
)
{
return DrawIconEx(hDC, X, Y, hIcon, 0, 0, 0, NULL, DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE);
}
BOOL WINAPI DrawIconEx(
_In_ HDC hdc,
_In_ int xLeft,
_In_ int yTop,
_In_ HICON hIcon,
_In_ int cxWidth,
_In_ int cyWidth,
_In_ UINT istepIfAniCur,
_In_opt_ HBRUSH hbrFlickerFreeDraw,
_In_ UINT diFlags
)
{
UNIMPLEMENTED;
return FALSE;
}
BOOL WINAPI GetIconInfo(
_In_ HICON hIcon,
_Out_ PICONINFO piconinfo
)
{
UNIMPLEMENTED;
return FALSE;
}
BOOL WINAPI DestroyIcon(
_In_ HICON hIcon
)
{
UNIMPLEMENTED;
return FALSE;
}
HICON WINAPI LoadIconA(
_In_opt_ HINSTANCE hInstance,
_In_ LPCSTR lpIconName
)
{
TRACE("%p, %s\n", hInstance, debugstr_a(lpIconName));
return LoadImageA(hInstance,
lpIconName,
IMAGE_ICON,
0,
0,
LR_SHARED | LR_DEFAULTSIZE );
}
HICON WINAPI LoadIconW(
_In_opt_ HINSTANCE hInstance,
_In_ LPCWSTR lpIconName
)
{
TRACE("%p, %s\n", hInstance, debugstr_w(lpIconName));
return LoadImageW(hInstance,
lpIconName,
IMAGE_ICON,
0,
0,
LR_SHARED | LR_DEFAULTSIZE );
}
HCURSOR WINAPI LoadCursorA(
_In_opt_ HINSTANCE hInstance,
_In_ LPCSTR lpCursorName
)
{
TRACE("%p, %s\n", hInstance, debugstr_a(lpCursorName));
return LoadImageA(hInstance,
lpCursorName,
IMAGE_CURSOR,
0,
0,
LR_SHARED | LR_DEFAULTSIZE );
}
HCURSOR WINAPI LoadCursorW(
_In_opt_ HINSTANCE hInstance,
_In_ LPCWSTR lpCursorName
)
{
TRACE("%p, %s\n", hInstance, debugstr_w(lpCursorName));
return LoadImageW(hInstance,
lpCursorName,
IMAGE_CURSOR,
0,
0,
LR_SHARED | LR_DEFAULTSIZE );
}
HCURSOR WINAPI LoadCursorFromFileA(
_In_ LPCSTR lpFileName
)
{
TRACE("%s\n", debugstr_a(lpFileName));
return LoadImageA(NULL,
lpFileName,
IMAGE_CURSOR,
0,
0,
LR_LOADFROMFILE | LR_DEFAULTSIZE );
}
HCURSOR WINAPI LoadCursorFromFileW(
_In_ LPCWSTR lpFileName
)
{
TRACE("%s\n", debugstr_w(lpFileName));
return LoadImageW(NULL,
lpFileName,
IMAGE_CURSOR,
0,
0,
LR_LOADFROMFILE | LR_DEFAULTSIZE );
}
HBITMAP WINAPI LoadBitmapA(
_In_opt_ HINSTANCE hInstance,
_In_ LPCSTR lpBitmapName
)
{
TRACE("%p, %s\n", hInstance, debugstr_a(lpBitmapName));
return LoadImageA(hInstance,
lpBitmapName,
IMAGE_BITMAP,
0,
0,
0);
}
HBITMAP WINAPI LoadBitmapW(
_In_opt_ HINSTANCE hInstance,
_In_ LPCWSTR lpBitmapName
)
{
TRACE("%p, %s\n", hInstance, debugstr_w(lpBitmapName));
return LoadImageW(hInstance,
lpBitmapName,
IMAGE_BITMAP,
0,
0,
0);
}
HANDLE WINAPI LoadImageA(
_In_opt_ HINSTANCE hinst,
_In_ LPCSTR lpszName,
_In_ UINT uType,
_In_ int cxDesired,
_In_ int cyDesired,
_In_ UINT fuLoad
)
{
HANDLE res;
LPWSTR u_name;
DWORD len;
if (IS_INTRESOURCE(lpszName))
return LoadImageW(hinst, (LPCWSTR)lpszName, uType, cxDesired, cyDesired, fuLoad);
len = MultiByteToWideChar( CP_ACP, 0, lpszName, -1, NULL, 0 );
u_name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, lpszName, -1, u_name, len );
res = LoadImageW(hinst, u_name, uType, cxDesired, cyDesired, fuLoad);
HeapFree(GetProcessHeap(), 0, u_name);
return res;
}
HANDLE WINAPI LoadImageW(
_In_opt_ HINSTANCE hinst,
_In_ LPCWSTR lpszName,
_In_ UINT uType,
_In_ int cxDesired,
_In_ int cyDesired,
_In_ UINT fuLoad
)
{
/* Redirect to each implementation */
switch(uType)
{
case IMAGE_BITMAP:
return BITMAP_LoadImageW(hinst, lpszName, cxDesired, cyDesired, fuLoad);
case IMAGE_CURSOR:
case IMAGE_ICON:
return CURSORICON_LoadImageW(hinst, lpszName, cxDesired, cyDesired, fuLoad, uType == IMAGE_ICON);
default:
SetLastError(ERROR_INVALID_PARAMETER);
break;
}
return NULL;
}
int WINAPI LookupIconIdFromDirectory(
_In_ PBYTE presbits,
_In_ BOOL fIcon
)
{
UNIMPLEMENTED;
return 0;
}
int WINAPI LookupIconIdFromDirectoryEx(
_In_ PBYTE presbits,
_In_ BOOL fIcon,
_In_ int cxDesired,
_In_ int cyDesired,
_In_ UINT Flags
)
{
UNIMPLEMENTED;
return 0;
}
HICON WINAPI CreateIcon(
_In_opt_ HINSTANCE hInstance,
_In_ int nWidth,
_In_ int nHeight,
_In_ BYTE cPlanes,
_In_ BYTE cBitsPixel,
_In_ const BYTE *lpbANDbits,
_In_ const BYTE *lpbXORbits
)
{
UNIMPLEMENTED;
return NULL;
}
HICON WINAPI CreateIconFromResource(
_In_ PBYTE presbits,
_In_ DWORD dwResSize,
_In_ BOOL fIcon,
_In_ DWORD dwVer
)
{
return CreateIconFromResourceEx( presbits, dwResSize, fIcon, dwVer, 0,0,0);
}
HICON WINAPI CreateIconFromResourceEx(
_In_ PBYTE pbIconBits,
_In_ DWORD cbIconBits,
_In_ BOOL fIcon,
_In_ DWORD dwVersion,
_In_ int cxDesired,
_In_ int cyDesired,
_In_ UINT uFlags
)
{
UNIMPLEMENTED;
return NULL;
}
HICON WINAPI CreateIconIndirect(
_In_ PICONINFO piconinfo
)
{
UNIMPLEMENTED;
return NULL;
}
HCURSOR WINAPI CreateCursor(
_In_opt_ HINSTANCE hInst,
_In_ int xHotSpot,
_In_ int yHotSpot,
_In_ int nWidth,
_In_ int nHeight,
_In_ const VOID *pvANDPlane,
_In_ const VOID *pvXORPlane
)
{
UNIMPLEMENTED;
return NULL;
}
BOOL WINAPI SetSystemCursor(
_In_ HCURSOR hcur,
_In_ DWORD id
)
{
UNIMPLEMENTED;
return FALSE;
}
BOOL WINAPI SetCursorPos(
_In_ int X,
_In_ int Y
)
{
UNIMPLEMENTED;
return FALSE;
}
BOOL WINAPI GetCursorPos(
_Out_ LPPOINT lpPoint
)
{
UNIMPLEMENTED;
return FALSE;
}
int WINAPI ShowCursor(
_In_ BOOL bShow
)
{
UNIMPLEMENTED;
return -1;
}
HCURSOR WINAPI GetCursor(void)
{
UNIMPLEMENTED;
return NULL;
}
BOOL WINAPI DestroyCursor(
_In_ HCURSOR hCursor
)
{
UNIMPLEMENTED;
return FALSE;
}