From: Amine Khaldi Date: Sat, 26 Mar 2011 13:00:21 +0000 (+0000) Subject: [CMAKE] X-Git-Tag: backups/GSoC_2011/GSoC_Network@51549~46 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=785bea480a6845014874b3e9a8f071c00744748f [CMAKE] - Sync with trunk r51050. svn path=/branches/cmake-bringup/; revision=51154 --- 785bea480a6845014874b3e9a8f071c00744748f diff --cc base/applications/cmdutils/xcopy/Es.rc index 00000000000,67c9eb8ba04..67c9eb8ba04 mode 000000,100644..100644 --- a/base/applications/cmdutils/xcopy/Es.rc +++ b/base/applications/cmdutils/xcopy/Es.rc diff --cc base/applications/network/ping/lang/uk-UA.rc index 00000000000,eb0523a771f..eb0523a771f mode 000000,100644..100644 --- a/base/applications/network/ping/lang/uk-UA.rc +++ b/base/applications/network/ping/lang/uk-UA.rc diff --cc base/applications/rapps/lang/fr-FR.rc index 00000000000,e4d526e6142..e4d526e6142 mode 000000,100644..100644 --- a/base/applications/rapps/lang/fr-FR.rc +++ b/base/applications/rapps/lang/fr-FR.rc diff --cc base/applications/rapps/rapps/mirc6.txt index 00000000000,1debcaa7e62..1debcaa7e62 mode 000000,100644..100644 --- a/base/applications/rapps/rapps/mirc6.txt +++ b/base/applications/rapps/rapps/mirc6.txt diff --cc base/applications/rapps/rapps/sumatrapdf.txt index 00000000000,abb9bc6926e..abb9bc6926e mode 000000,100644..100644 --- a/base/applications/rapps/rapps/sumatrapdf.txt +++ b/base/applications/rapps/rapps/sumatrapdf.txt diff --cc base/applications/rapps/rsrc.rc index 4be23905aea,00000000000..c1bdae757b1 mode 100644,000000..100644 --- a/base/applications/rapps/rsrc.rc +++ b/base/applications/rapps/rsrc.rc @@@ -1,12 -1,0 +1,13 @@@ +#include "lang/bg-BG.rc" +#include "lang/cs-CZ.rc" +#include "lang/de-DE.rc" +#include "lang/en-US.rc" +#include "lang/es-ES.rc" ++#include "lang/fr-FR.rc" +#include "lang/it-IT.rc" +//#include "lang/ja-JP.rc" FIXME: iconv issue +#include "lang/no-NO.rc" +#include "lang/pl-PL.rc" +#include "lang/ru-RU.rc" +#include "lang/sk-SK.rc" +#include "lang/uk-UA.rc" diff --cc base/system/runonce/lang/fr-FR.rc index 00000000000,8c5d3bb443e..8c5d3bb443e mode 000000,100644..100644 --- a/base/system/runonce/lang/fr-FR.rc +++ b/base/system/runonce/lang/fr-FR.rc diff --cc boot/bootdata/hivedef_i386.inf index aeb59c43efb,b49f1ba038d..b49f1ba038d Binary files differ diff --cc boot/freeldr/freeldr/debug.c index 08f49bdf515,00000000000..daabc6715f3 mode 100644,000000..100644 --- a/boot/freeldr/freeldr/debug.c +++ b/boot/freeldr/freeldr/debug.c @@@ -1,373 -1,0 +1,360 @@@ +/* + * FreeLoader + * Copyright (C) 1998-2003 Brian Palmer + * + * 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. + */ + +#include + +#include + +#if DBG && !defined(_M_ARM) + +//#define DEBUG_ALL +//#define DEBUG_INIFILE +//#define DEBUG_REACTOS +//#define DEBUG_CUSTOM +#define DEBUG_NONE + +#if defined (DEBUG_ALL) +ULONG DebugPrintMask = DPRINT_WARNING | DPRINT_MEMORY | DPRINT_FILESYSTEM | + DPRINT_UI | DPRINT_DISK | DPRINT_CACHE | DPRINT_REACTOS | + DPRINT_LINUX | DPRINT_HWDETECT; +#elif defined (DEBUG_INIFILE) +ULONG DebugPrintMask = DPRINT_INIFILE; +#elif defined (DEBUG_REACTOS) +ULONG DebugPrintMask = DPRINT_REACTOS | DPRINT_REGISTRY; +#elif defined (DEBUG_CUSTOM) +ULONG DebugPrintMask = DPRINT_WARNING | + DPRINT_UI | DPRINT_CACHE | DPRINT_REACTOS | + DPRINT_LINUX; +#else //#elif defined (DEBUG_NONE) +ULONG DebugPrintMask = 0; +#endif + +#define SCREEN 1 +#define RS232 2 +#define BOCHS 4 + +#define COM1 1 +#define COM2 2 +#define COM3 3 +#define COM4 4 + +#define BOCHS_OUTPUT_PORT 0xe9 + +ULONG DebugPort = RS232; +//ULONG DebugPort = SCREEN; +//ULONG DebugPort = BOCHS; +//ULONG DebugPort = SCREEN|BOCHS; +ULONG ComPort = COM1; +//ULONG BaudRate = 19200; +ULONG BaudRate = 115200; + +BOOLEAN DebugStartOfLine = TRUE; + - // We need to emulate these, because the original ones don't work in freeldr - int __cdecl wctomb(char *mbchar, wchar_t wchar) - { - *mbchar = wchar; - return 1; - } - - int __cdecl mbtowc (wchar_t *wchar, const char *mbchar, size_t count) - { - *wchar = *mbchar; - return 1; - } - +VOID DebugInit(VOID) +{ + if (DebugPort & RS232) + { + Rs232PortInitialize(ComPort, BaudRate); + } +} + +VOID DebugPrintChar(UCHAR Character) +{ + if (Character == '\n') + { + DebugStartOfLine = TRUE; + } + + if (DebugPort & RS232) + { + if (Character == '\n') + { + Rs232PortPutByte('\r'); + } + Rs232PortPutByte(Character); + } + if (DebugPort & BOCHS) + { + WRITE_PORT_UCHAR((PUCHAR)BOCHS_OUTPUT_PORT, Character); + } + if (DebugPort & SCREEN) + { + MachConsPutChar(Character); + } +} + +ULONG +DbgPrint(const char *Format, ...) +{ + int i; + int Length; + va_list ap; + CHAR Buffer[512]; + + va_start(ap, Format); + Length = _vsnprintf(Buffer, sizeof(Buffer), Format, ap); + va_end(ap); + + /* Check if we went past the buffer */ + if (Length == -1) + { + /* Terminate it if we went over-board */ + Buffer[sizeof(Buffer) - 1] = '\n'; + + /* Put maximum */ + Length = sizeof(Buffer); + } + + for (i = 0; i < Length; i++) + { + DebugPrintChar(Buffer[i]); + } + + return 0; +} + +VOID DebugPrintHeader(ULONG Mask) +{ + /* No header */ + if (Mask == 0) + return; + + switch (Mask) + { + case DPRINT_WARNING: + DbgPrint("WARNING: "); + break; + case DPRINT_MEMORY: + DbgPrint("MEMORY: "); + break; + case DPRINT_FILESYSTEM: + DbgPrint("FILESYS: "); + break; + case DPRINT_INIFILE: + DbgPrint("INIFILE: "); + break; + case DPRINT_UI: + DbgPrint("UI: "); + break; + case DPRINT_DISK: + DbgPrint("DISK: "); + break; + case DPRINT_CACHE: + DbgPrint("CACHE: "); + break; + case DPRINT_REGISTRY: + DbgPrint("REGISTRY: "); + break; + case DPRINT_REACTOS: + DbgPrint("REACTOS: "); + break; + case DPRINT_LINUX: + DbgPrint("LINUX: "); + break; + case DPRINT_WINDOWS: + DbgPrint("WINLDR: "); + break; + case DPRINT_HWDETECT: + DbgPrint("HWDETECT: "); + break; + case DPRINT_PELOADER: + DbgPrint("PELOADER: "); + break; + case DPRINT_SCSIPORT: + DbgPrint("SCSIPORT: "); + break; + default: + DbgPrint("UNKNOWN: "); + break; + } +} + +char* g_file; +int g_line; + +VOID DbgPrintMask(ULONG Mask, char *format, ...) +{ + va_list ap; + char Buffer[2096]; + char *ptr = Buffer; + + // Mask out unwanted debug messages + if (!(Mask & DebugPrintMask)) + { + return; + } + + // Disable file/line for scsiport messages + if (Mask & DPRINT_SCSIPORT) + { + DebugStartOfLine = FALSE; + } + + // Print the header if we have started a new line + if (DebugStartOfLine) + { + DbgPrint("(%s:%d) ", g_file, g_line); + DebugPrintHeader(Mask); + DebugStartOfLine = FALSE; + } + + va_start(ap, format); + vsprintf(Buffer, format, ap); + va_end(ap); + + while (*ptr) + { + DebugPrintChar(*ptr++); + } +} + +VOID DebugDumpBuffer(ULONG Mask, PVOID Buffer, ULONG Length) +{ + PUCHAR BufPtr = (PUCHAR)Buffer; + ULONG Idx; + ULONG Idx2; + + // Mask out unwanted debug messages + if (!(Mask & DebugPrintMask)) + { + return; + } + + DebugStartOfLine = FALSE; // We don't want line headers + DbgPrintMask(Mask, "Dumping buffer at 0x%x with length of %d bytes:\n", Buffer, Length); + + for (Idx=0; Idx 20) && (BufPtr[Idx] < 0x80)) + { + DbgPrintMask(Mask, "%c", BufPtr[Idx]); + } + else + { + DbgPrintMask(Mask, "."); + } + } + + DbgPrintMask(Mask, "\n"); + } +} + +#else + +VOID DbgPrintMask(ULONG Mask, char *format, ...) +{ +} + +ULONG DbgPrint(PCCH Format, ...) +{ + return 0; +} + +#endif // DBG + +ULONG +MsgBoxPrint(const char *Format, ...) +{ + va_list ap; + CHAR Buffer[512]; + ULONG Length; + + va_start(ap, Format); + + /* Construct a string */ + Length = _vsnprintf(Buffer, 512, Format, ap); + + /* Check if we went past the buffer */ + if (Length == MAXULONG) + { + /* Terminate it if we went over-board */ + Buffer[sizeof(Buffer) - 1] = '\n'; + + /* Put maximum */ + Length = sizeof(Buffer); + } + + /* Show it as a message box */ + UiMessageBox(Buffer); + + /* Cleanup and exit */ + va_end(ap); + return 0; +} + +NTKERNELAPI +VOID +NTAPI +KeBugCheckEx( + IN ULONG BugCheckCode, + IN ULONG_PTR BugCheckParameter1, + IN ULONG_PTR BugCheckParameter2, + IN ULONG_PTR BugCheckParameter3, + IN ULONG_PTR BugCheckParameter4) +{ + char Buffer[70]; + sprintf(Buffer, "*** STOP: 0x%08lX (0x%08lX, 0x%08lX, 0x%08lX, 0x%08lX)", + BugCheckCode, BugCheckParameter1, BugCheckParameter2, + BugCheckParameter3, BugCheckParameter4); + UiMessageBoxCritical(Buffer); + assert(FALSE); + for (;;); +} diff --cc boot/freeldr/freeldr/freeldr.c index 077f2bb6686,00000000000..98af295c4c7 mode 100644,000000..100644 --- a/boot/freeldr/freeldr/freeldr.c +++ b/boot/freeldr/freeldr/freeldr.c @@@ -1,66 -1,0 +1,79 @@@ +/* + * FreeLoader + * Copyright (C) 1998-2003 Brian Palmer + * + * 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. + */ + +#include +#include + +VOID NTAPI HalpInitializePciStubs(VOID); +VOID NTAPI HalpInitBusHandler(VOID); + +VOID BootMain(LPSTR CmdLine) +{ + CmdLineParse(CmdLine); + + MachInit(CmdLine); + + FsInit(); + + DebugInit(); + + DPRINTM(DPRINT_WARNING, "BootMain() called.\n"); + + if (!UiInitialize(FALSE)) + { + UiMessageBoxCritical("Unable to initialize UI.\n"); + return; + } + + if (!MmInitializeMemoryManager()) + { + UiMessageBoxCritical("Unable to initialize memory manager"); + return; + } + +#ifdef _M_IX86 + HalpInitializePciStubs(); + HalpInitBusHandler(); +#endif + RunLoader(); +} + +#ifdef _MSC_VER +long _ftol2(double f) +{ + return _ftol(f); +} +long _ftol2_sse(double f) +{ + return _ftol(f); +} +#endif ++ ++// We need to emulate these, because the original ones don't work in freeldr ++int __cdecl wctomb(char *mbchar, wchar_t wchar) ++{ ++ *mbchar = wchar; ++ return 1; ++} ++ ++int __cdecl mbtowc (wchar_t *wchar, const char *mbchar, size_t count) ++{ ++ *wchar = *mbchar; ++ return 1; ++} diff --cc dll/cpl/console/lang/fr-Fr.rc index 00000000000,3cc34122141..3cc34122141 mode 000000,100644..100644 --- a/dll/cpl/console/lang/fr-Fr.rc +++ b/dll/cpl/console/lang/fr-Fr.rc diff --cc dll/cpl/usrmgr/lang/fr-FR.rc index 00000000000,d98b04dd671..d98b04dd671 mode 000000,100644..100644 --- a/dll/cpl/usrmgr/lang/fr-FR.rc +++ b/dll/cpl/usrmgr/lang/fr-FR.rc diff --cc dll/ntdll/CMakeLists.txt index d57e5bbd930,00000000000..aab01f16052 mode 100644,000000..100644 --- a/dll/ntdll/CMakeLists.txt +++ b/dll/ntdll/CMakeLists.txt @@@ -1,59 -1,0 +1,60 @@@ + +spec2def(ntdll.dll def/ntdll.spec) + +add_definitions( + -D__NTDLL__ + -D_NTOSKRNL_ + -DCRTDLL) + +include_directories( + BEFORE include + ${REACTOS_SOURCE_DIR}/include/reactos/subsys) + +list(APPEND SOURCE + csr/api.c + csr/capture.c + csr/connect.c + dbg/dbgui.c ++ ldr/actctx.c ++ ldr/ldrinit.c + ldr/startup.c + ldr/utils.c - ldr/actctx.c + rtl/libsupp.c + rtl/version.c + def/ntdll.rc + ${CMAKE_CURRENT_BINARY_DIR}/ntdll.def) + +if(ARCH MATCHES i386) +list(APPEND SOURCE dispatch/i386/dispatch.S) +elseif(ARCH MATCHES amd64) +list(APPEND SOURCE dispatch/amd64/stubs.c) +elseif(ARCH MATCHES arm) +list(APPEND SOURCE dispatch/arm/stubs_asm.s) +else() +list(APPEND SOURCE dispatch/dispatch.c) +endif(ARCH MATCHES i386) + +add_library(ntdll SHARED + ${CMAKE_CURRENT_BINARY_DIR}/ntdll_ntdll.h.gch + ${SOURCE}) + +set_entrypoint(ntdll 0) + +if(MSVC) +target_link_libraries(ntdll rtl) +else() +target_link_libraries(ntdll -Wl,--whole-archive rtl -Wl,--no-whole-archive) +endif() + +target_link_libraries(ntdll + ntdllsys + libcntpr + ${PSEH_LIB}) + +set_image_base(ntdll ${baseaddress_ntdll}) +add_pch(ntdll ${CMAKE_CURRENT_SOURCE_DIR}/include/ntdll.h ${SOURCE}) +add_dependencies(ntdll ntstatus asm) + +add_minicd_target(ntdll reactos/system32 ntdll.dll) +add_cab_target(ntdll 1) +add_importlib_target(def/ntdll.spec) diff --cc dll/ntdll/ldr/ldrinit.c index 00000000000,77baa0a5ed8..77baa0a5ed8 mode 000000,100644..100644 --- a/dll/ntdll/ldr/ldrinit.c +++ b/dll/ntdll/ldr/ldrinit.c diff --cc dll/win32/comctl32/comctl_Eo.rc index 00000000000,5d627aa2f3a..5d627aa2f3a mode 000000,100644..100644 --- a/dll/win32/comctl32/comctl_Eo.rc +++ b/dll/win32/comctl32/comctl_Eo.rc diff --cc dll/win32/comctl32/idb_hist_large.bmp index b7818fbafb2,c6aee0bb37a..c6aee0bb37a Binary files differ diff --cc dll/win32/comctl32/idb_hist_small.bmp index c735f54377f,2ae50010edb..2ae50010edb Binary files differ diff --cc dll/win32/comctl32/idb_std_large.bmp index 7e19185c929,c10dc72da1b..c10dc72da1b Binary files differ diff --cc dll/win32/comctl32/idb_std_small.bmp index 7db2f3ca805,aedd4a861cf..aedd4a861cf Binary files differ diff --cc dll/win32/comctl32/idb_view_large.bmp index 22e4d1d8b8b,ce4ea4f4c1b..ce4ea4f4c1b Binary files differ diff --cc dll/win32/comctl32/idb_view_small.bmp index 6ba3d831637,abee9b8063d..abee9b8063d Binary files differ diff --cc dll/win32/comctl32/monthcal.c index 3eb2c32b101,00000000000..2091d8875fb mode 100644,000000..100644 --- a/dll/win32/comctl32/monthcal.c +++ b/dll/win32/comctl32/monthcal.c @@@ -1,2749 -1,0 +1,2785 @@@ +/* + * Month calendar control + * + * Copyright 1998, 1999 Eric Kohl (ekohl@abo.rhein-zeitung.de) + * Copyright 1999 Alex Priem (alexp@sci.kun.nl) + * Copyright 1999 Chris Morgan and + * James Abbatiello + * Copyright 2000 Uwe Bonnes + * Copyright 2009, 2010 Nikolay Sivov + * + * 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 + * + * NOTE + * + * This code was audited for completeness against the documented features + * of Comctl32.dll version 6.0 on Oct. 20, 2004, by Dimitrie O. Paun. + * + * Unless otherwise noted, we believe this code to be complete, as per + * the specification mentioned above. + * If you discover missing features, or bugs, please note them below. + * + * TODO: + * -- MCM_[GS]ETUNICODEFORMAT + * -- MONTHCAL_GetMonthRange + * -- handle resources better (doesn't work now); + * -- take care of internationalization. + * -- keyboard handling. + * -- search for FIXME + */ + +#include +#include +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winuser.h" +#include "winnls.h" +#include "commctrl.h" +#include "comctl32.h" +#include "uxtheme.h" +#include "tmschema.h" +#include "wine/unicode.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(monthcal); + +#define MC_SEL_LBUTUP 1 /* Left button released */ +#define MC_SEL_LBUTDOWN 2 /* Left button pressed in calendar */ +#define MC_PREVPRESSED 4 /* Prev month button pressed */ +#define MC_NEXTPRESSED 8 /* Next month button pressed */ +#define MC_PREVNEXTMONTHDELAY 350 /* when continuously pressing `next/prev + month', wait 350 ms before going + to the next/prev month */ +#define MC_TODAYUPDATEDELAY 120000 /* time between today check for update (2 min) */ + +#define MC_PREVNEXTMONTHTIMER 1 /* Timer ID's */ +#define MC_TODAYUPDATETIMER 2 + +#define countof(arr) (sizeof(arr)/sizeof(arr[0])) + +/* convert from days to 100 nanoseconds unit - used as FILETIME unit */ +#define DAYSTO100NSECS(days) (((ULONGLONG)(days))*24*60*60*10000000) + +/* single calendar data */ +typedef struct _CALENDAR_INFO +{ + RECT title; /* rect for the header above the calendar */ + RECT titlemonth; /* the 'month name' text in the header */ + RECT titleyear; /* the 'year number' text in the header */ + RECT wdays; /* week days at top */ + RECT days; /* calendar area */ + RECT weeknums; /* week numbers at left side */ + + SYSTEMTIME month;/* contains calendar main month/year */ +} CALENDAR_INFO; + +typedef struct +{ + HWND hwndSelf; + DWORD dwStyle; /* cached GWL_STYLE */ - COLORREF bk; - COLORREF txt; - COLORREF titlebk; - COLORREF titletxt; - COLORREF monthbk; - COLORREF trailingtxt; ++ ++ COLORREF colors[MCSC_TRAILINGTEXT+1]; ++ + HFONT hFont; + HFONT hBoldFont; + int textHeight; + int textWidth; + int height_increment; + int width_increment; + INT delta; /* scroll rate; # of months that the */ + /* control moves when user clicks a scroll button */ + int visible; /* # of months visible */ + int firstDay; /* Start month calendar with firstDay's day, + stored in SYSTEMTIME format */ + BOOL firstDaySet; /* first week day differs from locale defined */ + + BOOL isUnicode; /* value set with MCM_SETUNICODE format */ + + int monthRange; + MONTHDAYSTATE *monthdayState; + SYSTEMTIME todaysDate; + BOOL todaySet; /* Today was forced with MCM_SETTODAY */ + int status; /* See MC_SEL flags */ + SYSTEMTIME firstSel; /* first selected day */ + INT maxSelCount; - SYSTEMTIME minSel; ++ SYSTEMTIME minSel; /* contains single selection when used without MCS_MULTISELECT */ + SYSTEMTIME maxSel; - SYSTEMTIME curSel; /* contains currently selected year, month and day */ + SYSTEMTIME focusedSel; /* date currently focused with mouse movement */ + DWORD rangeValid; + SYSTEMTIME minDate; + SYSTEMTIME maxDate; + + RECT titlebtnnext; /* the `next month' button in the header */ + RECT titlebtnprev; /* the `prev month' button in the header */ + RECT todayrect; /* `today: xx/xx/xx' text rect */ + HWND hwndNotify; /* Window to receive the notifications */ + HWND hWndYearEdit; /* Window Handle of edit box to handle years */ + HWND hWndYearUpDown;/* Window Handle of updown box to handle years */ + WNDPROC EditWndProc; /* original Edit window procedure */ + + CALENDAR_INFO *calendars; + INT cal_num; +} MONTHCAL_INFO, *LPMONTHCAL_INFO; + +static const WCHAR themeClass[] = { 'S','c','r','o','l','l','b','a','r',0 }; + +/* empty SYSTEMTIME const */ +static const SYSTEMTIME st_null; +/* valid date limits */ +static const SYSTEMTIME max_allowed_date = { 9999, 12, 0, 31, 0, 0, 0, 0 }; +static const SYSTEMTIME min_allowed_date = { 1752, 9, 0, 14, 0, 0, 0, 0 }; + - - #define MONTHCAL_GetInfoPtr(hwnd) ((MONTHCAL_INFO *)GetWindowLongPtrW(hwnd, 0)) ++/* Prev/Next buttons */ ++enum nav_direction ++{ ++ DIRECTION_BACKWARD, ++ DIRECTION_FORWARD ++}; + +/* helper functions */ + +/* send a single MCN_SELCHANGE notification */ +static inline void MONTHCAL_NotifySelectionChange(const MONTHCAL_INFO *infoPtr) +{ + NMSELCHANGE nmsc; + + nmsc.nmhdr.hwndFrom = infoPtr->hwndSelf; + nmsc.nmhdr.idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID); + nmsc.nmhdr.code = MCN_SELCHANGE; + nmsc.stSelStart = infoPtr->minSel; + nmsc.stSelEnd = infoPtr->maxSel; + SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, nmsc.nmhdr.idFrom, (LPARAM)&nmsc); +} + +/* send a single MCN_SELECT notification */ +static inline void MONTHCAL_NotifySelect(const MONTHCAL_INFO *infoPtr) +{ + NMSELCHANGE nmsc; + + nmsc.nmhdr.hwndFrom = infoPtr->hwndSelf; + nmsc.nmhdr.idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID); + nmsc.nmhdr.code = MCN_SELECT; + nmsc.stSelStart = infoPtr->minSel; + nmsc.stSelEnd = infoPtr->maxSel; + + SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, nmsc.nmhdr.idFrom, (LPARAM)&nmsc); +} + +/* returns the number of days in any given month, checking for leap days */ +/* january is 1, december is 12 */ +int MONTHCAL_MonthLength(int month, int year) +{ + const int mdays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + /* Wrap around, this eases handling. Getting length only we shouldn't care + about year change here cause January and December have + the same day quantity */ + if(month == 0) + month = 12; + else if(month == 13) + month = 1; + + /* special case for calendar transition year */ + if(month == min_allowed_date.wMonth && year == min_allowed_date.wYear) return 19; + + /* if we have a leap year add 1 day to February */ + /* a leap year is a year either divisible by 400 */ + /* or divisible by 4 and not by 100 */ + if(month == 2) { /* February */ + return mdays[month - 1] + ((year%400 == 0) ? 1 : ((year%100 != 0) && + (year%4 == 0)) ? 1 : 0); + } + else { + return mdays[month - 1]; + } +} + +/* compares timestamps using date part only */ +static inline BOOL MONTHCAL_IsDateEqual(const SYSTEMTIME *first, const SYSTEMTIME *second) +{ + return (first->wYear == second->wYear) && (first->wMonth == second->wMonth) && + (first->wDay == second->wDay); +} + +/* make sure that date fields are valid */ +static BOOL MONTHCAL_ValidateDate(const SYSTEMTIME *time) +{ + if(time->wMonth < 1 || time->wMonth > 12 ) return FALSE; + if(time->wDayOfWeek > 6) return FALSE; + if(time->wDay > MONTHCAL_MonthLength(time->wMonth, time->wYear)) + return FALSE; + + return TRUE; +} + +/* Copies timestamp part only. + * + * PARAMETERS + * + * [I] from : source date + * [O] to : dest date + */ +static void MONTHCAL_CopyTime(const SYSTEMTIME *from, SYSTEMTIME *to) +{ + to->wHour = from->wHour; + to->wMinute = from->wMinute; + to->wSecond = from->wSecond; +} + +/* Copies date part only. + * + * PARAMETERS + * + * [I] from : source date + * [O] to : dest date + */ +static void MONTHCAL_CopyDate(const SYSTEMTIME *from, SYSTEMTIME *to) +{ + to->wYear = from->wYear; + to->wMonth = from->wMonth; + to->wDay = from->wDay; + to->wDayOfWeek = from->wDayOfWeek; +} + +/* Compares two dates in SYSTEMTIME format + * + * PARAMETERS + * + * [I] first : pointer to valid first date data to compare + * [I] second : pointer to valid second date data to compare + * + * RETURN VALUE + * + * -1 : first < second + * 0 : first == second + * 1 : first > second + * + * Note that no date validation performed, alreadt validated values expected. + */ +static LONG MONTHCAL_CompareSystemTime(const SYSTEMTIME *first, const SYSTEMTIME *second) +{ + FILETIME ft_first, ft_second; + + SystemTimeToFileTime(first, &ft_first); + SystemTimeToFileTime(second, &ft_second); + + return CompareFileTime(&ft_first, &ft_second); +} + +static LONG MONTHCAL_CompareMonths(const SYSTEMTIME *first, const SYSTEMTIME *second) +{ + SYSTEMTIME st_first, st_second; + + st_first = st_second = st_null; + MONTHCAL_CopyDate(first, &st_first); + MONTHCAL_CopyDate(second, &st_second); + st_first.wDay = st_second.wDay = 1; + + return MONTHCAL_CompareSystemTime(&st_first, &st_second); +} + +static LONG MONTHCAL_CompareDate(const SYSTEMTIME *first, const SYSTEMTIME *second) +{ + SYSTEMTIME st_first, st_second; + + st_first = st_second = st_null; + MONTHCAL_CopyDate(first, &st_first); + MONTHCAL_CopyDate(second, &st_second); + + return MONTHCAL_CompareSystemTime(&st_first, &st_second); +} + +/* Checks largest possible date range and configured one + * + * PARAMETERS + * + * [I] infoPtr : valid pointer to control data + * [I] date : pointer to valid date data to check + * [I] fix : make date fit valid range + * + * RETURN VALUE + * + * TRUE - date whithin largest and configured range + * FALSE - date is outside largest or configured range + */ +static BOOL MONTHCAL_IsDateInValidRange(const MONTHCAL_INFO *infoPtr, + SYSTEMTIME *date, BOOL fix) +{ + const SYSTEMTIME *fix_st = NULL; + + if(MONTHCAL_CompareSystemTime(date, &max_allowed_date) == 1) { + fix_st = &max_allowed_date; + } + else if(MONTHCAL_CompareSystemTime(date, &min_allowed_date) == -1) { + fix_st = &min_allowed_date; + } + else if(infoPtr->rangeValid & GDTR_MAX) { + if((MONTHCAL_CompareSystemTime(date, &infoPtr->maxDate) == 1)) { + fix_st = &infoPtr->maxDate; + } + } + else if(infoPtr->rangeValid & GDTR_MIN) { + if((MONTHCAL_CompareSystemTime(date, &infoPtr->minDate) == -1)) { + fix_st = &infoPtr->minDate; + } + } + + if (fix && fix_st) { + date->wYear = fix_st->wYear; + date->wMonth = fix_st->wMonth; + } + + return fix_st ? FALSE : TRUE; +} + +/* Checks passed range width with configured maximum selection count + * + * PARAMETERS + * + * [I] infoPtr : valid pointer to control data + * [I] range0 : pointer to valid date data (requested bound) + * [I] range1 : pointer to valid date data (primary bound) + * [O] adjust : returns adjusted range bound to fit maximum range (optional) + * + * Adjust value computed basing on primary bound and current maximum selection + * count. For simple range check (without adjusted value required) (range0, range1) + * relation means nothing. + * + * RETURN VALUE + * + * TRUE - range is shorter or equal to maximum + * FALSE - range is larger than maximum + */ +static BOOL MONTHCAL_IsSelRangeValid(const MONTHCAL_INFO *infoPtr, + const SYSTEMTIME *range0, + const SYSTEMTIME *range1, + SYSTEMTIME *adjust) +{ + ULARGE_INTEGER ul_range0, ul_range1, ul_diff; + FILETIME ft_range0, ft_range1; + LONG cmp; + + SystemTimeToFileTime(range0, &ft_range0); + SystemTimeToFileTime(range1, &ft_range1); + + ul_range0.u.LowPart = ft_range0.dwLowDateTime; + ul_range0.u.HighPart = ft_range0.dwHighDateTime; + ul_range1.u.LowPart = ft_range1.dwLowDateTime; + ul_range1.u.HighPart = ft_range1.dwHighDateTime; + + cmp = CompareFileTime(&ft_range0, &ft_range1); + + if(cmp == 1) + ul_diff.QuadPart = ul_range0.QuadPart - ul_range1.QuadPart; + else + ul_diff.QuadPart = -ul_range0.QuadPart + ul_range1.QuadPart; + + if(ul_diff.QuadPart >= DAYSTO100NSECS(infoPtr->maxSelCount)) { + + if(adjust) { + if(cmp == 1) + ul_range0.QuadPart = ul_range1.QuadPart + DAYSTO100NSECS(infoPtr->maxSelCount - 1); + else + ul_range0.QuadPart = ul_range1.QuadPart - DAYSTO100NSECS(infoPtr->maxSelCount - 1); + + ft_range0.dwLowDateTime = ul_range0.u.LowPart; + ft_range0.dwHighDateTime = ul_range0.u.HighPart; + FileTimeToSystemTime(&ft_range0, adjust); + } + + return FALSE; + } + else return TRUE; +} + +/* Used in MCM_SETRANGE/MCM_SETSELRANGE to determine resulting time part. + Milliseconds are intentionally not validated. */ +static BOOL MONTHCAL_ValidateTime(const SYSTEMTIME *time) +{ + if((time->wHour > 24) || (time->wMinute > 59) || (time->wSecond > 59)) + return FALSE; + else + return TRUE; +} + +/* Note:Depending on DST, this may be offset by a day. + Need to find out if we're on a DST place & adjust the clock accordingly. + Above function assumes we have a valid data. + Valid for year>1752; 1 <= d <= 31, 1 <= m <= 12. + 0 = Sunday. +*/ + +/* Returns the day in the week + * + * PARAMETERS + * [i] date : input date + * [I] inplace : set calculated value back to date structure + * + * RETURN VALUE + * day of week in SYSTEMTIME format: (0 == sunday,..., 6 == saturday) + */ +int MONTHCAL_CalculateDayOfWeek(SYSTEMTIME *date, BOOL inplace) +{ + SYSTEMTIME st = st_null; + FILETIME ft; + + MONTHCAL_CopyDate(date, &st); + + SystemTimeToFileTime(&st, &ft); + FileTimeToSystemTime(&ft, &st); + + if (inplace) date->wDayOfWeek = st.wDayOfWeek; + + return st.wDayOfWeek; +} + ++/* add/substract 'months' from date */ ++static inline void MONTHCAL_GetMonth(SYSTEMTIME *date, INT months) ++{ ++ INT length, m = date->wMonth + months; ++ ++ date->wYear += m > 0 ? (m - 1) / 12 : m / 12 - 1; ++ date->wMonth = m > 0 ? (m - 1) % 12 + 1 : 12 + m % 12; ++ /* fix moving from last day in a month */ ++ length = MONTHCAL_MonthLength(date->wMonth, date->wYear); ++ if(date->wDay > length) date->wDay = length; ++ MONTHCAL_CalculateDayOfWeek(date, TRUE); ++} ++ +/* properly updates date to point on next month */ +static inline void MONTHCAL_GetNextMonth(SYSTEMTIME *date) +{ - if(++date->wMonth > 12) - { - date->wMonth = 1; - date->wYear++; - } - MONTHCAL_CalculateDayOfWeek(date, TRUE); ++ return MONTHCAL_GetMonth(date, 1); +} + +/* properly updates date to point on prev month */ +static inline void MONTHCAL_GetPrevMonth(SYSTEMTIME *date) +{ - if(--date->wMonth < 1) - { - date->wMonth = 12; - date->wYear--; - } - MONTHCAL_CalculateDayOfWeek(date, TRUE); ++ return MONTHCAL_GetMonth(date, -1); +} + +/* Returns full date for a first currently visible day */ +static void MONTHCAL_GetMinDate(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *date) +{ + /* zero indexed calendar has the earliest date */ + SYSTEMTIME st_first = infoPtr->calendars[0].month; + INT firstDay; + + st_first.wDay = 1; + firstDay = MONTHCAL_CalculateDayOfWeek(&st_first, FALSE); + + *date = infoPtr->calendars[0].month; + MONTHCAL_GetPrevMonth(date); + + date->wDay = MONTHCAL_MonthLength(date->wMonth, date->wYear) + + (infoPtr->firstDay - firstDay) % 7 + 1; + + if(date->wDay > MONTHCAL_MonthLength(date->wMonth, date->wYear)) + date->wDay -= 7; + + /* fix day of week */ + MONTHCAL_CalculateDayOfWeek(date, TRUE); +} + +/* Returns full date for a last currently visible day */ +static void MONTHCAL_GetMaxDate(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *date) +{ + /* the latest date is in latest calendar */ + SYSTEMTIME st, lt_month = infoPtr->calendars[infoPtr->cal_num-1].month; + + *date = lt_month; + MONTHCAL_GetNextMonth(date); + + MONTHCAL_GetMinDate(infoPtr, &st); + /* Use month length to get max day. 42 means max day count in calendar area */ + date->wDay = 42 - (MONTHCAL_MonthLength(st.wMonth, st.wYear) - st.wDay + 1) - + MONTHCAL_MonthLength(lt_month.wMonth, lt_month.wYear); + + /* fix day of week */ + MONTHCAL_CalculateDayOfWeek(date, TRUE); +} + +/* From a given point, calculate the row (weekpos), column(daypos) + and day in the calendar. day== 0 mean the last day of tha last month +*/ +static int MONTHCAL_CalcDayFromPos(const MONTHCAL_INFO *infoPtr, int x, int y, + int *daypos, int *weekpos) +{ + int retval, firstDay; + RECT rcClient; - SYSTEMTIME st = infoPtr->curSel; ++ SYSTEMTIME st = infoPtr->minSel; + + GetClientRect(infoPtr->hwndSelf, &rcClient); + + /* if the point is outside the x bounds of the window put + it at the boundary */ + if (x > rcClient.right) + x = rcClient.right; + + *daypos = (x - infoPtr->calendars[0].days.left ) / infoPtr->width_increment; + *weekpos = (y - infoPtr->calendars[0].days.top ) / infoPtr->height_increment; + + st.wDay = 1; + firstDay = (MONTHCAL_CalculateDayOfWeek(&st, FALSE) + 6 - infoPtr->firstDay) % 7; + retval = *daypos + (7 * *weekpos) - firstDay; + return retval; +} + +/* Sets the RECT struct r to the rectangle around the date + * + * PARAMETERS + * + * [I] infoPtr : pointer to control data + * [I] date : date value + * [O] x : day column (zero based) + * [O] y : week column (zero based) + */ +static void MONTHCAL_CalcDayXY(const MONTHCAL_INFO *infoPtr, - const SYSTEMTIME *date, int *x, int *y) ++ const SYSTEMTIME *date, INT *x, INT *y) +{ - SYSTEMTIME st = infoPtr->curSel; ++ SYSTEMTIME st = infoPtr->minSel; + LONG cmp; + int first; + + st.wDay = 1; + first = (MONTHCAL_CalculateDayOfWeek(&st, FALSE) + 6 - infoPtr->firstDay) % 7; + - cmp = MONTHCAL_CompareMonths(date, &infoPtr->curSel); ++ cmp = MONTHCAL_CompareMonths(date, &infoPtr->minSel); + + /* previous month */ + if(cmp == -1) { - *x = (first - MONTHCAL_MonthLength(date->wMonth, infoPtr->curSel.wYear) + date->wDay) % 7; ++ *x = (first - MONTHCAL_MonthLength(date->wMonth, infoPtr->minSel.wYear) + date->wDay) % 7; + *y = 0; + return; + } + + /* next month calculation is same as for current, + just add current month length */ + if(cmp == 1) { - first += MONTHCAL_MonthLength(infoPtr->curSel.wMonth, infoPtr->curSel.wYear); ++ first += MONTHCAL_MonthLength(infoPtr->minSel.wMonth, infoPtr->minSel.wYear); + } + + *x = (date->wDay + first) % 7; + *y = (date->wDay + first - *x) / 7; +} + + +/* x: column(day), y: row(week) */ +static inline void MONTHCAL_CalcDayRect(const MONTHCAL_INFO *infoPtr, RECT *r, int x, int y) +{ + r->left = infoPtr->calendars[0].days.left + x * infoPtr->width_increment; + r->right = r->left + infoPtr->width_increment; + r->top = infoPtr->calendars[0].days.top + y * infoPtr->height_increment; + r->bottom = r->top + infoPtr->textHeight; +} + + +/* Sets the RECT struct r to the rectangle around the date */ +static inline void MONTHCAL_CalcPosFromDay(const MONTHCAL_INFO *infoPtr, + const SYSTEMTIME *date, RECT *r) +{ + int x, y; + + MONTHCAL_CalcDayXY(infoPtr, date, &x, &y); + MONTHCAL_CalcDayRect(infoPtr, r, x, y); +} + +/* Focused day helper: + + - set focused date to given value; + - reset to zero value if NULL passed; + - invalidate previous and new day rectangle only if needed. + + Returns TRUE if focused day changed, FALSE otherwise. +*/ +static BOOL MONTHCAL_SetDayFocus(MONTHCAL_INFO *infoPtr, const SYSTEMTIME *st) +{ + RECT r; + + if(st) + { + /* there's nothing to do if it's the same date, + mouse move within same date rectangle case */ + if(MONTHCAL_IsDateEqual(&infoPtr->focusedSel, st)) return FALSE; + + /* invalidate old focused day */ + MONTHCAL_CalcPosFromDay(infoPtr, &infoPtr->focusedSel, &r); + InvalidateRect(infoPtr->hwndSelf, &r, FALSE); + + infoPtr->focusedSel = *st; + } + + MONTHCAL_CalcPosFromDay(infoPtr, &infoPtr->focusedSel, &r); + + if(!st && MONTHCAL_ValidateDate(&infoPtr->focusedSel)) + infoPtr->focusedSel = st_null; + + /* on set invalidates new day, on reset clears previous focused day */ + InvalidateRect(infoPtr->hwndSelf, &r, FALSE); + + return TRUE; +} + +/* Draw today day mark rectangle + * + * [I] hdc : context to draw in + * [I] day : day to mark with rectangle + * + */ +static void MONTHCAL_CircleDay(const MONTHCAL_INFO *infoPtr, HDC hdc, + const SYSTEMTIME *date) +{ + HPEN hRedPen = CreatePen(PS_SOLID, 1, RGB(255, 0, 0)); + HPEN hOldPen2 = SelectObject(hdc, hRedPen); + HBRUSH hOldBrush; + RECT day_rect; + + MONTHCAL_CalcPosFromDay(infoPtr, date, &day_rect); + + hOldBrush = SelectObject(hdc, GetStockObject(NULL_BRUSH)); + Rectangle(hdc, day_rect.left, day_rect.top, day_rect.right, day_rect.bottom); + + SelectObject(hdc, hOldBrush); + DeleteObject(hRedPen); + SelectObject(hdc, hOldPen2); +} + +static void MONTHCAL_DrawDay(const MONTHCAL_INFO *infoPtr, HDC hdc, const SYSTEMTIME *st, + int bold, const PAINTSTRUCT *ps) +{ + static const WCHAR fmtW[] = { '%','d',0 }; + WCHAR buf[10]; + RECT r, r_temp; + static BOOL bold_selected; + BOOL selected_day = FALSE; + HBRUSH hbr; + COLORREF oldCol = 0; + COLORREF oldBk = 0; + +/* No need to check styles: when selection is not valid, it is set to zero. + * 1rcPaint), &r)) return; + + if ((MONTHCAL_CompareDate(st, &infoPtr->minSel) >= 0) && + (MONTHCAL_CompareDate(st, &infoPtr->maxSel) <= 0)) { + + TRACE("%d %d %d\n", st->wDay, infoPtr->minSel.wDay, infoPtr->maxSel.wDay); + TRACE("%s\n", wine_dbgstr_rect(&r)); - oldCol = SetTextColor(hdc, infoPtr->monthbk); - oldBk = SetBkColor(hdc, infoPtr->trailingtxt); ++ oldCol = SetTextColor(hdc, infoPtr->colors[MCSC_MONTHBK]); ++ oldBk = SetBkColor(hdc, infoPtr->colors[MCSC_TRAILINGTEXT]); + hbr = GetSysColorBrush(COLOR_HIGHLIGHT); + FillRect(hdc, &r, hbr); + + selected_day = TRUE; + } + + if(bold && !bold_selected) { + SelectObject(hdc, infoPtr->hBoldFont); + bold_selected = TRUE; + } + if(!bold && bold_selected) { + SelectObject(hdc, infoPtr->hFont); + bold_selected = FALSE; + } + + SetBkMode(hdc,TRANSPARENT); + wsprintfW(buf, fmtW, st->wDay); + DrawTextW(hdc, buf, -1, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE ); + + if(selected_day) { + SetTextColor(hdc, oldCol); + SetBkColor(hdc, oldBk); + } +} + + - static void MONTHCAL_PaintButton(MONTHCAL_INFO *infoPtr, HDC hdc, BOOL btnNext) ++static void MONTHCAL_PaintButton(MONTHCAL_INFO *infoPtr, HDC hdc, enum nav_direction button) +{ + HTHEME theme = GetWindowTheme (infoPtr->hwndSelf); - RECT *r = btnNext ? &infoPtr->titlebtnnext : &infoPtr->titlebtnprev; - BOOL pressed = btnNext ? (infoPtr->status & MC_NEXTPRESSED) : - (infoPtr->status & MC_PREVPRESSED); ++ RECT *r = button == DIRECTION_FORWARD ? &infoPtr->titlebtnnext : &infoPtr->titlebtnprev; ++ BOOL pressed = button == DIRECTION_FORWARD ? infoPtr->status & MC_NEXTPRESSED : ++ infoPtr->status & MC_PREVPRESSED; + if (theme) + { + static const int states[] = { + /* Prev button */ + ABS_LEFTNORMAL, ABS_LEFTPRESSED, ABS_LEFTDISABLED, + /* Next button */ + ABS_RIGHTNORMAL, ABS_RIGHTPRESSED, ABS_RIGHTDISABLED + }; - int stateNum = btnNext ? 3 : 0; ++ int stateNum = button == DIRECTION_FORWARD ? 3 : 0; + if (pressed) + stateNum += 1; + else + { + if (infoPtr->dwStyle & WS_DISABLED) stateNum += 2; + } + DrawThemeBackground (theme, hdc, SBP_ARROWBTN, states[stateNum], r, NULL); + } + else + { - int style = btnNext ? DFCS_SCROLLRIGHT : DFCS_SCROLLLEFT; ++ int style = button == DIRECTION_FORWARD ? DFCS_SCROLLRIGHT : DFCS_SCROLLLEFT; + if (pressed) + style |= DFCS_PUSHED; + else + { + if (infoPtr->dwStyle & WS_DISABLED) style |= DFCS_INACTIVE; + } + + DrawFrameControl(hdc, r, DFC_SCROLL, style); + } +} +/* paint a title with buttons and month/year string */ +static void MONTHCAL_PaintTitle(MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps, INT calIdx) +{ + static const WCHAR fmt_monthW[] = { '%','s',' ','%','l','d',0 }; + RECT *title = &infoPtr->calendars[calIdx].title; ++ const SYSTEMTIME *st = &infoPtr->calendars[calIdx].month; + WCHAR buf_month[80], buf_fmt[80]; + HBRUSH hbr; + SIZE sz; + + /* fill header box */ - hbr = CreateSolidBrush(infoPtr->titlebk); ++ hbr = CreateSolidBrush(infoPtr->colors[MCSC_TITLEBK]); + FillRect(hdc, title, hbr); + DeleteObject(hbr); + + /* month/year string */ - SetBkColor(hdc, infoPtr->titlebk); - SetTextColor(hdc, infoPtr->titletxt); ++ SetBkColor(hdc, infoPtr->colors[MCSC_TITLEBK]); ++ SetTextColor(hdc, infoPtr->colors[MCSC_TITLETEXT]); + SelectObject(hdc, infoPtr->hBoldFont); + - GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SMONTHNAME1+infoPtr->curSel.wMonth-1, ++ GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SMONTHNAME1 + st->wMonth - 1, + buf_month, countof(buf_month)); + - wsprintfW(buf_fmt, fmt_monthW, buf_month, infoPtr->curSel.wYear); ++ wsprintfW(buf_fmt, fmt_monthW, buf_month, st->wYear); + DrawTextW(hdc, buf_fmt, strlenW(buf_fmt), title, + DT_CENTER | DT_VCENTER | DT_SINGLELINE); + + /* update title rectangles with current month - used while testing hits */ + GetTextExtentPoint32W(hdc, buf_fmt, strlenW(buf_fmt), &sz); + infoPtr->calendars[calIdx].titlemonth.left = title->right / 2 + title->left / 2 - sz.cx / 2; + infoPtr->calendars[calIdx].titleyear.right = title->right / 2 + title->left / 2 + sz.cx / 2; + + GetTextExtentPoint32W(hdc, buf_month, strlenW(buf_month), &sz); + infoPtr->calendars[calIdx].titlemonth.right = infoPtr->calendars[calIdx].titlemonth.left + sz.cx; + infoPtr->calendars[calIdx].titleyear.left = infoPtr->calendars[calIdx].titlemonth.right; +} + +static void MONTHCAL_PaintWeeknumbers(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps, INT calIdx) +{ ++ const SYSTEMTIME *date = &infoPtr->calendars[calIdx].month; + static const WCHAR fmt_weekW[] = { '%','d',0 }; + INT mindays, weeknum, weeknum1, startofprescal; - SYSTEMTIME st = infoPtr->curSel; - RECT r; - WCHAR buf[80]; + INT i, prev_month; ++ SYSTEMTIME st; ++ WCHAR buf[80]; ++ HBRUSH hbr; ++ RECT r; + + if (!(infoPtr->dwStyle & MCS_WEEKNUMBERS)) return; + + MONTHCAL_GetMinDate(infoPtr, &st); + startofprescal = st.wDay; - st = infoPtr->curSel; ++ st = *date; + - prev_month = infoPtr->curSel.wMonth - 1; ++ prev_month = date->wMonth - 1; + if(prev_month == 0) prev_month = 12; + + /* + Rules what week to call the first week of a new year: + LOCALE_IFIRSTWEEKOFYEAR == 0 (e.g US?): + The week containing Jan 1 is the first week of year + LOCALE_IFIRSTWEEKOFYEAR == 2 (e.g. Germany): + First week of year must contain 4 days of the new year + LOCALE_IFIRSTWEEKOFYEAR == 1 (what contries?) + The first week of the year must contain only days of the new year + */ + GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IFIRSTWEEKOFYEAR, buf, countof(buf)); + weeknum = atoiW(buf); + switch (weeknum) + { + case 1: mindays = 6; + break; + case 2: mindays = 3; + break; + case 0: mindays = 0; + break; + default: + WARN("Unknown LOCALE_IFIRSTWEEKOFYEAR value %d, defaulting to 0\n", weeknum); + mindays = 0; + } + - if (infoPtr->curSel.wMonth == 1) ++ if (date->wMonth == 1) + { + /* calculate all those exceptions for january */ + st.wDay = st.wMonth = 1; + weeknum1 = MONTHCAL_CalculateDayOfWeek(&st, FALSE); + if ((infoPtr->firstDay - weeknum1) % 7 > mindays) + weeknum = 1; + else + { + weeknum = 0; + for(i = 0; i < 11; i++) - weeknum += MONTHCAL_MonthLength(i+1, infoPtr->curSel.wYear - 1); ++ weeknum += MONTHCAL_MonthLength(i+1, date->wYear - 1); + + weeknum += startofprescal + 7; + weeknum /= 7; + st.wYear -= 1; + weeknum1 = MONTHCAL_CalculateDayOfWeek(&st, FALSE); + if ((infoPtr->firstDay - weeknum1) % 7 > mindays) weeknum++; + } + } + else + { + weeknum = 0; + for(i = 0; i < prev_month - 1; i++) - weeknum += MONTHCAL_MonthLength(i+1, infoPtr->curSel.wYear); ++ weeknum += MONTHCAL_MonthLength(i+1, date->wYear); + + weeknum += startofprescal + 7; + weeknum /= 7; + st.wDay = st.wMonth = 1; + weeknum1 = MONTHCAL_CalculateDayOfWeek(&st, FALSE); + if ((infoPtr->firstDay - weeknum1) % 7 > mindays) weeknum++; + } + + r = infoPtr->calendars[calIdx].weeknums; ++ ++ /* erase whole week numbers area */ ++ hbr = CreateSolidBrush(infoPtr->colors[MCSC_MONTHBK]); ++ FillRect(hdc, &r, hbr); ++ DeleteObject(hbr); ++ ++ /* reduce rectangle to one week number */ + r.bottom = r.top + infoPtr->height_increment; + + for(i = 0; i < 6; i++) { + if((i == 0) && (weeknum > 50)) + { + wsprintfW(buf, fmt_weekW, weeknum); + weeknum = 0; + } + else if((i == 5) && (weeknum > 47)) + { + wsprintfW(buf, fmt_weekW, 1); + } + else + wsprintfW(buf, fmt_weekW, weeknum + i); + + DrawTextW(hdc, buf, -1, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE); + OffsetRect(&r, 0, infoPtr->height_increment); + } + + /* line separator for week numbers column */ + MoveToEx(hdc, infoPtr->calendars[calIdx].weeknums.right, infoPtr->calendars[calIdx].weeknums.top + 3 , NULL); + LineTo(hdc, infoPtr->calendars[calIdx].weeknums.right, infoPtr->calendars[calIdx].weeknums.bottom); +} + +/* bottom today date */ +static void MONTHCAL_PaintTodayTitle(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps) +{ + if(!(infoPtr->dwStyle & MCS_NOTODAY)) { + static const WCHAR todayW[] = { 'T','o','d','a','y',':',0 }; + static const WCHAR fmt_todayW[] = { '%','s',' ','%','s',0 }; + WCHAR buf_todayW[30], buf_dateW[20], buf[80]; + RECT rtoday; + + if(!(infoPtr->dwStyle & MCS_NOTODAYCIRCLE)) { + SYSTEMTIME fake_st; + + MONTHCAL_GetMaxDate(infoPtr, &fake_st); + /* this is always safe cause next month will never fully fit calendar */ + fake_st.wDay += 1; + MONTHCAL_CircleDay(infoPtr, hdc, &fake_st); + } + if (!LoadStringW(COMCTL32_hModule, IDM_TODAY, buf_todayW, countof(buf_todayW))) + { + WARN("Can't load resource\n"); + strcpyW(buf_todayW, todayW); + } + MONTHCAL_CalcDayRect(infoPtr, &rtoday, 1, 6); + GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &infoPtr->todaysDate, NULL, + buf_dateW, countof(buf_dateW)); + SelectObject(hdc, infoPtr->hBoldFont); + + wsprintfW(buf, fmt_todayW, buf_todayW, buf_dateW); + DrawTextW(hdc, buf, -1, &rtoday, DT_CALCRECT | DT_LEFT | DT_VCENTER | DT_SINGLELINE); + DrawTextW(hdc, buf, -1, &rtoday, DT_LEFT | DT_VCENTER | DT_SINGLELINE); + + SelectObject(hdc, infoPtr->hFont); + } +} + +/* today mark + focus */ +static void MONTHCAL_PaintFocusAndCircle(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps) +{ - if((infoPtr->curSel.wMonth == infoPtr->todaysDate.wMonth) && - (infoPtr->curSel.wYear == infoPtr->todaysDate.wYear) && ++ if((infoPtr->minSel.wMonth == infoPtr->todaysDate.wMonth) && ++ (infoPtr->minSel.wYear == infoPtr->todaysDate.wYear) && + !(infoPtr->dwStyle & MCS_NOTODAYCIRCLE)) + { + MONTHCAL_CircleDay(infoPtr, hdc, &infoPtr->todaysDate); + } + + if(!MONTHCAL_IsDateEqual(&infoPtr->focusedSel, &st_null)) + { + RECT r; + MONTHCAL_CalcPosFromDay(infoPtr, &infoPtr->focusedSel, &r); + DrawFocusRect(hdc, &r); + } +} + +/* paint a calendar area */ +static void MONTHCAL_PaintCalendar(const MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps, INT calIdx) +{ - INT prev_month, i, j; ++ const SYSTEMTIME *date = &infoPtr->calendars[calIdx].month; ++ INT prev_month, i, j, length; ++ RECT r, fill_bk_rect; ++ SYSTEMTIME st; + WCHAR buf[80]; + HBRUSH hbr; - RECT r, fill_bk_rect; + int mask; - SYSTEMTIME st; + + /* fill whole days area - from week days area to today note rectangle */ + fill_bk_rect = infoPtr->calendars[calIdx].wdays; + fill_bk_rect.bottom = infoPtr->calendars[calIdx].days.bottom + + (infoPtr->todayrect.bottom - infoPtr->todayrect.top); + - hbr = CreateSolidBrush(infoPtr->monthbk); ++ hbr = CreateSolidBrush(infoPtr->colors[MCSC_MONTHBK]); + FillRect(hdc, &fill_bk_rect, hbr); + DeleteObject(hbr); + + /* draw line under day abbreviations */ + MoveToEx(hdc, infoPtr->calendars[calIdx].days.left + 3, + infoPtr->calendars[calIdx].title.bottom + infoPtr->textHeight + 1, NULL); + LineTo(hdc, infoPtr->calendars[calIdx].days.right - 3, + infoPtr->calendars[calIdx].title.bottom + infoPtr->textHeight + 1); + - prev_month = infoPtr->curSel.wMonth - 1; ++ prev_month = date->wMonth - 1; + if (prev_month == 0) prev_month = 12; + + infoPtr->calendars[calIdx].wdays.left = infoPtr->calendars[calIdx].days.left = + infoPtr->calendars[calIdx].weeknums.right; + + /* 1. draw day abbreviations */ + SelectObject(hdc, infoPtr->hFont); - SetBkColor(hdc, infoPtr->monthbk); - SetTextColor(hdc, infoPtr->trailingtxt); ++ SetBkColor(hdc, infoPtr->colors[MCSC_MONTHBK]); ++ SetTextColor(hdc, infoPtr->colors[MCSC_TRAILINGTEXT]); + /* rectangle to draw a single day abbreviation within */ + r = infoPtr->calendars[calIdx].wdays; + r.right = r.left + infoPtr->width_increment; + + i = infoPtr->firstDay; + for(j = 0; j < 7; j++) { + GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SABBREVDAYNAME1 + (i+j+6)%7, buf, countof(buf)); + DrawTextW(hdc, buf, strlenW(buf), &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE); + OffsetRect(&r, infoPtr->width_increment, 0); + } + + /* 2. previous and next months */ + if (!(infoPtr->dwStyle & MCS_NOTRAILINGDATES) && (calIdx == 0 || calIdx == infoPtr->cal_num - 1)) + { + SYSTEMTIME st_max; + - SetTextColor(hdc, infoPtr->trailingtxt); ++ SetTextColor(hdc, infoPtr->colors[MCSC_TRAILINGTEXT]); + + /* draw prev month */ + if (calIdx == 0) + { + MONTHCAL_GetMinDate(infoPtr, &st); + mask = 1 << (st.wDay-1); ++ length = MONTHCAL_MonthLength(prev_month, date->wYear); + - while(st.wDay <= MONTHCAL_MonthLength(prev_month, infoPtr->curSel.wYear)) ++ while(st.wDay <= length) + { + MONTHCAL_DrawDay(infoPtr, hdc, &st, infoPtr->monthdayState[0] & mask, ps); + mask <<= 1; + st.wDay++; + } + } + + /* draw next month */ + if (calIdx == infoPtr->cal_num - 1) + { - st = infoPtr->curSel; ++ st = *date; + st.wDay = 1; + MONTHCAL_GetNextMonth(&st); + MONTHCAL_GetMaxDate(infoPtr, &st_max); + mask = 1; + + while(st.wDay <= st_max.wDay) + { + MONTHCAL_DrawDay(infoPtr, hdc, &st, infoPtr->monthdayState[2] & mask, ps); + mask <<= 1; + st.wDay++; + } + } + } + + /* 3. current month */ - SetTextColor(hdc, infoPtr->txt); - st = infoPtr->curSel; ++ SetTextColor(hdc, infoPtr->colors[MCSC_TEXT]); ++ st = *date; + st.wDay = 1; + mask = 1; - while(st.wDay <= MONTHCAL_MonthLength(infoPtr->curSel.wMonth, infoPtr->curSel.wYear)) { ++ length = MONTHCAL_MonthLength(date->wMonth, date->wYear); ++ while(st.wDay <= length) ++ { + MONTHCAL_DrawDay(infoPtr, hdc, &st, infoPtr->monthdayState[1] & mask, ps); + mask <<= 1; + st.wDay++; + } +} + +static void MONTHCAL_Refresh(MONTHCAL_INFO *infoPtr, HDC hdc, const PAINTSTRUCT *ps) +{ + COLORREF old_text_clr, old_bk_clr; + HFONT old_font; + INT i; + + old_text_clr = SetTextColor(hdc, comctl32_color.clrWindowText); + old_bk_clr = GetBkColor(hdc); + old_font = GetCurrentObject(hdc, OBJ_FONT); + + for (i = 0; i < infoPtr->cal_num; i++) + { + RECT *title = &infoPtr->calendars[i].title; + RECT r; + + /* draw title, redraw all its elements */ + if (IntersectRect(&r, &(ps->rcPaint), title)) + MONTHCAL_PaintTitle(infoPtr, hdc, ps, i); + + /* draw calendar area */ + UnionRect(&r, &infoPtr->calendars[i].wdays, &infoPtr->todayrect); + if (IntersectRect(&r, &(ps->rcPaint), &r)) + MONTHCAL_PaintCalendar(infoPtr, hdc, ps, i); + + /* week numbers */ + MONTHCAL_PaintWeeknumbers(infoPtr, hdc, ps, i); + } + + /* focus and today rectangle */ + MONTHCAL_PaintFocusAndCircle(infoPtr, hdc, ps); + + /* today at the bottom left */ + MONTHCAL_PaintTodayTitle(infoPtr, hdc, ps); + + /* navigation buttons */ - MONTHCAL_PaintButton(infoPtr, hdc, FALSE); - MONTHCAL_PaintButton(infoPtr, hdc, TRUE); ++ MONTHCAL_PaintButton(infoPtr, hdc, DIRECTION_BACKWARD); ++ MONTHCAL_PaintButton(infoPtr, hdc, DIRECTION_FORWARD); + + /* restore context */ + SetBkColor(hdc, old_bk_clr); + SelectObject(hdc, old_font); + SetTextColor(hdc, old_text_clr); +} + +static LRESULT - MONTHCAL_GetMinReqRect(const MONTHCAL_INFO *infoPtr, LPRECT lpRect) ++MONTHCAL_GetMinReqRect(const MONTHCAL_INFO *infoPtr, RECT *rect) +{ - TRACE("rect %p\n", lpRect); ++ TRACE("rect %p\n", rect); + - if(!lpRect) return FALSE; ++ if(!rect) return FALSE; + - lpRect->left = infoPtr->calendars[0].title.left; - lpRect->top = infoPtr->calendars[0].title.top; - lpRect->right = infoPtr->calendars[0].title.right; - lpRect->bottom = infoPtr->todayrect.bottom; ++ *rect = infoPtr->calendars[0].title; ++ rect->bottom = infoPtr->calendars[0].days.bottom + infoPtr->todayrect.bottom - ++ infoPtr->todayrect.top; + - AdjustWindowRect(lpRect, infoPtr->dwStyle, FALSE); ++ AdjustWindowRect(rect, infoPtr->dwStyle, FALSE); + + /* minimal rectangle is zero based */ - OffsetRect(lpRect, -lpRect->left, -lpRect->top); ++ OffsetRect(rect, -rect->left, -rect->top); + - TRACE("%s\n", wine_dbgstr_rect(lpRect)); ++ TRACE("%s\n", wine_dbgstr_rect(rect)); + + return TRUE; +} + ++static COLORREF ++MONTHCAL_GetColor(const MONTHCAL_INFO *infoPtr, UINT index) ++{ ++ TRACE("%p, %d\n", infoPtr, index); ++ ++ if (index > MCSC_TRAILINGTEXT) return -1; ++ return infoPtr->colors[index]; ++} + +static LRESULT - MONTHCAL_GetColor(const MONTHCAL_INFO *infoPtr, INT index) ++MONTHCAL_SetColor(MONTHCAL_INFO *infoPtr, UINT index, COLORREF color) +{ - TRACE("\n"); ++ COLORREF prev; + - switch(index) { - case MCSC_BACKGROUND: - return infoPtr->bk; - case MCSC_TEXT: - return infoPtr->txt; - case MCSC_TITLEBK: - return infoPtr->titlebk; - case MCSC_TITLETEXT: - return infoPtr->titletxt; - case MCSC_MONTHBK: - return infoPtr->monthbk; - case MCSC_TRAILINGTEXT: - return infoPtr->trailingtxt; - } - - return -1; - } ++ TRACE("%p, %d: color %08x\n", infoPtr, index, color); + ++ if (index > MCSC_TRAILINGTEXT) return -1; + - static LRESULT - MONTHCAL_SetColor(MONTHCAL_INFO *infoPtr, INT index, COLORREF color) - { - COLORREF prev = -1; - - TRACE("%d: color %08x\n", index, color); - - switch(index) { - case MCSC_BACKGROUND: - prev = infoPtr->bk; - infoPtr->bk = color; - break; - case MCSC_TEXT: - prev = infoPtr->txt; - infoPtr->txt = color; - break; - case MCSC_TITLEBK: - prev = infoPtr->titlebk; - infoPtr->titlebk = color; - break; - case MCSC_TITLETEXT: - prev=infoPtr->titletxt; - infoPtr->titletxt = color; - break; - case MCSC_MONTHBK: - prev = infoPtr->monthbk; - infoPtr->monthbk = color; - break; - case MCSC_TRAILINGTEXT: - prev = infoPtr->trailingtxt; - infoPtr->trailingtxt = color; - break; - } ++ prev = infoPtr->colors[index]; ++ infoPtr->colors[index] = color; + + InvalidateRect(infoPtr->hwndSelf, NULL, index == MCSC_BACKGROUND ? TRUE : FALSE); + return prev; +} + - +static LRESULT +MONTHCAL_GetMonthDelta(const MONTHCAL_INFO *infoPtr) +{ + TRACE("\n"); + + if(infoPtr->delta) + return infoPtr->delta; + else + return infoPtr->visible; +} + + +static LRESULT +MONTHCAL_SetMonthDelta(MONTHCAL_INFO *infoPtr, INT delta) +{ + INT prev = infoPtr->delta; + + TRACE("delta %d\n", delta); + + infoPtr->delta = delta; + return prev; +} + + +static inline LRESULT +MONTHCAL_GetFirstDayOfWeek(const MONTHCAL_INFO *infoPtr) +{ + int day; + + /* convert from SYSTEMTIME to locale format */ + day = (infoPtr->firstDay >= 0) ? (infoPtr->firstDay+6)%7 : infoPtr->firstDay; + + return MAKELONG(day, infoPtr->firstDaySet); +} + + +/* Sets the first day of the week that will appear in the control + * + * + * PARAMETERS: + * [I] infoPtr : valid pointer to control data + * [I] day : day number to set as new first day (0 == Monday,...,6 == Sunday) + * + * + * RETURN VALUE: + * Low word contains previous first day, + * high word indicates was first day forced with this message before or is + * locale difined (TRUE - was forced, FALSE - wasn't). + * + * FIXME: this needs to be implemented properly in MONTHCAL_Refresh() + * FIXME: we need more error checking here + */ +static LRESULT +MONTHCAL_SetFirstDayOfWeek(MONTHCAL_INFO *infoPtr, INT day) +{ + LRESULT prev = MONTHCAL_GetFirstDayOfWeek(infoPtr); + int new_day; + + TRACE("%d\n", day); + + if(day == -1) + { + WCHAR buf[80]; + + GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_IFIRSTDAYOFWEEK, buf, countof(buf)); + TRACE("%s %d\n", debugstr_w(buf), strlenW(buf)); + + new_day = atoiW(buf); + + infoPtr->firstDaySet = FALSE; + } + else if(day >= 7) + { + new_day = 6; /* max first day allowed */ + infoPtr->firstDaySet = TRUE; + } + else + { + /* Native behaviour for that case is broken: invalid date number >31 + got displayed at (0,0) position, current month starts always from + (1,0) position. Should be implemented here as well only if there's + nothing else to do. */ + if (day < -1) + FIXME("No bug compatibility for day=%d\n", day); + + new_day = day; + infoPtr->firstDaySet = TRUE; + } + + /* convert from locale to SYSTEMTIME format */ + infoPtr->firstDay = (new_day >= 0) ? (++new_day) % 7 : new_day; + + InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); + + return prev; +} + + +static LRESULT +MONTHCAL_GetMonthRange(const MONTHCAL_INFO *infoPtr, DWORD flag, SYSTEMTIME *st) +{ + TRACE("flag=%d, st=%p\n", flag, st); + + if(st) + { + switch (flag) { + case GMR_VISIBLE: + { + st[0] = infoPtr->calendars[0].month; + st[1] = infoPtr->calendars[infoPtr->cal_num-1].month; + + if (st[0].wMonth == min_allowed_date.wMonth && + st[0].wYear == min_allowed_date.wYear) + { + st[0].wDay = min_allowed_date.wDay; + } + else + st[0].wDay = 1; + MONTHCAL_CalculateDayOfWeek(&st[0], TRUE); + + st[1].wDay = MONTHCAL_MonthLength(st[1].wMonth, st[1].wYear); + MONTHCAL_CalculateDayOfWeek(&st[1], TRUE); + + return infoPtr->cal_num; + } + case GMR_DAYSTATE: + { + /*FIXME: currently multicalendar feature isn't implemented, + min date from previous month and max date from next one returned */ + MONTHCAL_GetMinDate(infoPtr, &st[0]); + MONTHCAL_GetMaxDate(infoPtr, &st[1]); + break; + } + default: + WARN("Unknown flag value, got %d\n", flag); + } + } + + return infoPtr->monthRange; +} + + +static LRESULT +MONTHCAL_GetMaxTodayWidth(const MONTHCAL_INFO *infoPtr) +{ + return(infoPtr->todayrect.right - infoPtr->todayrect.left); +} + + +static LRESULT +MONTHCAL_SetRange(MONTHCAL_INFO *infoPtr, SHORT limits, SYSTEMTIME *range) +{ + FILETIME ft_min, ft_max; + + TRACE("%x %p\n", limits, range); + + if ((limits & GDTR_MIN && !MONTHCAL_ValidateDate(&range[0])) || + (limits & GDTR_MAX && !MONTHCAL_ValidateDate(&range[1]))) + return FALSE; + + if (limits & GDTR_MIN) + { + if (!MONTHCAL_ValidateTime(&range[0])) + MONTHCAL_CopyTime(&infoPtr->todaysDate, &range[0]); + + infoPtr->minDate = range[0]; + infoPtr->rangeValid |= GDTR_MIN; + } + if (limits & GDTR_MAX) + { + if (!MONTHCAL_ValidateTime(&range[1])) + MONTHCAL_CopyTime(&infoPtr->todaysDate, &range[1]); + + infoPtr->maxDate = range[1]; + infoPtr->rangeValid |= GDTR_MAX; + } + + /* Only one limit set - we are done */ + if ((infoPtr->rangeValid & (GDTR_MIN | GDTR_MAX)) != (GDTR_MIN | GDTR_MAX)) + return TRUE; + + SystemTimeToFileTime(&infoPtr->maxDate, &ft_max); + SystemTimeToFileTime(&infoPtr->minDate, &ft_min); + + if (CompareFileTime(&ft_min, &ft_max) >= 0) + { + if ((limits & (GDTR_MIN | GDTR_MAX)) == (GDTR_MIN | GDTR_MAX)) + { + /* Native swaps limits only when both limits are being set. */ + SYSTEMTIME st_tmp = infoPtr->minDate; + infoPtr->minDate = infoPtr->maxDate; + infoPtr->maxDate = st_tmp; + } + else + { + /* reset the other limit */ + if (limits & GDTR_MIN) infoPtr->maxDate = st_null; + if (limits & GDTR_MAX) infoPtr->minDate = st_null; + infoPtr->rangeValid &= limits & GDTR_MIN ? ~GDTR_MAX : ~GDTR_MIN; + } + } + + return TRUE; +} + + +static LRESULT +MONTHCAL_GetRange(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *range) +{ + TRACE("%p\n", range); + + if(!range) return FALSE; + + range[1] = infoPtr->maxDate; + range[0] = infoPtr->minDate; + + return infoPtr->rangeValid; +} + + +static LRESULT +MONTHCAL_SetDayState(const MONTHCAL_INFO *infoPtr, INT months, MONTHDAYSTATE *states) +{ + TRACE("%p %d %p\n", infoPtr, months, states); + if(months != infoPtr->monthRange) return 0; + + memcpy(infoPtr->monthdayState, states, months*sizeof(MONTHDAYSTATE)); + + return 1; +} + +static LRESULT +MONTHCAL_GetCurSel(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *curSel) +{ + TRACE("%p\n", curSel); + if(!curSel) return FALSE; + if(infoPtr->dwStyle & MCS_MULTISELECT) return FALSE; + - *curSel = infoPtr->curSel; ++ *curSel = infoPtr->minSel; + TRACE("%d/%d/%d\n", curSel->wYear, curSel->wMonth, curSel->wDay); + return TRUE; +} + +static LRESULT +MONTHCAL_SetCurSel(MONTHCAL_INFO *infoPtr, SYSTEMTIME *curSel) +{ - SYSTEMTIME prev = infoPtr->curSel; ++ SYSTEMTIME prev = infoPtr->minSel; ++ WORD day; + + TRACE("%p\n", curSel); + if(!curSel) return FALSE; + if(infoPtr->dwStyle & MCS_MULTISELECT) return FALSE; + + if(!MONTHCAL_ValidateDate(curSel)) return FALSE; + /* exit earlier if selection equals current */ - if (MONTHCAL_IsDateEqual(&infoPtr->curSel, curSel)) return TRUE; ++ if (MONTHCAL_IsDateEqual(&infoPtr->minSel, curSel)) return TRUE; + + if(!MONTHCAL_IsDateInValidRange(infoPtr, curSel, FALSE)) return FALSE; + ++ infoPtr->calendars[0].month = *curSel; + infoPtr->minSel = *curSel; + infoPtr->maxSel = *curSel; + + /* if selection is still in current month, reduce rectangle */ ++ day = prev.wDay; + prev.wDay = curSel->wDay; + if (MONTHCAL_IsDateEqual(&prev, curSel)) + { + RECT r_prev, r_new; + - /* note that infoPtr->curSel isn't updated yet */ - MONTHCAL_CalcPosFromDay(infoPtr, &infoPtr->curSel, &r_prev); ++ prev.wDay = day; ++ MONTHCAL_CalcPosFromDay(infoPtr, &prev, &r_prev); + MONTHCAL_CalcPosFromDay(infoPtr, curSel, &r_new); + + InvalidateRect(infoPtr->hwndSelf, &r_prev, FALSE); + InvalidateRect(infoPtr->hwndSelf, &r_new, FALSE); + } + else + InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); + - infoPtr->curSel = *curSel; - infoPtr->calendars[0].month = *curSel; - + return TRUE; +} + + +static LRESULT +MONTHCAL_GetMaxSelCount(const MONTHCAL_INFO *infoPtr) +{ + return infoPtr->maxSelCount; +} + + +static LRESULT +MONTHCAL_SetMaxSelCount(MONTHCAL_INFO *infoPtr, INT max) +{ + TRACE("%d\n", max); + + if(!(infoPtr->dwStyle & MCS_MULTISELECT)) return FALSE; + if(max <= 0) return FALSE; + + infoPtr->maxSelCount = max; + + return TRUE; +} + + +static LRESULT +MONTHCAL_GetSelRange(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *range) +{ + TRACE("%p\n", range); + + if(!range) return FALSE; + + if(infoPtr->dwStyle & MCS_MULTISELECT) + { + range[1] = infoPtr->maxSel; + range[0] = infoPtr->minSel; + TRACE("[min,max]=[%d %d]\n", infoPtr->minSel.wDay, infoPtr->maxSel.wDay); + return TRUE; + } + + return FALSE; +} + + +static LRESULT +MONTHCAL_SetSelRange(MONTHCAL_INFO *infoPtr, SYSTEMTIME *range) +{ + TRACE("%p\n", range); + + if(!range) return FALSE; + + if(infoPtr->dwStyle & MCS_MULTISELECT) + { + SYSTEMTIME old_range[2]; + + /* adjust timestamps */ + if(!MONTHCAL_ValidateTime(&range[0])) + MONTHCAL_CopyTime(&infoPtr->todaysDate, &range[0]); + if(!MONTHCAL_ValidateTime(&range[1])) + MONTHCAL_CopyTime(&infoPtr->todaysDate, &range[1]); + + /* maximum range exceeded */ + if(!MONTHCAL_IsSelRangeValid(infoPtr, &range[0], &range[1], NULL)) return FALSE; + + old_range[0] = infoPtr->minSel; + old_range[1] = infoPtr->maxSel; + + /* swap if min > max */ + if(MONTHCAL_CompareSystemTime(&range[0], &range[1]) <= 0) + { + infoPtr->minSel = range[0]; + infoPtr->maxSel = range[1]; + } + else + { + infoPtr->minSel = range[1]; + infoPtr->maxSel = range[0]; + } - infoPtr->curSel = infoPtr->minSel; + infoPtr->calendars[0].month = infoPtr->minSel; + + /* update day of week */ + MONTHCAL_CalculateDayOfWeek(&infoPtr->minSel, TRUE); + MONTHCAL_CalculateDayOfWeek(&infoPtr->maxSel, TRUE); - MONTHCAL_CalculateDayOfWeek(&infoPtr->curSel, TRUE); + + /* redraw if bounds changed */ + /* FIXME: no actual need to redraw everything */ + if(!MONTHCAL_IsDateEqual(&old_range[0], &range[0]) || + !MONTHCAL_IsDateEqual(&old_range[1], &range[1])) + { + InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); + } + + TRACE("[min,max]=[%d %d]\n", infoPtr->minSel.wDay, infoPtr->maxSel.wDay); + return TRUE; + } + + return FALSE; +} + + +static LRESULT +MONTHCAL_GetToday(const MONTHCAL_INFO *infoPtr, SYSTEMTIME *today) +{ + TRACE("%p\n", today); + + if(!today) return FALSE; + *today = infoPtr->todaysDate; + return TRUE; +} + +/* Internal helper for MCM_SETTODAY handler and auto update timer handler + * + * RETURN VALUE + * + * TRUE - today date changed + * FALSE - today date isn't changed + */ +static BOOL +MONTHCAL_UpdateToday(MONTHCAL_INFO *infoPtr, const SYSTEMTIME *today) +{ + RECT new_r, old_r; + + if(MONTHCAL_IsDateEqual(today, &infoPtr->todaysDate)) return FALSE; + + MONTHCAL_CalcPosFromDay(infoPtr, &infoPtr->todaysDate, &old_r); + MONTHCAL_CalcPosFromDay(infoPtr, today, &new_r); + + infoPtr->todaysDate = *today; + + /* only two days need redrawing */ + InvalidateRect(infoPtr->hwndSelf, &old_r, FALSE); + InvalidateRect(infoPtr->hwndSelf, &new_r, FALSE); + return TRUE; +} + +/* MCM_SETTODAT handler */ +static LRESULT +MONTHCAL_SetToday(MONTHCAL_INFO *infoPtr, const SYSTEMTIME *today) +{ + TRACE("%p\n", today); + + if(!today) return FALSE; + + /* remember if date was set successfully */ + if(MONTHCAL_UpdateToday(infoPtr, today)) infoPtr->todaySet = TRUE; + + return TRUE; +} + +/* returns calendar index containing specified point, or -1 if it's background */ +static INT MONTHCAL_GetCalendarFromPoint(const MONTHCAL_INFO *infoPtr, const POINT *pt) +{ + RECT r; + INT i; + + for (i = 0; i < infoPtr->cal_num; i++) + { + /* whole bounding rectangle allows some optimization to compute */ + r.left = infoPtr->calendars[i].title.left; + r.top = infoPtr->calendars[i].title.top; + r.bottom = infoPtr->calendars[i].days.bottom; + r.right = infoPtr->calendars[i].days.right; + + if (PtInRect(&r, *pt)) return i; + } + + return -1; +} + ++static inline UINT fill_hittest_info(const MCHITTESTINFO *src, MCHITTESTINFO *dest) ++{ ++ dest->uHit = src->uHit; ++ dest->st = src->st; ++ ++ if (dest->cbSize == sizeof(MCHITTESTINFO)) ++ memcpy(&dest->rc, &src->rc, sizeof(MCHITTESTINFO) - MCHITTESTINFO_V1_SIZE); ++ ++ return src->uHit; ++} ++ +static LRESULT +MONTHCAL_HitTest(const MONTHCAL_INFO *infoPtr, MCHITTESTINFO *lpht) +{ + INT day, wday, wnum, calIdx; ++ MCHITTESTINFO htinfo; + SYSTEMTIME ht_month; + UINT x, y; + + if(!lpht || lpht->cbSize < MCHITTESTINFO_V1_SIZE) return -1; + + x = lpht->pt.x; + y = lpht->pt.y; + - memset(&lpht->st, 0, sizeof(lpht->st)); ++ htinfo.st = st_null; ++ ++ /* we should preserve passed fields if hit area doesn't need them */ ++ if (lpht->cbSize == sizeof(MCHITTESTINFO)) ++ memcpy(&htinfo.rc, &lpht->rc, sizeof(MCHITTESTINFO) - MCHITTESTINFO_V1_SIZE); + + /* Comment in for debugging... + TRACE("%d %d wd[%d %d %d %d] d[%d %d %d %d] t[%d %d %d %d] wn[%d %d %d %d]\n", x, y, + infoPtr->wdays.left, infoPtr->wdays.right, + infoPtr->wdays.top, infoPtr->wdays.bottom, + infoPtr->days.left, infoPtr->days.right, + infoPtr->days.top, infoPtr->days.bottom, + infoPtr->todayrect.left, infoPtr->todayrect.right, + infoPtr->todayrect.top, infoPtr->todayrect.bottom, + infoPtr->weeknums.left, infoPtr->weeknums.right, + infoPtr->weeknums.top, infoPtr->weeknums.bottom); + */ + + /* guess in what calendar we are */ + calIdx = MONTHCAL_GetCalendarFromPoint(infoPtr, &lpht->pt); + if (calIdx == -1) + { + if (PtInRect(&infoPtr->todayrect, lpht->pt)) - lpht->uHit = MCHT_TODAYLINK; ++ { ++ htinfo.uHit = MCHT_TODAYLINK; ++ htinfo.rc = infoPtr->todayrect; ++ } + else + /* outside of calendar area? What's left must be background :-) */ - lpht->uHit = MCHT_CALENDARBK; ++ htinfo.uHit = MCHT_CALENDARBK; + - return lpht->uHit; ++ return fill_hittest_info(&htinfo, lpht); + } + + ht_month = infoPtr->calendars[calIdx].month; + + /* are we in the header? */ + if (PtInRect(&infoPtr->calendars[calIdx].title, lpht->pt)) { + /* FIXME: buttons hittesting could be optimized cause maximum + two calendars have buttons */ + if (calIdx == 0 && PtInRect(&infoPtr->titlebtnprev, lpht->pt)) + { - lpht->uHit = MCHT_TITLEBTNPREV; ++ htinfo.uHit = MCHT_TITLEBTNPREV; ++ htinfo.rc = infoPtr->titlebtnprev; + } + else if (PtInRect(&infoPtr->titlebtnnext, lpht->pt)) + { - lpht->uHit = MCHT_TITLEBTNNEXT; ++ htinfo.uHit = MCHT_TITLEBTNNEXT; ++ htinfo.rc = infoPtr->titlebtnnext; + } + else if (PtInRect(&infoPtr->calendars[calIdx].titlemonth, lpht->pt)) + { - lpht->uHit = MCHT_TITLEMONTH; ++ htinfo.uHit = MCHT_TITLEMONTH; ++ htinfo.rc = infoPtr->calendars[calIdx].titlemonth; ++ htinfo.iOffset = calIdx; + } + else if (PtInRect(&infoPtr->calendars[calIdx].titleyear, lpht->pt)) + { - lpht->uHit = MCHT_TITLEYEAR; ++ htinfo.uHit = MCHT_TITLEYEAR; ++ htinfo.rc = infoPtr->calendars[calIdx].titleyear; ++ htinfo.iOffset = calIdx; + } + else - lpht->uHit = MCHT_TITLE; ++ { ++ htinfo.uHit = MCHT_TITLE; ++ htinfo.rc = infoPtr->calendars[calIdx].title; ++ htinfo.iOffset = calIdx; ++ } + - return lpht->uHit; ++ return fill_hittest_info(&htinfo, lpht); + } + + /* days area (including week days and week numbers */ + day = MONTHCAL_CalcDayFromPos(infoPtr, x, y, &wday, &wnum); + if (PtInRect(&infoPtr->calendars[calIdx].wdays, lpht->pt)) + { - lpht->uHit = MCHT_CALENDARDAY; - lpht->st.wYear = ht_month.wYear; - lpht->st.wMonth = (day < 1) ? ht_month.wMonth -1 : ht_month.wMonth; - lpht->st.wDay = (day < 1) ? ++ htinfo.uHit = MCHT_CALENDARDAY; ++ htinfo.iOffset = calIdx; ++ htinfo.st.wYear = ht_month.wYear; ++ htinfo.st.wMonth = (day < 1) ? ht_month.wMonth -1 : ht_month.wMonth; ++ htinfo.st.wDay = (day < 1) ? + MONTHCAL_MonthLength(ht_month.wMonth-1, ht_month.wYear) - day : day; ++ ++ MONTHCAL_CalcDayXY(infoPtr, &htinfo.st, &htinfo.iCol, &htinfo.iRow); + } + else if(PtInRect(&infoPtr->calendars[calIdx].weeknums, lpht->pt)) + { - lpht->uHit = MCHT_CALENDARWEEKNUM; - lpht->st.wYear = ht_month.wYear; ++ htinfo.uHit = MCHT_CALENDARWEEKNUM; ++ htinfo.st.wYear = ht_month.wYear; ++ htinfo.iOffset = calIdx; + - if (day < 1) { - lpht->st.wMonth = ht_month.wMonth - 1; ++ if (day < 1) ++ { ++ htinfo.st.wMonth = ht_month.wMonth - 1; ++ htinfo.st.wDay = MONTHCAL_MonthLength(ht_month.wMonth-1, ht_month.wYear) - day; + } - else if (day > MONTHCAL_MonthLength(ht_month.wMonth, ht_month.wYear)) { - lpht->st.wMonth = ht_month.wMonth + 1; ++ else if (day > MONTHCAL_MonthLength(ht_month.wMonth, ht_month.wYear)) ++ { ++ htinfo.st.wMonth = ht_month.wMonth + 1; ++ htinfo.st.wDay = day - MONTHCAL_MonthLength(ht_month.wMonth, ht_month.wYear); + } + else - lpht->st.wMonth = ht_month.wMonth; - - if (day < 1) { - lpht->st.wDay = MONTHCAL_MonthLength(ht_month.wMonth-1, ht_month.wYear) - day; - } - else if (day > MONTHCAL_MonthLength(ht_month.wMonth, ht_month.wYear)) { - lpht->st.wDay = day - MONTHCAL_MonthLength(ht_month.wMonth, ht_month.wYear); ++ { ++ htinfo.st.wMonth = ht_month.wMonth; ++ htinfo.st.wDay = day; + } - else - lpht->st.wDay = day; + } + else if(PtInRect(&infoPtr->calendars[calIdx].days, lpht->pt)) + { - lpht->st.wYear = ht_month.wYear; - lpht->st.wMonth = ht_month.wMonth; ++ htinfo.iOffset = calIdx; ++ htinfo.st.wYear = ht_month.wYear; ++ htinfo.st.wMonth = ht_month.wMonth; + if (day < 1) + { - lpht->uHit = MCHT_CALENDARDATEPREV; - MONTHCAL_GetPrevMonth(&lpht->st); - lpht->st.wDay = MONTHCAL_MonthLength(lpht->st.wMonth, lpht->st.wYear) + day; ++ htinfo.uHit = MCHT_CALENDARDATEPREV; ++ MONTHCAL_GetPrevMonth(&htinfo.st); ++ htinfo.st.wDay = MONTHCAL_MonthLength(lpht->st.wMonth, lpht->st.wYear) + day; + } + else if (day > MONTHCAL_MonthLength(ht_month.wMonth, ht_month.wYear)) + { - lpht->uHit = MCHT_CALENDARDATENEXT; - MONTHCAL_GetNextMonth(&lpht->st); - lpht->st.wDay = day - MONTHCAL_MonthLength(ht_month.wMonth, ht_month.wYear); ++ htinfo.uHit = MCHT_CALENDARDATENEXT; ++ MONTHCAL_GetNextMonth(&htinfo.st); ++ htinfo.st.wDay = day - MONTHCAL_MonthLength(ht_month.wMonth, ht_month.wYear); + } - else { - lpht->uHit = MCHT_CALENDARDATE; - lpht->st.wDay = day; ++ else ++ { ++ htinfo.uHit = MCHT_CALENDARDATE; ++ htinfo.st.wDay = day; + } + ++ MONTHCAL_CalcDayXY(infoPtr, &htinfo.st, &htinfo.iCol, &htinfo.iRow); ++ MONTHCAL_CalcDayRect(infoPtr, &htinfo.rc, htinfo.iCol, htinfo.iRow); + /* always update day of week */ - MONTHCAL_CalculateDayOfWeek(&lpht->st, TRUE); ++ MONTHCAL_CalculateDayOfWeek(&htinfo.st, TRUE); + } + - return lpht->uHit; ++ return fill_hittest_info(&htinfo, lpht); +} + +/* MCN_GETDAYSTATE notification helper */ +static void MONTHCAL_NotifyDayState(MONTHCAL_INFO *infoPtr) +{ + if(infoPtr->dwStyle & MCS_DAYSTATE) { + NMDAYSTATE nmds; + + nmds.nmhdr.hwndFrom = infoPtr->hwndSelf; + nmds.nmhdr.idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID); + nmds.nmhdr.code = MCN_GETDAYSTATE; + nmds.cDayState = infoPtr->monthRange; + nmds.prgDayState = Alloc(infoPtr->monthRange * sizeof(MONTHDAYSTATE)); + + nmds.stStart = infoPtr->todaysDate; - nmds.stStart.wYear = infoPtr->curSel.wYear; - nmds.stStart.wMonth = infoPtr->curSel.wMonth; ++ nmds.stStart.wYear = infoPtr->minSel.wYear; ++ nmds.stStart.wMonth = infoPtr->minSel.wMonth; + nmds.stStart.wDay = 1; + + SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, nmds.nmhdr.idFrom, (LPARAM)&nmds); + memcpy(infoPtr->monthdayState, nmds.prgDayState, infoPtr->monthRange*sizeof(MONTHDAYSTATE)); + + Free(nmds.prgDayState); + } +} + - static void MONTHCAL_GoToPrevNextMonth(MONTHCAL_INFO *infoPtr, BOOL prev) ++/* no valid range check performed */ ++static void MONTHCAL_Scroll(MONTHCAL_INFO *infoPtr, INT delta) +{ - SYSTEMTIME st = infoPtr->curSel; ++ INT i, selIdx = -1; + - TRACE("%s\n", prev ? "prev" : "next"); - - if(prev) MONTHCAL_GetPrevMonth(&st); else MONTHCAL_GetNextMonth(&st); ++ for(i = 0; i < infoPtr->cal_num; i++) ++ { ++ /* save selection position to shift it later */ ++ if (selIdx == -1 && MONTHCAL_CompareMonths(&infoPtr->minSel, &infoPtr->calendars[i].month) == 0) ++ selIdx = i; + - if(!MONTHCAL_IsDateInValidRange(infoPtr, &st, FALSE)) return; ++ MONTHCAL_GetMonth(&infoPtr->calendars[i].month, delta); ++ } + ++ /* selection is always shifted to first calendar */ + if(infoPtr->dwStyle & MCS_MULTISELECT) + { + SYSTEMTIME range[2]; + - range[0] = infoPtr->minSel; - range[1] = infoPtr->maxSel; - - if(prev) - { - MONTHCAL_GetPrevMonth(&range[0]); - MONTHCAL_GetPrevMonth(&range[1]); - } - else - { - MONTHCAL_GetNextMonth(&range[0]); - MONTHCAL_GetNextMonth(&range[1]); - } - ++ MONTHCAL_GetSelRange(infoPtr, range); ++ MONTHCAL_GetMonth(&range[0], delta - selIdx); ++ MONTHCAL_GetMonth(&range[1], delta - selIdx); + MONTHCAL_SetSelRange(infoPtr, range); + } + else ++ { ++ SYSTEMTIME st = infoPtr->minSel; ++ ++ MONTHCAL_GetMonth(&st, delta - selIdx); + MONTHCAL_SetCurSel(infoPtr, &st); ++ } ++} + - MONTHCAL_NotifyDayState(infoPtr); ++static void MONTHCAL_GoToMonth(MONTHCAL_INFO *infoPtr, enum nav_direction direction) ++{ ++ INT delta = infoPtr->delta ? infoPtr->delta : infoPtr->cal_num; ++ SYSTEMTIME st; ++ ++ TRACE("%s\n", direction == DIRECTION_BACKWARD ? "back" : "fwd"); + ++ /* check if change allowed by range set */ ++ if(direction == DIRECTION_BACKWARD) ++ { ++ st = infoPtr->calendars[0].month; ++ MONTHCAL_GetMonth(&st, -delta); ++ } ++ else ++ { ++ st = infoPtr->calendars[infoPtr->cal_num-1].month; ++ MONTHCAL_GetMonth(&st, delta); ++ } ++ ++ if(!MONTHCAL_IsDateInValidRange(infoPtr, &st, FALSE)) return; ++ ++ MONTHCAL_Scroll(infoPtr, direction == DIRECTION_BACKWARD ? -delta : delta); ++ MONTHCAL_NotifyDayState(infoPtr); + MONTHCAL_NotifySelectionChange(infoPtr); +} + +static LRESULT +MONTHCAL_RButtonUp(MONTHCAL_INFO *infoPtr, LPARAM lParam) +{ + static const WCHAR todayW[] = { 'G','o',' ','t','o',' ','T','o','d','a','y',':',0 }; + HMENU hMenu; + POINT menupoint; + WCHAR buf[32]; + + hMenu = CreatePopupMenu(); + if (!LoadStringW(COMCTL32_hModule, IDM_GOTODAY, buf, countof(buf))) + { + WARN("Can't load resource\n"); + strcpyW(buf, todayW); + } + AppendMenuW(hMenu, MF_STRING|MF_ENABLED, 1, buf); + menupoint.x = (short)LOWORD(lParam); + menupoint.y = (short)HIWORD(lParam); + ClientToScreen(infoPtr->hwndSelf, &menupoint); + if( TrackPopupMenu(hMenu, TPM_RIGHTBUTTON | TPM_NONOTIFY | TPM_RETURNCMD, + menupoint.x, menupoint.y, 0, infoPtr->hwndSelf, NULL)) + { - infoPtr->curSel = infoPtr->todaysDate; + infoPtr->calendars[0].month = infoPtr->todaysDate; + infoPtr->minSel = infoPtr->todaysDate; + infoPtr->maxSel = infoPtr->todaysDate; + InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); + } + + return 0; +} + +/*** + * DESCRIPTION: + * Subclassed edit control windproc function + * + * PARAMETER(S): + * [I] hwnd : the edit window handle + * [I] uMsg : the message that is to be processed + * [I] wParam : first message parameter + * [I] lParam : second message parameter + * + */ +static LRESULT CALLBACK EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + MONTHCAL_INFO *infoPtr = (MONTHCAL_INFO *)GetWindowLongPtrW(GetParent(hwnd), 0); + + TRACE("(hwnd=%p, uMsg=%x, wParam=%lx, lParam=%lx)\n", + hwnd, uMsg, wParam, lParam); + + switch (uMsg) + { + case WM_GETDLGCODE: + return DLGC_WANTARROWS | DLGC_WANTALLKEYS; + + case WM_DESTROY: + { + WNDPROC editProc = infoPtr->EditWndProc; + infoPtr->EditWndProc = NULL; + SetWindowLongPtrW(hwnd, GWLP_WNDPROC, (DWORD_PTR)editProc); + return CallWindowProcW(editProc, hwnd, uMsg, wParam, lParam); + } + + case WM_KILLFOCUS: + break; + + case WM_KEYDOWN: + if ((VK_ESCAPE == (INT)wParam) || (VK_RETURN == (INT)wParam)) + break; + + default: + return CallWindowProcW(infoPtr->EditWndProc, hwnd, uMsg, wParam, lParam); + } + + SendMessageW(infoPtr->hWndYearUpDown, WM_CLOSE, 0, 0); + SendMessageW(hwnd, WM_CLOSE, 0, 0); + return 0; +} + +/* creates updown control and edit box */ - static void MONTHCAL_EditYear(MONTHCAL_INFO *infoPtr) ++static void MONTHCAL_EditYear(MONTHCAL_INFO *infoPtr, INT calIdx) +{ ++ RECT *rc = &infoPtr->calendars[calIdx].titleyear; ++ RECT *title = &infoPtr->calendars[calIdx].title; ++ + infoPtr->hWndYearEdit = + CreateWindowExW(0, WC_EDITW, 0, WS_VISIBLE | WS_CHILD | ES_READONLY, - infoPtr->calendars[0].titleyear.left + 3, infoPtr->titlebtnnext.top, - infoPtr->calendars[0].titleyear.right - infoPtr->calendars[0].titleyear.left + 4, ++ rc->left + 3, (title->bottom + title->top - infoPtr->textHeight) / 2, ++ rc->right - rc->left + 4, + infoPtr->textHeight, infoPtr->hwndSelf, + NULL, NULL, NULL); + + SendMessageW(infoPtr->hWndYearEdit, WM_SETFONT, (WPARAM)infoPtr->hBoldFont, TRUE); + + infoPtr->hWndYearUpDown = + CreateWindowExW(0, UPDOWN_CLASSW, 0, + WS_VISIBLE | WS_CHILD | UDS_SETBUDDYINT | UDS_NOTHOUSANDS | UDS_ARROWKEYS, - infoPtr->calendars[0].titleyear.right + 7, infoPtr->titlebtnnext.top, ++ rc->right + 7, (title->bottom + title->top - infoPtr->textHeight) / 2, + 18, infoPtr->textHeight, infoPtr->hwndSelf, + NULL, NULL, NULL); + + /* attach edit box */ + SendMessageW(infoPtr->hWndYearUpDown, UDM_SETRANGE, 0, + MAKELONG(max_allowed_date.wYear, min_allowed_date.wYear)); + SendMessageW(infoPtr->hWndYearUpDown, UDM_SETBUDDY, (WPARAM)infoPtr->hWndYearEdit, 0); - SendMessageW(infoPtr->hWndYearUpDown, UDM_SETPOS, 0, infoPtr->curSel.wYear); ++ SendMessageW(infoPtr->hWndYearUpDown, UDM_SETPOS, 0, infoPtr->calendars[calIdx].month.wYear); + + /* subclass edit box */ + infoPtr->EditWndProc = (WNDPROC)SetWindowLongPtrW(infoPtr->hWndYearEdit, + GWLP_WNDPROC, (DWORD_PTR)EditWndProc); + + SetFocus(infoPtr->hWndYearEdit); +} + +static LRESULT +MONTHCAL_LButtonDown(MONTHCAL_INFO *infoPtr, LPARAM lParam) +{ + MCHITTESTINFO ht; + DWORD hit; + + /* Actually we don't need input focus for calendar, this is used to kill + year updown and its buddy edit box */ + if (IsWindow(infoPtr->hWndYearUpDown)) + { + SetFocus(infoPtr->hwndSelf); + return 0; + } + + SetCapture(infoPtr->hwndSelf); + + ht.cbSize = sizeof(MCHITTESTINFO); + ht.pt.x = (short)LOWORD(lParam); + ht.pt.y = (short)HIWORD(lParam); + + hit = MONTHCAL_HitTest(infoPtr, &ht); + + TRACE("%x at (%d, %d)\n", hit, ht.pt.x, ht.pt.y); + + switch(hit) + { + case MCHT_TITLEBTNNEXT: - MONTHCAL_GoToPrevNextMonth(infoPtr, FALSE); ++ MONTHCAL_GoToMonth(infoPtr, DIRECTION_FORWARD); + infoPtr->status = MC_NEXTPRESSED; + SetTimer(infoPtr->hwndSelf, MC_PREVNEXTMONTHTIMER, MC_PREVNEXTMONTHDELAY, 0); + InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); + return 0; + + case MCHT_TITLEBTNPREV: - MONTHCAL_GoToPrevNextMonth(infoPtr, TRUE); ++ MONTHCAL_GoToMonth(infoPtr, DIRECTION_BACKWARD); + infoPtr->status = MC_PREVPRESSED; + SetTimer(infoPtr->hwndSelf, MC_PREVNEXTMONTHTIMER, MC_PREVNEXTMONTHDELAY, 0); + InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); + return 0; + + case MCHT_TITLEMONTH: + { + HMENU hMenu = CreatePopupMenu(); + WCHAR buf[32]; + POINT menupoint; + INT i; + + for (i = 0; i < 12; i++) + { + GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SMONTHNAME1+i, buf, countof(buf)); + AppendMenuW(hMenu, MF_STRING|MF_ENABLED, i + 1, buf); + } + menupoint.x = ht.pt.x; + menupoint.y = ht.pt.y; + ClientToScreen(infoPtr->hwndSelf, &menupoint); + i = TrackPopupMenu(hMenu,TPM_LEFTALIGN | TPM_NONOTIFY | TPM_RIGHTBUTTON | TPM_RETURNCMD, + menupoint.x, menupoint.y, 0, infoPtr->hwndSelf, NULL); + - if ((i > 0) && (i < 13) && infoPtr->curSel.wMonth != i) ++ if ((i > 0) && (i < 13) && infoPtr->calendars[ht.iOffset].month.wMonth != i) + { - infoPtr->curSel.wMonth = i; - MONTHCAL_IsDateInValidRange(infoPtr, &infoPtr->curSel, TRUE); - InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); ++ INT delta = i - infoPtr->calendars[ht.iOffset].month.wMonth; ++ SYSTEMTIME st; ++ ++ /* check if change allowed by range set */ ++ st = delta < 0 ? infoPtr->calendars[0].month : ++ infoPtr->calendars[infoPtr->cal_num-1].month; ++ MONTHCAL_GetMonth(&st, delta); ++ ++ if (MONTHCAL_IsDateInValidRange(infoPtr, &st, FALSE)) ++ { ++ MONTHCAL_Scroll(infoPtr, delta); ++ MONTHCAL_NotifyDayState(infoPtr); ++ MONTHCAL_NotifySelectionChange(infoPtr); ++ InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); ++ } + } + return 0; + } + case MCHT_TITLEYEAR: + { - MONTHCAL_EditYear(infoPtr); ++ MONTHCAL_EditYear(infoPtr, ht.iOffset); + return 0; + } + case MCHT_TODAYLINK: + { - infoPtr->curSel = infoPtr->todaysDate; + infoPtr->calendars[0].month = infoPtr->todaysDate; + infoPtr->minSel = infoPtr->todaysDate; + infoPtr->maxSel = infoPtr->todaysDate; + InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); + + MONTHCAL_NotifySelectionChange(infoPtr); + MONTHCAL_NotifySelect(infoPtr); + return 0; + } + case MCHT_CALENDARDATENEXT: + case MCHT_CALENDARDATEPREV: + case MCHT_CALENDARDATE: + { + SYSTEMTIME st[2]; + + MONTHCAL_CopyDate(&ht.st, &infoPtr->firstSel); + + st[0] = st[1] = ht.st; + /* clear selection range */ + MONTHCAL_SetSelRange(infoPtr, st); + + infoPtr->status = MC_SEL_LBUTDOWN; + MONTHCAL_SetDayFocus(infoPtr, &ht.st); + return 0; + } + } + + return 1; +} + + +static LRESULT +MONTHCAL_LButtonUp(MONTHCAL_INFO *infoPtr, LPARAM lParam) +{ + NMHDR nmhdr; + MCHITTESTINFO ht; + DWORD hit; + + TRACE("\n"); + + if(infoPtr->status & (MC_PREVPRESSED | MC_NEXTPRESSED)) { + RECT *r; + + KillTimer(infoPtr->hwndSelf, MC_PREVNEXTMONTHTIMER); + r = infoPtr->status & MC_PREVPRESSED ? &infoPtr->titlebtnprev : &infoPtr->titlebtnnext; + infoPtr->status &= ~(MC_PREVPRESSED | MC_NEXTPRESSED); + + InvalidateRect(infoPtr->hwndSelf, r, FALSE); + } + + ReleaseCapture(); + + /* always send NM_RELEASEDCAPTURE notification */ + nmhdr.hwndFrom = infoPtr->hwndSelf; + nmhdr.idFrom = GetWindowLongPtrW(infoPtr->hwndSelf, GWLP_ID); + nmhdr.code = NM_RELEASEDCAPTURE; + TRACE("Sent notification from %p to %p\n", infoPtr->hwndSelf, infoPtr->hwndNotify); + + SendMessageW(infoPtr->hwndNotify, WM_NOTIFY, nmhdr.idFrom, (LPARAM)&nmhdr); + + if(!(infoPtr->status & MC_SEL_LBUTDOWN)) return 0; + + ht.cbSize = sizeof(MCHITTESTINFO); + ht.pt.x = (short)LOWORD(lParam); + ht.pt.y = (short)HIWORD(lParam); + hit = MONTHCAL_HitTest(infoPtr, &ht); + + infoPtr->status = MC_SEL_LBUTUP; + MONTHCAL_SetDayFocus(infoPtr, NULL); + + if((hit & MCHT_CALENDARDATE) == MCHT_CALENDARDATE) + { - SYSTEMTIME sel = infoPtr->curSel; ++ SYSTEMTIME sel = infoPtr->minSel; + + /* will be invalidated here */ + MONTHCAL_SetCurSel(infoPtr, &ht.st); + + /* send MCN_SELCHANGE only if new date selected */ + if (!MONTHCAL_IsDateEqual(&sel, &ht.st)) + MONTHCAL_NotifySelectionChange(infoPtr); + + MONTHCAL_NotifySelect(infoPtr); + } + + return 0; +} + + +static LRESULT +MONTHCAL_Timer(MONTHCAL_INFO *infoPtr, WPARAM id) +{ + TRACE("%ld\n", id); + + switch(id) { + case MC_PREVNEXTMONTHTIMER: - if(infoPtr->status & MC_NEXTPRESSED) MONTHCAL_GoToPrevNextMonth(infoPtr, FALSE); - if(infoPtr->status & MC_PREVPRESSED) MONTHCAL_GoToPrevNextMonth(infoPtr, TRUE); ++ if(infoPtr->status & MC_NEXTPRESSED) MONTHCAL_GoToMonth(infoPtr, DIRECTION_FORWARD); ++ if(infoPtr->status & MC_PREVPRESSED) MONTHCAL_GoToMonth(infoPtr, DIRECTION_BACKWARD); + InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); + break; + case MC_TODAYUPDATETIMER: + { + SYSTEMTIME st; + + if(infoPtr->todaySet) return 0; + + GetLocalTime(&st); + MONTHCAL_UpdateToday(infoPtr, &st); + + /* notification sent anyway */ + MONTHCAL_NotifySelectionChange(infoPtr); + + return 0; + } + default: + ERR("got unknown timer %ld\n", id); + break; + } + + return 0; +} + + +static LRESULT +MONTHCAL_MouseMove(MONTHCAL_INFO *infoPtr, LPARAM lParam) +{ + MCHITTESTINFO ht; + SYSTEMTIME st_ht; + INT hit; + RECT r; + + if(!(infoPtr->status & MC_SEL_LBUTDOWN)) return 0; + + ht.cbSize = sizeof(MCHITTESTINFO); + ht.pt.x = (short)LOWORD(lParam); + ht.pt.y = (short)HIWORD(lParam); + + hit = MONTHCAL_HitTest(infoPtr, &ht); + + /* not on the calendar date numbers? bail out */ + TRACE("hit:%x\n",hit); + if((hit & MCHT_CALENDARDATE) != MCHT_CALENDARDATE) + { + MONTHCAL_SetDayFocus(infoPtr, NULL); + return 0; + } + + st_ht = ht.st; + + /* if pointer is over focused day still there's nothing to do */ + if(!MONTHCAL_SetDayFocus(infoPtr, &ht.st)) return 0; + + MONTHCAL_CalcPosFromDay(infoPtr, &ht.st, &r); + + if(infoPtr->dwStyle & MCS_MULTISELECT) { + SYSTEMTIME st[2]; + + MONTHCAL_GetSelRange(infoPtr, st); + + /* If we're still at the first selected date and range is empty, return. + If range isn't empty we should change range to a single firstSel */ + if(MONTHCAL_IsDateEqual(&infoPtr->firstSel, &st_ht) && + MONTHCAL_IsDateEqual(&st[0], &st[1])) goto done; + + MONTHCAL_IsSelRangeValid(infoPtr, &st_ht, &infoPtr->firstSel, &st_ht); + + st[0] = infoPtr->firstSel; + /* we should overwrite timestamp here */ + MONTHCAL_CopyDate(&st_ht, &st[1]); + + /* bounds will be swapped here if needed */ + MONTHCAL_SetSelRange(infoPtr, st); + + return 0; + } + +done: + + /* FIXME: this should specify a rectangle containing only the days that changed + using InvalidateRect */ + InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); + + return 0; +} + + +static LRESULT +MONTHCAL_Paint(MONTHCAL_INFO *infoPtr, HDC hdc_paint) +{ + HDC hdc; + PAINTSTRUCT ps; + + if (hdc_paint) + { + GetClientRect(infoPtr->hwndSelf, &ps.rcPaint); + hdc = hdc_paint; + } + else + hdc = BeginPaint(infoPtr->hwndSelf, &ps); + + MONTHCAL_Refresh(infoPtr, hdc, &ps); + if (!hdc_paint) EndPaint(infoPtr->hwndSelf, &ps); + return 0; +} + +static LRESULT +MONTHCAL_EraseBkgnd(const MONTHCAL_INFO *infoPtr, HDC hdc) +{ + HBRUSH hbr; + RECT rc; + + if (!GetClipBox(hdc, &rc)) return FALSE; + + /* fill background */ - hbr = CreateSolidBrush (infoPtr->bk); ++ hbr = CreateSolidBrush (infoPtr->colors[MCSC_BACKGROUND]); + FillRect(hdc, &rc, hbr); + DeleteObject(hbr); + + return TRUE; +} + +static LRESULT +MONTHCAL_PrintClient(MONTHCAL_INFO *infoPtr, HDC hdc, DWORD options) +{ + FIXME("Partial Stub: (hdc=%p options=0x%08x)\n", hdc, options); + + if ((options & PRF_CHECKVISIBLE) && !IsWindowVisible(infoPtr->hwndSelf)) + return 0; + + if (options & PRF_ERASEBKGND) + MONTHCAL_EraseBkgnd(infoPtr, hdc); + + if (options & PRF_CLIENT) + MONTHCAL_Paint(infoPtr, hdc); + + return 0; +} + +static LRESULT +MONTHCAL_SetFocus(const MONTHCAL_INFO *infoPtr) +{ + TRACE("\n"); + + InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); + + return 0; +} + +/* sets the size information */ +static void MONTHCAL_UpdateSize(MONTHCAL_INFO *infoPtr) +{ + static const WCHAR O0W[] = { '0','0',0 }; + HDC hdc = GetDC(infoPtr->hwndSelf); + RECT *title=&infoPtr->calendars[0].title; + RECT *prev=&infoPtr->titlebtnprev; + RECT *next=&infoPtr->titlebtnnext; + RECT *titlemonth=&infoPtr->calendars[0].titlemonth; + RECT *titleyear=&infoPtr->calendars[0].titleyear; + RECT *wdays=&infoPtr->calendars[0].wdays; + RECT *weeknumrect=&infoPtr->calendars[0].weeknums; + RECT *days=&infoPtr->calendars[0].days; + RECT *todayrect=&infoPtr->todayrect; + SIZE size, sz; + TEXTMETRICW tm; + HFONT currentFont; + INT xdiv, dx, dy, i; + RECT rcClient; + WCHAR buff[80]; + + GetClientRect(infoPtr->hwndSelf, &rcClient); + + currentFont = SelectObject(hdc, infoPtr->hFont); + + /* get the height and width of each day's text */ + GetTextMetricsW(hdc, &tm); + infoPtr->textHeight = tm.tmHeight + tm.tmExternalLeading + tm.tmInternalLeading; + + /* find largest abbreviated day name for current locale */ + size.cx = sz.cx = 0; + for (i = 0; i < 7; i++) + { + if(GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SABBREVDAYNAME1 + i, + buff, countof(buff))) + { + GetTextExtentPoint32W(hdc, buff, lstrlenW(buff), &sz); + if (sz.cx > size.cx) size.cx = sz.cx; + } + else /* locale independent fallback on failure */ + { + static const WCHAR SunW[] = { 'S','u','n',0 }; + + GetTextExtentPoint32W(hdc, SunW, lstrlenW(SunW), &size); + break; + } + } + + infoPtr->textWidth = size.cx + 2; + + /* recalculate the height and width increments and offsets */ + GetTextExtentPoint32W(hdc, O0W, 2, &size); + + xdiv = (infoPtr->dwStyle & MCS_WEEKNUMBERS) ? 8 : 7; + + infoPtr->width_increment = size.cx * 2 + 4; + infoPtr->height_increment = infoPtr->textHeight; + + /* calculate title area */ + title->top = 0; + title->bottom = 3 * infoPtr->height_increment / 2; + title->left = 0; + title->right = infoPtr->width_increment * xdiv; + + /* set the dimensions of the next and previous buttons and center */ + /* the month text vertically */ + prev->top = next->top = title->top + 4; + prev->bottom = next->bottom = title->bottom - 4; + prev->left = title->left + 4; + prev->right = prev->left + (title->bottom - title->top); + next->right = title->right - 4; + next->left = next->right - (title->bottom - title->top); + + /* titlemonth->left and right change based upon the current month */ + /* and are recalculated in refresh as the current month may change */ + /* without the control being resized */ + titlemonth->top = titleyear->top = title->top + (infoPtr->height_increment)/2; + titlemonth->bottom = titleyear->bottom = title->bottom - (infoPtr->height_increment)/2; + + /* setup the dimensions of the rectangle we draw the names of the */ + /* days of the week in */ + weeknumrect->left = 0; + + if(infoPtr->dwStyle & MCS_WEEKNUMBERS) + weeknumrect->right = prev->right; + else + weeknumrect->right = weeknumrect->left; + + wdays->left = days->left = weeknumrect->right; + wdays->right = days->right = wdays->left + 7 * infoPtr->width_increment; + wdays->top = title->bottom; + wdays->bottom = wdays->top + infoPtr->height_increment; + + days->top = weeknumrect->top = wdays->bottom; + days->bottom = weeknumrect->bottom = days->top + 6 * infoPtr->height_increment; + + todayrect->left = 0; + todayrect->right = title->right; + todayrect->top = days->bottom; + todayrect->bottom = days->bottom + infoPtr->height_increment; + + /* offset all rectangles to center in client area */ + dx = (rcClient.right - title->right) / 2; + dy = (rcClient.bottom - todayrect->bottom) / 2; + + /* if calendar doesn't fit client area show it at left/top bounds */ + if (title->left + dx < 0) dx = 0; + if (title->top + dy < 0) dy = 0; + + if (dx != 0 || dy != 0) + { + OffsetRect(title, dx, dy); + OffsetRect(prev, dx, dy); + OffsetRect(next, dx, dy); + OffsetRect(titlemonth, dx, dy); + OffsetRect(titleyear, dx, dy); + OffsetRect(wdays, dx, dy); + OffsetRect(weeknumrect, dx, dy); + OffsetRect(days, dx, dy); + OffsetRect(todayrect, dx, dy); + } + + TRACE("dx=%d dy=%d client[%s] title[%s] wdays[%s] days[%s] today[%s]\n", + infoPtr->width_increment,infoPtr->height_increment, + wine_dbgstr_rect(&rcClient), + wine_dbgstr_rect(title), + wine_dbgstr_rect(wdays), + wine_dbgstr_rect(days), + wine_dbgstr_rect(todayrect)); + + /* restore the originally selected font */ + SelectObject(hdc, currentFont); + + ReleaseDC(infoPtr->hwndSelf, hdc); +} + +static LRESULT MONTHCAL_Size(MONTHCAL_INFO *infoPtr, int Width, int Height) +{ + TRACE("(width=%d, height=%d)\n", Width, Height); + + MONTHCAL_UpdateSize(infoPtr); - - /* invalidate client area and erase background */ + InvalidateRect(infoPtr->hwndSelf, NULL, TRUE); + + return 0; +} + +static LRESULT MONTHCAL_GetFont(const MONTHCAL_INFO *infoPtr) +{ + return (LRESULT)infoPtr->hFont; +} + +static LRESULT MONTHCAL_SetFont(MONTHCAL_INFO *infoPtr, HFONT hFont, BOOL redraw) +{ + HFONT hOldFont; + LOGFONTW lf; + + if (!hFont) return 0; + + hOldFont = infoPtr->hFont; + infoPtr->hFont = hFont; + + GetObjectW(infoPtr->hFont, sizeof(lf), &lf); + lf.lfWeight = FW_BOLD; + infoPtr->hBoldFont = CreateFontIndirectW(&lf); + + MONTHCAL_UpdateSize(infoPtr); + + if (redraw) + InvalidateRect(infoPtr->hwndSelf, NULL, FALSE); + + return (LRESULT)hOldFont; +} + +/* update theme after a WM_THEMECHANGED message */ +static LRESULT theme_changed (const MONTHCAL_INFO* infoPtr) +{ + HTHEME theme = GetWindowTheme (infoPtr->hwndSelf); + CloseThemeData (theme); + OpenThemeData (infoPtr->hwndSelf, themeClass); + return 0; +} + +static INT MONTHCAL_StyleChanged(MONTHCAL_INFO *infoPtr, WPARAM wStyleType, + const STYLESTRUCT *lpss) +{ + TRACE("(styletype=%lx, styleOld=0x%08x, styleNew=0x%08x)\n", + wStyleType, lpss->styleOld, lpss->styleNew); + + if (wStyleType != GWL_STYLE) return 0; + + infoPtr->dwStyle = lpss->styleNew; + + /* make room for week numbers */ + if ((lpss->styleNew ^ lpss->styleOld) & MCS_WEEKNUMBERS) + MONTHCAL_UpdateSize(infoPtr); + + return 0; +} + +static INT MONTHCAL_StyleChanging(MONTHCAL_INFO *infoPtr, WPARAM wStyleType, + STYLESTRUCT *lpss) +{ + TRACE("(styletype=%lx, styleOld=0x%08x, styleNew=0x%08x)\n", + wStyleType, lpss->styleOld, lpss->styleNew); + + /* block MCS_MULTISELECT change */ + if ((lpss->styleNew ^ lpss->styleOld) & MCS_MULTISELECT) + { + if (lpss->styleOld & MCS_MULTISELECT) + lpss->styleNew |= MCS_MULTISELECT; + else + lpss->styleNew &= ~MCS_MULTISELECT; + } + + return 0; +} + +/* FIXME: check whether dateMin/dateMax need to be adjusted. */ +static LRESULT +MONTHCAL_Create(HWND hwnd, LPCREATESTRUCTW lpcs) +{ + MONTHCAL_INFO *infoPtr; + + /* allocate memory for info structure */ + infoPtr = Alloc(sizeof(MONTHCAL_INFO)); + SetWindowLongPtrW(hwnd, 0, (DWORD_PTR)infoPtr); + + if (infoPtr == NULL) { + ERR("could not allocate info memory!\n"); + return 0; + } + + infoPtr->hwndSelf = hwnd; + infoPtr->hwndNotify = lpcs->hwndParent; + infoPtr->dwStyle = GetWindowLongW(hwnd, GWL_STYLE); + infoPtr->calendars = Alloc(sizeof(CALENDAR_INFO)); + if (!infoPtr->calendars) goto fail; + + infoPtr->cal_num = 1; + + MONTHCAL_SetFont(infoPtr, GetStockObject(DEFAULT_GUI_FONT), FALSE); + + /* initialize info structure */ + /* FIXME: calculate systemtime ->> localtime(substract timezoneinfo) */ + + GetLocalTime(&infoPtr->todaysDate); + MONTHCAL_SetFirstDayOfWeek(infoPtr, -1); + + infoPtr->maxSelCount = (infoPtr->dwStyle & MCS_MULTISELECT) ? 7 : 1; + infoPtr->monthRange = 3; + + infoPtr->monthdayState = Alloc(infoPtr->monthRange * sizeof(MONTHDAYSTATE)); + if (!infoPtr->monthdayState) goto fail; + - infoPtr->titlebk = comctl32_color.clrActiveCaption; - infoPtr->titletxt = comctl32_color.clrWindow; - infoPtr->monthbk = comctl32_color.clrWindow; - infoPtr->trailingtxt = comctl32_color.clrGrayText; - infoPtr->bk = comctl32_color.clrWindow; - infoPtr->txt = comctl32_color.clrWindowText; ++ infoPtr->colors[MCSC_BACKGROUND] = comctl32_color.clrWindow; ++ infoPtr->colors[MCSC_TEXT] = comctl32_color.clrWindowText; ++ infoPtr->colors[MCSC_TITLEBK] = comctl32_color.clrActiveCaption; ++ infoPtr->colors[MCSC_TITLETEXT] = comctl32_color.clrWindow; ++ infoPtr->colors[MCSC_MONTHBK] = comctl32_color.clrWindow; ++ infoPtr->colors[MCSC_TRAILINGTEXT] = comctl32_color.clrGrayText; + + infoPtr->minSel = infoPtr->todaysDate; + infoPtr->maxSel = infoPtr->todaysDate; - infoPtr->curSel = infoPtr->todaysDate; + infoPtr->calendars[0].month = infoPtr->todaysDate; + infoPtr->isUnicode = TRUE; + + /* call MONTHCAL_UpdateSize to set all of the dimensions */ + /* of the control */ + MONTHCAL_UpdateSize(infoPtr); + + /* today auto update timer, to be freed only on control destruction */ + SetTimer(infoPtr->hwndSelf, MC_TODAYUPDATETIMER, MC_TODAYUPDATEDELAY, 0); + + OpenThemeData (infoPtr->hwndSelf, themeClass); + + return 0; + +fail: + Free(infoPtr->monthdayState); + Free(infoPtr->calendars); + Free(infoPtr); + return 0; +} + +static LRESULT +MONTHCAL_Destroy(MONTHCAL_INFO *infoPtr) +{ + /* free month calendar info data */ + Free(infoPtr->monthdayState); + Free(infoPtr->calendars); + SetWindowLongPtrW(infoPtr->hwndSelf, 0, 0); + + CloseThemeData (GetWindowTheme (infoPtr->hwndSelf)); + + Free(infoPtr); + return 0; +} + +/* + * Handler for WM_NOTIFY messages + */ +static LRESULT +MONTHCAL_Notify(MONTHCAL_INFO *infoPtr, NMHDR *hdr) +{ + /* notification from year edit updown */ + if (hdr->code == UDN_DELTAPOS) + { + NMUPDOWN *nmud = (NMUPDOWN*)hdr; + - if (hdr->hwndFrom == infoPtr->hWndYearUpDown) ++ if (hdr->hwndFrom == infoPtr->hWndYearUpDown && nmud->iDelta) + { + /* year value limits are set up explicitly after updown creation */ - if ((nmud->iDelta + nmud->iPos) != infoPtr->curSel.wYear) - { - SYSTEMTIME new_date = infoPtr->curSel; - - new_date.wYear = nmud->iDelta + nmud->iPos; - MONTHCAL_SetCurSel(infoPtr, &new_date); - } ++ MONTHCAL_Scroll(infoPtr, 12 * nmud->iDelta); ++ MONTHCAL_NotifyDayState(infoPtr); ++ MONTHCAL_NotifySelectionChange(infoPtr); + } + } + return 0; +} + +static inline BOOL +MONTHCAL_SetUnicodeFormat(MONTHCAL_INFO *infoPtr, BOOL isUnicode) +{ + BOOL prev = infoPtr->isUnicode; + infoPtr->isUnicode = isUnicode; + return prev; +} + +static inline BOOL +MONTHCAL_GetUnicodeFormat(const MONTHCAL_INFO *infoPtr) +{ + return infoPtr->isUnicode; +} + +static LRESULT WINAPI +MONTHCAL_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ - MONTHCAL_INFO *infoPtr; ++ MONTHCAL_INFO *infoPtr = (MONTHCAL_INFO *)GetWindowLongPtrW(hwnd, 0); + + TRACE("hwnd=%p msg=%x wparam=%lx lparam=%lx\n", hwnd, uMsg, wParam, lParam); + - infoPtr = MONTHCAL_GetInfoPtr(hwnd); + if (!infoPtr && (uMsg != WM_CREATE)) + return DefWindowProcW(hwnd, uMsg, wParam, lParam); + switch(uMsg) + { + case MCM_GETCURSEL: + return MONTHCAL_GetCurSel(infoPtr, (LPSYSTEMTIME)lParam); + + case MCM_SETCURSEL: + return MONTHCAL_SetCurSel(infoPtr, (LPSYSTEMTIME)lParam); + + case MCM_GETMAXSELCOUNT: + return MONTHCAL_GetMaxSelCount(infoPtr); + + case MCM_SETMAXSELCOUNT: + return MONTHCAL_SetMaxSelCount(infoPtr, wParam); + + case MCM_GETSELRANGE: + return MONTHCAL_GetSelRange(infoPtr, (LPSYSTEMTIME)lParam); + + case MCM_SETSELRANGE: + return MONTHCAL_SetSelRange(infoPtr, (LPSYSTEMTIME)lParam); + + case MCM_GETMONTHRANGE: + return MONTHCAL_GetMonthRange(infoPtr, wParam, (SYSTEMTIME*)lParam); + + case MCM_SETDAYSTATE: + return MONTHCAL_SetDayState(infoPtr, (INT)wParam, (LPMONTHDAYSTATE)lParam); + + case MCM_GETMINREQRECT: + return MONTHCAL_GetMinReqRect(infoPtr, (LPRECT)lParam); + + case MCM_GETCOLOR: + return MONTHCAL_GetColor(infoPtr, wParam); + + case MCM_SETCOLOR: + return MONTHCAL_SetColor(infoPtr, wParam, (COLORREF)lParam); + + case MCM_GETTODAY: + return MONTHCAL_GetToday(infoPtr, (LPSYSTEMTIME)lParam); + + case MCM_SETTODAY: + return MONTHCAL_SetToday(infoPtr, (LPSYSTEMTIME)lParam); + + case MCM_HITTEST: + return MONTHCAL_HitTest(infoPtr, (PMCHITTESTINFO)lParam); + + case MCM_GETFIRSTDAYOFWEEK: + return MONTHCAL_GetFirstDayOfWeek(infoPtr); + + case MCM_SETFIRSTDAYOFWEEK: + return MONTHCAL_SetFirstDayOfWeek(infoPtr, (INT)lParam); + + case MCM_GETRANGE: + return MONTHCAL_GetRange(infoPtr, (LPSYSTEMTIME)lParam); + + case MCM_SETRANGE: + return MONTHCAL_SetRange(infoPtr, (SHORT)wParam, (LPSYSTEMTIME)lParam); + + case MCM_GETMONTHDELTA: + return MONTHCAL_GetMonthDelta(infoPtr); + + case MCM_SETMONTHDELTA: + return MONTHCAL_SetMonthDelta(infoPtr, wParam); + + case MCM_GETMAXTODAYWIDTH: + return MONTHCAL_GetMaxTodayWidth(infoPtr); + + case MCM_SETUNICODEFORMAT: + return MONTHCAL_SetUnicodeFormat(infoPtr, (BOOL)wParam); + + case MCM_GETUNICODEFORMAT: + return MONTHCAL_GetUnicodeFormat(infoPtr); + + case WM_GETDLGCODE: + return DLGC_WANTARROWS | DLGC_WANTCHARS; + + case WM_RBUTTONUP: + return MONTHCAL_RButtonUp(infoPtr, lParam); + + case WM_LBUTTONDOWN: + return MONTHCAL_LButtonDown(infoPtr, lParam); + + case WM_MOUSEMOVE: + return MONTHCAL_MouseMove(infoPtr, lParam); + + case WM_LBUTTONUP: + return MONTHCAL_LButtonUp(infoPtr, lParam); + + case WM_PAINT: + return MONTHCAL_Paint(infoPtr, (HDC)wParam); + + case WM_PRINTCLIENT: + return MONTHCAL_PrintClient(infoPtr, (HDC)wParam, (DWORD)lParam); + + case WM_ERASEBKGND: + return MONTHCAL_EraseBkgnd(infoPtr, (HDC)wParam); + + case WM_SETFOCUS: + return MONTHCAL_SetFocus(infoPtr); + + case WM_SIZE: + return MONTHCAL_Size(infoPtr, (SHORT)LOWORD(lParam), (SHORT)HIWORD(lParam)); + + case WM_NOTIFY: + return MONTHCAL_Notify(infoPtr, (NMHDR*)lParam); + + case WM_CREATE: + return MONTHCAL_Create(hwnd, (LPCREATESTRUCTW)lParam); + + case WM_SETFONT: + return MONTHCAL_SetFont(infoPtr, (HFONT)wParam, (BOOL)lParam); + + case WM_GETFONT: + return MONTHCAL_GetFont(infoPtr); + + case WM_TIMER: + return MONTHCAL_Timer(infoPtr, wParam); + + case WM_THEMECHANGED: + return theme_changed (infoPtr); + + case WM_DESTROY: + return MONTHCAL_Destroy(infoPtr); + + case WM_SYSCOLORCHANGE: + COMCTL32_RefreshSysColors(); + return 0; + + case WM_STYLECHANGED: + return MONTHCAL_StyleChanged(infoPtr, wParam, (LPSTYLESTRUCT)lParam); + + case WM_STYLECHANGING: + return MONTHCAL_StyleChanging(infoPtr, wParam, (LPSTYLESTRUCT)lParam); + + default: + if ((uMsg >= WM_USER) && (uMsg < WM_APP) && !COMCTL32_IsReflectedMessage(uMsg)) + ERR( "unknown msg %04x wp=%08lx lp=%08lx\n", uMsg, wParam, lParam); + return DefWindowProcW(hwnd, uMsg, wParam, lParam); + } +} + + +void +MONTHCAL_Register(void) +{ + WNDCLASSW wndClass; + + ZeroMemory(&wndClass, sizeof(WNDCLASSW)); + wndClass.style = CS_GLOBALCLASS; + wndClass.lpfnWndProc = MONTHCAL_WindowProc; + wndClass.cbClsExtra = 0; + wndClass.cbWndExtra = sizeof(MONTHCAL_INFO *); + wndClass.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW); + wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wndClass.lpszClassName = MONTHCAL_CLASSW; + + RegisterClassW(&wndClass); +} + + +void +MONTHCAL_Unregister(void) +{ + UnregisterClassW(MONTHCAL_CLASSW, NULL); +} diff --cc dll/win32/kernel32/kernel32.spec index e8adc8e7a6c,00000000000..c0a8bf54022 mode 100644,000000..100644 --- a/dll/win32/kernel32/kernel32.spec +++ b/dll/win32/kernel32/kernel32.spec @@@ -1,1456 -1,0 +1,1456 @@@ +@ stdcall AcquireSRWLockExclusive(ptr) ntdll.RtlAcquireSRWLockExclusive +@ stdcall AcquireSRWLockShared(ptr) ntdll.RtlAcquireSRWLockShared +@ stdcall ActivateActCtx(ptr ptr) +@ stdcall AddAtomA(str) +@ stdcall AddAtomW(wstr) +@ stdcall AddConsoleAliasA(str str str) ;check +@ stdcall AddConsoleAliasW(wstr wstr wstr) ;check +;@ stdcall -arch=x86_64 AddIntegrityLabelToBoundaryDescriptor ; Win 7 +@ stdcall AddLocalAlternateComputerNameA(str ptr) +@ stdcall AddLocalAlternateComputerNameW(wstr ptr) +@ stdcall AddRefActCtx(ptr) +;@ stdcall AddSIDToBoundaryDescriptor ; Win 7 +;@ stdcall AddSecureMemoryCacheCallback ; Win 7 +@ stdcall AddVectoredContinueHandler(long ptr) ntdll.RtlAddVectoredContinueHandler +@ stdcall AddVectoredExceptionHandler(long ptr) ntdll.RtlAddVectoredExceptionHandler +;@ stdcall AdjustCalendarDate ; Win 7 +@ stdcall AllocConsole() +;@ stub AllocLSCallback ; missing in XP SP3 and 2003 R2 and Win 7 +@ stdcall AllocateUserPhysicalPages(long ptr ptr) +;@ stdcall AllocateUserPhysicalPagesNuma ; Win 7 +;@ stdcall ApplicationRecoveryFinished ; Win 7 +;@ stdcall ApplicationRecoveryInProgress ; Win 7 +@ stdcall AreFileApisANSI() +@ stdcall AssignProcessToJobObject(ptr ptr) +@ stdcall AttachConsole(long) +@ stdcall BackupRead(ptr ptr long ptr long long ptr) +@ stdcall BackupSeek(ptr long long ptr ptr ptr) +@ stdcall BackupWrite(ptr ptr long ptr long long ptr) +@ stdcall BaseCheckAppcompatCache(long long long ptr) ;check +;@ stdcall BaseCheckAppcompatCacheEx ; Win7 +;@ stub BaseCheckRunApp ; Win7 +@ stdcall BaseCleanupAppcompatCache() ; missing in Win 7 +@ stdcall BaseCleanupAppcompatCacheSupport(ptr) +;@ stdcall BaseDllReadWriteIniFile ; Win 7 +@ stdcall BaseDumpAppcompatCache() +@ stdcall BaseFlushAppcompatCache() +;@ stdcall BaseFormatObjectAttributes ; Win 7 +;@ stdcall BaseFormatTimeOut ; Win 7 +;@ stdcall BaseGenerateAppCompatData ; Win 7 +;@ stdcall BaseGetNamedObjectDirectory ; Win 7 +@ stdcall BaseInitAppcompatCache() ; missing in Win 7 +@ stdcall BaseInitAppcompatCacheSupport() +;@ stdcall BaseIsAppcompatInfrastructureDisabled ; Win 7 +@ stdcall BaseProcessInitPostImport() ; missing in Win 7 +@ stdcall BaseQueryModuleData(str str ptr ptr ptr) ;check +;@ stdcall BaseThreadInitThunk ; Win 7 - ;@ stdcall BaseSetLastNTError ; Win 7, not 64 bit ++;@ stdcall BaseSetLastNTError ; Win 7, not 64 bit (present on w2k3 but not exported) +@ stdcall BaseUpdateAppcompatCache(long long long) +;@ stdcall BaseVerifyUnicodeString ; Win 7 +;@ stdcall Basep8BitStringToDynamicUnicodeString ; Win 7 +;@ stdcall BasepAllocateActivationContextActivationBlock ; Win 7 +;@ stdcall BasepAnsiStringToDynamicUnicodeString ; Win 7 +;@ stdcall BasepCheckAppCompat ; Win 7 +;@ stdcall BasepCheckBadapp ; Win 7 +@ stdcall BasepCheckWinSaferRestrictions(long long long long long long) +;@ stub BasepDebugDump ; missing in XP SP3 and Win 7 +;@ stdcall BasepFreeActivationContextActivationBlock ; Win 7 +;@ stdcall BasepFreeAppCompatData ; Win 7 +;@ stdcall BasepMapModuleHandle ; Win 7 +@ stdcall Beep(long long) +@ stdcall BeginUpdateResourceA(str long) +@ stdcall BeginUpdateResourceW(wstr long) +@ stdcall BindIoCompletionCallback(long ptr long) +@ stdcall BuildCommDCBA(str ptr) +@ stdcall BuildCommDCBAndTimeoutsA(str ptr ptr) +@ stdcall BuildCommDCBAndTimeoutsW(wstr ptr ptr) +@ stdcall BuildCommDCBW(wstr ptr) +@ stdcall CallNamedPipeA(str ptr long ptr long ptr long) +@ stdcall CallNamedPipeW(wstr ptr long ptr long ptr long) +;@ stdcall CallbackMayRunLong ; Win 7 +@ stdcall CancelDeviceWakeupRequest(long) +@ stdcall CancelIo(long) +@ stdcall CancelIoEx(long ptr) +@ stdcall CancelSynchronousIo(long) +;@ stdcall CancelThreadpoolIo(ptr) ntdll.TpCancelAsyncIoOperation; Win 7 +@ stdcall CancelTimerQueueTimer(long long) +@ stdcall CancelWaitableTimer(long) +@ stdcall ChangeTimerQueueTimer(ptr ptr long long) +;@ stdcall CheckElevation ; Win 7 +;@ stdcall CheckElevationEnabled ; Win 7 +;@ stdcall CheckForReadOnlyResource ; Win 7 +@ stdcall CheckNameLegalDOS8Dot3A(str str long long long) +@ stdcall CheckNameLegalDOS8Dot3W(wstr str long long long) +@ stdcall CheckRemoteDebuggerPresent(long ptr) +@ stdcall ClearCommBreak(long) +@ stdcall ClearCommError(long ptr ptr) +@ stdcall CloseConsoleHandle(long) +@ stdcall CloseHandle(long) +;@ stdcall ClosePrivateNamespace ; Win 7 +@ stdcall CloseProfileUserMapping() +; @ stub CloseSystemHandle ; missing in XP SP3 and Win 7 +;@ stdcall CloseThreadpool(ptr) ntdll.TpReleasePool ; Win 7 +;@ stdcall CloseThreadpoolCleanupGroup(ptr) ntdll.TpReleaseCleanupGroup ; Win 7 +;@ stdcall CloseThreadpoolCleanupGroupMembers(ptr long ptr) ntdll.TpReleaseCleanupGroupMembers ; Win 7 +;@ stdcall CloseThreadpoolIo ntdll.TpReleaseIoCompletion ; Win 7 +;@ stdcall CloseThreadpoolTimer ntdll.TpReleaseTimer ; Win 7 +;@ stdcall CloseThreadpoolWait ntdll.TpReleaseWait ; Win 7 +;@ stdcall CloseThreadpoolWork ntdll.TpReleaseWork ; Win 7 +@ stdcall CmdBatNotification(long) +@ stdcall CommConfigDialogA(str long ptr) +@ stdcall CommConfigDialogW(wstr long ptr) +;@ stdcall CompareCalendarDates ; Win 7 +@ stdcall CompareFileTime(ptr ptr) +@ stdcall CompareStringA(long long str long str long) +;@ stdcall CompareStringEx ; Win 7 +;@ stdcall CompareStringOrdinal ; Win 7 +@ stdcall CompareStringW(long long wstr long wstr long) +@ stdcall ConnectNamedPipe(long ptr) +@ stdcall ConsoleMenuControl(long long long) +; @ stub ConsoleSubst ; missing in XP SP3 and Win 7 +@ stdcall ContinueDebugEvent(long long long) +;@ stdcall ConvertCalDateTimeToSystemTime ; Win 7 +@ stdcall ConvertDefaultLocale (long) +@ stdcall ConvertFiberToThread() +;@ stdcall ConvertNLSDayOfWeekToWin32DayOfWeek ; Win 7 +;@ stdcall ConvertSystemTimeToCalDateTime ; Win 7 +@ stdcall ConvertThreadToFiber(ptr) +@ stdcall ConvertThreadToFiberEx(ptr long) +;@ stdcall CopyExtendedContext ; Win 7 +@ stdcall CopyFileA(str str long) +@ stdcall CopyFileExA (str str ptr ptr ptr long) +@ stdcall CopyFileExW (wstr wstr ptr ptr ptr long) +;@ stdcall CopyFileTransactedA ; Win 7 +;@ stdcall CopyFileTransactedW ; Win 7 +@ stdcall CopyFileW(wstr wstr long) +@ stdcall CopyLZFile(long long) LZCopy +@ stdcall CreateActCtxA(ptr) +@ stdcall CreateActCtxW(ptr) +;@ stdcall CreateBoundaryDescriptorA ; Win 7 +;@ stdcall CreateBoundaryDescriptorW ; Win 7 +@ stdcall CreateConsoleScreenBuffer(long long ptr long ptr) +@ stdcall CreateDirectoryA(str ptr) +@ stdcall CreateDirectoryExA(str str ptr) +@ stdcall CreateDirectoryExW(wstr wstr ptr) +;@ stdcall CreateDirectoryTransactedA ; Win 7 +;@ stdcall CreateDirectoryTransactedW ; Win 7 +@ stdcall CreateDirectoryW(wstr ptr) +@ stdcall CreateEventA(ptr long long str) +@ stdcall CreateEventExA(ptr str long long) +@ stdcall CreateEventExW(ptr wstr long long) +@ stdcall CreateEventW(ptr long long wstr) +@ stdcall CreateFiber(long ptr ptr) +@ stdcall CreateFiberEx(long long long ptr ptr) +@ stdcall CreateFileA(str long long ptr long long long) +@ stdcall CreateFileMappingA(long ptr long long long str) +;@ stdcall CreateFileMappingNumaA ; Win 7 +;@ stdcall CreateFileMappingNumaW ; Win 7 +@ stdcall CreateFileMappingW(long ptr long long long wstr) +;@ stdcall CreateFileTransactedA ; Win 7 +;@ stdcall CreateFileTransactedW ; Win 7 +@ stdcall CreateFileW(wstr long long ptr long long long) +@ stdcall CreateHardLinkA(str str ptr) +;@ stdcall CreateHardLinkTransactedA ; Win 7 +;@ stdcall CreateHardLinkTransactedW ; Win 7 +@ stdcall CreateHardLinkW(wstr wstr ptr) +@ stdcall CreateIoCompletionPort(long long long long) +@ stdcall CreateJobObjectA(ptr str) +@ stdcall CreateJobObjectW(ptr wstr) +@ stdcall CreateJobSet(long ptr long) +;@ stub CreateKernelThread ; missing in XP SP3 and Win 7 +@ stdcall CreateMailslotA(ptr long long ptr) +@ stdcall CreateMailslotW(ptr long long ptr) +@ stdcall CreateMemoryResourceNotification(long) +@ stdcall CreateMutexA(ptr long str) +@ stdcall CreateMutexExA(ptr str long long) +@ stdcall CreateMutexExW(ptr wstr long long) +@ stdcall CreateMutexW(ptr long wstr) +@ stdcall CreateNamedPipeA(str long long long long long long ptr) +@ stdcall CreateNamedPipeW(wstr long long long long long long ptr) +@ stdcall CreateNlsSecurityDescriptor(ptr long long) ; missing in Win 7 +@ stdcall CreatePipe(ptr ptr ptr long) +;@ stdcall CreatePrivateNamespaceA ; Win 7 +;@ stdcall CreatePrivateNamespaceW ; Win 7 +@ stdcall CreateProcessA(str str ptr ptr long long ptr str ptr ptr) +;@ stdcall CreateProcessAsUserW ; Win 7 +@ stdcall CreateProcessInternalA(ptr str str ptr ptr long long ptr str ptr ptr long) +@ stdcall CreateProcessInternalW(ptr wstr wstr ptr ptr long long ptr wstr ptr ptr long) +@ stdcall CreateProcessInternalWSecure() ; missing in Win 7 +@ stdcall CreateProcessW(wstr wstr ptr ptr long long ptr wstr ptr ptr) +@ stdcall CreateRemoteThread(long ptr long ptr long long ptr) +;@ stdcall CreateRemoteThreadEx api-ms-win-core-processthreads-l1-1-0.CreateRemoteThreadEx ; Win 7 +@ stdcall CreateSemaphoreA(ptr long long str) +@ stdcall CreateSemaphoreExA(ptr long long str long long) +@ stdcall CreateSemaphoreExW(ptr long long wstr long long) +@ stdcall CreateSemaphoreW(ptr long long wstr) +@ stdcall CreateSocketHandle() +@ stdcall CreateSymbolicLinkA(str str long) +;@ stdcall CreateSymbolicLinkTransactedA ; Win 7 +;@ stdcall CreateSymbolicLinkTransactedW ; Win 7 +@ stdcall CreateSymbolicLinkW(wstr wstr long) +@ stdcall CreateTapePartition(long long long long) +@ stdcall CreateThread(ptr long ptr long long ptr) +;@ stdcall CreateThreadpool ; Win 7 +;@ stdcall CreateThreadpoolCleanupGroup ; Win 7 +;@ stdcall CreateThreadpoolIo ; Win 7 +;@ stdcall CreateThreadpoolTimer ; Win 7 +;@ stdcall CreateThreadpoolWait ; Win 7 +;@ stdcall CreateThreadpoolWork ; Win 7 +@ stdcall CreateTimerQueue () +@ stdcall CreateTimerQueueTimer(ptr long ptr ptr long long long) +@ stdcall CreateToolhelp32Snapshot(long long) +;@ stdcall arch=x86_64 CreateUmsCompletionList +;@ stdcall arch=x86_64 CreateUmsThreadContext +@ stdcall CreateVirtualBuffer(long long long) ; missing in Win 7 +@ stdcall CreateWaitableTimerA(ptr long str) +@ stdcall CreateWaitableTimerExA(ptr str long long) +@ stdcall CreateWaitableTimerExW(ptr wstr long long) +@ stdcall CreateWaitableTimerW(ptr long wstr) +@ stdcall DeactivateActCtx(long ptr) +@ stdcall DebugActiveProcess(long) +@ stdcall DebugActiveProcessStop(long) +@ stdcall DebugBreak() ntdll.DbgBreakPoint +@ stdcall DebugBreakProcess(long) +@ stdcall DebugSetProcessKillOnExit(long) +@ stdcall DecodePointer(ptr) ntdll.RtlDecodePointer +@ stdcall DecodeSystemPointer(ptr) ntdll.RtlDecodeSystemPointer +@ stdcall DefineDosDeviceA(long str str) +@ stdcall DefineDosDeviceW(long wstr wstr) +@ stdcall DelayLoadFailureHook(str str) +@ stdcall DeleteAtom(long) +;@ stdcall DeleteBoundaryDescriptor ntdll.RtlDeleteBoundaryDescriptor ; Win 7 +@ stdcall DeleteCriticalSection(ptr) ntdll.RtlDeleteCriticalSection +@ stdcall DeleteFiber(ptr) +@ stdcall DeleteFileA(str) +;@ stdcall DeleteFileTransactedA ; Win 7 +;@ stdcall DeleteFileTransactedW ; Win 7 +@ stdcall DeleteFileW(wstr) +;@ stdcall DeleteProcThreadAttributeList api-ms-win-core-processthreads-l1-1-0.DeleteProcThreadAttributeList ; Win 7 +@ stdcall DeleteTimerQueue(long) +@ stdcall DeleteTimerQueueEx (long long) +@ stdcall DeleteTimerQueueTimer(long long long) +;@ stdcall -arch=x86_64 DeleteUmsCompletionList +;@ stdcall -arch=x86_64 DeleteUmsThreadContext +@ stdcall DeleteVolumeMountPointA(str) ;check +@ stdcall DeleteVolumeMountPointW(wstr) ;check +;@ stdcall -arch=x86_64 DequeueUmsCompletionListItems +@ stdcall DeviceIoControl(long long ptr long ptr long ptr ptr) +@ stdcall DisableThreadLibraryCalls(long) +;@ stdcall DisableThreadProfiling ; Win 7 +;@ stdcall DisassociateCurrentThreadFromCallback ntdll.TpDisassociateCallback ; Win 7 +@ stdcall DisconnectNamedPipe(long) +@ stdcall DnsHostnameToComputerNameA (str ptr ptr) +@ stdcall DnsHostnameToComputerNameW (wstr ptr ptr) +@ stdcall DosDateTimeToFileTime(long long ptr) +@ stdcall DosPathToSessionPathA(long str str) +@ stdcall DosPathToSessionPathW(long wstr wstr) +@ stdcall DuplicateConsoleHandle(long long long long) +@ stdcall DuplicateHandle(long long long ptr long long long) +;@ stdcall EnableThreadProfiling ; Win 7 +@ stdcall EncodePointer(ptr) ntdll.RtlEncodePointer +@ stdcall EncodeSystemPointer(ptr) ntdll.RtlEncodeSystemPointer +@ stdcall EndUpdateResourceA(long long) +@ stdcall EndUpdateResourceW(long long) +@ stdcall EnterCriticalSection(ptr) ntdll.RtlEnterCriticalSection +;@ stdcall -arch=x86_64 EnterUmsSchedulingMode +@ stdcall EnumCalendarInfoA(ptr long long long) +@ stdcall EnumCalendarInfoExA(ptr long long long) +;@ stdcall EnumCalendarInfoExEx ; Win 7 +@ stdcall EnumCalendarInfoExW(ptr long long long) +@ stdcall EnumCalendarInfoW(ptr long long long) +@ stdcall EnumDateFormatsA(ptr long long) +@ stdcall EnumDateFormatsExA(ptr long long) +;@ stdcall EnumDateFormatsExEx ; Win 7 +@ stdcall EnumDateFormatsExW(ptr long long) +@ stdcall EnumDateFormatsW(ptr long long) +@ stdcall EnumLanguageGroupLocalesA(ptr long long ptr) +@ stdcall EnumLanguageGroupLocalesW(ptr long long ptr) +@ stdcall EnumResourceLanguagesA(long str str ptr long) +;@ stdcall EnumResourceLanguagesExA ; Win 7 +;@ stdcall EnumResourceLanguagesExW ; Win 7 +@ stdcall EnumResourceLanguagesW(long wstr wstr ptr long) +@ stdcall EnumResourceNamesA(long str ptr long) +;@ stdcall EnumResourceNamesExA ; Win 7 +;@ stdcall EnumResourceNamesExW ; Win 7 +@ stdcall EnumResourceNamesW(long wstr ptr long) +@ stdcall EnumResourceTypesA(long ptr long) +;@ stdcall EnumResourceTypesExA ; Win 7 +;@ stdcall EnumResourceTypesExW ; Win 7 +@ stdcall EnumResourceTypesW(long ptr long) +@ stdcall EnumSystemCodePagesA(ptr long) +@ stdcall EnumSystemCodePagesW(ptr long) +;@ stdcall EnumSystemFirmwareTables ; Win 7 +@ stdcall EnumSystemGeoID(long long ptr) +@ stdcall EnumSystemLanguageGroupsA(ptr long ptr) +@ stdcall EnumSystemLanguageGroupsW(ptr long ptr) +@ stdcall EnumSystemLocalesA(ptr long) +;@ stdcall EnumSystemLocalesEx ; Win 7 +@ stdcall EnumSystemLocalesW(ptr long) +@ stdcall EnumTimeFormatsA(ptr long long) +;@ stdcall EnumTimeFormatsEx ; Win 7 +@ stdcall EnumTimeFormatsW(ptr long long) +@ stdcall EnumUILanguagesA(ptr long long) +@ stdcall EnumUILanguagesW(ptr long long) +@ stdcall EnumerateLocalComputerNamesA(ptr long str ptr) +@ stdcall EnumerateLocalComputerNamesW(ptr long wstr ptr) +@ stdcall EraseTape(ptr long long) +@ stdcall EscapeCommFunction(long long) +@ stdcall ExitProcess(long) ; FIXME: ntdll.RtlExitUserProcess +@ stdcall ExitThread(long) ; FIXME: ntdll.RtlExitUserThread +@ stdcall ExitVDM(long long) +@ stdcall ExpandEnvironmentStringsA(str ptr long) +@ stdcall ExpandEnvironmentStringsW(wstr ptr long) +@ stdcall ExpungeConsoleCommandHistoryA(long) +@ stdcall ExpungeConsoleCommandHistoryW(long) +@ stdcall ExtendVirtualBuffer(long long) ; missing in Win 7 +@ stdcall FatalAppExitA(long str) +@ stdcall FatalAppExitW(long wstr) +@ stdcall FatalExit(long) +@ stdcall FileTimeToDosDateTime(ptr ptr ptr) +@ stdcall FileTimeToLocalFileTime(ptr ptr) +@ stdcall FileTimeToSystemTime(ptr ptr) +@ stdcall FillConsoleOutputAttribute(long long long long ptr) +@ stdcall FillConsoleOutputCharacterA(long long long long ptr) +@ stdcall FillConsoleOutputCharacterW(long long long long ptr) +@ stdcall FindActCtxSectionGuid(long ptr long ptr ptr) +@ stdcall FindActCtxSectionStringA(long ptr long str ptr) +@ stdcall FindActCtxSectionStringW(long ptr long wstr ptr) +@ stdcall FindAtomA(str) +@ stdcall FindAtomW(wstr) +@ stdcall FindClose(long) +@ stdcall FindCloseChangeNotification(long) +@ stdcall FindFirstChangeNotificationA(str long long) +@ stdcall FindFirstChangeNotificationW(wstr long long) +@ stdcall FindFirstFileA(str ptr) +@ stdcall FindFirstFileExA(str long ptr long ptr long) +@ stdcall FindFirstFileExW(wstr long ptr long ptr long) +;@ stdcall FindFirstFileNameTransactedW ; Win 7 +;@ stdcall FindFirstFileNameW ; Win 7 +;@ stdcall FindFirstFileTransactedA ; Win 7 +;@ stdcall FindFirstFileTransactedW ; Win 7 +@ stdcall FindFirstFileW(wstr ptr) +;@ stdcall FindFirstStreamTransactedW ; Win 7 +@ stdcall FindFirstStreamW(wstr ptr ptr long) +@ stdcall FindFirstVolumeA(ptr long) +@ stdcall FindFirstVolumeMountPointA(str ptr long) +@ stdcall FindFirstVolumeMountPointW(wstr ptr long) +@ stdcall FindFirstVolumeW(ptr long) +;@ stdcall FindNLSString ; Win 7 +;@ stdcall FindNLSStringEx ; Win 7 +@ stdcall FindNextChangeNotification(long) +@ stdcall FindNextFileA(long ptr) +;@ stdcall FindNextFileNameW ; Win 7 +@ stdcall FindNextFileW(long ptr) +;@ stdcall FindNextStreamW ; Win 7 +@ stdcall FindNextVolumeA(long ptr long) +@ stdcall FindNextVolumeMountPointA(long str long) +@ stdcall FindNextVolumeMountPointW(long wstr long) +@ stdcall FindNextVolumeW(long ptr long) +@ stdcall FindResourceA(long str str) +@ stdcall FindResourceExA(long str str long) +@ stdcall FindResourceExW(long wstr wstr long) +@ stdcall FindResourceW(long wstr wstr) +;@ stdcall FindStringOrdinal ; Win 7 +@ stdcall FindVolumeClose(ptr) +@ stdcall FindVolumeMountPointClose(ptr) +;@ stdcall FlsAlloc(ptr) ; missing in XP SP3 +;@ stdcall FlsFree(long) ; missing in XP SP3 +;@ stdcall FlsGetValue(long) ; missing in XP SP3 +;@ stdcall FlsSetValue(long ptr) ; missing in XP SP3 +@ stdcall FlushConsoleInputBuffer(long) +@ stdcall FlushFileBuffers(long) +@ stdcall FlushInstructionCache(long long long) +;@ stdcall FlushProcessWriteBuffers ntdll.NtFlushProcessWriteBuffers ; Win 7 +@ stdcall FlushViewOfFile(ptr long) +@ stdcall FoldStringA(long str long ptr long) +@ stdcall FoldStringW(long wstr long ptr long) +@ stdcall FormatMessageA(long ptr long long ptr long ptr) +@ stdcall FormatMessageW(long ptr long long ptr long ptr) +@ stdcall FreeConsole() +@ stdcall FreeEnvironmentStringsA(ptr) +@ stdcall FreeEnvironmentStringsW(ptr) +@ stdcall FreeLibrary(long) +@ stdcall FreeLibraryAndExitThread(long long) +;@ stdcall FreeLibraryWhenCallbackReturns ntdll.TpCallbackUnloadDllOnCompletion ; Win 7 +@ stdcall FreeResource(long) +@ stdcall FreeUserPhysicalPages(long long long) +@ stdcall FreeVirtualBuffer(ptr) ; missing in Win 7 +@ stdcall GenerateConsoleCtrlEvent(long long) +@ stdcall GetACP() +;@ stdcall GetActiveProcessorCount ; Win 7 +;@ stdcall GetActiveProcessorGroupCount ; Win 7 +;@ stdcall GetApplicationRecoveryCallback ; Win 7 +;@ stdcall GetApplicationRestartSettings ; Win 7 +@ stdcall GetAtomNameA(long ptr long) +@ stdcall GetAtomNameW(long ptr long) +@ stdcall GetBinaryType(str ptr) GetBinaryTypeA +@ stdcall GetBinaryTypeA(str ptr) +@ stdcall GetBinaryTypeW(wstr ptr) +@ stdcall GetCPFileNameFromRegistry(long wstr long) ;check missing in Win 7 +@ stdcall GetCPInfo(long ptr) +@ stdcall GetCPInfoExA(long long ptr) +@ stdcall GetCPInfoExW(long long ptr) +;@ stdcall GetCalendarDateFormat ; Win 7 +;@ stdcall GetCalendarDateFormatEx ; Win 7 +;@ stdcall GetCalendarDaysInMonth ; Win 7 +;@ stdcall GetCalendarDifferenceInDays ; Win 7 +@ stdcall GetCalendarInfoA(long long long ptr long ptr) +;@ stdcall GetCalendarInfoEx ; Win 7 +@ stdcall GetCalendarInfoW(long long long ptr long ptr) +;@ stdcall GetCalendarMonthsInYear ; Win 7 +;@ stdcall GetCalendarSupportedDateRange ; Win 7 +;@ stdcall GetCalendarWeekNumber ; Win 7 +@ stdcall GetComPlusPackageInstallStatus() +@ stdcall GetCommConfig(long ptr long) +@ stdcall GetCommMask(long ptr) +@ stdcall GetCommModemStatus(long ptr) +@ stdcall GetCommProperties(long ptr) +@ stdcall GetCommState(long ptr) +@ stdcall GetCommTimeouts(long ptr) +@ stdcall GetCommandLineA() +@ stdcall GetCommandLineW() +@ stdcall GetCompressedFileSizeA(long ptr) +;@ stdcall GetCompressedFileSizeTransactedA ; Win 7 +;@ stdcall GetCompressedFileSizeTransactedW ; Win 7 +@ stdcall GetCompressedFileSizeW(long ptr) +@ stdcall GetComputerNameA(ptr ptr) +@ stdcall GetComputerNameExA(long ptr ptr) +@ stdcall GetComputerNameExW(long ptr ptr) +@ stdcall GetComputerNameW(ptr ptr) +@ stdcall GetConsoleAliasA(str str long str) +@ stdcall GetConsoleAliasExesA(str long) +@ stdcall GetConsoleAliasExesLengthA() +@ stdcall GetConsoleAliasExesLengthW() +@ stdcall GetConsoleAliasExesW(wstr long) +@ stdcall GetConsoleAliasW(wstr ptr long wstr) +@ stdcall GetConsoleAliasesA(str long str) +@ stdcall GetConsoleAliasesLengthA(str) +@ stdcall GetConsoleAliasesLengthW(wstr) +@ stdcall GetConsoleAliasesW(wstr long wstr) +@ stdcall GetConsoleCP() +@ stdcall GetConsoleCharType(long long ptr) +@ stdcall GetConsoleCommandHistoryA(long long long) +@ stdcall GetConsoleCommandHistoryLengthA(long) +@ stdcall GetConsoleCommandHistoryLengthW(long) +@ stdcall GetConsoleCommandHistoryW(long long long) +@ stdcall GetConsoleCursorInfo(long ptr) +@ stdcall GetConsoleCursorMode(long ptr ptr) +@ stdcall GetConsoleDisplayMode(ptr) +@ stdcall GetConsoleFontInfo(long long long ptr) +@ stdcall GetConsoleFontSize(long long) +@ stdcall GetConsoleHardwareState(long long ptr) +@ stdcall GetConsoleHistoryInfo(ptr) +@ stdcall GetConsoleInputExeNameA(long ptr) +@ stdcall GetConsoleInputExeNameW(long ptr) +@ stdcall GetConsoleInputWaitHandle() +@ stdcall GetConsoleKeyboardLayoutNameA(ptr) +@ stdcall GetConsoleKeyboardLayoutNameW(ptr) +@ stdcall GetConsoleMode(long ptr) +@ stdcall GetConsoleNlsMode(long ptr) +;@ stdcall GetConsoleOriginalTitleA ; Win 7 +;@ stdcall GetConsoleOriginalTitleW ; Win 7 +@ stdcall GetConsoleOutputCP() +@ stdcall GetConsoleProcessList(ptr long) ; missing in XP SP3 +@ stdcall GetConsoleScreenBufferInfo(long ptr) +;@ stdcall GetConsoleScreenBufferInfoEx ; Win 7 +@ stdcall GetConsoleSelectionInfo(ptr) +@ stdcall GetConsoleTitleA(ptr long) +@ stdcall GetConsoleTitleW(ptr long) +@ stdcall GetConsoleWindow() +@ stdcall GetCurrencyFormatA(long long str ptr str long) +;@ stdcall GetCurrencyFormatEx ; Win 7 +@ stdcall GetCurrencyFormatW(long long str ptr str long) +@ stdcall GetCurrentActCtx(ptr) +@ stdcall GetCurrentConsoleFont(long long ptr) +;@ stdcall GetCurrentConsoleFontEx ; Win 7 +@ stdcall GetCurrentDirectoryA(long ptr) +@ stdcall GetCurrentDirectoryW(long ptr) +@ stdcall GetCurrentProcess() +@ stdcall GetCurrentProcessId() +@ stdcall GetCurrentProcessorNumber() ntdll.RtlGetCurrentProcessorNumber +;@ stdcall GetCurrentProcessorNumberEx ntdll.RtlGetCurrentProcessorNumberEx ; Win 7 +@ stdcall GetCurrentThread() +@ stdcall GetCurrentThreadId() +;@ stdcall GetCurrentUmsThread +@ stdcall GetDateFormatA(long long ptr str ptr long) +;@ stdcall GetDateFormatEx ; Win 7 +@ stdcall GetDateFormatW(long long ptr wstr ptr long) +;@ stub GetDaylightFlag ; missing in XP SP3 and Win 7 +@ stdcall GetDefaultCommConfigA(str ptr long) +@ stdcall GetDefaultCommConfigW(wstr ptr long) +@ stdcall GetDefaultSortkeySize(ptr) ; missing in Win 7 +@ stdcall GetDevicePowerState(long ptr) +@ stdcall GetDiskFreeSpaceA(str ptr ptr ptr ptr) +@ stdcall GetDiskFreeSpaceExA (str ptr ptr ptr) +@ stdcall GetDiskFreeSpaceExW (wstr ptr ptr ptr) +@ stdcall GetDiskFreeSpaceW(wstr ptr ptr ptr ptr) +@ stdcall GetDllDirectoryA(long ptr) +@ stdcall GetDllDirectoryW(long ptr) +@ stdcall GetDriveTypeA(str) +@ stdcall GetDriveTypeW(wstr) +;@ stdcall GetDurationFormat ; Win 7 +;@ stdcall GetDurationFormatEx ; Win 7 +;@ stdcall GetDynamicTimeZoneInformation ; Win 7 +;@ stdcall GetEnabledExtendedFeatures api-ms-win-core-xstate-l1-1-0.RtlGetEnabledExtendedFeatures ; Win 7 +@ stdcall GetEnvironmentStrings() +@ stdcall GetEnvironmentStringsA() GetEnvironmentStrings +@ stdcall GetEnvironmentStringsW() +@ stdcall GetEnvironmentVariableA(str ptr long) +@ stdcall GetEnvironmentVariableW(wstr ptr long) +;@ stdcall GetEraNameCountedString ; Win 7 +@ stdcall GetErrorMode() +@ stdcall GetExitCodeProcess(long ptr) +@ stdcall GetExitCodeThread(long ptr) +@ stdcall GetExpandedNameA(str ptr) +@ stdcall GetExpandedNameW(wstr ptr) +;@ stdcall GetExtendedContextLength ; Win 7 +;@ stdcall GetExtendedFeaturesMask api-ms-win-core-xstate-l1-1-0.RtlGetExtendedFeaturesMask ; Win 7 +@ stdcall GetFileAttributesA(str) +@ stdcall GetFileAttributesByHandle(long ptr long) ; missing in Win 7 +@ stdcall GetFileAttributesExA(str long ptr) +@ stdcall GetFileAttributesExW(wstr long ptr) +;@ stdcall GetFileAttributesTransactedA ; Win 7 +;@ stdcall GetFileAttributesTransactedW ; Win 7 +@ stdcall GetFileAttributesW(wstr) +@ stdcall GetFileBandwidthReservation(long ptr ptr ptr ptr ptr) +@ stdcall GetFileInformationByHandle(long ptr) +;@ stdcall GetFileInformationByHandleEx ; Win 7 +;@ stdcall GetFileMUIInfo ; Win 7 +;@ stdcall GetFileMUIPath ; Win 7 +@ stdcall GetFileSize(long ptr) +@ stdcall GetFileSizeEx(long ptr) +@ stdcall GetFileTime(long ptr ptr ptr) +@ stdcall GetFileType(long) +@ stdcall GetFinalPathNameByHandleA(long str long long) +@ stdcall GetFinalPathNameByHandleW(long wstr long long) +@ stdcall GetFirmwareEnvironmentVariableA(str str ptr long) +@ stdcall GetFirmwareEnvironmentVariableW(wstr wstr ptr long) +@ stdcall GetFullPathNameA(str long ptr ptr) +;@ stdcall GetFullPathNameTransactedA ; Win 7 +;@ stdcall GetFullPathNameTransactedW ; Win 7 +@ stdcall GetFullPathNameW(wstr long ptr ptr) +@ stdcall GetGeoInfoA(long long ptr long long) +@ stdcall GetGeoInfoW(long long ptr long long) +@ stdcall GetHandleContext(long) ; missing on x64 +@ stdcall GetHandleInformation(long ptr) +;@ stub GetSCallbackTarget ; missing in XP SP3 and Win 7 +;@ stub GetSCallbackTemplate ; missing in XP SP3 and Win 7 +@ stdcall GetLargePageMinimum() +@ stdcall GetLargestConsoleWindowSize(long) +@ stdcall GetLastError() ntdll.RtlGetLastWin32Error +@ stdcall GetLinguistLangSize(ptr) ; missing in Win 7 +@ stdcall GetLocalTime(ptr) +@ stdcall GetLocaleInfoA(long long ptr long) +@ stdcall GetLocaleInfoEx(wstr long wstr long) ; Vista+ +@ stdcall GetLocaleInfoW(long long ptr long) +@ stdcall GetLogicalDriveStringsA(long ptr) +@ stdcall GetLogicalDriveStringsW(long ptr) +@ stdcall GetLogicalDrives() +@ stdcall GetLogicalProcessorInformation(ptr ptr) +;@ stdcall GetLogicalProcessorInformationEx api-ms-win-core-sysinfo-l1-1-0.GetLogicalProcessorInformationEx ; Win 7 +@ stdcall GetLongPathNameA (str long long) +;@ stdcall GetLongPathNameTransactedA ; Win 7 +;@ stdcall GetLongPathNameTransactedW ; Win 7 +@ stdcall GetLongPathNameW (wstr long long) +@ stdcall GetMailslotInfo(long ptr ptr ptr ptr) +;@ stdcall GetMaximumProcessorCount ; Win 7 +;@ stdcall GetMaximumProcessorGroupCount ; Win 7 +@ stdcall GetModuleFileNameA(long ptr long) +@ stdcall GetModuleFileNameW(long ptr long) +@ stdcall GetModuleHandleA(str) +@ stdcall GetModuleHandleExA(long ptr ptr) +@ stdcall GetModuleHandleExW(long ptr ptr) +@ stdcall GetModuleHandleW(wstr) +;@ stdcall GetNLSVersion ; Win 7 +;@ stdcall GetNLSVersionEx ; Win 7 +;@ stdcall GetNamedPipeAttribute ; Win 7 +;@ stdcall GetNamedPipeClientComputerNameA ; Win 7 +;@ stdcall GetNamedPipeClientComputerNameW ; Win 7 +;@ stdcall GetNamedPipeClientProcessId ; Win 7 +;@ stdcall GetNamedPipeClientSessionId ; Win 7 +@ stdcall GetNamedPipeHandleStateA(long ptr ptr ptr ptr str long) +@ stdcall GetNamedPipeHandleStateW(long ptr ptr ptr ptr wstr long) +@ stdcall GetNamedPipeInfo(long ptr ptr ptr ptr) +;@ stdcall GetNamedPipeServerProcessId ; Win 7 +;@ stdcall GetNamedPipeServerSessionId ; Win 7 +@ stdcall GetNativeSystemInfo(ptr) +;@ stdcall -arch=x86_64 GetNextUmsListItem +@ stdcall GetNextVDMCommand(long) +@ stdcall GetNlsSectionName(long long long str str long) ; missing in Win 7 +@ stdcall GetNumaAvailableMemory(ptr long ptr) ; missing in Win 7 +@ stdcall GetNumaAvailableMemoryNode(long ptr) +;@ stdcall GetNumaAvailableMemoryNodeEx ; Win 7 +@ stdcall GetNumaHighestNodeNumber(ptr) +;@ stdcall GetNumaNodeNumberFromHandle ; Win 7 +@ stdcall GetNumaNodeProcessorMask(long ptr) +;@ stdcall GetNumaNodeProcessorMaskEx ; Win 7 +@ stdcall GetNumaProcessorMap(ptr long ptr) ; missing in Win 7 +@ stdcall GetNumaProcessorNode(long ptr) +;@ stdcall GetNumaProcessorNodeEx ; Win 7 +;@ stdcall GetNumaProximityNode ; Win 7 +;@ stdcall GetNumaProximityNodeEx ; Win 7 +@ stdcall GetNumberFormatA(long long str ptr ptr long) +;@ stdcall GetNumberFormatEx ; Win 7 +@ stdcall GetNumberFormatW(long long wstr ptr ptr long) +@ stdcall GetNumberOfConsoleFonts() +@ stdcall GetNumberOfConsoleInputEvents(long ptr) +@ stdcall GetNumberOfConsoleMouseButtons(ptr) +@ stdcall GetOEMCP() +@ stdcall GetOverlappedResult(long ptr ptr long) +;@ stdcall GetPhysicallyInstalledSystemMemory ; Win 7 +@ stdcall GetPriorityClass(long) +@ stdcall GetPrivateProfileIntA(str str long str) +@ stdcall GetPrivateProfileIntW(wstr wstr long wstr) +@ stdcall GetPrivateProfileSectionA(str ptr long str) +@ stdcall GetPrivateProfileSectionNamesA(ptr long str) +@ stdcall GetPrivateProfileSectionNamesW(ptr long wstr) +@ stdcall GetPrivateProfileSectionW(wstr ptr long wstr) +@ stdcall GetPrivateProfileStringA(str str str ptr long str) +@ stdcall GetPrivateProfileStringW(wstr wstr wstr ptr long wstr) +@ stdcall GetPrivateProfileStructA (str str ptr long str) +@ stdcall GetPrivateProfileStructW(wstr wstr ptr long wstr) +@ stdcall GetProcAddress(long str) +@ stdcall GetProcessAffinityMask(long ptr ptr) +;@ stdcall GetProcessFlags(long) +;@ stdcall GetProcessDEPPolicy ; Win 7 +;@ stdcall GetProcessGroupAffinity ; Win 7 +@ stdcall GetProcessHandleCount(long ptr) +@ stdcall GetProcessHeap() +@ stdcall GetProcessHeaps(long ptr) +@ stdcall GetProcessId(long) +;@ stdcall GetProcessIdOfThread ; Win 7 +@ stdcall GetProcessIoCounters(long ptr) +;@ stdcall GetProcessPreferredUILanguages ; Win 7 +@ stdcall GetProcessPriorityBoost(long ptr) +@ stdcall GetProcessShutdownParameters(ptr ptr) +@ stdcall GetProcessTimes(long ptr ptr ptr ptr) +@ stdcall GetProcessVersion(long) +@ stdcall GetProcessWorkingSetSize(long ptr ptr) +;@ stdcall GetProcessWorkingSetSizeEx ; Win 7 +;@ stdcall GetProcessorSystemCycleTime ; Win 7 +;@ stdcall GetProductInfo(long long long long ptr) ; Win 7 +;@ stub GetProductName +@ stdcall GetProfileIntA(str str long) +@ stdcall GetProfileIntW(wstr wstr long) +@ stdcall GetProfileSectionA(str ptr long) +@ stdcall GetProfileSectionW(wstr ptr long) +@ stdcall GetProfileStringA(str str str ptr long) +@ stdcall GetProfileStringW(wstr wstr wstr ptr long) +@ stdcall GetQueuedCompletionStatus(long ptr ptr ptr long) +;@ stdcall GetQueuedCompletionStatusEx ; Win 7 +;@ stub GetLSCallbackTarget ; missing in XP SP3 and Win 7 +;@ stub GetLSCallbackTemplate ; missing in XP SP3 and Win 7 +@ stdcall GetShortPathNameA(str ptr long) +@ stdcall GetShortPathNameW(wstr ptr long) +@ stdcall GetStartupInfoA(ptr) +@ stdcall GetStartupInfoW(ptr) +@ stdcall GetStdHandle(long) +;@ stdcall GetStringScripts ; Win 7 +@ stdcall GetStringTypeA(long long str long ptr) +@ stdcall GetStringTypeExA(long long str long ptr) +@ stdcall GetStringTypeExW(long long wstr long ptr) +@ stdcall GetStringTypeW(long wstr long ptr) +;@ stdcall GetSystemDEPPolicy ; Win 7 +@ stdcall GetSystemDefaultLCID() +@ stdcall GetSystemDefaultLangID() +;@ stdcall GetSystemDefaultLocaleName ; Win 7 +@ stdcall GetSystemDefaultUILanguage() +@ stdcall GetSystemDirectoryA(ptr long) +@ stdcall GetSystemDirectoryW(ptr long) +;@ stdcall GetSystemFileCacheSize ; Win 7 +;@ stdcall GetSystemFirmwareTable ; Win 7 +@ stdcall GetSystemInfo(ptr) +@ stdcall GetSystemPowerStatus(ptr) +;@ stdcall GetSystemPreferredUILanguages ; Win 7 +@ stdcall GetSystemRegistryQuota(ptr ptr) +@ stdcall GetSystemTime(ptr) +@ stdcall GetSystemTimeAdjustment(ptr ptr ptr) +@ stdcall GetSystemTimeAsFileTime(ptr) +@ stdcall GetSystemTimes(ptr ptr ptr) +@ stdcall GetSystemWindowsDirectoryA(ptr long) +@ stdcall GetSystemWindowsDirectoryW(ptr long) +@ stdcall GetSystemWow64DirectoryA(ptr long) +@ stdcall GetSystemWow64DirectoryW(ptr long) +@ stdcall GetTapeParameters(ptr long ptr ptr) +@ stdcall GetTapePosition(ptr long ptr ptr ptr) +@ stdcall GetTapeStatus(ptr) +@ stdcall GetTempFileNameA(str str long ptr) +@ stdcall GetTempFileNameW(wstr wstr long ptr) +@ stdcall GetTempPathA(long ptr) +@ stdcall GetTempPathW(long ptr) +@ stdcall GetThreadContext(long ptr) +;@ stdcall GetThreadErrorMode() ; Win 7 +;@ stdcall GetThreadGroupAffinity ; Win 7 +@ stdcall GetThreadIOPendingFlag(long ptr) +@ stdcall GetThreadId(ptr) +;@ stdcall GetThreadIdealProcessorEx ; Win 7 +@ stdcall GetThreadLocale() +;@ stdcall GetThreadPreferredUILanguages ; Win 7 +@ stdcall GetThreadPriority(long) +@ stdcall GetThreadPriorityBoost(long ptr) +@ stdcall GetThreadSelectorEntry(long long ptr) +@ stdcall GetThreadTimes(long ptr ptr ptr ptr) +;@ stdcall GetThreadUILanguage ; Win 7 +@ stdcall GetTickCount() +@ stdcall -ret64 GetTickCount64() +@ stdcall GetTimeFormatA(long long ptr str ptr long) +;@ stdcall GetTimeFormatEx ; Win 7 +@ stdcall GetTimeFormatW(long long ptr wstr ptr long) +@ stdcall GetTimeZoneInformation(ptr) +;@ stdcall GetTimeZoneInformationForYear ; Win 7 +;@ stdcall GetUILanguageInfo ; Win 7 +;@ stdcall -arch=x86_64 GetUmsCompletionListEvent +@ stdcall GetUserDefaultLCID() +@ stdcall GetUserDefaultLangID() +;@ stdcall GetUserDefaultLocaleName ; Win 7 +@ stdcall GetUserDefaultUILanguage() +@ stdcall GetUserGeoID(long) +;@ stdcall GetUserPreferredUILanguages ; Win 7 +@ stdcall GetVDMCurrentDirectories(long long) +@ stdcall GetVersion() +@ stdcall GetVersionExA(ptr) +@ stdcall GetVersionExW(ptr) +@ stdcall GetVolumeInformationA(str ptr long ptr ptr ptr ptr long) +;@ stdcall GetVolumeInformationByHandleW ; Win 7 +@ stdcall GetVolumeInformationW(wstr ptr long ptr ptr ptr ptr long) +@ stdcall GetVolumeNameForVolumeMountPointA(str ptr long) +@ stdcall GetVolumeNameForVolumeMountPointW(wstr ptr long) +@ stdcall GetVolumePathNameA(str ptr long) +@ stdcall GetVolumePathNameW(wstr ptr long) +@ stdcall GetVolumePathNamesForVolumeNameA(str str long ptr) +@ stdcall GetVolumePathNamesForVolumeNameW(wstr wstr long ptr) +@ stdcall GetWindowsDirectoryA(ptr long) +@ stdcall GetWindowsDirectoryW(ptr long) +@ stdcall GetWriteWatch(long ptr long ptr ptr ptr) +@ stdcall GlobalAddAtomA(str) +@ stdcall GlobalAddAtomW(wstr) +@ stdcall GlobalAlloc(long long) +@ stdcall GlobalCompact(long) +@ stdcall GlobalDeleteAtom(long) +@ stdcall GlobalFindAtomA(str) +@ stdcall GlobalFindAtomW(wstr) +@ stdcall GlobalFix(long) +@ stdcall GlobalFlags(long) +@ stdcall GlobalFree(long) +@ stdcall GlobalGetAtomNameA(long ptr long) +@ stdcall GlobalGetAtomNameW(long ptr long) +@ stdcall GlobalHandle(ptr) +@ stdcall GlobalLock(long) +@ stdcall GlobalMemoryStatus(ptr) +@ stdcall GlobalMemoryStatusEx(ptr) +@ stdcall GlobalReAlloc(long long long) +@ stdcall GlobalSize(long) +@ stdcall GlobalUnWire(long) +@ stdcall GlobalUnfix(long) +@ stdcall GlobalUnlock(long) +@ stdcall GlobalWire(long) +@ stdcall Heap32First(ptr long long) +@ stdcall Heap32ListFirst(long ptr) +@ stdcall Heap32ListNext(long ptr) +@ stdcall Heap32Next(ptr) +@ stdcall HeapAlloc(long long long) ntdll.RtlAllocateHeap +@ stdcall HeapCompact(long long) +@ stdcall HeapCreate(long long long) +@ stdcall HeapCreateTagsW(long long wstr wstr) ; missing in Win 7 +@ stdcall HeapDestroy(long) +@ stdcall HeapExtend(long long ptr long) ; missing in Win 7 +@ stdcall HeapFree(long long long) ntdll.RtlFreeHeap +@ stdcall HeapLock(long) +@ stdcall HeapQueryInformation(long long ptr long ptr) +@ stdcall HeapQueryTagW(long long long long ptr) ; missing in Win 7 +@ stdcall HeapReAlloc(long long ptr long) ntdll.RtlReAllocateHeap +;@ stub HeapSetFlags ; missing in XP SP3 and Win 7 +@ stdcall HeapSetInformation(ptr long ptr long) +@ stdcall HeapSize(long long ptr) ntdll.RtlSizeHeap +@ stdcall HeapSummary(long long ptr) +@ stdcall HeapUnlock(long) +@ stdcall HeapUsage(long long long long ptr) ; missing in Win 7 +@ stdcall HeapValidate(long long ptr) +@ stdcall HeapWalk(long ptr) +;@ stdcall IdnToAscii ; Win 7 +;@ stdcall IdnToNameprepUnicode ; Win 7 +;@ stdcall IdnToUnicode ; Win 7 +@ stdcall InitAtomTable(long) +;@ stdcall InitOnceBeginInitialize ; Win 7 +;@ stdcall InitOnceComplete ; Win 7 +;@ stdcall InitOnceExecuteOnce ; Win 7 +;@ stdcall InitOnceInitialize ntdll.RtlRunOnceInitialize ; Win 7 +;@ stdcall InitializeConditionVariable ntdll.RtlInitializeConditionVariable ; Win 7 +@ stdcall InitializeCriticalSection(ptr) ; FIXME: ntdll.RtlInitializeCriticalSection +@ stdcall InitializeCriticalSectionAndSpinCount(ptr long) +@ stdcall InitializeCriticalSectionEx(ptr long long) +;@ stdcall InitializeExtendedContext ; Win 7 +;@ stdcall InitializeProcThreadAttributeList api-ms-win-core-processthreads-l1-1-0.InitializeProcThreadAttributeList ; Win 7 +@ stdcall InitializeSListHead(ptr) ntdll.RtlInitializeSListHead +@ stdcall InitializeSRWLock(ptr) ntdll.RtlInitializeSRWLock +@ stdcall -arch=i386 InterlockedCompareExchange (ptr long long) +;@ stdcall -arch=i386 -ret64 InterlockedCompareExchange64(ptr double double) ntdll.RtlInterlockedCompareExchange64 +@ stdcall -arch=i386 InterlockedDecrement(ptr) +@ stdcall -arch=i386 InterlockedExchange(ptr long) +@ stdcall -arch=i386 InterlockedExchangeAdd (ptr long ) +@ stdcall InterlockedFlushSList(ptr) ntdll.RtlInterlockedFlushSList +@ stdcall -arch=i386 InterlockedIncrement(ptr) +@ stdcall InterlockedPopEntrySList(ptr) ntdll.RtlInterlockedPopEntrySList +@ stdcall InterlockedPushEntrySList(ptr ptr) ntdll.RtlInterlockedPushEntrySList +;@ stdcall InterlockedPushListSList ntdll.RtlInterlockedPushListSList ; Win 7 +@ stdcall InvalidateConsoleDIBits(long long) +;@ stub InvalidateNSCache ; missing in XP SP3 and Win 7 +@ stdcall IsBadCodePtr(ptr) +@ stdcall IsBadHugeReadPtr(ptr long) +@ stdcall IsBadHugeWritePtr(ptr long) +@ stdcall IsBadReadPtr(ptr long) +@ stdcall IsBadStringPtrA(ptr long) +@ stdcall IsBadStringPtrW(ptr long) +@ stdcall IsBadWritePtr(ptr long) +;@ stdcall IsCalendarLeapDay ; Win 7 +;@ stdcall IsCalendarLeapMonth ; Win 7 +;@ stdcall IsCalendarLeapYear ; Win 7 +@ stdcall IsDBCSLeadByte(long) +@ stdcall IsDBCSLeadByteEx(long long) +@ stdcall IsDebuggerPresent() +;@ stdcall IsNLSDefinedString ; Win 7 +;@ stdcall IsNormalizedString ; Win 7 +@ stdcall IsProcessInJob(long long ptr) +@ stdcall IsProcessorFeaturePresent(long) +@ stdcall IsSystemResumeAutomatic() +@ stdcall IsThreadAFiber() +;@ stdcall IsThreadAFiber ; Win 7 +;@ stdcall IsThreadpoolTimerSet ntdll.TpIsTimerSet ; Win 7 +;@ stdcall IsTimeZoneRedirectionEnabled ; Win 7 +;@ stdcall IsValidCalDateTime ; Win 7 +@ stdcall IsValidCodePage(long) +@ stdcall IsValidLanguageGroup(long long) +@ stdcall IsValidLocale(long long) +;@ stdcall IsValidLocaleName ; Win 7 +@ stdcall IsValidUILanguage(long) ; missing in Win 7 +@ stdcall IsWow64Process(ptr ptr) +;@ stdcall K32EmptyWorkingSet ; Win 7 +;@ stdcall K32EnumDeviceDrivers ; Win 7 +;@ stdcall K32EnumPageFilesA ; Win 7 +;@ stdcall K32EnumPageFilesW ; Win 7 +;@ stdcall K32EnumProcessModules ; Win 7 +;@ stdcall K32EnumProcessModulesEx ; Win 7 +;@ stdcall K32EnumProcesses ; Win 7 +;@ stdcall K32GetDeviceDriverBaseNameA ; Win 7 +;@ stdcall K32GetDeviceDriverBaseNameW ; Win 7 +;@ stdcall K32GetDeviceDriverFileNameA ; Win 7 +;@ stdcall K32GetDeviceDriverFileNameW ; Win 7 +;@ stdcall K32GetMappedFileNameA ; Win 7 +;@ stdcall K32GetMappedFileNameW ; Win 7 +;@ stdcall K32GetModuleBaseNameA ; Win 7 +;@ stdcall K32GetModuleBaseNameW ; Win 7 +;@ stdcall K32GetModuleFileNameExA ; Win 7 +;@ stdcall K32GetModuleFileNameExW ; Win 7 +;@ stdcall K32GetModuleInformation ; Win 7 +;@ stdcall K32GetPerformanceInfo ; Win 7 +;@ stdcall K32GetProcessImageFileNameA ; Win 7 +;@ stdcall K32GetProcessImageFileNameW ; Win 7 +;@ stdcall K32GetProcessMemoryInfo ; Win 7 +;@ stdcall K32GetWsChanges ; Win 7 +;@ stdcall K32GetWsChangesEx ; Win 7 +;@ stdcall K32InitializeProcessForWsWatch ; Win 7 +;@ stdcall K32QueryWorkingSet ; Win 7 +;@ stdcall K32QueryWorkingSetEx ; Win 7 +@ stdcall LCIDToLocaleName(long wstr long long) ; needed for wine gecko; missing in XP SP3 +@ stdcall LCMapStringA(long long str long ptr long) +;@ stdcall LCMapStringEx ; Win 7 +@ stdcall LCMapStringW(long long wstr long ptr long) +@ stdcall LZClose(long) +;@ stdcall LZCloseFile ; Win 7 +@ stdcall LZCopy(long long) +;@ stdcall LZCreateFileW ; Win 7 +@ stdcall LZDone() +@ stdcall LZInit(long) +@ stdcall LZOpenFileA(str ptr long) +@ stdcall LZOpenFileW(wstr ptr long) +@ stdcall LZRead(long str long) +@ stdcall LZSeek(long long long) +@ stdcall LZStart() +@ stdcall LeaveCriticalSection(ptr) ntdll.RtlLeaveCriticalSection +;@ stdcall LeaveCriticalSectionWhenCallbackReturns ntdll.TpCallbackLeaveCriticalSectionOnCompletion ; Win 7 +;@ stdcall LoadAppInitDlls ; Win 7 +@ stdcall LoadLibraryA(str) +@ stdcall LoadLibraryExA( str long long) +@ stdcall LoadLibraryExW(wstr long long) +@ stdcall LoadLibraryW(wstr) +@ stdcall LoadModule(str ptr) +@ stdcall LoadResource(long long) +;@ stdcall LoadStringBaseExW ; Win 7 +;@ stdcall LoadStringBaseW ; Win 7 +@ stdcall LocalAlloc(long long) +@ stdcall LocalCompact(long) +@ stdcall LocalFileTimeToFileTime(ptr ptr) +@ stdcall LocalFlags(long) +@ stdcall LocalFree(long) +@ stdcall LocalHandle(ptr) +@ stdcall LocalLock(long) +@ stdcall LocalReAlloc(long long long) +@ stdcall LocalShrink(long long) +@ stdcall LocalSize(long) +@ stdcall LocalUnlock(long) +;@ stub LocaleNameToLCID ; missing in XP SP3 +;@ stdcall LocateExtendedFeature api-ms-win-core-xstate-l1-1-0.RtlLocateExtendedFeature ; Win 7 +;@ stdcall LocateLegacyContext api-ms-win-core-xstate-l1-1-0.RtlLocateLegacyContext ; Win 7 +@ stdcall LockFile(long long long long long) +@ stdcall LockFileEx(long long long long long ptr) +@ stdcall LockResource(long) +;@ stdcall MakeCriticalSectionGlobal(ptr) // ??? +@ stdcall MapUserPhysicalPages(ptr long ptr) +@ stdcall MapUserPhysicalPagesScatter(ptr long ptr) +@ stdcall MapViewOfFile(long long long long long) +@ stdcall MapViewOfFileEx(long long long long long ptr) +;@ stdcall MapViewOfFileExNuma ; Win 7 +@ stdcall Module32First(long ptr) +@ stdcall Module32FirstW(long ptr) +@ stdcall Module32Next(long ptr) +@ stdcall Module32NextW(long ptr) +@ stdcall MoveFileA(str str) +@ stdcall MoveFileExA(str str long) +@ stdcall MoveFileExW(wstr wstr long) +;@ stdcall MoveFileTransactedA ; Win 7 +;@ stdcall MoveFileTransactedW ; Win 7 +@ stdcall MoveFileW(wstr wstr) +@ stdcall MoveFileWithProgressA(str str ptr ptr long) +@ stdcall MoveFileWithProgressW(wstr wstr ptr ptr long) +@ stdcall MulDiv(long long long) +@ stdcall MultiByteToWideChar(long long str long ptr long) +@ stdcall NeedCurrentDirectoryForExePathA(str) +@ stdcall NeedCurrentDirectoryForExePathW(wstr) +;@ stdcall NlsCheckPolicy ; Win 7 +@ stdcall NlsConvertIntegerToString(long long long wstr long) ; missing in Win 7 +;@ stdcall NlsEventDataDescCreate ; Win 7 +@ stdcall NlsGetCacheUpdateCount() +;@ stub NlsResetProcessLocale ; missing in XP SP3 and Win 7 +;@ stdcall NlsUpdateLocale ; Win 7 +;@ stdcall NlsUpdateSystemLocale ; Win 7 +;@ stdcall NlsWriteEtwEvent ; Win 7 +;@ stdcall NormalizeString ; Win 7 +;@ stdcall NotifyMountMgr ; Win 7 +;@ stub NotifyNLSUserCache ; missing in XP SP3 and win 7 +;@ stdcall NotifyUILanguageChange ; Win 7 +@ stdcall NumaVirtualQueryNode(long long long long) ; missing in win 7 +@ stdcall OpenConsoleW(wstr long long long) +@ stdcall OpenDataFile(long long) ; missing in Win 7 +@ stdcall OpenEventA(long long str) +@ stdcall OpenEventW(long long wstr) +@ stdcall OpenFile(str ptr long) +;@ stdcall OpenFileById ; Win 7 +@ stdcall OpenFileMappingA(long long str) +@ stdcall OpenFileMappingW(long long wstr) +@ stdcall OpenJobObjectA(long long str) +@ stdcall OpenJobObjectW(long long wstr) +@ stdcall OpenMutexA(long long str) +@ stdcall OpenMutexW(long long wstr) +;@ stdcall OpenPrivateNamespaceA ; Win 7 +;@ stdcall OpenPrivateNamespaceW ; Win 7 +@ stdcall OpenProcess(long long long) +;@ stdcall OpenProcessToken api-ms-win-core-processthreads-l1-1-0.OpenProcessToken ; Win 7 +@ stdcall OpenProfileUserMapping() +@ stdcall OpenSemaphoreA(long long str) +@ stdcall OpenSemaphoreW(long long wstr) +@ stdcall OpenThread(long long long) +;@ stdcall OpenThreadToken api-ms-win-core-processthreads-l1-1-0.OpenThreadToken ; win 7 +@ stdcall OpenWaitableTimerA(long long str) +@ stdcall OpenWaitableTimerW(long long wstr) +@ stdcall OutputDebugStringA(str) +@ stdcall OutputDebugStringW(wstr) +@ stdcall PeekConsoleInputA(ptr ptr long ptr) +@ stdcall PeekConsoleInputW(ptr ptr long ptr) +@ stdcall PeekNamedPipe(long ptr long ptr ptr ptr) +@ stdcall PostQueuedCompletionStatus(long long ptr ptr) +;@ stdcall PowerClearRequest ; Win 7 +;@ stdcall PowerCreateRequest ; Win 7 +;@ stdcall PowerSetRequest ; Win 7 +@ stdcall PrepareTape(ptr long long) +@ stdcall PrivCopyFileExW(wstr wstr ptr ptr long long) +@ stdcall PrivMoveFileIdentityW(long long long) +@ stdcall Process32First (ptr ptr) +@ stdcall Process32FirstW (ptr ptr) +@ stdcall Process32Next (ptr ptr) +@ stdcall Process32NextW (ptr ptr) +@ stdcall ProcessIdToSessionId(long ptr) +@ stdcall PulseEvent(long) +@ stdcall PurgeComm(long long) +;@ stdcall QueryActCtxSettingsW ; Win 7 +;@ stdcall QueryActCtxW(long ptr ptr long ptr long ptr) +@ stdcall QueryActCtxW(long ptr ptr long ptr long ptr) +@ stdcall QueryDepthSList(ptr) ntdll.RtlQueryDepthSList +@ stdcall QueryDosDeviceA(str ptr long) +@ stdcall QueryDosDeviceW(wstr ptr long) +@ stdcall QueryFullProcessImageNameA(ptr long str ptr) ; Vista and later +@ stdcall QueryFullProcessImageNameW(ptr long wstr ptr) ; Vista and later +;@ stdcall QueryIdleProcessorCycleTime ; Win 7 +;@ stdcall QueryIdleProcessorCycleTimeEx ; Win 7 +@ stdcall QueryInformationJobObject(long long ptr long ptr) +@ stdcall QueryMemoryResourceNotification(ptr ptr) +;@ stub QueryNumberOfEventLogRecords ; missing in XP SP3 and Win 7 +;@ stub QueryOldestEventLogRecord ; missing in XP SP3 and Win 7 +@ stdcall QueryPerformanceCounter(ptr) +@ stdcall QueryPerformanceFrequency(ptr) +;@ stdcall QueryProcessAffinityUpdateMode ; Win 7 +;@ stdcall QueryProcessCycleTime ; Win 7 +;@ stdcall QueryThreadCycleTime ; Win 7 +;@ stdcall QueryThreadProfiling ; Win 7 +;@ stdcall QueryThreadpoolStackInformation ; Win 7 +;@ stdcall -arch=x86_64 QueryUmsThreadInformation +;@ stdcall QueryUnbiasedInterruptTime ; Win 7 +@ stdcall QueryWin31IniFilesMappedToRegistry(long long long long) ; missing in Win 7 +@ stdcall QueueUserAPC(ptr long long) +@ stdcall QueueUserWorkItem(ptr ptr long) +@ stdcall RaiseException(long long long ptr) +;@ stdcall RaiseFailFastException ; Win 7 +@ stdcall ReOpenFile(ptr long long long) +@ stdcall ReadConsoleA(long ptr long ptr ptr) +@ stdcall ReadConsoleInputA(long ptr long ptr) +@ stdcall ReadConsoleInputExA(long ptr long ptr long) +@ stdcall ReadConsoleInputExW(long ptr long ptr long) +@ stdcall ReadConsoleInputW(long ptr long ptr) +@ stdcall ReadConsoleOutputA(long ptr long long ptr) +@ stdcall ReadConsoleOutputAttribute(long ptr long long ptr) +@ stdcall ReadConsoleOutputCharacterA(long ptr long long ptr) +@ stdcall ReadConsoleOutputCharacterW(long ptr long long ptr) +@ stdcall ReadConsoleOutputW(long ptr long long ptr) +@ stdcall ReadConsoleW(long ptr long ptr ptr) +@ stdcall ReadDirectoryChangesW(long ptr long long long ptr ptr ptr) +@ stdcall ReadFile(long ptr long ptr ptr) +@ stdcall ReadFileEx(long ptr long ptr ptr) +@ stdcall ReadFileScatter(long ptr long ptr ptr) +@ stdcall ReadProcessMemory(long ptr ptr long ptr) +;@ stdcall ReadThreadProfilingData ; Win 7 +;@ stdcall RegCloseKey ; Win 7 +;@ stdcall RegCreateKeyExA ; Win 7 +;@ stdcall RegCreateKeyExW ; Win 7 +;@ stdcall RegDeleteKeyExA ; Win 7 +;@ stdcall RegDeleteKeyExW ; Win 7 +;@ stdcall RegDeleteTreeA ; Win 7 +;@ stdcall RegDeleteTreeW ; Win 7 +;@ stdcall RegDeleteValueA ; Win 7 +;@ stdcall RegDeleteValueW ; Win 7 +;@ stdcall RegDisablePredefinedCacheEx ; Win 7 +;@ stdcall RegEnumKeyExA ; Win 7 +;@ stdcall RegEnumKeyExW ; Win 7 +;@ stdcall RegEnumValueA ; Win 7 +;@ stdcall RegEnumValueW ; Win 7 +;@ stdcall RegFlushKey ; Win 7 +;@ stdcall RegGetKeySecurity ; Win 7 +;@ stdcall RegGetValueA ; Win 7 +;@ stdcall RegGetValueW ; Win 7 +;@ stdcall RegKrnGetGlobalState ; Win 7 +;@ stdcall RegKrnInitialize ; Win 7 +;@ stdcall RegLoadKeyA ; Win 7 +;@ stdcall RegLoadKeyW ; Win 7 +;@ stdcall RegLoadMUIStringA ; Win 7 +;@ stdcall RegLoadMUIStringW ; Win 7 +;@ stdcall RegNotifyChangeKeyValue ; Win 7 +;@ stdcall RegOpenCurrentUser ; Win 7 +;@ stdcall RegOpenKeyExA ; Win 7 +;@ stdcall RegOpenKeyExW ; Win 7 +;@ stdcall RegOpenUserClassesRoot ; Win 7 +;@ stdcall RegQueryInfoKeyA ; Win 7 +;@ stdcall RegQueryInfoKeyW ; Win 7 +;@ stdcall RegQueryValueExA ; Win 7 +;@ stdcall RegQueryValueExW ; Win 7 +;@ stdcall RegRestoreKeyA ; Win 7 +;@ stdcall RegRestoreKeyW ; Win 7 +;@ stdcall RegSaveKeyExA ; Win 7 +;@ stdcall RegSaveKeyExW ; Win 7 +;@ stdcall RegSetKeySecurity ; Win 7 +;@ stdcall RegSetValueExA ; Win 7 +;@ stdcall RegSetValueExW ; Win 7 +;@ stdcall RegUnLoadKeyA ; Win 7 +;@ stdcall RegUnLoadKeyW ; Win 7 +;@ stdcall RegisterApplicationRecoveryCallback ; Win 7 +@ stdcall RegisterApplicationRestart(wstr long) +@ stdcall RegisterConsoleIME(ptr ptr) +@ stdcall RegisterConsoleOS2(long) +@ stdcall RegisterConsoleVDM(long long long long long long long long long long long) +;@ stub RegisterServiceProcess ; missing in XP SP3 and Win 7 +;@ stub RegisterSysMsgHandler ; missing in XP SP3 and win 7 +@ stdcall RegisterWaitForInputIdle(ptr) +@ stdcall RegisterWaitForSingleObject(ptr long ptr ptr long long) +@ stdcall RegisterWaitForSingleObjectEx(long ptr ptr long long) +@ stdcall RegisterWowBaseHandlers(long) +@ stdcall RegisterWowExec(long) +;@ stdcall ReinitializeCriticalSection(ptr) ; ??? +@ stdcall ReleaseActCtx(ptr) +@ stdcall ReleaseMutex(long) +;@ stdcall ReleaseMutexWhenCallbackReturns ntdll.TpCallbackReleaseMutexOnCompletion ; Win 7 +@ stdcall ReleaseSRWLockExclusive(ptr) ntdll.RtlReleaseSRWLockExclusive +@ stdcall ReleaseSRWLockShared(ptr) ntdll.RtlReleaseSRWLockShared +@ stdcall ReleaseSemaphore(long long ptr) +;@ stdcall ReleaseSemaphoreWhenCallbackReturns ntdll.TpCallbackReleaseSemaphoreOnCompletion ; Win 7 +@ stdcall RemoveDirectoryA(str) +;@ stdcall RemoveDirectoryTransactedA ; Win 7 +;@ stdcall RemoveDirectoryTransactedW ; Win 7 +@ stdcall RemoveDirectoryW(wstr) +@ stdcall RemoveLocalAlternateComputerNameA(str long) +@ stdcall RemoveLocalAlternateComputerNameW(wstr long) +;@ stdcall RemoveSecureMemoryCacheCallback ; Win 7 +@ stdcall RemoveVectoredContinueHandler(ptr) ntdll.RtlRemoveVectoredContinueHandler +@ stdcall RemoveVectoredExceptionHandler(ptr) ntdll.RtlRemoveVectoredExceptionHandler +@ stdcall ReplaceFile(wstr wstr wstr long ptr ptr) ReplaceFileW +@ stdcall ReplaceFileA(str str str long ptr ptr) +@ stdcall ReplaceFileW(wstr wstr wstr long ptr ptr) +;@ stdcall ReplacePartitionUnit ; Win 7 +@ stdcall RequestDeviceWakeup(long) +@ stdcall RequestWakeupLatency(long) +@ stdcall ResetEvent(long) +@ stdcall ResetWriteWatch(ptr long) +;@ stdcall ResolveLocaleName ; Win 7 +@ stdcall RestoreLastError(long) ntdll.RtlRestoreLastWin32Error +@ stdcall ResumeThread(long) +@ cdecl -arch=x86_64 RtlAddFunctionTable(ptr long long) ntdll.RtlAddFunctionTable +@ stdcall -register RtlCaptureContext(ptr) ntdll.RtlCaptureContext +@ stdcall RtlCaptureStackBackTrace(long long ptr ptr) ntdll.RtlCaptureStackBackTrace +@ stdcall -arch=x86_64 RtlCompareMemory(ptr ptr ptr) +@ stdcall -arch=x86_64 RtlCopyMemory(ptr ptr ptr) +@ stdcall -arch=x86_64 RtlDeleteFunctionTable(ptr) +@ stdcall RtlFillMemory(ptr long long) ntdll.RtlFillMemory +@ stdcall -arch=x86_64 RtlInstallFunctionTableCallback(double double long ptr ptr ptr) +@ stdcall -arch=x86_64 RtlLookupFunctionEntry(ptr ptr ptr) ntdll.RtlLookupFunctionEntry +@ stdcall RtlMoveMemory(ptr ptr long) ntdll.RtlMoveMemory +@ stdcall -arch=x86_64 RtlPcToFileHeader(ptr ptr) ntdll.RtlPcToFileHeader +@ stdcall -arch=x86_64 RtlRaiseException(ptr) ntdll.RtlRaiseException +@ stdcall -arch=x86_64 RtlRestoreContext(ptr ptr) ntdll.RtlRestoreContext +@ stdcall RtlUnwind(ptr ptr ptr long) ntdll.RtlUnwind +@ stdcall -arch=x86_64 RtlUnwindEx(ptr ptr ptr ptr ptr ptr) ntdll.RtlUnwindEx +@ stdcall -arch=x86_64 RtlVirtualUnwind(ptr ptr ptr long) ntdll.RtlVirtualUnwind +@ stdcall RtlZeroMemory(ptr long) ntdll.RtlZeroMemory +@ stdcall ScrollConsoleScreenBufferA(long ptr ptr ptr ptr) +@ stdcall ScrollConsoleScreenBufferW(long ptr ptr ptr ptr) +@ stdcall SearchPathA(str str str long ptr ptr) +@ stdcall SearchPathW(wstr wstr wstr long ptr ptr) +@ stdcall SetCPGlobal(long) ; missing in Win 7 +@ stdcall SetCalendarInfoA(long long long str) +@ stdcall SetCalendarInfoW(long long long wstr) +@ stdcall SetClientTimeZoneInformation(ptr) +@ stdcall SetComPlusPackageInstallStatus(ptr) +@ stdcall SetCommBreak(long) +@ stdcall SetCommConfig(long ptr long) +@ stdcall SetCommMask(long ptr) +@ stdcall SetCommState(long ptr) +@ stdcall SetCommTimeouts(long ptr) +@ stdcall SetComputerNameA(str) +@ stdcall SetComputerNameExA(long str) +@ stdcall SetComputerNameExW(long wstr) +@ stdcall SetComputerNameW(wstr) +@ stdcall SetConsoleActiveScreenBuffer(long) +@ stdcall SetConsoleCP(long) +@ stdcall SetConsoleCommandHistoryMode(long) ; missing in win 7 +@ stdcall SetConsoleCtrlHandler(ptr long) +@ stdcall SetConsoleCursor(long long) +@ stdcall SetConsoleCursorInfo(long ptr) +@ stdcall SetConsoleCursorMode(long long long) +@ stdcall SetConsoleCursorPosition(long long) +@ stdcall SetConsoleDisplayMode(long long ptr) +@ stdcall SetConsoleFont(long long) +@ stdcall SetConsoleHardwareState(long long long) +@ stdcall SetConsoleHistoryInfo(ptr) +@ stdcall SetConsoleIcon(ptr) +@ stdcall SetConsoleInputExeNameA(ptr) +@ stdcall SetConsoleInputExeNameW(ptr) +@ stdcall SetConsoleKeyShortcuts(long long long long) +@ stdcall SetConsoleLocalEUDC(long long long long) +@ stdcall SetConsoleMaximumWindowSize(long long) +@ stdcall SetConsoleMenuClose(long) +@ stdcall SetConsoleMode(long long) +@ stdcall SetConsoleNlsMode(long long) +@ stdcall SetConsoleNumberOfCommandsA(long long) +@ stdcall SetConsoleNumberOfCommandsW(long long) +@ stdcall SetConsoleOS2OemFormat(long) +@ stdcall SetConsoleOutputCP(long) +@ stdcall SetConsolePalette(long long long) +;@ stdcall SetConsoleScreenBufferInfoEx ; Win 7 +@ stdcall SetConsoleScreenBufferSize(long long) +@ stdcall SetConsoleTextAttribute(long long) +@ stdcall SetConsoleTitleA(str) +@ stdcall SetConsoleTitleW(wstr) +@ stdcall SetConsoleWindowInfo(long long ptr) +@ stdcall SetCriticalSectionSpinCount(ptr long) ntdll.RtlSetCriticalSectionSpinCount +;@ stdcall SetCurrentConsoleFontEx ; Win 7 +@ stdcall SetCurrentDirectoryA(str) +@ stdcall SetCurrentDirectoryW(wstr) +;@ stub SetDaylightFlag ; missing in XP SP3 and Win 7 +@ stdcall SetDefaultCommConfigA(str ptr long) +@ stdcall SetDefaultCommConfigW(wstr ptr long) +@ stdcall SetDllDirectoryA(str) +@ stdcall SetDllDirectoryW(wstr) +;@ stdcall SetDynamicTimeZoneInformation ; Win 7 +@ stdcall SetEndOfFile(long) +;@ stdcall SetEnvironmentStringsA ; Win 7 +;@ stdcall SetEnvironmentStringsW ; Win 7 +@ stdcall SetEnvironmentVariableA(str str) +@ stdcall SetEnvironmentVariableW(wstr wstr) +@ stdcall SetErrorMode(long) +@ stdcall SetEvent(long) +;@ stdcall SetEventWhenCallbackReturns ntdll.TpCallbackSetEventOnCompletion ; Win 7 +;@ stdcall SetExtendedFeaturesMask api-ms-win-core-xstate-l1-1-0.RtlSetExtendedFeaturesMask ; Win 7 +@ stdcall SetFileApisToANSI() +@ stdcall SetFileApisToOEM() +@ stdcall SetFileAttributesA(str long) +;@ stdcall SetFileAttributesTransactedA ; Win 7 +;@ stdcall SetFileAttributesTransactedW ; Win 7 +@ stdcall SetFileAttributesW(wstr long) +;@ stdcall SetFileBandwidthReservation ; Win 7 +;@ stdcall SetFileCompletionNotificationModes ; Win 7 +;@ stdcall SetFileInformationByHandle ; Win 7 +;@ stdcall SetFileIoOverlappedRange ; Win 7 +@ stdcall SetFilePointer(long long ptr long) +@ stdcall SetFilePointerEx(long double ptr long) +@ stdcall SetFileShortNameA(long str) +@ stdcall SetFileShortNameW(long wstr) +@ stdcall SetFileTime(long ptr ptr ptr) +@ stdcall SetFileValidData(long double) +@ stdcall SetFirmwareEnvironmentVariableA(str str ptr long) +@ stdcall SetFirmwareEnvironmentVariableW(wstr wstr ptr long) +@ stdcall SetHandleContext(long long) ; missing in Win 7 x64 +@ stdcall SetHandleCount(long) +@ stdcall SetHandleInformation(long long long) +@ stdcall SetInformationJobObject(long long ptr long) +@ stdcall SetLastConsoleEventActive() ; missing in XP SP3 +@ stdcall SetLastError(long) ntdll.RtlSetLastWin32Error +@ stdcall SetLocalPrimaryComputerNameA(long long) ; missing in XP SP3 +@ stdcall SetLocalPrimaryComputerNameW(long long) ; missing in XP SP3 +@ stdcall SetLocalTime(ptr) +@ stdcall SetLocaleInfoA(long long str) +@ stdcall SetLocaleInfoW(long long wstr) +@ stdcall SetMailslotInfo(long long) +@ stdcall SetMessageWaitingIndicator(ptr long) +;@ stdcall SetNamedPipeAttribute ; Win 7 +@ stdcall SetNamedPipeHandleState(long ptr ptr ptr) +@ stdcall SetPriorityClass(long long) +@ stdcall SetProcessAffinityMask(long long) +;@ stdcall SetProcessAffinityUpdateMode ; Win 7 +;@ stdcall SetProcessDEPPolicy ; Win 7 +;@ stdcall SetProcessPreferredUILanguages ; Win 7 +@ stdcall SetProcessPriorityBoost(long long) +@ stdcall SetProcessShutdownParameters(long long) +@ stdcall SetProcessWorkingSetSize(long long long) +;@ stdcall SetProcessWorkingSetSizeEx ; Win 7 +;@ stdcall SetSearchPathMode ; Win 7 +@ stdcall SetStdHandle(long long) +;@ stdcall SetStdHandleEx ; Win 7 +;@ stdcall SetSystemFileCacheSize ; Win 7 +@ stdcall SetSystemPowerState(long long) +@ stdcall SetSystemTime(ptr) +@ stdcall SetSystemTimeAdjustment(long long) +@ stdcall SetTapeParameters(ptr long ptr) +@ stdcall SetTapePosition(ptr long long long long long) +@ stdcall SetTermsrvAppInstallMode(long) +@ stdcall SetThreadAffinityMask(long long) +@ stdcall SetThreadContext(long ptr) +;@ stdcall SetThreadErrorMode(long ptr) ; Win 7 +@ stdcall SetThreadExecutionState(long) +;@ stdcall SetThreadGroupAffinity ; Win 7 +@ stdcall SetThreadIdealProcessor(long long) +;@ stdcall SetThreadIdealProcessorEx ; Win 7 +@ stdcall SetThreadLocale(long) +;@ stdcall SetThreadPreferredUILanguages ; Win 7 +@ stdcall SetThreadPriority(long long) +@ stdcall SetThreadPriorityBoost(long long) +;@ stdcall SetThreadStackGuarantee ; Win 7 +;@ stdcall SetThreadToken api-ms-win-core-processthreads-l1-1-0.SetThreadToken ; Win 7 +@ stdcall SetThreadUILanguage(long) +;@ stdcall SetThreadpoolStackInformation ; Win 7 +;@ stdcall SetThreadpoolThreadMaximum ntdll.TpSetPoolMaxThreads ; Win 7 +;@ stdcall SetThreadpoolThreadMinimum ; Win 7 +;@ stdcall SetThreadpoolTimer ntdll.TpSetTimer ; Win 7 +;@ stdcall SetThreadpoolWait ntdll.TpSetWait ; Win 7 +@ stdcall SetTimeZoneInformation(ptr) +@ stdcall SetTimerQueueTimer(long ptr ptr long long long) +;@ stdcall -arch?x86_64 SetUmsThreadInformation +@ stdcall SetUnhandledExceptionFilter(ptr) +@ stdcall SetUserGeoID(long) +@ stdcall SetVDMCurrentDirectories(long long) +@ stdcall SetVolumeLabelA(str str) +@ stdcall SetVolumeLabelW(wstr wstr) +@ stdcall SetVolumeMountPointA(str str) +@ stdcall SetVolumeMountPointW(wstr wstr) +@ stdcall SetWaitableTimer(long ptr long ptr ptr long) +;@ stdcall SetWaitableTimerEx api-ms-win-core-threadpool-l1-1-0.SetWaitableTimerEx ; Win 7 +@ stdcall SetupComm(long long long) +@ stdcall ShowConsoleCursor(long long) +@ stdcall SignalObjectAndWait(long long long long) +@ stdcall SizeofResource(long long) +@ stdcall Sleep(long) +;@ stdcall SleepConditionVariableCS ; Win 7 +;@ stdcall SleepConditionVariableSRW ; Win 7 +@ stdcall SleepEx(long long) +;@ stdcall SortCloseHandle ; Win 7 +;@ stdcall SortGetHandle ; Win 7 +;@ stdcall StartThreadpoolIo ntdll.TpStartAsyncIoOperation ; Win 7 +;@ stdcall SubmitThreadpoolWork ntdll.TpPostWork ; Win 7 +@ stdcall SuspendThread(long) +@ stdcall SwitchToFiber(ptr) +@ stdcall SwitchToThread() +@ stdcall SystemTimeToFileTime(ptr ptr) +@ stdcall SystemTimeToTzSpecificLocalTime (ptr ptr ptr) +@ stdcall TerminateJobObject(long long) +@ stdcall TerminateProcess(long long) +@ stdcall TerminateThread(long long) +@ stdcall TermsrvAppInstallMode() +@ stdcall Thread32First(long ptr) +@ stdcall Thread32Next(long ptr) +@ stdcall TlsAlloc() +;@ stub TlsAllocInternal ; missing in XP SP3 and Win 7 +@ stdcall TlsFree(long) +;@ stub TlsFreeInternal ; missing in XP SP3 and Win 7 +@ stdcall TlsGetValue(long) +@ stdcall TlsSetValue(long ptr) +@ stdcall Toolhelp32ReadProcessMemory(long ptr ptr long ptr) +@ stdcall TransactNamedPipe(long ptr long ptr long ptr ptr) +@ stdcall TransmitCommChar(long long) +@ stdcall TrimVirtualBuffer(ptr) ; missing in Win 7 +;@ stdcall TryAcquireSRWLockExclusive ntdll.RtlTryAcquireSRWLockExclusive ; Win 7 +;@ stdcall TryAcquireSRWLockShared ntdll.RtlTryAcquireSRWLockShared ; Win 7 +@ stdcall TryEnterCriticalSection(ptr) ntdll.RtlTryEnterCriticalSection +;@ stdcall TrySubmitThreadpoolCallback ; Win 7 +@ stdcall TzSpecificLocalTimeToSystemTime(ptr ptr ptr) +@ stdcall UTRegister(long str str str ptr ptr ptr) +@ stdcall UTUnRegister(long) +;@ stdcall -arch=x86_64 UmsThreadYield +@ stdcall UnhandledExceptionFilter(ptr) +;@ stdcall UninitializeCriticalSection(ptr) ; ??? +@ stdcall UnlockFile(long long long long long) +@ stdcall UnlockFileEx(long long long long ptr) +@ stdcall UnmapViewOfFile(ptr) +;@ stdcall UnregisterApplicationRecoveryCallback ; Win 7 +;@ stdcall UnregisterApplicationRestart ; Win 7 +@ stdcall UnregisterConsoleIME() +@ stdcall UnregisterWait(long) +@ stdcall UnregisterWaitEx(long long) +;@ stdcall UpdateCalendarDayOfWeek ; Win 7 +;@ stdcall UpdateProcThreadAttribute api-ms-win-core-processthreads-l1-1-0.UpdateProcThreadAttribute ; Win 7 +@ stdcall UpdateResourceA(long str str long ptr long) +@ stdcall UpdateResourceW(long wstr wstr long ptr long) +@ stdcall VDMConsoleOperation(long long) +@ stdcall VDMOperationStarted(long) +;@ stub ValidateCType ; missing in XP SP3 and Win 7 +;@ stub ValidateLocale ; missing in XP SP3 and Win 7 +@ stdcall VerLanguageNameA(long str long) +@ stdcall VerLanguageNameW(long wstr long) +@ stdcall -ret64 VerSetConditionMask(long long long long) ntdll.VerSetConditionMask +@ stdcall VerifyConsoleIoHandle(long) +;@ stdcall VerifyScripts ; Win 7 +@ stdcall VerifyVersionInfoA(long long double) +@ stdcall VerifyVersionInfoW(long long double) +@ stdcall VirtualAlloc(ptr long long long) +@ stdcall VirtualAllocEx(long ptr long long long) +;@ stdcall VirtualAllocExNuma ; Win 7 +@ stdcall VirtualBufferExceptionHandler(long long long) ; missing in Win 7 +@ stdcall VirtualFree(ptr long long) +@ stdcall VirtualFreeEx(long ptr long long) +@ stdcall VirtualLock(ptr long) +@ stdcall VirtualProtect(ptr long long ptr) +@ stdcall VirtualProtectEx(long ptr long long ptr) +@ stdcall VirtualQuery(ptr ptr long) +@ stdcall VirtualQueryEx(long ptr ptr long) +@ stdcall VirtualUnlock(ptr long) +;@ stdcall WTSGetActiveConsoleSessionId ; Win 7 +@ stdcall WaitCommEvent(long ptr ptr) +@ stdcall WaitForDebugEvent(ptr long) +@ stdcall WaitForMultipleObjects(long ptr long long) +@ stdcall WaitForMultipleObjectsEx(long ptr long long long) +@ stdcall WaitForSingleObject(long long) +@ stdcall WaitForSingleObjectEx(long long long) +;@ stdcall WaitForThreadpoolIoCallbacks ntdll.TpWaitForIoCompletion ; Win 7 +;@ stdcall WaitForThreadpoolTimerCallbacks ntdll.TpWaitForTimer ; Win 7 +;@ stdcall WaitForThreadpoolWaitCallbacks ntdll.TpWaitForWait ; Win 7 +;@ stdcall WaitForThreadpoolWorkCallbacks ntdll.TpWaitForWork ; Win 7 +@ stdcall WaitNamedPipeA (str long) +@ stdcall WaitNamedPipeW (wstr long) +@ stdcall WakeAllConditionVariable(ptr) ntdll.RtlWakeAllConditionVariable +@ stdcall WakeConditionVariable(ptr) ntdll.RtlWakeConditionVariable +;@ stdcall WerGetFlags ; Win 7 +;@ stdcall WerRegisterFile ; Win 7 +;@ stdcall WerRegisterMemoryBlock ; Win 7 +;@ stdcall WerRegisterRuntimeExceptionModule ; Win 7 +;@ stdcall WerSetFlags ; Win 7 +;@ stdcall WerUnregisterFile ; Win 7 +;@ stdcall WerUnregisterMemoryBlock ; Win 7 +;@ stdcall WerUnregisterRuntimeExceptionModule ; Win 7 +;@ stdcall WerpCleanupMessageMapping ; Win 7 +;@ stdcall WerpInitiateRemoteRecovery ; Win 7 +;@ stdcall WerpNotifyLoadStringResource ; Win 7 +;@ stdcall WerpNotifyLoadStringResourceEx ; Win 7 +;@ stdcall WerpNotifyUseStringResource ; Win 7 +;@ stdcall WerpStringLookup ; Win 7 +@ stdcall WideCharToMultiByte(long long wstr long ptr long ptr ptr) +@ stdcall WinExec(str long) +@ stdcall Wow64DisableWow64FsRedirection(ptr) +@ stdcall Wow64EnableWow64FsRedirection(long) +;@ stdcall Wow64GetThreadContext ; Win 7 +;@ stdcall Wow64GetThreadSelectorEntry ; Win 7 +@ stdcall Wow64RevertWow64FsRedirection(ptr) +;@ stdcall Wow64SetThreadContext ; Win 7 +;@ stdcall Wow64SuspendThread ; Win 7 +@ stdcall WriteConsoleA(long ptr long ptr ptr) +@ stdcall WriteConsoleInputA(long ptr long ptr) +@ stdcall WriteConsoleInputVDMA(long long long long) +@ stdcall WriteConsoleInputVDMW(long long long long) +@ stdcall WriteConsoleInputW(long ptr long ptr) +@ stdcall WriteConsoleOutputA(long ptr long long ptr) +@ stdcall WriteConsoleOutputAttribute(long ptr long long ptr) +@ stdcall WriteConsoleOutputCharacterA(long ptr long long ptr) +@ stdcall WriteConsoleOutputCharacterW(long ptr long long ptr) +@ stdcall WriteConsoleOutputW(long ptr long long ptr) +@ stdcall WriteConsoleW(long ptr long ptr ptr) +@ stdcall WriteFile(long ptr long ptr ptr) +@ stdcall WriteFileEx(long ptr long ptr ptr) +@ stdcall WriteFileGather(long ptr long ptr ptr) +@ stdcall WritePrivateProfileSectionA(str str str) +@ stdcall WritePrivateProfileSectionW(wstr wstr wstr) +@ stdcall WritePrivateProfileStringA(str str str str) +@ stdcall WritePrivateProfileStringW(wstr wstr wstr wstr) +@ stdcall WritePrivateProfileStructA (str str ptr long str) +@ stdcall WritePrivateProfileStructW(wstr wstr ptr long wstr) +@ stdcall WriteProcessMemory(long ptr ptr long ptr) +@ stdcall WriteProfileSectionA(str str) +@ stdcall WriteProfileSectionW(str str) +@ stdcall WriteProfileStringA(str str str) +@ stdcall WriteProfileStringW(wstr wstr wstr) +@ stdcall WriteTapemark(ptr long long long) +@ stdcall WTSGetActiveConsoleSessionId() ; missing in win 7 +@ stdcall ZombifyActCtx(ptr) +;@ stdcall -arch=x86_64 __C_specific_handler ntdll.__C_specific_handler +;@ stdcall -arch=x86_64 __chkstk ntdll.__chkstk +;@ stdcall -arch=x86_64 __misaligned_access ntdll.__misaligned_access +;@ stub _DebugOut ; missing in XP SP3 and Win 7 +;@ stub _DebugPrintf ; missing in XP SP3 and Win 7 +@ stdcall _hread(long ptr long) +@ stdcall _hwrite(long ptr long) +@ stdcall _lclose(long) +@ stdcall _lcreat(str long) +@ stdcall _llseek(long long long) +;@ stdcall -arch=x86_64 _local_unwind ntdll._local_unwind; Win 7 +@ stdcall _lopen(str long) +@ stdcall _lread(long ptr long) _hread +@ stdcall _lwrite(long ptr long) _hwrite +;@ stub dprintf ; missing in XP SP3 and Win 7 +@ stdcall lstrcat(str str) lstrcatA +@ stdcall lstrcatA(str str) +@ stdcall lstrcatW(wstr wstr) +@ stdcall lstrcmp(str str) lstrcmpA +@ stdcall lstrcmpA(str str) +@ stdcall lstrcmpW(wstr wstr) +@ stdcall lstrcmpi(str str) lstrcmpiA +@ stdcall lstrcmpiA(str str) +@ stdcall lstrcmpiW(wstr wstr) +@ stdcall lstrcpy(ptr str) lstrcpyA +@ stdcall lstrcpyA(ptr str) +@ stdcall lstrcpyW(ptr wstr) +@ stdcall lstrcpyn(ptr str long) lstrcpynA +@ stdcall lstrcpynA(ptr str long) +@ stdcall lstrcpynW(ptr wstr long) +@ stdcall lstrlen(str) lstrlenA +@ stdcall lstrlenA(str) +@ stdcall lstrlenW(wstr) +;@ stdcall -arch=x86_64 uaw_lstrcmpW ; Win 7 +;@ stdcall -arch=x86_64 uaw_lstrcmpiW ; Win 7 +;@ stdcall -arch=x86_64 uaw_lstrlenW ; Win 7 +;@ stdcall -arch=x86_64 uaw_wcschr ; Win 7 +;@ stdcall -arch=x86_64 uaw_wcscpy ; Win 7 +;@ stdcall -arch=x86_64 uaw_wcsicmp ; Win 7 +;@ stdcall -arch=x86_64 uaw_wcslen ; Win 7 +;@ stdcall -arch=x86_64 uaw_wcsrchr ; Win 7 + diff --cc dll/win32/user32/resources/obm_btncorners.bmp index 00000000000,e7838624b1a..e7838624b1a mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_btsize.bmp index 00000000000,076e4f870ee..076e4f870ee mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_check.bmp index 00000000000,e9e4fb5de77..e9e4fb5de77 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_dnarrow.bmp index 00000000000,0f3288f3245..0f3288f3245 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_dnarrowd.bmp index 00000000000,51b38e90f75..51b38e90f75 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_dnarrowi.bmp index 00000000000,3cbf4fbba4c..3cbf4fbba4c mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_lfarrow.bmp index 00000000000,6ceef252550..6ceef252550 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_lfarrowd.bmp index 00000000000,bb446c3e040..bb446c3e040 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_lfarrowi.bmp index 00000000000,c81363d484f..c81363d484f mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_old_close.bmp index 00000000000,905e927ec82..905e927ec82 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_old_dnarrow.bmp index 00000000000,bab716f95a6..bab716f95a6 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_old_lfarrow.bmp index 00000000000,4d4c4c62f99..4d4c4c62f99 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_old_reduce.bmp index 00000000000,cee2329995f..cee2329995f mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_old_restore.bmp index 00000000000,f6938f01325..f6938f01325 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_old_rgarrow.bmp index 00000000000,0c05d811730..0c05d811730 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_old_uparrow.bmp index 00000000000,299fadb47a0..299fadb47a0 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_old_zoom.bmp index 00000000000,c1b4eb68b88..c1b4eb68b88 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_reduce.bmp index 00000000000,d0dbf01a44a..d0dbf01a44a mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_reduced.bmp index 00000000000,c39f8e9505a..c39f8e9505a mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_restore.bmp index 00000000000,a22d3ddff44..a22d3ddff44 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_restored.bmp index 00000000000,6958dc2ca15..6958dc2ca15 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_rgarrow.bmp index 00000000000,75cc1ff5308..75cc1ff5308 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_rgarrowd.bmp index 00000000000,abf3f7c99f2..abf3f7c99f2 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_rgarrowi.bmp index 00000000000,a90b836a739..a90b836a739 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_size.bmp index 00000000000,d4eedf965f3..d4eedf965f3 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_trtype.bmp index 00000000000,da41d3233f1..da41d3233f1 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_uparrow.bmp index 00000000000,ce3aa0e29ae..ce3aa0e29ae mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_uparrowd.bmp index 00000000000,872dc323044..872dc323044 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_uparrowi.bmp index 00000000000,6abb8106366..6abb8106366 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_zoom.bmp index 00000000000,a3838ebaea1..a3838ebaea1 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/resources/obm_zoomd.bmp index 00000000000,649958db0c3..649958db0c3 mode 000000,100644..100644 Binary files differ diff --cc dll/win32/user32/user32.rc index 79b9ac45e2f,00000000000..40e4bbe04df mode 100644,000000..100644 --- a/dll/win32/user32/user32.rc +++ b/dll/win32/user32/user32.rc @@@ -1,105 -1,0 +1,136 @@@ +/* $Id$ */ + +#include +#include "include/resource.h" + +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS User API Client Dll\0" +#define REACTOS_STR_INTERNAL_NAME "user32\0" +#define REACTOS_STR_ORIGINAL_FILENAME "user32.dll\0" +#include + +#define IDS_MDI_MOREWINDOWS 13 + +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL + +///////////////////////////////////////////////////////////////////////////// +// +// Cursors +// + +/* New cursor resources */ +100 CURSOR "resources/ocr_normal.cur" +101 CURSOR "resources/ocr_ibeam.cur" +102 CURSOR "resources/ocr_wait.cur" +103 CURSOR "resources/ocr_cross.cur" +104 CURSOR "resources/ocr_up.cur" +105 CURSOR "resources/ocr_sizenwse.cur" +106 CURSOR "resources/ocr_sizenesw.cur" +107 CURSOR "resources/ocr_sizewe.cur" +108 CURSOR "resources/ocr_sizens.cur" +109 CURSOR "resources/ocr_sizeall.cur" +110 CURSOR "resources/ocr_no.cur" +111 CURSOR "resources/ocr_appstarting.cur" +112 CURSOR "resources/ocr_help.cur" +113 CURSOR "resources/ocr_pen.cur" +114 CURSOR "resources/ocr_hand.cur" +115 CURSOR "resources/ocr_icon.cur" +116 CURSOR "resources/ocr_cdautostart.cur" + +/* Compatible cursor resources (will be removed) */ - 32512 CURSOR "resources/ocr_normal.cur" - 32513 CURSOR "resources/ocr_ibeam.cur" - 32514 CURSOR "resources/ocr_wait.cur" - 32515 CURSOR "resources/ocr_cross.cur" - 32516 CURSOR "resources/ocr_up.cur" - 32642 CURSOR "resources/ocr_sizenwse.cur" - 32643 CURSOR "resources/ocr_sizenesw.cur" - 32644 CURSOR "resources/ocr_sizewe.cur" - 32645 CURSOR "resources/ocr_sizens.cur" - 32646 CURSOR "resources/ocr_sizeall.cur" - 32648 CURSOR "resources/ocr_no.cur" - 32650 CURSOR "resources/ocr_appstarting.cur" - 32651 CURSOR "resources/ocr_help.cur" - 32640 CURSOR "resources/ocr_size.cur" - 32641 CURSOR "resources/ocr_icon.cur" - 32649 CURSOR "resources/ocr_hand.cur" ++OCR_NORMAL CURSOR "resources/ocr_normal.cur" ++OCR_IBEAM CURSOR "resources/ocr_ibeam.cur" ++OCR_WAIT CURSOR "resources/ocr_wait.cur" ++OCR_CROSS CURSOR "resources/ocr_cross.cur" ++OCR_UP CURSOR "resources/ocr_up.cur" ++OCR_SIZENWSE CURSOR "resources/ocr_sizenwse.cur" ++OCR_SIZENESW CURSOR "resources/ocr_sizenesw.cur" ++OCR_SIZEWE CURSOR "resources/ocr_sizewe.cur" ++OCR_SIZENS CURSOR "resources/ocr_sizens.cur" ++OCR_SIZEALL CURSOR "resources/ocr_sizeall.cur" ++OCR_NO CURSOR "resources/ocr_no.cur" ++OCR_APPSTARTING CURSOR "resources/ocr_appstarting.cur" ++OCR_HELP CURSOR "resources/ocr_help.cur" ++OCR_SIZE CURSOR "resources/ocr_size.cur" ++OCR_ICON CURSOR "resources/ocr_icon.cur" ++OCR_HAND CURSOR "resources/ocr_hand.cur" + +///////////////////////////////////////////////////////////////////////////// +// +// Icons +// + - 32512 ICON "resources/oic_sample.ico" - 32513 ICON "resources/oic_hand.ico" - 32514 ICON "resources/oic_ques.ico" - 32515 ICON "resources/oic_bang.ico" - 32516 ICON "resources/oic_note.ico" - 32517 ICON "resources/oic_reactos.ico" ++OIC_SAMPLE ICON "resources/oic_sample.ico" ++OIC_HAND ICON "resources/oic_hand.ico" ++OIC_QUES ICON "resources/oic_ques.ico" ++OIC_BANG ICON "resources/oic_bang.ico" ++OIC_NOTE ICON "resources/oic_note.ico" ++OIC_WINLOGO ICON "resources/oic_reactos.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmaps +// + +OBM_CHECKBOXES BITMAP "resources/obm_checkboxes.bmp" +OBM_CLOSE BITMAP "resources/obm_close.bmp" +OBM_COMBO BITMAP "resources/obm_combo.bmp" +OBM_MNARROW BITMAP "resources/obm_mnarrow.bmp" ++OBM_TRTYPE BITMAP "resources/obm_trtype.bmp" ++OBM_LFARROWI BITMAP "resources/obm_lfarrowi.bmp" ++OBM_RGARROWI BITMAP "resources/obm_rgarrowi.bmp" ++OBM_DNARROWI BITMAP "resources/obm_dnarrowi.bmp" ++OBM_UPARROWI BITMAP "resources/obm_uparrowi.bmp" ++OBM_LFARROWD BITMAP "resources/obm_lfarrowd.bmp" ++OBM_RGARROWD BITMAP "resources/obm_rgarrowd.bmp" ++OBM_DNARROWD BITMAP "resources/obm_dnarrowd.bmp" ++OBM_UPARROWD BITMAP "resources/obm_uparrowd.bmp" ++OBM_RESTORED BITMAP "resources/obm_restored.bmp" ++OBM_ZOOMD BITMAP "resources/obm_zoomd.bmp" ++OBM_REDUCED BITMAP "resources/obm_reduced.bmp" ++OBM_RESTORE BITMAP "resources/obm_restore.bmp" ++OBM_ZOOM BITMAP "resources/obm_zoom.bmp" ++OBM_REDUCE BITMAP "resources/obm_reduce.bmp" ++OBM_LFARROW BITMAP "resources/obm_lfarrow.bmp" ++OBM_RGARROW BITMAP "resources/obm_rgarrow.bmp" ++OBM_DNARROW BITMAP "resources/obm_dnarrow.bmp" ++OBM_UPARROW BITMAP "resources/obm_uparrow.bmp" ++OBM_OLD_RESTORE BITMAP "resources/obm_old_restore.bmp" ++OBM_OLD_ZOOM BITMAP "resources/obm_old_zoom.bmp" ++OBM_OLD_REDUCE BITMAP "resources/obm_old_reduce.bmp" ++OBM_BTNCORNERS BITMAP "resources/obm_btncorners.bmp" ++OBM_CHECK BITMAP "resources/obm_check.bmp" ++OBM_BTSIZE BITMAP "resources/obm_btsize.bmp" ++OBM_OLD_LFARROW BITMAP "resources/obm_old_lfarrow.bmp" ++OBM_OLD_RGARROW BITMAP "resources/obm_old_rgarrow.bmp" ++OBM_OLD_DNARROW BITMAP "resources/obm_old_dnarrow.bmp" ++OBM_OLD_UPARROW BITMAP "resources/obm_old_uparrow.bmp" ++OBM_SIZE BITMAP "resources/obm_size.bmp" ++OBM_OLD_CLOSE BITMAP "resources/obm_old_close.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// Languages +// + +#include "lang/bg-BG.rc" +#include "lang/cs-CZ.rc" +#include "lang/da-DK.rc" +#include "lang/de-DE.rc" +#include "lang/el-GR.rc" +#include "lang/en-US.rc" +#include "lang/es-ES.rc" +#include "lang/fr-FR.rc" +#include "lang/hu-HU.rc" +#include "lang/id-ID.rc" +#include "lang/it-IT.rc" +//#include "lang/ja-JP.rc" +#include "lang/lt-LT.rc" +#include "lang/nl-NL.rc" +#include "lang/no-NO.rc" +#include "lang/pl-PL.rc" +#include "lang/ro-RO.rc" +#include "lang/ru-RU.rc" +#include "lang/sk-SK.rc" +#include "lang/sv-SE.rc" +#include "lang/uk-UA.rc" diff --cc dll/win32/user32/windows/menu.c index 04fefbd253f,00000000000..bbc24c7db52 mode 100644,000000..100644 --- a/dll/win32/user32/windows/menu.c +++ b/dll/win32/user32/windows/menu.c @@@ -1,5237 -1,0 +1,5233 @@@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS user32.dll + * FILE: user32/windows/menu.c + * PURPOSE: Menus + * + * PROGRAMMERS: Casper S. Hornstrup + * James Tabor + */ + +/* INCLUDES ******************************************************************/ + +#include +#include + +LRESULT DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active); + +WINE_DEFAULT_DEBUG_CHANNEL(menu); + +/* internal popup menu window messages */ + +#define MM_SETMENUHANDLE (WM_USER + 0) +#define MM_GETMENUHANDLE (WM_USER + 1) + +/* internal flags for menu tracking */ + +#define TF_ENDMENU 0x10000 +#define TF_SUSPENDPOPUP 0x20000 +#define TF_SKIPREMOVE 0x40000 + +#define ITEM_PREV -1 +#define ITEM_NEXT 1 + +/* Internal MenuTrackMenu() flags */ +#define TPM_INTERNAL 0xF0000000 +#define TPM_BUTTONDOWN 0x40000000 /* menu was clicked before tracking */ +#define TPM_POPUPMENU 0x20000000 /* menu is a popup menu */ + + +#define MENU_TYPE_MASK (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR) + +#define MENU_ITEM_TYPE(flags) ((flags) & MENU_TYPE_MASK) + +/* macro to test that flags do not indicate bitmap, ownerdraw or separator */ +#define IS_STRING_ITEM(flags) (MF_STRING == MENU_ITEM_TYPE(flags)) +#define IS_MAGIC_BITMAP(id) ((id) && ((INT_PTR)(id) < 12) && ((INT_PTR)(id) >= -1)) + +#define IS_SYSTEM_MENU(MenuInfo) \ + (0 == ((MenuInfo)->Flags & MF_POPUP) && 0 != ((MenuInfo)->Flags & MF_SYSMENU)) + +#define IS_SYSTEM_POPUP(MenuInfo) \ + (0 != ((MenuInfo)->Flags & MF_POPUP) && 0 != ((MenuInfo)->Flags & MF_SYSMENU)) + +#define IS_BITMAP_ITEM(flags) (MF_BITMAP == MENU_ITEM_TYPE(flags)) + +/* Use global popup window because there's no way 2 menus can + * be tracked at the same time. */ +static HWND top_popup; +static HMENU top_popup_hmenu; + +/* Flag set by EndMenu() to force an exit from menu tracking */ +static BOOL fEndMenu = FALSE; + +#define MENU_ITEM_HBMP_SPACE (5) +#define MENU_BAR_ITEMS_SPACE (12) +#define SEPARATOR_HEIGHT (5) +#define MENU_TAB_SPACE (8) + +typedef struct +{ + UINT TrackFlags; + HMENU CurrentMenu; /* current submenu (can be equal to hTopMenu)*/ + HMENU TopMenu; /* initial menu */ + HWND OwnerWnd; /* where notifications are sent */ + POINT Pt; +} MTRACKER; + + +/********************************************************************* + * PopupMenu class descriptor + */ +const struct builtin_class_descr POPUPMENU_builtin_class = +{ + WC_MENU, /* name */ + CS_SAVEBITS | CS_DBLCLKS, /* style */ + (WNDPROC) NULL, /* FIXME - procA */ + (WNDPROC) PopupMenuWndProcW, /* FIXME - procW */ + sizeof(MENUINFO *), /* extra */ + (LPCWSTR) IDC_ARROW, /* cursor */ + (HBRUSH)(COLOR_MENU + 1) /* brush */ +}; + +#ifndef GET_WORD +#define GET_WORD(ptr) (*(WORD *)(ptr)) +#endif +#ifndef GET_DWORD +#define GET_DWORD(ptr) (*(DWORD *)(ptr)) +#endif + +HFONT hMenuFont = NULL; +HFONT hMenuFontBold = NULL; + +/* Dimension of the menu bitmaps */ +static HBITMAP BmpSysMenu = NULL; + +static SIZE MenuCharSize; + +/*********************************************************************** + * MenuGetRosMenuInfo + * + * Get full information about menu + */ +static BOOL FASTCALL +MenuGetRosMenuInfo(PROSMENUINFO MenuInfo, HMENU Menu) +{ + MenuInfo->cbSize = sizeof(ROSMENUINFO); + MenuInfo->fMask = MIM_BACKGROUND | MIM_HELPID | MIM_MAXHEIGHT | MIM_MENUDATA | MIM_STYLE; + + return NtUserMenuInfo(Menu, MenuInfo, FALSE); +} + +/*********************************************************************** + * MenuSetRosMenuInfo + * + * Set full information about menu + */ +static BOOL FASTCALL +MenuSetRosMenuInfo(PROSMENUINFO MenuInfo) +{ + MenuInfo->cbSize = sizeof(ROSMENUINFO); + MenuInfo->fMask = MIM_BACKGROUND | MIM_HELPID | MIM_MAXHEIGHT | MIM_MENUDATA | MIM_STYLE; + + return NtUserMenuInfo(MenuInfo->Self, MenuInfo, TRUE); +} + +/*********************************************************************** + * MenuInitRosMenuItemInfo + * + * Initialize a buffer for use with MenuGet/SetRosMenuItemInfo + */ +static VOID FASTCALL +MenuInitRosMenuItemInfo(PROSMENUITEMINFO ItemInfo) +{ + ZeroMemory(ItemInfo, sizeof(ROSMENUITEMINFO)); + ItemInfo->cbSize = sizeof(ROSMENUITEMINFO); +} + +/*********************************************************************** + * MenuGetRosMenuItemInfo + * + * Get full information about a menu item + */ +static BOOL FASTCALL +MenuGetRosMenuItemInfo(HMENU Menu, UINT Index, PROSMENUITEMINFO ItemInfo) +{ + UINT Save_Mask = ItemInfo->fMask; /* Save the org mask bits. */ + + if (ItemInfo->dwTypeData != NULL) + { + HeapFree(GetProcessHeap(), 0, ItemInfo->dwTypeData); + } + + + ItemInfo->fMask = MIIM_BITMAP | MIIM_CHECKMARKS | MIIM_DATA | MIIM_FTYPE + | MIIM_ID | MIIM_STATE | MIIM_STRING | MIIM_SUBMENU | MIIM_TYPE; + ItemInfo->dwTypeData = NULL; + + if (! NtUserMenuItemInfo(Menu, Index, TRUE, ItemInfo, FALSE)) + { + ItemInfo->fType = 0; + return FALSE; + } + + if (MENU_ITEM_TYPE(ItemInfo->fType) == MF_STRING) + { + ItemInfo->cch++; + ItemInfo->dwTypeData = HeapAlloc(GetProcessHeap(), 0, + ItemInfo->cch * sizeof(WCHAR)); + if (NULL == ItemInfo->dwTypeData) + { + return FALSE; + } + + if (! NtUserMenuItemInfo(Menu, Index, TRUE, ItemInfo, FALSE)) + { + ItemInfo->fType = 0; + return FALSE; + } + ItemInfo->dwTypeData[ItemInfo->cch - 1] = UNICODE_NULL; + } + ItemInfo->fMask = Save_Mask; + return TRUE; +} + +/*********************************************************************** + * MenuSetRosMenuItemInfo + * + * Set selected information about a menu item, need to set the mask bits. + */ +static BOOL FASTCALL +MenuSetRosMenuItemInfo(HMENU Menu, UINT Index, PROSMENUITEMINFO ItemInfo) +{ + BOOL Ret; + + if (MENU_ITEM_TYPE(ItemInfo->fType) == MF_STRING && + ItemInfo->dwTypeData != NULL) + { + ItemInfo->cch = strlenW(ItemInfo->dwTypeData); + } + Ret = NtUserMenuItemInfo(Menu, Index, TRUE, ItemInfo, TRUE); + + return Ret; +} + +/*********************************************************************** + * MenuCleanupRosMenuItemInfo + * + * Cleanup after use of MenuGet/SetRosMenuItemInfo + */ +static VOID FASTCALL +MenuCleanupRosMenuItemInfo(PROSMENUITEMINFO ItemInfo) +{ + if (ItemInfo->dwTypeData != NULL) + { + HeapFree(GetProcessHeap(), 0, ItemInfo->dwTypeData); + ItemInfo->dwTypeData = NULL; + } +} + +/*********************************************************************** + * MenuGetAllRosMenuItemInfo + * + * Get full information about all menu items + */ +static INT FASTCALL +MenuGetAllRosMenuItemInfo(HMENU Menu, PROSMENUITEMINFO *ItemInfo) +{ + DWORD BufSize; + + BufSize = NtUserBuildMenuItemList(Menu, (VOID *) 1, 0, 0); + if (BufSize == (DWORD) -1 || BufSize == 0) + { + return -1; + } + *ItemInfo = HeapAlloc(GetProcessHeap(), 0, BufSize); + if (NULL == *ItemInfo) + { + return -1; + } + + return NtUserBuildMenuItemList(Menu, *ItemInfo, BufSize, 0); +} + +/*********************************************************************** + * MenuCleanupAllRosMenuItemInfo + * + * Cleanup after use of MenuGetAllRosMenuItemInfo + */ +static VOID FASTCALL +MenuCleanupAllRosMenuItemInfo(PROSMENUITEMINFO ItemInfo) +{ + HeapFree(GetProcessHeap(), 0, ItemInfo); +} + +/*********************************************************************** + * MenuInitSysMenuPopup + * + * Grey the appropriate items in System menu. + */ +void FASTCALL MenuInitSysMenuPopup(HMENU hmenu, DWORD style, DWORD clsStyle, LONG HitTest ) +{ + BOOL gray; + UINT DefItem; + #if 0 + MENUITEMINFOW mii; + #endif + + gray = !(style & WS_THICKFRAME) || (style & (WS_MAXIMIZE | WS_MINIMIZE)); + EnableMenuItem( hmenu, SC_SIZE, (gray ? MF_GRAYED : MF_ENABLED) ); + gray = ((style & WS_MAXIMIZE) != 0); + EnableMenuItem( hmenu, SC_MOVE, (gray ? MF_GRAYED : MF_ENABLED) ); + gray = !(style & WS_MINIMIZEBOX) || (style & WS_MINIMIZE); + EnableMenuItem( hmenu, SC_MINIMIZE, (gray ? MF_GRAYED : MF_ENABLED) ); + gray = !(style & WS_MAXIMIZEBOX) || (style & WS_MAXIMIZE); + EnableMenuItem( hmenu, SC_MAXIMIZE, (gray ? MF_GRAYED : MF_ENABLED) ); + gray = !(style & (WS_MAXIMIZE | WS_MINIMIZE)); + EnableMenuItem( hmenu, SC_RESTORE, (gray ? MF_GRAYED : MF_ENABLED) ); + gray = (clsStyle & CS_NOCLOSE) != 0; + + /* The menu item must keep its state if it's disabled */ + if(gray) + EnableMenuItem( hmenu, SC_CLOSE, MF_GRAYED); + + /* Set default menu item */ + if(style & WS_MINIMIZE) DefItem = SC_RESTORE; + else if(HitTest == HTCAPTION) DefItem = ((style & (WS_MAXIMIZE | WS_MINIMIZE)) ? SC_RESTORE : SC_MAXIMIZE); + else DefItem = SC_CLOSE; +#if 0 + mii.cbSize = sizeof(MENUITEMINFOW); + mii.fMask |= MIIM_STATE; + if((DefItem != SC_CLOSE) && GetMenuItemInfoW(hmenu, DefItem, FALSE, &mii) && + (mii.fState & (MFS_GRAYED | MFS_DISABLED))) DefItem = SC_CLOSE; +#endif + SetMenuDefaultItem(hmenu, DefItem, MF_BYCOMMAND); +} + +/****************************************************************************** + * + * UINT MenuGetStartOfNextColumn( + * PROSMENUINFO MenuInfo) + * + *****************************************************************************/ +static UINT MenuGetStartOfNextColumn( + PROSMENUINFO MenuInfo) +{ + PROSMENUITEMINFO MenuItems; + UINT i; + + i = MenuInfo->FocusedItem; + if ( i == NO_SELECTED_ITEM ) + return i; + + if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0) + return NO_SELECTED_ITEM; + + for (i++ ; i < MenuInfo->MenuItemCount; i++) + if (0 != (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK))) + return i; + + return NO_SELECTED_ITEM; +} + +/****************************************************************************** + * + * UINT MenuGetStartOfPrevColumn( + * PROSMENUINFO MenuInfo) + * + *****************************************************************************/ + +static UINT FASTCALL MenuGetStartOfPrevColumn( + PROSMENUINFO MenuInfo) +{ + PROSMENUITEMINFO MenuItems; + UINT i; + + if (!MenuInfo->FocusedItem || MenuInfo->FocusedItem == NO_SELECTED_ITEM) + return NO_SELECTED_ITEM; + + if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &MenuItems) <= 0) + return NO_SELECTED_ITEM; + + /* Find the start of the column */ + for (i = MenuInfo->FocusedItem; + 0 != i && 0 == (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)); + --i) + { + ; /* empty */ + } + + if (i == 0) + { + MenuCleanupAllRosMenuItemInfo(MenuItems); + return NO_SELECTED_ITEM; + } + + for (--i; 0 != i; --i) + if (MenuItems[i].fType & (MF_MENUBREAK | MF_MENUBARBREAK)) + break; + + MenuCleanupAllRosMenuItemInfo(MenuItems); + TRACE("ret %d.\n", i ); + + return i; +} + +/*********************************************************************** + * MenuFindSubMenu + * + * Find a Sub menu. Return the position of the submenu, and modifies + * *hmenu in case it is found in another sub-menu. + * If the submenu cannot be found, NO_SELECTED_ITEM is returned. + */ +static UINT FASTCALL MenuFindSubMenu(HMENU *hmenu, HMENU hSubTarget ) +{ + ROSMENUINFO menu; + UINT i; + ROSMENUITEMINFO item; + if (((*hmenu)==(HMENU)0xffff) || + (!MenuGetRosMenuInfo(&menu, *hmenu))) + return NO_SELECTED_ITEM; + + MenuInitRosMenuItemInfo(&item); + for (i = 0; i < menu.MenuItemCount; i++) { + if (! MenuGetRosMenuItemInfo(menu.Self, i, &item)) + { + MenuCleanupRosMenuItemInfo(&item); + return NO_SELECTED_ITEM; + } + if (!(item.fType & MF_POPUP)) continue; + if (item.hSubMenu == hSubTarget) { + MenuCleanupRosMenuItemInfo(&item); + return i; + } + else { + HMENU hsubmenu = item.hSubMenu; + UINT pos = MenuFindSubMenu(&hsubmenu, hSubTarget ); + if (pos != NO_SELECTED_ITEM) { + *hmenu = hsubmenu; + return pos; + } + } + } + MenuCleanupRosMenuItemInfo(&item); + return NO_SELECTED_ITEM; +} + +/*********************************************************************** + * MenuLoadBitmaps + * + * Load the arrow bitmap. We can't do this from MenuInit since user32 + * can also be used (and thus initialized) from text-mode. + */ +static void FASTCALL +MenuLoadBitmaps(VOID) +{ + /* Load system buttons bitmaps */ + if (NULL == BmpSysMenu) + { + BmpSysMenu = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE)); + } +} + +/*********************************************************************** + * MenuDrawPopupGlyph + * + * Draws popup magic glyphs (can be found in system menu). + */ +static void FASTCALL +MenuDrawPopupGlyph(HDC dc, LPRECT r, INT_PTR popupMagic, BOOL inactive, BOOL hilite) +{ + LOGFONTW lf; + HFONT hFont, hOldFont; + COLORREF clrsave; + INT bkmode; + TCHAR symbol; + switch (popupMagic) + { + case (INT_PTR) HBMMENU_POPUP_RESTORE: + symbol = '2'; + break; + case (INT_PTR) HBMMENU_POPUP_MINIMIZE: + symbol = '0'; + break; + case (INT_PTR) HBMMENU_POPUP_MAXIMIZE: + symbol = '1'; + break; + case (INT_PTR) HBMMENU_POPUP_CLOSE: + symbol = 'r'; + break; + default: + ERR("Invalid popup magic bitmap %d\n", (int)popupMagic); + return; + } + ZeroMemory(&lf, sizeof(LOGFONTW)); + InflateRect(r, -2, -2); + lf.lfHeight = r->bottom - r->top; + lf.lfWidth = 0; + lf.lfWeight = FW_NORMAL; + lf.lfCharSet = DEFAULT_CHARSET; + lstrcpy(lf.lfFaceName, TEXT("Marlett")); + hFont = CreateFontIndirect(&lf); + /* save font and text color */ + hOldFont = SelectObject(dc, hFont); + clrsave = GetTextColor(dc); + bkmode = GetBkMode(dc); + /* set color and drawing mode */ + SetBkMode(dc, TRANSPARENT); + if (inactive) + { + /* draw shadow */ + if (!hilite) + { + SetTextColor(dc, GetSysColor(COLOR_HIGHLIGHTTEXT)); + TextOut(dc, r->left + 1, r->top + 1, &symbol, 1); + } + } + SetTextColor(dc, GetSysColor(inactive ? COLOR_GRAYTEXT : (hilite ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT))); + /* draw selected symbol */ + TextOut(dc, r->left, r->top, &symbol, 1); + /* restore previous settings */ + SetTextColor(dc, clrsave); + SelectObject(dc, hOldFont); + SetBkMode(dc, bkmode); + DeleteObject(hFont); +} + +/*********************************************************************** + * MenuFindItemByKey + * + * Find the menu item selected by a key press. + * Return item id, -1 if none, -2 if we should close the menu. + */ +static UINT FASTCALL MenuFindItemByKey(HWND WndOwner, PROSMENUINFO MenuInfo, + WCHAR Key, BOOL ForceMenuChar) +{ + ROSMENUINFO SysMenuInfo; + PROSMENUITEMINFO Items, ItemInfo; + LRESULT MenuChar; + UINT i; + + TRACE("\tlooking for '%c' (0x%02x) in [%p]\n", (char) Key, Key, MenuInfo); + + if (NULL == MenuInfo || ! IsMenu(MenuInfo->Self)) + { + if (MenuGetRosMenuInfo(&SysMenuInfo, GetSystemMenu(WndOwner, FALSE))) + { + MenuInfo = &SysMenuInfo; + } + else + { + MenuInfo = NULL; + } + } + + if (NULL != MenuInfo) + { + if (MenuGetAllRosMenuItemInfo(MenuInfo->Self, &Items) <= 0) + { + return -1; + } + if (! ForceMenuChar) + { + Key = toupperW(Key); + ItemInfo = Items; + for (i = 0; i < MenuInfo->MenuItemCount; i++, ItemInfo++) + { + if ((ItemInfo->lpstr) && NULL != ItemInfo->dwTypeData) + { + WCHAR *p = (WCHAR *) ItemInfo->dwTypeData - 2; + do + { + p = strchrW(p + 2, '&'); + } + while (NULL != p && L'&' == p[1]); + if (NULL != p && (toupperW(p[1]) == Key)) + { + return i; + } + } + } + } + + MenuChar = SendMessageW(WndOwner, WM_MENUCHAR, + MAKEWPARAM(Key, MenuInfo->Flags), (LPARAM) MenuInfo->Self); + if (2 == HIWORD(MenuChar)) + { + return LOWORD(MenuChar); + } + if (1 == HIWORD(MenuChar)) + { + return (UINT) (-2); + } + } + + return (UINT)(-1); +} + +/*********************************************************************** + * MenuGetBitmapItemSize + * + * Get the size of a bitmap item. + */ +static void FASTCALL MenuGetBitmapItemSize(PROSMENUITEMINFO lpitem, SIZE *size, HWND WndOwner) +{ + BITMAP bm; + HBITMAP bmp = lpitem->hbmpItem; + + size->cx = size->cy = 0; + + /* check if there is a magic menu item associated with this item */ + if (IS_MAGIC_BITMAP(bmp)) + { + switch((INT_PTR) bmp) + { + case (INT_PTR)HBMMENU_CALLBACK: + { + MEASUREITEMSTRUCT measItem; + measItem.CtlType = ODT_MENU; + measItem.CtlID = 0; + measItem.itemID = lpitem->wID; + measItem.itemWidth = lpitem->Rect.right - lpitem->Rect.left; + measItem.itemHeight = lpitem->Rect.bottom - lpitem->Rect.top; + measItem.itemData = lpitem->dwItemData; + SendMessageW( WndOwner, WM_MEASUREITEM, lpitem->wID, (LPARAM)&measItem); + size->cx = measItem.itemWidth; + size->cy = measItem.itemHeight; + return; + } + break; + + case (INT_PTR) HBMMENU_SYSTEM: + if (0 != lpitem->dwItemData) + { + bmp = (HBITMAP) lpitem->dwItemData; + break; + } + /* fall through */ + case (INT_PTR) HBMMENU_MBAR_RESTORE: + case (INT_PTR) HBMMENU_MBAR_MINIMIZE: + case (INT_PTR) HBMMENU_MBAR_CLOSE: + case (INT_PTR) HBMMENU_MBAR_MINIMIZE_D: + case (INT_PTR) HBMMENU_MBAR_CLOSE_D: + case (INT_PTR) HBMMENU_POPUP_CLOSE: + case (INT_PTR) HBMMENU_POPUP_RESTORE: + case (INT_PTR) HBMMENU_POPUP_MAXIMIZE: + case (INT_PTR) HBMMENU_POPUP_MINIMIZE: + /* FIXME: Why we need to subtract these magic values? */ + /* to make them smaller than the menu bar? */ + size->cx = GetSystemMetrics(SM_CXSIZE) - 2; + size->cy = GetSystemMetrics(SM_CYSIZE) - 4; + return; + } + } + + if (GetObjectW(bmp, sizeof(BITMAP), &bm)) + { + size->cx = bm.bmWidth; + size->cy = bm.bmHeight; + } +} + +/*********************************************************************** + * MenuDrawBitmapItem + * + * Draw a bitmap item. + */ +static void FASTCALL MenuDrawBitmapItem(HDC hdc, PROSMENUITEMINFO lpitem, const RECT *rect, + HMENU hmenu, HWND WndOwner, UINT odaction, BOOL MenuBar) +{ + BITMAP bm; + DWORD rop; + HDC hdcMem; + HBITMAP bmp; + int w = rect->right - rect->left; + int h = rect->bottom - rect->top; + int bmp_xoffset = 0; + int left, top; + HBITMAP hbmToDraw = lpitem->hbmpItem; + bmp = hbmToDraw; + + /* Check if there is a magic menu item associated with this item */ + if (IS_MAGIC_BITMAP(hbmToDraw)) + { + UINT flags = 0; + RECT r; + + r = *rect; + switch ((INT_PTR)hbmToDraw) + { + case (INT_PTR)HBMMENU_SYSTEM: + if (lpitem->dwTypeData) + { + bmp = (HBITMAP)lpitem->dwTypeData; + if (!GetObjectW( bmp, sizeof(bm), &bm )) return; + } + else + { + if (!BmpSysMenu) BmpSysMenu = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE)); + bmp = BmpSysMenu; + if (! GetObjectW(bmp, sizeof(bm), &bm)) return; + /* only use right half of the bitmap */ + bmp_xoffset = bm.bmWidth / 2; + bm.bmWidth -= bmp_xoffset; + } + goto got_bitmap; + case (INT_PTR)HBMMENU_MBAR_RESTORE: + flags = DFCS_CAPTIONRESTORE; + break; + case (INT_PTR)HBMMENU_MBAR_MINIMIZE: + r.right += 1; + flags = DFCS_CAPTIONMIN; + break; + case (INT_PTR)HBMMENU_MBAR_MINIMIZE_D: + r.right += 1; + flags = DFCS_CAPTIONMIN | DFCS_INACTIVE; + break; + case (INT_PTR)HBMMENU_MBAR_CLOSE: + flags = DFCS_CAPTIONCLOSE; + break; + case (INT_PTR)HBMMENU_MBAR_CLOSE_D: + flags = DFCS_CAPTIONCLOSE | DFCS_INACTIVE; + break; + case (INT_PTR)HBMMENU_CALLBACK: + { + DRAWITEMSTRUCT drawItem; + POINT origorg; + drawItem.CtlType = ODT_MENU; + drawItem.CtlID = 0; + drawItem.itemID = lpitem->wID; + drawItem.itemAction = odaction; + drawItem.itemState = (lpitem->fState & MF_CHECKED)?ODS_CHECKED:0; + drawItem.itemState |= (lpitem->fState & MF_DEFAULT)?ODS_DEFAULT:0; + drawItem.itemState |= (lpitem->fState & MF_DISABLED)?ODS_DISABLED:0; + drawItem.itemState |= (lpitem->fState & MF_GRAYED)?ODS_GRAYED|ODS_DISABLED:0; + drawItem.itemState |= (lpitem->fState & MF_HILITE)?ODS_SELECTED:0; + drawItem.hwndItem = (HWND)hmenu; + drawItem.hDC = hdc; + drawItem.rcItem = *rect; + drawItem.itemData = lpitem->dwItemData; + /* some applications make this assumption on the DC's origin */ + SetViewportOrgEx( hdc, lpitem->Rect.left, lpitem->Rect.top, &origorg); + OffsetRect( &drawItem.rcItem, - lpitem->Rect.left, - lpitem->Rect.top); + SendMessageW( WndOwner, WM_DRAWITEM, 0, (LPARAM)&drawItem); + SetViewportOrgEx( hdc, origorg.x, origorg.y, NULL); + return; + } + break; + + case (INT_PTR) HBMMENU_POPUP_CLOSE: + case (INT_PTR) HBMMENU_POPUP_RESTORE: + case (INT_PTR) HBMMENU_POPUP_MAXIMIZE: + case (INT_PTR) HBMMENU_POPUP_MINIMIZE: + MenuDrawPopupGlyph(hdc, &r, (INT_PTR)hbmToDraw, lpitem->fState & MF_GRAYED, lpitem->fState & MF_HILITE); + return; + } + InflateRect(&r, -1, -1); + if (0 != (lpitem->fState & MF_HILITE)) + { + flags |= DFCS_PUSHED; + } + DrawFrameControl(hdc, &r, DFC_CAPTION, flags); + return; + } + + if (!bmp || !GetObjectW( bmp, sizeof(bm), &bm )) return; + + got_bitmap: + hdcMem = CreateCompatibleDC( hdc ); + SelectObject( hdcMem, bmp ); + + /* handle fontsize > bitmap_height */ + top = (h>bm.bmHeight) ? rect->top+(h-bm.bmHeight)/2 : rect->top; + left=rect->left; + rop=((lpitem->fState & MF_HILITE) && !IS_MAGIC_BITMAP(hbmToDraw)) ? NOTSRCCOPY : SRCCOPY; + if ((lpitem->fState & MF_HILITE) && lpitem->hbmpItem) + SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT)); + BitBlt( hdc, left, top, w, h, hdcMem, bmp_xoffset, 0, rop ); + DeleteDC( hdcMem ); +} + +/*********************************************************************** + * MenuCalcItemSize + * + * Calculate the size of the menu item and store it in lpitem->rect. + */ +static void FASTCALL MenuCalcItemSize( HDC hdc, PROSMENUITEMINFO lpitem, PROSMENUINFO MenuInfo, HWND hwndOwner, + INT orgX, INT orgY, BOOL menuBar) +{ + WCHAR *p; + UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK ); + INT itemheight = 0; + + TRACE("dc=%x owner=%x (%d,%d)\n", hdc, hwndOwner, orgX, orgY); + + MenuCharSize.cx = GdiGetCharDimensions( hdc, NULL, &MenuCharSize.cy ); + + SetRect( &lpitem->Rect, orgX, orgY, orgX, orgY ); + + if (lpitem->fType & MF_OWNERDRAW) + { + MEASUREITEMSTRUCT mis; + mis.CtlType = ODT_MENU; + mis.CtlID = 0; + mis.itemID = lpitem->wID; + mis.itemData = lpitem->dwItemData; + mis.itemHeight = HIWORD( GetDialogBaseUnits()); + mis.itemWidth = 0; + SendMessageW( hwndOwner, WM_MEASUREITEM, 0, (LPARAM)&mis ); + /* Tests reveal that Windows ( Win95 thru WinXP) adds twice the average + * width of a menufont character to the width of an owner-drawn menu. + */ + lpitem->Rect.right += mis.itemWidth + 2 * MenuCharSize.cx; + + if (menuBar) { + /* under at least win95 you seem to be given a standard + height for the menu and the height value is ignored */ + lpitem->Rect.bottom += GetSystemMetrics(SM_CYMENUSIZE); + } else + lpitem->Rect.bottom += mis.itemHeight; + + TRACE("id=%04lx size=%dx%d\n", + lpitem->wID, mis.itemWidth, mis.itemHeight); + return; + } + + if (lpitem->fType & MF_SEPARATOR) + { + lpitem->Rect.bottom += SEPARATOR_HEIGHT; + if( !menuBar) + lpitem->Rect.right += check_bitmap_width + MenuCharSize.cx; + return; + } + + lpitem->dxTab = 0; + + if (lpitem->hbmpItem) + { + SIZE size; + + if (!menuBar) { + MenuGetBitmapItemSize(lpitem, &size, hwndOwner ); + /* Keep the size of the bitmap in callback mode to be able + * to draw it correctly */ + lpitem->Rect.right = lpitem->Rect.left + size.cx; + if (MenuInfo->maxBmpSize.cx < abs(size.cx) + MENU_ITEM_HBMP_SPACE || + MenuInfo->maxBmpSize.cy < abs(size.cy)) + { + MenuInfo->maxBmpSize.cx = abs(size.cx) + MENU_ITEM_HBMP_SPACE; + MenuInfo->maxBmpSize.cy = abs(size.cy); + } + MenuSetRosMenuInfo(MenuInfo); + itemheight = size.cy + 2; + + if( !(MenuInfo->dwStyle & MNS_NOCHECK)) + lpitem->Rect.right += 2 * check_bitmap_width; + lpitem->Rect.right += 4 + MenuCharSize.cx; + lpitem->dxTab = lpitem->Rect.right; + lpitem->Rect.right += check_bitmap_width; + } else /* hbmpItem & MenuBar */ { + MenuGetBitmapItemSize(lpitem, &size, hwndOwner ); + lpitem->Rect.right += size.cx; + if( lpitem->lpstr) lpitem->Rect.right += 2; + itemheight = size.cy; + + /* Special case: Minimize button doesn't have a space behind it. */ + if (lpitem->hbmpItem == (HBITMAP)HBMMENU_MBAR_MINIMIZE || + lpitem->hbmpItem == (HBITMAP)HBMMENU_MBAR_MINIMIZE_D) + lpitem->Rect.right -= 1; + } + } + else if (!menuBar) { + if( !(MenuInfo->dwStyle & MNS_NOCHECK)) + lpitem->Rect.right += check_bitmap_width; + lpitem->Rect.right += 4 + MenuCharSize.cx; + lpitem->dxTab = lpitem->Rect.right; + lpitem->Rect.right += check_bitmap_width; + } + + /* it must be a text item - unless it's the system menu */ + if (!(lpitem->fType & MF_SYSMENU) && lpitem->lpstr) { + HFONT hfontOld = NULL; + RECT rc = lpitem->Rect; + LONG txtheight, txtwidth; + + if ( lpitem->fState & MFS_DEFAULT ) { + hfontOld = SelectObject( hdc, hMenuFontBold ); + } + if (menuBar) { + txtheight = DrawTextW( hdc, lpitem->dwTypeData, -1, &rc, + DT_SINGLELINE|DT_CALCRECT); + lpitem->Rect.right += rc.right - rc.left; + itemheight = max( max( itemheight, txtheight), + GetSystemMetrics( SM_CYMENU) - 1); + lpitem->Rect.right += 2 * MenuCharSize.cx; + } else { + if ((p = strchrW( lpitem->dwTypeData, '\t' )) != NULL) { + RECT tmprc = rc; + LONG tmpheight; + int n = (int)( p - lpitem->dwTypeData); + /* Item contains a tab (only meaningful in popup menus) */ + /* get text size before the tab */ + txtheight = DrawTextW( hdc, lpitem->dwTypeData, n, &rc, + DT_SINGLELINE|DT_CALCRECT); + txtwidth = rc.right - rc.left; + p += 1; /* advance past the Tab */ + /* get text size after the tab */ + tmpheight = DrawTextW( hdc, p, -1, &tmprc, + DT_SINGLELINE|DT_CALCRECT); + lpitem->dxTab += txtwidth; + txtheight = max( txtheight, tmpheight); + txtwidth += MenuCharSize.cx + /* space for the tab */ + tmprc.right - tmprc.left; /* space for the short cut */ + } else { + txtheight = DrawTextW( hdc, lpitem->dwTypeData, -1, &rc, + DT_SINGLELINE|DT_CALCRECT); + txtwidth = rc.right - rc.left; + lpitem->dxTab += txtwidth; + } + lpitem->Rect.right += 2 + txtwidth; + itemheight = max( itemheight, + max( txtheight + 2, MenuCharSize.cy + 4)); + } + if (hfontOld) SelectObject (hdc, hfontOld); + } else if( menuBar) { + itemheight = max( itemheight, GetSystemMetrics(SM_CYMENU)-1); + } + lpitem->Rect.bottom += itemheight; + TRACE("(%ld,%ld)-(%ld,%ld)\n", lpitem->Rect.left, lpitem->Rect.top, lpitem->Rect.right, lpitem->Rect.bottom); +} + +/*********************************************************************** + * MenuPopupMenuCalcSize + * + * Calculate the size of a popup menu. + */ +static void FASTCALL MenuPopupMenuCalcSize(PROSMENUINFO MenuInfo, HWND WndOwner) +{ + ROSMENUITEMINFO lpitem; + HDC hdc; + int start, i; + int orgX, orgY, maxX, maxTab, maxTabWidth; + + MenuInfo->Width = MenuInfo->Height = 0; + if (MenuInfo->MenuItemCount == 0) + { + MenuSetRosMenuInfo(MenuInfo); + return; + } + + hdc = GetDC(NULL); + SelectObject( hdc, hMenuFont ); + + start = 0; + maxX = 2 + 1; + + MenuInfo->maxBmpSize.cx = 0; + MenuInfo->maxBmpSize.cy = 0; + + MenuInitRosMenuItemInfo(&lpitem); + while (start < MenuInfo->MenuItemCount) + { + orgX = maxX; + orgY = 2; + + maxTab = maxTabWidth = 0; + + /* Parse items until column break or end of menu */ + for (i = start; i < MenuInfo->MenuItemCount; i++) + { + if (! MenuGetRosMenuItemInfo(MenuInfo->Self, i, &lpitem)) + { + MenuCleanupRosMenuItemInfo(&lpitem); + MenuSetRosMenuInfo(MenuInfo); + return; + } + if (i != start && + (lpitem.fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break; + + MenuCalcItemSize(hdc, &lpitem, MenuInfo, WndOwner, orgX, orgY, FALSE); + if (! MenuSetRosMenuItemInfo(MenuInfo->Self, i, &lpitem)) + { + MenuCleanupRosMenuItemInfo(&lpitem); + MenuSetRosMenuInfo(MenuInfo); + return; + } +// Not sure here,, The patch from wine removes this. +// if ((lpitem.fType & MF_MENUBARBREAK) != 0) +// { +// OrgX++; +// } + maxX = max(maxX, lpitem.Rect.right); + orgY = lpitem.Rect.bottom; + if ((lpitem.lpstr) && lpitem.dxTab ) + { + maxTab = max( maxTab, lpitem.dxTab ); + maxTabWidth = max(maxTabWidth, lpitem.Rect.right - lpitem.dxTab); + } + } + + /* Finish the column (set all items to the largest width found) */ + maxX = max( maxX, maxTab + maxTabWidth ); + while (start < i) + { + if (MenuGetRosMenuItemInfo(MenuInfo->Self, start, &lpitem)) + { + lpitem.Rect.right = maxX; + if ((lpitem.lpstr) && 0 != lpitem.dxTab) + { + lpitem.dxTab = maxTab; + } + MenuSetRosMenuItemInfo(MenuInfo->Self, start, &lpitem); + } + start++; + } + MenuInfo->Height = max(MenuInfo->Height, orgY); + } + + MenuInfo->Width = maxX; + + /* space for 3d border */ + MenuInfo->Height += 2; + MenuInfo->Width += 2; + + MenuCleanupRosMenuItemInfo(&lpitem); + MenuSetRosMenuInfo(MenuInfo); + ReleaseDC( 0, hdc ); +} + +/*********************************************************************** + * MenuMenuBarCalcSize + * + * FIXME: Word 6 implements its own MDI and its own 'close window' bitmap + * height is off by 1 pixel which causes lengthy window relocations when + * active document window is maximized/restored. + * + * Calculate the size of the menu bar. + */ +static void FASTCALL MenuMenuBarCalcSize( HDC hdc, LPRECT lprect, + PROSMENUINFO MenuInfo, HWND hwndOwner ) +{ + ROSMENUITEMINFO ItemInfo; + int start, i, orgX, orgY, maxY, helpPos; + + if ((lprect == NULL) || (MenuInfo == NULL)) return; + if (MenuInfo->MenuItemCount == 0) return; + TRACE("left=%ld top=%ld right=%ld bottom=%ld\n", lprect->left, lprect->top, lprect->right, lprect->bottom); + MenuInfo->Width = lprect->right - lprect->left; + MenuInfo->Height = 0; + maxY = lprect->top + 1; + start = 0; + helpPos = -1; + + MenuInfo->maxBmpSize.cx = 0; + MenuInfo->maxBmpSize.cy = 0; + + MenuInitRosMenuItemInfo(&ItemInfo); + while (start < MenuInfo->MenuItemCount) + { + if (! MenuGetRosMenuItemInfo(MenuInfo->Self, start, &ItemInfo)) + { + MenuCleanupRosMenuItemInfo(&ItemInfo); + return; + } + orgX = lprect->left; + orgY = maxY; + + /* Parse items until line break or end of menu */ + for (i = start; i < MenuInfo->MenuItemCount; i++) + { + if ((helpPos == -1) && (ItemInfo.fType & MF_RIGHTJUSTIFY)) helpPos = i; + if ((i != start) && + (ItemInfo.fType & (MF_MENUBREAK | MF_MENUBARBREAK))) break; + + TRACE("calling MENU_CalcItemSize org=(%d, %d)\n", orgX, orgY); + MenuCalcItemSize(hdc, &ItemInfo, MenuInfo, hwndOwner, orgX, orgY, TRUE); + if (! MenuSetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo)) + { + MenuCleanupRosMenuItemInfo(&ItemInfo); + return; + } + + if (ItemInfo.Rect.right > lprect->right) + { + if (i != start) break; + else ItemInfo.Rect.right = lprect->right; + } + maxY = max( maxY, ItemInfo.Rect.bottom ); + orgX = ItemInfo.Rect.right; + if (i + 1 < MenuInfo->MenuItemCount) + { + if (! MenuGetRosMenuItemInfo(MenuInfo->Self, i + 1, &ItemInfo)) + { + MenuCleanupRosMenuItemInfo(&ItemInfo); + return; + } + } + } + +/* FIXME: Is this really needed? */ /*NO! it is not needed, why make the +HBMMENU_MBAR_CLOSE, MINIMIZE & RESTORE, look the same size as the menu bar! */ +#if 0 + /* Finish the line (set all items to the largest height found) */ + while (start < i) + { + if (MenuGetRosMenuItemInfo(MenuInfo->Self, start, &ItemInfo)) + { + ItemInfo.Rect.bottom = maxY; + MenuSetRosMenuItemInfo(MenuInfo->Self, start, &ItemInfo); + } + start++; + } +#else + start = i; /* This works! */ +#endif + } + + lprect->bottom = maxY; + MenuInfo->Height = lprect->bottom - lprect->top; + MenuSetRosMenuInfo(MenuInfo); + + if (helpPos != -1) + { + /* Flush right all items between the MF_RIGHTJUSTIFY and */ + /* the last item (if several lines, only move the last line) */ + if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->MenuItemCount - 1, &ItemInfo)) + { + MenuCleanupRosMenuItemInfo(&ItemInfo); + return; + } + orgY = ItemInfo.Rect.top; + orgX = lprect->right; + for (i = MenuInfo->MenuItemCount - 1; helpPos <= i; i--) + { + if (i < helpPos) + { + break; /* done */ + } + if (ItemInfo.Rect.top != orgY) + { + break; /* Other line */ + } + if (orgX <= ItemInfo.Rect.right) + { + break; /* Too far right already */ + } + ItemInfo.Rect.left += orgX - ItemInfo.Rect.right; + ItemInfo.Rect.right = orgX; + orgX = ItemInfo.Rect.left; + MenuSetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo); + if (helpPos + 1 <= i && + ! MenuGetRosMenuItemInfo(MenuInfo->Self, i - 1, &ItemInfo)) + { + MenuCleanupRosMenuItemInfo(&ItemInfo); + return; + } + } + } + + MenuCleanupRosMenuItemInfo(&ItemInfo); +} + +/*********************************************************************** + * MenuDrawMenuItem + * + * Draw a single menu item. + */ +static void FASTCALL MenuDrawMenuItem(HWND hWnd, PROSMENUINFO MenuInfo, HWND WndOwner, HDC hdc, + PROSMENUITEMINFO lpitem, UINT Height, BOOL menuBar, UINT odaction) +{ + RECT rect; + PWCHAR Text; + BOOL flat_menu = FALSE; + int bkgnd; + PWND Wnd = ValidateHwnd(hWnd); + + if (!Wnd) + return; + + if (lpitem->fType & MF_SYSMENU) + { + if ( (Wnd->style & WS_MINIMIZE)) + { + UserGetInsideRectNC(Wnd, &rect); + UserDrawSysMenuButton(hWnd, hdc, &rect, + lpitem->fState & (MF_HILITE | MF_MOUSESELECT)); + } + return; + } + + SystemParametersInfoW (SPI_GETFLATMENU, 0, &flat_menu, 0); + bkgnd = (menuBar && flat_menu) ? COLOR_MENUBAR : COLOR_MENU; + + /* Setup colors */ + + if (lpitem->fState & MF_HILITE) + { + if(menuBar && !flat_menu) { + SetTextColor(hdc, GetSysColor(COLOR_MENUTEXT)); + SetBkColor(hdc, GetSysColor(COLOR_MENU)); + } else { + if (lpitem->fState & MF_GRAYED) + SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT)); + else + SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT)); + SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT)); + } + } + else + { + if (lpitem->fState & MF_GRAYED) + SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) ); + else + SetTextColor( hdc, GetSysColor( COLOR_MENUTEXT ) ); + SetBkColor( hdc, GetSysColor( bkgnd ) ); + } + + rect = lpitem->Rect; + + if (lpitem->fType & MF_OWNERDRAW) + { + /* + ** Experimentation under Windows reveals that an owner-drawn + ** menu is given the rectangle which includes the space it requested + ** in its response to WM_MEASUREITEM _plus_ width for a checkmark + ** and a popup-menu arrow. This is the value of lpitem->rect. + ** Windows will leave all drawing to the application except for + ** the popup-menu arrow. Windows always draws that itself, after + ** the menu owner has finished drawing. + */ + DRAWITEMSTRUCT dis; + + dis.CtlType = ODT_MENU; + dis.CtlID = 0; + dis.itemID = lpitem->wID; + dis.itemData = (DWORD)lpitem->dwItemData; + dis.itemState = 0; + if (lpitem->fState & MF_CHECKED) dis.itemState |= ODS_CHECKED; + if (lpitem->fState & MF_GRAYED) dis.itemState |= ODS_GRAYED | ODS_DISABLED; + if (lpitem->fState & MF_HILITE) dis.itemState |= ODS_SELECTED; + dis.itemAction = odaction; /* ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS; */ + dis.hwndItem = (HWND) MenuInfo->Self; + dis.hDC = hdc; + dis.rcItem = rect; + TRACE("Ownerdraw: owner=%p itemID=%d, itemState=%d, itemAction=%d, " + "hwndItem=%p, hdc=%p, rcItem={%ld,%ld,%ld,%ld}\n", hWnd, + dis.itemID, dis.itemState, dis.itemAction, dis.hwndItem, + dis.hDC, dis.rcItem.left, dis.rcItem.top, dis.rcItem.right, + dis.rcItem.bottom); + SendMessageW(WndOwner, WM_DRAWITEM, 0, (LPARAM) &dis); + /* Draw the popup-menu arrow */ + if (lpitem->fType & MF_POPUP) + { + RECT rectTemp; + CopyRect(&rectTemp, &rect); + rectTemp.left = rectTemp.right - GetSystemMetrics(SM_CXMENUCHECK); + DrawFrameControl(hdc, &rectTemp, DFC_MENU, DFCS_MENUARROW); + } + return; + } + + if (menuBar && (lpitem->fType & MF_SEPARATOR)) return; + + if (lpitem->fState & MF_HILITE) + { + if (flat_menu) + { + InflateRect (&rect, -1, -1); + FillRect(hdc, &rect, GetSysColorBrush(COLOR_MENUHILIGHT)); + InflateRect (&rect, 1, 1); + FrameRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT)); + } + else + { + if(menuBar) + DrawEdge(hdc, &rect, BDR_SUNKENOUTER, BF_RECT); + else + FillRect(hdc, &rect, GetSysColorBrush(COLOR_HIGHLIGHT)); + } + } + else + FillRect( hdc, &rect, GetSysColorBrush(bkgnd) ); + + SetBkMode( hdc, TRANSPARENT ); + + /* vertical separator */ + if (!menuBar && (lpitem->fType & MF_MENUBARBREAK)) + { + HPEN oldPen; + RECT rc = rect; + + rc.left -= 3; + rc.top = 3; + rc.bottom = Height - 3; + if (flat_menu) + { + oldPen = SelectObject( hdc, GetStockObject(DC_PEN) ); + SetDCPenColor(hdc, GetSysColor(COLOR_BTNSHADOW)); + MoveToEx( hdc, rc.left, rc.top, NULL ); + LineTo( hdc, rc.left, rc.bottom ); + SelectObject( hdc, oldPen ); + } + else + DrawEdge (hdc, &rc, EDGE_ETCHED, BF_LEFT); + } + + /* horizontal separator */ + if (lpitem->fType & MF_SEPARATOR) + { + HPEN oldPen; + RECT rc = rect; + + rc.left++; + rc.right--; + rc.top += SEPARATOR_HEIGHT / 2; + if (flat_menu) + { + oldPen = SelectObject( hdc, GetStockObject(DC_PEN) ); + SetDCPenColor( hdc, GetSysColor(COLOR_BTNSHADOW)); + MoveToEx( hdc, rc.left, rc.top, NULL ); + LineTo( hdc, rc.right, rc.top ); + SelectObject( hdc, oldPen ); + } + else + DrawEdge (hdc, &rc, EDGE_ETCHED, BF_TOP); + return; + } + +#if 0 + /* helper lines for debugging */ + /* This is a very good test tool when hacking menus! (JT) 07/16/2006 */ + FrameRect(hdc, &rect, GetStockObject(BLACK_BRUSH)); + SelectObject(hdc, GetStockObject(DC_PEN)); + SetDCPenColor(hdc, GetSysColor(COLOR_WINDOWFRAME)); + MoveToEx(hdc, rect.left, (rect.top + rect.bottom) / 2, NULL); + LineTo(hdc, rect.right, (rect.top + rect.bottom) / 2); +#endif + + if (!menuBar) + { + HBITMAP bm; + INT y = rect.top + rect.bottom; + RECT rc = rect; + int checked = FALSE; + UINT check_bitmap_width = GetSystemMetrics( SM_CXMENUCHECK ); + UINT check_bitmap_height = GetSystemMetrics( SM_CYMENUCHECK ); + /* Draw the check mark + * + * FIXME: + * Custom checkmark bitmaps are monochrome but not always 1bpp. + */ + if( !(MenuInfo->dwStyle & MNS_NOCHECK)) { + bm = (lpitem->fState & MF_CHECKED) ? lpitem->hbmpChecked : + lpitem->hbmpUnchecked; + if (bm) /* we have a custom bitmap */ + { + HDC hdcMem = CreateCompatibleDC( hdc ); + + SelectObject( hdcMem, bm ); + BitBlt( hdc, rc.left, (y - check_bitmap_height) / 2, + check_bitmap_width, check_bitmap_height, + hdcMem, 0, 0, SRCCOPY ); + DeleteDC( hdcMem ); + checked = TRUE; + } + else if (lpitem->fState & MF_CHECKED) /* standard bitmaps */ + { + RECT r; + CopyRect(&r, &rect); + r.right = r.left + GetSystemMetrics(SM_CXMENUCHECK); + DrawFrameControl( hdc, &r, DFC_MENU, + (lpitem->fType & MFT_RADIOCHECK) ? + DFCS_MENUBULLET : DFCS_MENUCHECK); + checked = TRUE; + } + } + if ( lpitem->hbmpItem ) + { + RECT bmpRect; + CopyRect(&bmpRect, &rect); + if (!(MenuInfo->dwStyle & MNS_CHECKORBMP) && !(MenuInfo->dwStyle & MNS_NOCHECK)) + bmpRect.left += check_bitmap_width + 2; + if (!(checked && (MenuInfo->dwStyle & MNS_CHECKORBMP))) + { + bmpRect.right = bmpRect.left + MenuInfo->maxBmpSize.cx; + MenuDrawBitmapItem(hdc, lpitem, &bmpRect, MenuInfo->Self, WndOwner, odaction, menuBar); + } + } + /* Draw the popup-menu arrow */ + if (lpitem->fType & MF_POPUP) + { + RECT rectTemp; + CopyRect(&rectTemp, &rect); + rectTemp.left = rectTemp.right - GetSystemMetrics(SM_CXMENUCHECK); + DrawFrameControl(hdc, &rectTemp, DFC_MENU, DFCS_MENUARROW); + } + rect.left += 4; + if( !(MenuInfo->dwStyle & MNS_NOCHECK)) + rect.left += check_bitmap_width; + rect.right -= check_bitmap_width; + } + else if( lpitem->hbmpItem) + { /* Draw the bitmap */ + MenuDrawBitmapItem(hdc, lpitem, &rect, MenuInfo->Self, WndOwner, odaction, menuBar); + } + + /* process text if present */ + if (lpitem->lpstr) + { + register int i = 0; + HFONT hfontOld = 0; + + UINT uFormat = menuBar ? DT_CENTER | DT_VCENTER | DT_SINGLELINE + : DT_LEFT | DT_VCENTER | DT_SINGLELINE; + + if(MenuInfo->dwStyle & MNS_CHECKORBMP) + rect.left += max(0, MenuInfo->maxBmpSize.cx - GetSystemMetrics(SM_CXMENUCHECK)); + else + rect.left += MenuInfo->maxBmpSize.cx; + + if ( lpitem->fState & MFS_DEFAULT ) + { + hfontOld = SelectObject(hdc, hMenuFontBold); + } + + if (menuBar) { + rect.left += MENU_BAR_ITEMS_SPACE / 2; + rect.right -= MENU_BAR_ITEMS_SPACE / 2; + } + + Text = (PWCHAR) lpitem->dwTypeData; + if(Text) + { + for (i = 0; L'\0' != Text[i]; i++) + if (Text[i] == L'\t' || Text[i] == L'\b') + break; + } + + if(lpitem->fState & MF_GRAYED) + { + if (!(lpitem->fState & MF_HILITE) ) + { + ++rect.left; ++rect.top; ++rect.right; ++rect.bottom; + SetTextColor(hdc, RGB(0xff, 0xff, 0xff)); + DrawTextW( hdc, Text, i, &rect, uFormat ); + --rect.left; --rect.top; --rect.right; --rect.bottom; + } + SetTextColor(hdc, RGB(0x80, 0x80, 0x80)); + } + + DrawTextW( hdc, Text, i, &rect, uFormat); + + /* paint the shortcut text */ + if (!menuBar && L'\0' != Text[i]) /* There's a tab or flush-right char */ + { + if (L'\t' == Text[i]) + { + rect.left = lpitem->dxTab; + uFormat = DT_LEFT | DT_VCENTER | DT_SINGLELINE; + } + else + { + rect.right = lpitem->dxTab; + uFormat = DT_RIGHT | DT_VCENTER | DT_SINGLELINE; + } + + if (lpitem->fState & MF_GRAYED) + { + if (!(lpitem->fState & MF_HILITE) ) + { + ++rect.left; ++rect.top; ++rect.right; ++rect.bottom; + SetTextColor(hdc, RGB(0xff, 0xff, 0xff)); + DrawTextW( hdc, Text + i + 1, -1, &rect, uFormat); + --rect.left; --rect.top; --rect.right; --rect.bottom; + } + SetTextColor(hdc, RGB(0x80, 0x80, 0x80)); + } + DrawTextW( hdc, Text + i + 1, -1, &rect, uFormat ); + } + + if (hfontOld) + SelectObject (hdc, hfontOld); + } +} + +/*********************************************************************** + * MenuDrawPopupMenu + * + * Paint a popup menu. + */ +static void FASTCALL MenuDrawPopupMenu(HWND hwnd, HDC hdc, HMENU hmenu ) +{ + HBRUSH hPrevBrush = 0; + RECT rect; + + TRACE("wnd=%p dc=%p menu=%p\n", hwnd, hdc, hmenu); + + GetClientRect( hwnd, &rect ); + + if((hPrevBrush = SelectObject( hdc, GetSysColorBrush(COLOR_MENU) )) + && (SelectObject( hdc, hMenuFont))) + { + HPEN hPrevPen; + + Rectangle( hdc, rect.left, rect.top, rect.right, rect.bottom ); + + hPrevPen = SelectObject( hdc, GetStockObject( NULL_PEN ) ); + if ( hPrevPen ) + { + BOOL flat_menu = FALSE; + ROSMENUINFO MenuInfo; + ROSMENUITEMINFO ItemInfo; + + SystemParametersInfoW (SPI_GETFLATMENU, 0, &flat_menu, 0); + if (flat_menu) + FrameRect(hdc, &rect, GetSysColorBrush(COLOR_BTNSHADOW)); + else + DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT); + + /* draw menu items */ + if (MenuGetRosMenuInfo(&MenuInfo, hmenu) && MenuInfo.MenuItemCount) + { + UINT u; + + MenuInitRosMenuItemInfo(&ItemInfo); + + for (u = 0; u < MenuInfo.MenuItemCount; u++) + { + if (MenuGetRosMenuItemInfo(MenuInfo.Self, u, &ItemInfo)) + { + MenuDrawMenuItem(hwnd, &MenuInfo, MenuInfo.WndOwner, hdc, &ItemInfo, + MenuInfo.Height, FALSE, ODA_DRAWENTIRE); + } + } + + MenuCleanupRosMenuItemInfo(&ItemInfo); + } + } else + { + SelectObject( hdc, hPrevBrush ); + } + } +} + +/*********************************************************************** + * MenuDrawMenuBar + * + * Paint a menu bar. Returns the height of the menu bar. + * called from [windows/nonclient.c] + */ +UINT MenuDrawMenuBar( HDC hDC, LPRECT lprect, HWND hwnd, + BOOL suppress_draw) +{ + ROSMENUINFO lppop; + HFONT hfontOld = 0; + HMENU hMenu = GetMenu(hwnd); + + if (! MenuGetRosMenuInfo(&lppop, hMenu) || lprect == NULL) + { + return GetSystemMetrics(SM_CYMENU); + } + + if (suppress_draw) + { + hfontOld = SelectObject(hDC, hMenuFont); + + MenuMenuBarCalcSize(hDC, lprect, &lppop, hwnd); + + lprect->bottom = lprect->top + lppop.Height; + + if (hfontOld) SelectObject( hDC, hfontOld); + return lppop.Height; + } + else + return DrawMenuBarTemp(hwnd, hDC, lprect, hMenu, NULL); +} + +/*********************************************************************** + * MenuShowPopup + * + * Display a popup menu. + */ +static BOOL FASTCALL MenuShowPopup(HWND hwndOwner, HMENU hmenu, UINT id, UINT flags, + INT x, INT y, INT xanchor, INT yanchor ) +{ + ROSMENUINFO MenuInfo; + ROSMENUITEMINFO ItemInfo; + UINT width, height; + POINT pt; + HMONITOR monitor; + MONITORINFO info; + + TRACE("owner=%p hmenu=%p id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x\n", + hwndOwner, hmenu, id, x, y, xanchor, yanchor); + + if (! MenuGetRosMenuInfo(&MenuInfo, hmenu)) return FALSE; + if (MenuInfo.FocusedItem != NO_SELECTED_ITEM) + { + MenuInitRosMenuItemInfo(&ItemInfo); + if (MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.FocusedItem, &ItemInfo)) + { + ItemInfo.fMask |= MIIM_STATE; + ItemInfo.fState &= ~(MF_HILITE|MF_MOUSESELECT); + MenuSetRosMenuItemInfo(MenuInfo.Self, MenuInfo.FocusedItem, &ItemInfo); + } + MenuCleanupRosMenuItemInfo(&ItemInfo); + MenuInfo.FocusedItem = NO_SELECTED_ITEM; + } + + /* store the owner for DrawItem */ + MenuInfo.WndOwner = hwndOwner; + MenuSetRosMenuInfo(&MenuInfo); + + MenuPopupMenuCalcSize(&MenuInfo, hwndOwner); + + /* adjust popup menu pos so that it fits within the desktop */ + + width = MenuInfo.Width + GetSystemMetrics(SM_CXBORDER); + height = MenuInfo.Height + GetSystemMetrics(SM_CYBORDER); + + /* FIXME: should use item rect */ + pt.x = x; + pt.y = y; + monitor = MonitorFromPoint( pt, MONITOR_DEFAULTTONEAREST ); + info.cbSize = sizeof(info); + GetMonitorInfoW( monitor, &info ); + + if( flags & TPM_RIGHTALIGN ) x -= width; + if( flags & TPM_CENTERALIGN ) x -= width / 2; + + if( flags & TPM_BOTTOMALIGN ) y -= height; + if( flags & TPM_VCENTERALIGN ) y -= height / 2; + + if( x + width > info.rcMonitor.right) + { + if( xanchor && x >= width - xanchor ) + x -= width - xanchor; + + if( x + width > info.rcMonitor.right) + x = info.rcMonitor.right - width; + } + if( x < info.rcMonitor.left ) x = info.rcMonitor.left; + + if( y + height > info.rcMonitor.bottom) + { + if( yanchor && y >= height + yanchor ) + y -= height + yanchor; + + if( y + height > info.rcMonitor.bottom) + y = info.rcMonitor.bottom - height; + } + if( y < info.rcMonitor.top ) y = info.rcMonitor.top; + + /* NOTE: In Windows, top menu popup is not owned. */ + MenuInfo.Wnd = CreateWindowExW( 0, WC_MENU, NULL, + WS_POPUP, x, y, width, height, + hwndOwner, 0, (HINSTANCE) GetWindowLongPtrW(hwndOwner, GWLP_HINSTANCE), + (LPVOID) MenuInfo.Self); + if ( !MenuInfo.Wnd || ! MenuSetRosMenuInfo(&MenuInfo)) return FALSE; + if (!top_popup) { + top_popup = MenuInfo.Wnd; + top_popup_hmenu = hmenu; + } + + IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPSTART, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0); + + /* Display the window */ + + SetWindowPos( MenuInfo.Wnd, HWND_TOPMOST, 0, 0, 0, 0, + SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); + UpdateWindow( MenuInfo.Wnd ); + return TRUE; +} + + +/*********************************************************************** + * MenuSelectItem + */ +static void FASTCALL MenuSelectItem(HWND hwndOwner, PROSMENUINFO hmenu, UINT wIndex, + BOOL sendMenuSelect, HMENU topmenu) +{ + ROSMENUITEMINFO ItemInfo; + ROSMENUINFO TopMenuInfo; + HDC hdc; + + TRACE("owner=%p menu=%p index=0x%04x select=0x%04x\n", hwndOwner, hmenu, wIndex, sendMenuSelect); + + if (!hmenu || !hmenu->MenuItemCount || !hmenu->Wnd) return; + if (hmenu->FocusedItem == wIndex) return; + if (hmenu->Flags & MF_POPUP) hdc = GetDC(hmenu->Wnd); + else hdc = GetDCEx(hmenu->Wnd, 0, DCX_CACHE | DCX_WINDOW); + if (!top_popup) { + top_popup = hmenu->Wnd; + top_popup_hmenu = hmenu->Self; + } + + SelectObject( hdc, hMenuFont ); + + MenuInitRosMenuItemInfo(&ItemInfo); + + /* Clear previous highlighted item */ + if (hmenu->FocusedItem != NO_SELECTED_ITEM) + { + if (MenuGetRosMenuItemInfo(hmenu->Self, hmenu->FocusedItem, &ItemInfo)) + { + ItemInfo.fMask |= MIIM_STATE; + ItemInfo.fState &= ~(MF_HILITE|MF_MOUSESELECT); + MenuSetRosMenuItemInfo(hmenu->Self, hmenu->FocusedItem, &ItemInfo); + } + MenuDrawMenuItem(hmenu->Wnd, hmenu, hwndOwner, hdc, &ItemInfo, + hmenu->Height, ! (hmenu->Flags & MF_POPUP), + ODA_SELECT); + } + + /* Highlight new item (if any) */ + hmenu->FocusedItem = wIndex; + MenuSetRosMenuInfo(hmenu); + if (hmenu->FocusedItem != NO_SELECTED_ITEM) + { + if (MenuGetRosMenuItemInfo(hmenu->Self, hmenu->FocusedItem, &ItemInfo)) + { + if (!(ItemInfo.fType & MF_SEPARATOR)) + { + ItemInfo.fMask |= MIIM_STATE; + ItemInfo.fState |= MF_HILITE; + MenuSetRosMenuItemInfo(hmenu->Self, hmenu->FocusedItem, &ItemInfo); + MenuDrawMenuItem(hmenu->Wnd, hmenu, hwndOwner, hdc, + &ItemInfo, hmenu->Height, ! (hmenu->Flags & MF_POPUP), + ODA_SELECT); + } + if (sendMenuSelect) + { + SendMessageW(hwndOwner, WM_MENUSELECT, + MAKELONG(ItemInfo.fType & MF_POPUP ? wIndex : ItemInfo.wID, + ItemInfo.fType | ItemInfo.fState | MF_MOUSESELECT | + (hmenu->Flags & MF_SYSMENU)), (LPARAM) hmenu->Self); + } + } + } + else if (sendMenuSelect) { + if(topmenu) { + int pos; + pos = MenuFindSubMenu(&topmenu, hmenu->Self); + if (pos != NO_SELECTED_ITEM) + { + if (MenuGetRosMenuInfo(&TopMenuInfo, topmenu) + && MenuGetRosMenuItemInfo(topmenu, pos, &ItemInfo)) + { + SendMessageW(hwndOwner, WM_MENUSELECT, + MAKELONG(Pos, ItemInfo.fType | ItemInfo.fState + | MF_MOUSESELECT + | (TopMenuInfo.Flags & MF_SYSMENU)), + (LPARAM) topmenu); + } + } + } + } + MenuCleanupRosMenuItemInfo(&ItemInfo); + ReleaseDC(hmenu->Wnd, hdc); +} + +/*********************************************************************** + * MenuMoveSelection + * + * Moves currently selected item according to the Offset parameter. + * If there is no selection then it should select the last item if + * Offset is ITEM_PREV or the first item if Offset is ITEM_NEXT. + */ +static void FASTCALL +MenuMoveSelection(HWND WndOwner, PROSMENUINFO MenuInfo, INT Offset) +{ + INT i; + ROSMENUITEMINFO ItemInfo; + INT OrigPos; + + TRACE("hwnd=%x menu=%x off=0x%04x\n", WndOwner, MenuInfo, Offset); + + /* Prevent looping */ + if (0 == MenuInfo->MenuItemCount || 0 == Offset) + return; + else if (Offset < -1) + Offset = -1; + else if (Offset > 1) + Offset = 1; + + MenuInitRosMenuItemInfo(&ItemInfo); + + OrigPos = MenuInfo->FocusedItem; + if (OrigPos == NO_SELECTED_ITEM) /* NO_SELECTED_ITEM is not -1 ! */ + { + OrigPos = 0; + i = -1; + } + else + { + i = MenuInfo->FocusedItem; + } + + do + { + /* Step */ + i += Offset; + /* Clip and wrap around */ + if (i < 0) + { + i = MenuInfo->MenuItemCount - 1; + } + else if (i >= MenuInfo->MenuItemCount) + { + i = 0; + } + /* If this is a good candidate; */ + if (MenuGetRosMenuItemInfo(MenuInfo->Self, i, &ItemInfo) && + 0 == (ItemInfo.fType & MF_SEPARATOR)) + { + MenuSelectItem(WndOwner, MenuInfo, i, TRUE, NULL); + MenuCleanupRosMenuItemInfo(&ItemInfo); + return; + } + } while (i != OrigPos); + + /* Not found */ + MenuCleanupRosMenuItemInfo(&ItemInfo); +} + +LRESULT WINAPI PopupMenuWndProcA(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam) +{ + TRACE("YES! hwnd=%x msg=0x%04x wp=0x%04lx lp=0x%08lx\n", Wnd, Message, wParam, lParam); + + switch(Message) + { + case WM_CREATE: + { + CREATESTRUCTA *cs = (CREATESTRUCTA *) lParam; + SetWindowLongPtrA(Wnd, 0, (LONG_PTR)cs->lpCreateParams); + return 0; + } + + case WM_MOUSEACTIVATE: /* We don't want to be activated */ + return MA_NOACTIVATE; + + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint(Wnd, &ps); + MenuDrawPopupMenu(Wnd, ps.hdc, (HMENU)GetWindowLongPtrA(Wnd, 0)); + EndPaint(Wnd, &ps); + return 0; + } + + case WM_PRINTCLIENT: + { + MenuDrawPopupMenu( Wnd, (HDC)wParam, + (HMENU)GetWindowLongPtrW( Wnd, 0 ) ); + return 0; + } + + case WM_ERASEBKGND: + return 1; + + case WM_DESTROY: + /* zero out global pointer in case resident popup window was destroyed. */ + if (Wnd == top_popup) + { + top_popup = NULL; + top_popup_hmenu = NULL; + } + break; + + case WM_SHOWWINDOW: + if (0 != wParam) + { + if (0 == GetWindowLongPtrA(Wnd, 0)) + { + OutputDebugStringA("no menu to display\n"); + } + } + else + { + SetWindowLongPtrA(Wnd, 0, 0); + } + break; + + case MM_SETMENUHANDLE: + SetWindowLongPtrA(Wnd, 0, wParam); + break; + + case MM_GETMENUHANDLE: + case MN_GETHMENU: + return GetWindowLongPtrA(Wnd, 0); + + default: + return DefWindowProcA(Wnd, Message, wParam, lParam); + } + return 0; +} + +LRESULT WINAPI +PopupMenuWndProcW(HWND Wnd, UINT Message, WPARAM wParam, LPARAM lParam) +{ + TRACE("hwnd=%x msg=0x%04x wp=0x%04lx lp=0x%08lx\n", Wnd, Message, wParam, lParam); + + switch(Message) + { + case WM_CREATE: + { + CREATESTRUCTW *cs = (CREATESTRUCTW *) lParam; + SetWindowLongPtrW(Wnd, 0, (LONG_PTR)cs->lpCreateParams); + return 0; + } + + case WM_MOUSEACTIVATE: /* We don't want to be activated */ + return MA_NOACTIVATE; + + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint(Wnd, &ps); + MenuDrawPopupMenu(Wnd, ps.hdc, (HMENU)GetWindowLongPtrW(Wnd, 0)); + EndPaint(Wnd, &ps); + return 0; + } + + case WM_PRINTCLIENT: + { + MenuDrawPopupMenu( Wnd, (HDC)wParam, + (HMENU)GetWindowLongPtrW( Wnd, 0 ) ); + return 0; + } + + case WM_ERASEBKGND: + return 1; + + case WM_DESTROY: + /* zero out global pointer in case resident popup window was destroyed. */ + if (Wnd == top_popup) + { + top_popup = NULL; + top_popup_hmenu = NULL; + } + break; + + case WM_SHOWWINDOW: + if (0 != wParam) + { + if (0 == GetWindowLongPtrW(Wnd, 0)) + { + OutputDebugStringA("no menu to display\n"); + } + } + else + { + SetWindowLongPtrW(Wnd, 0, 0); + } + break; + + case MM_SETMENUHANDLE: + SetWindowLongPtrW(Wnd, 0, wParam); + break; + + case MM_GETMENUHANDLE: + case MN_GETHMENU: + return GetWindowLongPtrW(Wnd, 0); + + default: + return DefWindowProcW(Wnd, Message, wParam, lParam); + } + + return 0; +} + +/********************************************************************** + * MENU_ParseResource + * + * Parse a standard menu resource and add items to the menu. + * Return a pointer to the end of the resource. + * + * NOTE: flags is equivalent to the mtOption field + */ +static LPCSTR MENU_ParseResource( LPCSTR res, HMENU hMenu, BOOL unicode ) +{ + WORD flags, id = 0; + HMENU hSubMenu; + LPCSTR str; + BOOL end = FALSE; + + do + { + flags = GET_WORD(res); + + /* remove MF_END flag before passing it to AppendMenu()! */ + end = (flags & MF_END); + if(end) flags ^= MF_END; + + res += sizeof(WORD); + if(!(flags & MF_POPUP)) + { + id = GET_WORD(res); + res += sizeof(WORD); + } + str = res; + if(!unicode) + res += strlen(str) + 1; + else + res += (strlenW((LPCWSTR)str) + 1) * sizeof(WCHAR); + if (flags & MF_POPUP) + { + hSubMenu = CreatePopupMenu(); + if(!hSubMenu) return NULL; + if(!(res = MENU_ParseResource(res, hSubMenu, unicode))) + return NULL; + if(!unicode) + AppendMenuA(hMenu, flags, (UINT)hSubMenu, str); + else + AppendMenuW(hMenu, flags, (UINT)hSubMenu, (LPCWSTR)str); + } + else /* Not a popup */ + { + if(!unicode) + { + if (*str == 0) + flags = MF_SEPARATOR; + } + else + { + if (*(LPCWSTR)str == 0) + flags = MF_SEPARATOR; + } + + if (flags & MF_SEPARATOR) + { + if (!(flags & (MF_GRAYED | MF_DISABLED))) + flags |= MF_GRAYED | MF_DISABLED; + } + + if(!unicode) + AppendMenuA(hMenu, flags, id, *str ? str : NULL); + else + AppendMenuW(hMenu, flags, id, + *(LPCWSTR)str ? (LPCWSTR)str : NULL); + } + } while(!end); + return res; +} + + +/********************************************************************** + * MENUEX_ParseResource + * + * Parse an extended menu resource and add items to the menu. + * Return a pointer to the end of the resource. + */ +static LPCSTR MENUEX_ParseResource( LPCSTR res, HMENU hMenu) +{ + WORD resinfo; + do { + MENUITEMINFOW mii; + + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_STATE | MIIM_ID | MIIM_FTYPE; + mii.fType = GET_DWORD(res); + res += sizeof(DWORD); + mii.fState = GET_DWORD(res); + res += sizeof(DWORD); + mii.wID = GET_DWORD(res); + res += sizeof(DWORD); + resinfo = GET_WORD(res); + res += sizeof(WORD); + /* Align the text on a word boundary. */ + res += (~((UINT_PTR)res - 1)) & 1; + mii.dwTypeData = (LPWSTR) res; + res += (1 + strlenW(mii.dwTypeData)) * sizeof(WCHAR); + /* Align the following fields on a dword boundary. */ + res += (~((UINT_PTR)res - 1)) & 3; + + TRACE("Menu item: [%08x,%08x,%04x,%04x,%S]\n", + mii.fType, mii.fState, mii.wID, resinfo, mii.dwTypeData); + + if (resinfo & 1) { /* Pop-up? */ + /* DWORD helpid = GET_DWORD(res); FIXME: use this. */ + res += sizeof(DWORD); + mii.hSubMenu = CreatePopupMenu(); + if (!mii.hSubMenu) + return NULL; + if (!(res = MENUEX_ParseResource(res, mii.hSubMenu))) { + DestroyMenu(mii.hSubMenu); + return NULL; + } + mii.fMask |= MIIM_SUBMENU; + mii.fType |= MF_POPUP; + mii.wID = (UINT) mii.hSubMenu; + } + else if(!*mii.dwTypeData && !(mii.fType & MF_SEPARATOR)) + { + mii.fType |= MF_SEPARATOR; + } + InsertMenuItemW(hMenu, -1, MF_BYPOSITION, &mii); + } while (!(resinfo & MF_END)); + return res; +} + +NTSTATUS WINAPI +User32LoadSysMenuTemplateForKernel(PVOID Arguments, ULONG ArgumentLength) +{ + HMENU hmenu = LoadMenuW(User32Instance, L"SYSMENU"); + LRESULT Result = (LRESULT)hmenu; + MENUINFO menuinfo = {0}; + MENUITEMINFOW info = {0}; + + // removing space for checkboxes from menu + menuinfo.cbSize = sizeof(menuinfo); + menuinfo.fMask = MIM_STYLE; + GetMenuInfo(hmenu, &menuinfo); + menuinfo.dwStyle |= MNS_NOCHECK; + SetMenuInfo(hmenu, &menuinfo); + + // adding bitmaps to menu items + info.cbSize = sizeof(info); + info.fMask |= MIIM_BITMAP; + info.hbmpItem = HBMMENU_POPUP_MINIMIZE; + SetMenuItemInfoW(hmenu, SC_MINIMIZE, FALSE, &info); + info.hbmpItem = HBMMENU_POPUP_RESTORE; + SetMenuItemInfoW(hmenu, SC_RESTORE, FALSE, &info); + info.hbmpItem = HBMMENU_POPUP_MAXIMIZE; + SetMenuItemInfoW(hmenu, SC_MAXIMIZE, FALSE, &info); + info.hbmpItem = HBMMENU_POPUP_CLOSE; + SetMenuItemInfoW(hmenu, SC_CLOSE, FALSE, &info); + + return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS)); +} + + +BOOL +MenuInit(VOID) +{ + NONCLIENTMETRICSW ncm; + + /* get the menu font */ + if(!hMenuFont || !hMenuFontBold) + { + ncm.cbSize = sizeof(ncm); + if(!SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0)) + { + DbgPrint("MenuInit(): SystemParametersInfoW(SPI_GETNONCLIENTMETRICS) failed!\n"); + return FALSE; + } + + hMenuFont = CreateFontIndirectW(&ncm.lfMenuFont); + if(hMenuFont == NULL) + { + DbgPrint("MenuInit(): CreateFontIndirectW(hMenuFont) failed!\n"); + return FALSE; + } + + ncm.lfMenuFont.lfWeight = max(ncm.lfMenuFont.lfWeight + 300, 1000); + hMenuFontBold = CreateFontIndirectW(&ncm.lfMenuFont); + if(hMenuFontBold == NULL) + { + DbgPrint("MenuInit(): CreateFontIndirectW(hMenuFontBold) failed!\n"); + DeleteObject(hMenuFont); + hMenuFont = NULL; + return FALSE; + } + } + + return TRUE; +} + +VOID +MenuCleanup(VOID) +{ + if (hMenuFont) + { + DeleteObject(hMenuFont); + hMenuFont = NULL; + } + + if (hMenuFontBold) + { + DeleteObject(hMenuFontBold); + hMenuFontBold = NULL; + } +} + +/*********************************************************************** + * DrawMenuBarTemp (USER32.@) + * + * UNDOCUMENTED !! + * + * called by W98SE desk.cpl Control Panel Applet + * + * Not 100% sure about the param names, but close. + * + * @implemented + */ +DWORD WINAPI +DrawMenuBarTemp(HWND Wnd, HDC DC, LPRECT Rect, HMENU Menu, HFONT Font) +{ + ROSMENUINFO MenuInfo; + ROSMENUITEMINFO ItemInfo; + UINT i; + HFONT FontOld = NULL; + BOOL flat_menu = FALSE; + + SystemParametersInfoW (SPI_GETFLATMENU, 0, &flat_menu, 0); + + if (NULL == Menu) + { + Menu = GetMenu(Wnd); + } + + if (NULL == Font) + { + Font = hMenuFont; + } + + if (NULL == Rect || ! MenuGetRosMenuInfo(&MenuInfo, Menu)) + { + return GetSystemMetrics(SM_CYMENU); + } + + TRACE("(%x, %x, %p, %x, %x)\n", Wnd, DC, Rect, Menu, Font); + + FontOld = SelectObject(DC, Font); + + if (0 == MenuInfo.Height) + { + MenuMenuBarCalcSize(DC, Rect, &MenuInfo, Wnd); + } + + Rect->bottom = Rect->top + MenuInfo.Height; + + FillRect(DC, Rect, GetSysColorBrush(flat_menu ? COLOR_MENUBAR : COLOR_MENU)); + + SelectObject(DC, GetStockObject(DC_PEN)); + SetDCPenColor(DC, GetSysColor(COLOR_3DFACE)); + MoveToEx(DC, Rect->left, Rect->bottom - 1, NULL); + LineTo(DC, Rect->right, Rect->bottom - 1); + + if (0 == MenuInfo.MenuItemCount) + { + SelectObject(DC, FontOld); + return GetSystemMetrics(SM_CYMENU); + } + + MenuInitRosMenuItemInfo(&ItemInfo); + for (i = 0; i < MenuInfo.MenuItemCount; i++) + { + if (MenuGetRosMenuItemInfo(MenuInfo.Self, i, &ItemInfo)) + { + MenuDrawMenuItem(Wnd, &MenuInfo, Wnd, DC, &ItemInfo, + MenuInfo.Height, TRUE, ODA_DRAWENTIRE); + } + } + MenuCleanupRosMenuItemInfo(&ItemInfo); + + SelectObject(DC, FontOld); + + return MenuInfo.Height; +} + +/*********************************************************************** + * MenuShowSubPopup + * + * Display the sub-menu of the selected item of this menu. + * Return the handle of the submenu, or menu if no submenu to display. + */ +static HMENU FASTCALL +MenuShowSubPopup(HWND WndOwner, PROSMENUINFO MenuInfo, BOOL SelectFirst, UINT Flags) +{ + extern void FASTCALL NcGetSysPopupPos(HWND Wnd, RECT *Rect); + RECT Rect; + ROSMENUITEMINFO ItemInfo; + ROSMENUINFO SubMenuInfo; + HDC Dc; + HMENU Ret; + + TRACE("owner=%x menu=%p 0x%04x\n", WndOwner, MenuInfo, SelectFirst); + + if (NO_SELECTED_ITEM == MenuInfo->FocusedItem) + { + return MenuInfo->Self; + } + + MenuInitRosMenuItemInfo(&ItemInfo); + if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo)) + { + MenuCleanupRosMenuItemInfo(&ItemInfo); + return MenuInfo->Self; + } + if (0 == (ItemInfo.fType & MF_POPUP) || 0 != (ItemInfo.fState & (MF_GRAYED | MF_DISABLED))) + { + MenuCleanupRosMenuItemInfo(&ItemInfo); + return MenuInfo->Self; + } + + /* message must be sent before using item, + because nearly everything may be changed by the application ! */ + + /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */ + if (0 == (Flags & TPM_NONOTIFY)) + { + SendMessageW(WndOwner, WM_INITMENUPOPUP, (WPARAM) ItemInfo.hSubMenu, + MAKELONG(MenuInfo->FocusedItem, IS_SYSTEM_MENU(MenuInfo))); + } + + if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo)) + { + MenuCleanupRosMenuItemInfo(&ItemInfo); + return MenuInfo->Self; + } + Rect = ItemInfo.Rect; + + /* correct item if modified as a reaction to WM_INITMENUPOPUP message */ + if (0 == (ItemInfo.fState & MF_HILITE)) + { + if (0 != (MenuInfo->Flags & MF_POPUP)) + { + Dc = GetDC(MenuInfo->Wnd); + } + else + { + Dc = GetDCEx(MenuInfo->Wnd, 0, DCX_CACHE | DCX_WINDOW); + } + + SelectObject(Dc, hMenuFont); + ItemInfo.fMask |= MIIM_STATE; + ItemInfo.fState |= MF_HILITE; + MenuSetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo); + MenuDrawMenuItem(MenuInfo->Wnd, MenuInfo, WndOwner, Dc, &ItemInfo, MenuInfo->Height, + ! (MenuInfo->Flags & MF_POPUP), ODA_DRAWENTIRE); + ReleaseDC(MenuInfo->Wnd, Dc); + } + + if (0 == ItemInfo.Rect.top && 0 == ItemInfo.Rect.left + && 0 == ItemInfo.Rect.bottom && 0 == ItemInfo.Rect.right) + { + ItemInfo.Rect = Rect; + } + + ItemInfo.fMask |= MIIM_STATE; + ItemInfo.fState |= MF_MOUSESELECT; + MenuSetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo); + + if (IS_SYSTEM_MENU(MenuInfo)) + { + MenuInitSysMenuPopup(ItemInfo.hSubMenu, GetWindowLongPtrW(MenuInfo->Wnd, GWL_STYLE), + GetClassLongPtrW(MenuInfo->Wnd, GCL_STYLE), HTSYSMENU); + + NcGetSysPopupPos(MenuInfo->Wnd, &Rect); + Rect.top = Rect.bottom; + Rect.right = GetSystemMetrics(SM_CXSIZE); + Rect.bottom = GetSystemMetrics(SM_CYSIZE); + } + else + { + GetWindowRect(MenuInfo->Wnd, &Rect); + if (0 != (MenuInfo->Flags & MF_POPUP)) + { + Rect.left += ItemInfo.Rect.right - GetSystemMetrics(SM_CXBORDER); + Rect.top += ItemInfo.Rect.top - 3; + Rect.right = ItemInfo.Rect.left - ItemInfo.Rect.right + GetSystemMetrics(SM_CXBORDER); + Rect.bottom = ItemInfo.Rect.top - ItemInfo.Rect.bottom - 3 - 2 + - GetSystemMetrics(SM_CYBORDER); + } + else + { + Rect.left += ItemInfo.Rect.left; + Rect.top += ItemInfo.Rect.bottom; + Rect.right = ItemInfo.Rect.right - ItemInfo.Rect.left; + Rect.bottom = ItemInfo.Rect.bottom - ItemInfo.Rect.top; + } + } + + MenuShowPopup(WndOwner, ItemInfo.hSubMenu, MenuInfo->FocusedItem, Flags, + Rect.left, Rect.top, Rect.right, Rect.bottom ); + if (SelectFirst && MenuGetRosMenuInfo(&SubMenuInfo, ItemInfo.hSubMenu)) + { + MenuMoveSelection(WndOwner, &SubMenuInfo, ITEM_NEXT); + } + + Ret = ItemInfo.hSubMenu; + MenuCleanupRosMenuItemInfo(&ItemInfo); + + return Ret; +} + +/********************************************************************** + * MENU_EndMenu + * + * Calls EndMenu() if the hwnd parameter belongs to the menu owner + * + * Does the (menu stuff) of the default window handling of WM_CANCELMODE + */ +void MENU_EndMenu( HWND hwnd ) +{ + ROSMENUINFO MenuInfo; + BOOL Ret = FALSE; + if (top_popup_hmenu) + Ret = MenuGetRosMenuInfo(&MenuInfo, top_popup_hmenu); + if (Ret && hwnd == MenuInfo.WndOwner) EndMenu(); +} + +/*********************************************************************** + * MenuHideSubPopups + * + * Hide the sub-popup menus of this menu. + */ +static void FASTCALL +MenuHideSubPopups(HWND WndOwner, PROSMENUINFO MenuInfo, + BOOL SendMenuSelect, UINT wFlags) +{ + ROSMENUINFO SubMenuInfo; + ROSMENUITEMINFO ItemInfo; + + TRACE("owner=%x menu=%x 0x%04x\n", WndOwner, MenuInfo, SendMenuSelect); + + if (NULL != MenuInfo && NULL != top_popup && NO_SELECTED_ITEM != MenuInfo->FocusedItem) + { + MenuInitRosMenuItemInfo(&ItemInfo); + ItemInfo.fMask |= MIIM_FTYPE | MIIM_STATE; + if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo) + || 0 == (ItemInfo.fType & MF_POPUP) + || 0 == (ItemInfo.fState & MF_MOUSESELECT)) + { + MenuCleanupRosMenuItemInfo(&ItemInfo); + return; + } + ItemInfo.fState &= ~MF_MOUSESELECT; + ItemInfo.fMask |= MIIM_STATE; + MenuSetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo); + if (MenuGetRosMenuInfo(&SubMenuInfo, ItemInfo.hSubMenu)) + { + MenuHideSubPopups(WndOwner, &SubMenuInfo, FALSE, wFlags); + MenuSelectItem(WndOwner, &SubMenuInfo, NO_SELECTED_ITEM, SendMenuSelect, NULL); + DestroyWindow(SubMenuInfo.Wnd); + SubMenuInfo.Wnd = NULL; + MenuSetRosMenuInfo(&SubMenuInfo); + + if (!(wFlags & TPM_NONOTIFY)) + SendMessageW( WndOwner, WM_UNINITMENUPOPUP, (WPARAM)ItemInfo.hSubMenu, + MAKELPARAM(0, IS_SYSTEM_MENU(&SubMenuInfo)) ); + } + } +} + +/*********************************************************************** + * MenuSwitchTracking + * + * Helper function for menu navigation routines. + */ +static void FASTCALL +MenuSwitchTracking(MTRACKER* Mt, PROSMENUINFO PtMenuInfo, UINT Index, UINT wFlags) +{ + ROSMENUINFO TopMenuInfo; + + TRACE("%x menu=%x 0x%04x\n", Mt, PtMenuInfo->Self, Index); + + if (MenuGetRosMenuInfo(&TopMenuInfo, Mt->TopMenu) && + Mt->TopMenu != PtMenuInfo->Self && + 0 == ((PtMenuInfo->Flags | TopMenuInfo.Flags) & MF_POPUP)) + { + /* both are top level menus (system and menu-bar) */ + MenuHideSubPopups(Mt->OwnerWnd, &TopMenuInfo, FALSE, wFlags); + MenuSelectItem(Mt->OwnerWnd, &TopMenuInfo, NO_SELECTED_ITEM, FALSE, NULL); + Mt->TopMenu = PtMenuInfo->Self; + } + else + { + MenuHideSubPopups(Mt->OwnerWnd, PtMenuInfo, FALSE, wFlags); + } + + MenuSelectItem(Mt->OwnerWnd, PtMenuInfo, Index, TRUE, NULL); +} + +/*********************************************************************** + * MenuExecFocusedItem + * + * Execute a menu item (for instance when user pressed Enter). + * Return the wID of the executed item. Otherwise, -1 indicating + * that no menu item was executed, -2 if a popup is shown; + * Have to receive the flags for the TrackPopupMenu options to avoid + * sending unwanted message. + * + */ +static INT FASTCALL +MenuExecFocusedItem(MTRACKER *Mt, PROSMENUINFO MenuInfo, UINT Flags) +{ + ROSMENUITEMINFO ItemInfo; + UINT wID; + + TRACE("%p menu=%p\n", Mt, MenuInfo); + + if (0 == MenuInfo->MenuItemCount || NO_SELECTED_ITEM == MenuInfo->FocusedItem) + { + return -1; + } + + MenuInitRosMenuItemInfo(&ItemInfo); + if (! MenuGetRosMenuItemInfo(MenuInfo->Self, MenuInfo->FocusedItem, &ItemInfo)) + { + MenuCleanupRosMenuItemInfo(&ItemInfo); + return -1; + } + + TRACE("%p %08x %p\n", MenuInfo, ItemInfo.wID, ItemInfo.hSubMenu); + + if (0 == (ItemInfo.fType & MF_POPUP)) + { + if (0 == (ItemInfo.fState & (MF_GRAYED | MF_DISABLED)) + && 0 == (ItemInfo.fType & MF_SEPARATOR)) + { + /* If TPM_RETURNCMD is set you return the id, but + do not send a message to the owner */ + if (0 == (Flags & TPM_RETURNCMD)) + { + if (0 != (MenuInfo->Flags & MF_SYSMENU)) + { + PostMessageW(Mt->OwnerWnd, WM_SYSCOMMAND, ItemInfo.wID, + MAKELPARAM((SHORT) Mt->Pt.x, (SHORT) Mt->Pt.y)); + } + else + { + if (MenuInfo->dwStyle & MNS_NOTIFYBYPOS) + PostMessageW(Mt->OwnerWnd, WM_MENUCOMMAND, + MenuInfo->FocusedItem, + (LPARAM)MenuInfo->Self); + else + PostMessageW(Mt->OwnerWnd, WM_COMMAND, ItemInfo.wID, 0); + } + } + wID = ItemInfo.wID; + MenuCleanupRosMenuItemInfo(&ItemInfo); + return wID; + } + } + else + { + Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, MenuInfo, TRUE, Flags); + return -2; + } + + return -1; +} + +/*********************************************************************** + * MenuButtonDown + * + * Return TRUE if we can go on with menu tracking. + */ +static BOOL FASTCALL +MenuButtonDown(MTRACKER* Mt, HMENU PtMenu, UINT Flags) +{ + int Index; + ROSMENUINFO MenuInfo; + ROSMENUITEMINFO Item; + + TRACE("%x PtMenu=%p\n", Mt, PtMenu); + + if (NULL != PtMenu) + { + if (! MenuGetRosMenuInfo(&MenuInfo, PtMenu)) + { + return FALSE; + } + if (IS_SYSTEM_MENU(&MenuInfo)) + { + Index = 0; + } + else + { + Index = NtUserMenuItemFromPoint(Mt->OwnerWnd, PtMenu, Mt->Pt.x, Mt->Pt.y); + } + MenuInitRosMenuItemInfo(&Item); + if (NO_SELECTED_ITEM == Index || ! MenuGetRosMenuItemInfo(PtMenu, Index, &Item)) + { + MenuCleanupRosMenuItemInfo(&Item); + return FALSE; + } + + if (!(Item.fType & MF_SEPARATOR) && + !(Item.fState & (MFS_DISABLED | MFS_GRAYED)) ) + { + if (MenuInfo.FocusedItem != Index) + { + MenuSwitchTracking(Mt, &MenuInfo, Index, Flags); + } + + /* If the popup menu is not already "popped" */ + if (0 == (Item.fState & MF_MOUSESELECT)) + { + Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo, FALSE, Flags); + } + } + + MenuCleanupRosMenuItemInfo(&Item); + + return TRUE; + } + + /* else the click was on the menu bar, finish the tracking */ + + return FALSE; +} + +/*********************************************************************** + * MenuButtonUp + * + * Return the value of MenuExecFocusedItem if + * the selected item was not a popup. Else open the popup. + * A -1 return value indicates that we go on with menu tracking. + * + */ +static INT FASTCALL +MenuButtonUp(MTRACKER *Mt, HMENU PtMenu, UINT Flags) +{ + UINT Id; + ROSMENUINFO MenuInfo; + ROSMENUITEMINFO ItemInfo; + + TRACE("%p hmenu=%x\n", Mt, PtMenu); + + if (NULL != PtMenu) + { + Id = 0; + if (! MenuGetRosMenuInfo(&MenuInfo, PtMenu)) + { + return -1; + } + + if (! IS_SYSTEM_MENU(&MenuInfo)) + { + Id = NtUserMenuItemFromPoint(Mt->OwnerWnd, MenuInfo.Self, Mt->Pt.x, Mt->Pt.y); + } + MenuInitRosMenuItemInfo(&ItemInfo); + if (0 <= Id && MenuGetRosMenuItemInfo(MenuInfo.Self, Id, &ItemInfo) && + MenuInfo.FocusedItem == Id) + { + if (0 == (ItemInfo.fType & MF_POPUP)) + { + INT ExecutedMenuId = MenuExecFocusedItem(Mt, &MenuInfo, Flags); + MenuCleanupRosMenuItemInfo(&ItemInfo); + return (ExecutedMenuId < 0) ? -1 : ExecutedMenuId; + } + MenuCleanupRosMenuItemInfo(&ItemInfo); + + /* If we are dealing with the top-level menu */ + /* and this is a click on an already "popped" item: */ + /* Stop the menu tracking and close the opened submenus */ + if (Mt->TopMenu == MenuInfo.Self && MenuInfo.TimeToHide) + { + MenuCleanupRosMenuItemInfo(&ItemInfo); + return 0; + } + } + MenuCleanupRosMenuItemInfo(&ItemInfo); + MenuInfo.TimeToHide = TRUE; + MenuSetRosMenuInfo(&MenuInfo); + } + + return -1; +} + +/*********************************************************************** + * MenuPtMenu + * + * Walks menu chain trying to find a menu pt maps to. + */ +static HMENU FASTCALL +MenuPtMenu(HMENU Menu, POINT Pt) +{ + extern LRESULT DefWndNCHitTest(HWND hWnd, POINT Point); + ROSMENUINFO MenuInfo; + ROSMENUITEMINFO ItemInfo; + HMENU Ret = NULL; + INT Ht; + + if (! MenuGetRosMenuInfo(&MenuInfo, Menu)) + { + return NULL; + } + + /* try subpopup first (if any) */ + if (NO_SELECTED_ITEM != MenuInfo.FocusedItem) + { + MenuInitRosMenuItemInfo(&ItemInfo); + if (MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.FocusedItem, &ItemInfo) && + 0 != (ItemInfo.fType & MF_POPUP) && + 0 != (ItemInfo.fState & MF_MOUSESELECT)) + { + Ret = MenuPtMenu(ItemInfo.hSubMenu, Pt); + if (NULL != Ret) + { + MenuCleanupRosMenuItemInfo(&ItemInfo); + return Ret; + } + } + MenuCleanupRosMenuItemInfo(&ItemInfo); + } + + /* check the current window (avoiding WM_HITTEST) */ + Ht = DefWndNCHitTest(MenuInfo.Wnd, Pt); + if (0 != (MenuInfo.Flags & MF_POPUP)) + { + if (HTNOWHERE != Ht && HTERROR != Ht) + { + Ret = Menu; + } + } + else if (HTSYSMENU == Ht) + { + Ret = NtUserGetSystemMenu(MenuInfo.Wnd, FALSE); + } + else if (HTMENU == Ht) + { + Ret = GetMenu(MenuInfo.Wnd); + } + + return Ret; +} + +/*********************************************************************** + * MenuMouseMove + * + * Return TRUE if we can go on with menu tracking. + */ +static BOOL FASTCALL +MenuMouseMove(MTRACKER *Mt, HMENU PtMenu, UINT Flags) +{ + UINT Index; + ROSMENUINFO MenuInfo; + ROSMENUITEMINFO ItemInfo; + + if (NULL != PtMenu) + { + if (! MenuGetRosMenuInfo(&MenuInfo, PtMenu)) + { + return TRUE; + } + if (IS_SYSTEM_MENU(&MenuInfo)) + { + Index = 0; + } + else + { + Index = NtUserMenuItemFromPoint(Mt->OwnerWnd, PtMenu, Mt->Pt.x, Mt->Pt.y); + } + } + else + { + Index = NO_SELECTED_ITEM; + } + + if (NO_SELECTED_ITEM == Index) + { + if (Mt->CurrentMenu == MenuInfo.Self || + MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu)) + { + MenuSelectItem(Mt->OwnerWnd, &MenuInfo, NO_SELECTED_ITEM, + TRUE, Mt->TopMenu); + } + } + else if (MenuInfo.FocusedItem != Index) + { + MenuInitRosMenuItemInfo(&ItemInfo); + if (MenuGetRosMenuItemInfo(MenuInfo.Self, Index, &ItemInfo) && + !(ItemInfo.fType & MF_SEPARATOR)) + { + MenuSwitchTracking(Mt, &MenuInfo, Index, Flags); + if (!(ItemInfo.fState & (MFS_DISABLED | MFS_GRAYED))) + Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo, FALSE, Flags); + } + MenuCleanupRosMenuItemInfo(&ItemInfo); + } + + return TRUE; +} + +/*********************************************************************** + * MenuGetSubPopup + * + * Return the handle of the selected sub-popup menu (if any). + */ +static HMENU FASTCALL +MenuGetSubPopup(HMENU Menu) +{ + ROSMENUINFO MenuInfo; + ROSMENUITEMINFO ItemInfo; + + if (! MenuGetRosMenuInfo(&MenuInfo, Menu) + || NO_SELECTED_ITEM == MenuInfo.FocusedItem) + { + return NULL; + } + + MenuInitRosMenuItemInfo(&ItemInfo); + if (! MenuGetRosMenuItemInfo(MenuInfo.Self, MenuInfo.FocusedItem, &ItemInfo)) + { + MenuCleanupRosMenuItemInfo(&ItemInfo); + return NULL; + } + if (0 != (ItemInfo.fType & MF_POPUP) && 0 != (ItemInfo.fState & MF_MOUSESELECT)) + { + MenuCleanupRosMenuItemInfo(&ItemInfo); + return ItemInfo.hSubMenu; + } + + MenuCleanupRosMenuItemInfo(&ItemInfo); + return NULL; +} + +/*********************************************************************** + * MenuDoNextMenu + * + * NOTE: WM_NEXTMENU documented in Win32 is a bit different. + */ +static LRESULT FASTCALL +MenuDoNextMenu(MTRACKER* Mt, UINT Vk, UINT wFlags) +{ + ROSMENUINFO TopMenuInfo; + ROSMENUINFO MenuInfo; + + if (! MenuGetRosMenuInfo(&TopMenuInfo, Mt->TopMenu)) + { + return (LRESULT) FALSE; + } + + if ((VK_LEFT == Vk && 0 == TopMenuInfo.FocusedItem) + || (VK_RIGHT == Vk && TopMenuInfo.FocusedItem == TopMenuInfo.MenuItemCount - 1)) + { + MDINEXTMENU NextMenu; + HMENU NewMenu; + HWND NewWnd; + UINT Id = 0; + + NextMenu.hmenuIn = (IS_SYSTEM_MENU(&TopMenuInfo)) ? GetSubMenu(Mt->TopMenu, 0) : Mt->TopMenu; + NextMenu.hmenuNext = NULL; + NextMenu.hwndNext = NULL; + SendMessageW(Mt->OwnerWnd, WM_NEXTMENU, Vk, (LPARAM) &NextMenu); + + TRACE("%p [%p] -> %p [%p]\n", + Mt->CurrentMenu, Mt->OwnerWnd, NextMenu.hmenuNext, NextMenu.hwndNext ); + + if (NULL == NextMenu.hmenuNext || NULL == NextMenu.hwndNext) + { + DWORD Style = GetWindowLongPtrW(Mt->OwnerWnd, GWL_STYLE); + NewWnd = Mt->OwnerWnd; + if (IS_SYSTEM_MENU(&TopMenuInfo)) + { + /* switch to the menu bar */ + + if (0 != (Style & WS_CHILD) + || NULL == (NewMenu = GetMenu(NewWnd))) + { + return FALSE; + } + + if (VK_LEFT == Vk) + { + if (! MenuGetRosMenuInfo(&MenuInfo, NewMenu)) + { + return FALSE; + } + Id = MenuInfo.MenuItemCount - 1; + } + } + else if (0 != (Style & WS_SYSMENU)) + { + /* switch to the system menu */ + NewMenu = NtUserGetSystemMenu(NewWnd, FALSE); + } + else + { + return FALSE; + } + } + else /* application returned a new menu to switch to */ + { + NewMenu = NextMenu.hmenuNext; + NewWnd = NextMenu.hwndNext; + + if (IsMenu(NewMenu) && IsWindow(NewWnd)) + { + DWORD Style = GetWindowLongPtrW(NewWnd, GWL_STYLE); + + if (0 != (Style & WS_SYSMENU) + && GetSystemMenu(NewWnd, FALSE) == NewMenu) + { + /* get the real system menu */ + NewMenu = NtUserGetSystemMenu(NewWnd, FALSE); + } + else if (0 != (Style & WS_CHILD) || GetMenu(NewWnd) != NewMenu) + { + /* FIXME: Not sure what to do here; + * perhaps try to track NewMenu as a popup? */ + + WARN(" -- got confused.\n"); + return FALSE; + } + } + else + { + return FALSE; + } + } + + if (NewMenu != Mt->TopMenu) + { + MenuSelectItem(Mt->OwnerWnd, &TopMenuInfo, NO_SELECTED_ITEM, + FALSE, 0 ); + if (Mt->CurrentMenu != Mt->TopMenu) + { + MenuHideSubPopups(Mt->OwnerWnd, &TopMenuInfo, FALSE, wFlags); + } + } + + if (NewWnd != Mt->OwnerWnd) + { + Mt->OwnerWnd = NewWnd; + SetCapture(Mt->OwnerWnd); + (void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, Mt->OwnerWnd); + } + + Mt->TopMenu = Mt->CurrentMenu = NewMenu; /* all subpopups are hidden */ + if (MenuGetRosMenuInfo(&TopMenuInfo, Mt->TopMenu)) + { + MenuSelectItem(Mt->OwnerWnd, &TopMenuInfo, Id, TRUE, 0); + } + + return TRUE; + } + + return FALSE; +} + +/*********************************************************************** + * MenuSuspendPopup + * + * The idea is not to show the popup if the next input message is + * going to hide it anyway. + */ +static BOOL FASTCALL +MenuSuspendPopup(MTRACKER* Mt, UINT Message) +{ + MSG Msg; + + Msg.hwnd = Mt->OwnerWnd; + + PeekMessageW(&Msg, 0, 0, 0, PM_NOYIELD | PM_REMOVE); + Mt->TrackFlags |= TF_SKIPREMOVE; + + switch (Message) + { + case WM_KEYDOWN: + PeekMessageW(&Msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE); + if (WM_KEYUP == Msg.message || WM_PAINT == Msg.message) + { + PeekMessageW(&Msg, 0, 0, 0, PM_NOYIELD | PM_REMOVE); + PeekMessageW(&Msg, 0, 0, 0, PM_NOYIELD | PM_NOREMOVE); + if (WM_KEYDOWN == Msg.message + && (VK_LEFT == Msg.wParam || VK_RIGHT == Msg.wParam)) + { + Mt->TrackFlags |= TF_SUSPENDPOPUP; + return TRUE; + } + } + break; + } + + /* failures go through this */ + Mt->TrackFlags &= ~TF_SUSPENDPOPUP; + + return FALSE; +} + +/*********************************************************************** + * MenuKeyEscape + * + * Handle a VK_ESCAPE key event in a menu. + */ +static BOOL FASTCALL +MenuKeyEscape(MTRACKER *Mt, UINT Flags) +{ + BOOL EndMenu = TRUE; + ROSMENUINFO MenuInfo; + HMENU MenuTmp, MenuPrev; + + if (Mt->CurrentMenu != Mt->TopMenu) + { + if (MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu) + && 0 != (MenuInfo.Flags & MF_POPUP)) + { + MenuPrev = MenuTmp = Mt->TopMenu; + + /* close topmost popup */ + while (MenuTmp != Mt->CurrentMenu) + { + MenuPrev = MenuTmp; + MenuTmp = MenuGetSubPopup(MenuPrev); + } + + if (MenuGetRosMenuInfo(&MenuInfo, MenuPrev)) + { + MenuHideSubPopups(Mt->OwnerWnd, &MenuInfo, TRUE, Flags); + } + Mt->CurrentMenu = MenuPrev; + EndMenu = FALSE; + } + } + + return EndMenu; +} + +/*********************************************************************** + * MenuKeyLeft + * + * Handle a VK_LEFT key event in a menu. + */ +static void FASTCALL +MenuKeyLeft(MTRACKER* Mt, UINT Flags) +{ + ROSMENUINFO MenuInfo; + ROSMENUINFO TopMenuInfo; + ROSMENUINFO PrevMenuInfo; + HMENU MenuTmp, MenuPrev; + UINT PrevCol; + + MenuPrev = MenuTmp = Mt->TopMenu; + + if (! MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu)) + { + return; + } + + /* Try to move 1 column left (if possible) */ + if (NO_SELECTED_ITEM != (PrevCol = MenuGetStartOfPrevColumn(&MenuInfo))) + { + if (MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu)) + { + MenuSelectItem(Mt->OwnerWnd, &MenuInfo, PrevCol, TRUE, 0); + } + return; + } + + /* close topmost popup */ + while (MenuTmp != Mt->CurrentMenu) + { + MenuPrev = MenuTmp; + MenuTmp = MenuGetSubPopup(MenuPrev); + } + + if (! MenuGetRosMenuInfo(&PrevMenuInfo, MenuPrev)) + { + return; + } + MenuHideSubPopups(Mt->OwnerWnd, &PrevMenuInfo, TRUE, Flags); + Mt->CurrentMenu = MenuPrev; + + if (! MenuGetRosMenuInfo(&TopMenuInfo, Mt->TopMenu)) + { + return; + } + if ((MenuPrev == Mt->TopMenu) && 0 == (TopMenuInfo.Flags & MF_POPUP)) + { + /* move menu bar selection if no more popups are left */ + + if (! MenuDoNextMenu(Mt, VK_LEFT, Flags)) + { + MenuMoveSelection(Mt->OwnerWnd, &TopMenuInfo, ITEM_PREV); + } + + if (MenuPrev != MenuTmp || 0 != (Mt->TrackFlags & TF_SUSPENDPOPUP)) + { + /* A sublevel menu was displayed - display the next one + * unless there is another displacement coming up */ + + if (! MenuSuspendPopup(Mt, WM_KEYDOWN) + && MenuGetRosMenuInfo(&TopMenuInfo, Mt->TopMenu)) + { + Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &TopMenuInfo, + TRUE, Flags); + } + } + } +} + +/*********************************************************************** + * MenuKeyRight + * + * Handle a VK_RIGHT key event in a menu. + */ +static void FASTCALL MenuKeyRight(MTRACKER *Mt, UINT Flags) +{ + HMENU hmenutmp; + ROSMENUINFO MenuInfo; + ROSMENUINFO CurrentMenuInfo; + UINT NextCol; + + TRACE("MenuKeyRight called, cur %p, top %p.\n", + Mt->CurrentMenu, Mt->TopMenu); + + if (! MenuGetRosMenuInfo(&MenuInfo, Mt->TopMenu)) return; + if ((MenuInfo.Flags & MF_POPUP) || (Mt->CurrentMenu != Mt->TopMenu)) + { + /* If already displaying a popup, try to display sub-popup */ + + hmenutmp = Mt->CurrentMenu; + if (MenuGetRosMenuInfo(&CurrentMenuInfo, Mt->CurrentMenu)) + { + Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &CurrentMenuInfo, TRUE, Flags); + } + + /* if subpopup was displayed then we are done */ + if (hmenutmp != Mt->CurrentMenu) return; + } + + if (! MenuGetRosMenuInfo(&CurrentMenuInfo, Mt->CurrentMenu)) + { + return; + } + + /* Check to see if there's another column */ + if (NO_SELECTED_ITEM != (NextCol = MenuGetStartOfNextColumn(&CurrentMenuInfo))) + { + TRACE("Going to %d.\n", NextCol); + if (MenuGetRosMenuInfo(&MenuInfo, Mt->CurrentMenu)) + { + MenuSelectItem(Mt->OwnerWnd, &MenuInfo, NextCol, TRUE, 0); + } + return; + } + + if (0 == (MenuInfo.Flags & MF_POPUP)) /* menu bar tracking */ + { + if (Mt->CurrentMenu != Mt->TopMenu) + { + MenuHideSubPopups(Mt->OwnerWnd, &MenuInfo, FALSE, Flags); + hmenutmp = Mt->CurrentMenu = Mt->TopMenu; + } + else + { + hmenutmp = NULL; + } + + /* try to move to the next item */ + if ( !MenuDoNextMenu(Mt, VK_RIGHT, Flags)) + MenuMoveSelection(Mt->OwnerWnd, &MenuInfo, ITEM_NEXT); + + if ( hmenutmp || Mt->TrackFlags & TF_SUSPENDPOPUP ) + { + if (! MenuSuspendPopup(Mt, WM_KEYDOWN) + && MenuGetRosMenuInfo(&MenuInfo, Mt->TopMenu)) + { + Mt->CurrentMenu = MenuShowSubPopup(Mt->OwnerWnd, &MenuInfo, + TRUE, Flags); + } + } + } +} + +/*********************************************************************** + * MenuTrackMenu + * + * Menu tracking code. + */ +static INT FASTCALL MenuTrackMenu(HMENU hmenu, UINT wFlags, INT x, INT y, + HWND hwnd, const RECT *lprect ) +{ + MSG msg; + ROSMENUINFO MenuInfo; + ROSMENUITEMINFO ItemInfo; + BOOL fRemove; + INT executedMenuId = -1; + MTRACKER mt; + BOOL enterIdleSent = FALSE; + + mt.TrackFlags = 0; + mt.CurrentMenu = hmenu; + mt.TopMenu = hmenu; + mt.OwnerWnd = hwnd; + mt.Pt.x = x; + mt.Pt.y = y; + + TRACE("hmenu=%p flags=0x%08x (%d,%d) hwnd=%x (%ld,%ld)-(%ld,%ld)\n", + hmenu, wFlags, x, y, hwnd, lprect ? lprect->left : 0, lprect ? lprect->top : 0, + lprect ? lprect->right : 0, lprect ? lprect->bottom : 0); + + if (!IsMenu(hmenu)) + { + WARN("Invalid menu handle %p\n", hmenu); + SetLastError( ERROR_INVALID_MENU_HANDLE ); + return FALSE; + } + + fEndMenu = FALSE; + if (! MenuGetRosMenuInfo(&MenuInfo, hmenu)) + { + return FALSE; + } + + if (wFlags & TPM_BUTTONDOWN) + { + /* Get the result in order to start the tracking or not */ + fRemove = MenuButtonDown( &mt, hmenu, wFlags ); + fEndMenu = !fRemove; + } + + SetCapture(mt.OwnerWnd); + (void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, mt.OwnerWnd); + + FIXME("MenuTrackMenu 1\n"); + while (! fEndMenu) + { + PVOID menu = ValidateHandle(mt.CurrentMenu, VALIDATE_TYPE_MENU); + if (!menu) /* sometimes happens if I do a window manager close */ + break; + + /* we have to keep the message in the queue until it's + * clear that menu loop is not over yet. */ + + for (;;) + { + if (PeekMessageW( &msg, 0, 0, 0, PM_NOREMOVE )) + { + if (!CallMsgFilterW( &msg, MSGF_MENU )) break; + /* remove the message from the queue */ + PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE ); + } + else + { + if (!enterIdleSent) + { + HWND win = MenuInfo.Flags & MF_POPUP ? MenuInfo.Wnd : NULL; + enterIdleSent = TRUE; + SendMessageW( mt.OwnerWnd, WM_ENTERIDLE, MSGF_MENU, (LPARAM) win); + } + WaitMessage(); + } + //FIXME("MenuTrackMenu loop 1\n"); + } + + /* check if EndMenu() tried to cancel us, by posting this message */ + if (msg.message == WM_CANCELMODE) + { + /* we are now out of the loop */ + fEndMenu = TRUE; + + /* remove the message from the queue */ + PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE ); + + /* break out of internal loop, ala ESCAPE */ + break; + } + + TranslateMessage( &msg ); + mt.Pt = msg.pt; + + if ( (msg.hwnd == MenuInfo.Wnd) || (msg.message!=WM_TIMER) ) + enterIdleSent=FALSE; + + fRemove = FALSE; + if ((msg.message >= WM_MOUSEFIRST) && (msg.message <= WM_MOUSELAST)) + { + /* + * Use the mouse coordinates in lParam instead of those in the MSG + * struct to properly handle synthetic messages. They are already + * in screen coordinates. + */ + mt.Pt.x = (short)LOWORD(msg.lParam); + mt.Pt.y = (short)HIWORD(msg.lParam); + + /* Find a menu for this mouse event */ + hmenu = MenuPtMenu(mt.TopMenu, mt.Pt); + + switch(msg.message) + { + /* no WM_NC... messages in captured state */ + + case WM_RBUTTONDBLCLK: + case WM_RBUTTONDOWN: + if (!(wFlags & TPM_RIGHTBUTTON)) break; + /* fall through */ + case WM_LBUTTONDBLCLK: + case WM_LBUTTONDOWN: + /* If the message belongs to the menu, removes it from the queue */ + /* Else, end menu tracking */ + fRemove = MenuButtonDown(&mt, hmenu, wFlags); + fEndMenu = !fRemove; + break; + + case WM_RBUTTONUP: + if (!(wFlags & TPM_RIGHTBUTTON)) break; + /* fall through */ + case WM_LBUTTONUP: + /* Check if a menu was selected by the mouse */ + if (hmenu) + { + executedMenuId = MenuButtonUp( &mt, hmenu, wFlags); + TRACE("executedMenuId %d\n", executedMenuId); + + /* End the loop if executedMenuId is an item ID */ + /* or if the job was done (executedMenuId = 0). */ + fEndMenu = fRemove = (executedMenuId != -1); + } + /* No menu was selected by the mouse */ + /* if the function was called by TrackPopupMenu, continue + with the menu tracking. If not, stop it */ + else + fEndMenu = ((wFlags & TPM_POPUPMENU) ? FALSE : TRUE); + + break; + + case WM_MOUSEMOVE: + /* the selected menu item must be changed every time */ + /* the mouse moves. */ + + if (hmenu) + fEndMenu |= !MenuMouseMove( &mt, hmenu, wFlags ); + + } /* switch(msg.message) - mouse */ + } + else if ((msg.message >= WM_KEYFIRST) && (msg.message <= WM_KEYLAST)) + { + fRemove = TRUE; /* Keyboard messages are always removed */ + switch(msg.message) + { + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + switch(msg.wParam) + { + case VK_MENU: + case VK_F10: + fEndMenu = TRUE; + break; + + case VK_HOME: + case VK_END: + if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu)) + { + MenuSelectItem(mt.OwnerWnd, &MenuInfo, + NO_SELECTED_ITEM, FALSE, 0 ); + MenuMoveSelection(mt.OwnerWnd, &MenuInfo, + VK_HOME == msg.wParam ? ITEM_NEXT : ITEM_PREV); + } + break; + + case VK_UP: + case VK_DOWN: /* If on menu bar, pull-down the menu */ + if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu)) + { + if (!(MenuInfo.Flags & MF_POPUP)) + { + if (MenuGetRosMenuInfo(&MenuInfo, mt.TopMenu)) + mt.CurrentMenu = MenuShowSubPopup(mt.OwnerWnd, &MenuInfo, TRUE, wFlags); + } + else /* otherwise try to move selection */ + MenuMoveSelection(mt.OwnerWnd, &MenuInfo, + (msg.wParam == VK_UP)? ITEM_PREV : ITEM_NEXT ); + } + break; + + case VK_LEFT: + MenuKeyLeft( &mt, wFlags ); + break; + + case VK_RIGHT: + MenuKeyRight( &mt, wFlags ); + break; + + case VK_ESCAPE: + fEndMenu = MenuKeyEscape(&mt, wFlags); + break; + + case VK_F1: + { + HELPINFO hi; + hi.cbSize = sizeof(HELPINFO); + hi.iContextType = HELPINFO_MENUITEM; + if (MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu)) + { + if (MenuInfo.FocusedItem == NO_SELECTED_ITEM) + hi.iCtrlId = 0; + else + { + MenuInitRosMenuItemInfo(&ItemInfo); + if (MenuGetRosMenuItemInfo(MenuInfo.Self, + MenuInfo.FocusedItem, + &ItemInfo)) + { + hi.iCtrlId = ItemInfo.wID; + } + else + { + hi.iCtrlId = 0; + } + MenuCleanupRosMenuItemInfo(&ItemInfo); + } + } + hi.hItemHandle = hmenu; + hi.dwContextId = MenuInfo.dwContextHelpID; + hi.MousePos = msg.pt; + SendMessageW(hwnd, WM_HELP, 0, (LPARAM)&hi); + break; + } + + default: + break; + } + break; /* WM_KEYDOWN */ + + case WM_CHAR: + case WM_SYSCHAR: + { + UINT pos; + + if (! MenuGetRosMenuInfo(&MenuInfo, mt.CurrentMenu)) break; + if (msg.wParam == L'\r' || msg.wParam == L' ') + { + executedMenuId = MenuExecFocusedItem(&mt, &MenuInfo, wFlags); + fEndMenu = (executedMenuId != -2); + break; + } + + /* Hack to avoid control chars. */ + /* We will find a better way real soon... */ + if (msg.wParam < 32) break; + + pos = MenuFindItemByKey(mt.OwnerWnd, &MenuInfo, + LOWORD(msg.wParam), FALSE); + if (pos == (UINT)-2) fEndMenu = TRUE; + else if (pos == (UINT)-1) MessageBeep(0); + else + { + MenuSelectItem(mt.OwnerWnd, &MenuInfo, pos, + TRUE, 0); + executedMenuId = MenuExecFocusedItem(&mt, &MenuInfo, wFlags); + fEndMenu = (executedMenuId != -2); + } + } + break; + } /* switch(msg.message) - kbd */ + } + else + { + PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE ); + DispatchMessageW( &msg ); + //FIXME("MenuTrackMenu loop 2\n"); + continue; + } + + if (!fEndMenu) fRemove = TRUE; + + /* finally remove message from the queue */ + + if (fRemove && !(mt.TrackFlags & TF_SKIPREMOVE) ) + PeekMessageW( &msg, 0, msg.message, msg.message, PM_REMOVE ); + else mt.TrackFlags &= ~TF_SKIPREMOVE; + //FIXME("MenuTrackMenu loop 3\n"); + } + FIXME("MenuTrackMenu 2\n"); + + (void)NtUserSetGUIThreadHandle(MSQ_STATE_MENUOWNER, NULL); + SetCapture(NULL); /* release the capture */ + + /* If dropdown is still painted and the close box is clicked on + then the menu will be destroyed as part of the DispatchMessage above. + This will then invalidate the menu handle in mt.hTopMenu. We should + check for this first. */ + if( IsMenu( mt.TopMenu ) ) + { + if (IsWindow(mt.OwnerWnd)) + { + if (MenuGetRosMenuInfo(&MenuInfo, mt.TopMenu)) + { + MenuHideSubPopups(mt.OwnerWnd, &MenuInfo, FALSE, wFlags); + + if (MenuInfo.Flags & MF_POPUP) + { + IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPEND, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0); + DestroyWindow(MenuInfo.Wnd); + MenuInfo.Wnd = NULL; + + if (!(MenuInfo.Flags & TPM_NONOTIFY)) + SendMessageW( mt.OwnerWnd, WM_UNINITMENUPOPUP, (WPARAM)mt.TopMenu, + MAKELPARAM(0, IS_SYSTEM_MENU(&MenuInfo)) ); + + } + MenuSelectItem( mt.OwnerWnd, &MenuInfo, NO_SELECTED_ITEM, FALSE, 0 ); + } + + SendMessageW( mt.OwnerWnd, WM_MENUSELECT, MAKEWPARAM(0, 0xffff), 0 ); + } + + /* Reset the variable for hiding menu */ + if (MenuGetRosMenuInfo(&MenuInfo, mt.TopMenu)) + { + MenuInfo.TimeToHide = FALSE; + MenuSetRosMenuInfo(&MenuInfo); + } + } + + /* The return value is only used by TrackPopupMenu */ + if (!(wFlags & TPM_RETURNCMD)) return TRUE; + if (executedMenuId == -1) executedMenuId = 0; + return executedMenuId; +} + +/*********************************************************************** + * MenuInitTracking + */ +static BOOL FASTCALL MenuInitTracking(HWND hWnd, HMENU hMenu, BOOL bPopup, UINT wFlags) +{ + ROSMENUINFO MenuInfo; + + TRACE("hwnd=%p hmenu=%p\n", hWnd, hMenu); + + HideCaret(0); + + MenuGetRosMenuInfo(&MenuInfo, hMenu); + /* This makes the menus of applications built with Delphi work. + * It also enables menus to be displayed in more than one window, + * but there are some bugs left that need to be fixed in this case. + */ + if(MenuInfo.Self == hMenu) + { + MenuInfo.Wnd = hWnd; + MenuSetRosMenuInfo(&MenuInfo); + } + + /* Send WM_ENTERMENULOOP and WM_INITMENU message only if TPM_NONOTIFY flag is not specified */ + if (!(wFlags & TPM_NONOTIFY)) + SendMessageW( hWnd, WM_ENTERMENULOOP, bPopup, 0 ); + + SendMessageW( hWnd, WM_SETCURSOR, (WPARAM)hWnd, HTCAPTION ); + + if (!(wFlags & TPM_NONOTIFY)) + { + SendMessageW( hWnd, WM_INITMENU, (WPARAM)hMenu, 0 ); + /* If an app changed/recreated menu bar entries in WM_INITMENU + * menu sizes will be recalculated once the menu created/shown. + */ + + if (!MenuInfo.Height) + { + /* app changed/recreated menu bar entries in WM_INITMENU + Recalculate menu sizes else clicks will not work */ + SetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | + SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED ); + + } + } + + IntNotifyWinEvent( EVENT_SYSTEM_MENUSTART, + hWnd, + MenuInfo.Flags & MF_SYSMENU ? OBJID_SYSMENU : OBJID_MENU, + CHILDID_SELF, 0); + return TRUE; +} +/*********************************************************************** + * MenuExitTracking + */ +static BOOL FASTCALL MenuExitTracking(HWND hWnd, BOOL bPopup) +{ + TRACE("hwnd=%p\n", hWnd); + + IntNotifyWinEvent( EVENT_SYSTEM_MENUEND, hWnd, OBJID_WINDOW, CHILDID_SELF, 0); + SendMessageW( hWnd, WM_EXITMENULOOP, bPopup, 0 ); + ShowCaret(0); + top_popup = 0; + top_popup_hmenu = NULL; + return TRUE; +} + +/*********************************************************************** + * MenuTrackMouseMenuBar + * + * Menu-bar tracking upon a mouse event. Called from NC_HandleSysCommand(). + */ +VOID MenuTrackMouseMenuBar( HWND hWnd, ULONG ht, POINT pt) +{ + HMENU hMenu = (ht == HTSYSMENU) ? NtUserGetSystemMenu( hWnd, FALSE) : GetMenu(hWnd); + UINT wFlags = TPM_BUTTONDOWN | TPM_LEFTALIGN | TPM_LEFTBUTTON; + + TRACE("wnd=%p ht=0x%04x (%ld,%ld)\n", hWnd, ht, pt.x, pt.y); + + if (IsMenu(hMenu)) + { + /* map point to parent client coordinates */ + HWND Parent = GetAncestor(hWnd, GA_PARENT ); + if (Parent != GetDesktopWindow()) + { + ScreenToClient(Parent, &pt); + } + + MenuInitTracking(hWnd, hMenu, FALSE, wFlags); + MenuTrackMenu(hMenu, wFlags, pt.x, pt.y, hWnd, NULL); + MenuExitTracking(hWnd, FALSE); + } +} + + +/*********************************************************************** + * MenuTrackKbdMenuBar + * + * Menu-bar tracking upon a keyboard event. Called from NC_HandleSysCommand(). + */ +VOID MenuTrackKbdMenuBar(HWND hwnd, UINT wParam, WCHAR wChar) +{ + UINT uItem = NO_SELECTED_ITEM; + HMENU hTrackMenu; + ROSMENUINFO MenuInfo; + UINT wFlags = TPM_LEFTALIGN | TPM_LEFTBUTTON; + + TRACE("hwnd %p wParam 0x%04x wChar 0x%04x\n", hwnd, wParam, wChar); + + /* find window that has a menu */ + + while (!((GetWindowLongPtrW( hwnd, GWL_STYLE ) & + (WS_CHILD | WS_POPUP)) != WS_CHILD)) + if (!(hwnd = GetAncestor( hwnd, GA_PARENT ))) return; + + /* check if we have to track a system menu */ + + hTrackMenu = GetMenu( hwnd ); + if (!hTrackMenu || IsIconic(hwnd) || wChar == ' ' ) + { + if (!(GetWindowLongPtrW( hwnd, GWL_STYLE ) & WS_SYSMENU)) return; + hTrackMenu = NtUserGetSystemMenu(hwnd, FALSE); + uItem = 0; + wParam |= HTSYSMENU; /* prevent item lookup */ + } + + if (!IsMenu( hTrackMenu )) return; + + MenuInitTracking( hwnd, hTrackMenu, FALSE, wFlags ); + + if (! MenuGetRosMenuInfo(&MenuInfo, hTrackMenu)) + { + goto track_menu; + } + + if( wChar && wChar != ' ' ) + { + uItem = MenuFindItemByKey( hwnd, &MenuInfo, wChar, (wParam & HTSYSMENU) ); + if ( uItem >= (UINT)(-2) ) + { + if( uItem == (UINT)(-1) ) MessageBeep(0); + /* schedule end of menu tracking */ + wFlags |= TF_ENDMENU; + goto track_menu; + } + } + + MenuSelectItem( hwnd, &MenuInfo, uItem, TRUE, 0 ); + + if (wParam & HTSYSMENU) + { + /* prevent sysmenu activation for managed windows on Alt down/up */ +// if (GetPropA( hwnd, "__wine_x11_managed" )) + wFlags |= TF_ENDMENU; /* schedule end of menu tracking */ + } + else + { + if( uItem == NO_SELECTED_ITEM ) + MenuMoveSelection( hwnd, &MenuInfo, ITEM_NEXT ); + else + PostMessageW( hwnd, WM_KEYDOWN, VK_DOWN, 0L ); + } + +track_menu: + MenuTrackMenu( hTrackMenu, wFlags, 0, 0, hwnd, NULL ); + MenuExitTracking( hwnd, FALSE ); + +} + +/********************************************************************** + * TrackPopupMenuEx (USER32.@) + */ +BOOL WINAPI TrackPopupMenuEx( HMENU Menu, UINT Flags, int x, int y, + HWND Wnd, LPTPMPARAMS Tpm) +{ + BOOL ret = FALSE; + ROSMENUINFO MenuInfo; + + if (!IsMenu(Menu)) + { + SetLastError( ERROR_INVALID_MENU_HANDLE ); + return FALSE; + } + + MenuGetRosMenuInfo(&MenuInfo, Menu); + if (IsWindow(MenuInfo.Wnd)) + { + SetLastError( ERROR_POPUP_ALREADY_ACTIVE ); + return FALSE; + } + + MenuInitTracking(Wnd, Menu, TRUE, Flags); + + /* Send WM_INITMENUPOPUP message only if TPM_NONOTIFY flag is not specified */ + if (!(Flags & TPM_NONOTIFY)) + SendMessageW(Wnd, WM_INITMENUPOPUP, (WPARAM) Menu, 0); + + if (MenuShowPopup(Wnd, Menu, 0, Flags, x, y, 0, 0 )) + ret = MenuTrackMenu(Menu, Flags | TPM_POPUPMENU, 0, 0, Wnd, + Tpm ? &Tpm->rcExclude : NULL); + MenuExitTracking(Wnd, TRUE); + return ret; +} + +/********************************************************************** + * TrackPopupMenu (USER32.@) + */ +BOOL WINAPI TrackPopupMenu( HMENU Menu, UINT Flags, int x, int y, + int Reserved, HWND Wnd, CONST RECT *Rect) +{ + return TrackPopupMenuEx( Menu, Flags, x, y, Wnd, NULL); +} + +/* + * From MSDN: + * The MFT_BITMAP, MFT_SEPARATOR, and MFT_STRING values cannot be combined + * with one another. Also MFT_OWNERDRAW. Set fMask to MIIM_TYPE to use fType. + * + * Windows 2K/XP: fType is used only if fMask has a value of MIIM_FTYPE. + * + * MIIM_TYPE: Retrieves or sets the fType and dwTypeData members. Windows + * 2K/XP: MIIM_TYPE is replaced by MIIM_BITMAP, MIIM_FTYPE, and MIIM_STRING. + * MFT_STRING is replaced by MIIM_STRING. + * (So, I guess we should use MIIM_STRING only for strings?) + * + * MIIM_FTYPE: Windows 2K/Windows XP: Retrieves or sets the fType member. + * + * Based on wine, SetMenuItemInfo_common: + * 1) set MIIM_STRING | MIIM_FTYPE | MIIM_BITMAP any one with MIIM_TYPE, + * it will result in a error. + * 2) set menu mask to MIIM_FTYPE and MFT_BITMAP ftype it will result in a error. + * These conditions are addressed in Win32k IntSetMenuItemInfo. + * + */ +static +BOOL +FASTCALL +MenuSetItemData( + LPMENUITEMINFOW mii, + UINT Flags, + UINT_PTR IDNewItem, + LPCWSTR NewItem, + BOOL Unicode) +{ +/* + * Let us assume MIIM_FTYPE is set and building a new menu item structure. + */ + if(Flags & MF_BITMAP) + { + mii->fMask |= MIIM_BITMAP; /* Use the new way of seting hbmpItem.*/ + mii->hbmpItem = (HBITMAP) NewItem; + + if (Flags & MF_HELP) + { + /* increase ident */ + mii->fType |= MF_HELP; + } + } + else if(Flags & MF_OWNERDRAW) + { + mii->fType |= MFT_OWNERDRAW; + mii->fMask |= MIIM_DATA; + mii->dwItemData = (DWORD_PTR) NewItem; + } + else if (Flags & MF_SEPARATOR) + { + mii->fType |= MFT_SEPARATOR; + if (!(Flags & (MF_GRAYED|MF_DISABLED))) + Flags |= MF_GRAYED|MF_DISABLED; + } + else /* Default action MF_STRING. */ + { + /* Item beginning with a backspace is a help item */ + if (NewItem != NULL) + { + if (Unicode) + { + if (*NewItem == '\b') + { + mii->fType |= MF_HELP; + NewItem++; + } + } + else + { + LPCSTR NewItemA = (LPCSTR) NewItem; + if (*NewItemA == '\b') + { + mii->fType |= MF_HELP; + NewItemA++; + NewItem = (LPCWSTR) NewItemA; + } + } + + if (Flags & MF_HELP) + mii->fType |= MF_HELP; + mii->fMask |= MIIM_STRING; + mii->fType |= MFT_STRING; /* Zero */ + mii->dwTypeData = (LPWSTR)NewItem; + if (Unicode) + mii->cch = (NULL == NewItem ? 0 : strlenW(NewItem)); + else + mii->cch = (NULL == NewItem ? 0 : strlen((LPCSTR)NewItem)); + } + else + { + mii->fType |= MFT_SEPARATOR; + if (!(Flags & (MF_GRAYED|MF_DISABLED))) + Flags |= MF_GRAYED|MF_DISABLED; + } + } + + if(Flags & MF_RIGHTJUSTIFY) /* Same as MF_HELP */ + { + mii->fType |= MFT_RIGHTJUSTIFY; + } + + if(Flags & MF_MENUBREAK) + { + mii->fType |= MFT_MENUBREAK; + } + else if(Flags & MF_MENUBARBREAK) + { + mii->fType |= MFT_MENUBARBREAK; + } + + if(Flags & MF_GRAYED || Flags & MF_DISABLED) + { + if (Flags & MF_GRAYED) + mii->fState |= MF_GRAYED; + + if (Flags & MF_DISABLED) + mii->fState |= MF_DISABLED; + + mii->fMask |= MIIM_STATE; + } + else if (Flags & MF_HILITE) + { + mii->fState |= MF_HILITE; + mii->fMask |= MIIM_STATE; + } + else /* default state */ + { + mii->fState |= MFS_ENABLED; + mii->fMask |= MIIM_STATE; + } + + if(Flags & MF_POPUP) + { + mii->fType |= MF_POPUP; + mii->fMask |= MIIM_SUBMENU; + mii->hSubMenu = (HMENU)IDNewItem; + } + else + { + mii->fMask |= MIIM_ID; + mii->wID = (UINT)IDNewItem; + } + return TRUE; +} + +NTSTATUS WINAPI +User32CallLoadMenuFromKernel(PVOID Arguments, ULONG ArgumentLength) +{ + PLOADMENU_CALLBACK_ARGUMENTS Common; + LRESULT Result; + + Common = (PLOADMENU_CALLBACK_ARGUMENTS) Arguments; + + Result = (LRESULT)LoadMenuW( Common->hModule, + IS_INTRESOURCE(Common->MenuName[0]) ? + MAKEINTRESOURCE(Common->MenuName[0]) : + (LPCWSTR)&Common->MenuName); + + return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS); +} + + +/* FUNCTIONS *****************************************************************/ + +/*static BOOL +MenuIsStringItem(ULONG TypeData) +{ + return(MF_STRING == MENU_ITEM_TYPE(ItemInfo->fType)); +}*/ + + +/* + * @implemented + */ +BOOL WINAPI +AppendMenuA(HMENU hMenu, + UINT uFlags, + UINT_PTR uIDNewItem, + LPCSTR lpNewItem) +{ + return(InsertMenuA(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem, + lpNewItem)); +} + + +/* + * @implemented + */ +BOOL WINAPI +AppendMenuW(HMENU hMenu, + UINT uFlags, + UINT_PTR uIDNewItem, + LPCWSTR lpNewItem) +{ + return(InsertMenuW(hMenu, -1, uFlags | MF_BYPOSITION, uIDNewItem, + lpNewItem)); +} + + +/* + * @implemented + */ +DWORD WINAPI +CheckMenuItem(HMENU hmenu, + UINT uIDCheckItem, + UINT uCheck) +{ + return NtUserCheckMenuItem(hmenu, uIDCheckItem, uCheck); +} + +static +BOOL +MenuCheckMenuRadioItem(HMENU hMenu, UINT idFirst, UINT idLast, UINT idCheck, UINT uFlags, BOOL bCheck, PUINT pChecked, PUINT pUnchecked, PUINT pMenuChanged) +{ + UINT ItemCount, i; + PROSMENUITEMINFO Items = NULL; + UINT cChecked, cUnchecked; + BOOL bRet = TRUE; + //ROSMENUINFO mi; + + if(idFirst > idLast) + return FALSE; + + ItemCount = GetMenuItemCount(hMenu); + + //mi.cbSize = sizeof(ROSMENUINFO); + //if(!NtUserMenuInfo(hmenu, &mi, FALSE)) return ret; + + + if(MenuGetAllRosMenuItemInfo(hMenu, &Items) <= 0) + { + ERR("MenuGetAllRosMenuItemInfo failed\n"); + return FALSE; + } + + cChecked = cUnchecked = 0; + + for (i = 0 ; i < ItemCount; i++) + { + BOOL check = FALSE; + if (0 != (Items[i].fType & MF_MENUBARBREAK)) continue; + if (0 != (Items[i].fType & MF_SEPARATOR)) continue; + + if ((Items[i].fType & MF_POPUP) && (uFlags == MF_BYCOMMAND)) + { + MenuCheckMenuRadioItem(Items[i].hSubMenu, idFirst, idLast, idCheck, uFlags, bCheck, pChecked, pUnchecked, pMenuChanged); + continue; + } + if (uFlags & MF_BYPOSITION) + { + if (i < idFirst || i > idLast) + continue; + + if (i == idCheck) + { + cChecked++; + check = TRUE; + } + else + { + cUnchecked++; + } + } + else + { + if (Items[i].wID < idFirst || Items[i].wID > idLast) + continue; + + if (Items[i].wID == idCheck) + { + cChecked++; + check = TRUE; + } + else + { + cUnchecked++; + } + } + + if (!bCheck) + continue; + + Items[i].fMask = MIIM_STATE | MIIM_FTYPE; + if (check) + { + Items[i].fType |= MFT_RADIOCHECK; + Items[i].fState |= MFS_CHECKED; + } + else + { + Items[i].fState &= ~MFS_CHECKED; + } + + if(!MenuSetRosMenuItemInfo(hMenu, i ,&Items[i])) + { + ERR("MenuSetRosMenuItemInfo failed\n"); + bRet = FALSE; + break; + } + } + HeapFree(GetProcessHeap(), 0, Items); + + *pChecked += cChecked; + *pUnchecked += cUnchecked; + + if (cChecked || cUnchecked) + (*pMenuChanged)++; + + return bRet; +} + +/* + * @implemented + */ +BOOL WINAPI +CheckMenuRadioItem(HMENU hmenu, + UINT idFirst, + UINT idLast, + UINT idCheck, + UINT uFlags) +{ + UINT cChecked = 0; + UINT cUnchecked = 0; + UINT cMenuChanged = 0; + + if (!MenuCheckMenuRadioItem(hmenu, idFirst, idLast, idCheck, uFlags, FALSE, &cChecked, &cUnchecked, &cMenuChanged)) + return FALSE; + + if (cMenuChanged > 1) + return FALSE; + + cMenuChanged = 0; + cChecked = 0; + cUnchecked = 0; + + if (!MenuCheckMenuRadioItem(hmenu, idFirst, idLast, idCheck, uFlags, TRUE, &cChecked, &cUnchecked, &cMenuChanged)) + return FALSE; + + return (cChecked != 0); +} + + +/* + * @implemented + */ +HMENU WINAPI +CreateMenu(VOID) +{ + MenuLoadBitmaps(); + return (HMENU)NtUserCallNoParam(NOPARAM_ROUTINE_CREATEMENU); +} + + +/* + * @implemented + */ +HMENU WINAPI +CreatePopupMenu(VOID) +{ + MenuLoadBitmaps(); + return (HMENU)NtUserCallNoParam(NOPARAM_ROUTINE_CREATEMENUPOPUP); +} + + +/* + * @implemented + */ +BOOL WINAPI +DrawMenuBar(HWND hWnd) +{ +// return (BOOL)NtUserCallHwndLock(hWnd, HWNDLOCK_ROUTINE_DRAWMENUBAR); + ROSMENUINFO MenuInfo; + HMENU hMenu; + hMenu = GetMenu(hWnd); + if (!hMenu) + return FALSE; + MenuGetRosMenuInfo(&MenuInfo, hMenu); + MenuInfo.Height = 0; // make sure to recalc size + MenuSetRosMenuInfo(&MenuInfo); - /* The wine method doesn't work and I suspect it's more effort - then hackfix solution ++ + SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | + SWP_NOZORDER | SWP_FRAMECHANGED ); - return TRUE;*/ - // FIXME: hackfix - DefWndNCPaint(hWnd,(HRGN)-1,-1); + return TRUE; +} + +/* + * @implemented + */ +BOOL WINAPI +EnableMenuItem(HMENU hMenu, + UINT uIDEnableItem, + UINT uEnable) +{ + return NtUserEnableMenuItem(hMenu, uIDEnableItem, uEnable); +} + +/* + * @implemented + */ +BOOL WINAPI +EndMenu(VOID) +{ + GUITHREADINFO guii; + guii.cbSize = sizeof(GUITHREADINFO); + if(GetGUIThreadInfo(GetCurrentThreadId(), &guii) && guii.hwndMenuOwner) + { + if (!fEndMenu && + top_popup && + guii.hwndMenuOwner != top_popup ) + { + ERR("Capture GUI pti hWnd does not match top_popup!\n"); + } + } + + /* if we are in the menu code, and it is active */ + if (!fEndMenu && top_popup) + { + /* terminate the menu handling code */ + fEndMenu = TRUE; + + /* needs to be posted to wakeup the internal menu handler */ + /* which will now terminate the menu, in the event that */ + /* the main window was minimized, or lost focus, so we */ + /* don't end up with an orphaned menu */ + PostMessageW( top_popup, WM_CANCELMODE, 0, 0); + } + return TRUE; +} + + +/* + * @implemented + */ +HMENU WINAPI +GetMenu(HWND hWnd) +{ + PWND Wnd = ValidateHwnd(hWnd); + + if (!Wnd) + return NULL; + + return UlongToHandle(Wnd->IDMenu); +} + + +/* + * @implemented + */ +LONG WINAPI +GetMenuCheckMarkDimensions(VOID) +{ + return(MAKELONG(GetSystemMetrics(SM_CXMENUCHECK), + GetSystemMetrics(SM_CYMENUCHECK))); +} + + +/* + * @implemented + */ +UINT WINAPI +GetMenuDefaultItem(HMENU hMenu, + UINT fByPos, + UINT gmdiFlags) +{ + return NtUserGetMenuDefaultItem(hMenu, fByPos, gmdiFlags); +} + + +/* + * @implemented + */ +BOOL WINAPI +GetMenuInfo(HMENU hmenu, + LPMENUINFO lpcmi) +{ + ROSMENUINFO mi; + BOOL res = FALSE; + + if(!lpcmi || (lpcmi->cbSize != sizeof(MENUINFO))) + return FALSE; + + RtlZeroMemory(&mi, sizeof(MENUINFO)); + mi.cbSize = sizeof(MENUINFO); + mi.fMask = lpcmi->fMask; + + res = NtUserMenuInfo(hmenu, &mi, FALSE); + + memcpy(lpcmi, &mi, sizeof(MENUINFO)); + return res; +} + + +/* + * @implemented + */ +int WINAPI +GetMenuItemCount(HMENU Menu) +{ + ROSMENUINFO MenuInfo; + + return MenuGetRosMenuInfo(&MenuInfo, Menu) ? MenuInfo.MenuItemCount : 0; +} + + +/* + * @implemented + */ +UINT WINAPI +GetMenuItemID(HMENU hMenu, + int nPos) +{ + ROSMENUITEMINFO mii; + + mii.cbSize = sizeof(MENUITEMINFOW); + mii.fMask = MIIM_ID | MIIM_SUBMENU; + + if (! NtUserMenuItemInfo(hMenu, nPos, MF_BYPOSITION, &mii, FALSE)) + { + return -1; + } + + if (NULL != mii.hSubMenu) + { + return -1; + } + if (0 == mii.wID) + { + return -1; + } + + return mii.wID; +} + + +/* + * @implemented + */ +BOOL WINAPI +GetMenuItemInfoA( + HMENU Menu, + UINT Item, + BOOL ByPosition, + LPMENUITEMINFOA mii) +{ + MENUITEMINFOW miiW; + LPSTR AnsiBuffer; + INT Count; + + if (mii->cbSize != sizeof(MENUITEMINFOA) && + mii->cbSize != sizeof(MENUITEMINFOA) - sizeof(HBITMAP)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if(!(mii->fMask & (MIIM_TYPE | MIIM_STRING))) + { + /* No text requested, just pass on */ + return NtUserMenuItemInfo(Menu, Item, ByPosition, (PROSMENUITEMINFO) mii, FALSE); + } + + AnsiBuffer = mii->dwTypeData; + Count = miiW.cch = mii->cch; + RtlCopyMemory(&miiW, mii, mii->cbSize); + miiW.dwTypeData = 0; + + if (AnsiBuffer) + { + miiW.dwTypeData = RtlAllocateHeap(GetProcessHeap(), 0, + miiW.cch * sizeof(WCHAR)); + if (miiW.dwTypeData == NULL) return FALSE; + miiW.dwTypeData[0] = 0; + } + + if (!NtUserMenuItemInfo(Menu, Item, ByPosition, (PROSMENUITEMINFO)&miiW, FALSE)) + { + if (miiW.dwTypeData) RtlFreeHeap(GetProcessHeap(), 0, miiW.dwTypeData); + return FALSE; + } + + RtlCopyMemory(mii, &miiW, miiW.cbSize); + + if (!AnsiBuffer || !Count) + { + if (miiW.dwTypeData) RtlFreeHeap(GetProcessHeap(), 0, miiW.dwTypeData); + mii->dwTypeData = AnsiBuffer; + mii->cch = miiW.cch; + return TRUE; + } + + if ((miiW.fMask & MIIM_STRING) || (IS_STRING_ITEM(miiW.fType))) + { + if (miiW.cch) + { + if (!WideCharToMultiByte(CP_ACP, 0, miiW.dwTypeData, miiW.cch, AnsiBuffer, mii->cch, NULL, NULL)) + { + AnsiBuffer[0] = 0; + } + if (Count > miiW.cch) + { + AnsiBuffer[miiW.cch] = 0; + } + mii->cch = mii->cch; + } + } + else + { + AnsiBuffer[0] = 0; + } + + RtlFreeHeap(GetProcessHeap(), 0, miiW.dwTypeData); + mii->dwTypeData = AnsiBuffer; + + return TRUE; +} + + +/* + * @implemented + */ +BOOL WINAPI +GetMenuItemInfoW( + HMENU Menu, + UINT Item, + BOOL ByPosition, + LPMENUITEMINFOW mii) +{ + MENUITEMINFOW miiW; + LPWSTR String; + INT Count; + + if (mii->cbSize != sizeof(MENUITEMINFOW) && + mii->cbSize != sizeof(MENUITEMINFOW) - sizeof(HBITMAP)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if(!(mii->fMask & (MIIM_TYPE | MIIM_STRING))) + { + /* No text requested, just pass on */ + return NtUserMenuItemInfo(Menu, Item, ByPosition, (PROSMENUITEMINFO) mii, FALSE); + } + + String = mii->dwTypeData; + Count = mii->cch; + RtlCopyMemory(&miiW, mii, mii->cbSize); + miiW.dwTypeData = 0; + + if (String) + { + miiW.dwTypeData = RtlAllocateHeap(GetProcessHeap(), 0, + miiW.cch * sizeof(WCHAR)); + if (miiW.dwTypeData == NULL) return FALSE; + miiW.dwTypeData[0] = 0; + } + + if (!NtUserMenuItemInfo(Menu, Item, ByPosition, (PROSMENUITEMINFO) &miiW, FALSE)) + { + if (miiW.dwTypeData) RtlFreeHeap(GetProcessHeap(), 0, miiW.dwTypeData); + return FALSE; + } + + RtlCopyMemory(mii, &miiW, miiW.cbSize); // Okay to over write user data. + + if (!String || !Count) + { + if (miiW.dwTypeData) RtlFreeHeap(GetProcessHeap(), 0, miiW.dwTypeData); + mii->dwTypeData = String; // may not be zero. + mii->cch = miiW.cch; + return TRUE; + } + + if ((miiW.fMask & MIIM_STRING) || (IS_STRING_ITEM(miiW.fType))) + { + lstrcpynW( String, miiW.dwTypeData, Count ); + } + + RtlFreeHeap(GetProcessHeap(), 0, miiW.dwTypeData); + mii->dwTypeData = String; + mii->cch = strlenW(String); + return TRUE; +} + + +/* + * @implemented + */ +UINT +WINAPI +GetMenuState( + HMENU hMenu, + UINT uId, + UINT uFlags) +{ + ROSMENUINFO MenuInfo; + ROSMENUITEMINFO mii; + memset( &mii, 0, sizeof(mii) ); + mii.cbSize = sizeof(MENUITEMINFOW); + mii.fMask = MIIM_STATE | MIIM_FTYPE | MIIM_SUBMENU; + + SetLastError(0); + if(NtUserMenuItemInfo(hMenu, uId, uFlags, &mii, FALSE)) + { + UINT nSubItems = 0; + if(mii.hSubMenu) + { + if (! MenuGetRosMenuInfo(&MenuInfo, mii.hSubMenu)) + { + return (UINT) -1; + } + nSubItems = MenuInfo.MenuItemCount; + + /* FIXME - ported from wine, does that work (0xff)? */ + if(GetLastError() != ERROR_INVALID_MENU_HANDLE) + return (nSubItems << 8) | ((mii.fState | mii.fType) & 0xff); + + return (UINT)-1; /* Invalid submenu */ + } + + /* FIXME - ported from wine, does that work? */ + return (mii.fType | mii.fState); + } + + return (UINT)-1; +} + + +/* + * @implemented + */ +int +WINAPI +GetMenuStringA( + HMENU hMenu, + UINT uIDItem, + LPSTR lpString, + int nMaxCount, + UINT uFlag) +{ + MENUITEMINFOA mii; + memset( &mii, 0, sizeof(mii) ); + mii.dwTypeData = lpString; + mii.fMask = MIIM_STRING | MIIM_FTYPE; + mii.fType = MFT_STRING; + mii.cbSize = sizeof(MENUITEMINFOA); + mii.cch = nMaxCount; + + if(!(GetMenuItemInfoA( hMenu, uIDItem, (BOOL)(MF_BYPOSITION & uFlag),&mii))) + return 0; + else + return mii.cch; +} + + +/* + * @implemented + */ +int +WINAPI +GetMenuStringW( + HMENU hMenu, + UINT uIDItem, + LPWSTR lpString, + int nMaxCount, + UINT uFlag) +{ + MENUITEMINFOW miiW; + memset( &miiW, 0, sizeof(miiW) ); + miiW.dwTypeData = lpString; + miiW.fMask = MIIM_STRING | MIIM_FTYPE; + miiW.fType = MFT_STRING; + miiW.cbSize = sizeof(MENUITEMINFOW); + miiW.cch = nMaxCount; + + if(!(GetMenuItemInfoW( hMenu, uIDItem, (BOOL)(MF_BYPOSITION & uFlag),&miiW))) + return 0; + else + return miiW.cch; +} + + +/* + * @implemented + */ +HMENU +WINAPI +GetSubMenu( + HMENU hMenu, + int nPos) +{ + ROSMENUITEMINFO mi; + + mi.cbSize = sizeof(MENUITEMINFOW); + mi.fMask = MIIM_SUBMENU; + + if (NtUserMenuItemInfo(hMenu, (UINT)nPos, MF_BYPOSITION, &mi, FALSE)) + { + return IsMenu(mi.hSubMenu) ? mi.hSubMenu : NULL; + } + + return NULL; +} + +/* + * @implemented + */ +HMENU +WINAPI +GetSystemMenu( + HWND hWnd, + BOOL bRevert) +{ + HMENU TopMenu; + + TopMenu = NtUserGetSystemMenu(hWnd, bRevert); + + return NULL == TopMenu ? NULL : GetSubMenu(TopMenu, 0); +} + + +/* + * @implemented + */ +BOOL +WINAPI +InsertMenuA( + HMENU hMenu, + UINT uPosition, + UINT uFlags, + UINT_PTR uIDNewItem, + LPCSTR lpNewItem) +{ + MENUITEMINFOA mii; + memset( &mii, 0, sizeof(mii) ); + mii.cbSize = sizeof(MENUITEMINFOA); + mii.fMask = MIIM_FTYPE; + + MenuSetItemData((LPMENUITEMINFOW) &mii, + uFlags, + uIDNewItem, + (LPCWSTR) lpNewItem, + FALSE); + + return InsertMenuItemA(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii); +} + + + +/* + * @implemented + */ +BOOL +WINAPI +InsertMenuItemA( + HMENU hMenu, + UINT uItem, + BOOL fByPosition, + LPCMENUITEMINFOA lpmii) +{ + MENUITEMINFOW mi; + UNICODE_STRING MenuText; + BOOL res = FALSE; + BOOL CleanHeap = FALSE; + NTSTATUS Status; + + if((lpmii->cbSize == sizeof(MENUITEMINFOA)) || + (lpmii->cbSize == sizeof(MENUITEMINFOA) - sizeof(HBITMAP))) + { + RtlCopyMemory ( &mi, lpmii, lpmii->cbSize ); + + if( lpmii->cbSize != sizeof( MENUITEMINFOW)) + { + mi.cbSize = sizeof( MENUITEMINFOW); + mi.hbmpItem = NULL; + } + /* copy the text string */ + if (((mi.fMask & MIIM_STRING) || + ((mi.fMask & MIIM_TYPE) && (MENU_ITEM_TYPE(mi.fType) == MF_STRING))) + && mi.dwTypeData != NULL) + { + Status = RtlCreateUnicodeStringFromAsciiz(&MenuText, (LPSTR)mi.dwTypeData); + if (!NT_SUCCESS (Status)) + { + SetLastError (RtlNtStatusToDosError(Status)); + return FALSE; + } + mi.dwTypeData = MenuText.Buffer; + mi.cch = MenuText.Length / sizeof(WCHAR); + CleanHeap = TRUE; + } + res = NtUserThunkedMenuItemInfo(hMenu, uItem, fByPosition, TRUE, &mi, NULL); + + if ( CleanHeap ) RtlFreeUnicodeString ( &MenuText ); + } + return res; +} + + +/* + * @implemented + */ +BOOL +WINAPI +InsertMenuItemW( + HMENU hMenu, + UINT uItem, + BOOL fByPosition, + LPCMENUITEMINFOW lpmii) +{ + MENUITEMINFOW mi; + UNICODE_STRING MenuText; + BOOL res = FALSE; + + /* while we could just pass 'lpmii' to win32k, we make a copy so that + if a bad user passes bad data, we crash his process instead of the + entire kernel */ + + if((lpmii->cbSize == sizeof(MENUITEMINFOW)) || + (lpmii->cbSize == sizeof(MENUITEMINFOW) - sizeof(HBITMAP))) + { + RtlCopyMemory(&mi, lpmii, lpmii->cbSize); + + if( lpmii->cbSize != sizeof( MENUITEMINFOW)) + { + mi.cbSize = sizeof( MENUITEMINFOW); + mi.hbmpItem = NULL; + } + /* copy the text string */ + if (((mi.fMask & MIIM_STRING) || + ((mi.fMask & MIIM_TYPE) && (MENU_ITEM_TYPE(mi.fType) == MF_STRING))) + && mi.dwTypeData != NULL) + { + RtlInitUnicodeString(&MenuText, (PWSTR)lpmii->dwTypeData); + mi.dwTypeData = MenuText.Buffer; + mi.cch = MenuText.Length / sizeof(WCHAR); + } + res = NtUserThunkedMenuItemInfo(hMenu, uItem, fByPosition, TRUE, &mi, NULL); + } + return res; +} + + +/* + * @implemented + */ +BOOL +WINAPI +InsertMenuW( + HMENU hMenu, + UINT uPosition, + UINT uFlags, + UINT_PTR uIDNewItem, + LPCWSTR lpNewItem) +{ + MENUITEMINFOW mii; + memset( &mii, 0, sizeof(mii) ); + mii.cbSize = sizeof(MENUITEMINFOW); + mii.fMask = MIIM_FTYPE; + + MenuSetItemData( &mii, + uFlags, + uIDNewItem, + lpNewItem, + TRUE); + + return InsertMenuItemW(hMenu, uPosition, (BOOL)((MF_BYPOSITION & uFlags) > 0), &mii); +} + + +/* + * @implemented + */ +BOOL +WINAPI +IsMenu( + HMENU Menu) +{ + if (ValidateHandle(Menu, VALIDATE_TYPE_MENU)) return TRUE; + return FALSE; +} + + +/* + * @implemented + */ +HMENU WINAPI +LoadMenuA(HINSTANCE hInstance, + LPCSTR lpMenuName) +{ + HANDLE Resource = FindResourceA(hInstance, lpMenuName, MAKEINTRESOURCEA(4)); + if (Resource == NULL) + { + return(NULL); + } + return(LoadMenuIndirectA((PVOID)LoadResource(hInstance, Resource))); +} + + +/* + * @implemented + */ +HMENU WINAPI +LoadMenuIndirectA(CONST MENUTEMPLATE *lpMenuTemplate) +{ + return(LoadMenuIndirectW(lpMenuTemplate)); +} + + +/* + * @implemented + */ +HMENU WINAPI +LoadMenuIndirectW(CONST MENUTEMPLATE *lpMenuTemplate) +{ + HMENU hMenu; + WORD version, offset; + LPCSTR p = (LPCSTR)lpMenuTemplate; + + version = GET_WORD(p); + p += sizeof(WORD); + + switch (version) + { + case 0: /* standard format is version of 0 */ + offset = GET_WORD(p); + p += sizeof(WORD) + offset; + if (!(hMenu = CreateMenu())) return 0; + if (!MENU_ParseResource(p, hMenu, TRUE)) + { + DestroyMenu(hMenu); + return 0; + } + return hMenu; + case 1: /* extended format is version of 1 */ + offset = GET_WORD(p); + p += sizeof(WORD) + offset; + if (!(hMenu = CreateMenu())) return 0; + if (!MENUEX_ParseResource(p, hMenu)) + { + DestroyMenu( hMenu ); + return 0; + } + return hMenu; + default: + DbgPrint("LoadMenuIndirectW(): version %d not supported.\n", version); + return 0; + } +} + + +/* + * @implemented + */ +HMENU WINAPI +LoadMenuW(HINSTANCE hInstance, + LPCWSTR lpMenuName) +{ + HANDLE Resource = FindResourceW(hInstance, lpMenuName, RT_MENU); + if (Resource == NULL) + { + return(NULL); + } + return(LoadMenuIndirectW((PVOID)LoadResource(hInstance, Resource))); +} + + +/* + * @implemented + */ +int +WINAPI +MenuItemFromPoint( + HWND hWnd, + HMENU hMenu, + POINT ptScreen) +{ + return NtUserMenuItemFromPoint(hWnd, hMenu, ptScreen.x, ptScreen.y); +} + + +/* + * @implemented + */ +BOOL +WINAPI +ModifyMenuA( + HMENU hMnu, + UINT uPosition, + UINT uFlags, + UINT_PTR uIDNewItem, + LPCSTR lpNewItem) +{ + ROSMENUINFO mi; + ROSMENUITEMINFO rmii; + MENUITEMINFOA mii; + memset( &mii, 0, sizeof(mii) ); + mii.cbSize = sizeof(MENUITEMINFOA); + mii.fMask = MIIM_FTYPE; + + if (!MenuGetRosMenuInfo( &mi, hMnu )) return FALSE; + + mi.Height = 0; + + if (!MenuSetRosMenuInfo( &mi )) return FALSE; + + MenuInitRosMenuItemInfo( &rmii ); + + if(!MenuGetRosMenuItemInfo( hMnu, uPosition, &rmii)) return FALSE; + + if ((rmii.fType & MF_POPUP) && (uFlags & MF_POPUP) && (rmii.hSubMenu != (HMENU)uIDNewItem)) + NtUserDestroyMenu( rmii.hSubMenu ); /* ModifyMenu() spec */ + + MenuCleanupRosMenuItemInfo( &rmii ); + + MenuSetItemData((LPMENUITEMINFOW) &mii, + uFlags, + uIDNewItem, + (LPCWSTR) lpNewItem, + FALSE); + + return SetMenuItemInfoA( hMnu, + uPosition, + (BOOL)(MF_BYPOSITION & uFlags), + &mii); +} + + +/* + * @implemented + */ +BOOL +WINAPI +ModifyMenuW( + HMENU hMnu, + UINT uPosition, + UINT uFlags, + UINT_PTR uIDNewItem, + LPCWSTR lpNewItem) +{ + ROSMENUINFO mi; + ROSMENUITEMINFO rmii; + MENUITEMINFOW mii; + memset ( &mii, 0, sizeof(mii) ); + mii.cbSize = sizeof(MENUITEMINFOW); + mii.fMask = MIIM_FTYPE; + + if (!MenuGetRosMenuInfo( &mi, hMnu )) return FALSE; + + mi.Height = 0; // Force size recalculation. + + if (!MenuSetRosMenuInfo( &mi )) return FALSE; + + MenuInitRosMenuItemInfo( &rmii ); + + if(!MenuGetRosMenuItemInfo( hMnu, uPosition, &rmii)) return FALSE; + + if ((rmii.fType & MF_POPUP) && (uFlags & MF_POPUP) && (rmii.hSubMenu != (HMENU)uIDNewItem)) + NtUserDestroyMenu( rmii.hSubMenu ); /* ModifyMenu() spec */ + + MenuCleanupRosMenuItemInfo( &rmii ); + + /* Init new data for this menu item */ + MenuSetItemData( &mii, + uFlags, + uIDNewItem, + lpNewItem, + TRUE); + + /* Now, make Win32k IntSetMenuItemInfo handle the changes to this menu item. */ + return SetMenuItemInfoW( hMnu, + uPosition, + (BOOL)(MF_BYPOSITION & uFlags), + &mii); +} + + +/* + * @implemented + */ +BOOL WINAPI +SetMenu(HWND hWnd, + HMENU hMenu) +{ + return NtUserSetMenu(hWnd, hMenu, TRUE); +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetMenuInfo( + HMENU hmenu, + LPCMENUINFO lpcmi) +{ + ROSMENUINFO mi; + BOOL res = FALSE; + + if (!lpcmi || (lpcmi->cbSize != sizeof(MENUINFO))) + { + SetLastError(ERROR_INVALID_PARAMETER); + return res; + } + + memcpy(&mi, lpcmi, sizeof(MENUINFO)); + return NtUserMenuInfo(hmenu, &mi, TRUE); +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetMenuItemBitmaps( + HMENU hMenu, + UINT uPosition, + UINT uFlags, + HBITMAP hBitmapUnchecked, + HBITMAP hBitmapChecked) +{ + ROSMENUITEMINFO uItem; + memset ( &uItem, 0, sizeof(uItem) ); + uItem.fMask = MIIM_STATE | MIIM_BITMAP; + + if(!(NtUserMenuItemInfo(hMenu, uPosition, + (BOOL)(MF_BYPOSITION & uFlags), &uItem, FALSE))) return FALSE; + + if (!hBitmapChecked && !hBitmapUnchecked) + { + uItem.fState &= ~MF_USECHECKBITMAPS; + } + else /* Install new bitmaps */ + { + uItem.hbmpChecked = hBitmapChecked; + uItem.hbmpUnchecked = hBitmapUnchecked; + uItem.fState |= MF_USECHECKBITMAPS; + } + return NtUserMenuItemInfo(hMenu, uPosition, + (BOOL)(MF_BYPOSITION & uFlags), &uItem, TRUE); +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetMenuItemInfoA( + HMENU hMenu, + UINT uItem, + BOOL fByPosition, + LPCMENUITEMINFOA lpmii) +{ + MENUITEMINFOW MenuItemInfoW; + UNICODE_STRING UnicodeString; + NTSTATUS Status; + ULONG Result = FALSE; + + RtlCopyMemory(&MenuItemInfoW, lpmii, min(lpmii->cbSize, sizeof(MENUITEMINFOW))); + + if( lpmii->cbSize != sizeof( MENUITEMINFOW)) + { + MenuItemInfoW.cbSize = sizeof( MENUITEMINFOW); + MenuItemInfoW.hbmpItem = NULL; + } +/* + * MIIM_STRING == good + * MIIM_TYPE & MFT_STRING == good + * MIIM_STRING & MFT_STRING == good + * MIIM_STRING & MFT_OWNERSRAW == good + */ + if (((MenuItemInfoW.fMask & MIIM_STRING) || + ((MenuItemInfoW.fMask & MIIM_TYPE) && + (MENU_ITEM_TYPE(MenuItemInfoW.fType) == MF_STRING))) + && MenuItemInfoW.dwTypeData != NULL) + { +/* cch is ignored when the content of a menu item is set by calling SetMenuItemInfo. */ + Status = RtlCreateUnicodeStringFromAsciiz(&UnicodeString, + (LPSTR)MenuItemInfoW.dwTypeData); + if (!NT_SUCCESS (Status)) + { + SetLastError (RtlNtStatusToDosError(Status)); + return FALSE; + } + MenuItemInfoW.dwTypeData = UnicodeString.Buffer; + MenuItemInfoW.cch = UnicodeString.Length / sizeof(WCHAR); + } + else + { + UnicodeString.Buffer = NULL; + } + + Result = NtUserMenuItemInfo(hMenu, uItem, fByPosition, + (PROSMENUITEMINFO)&MenuItemInfoW, TRUE); + + if (UnicodeString.Buffer != NULL) + { + RtlFreeUnicodeString(&UnicodeString); + } + + return Result; +} + + +/* + * @implemented + */ +BOOL +WINAPI +SetMenuItemInfoW( + HMENU hMenu, + UINT uItem, + BOOL fByPosition, + LPCMENUITEMINFOW lpmii) +{ + MENUITEMINFOW MenuItemInfoW; + ULONG Result; + + RtlCopyMemory(&MenuItemInfoW, lpmii, min(lpmii->cbSize, sizeof(MENUITEMINFOW))); + + if( lpmii->cbSize != sizeof( MENUITEMINFOW)) + { + MenuItemInfoW.cbSize = sizeof( MENUITEMINFOW); + MenuItemInfoW.hbmpItem = NULL; + } + + if (((MenuItemInfoW.fMask & MIIM_STRING) || + ((MenuItemInfoW.fMask & MIIM_TYPE) && + (MENU_ITEM_TYPE(MenuItemInfoW.fType) == MF_STRING))) + && MenuItemInfoW.dwTypeData != NULL) + { + MenuItemInfoW.cch = strlenW(MenuItemInfoW.dwTypeData); + } + Result = NtUserMenuItemInfo(hMenu, uItem, fByPosition, + (PROSMENUITEMINFO)&MenuItemInfoW, TRUE); + + return Result; +} + +/* + * @implemented + */ +BOOL +WINAPI +SetSystemMenu ( + HWND hwnd, + HMENU hMenu) +{ + if(!hwnd) + { + SetLastError(ERROR_INVALID_WINDOW_HANDLE); + return FALSE; + } + if(!hMenu) + { + SetLastError(ERROR_INVALID_MENU_HANDLE); + return FALSE; + } + return NtUserSetSystemMenu(hwnd, hMenu); +} + +// +// Example for the Win32/User32 rewrite. +// Def = TrackPopupMenuEx@24=NtUserTrackPopupMenuEx@24 +// +// +BOOL +WINAPI +NEWTrackPopupMenu( + HMENU Menu, + UINT Flags, + int x, + int y, + int Reserved, + HWND Wnd, + CONST RECT *Rect) +{ + return NtUserTrackPopupMenuEx( Menu, + Flags, + x, + y, + Wnd, + NULL); // LPTPMPARAMS is null +} + + +/* + * @implemented + */ +DWORD +WINAPI +GetMenuContextHelpId(HMENU hmenu) +{ + ROSMENUINFO mi; + mi.cbSize = sizeof(ROSMENUINFO); + mi.fMask = MIM_HELPID; + + if(NtUserMenuInfo(hmenu, &mi, FALSE)) + { + return mi.dwContextHelpID; + } + return 0; +} + +/* + * @unimplemented + */ +BOOL +WINAPI +MenuWindowProcA( + HWND hWnd, + ULONG_PTR Result, + UINT Msg, + WPARAM wParam, + LPARAM lParam + ) +{ + if ( Msg < WM_USER) + { + LRESULT lResult; + lResult = PopupMenuWndProcA(hWnd, Msg, wParam, lParam ); + if (Result) + { + Result = (ULONG_PTR)lResult; + return TRUE; + } + return FALSE; + } + return NtUserMessageCall(hWnd, Msg, wParam, lParam, Result, FNID_MENU, TRUE); + +} + +/* + * @unimplemented + */ +BOOL +WINAPI +MenuWindowProcW( + HWND hWnd, + ULONG_PTR Result, + UINT Msg, + WPARAM wParam, + LPARAM lParam + ) +{ + if ( Msg < WM_USER) + { + LRESULT lResult; + lResult = PopupMenuWndProcW(hWnd, Msg, wParam, lParam ); + if (Result) + { + Result = (ULONG_PTR)lResult; + return TRUE; + } + return FALSE; + } + return NtUserMessageCall(hWnd, Msg, wParam, lParam, Result, FNID_MENU, FALSE); +} + +/* + * @implemented + */ +BOOL +WINAPI +ChangeMenuW( + HMENU hMenu, + UINT cmd, + LPCWSTR lpszNewItem, + UINT cmdInsert, + UINT flags) +{ + /* + FIXME: Word passes the item id in 'cmd' and 0 or 0xffff as cmdInsert + for MF_DELETE. We should check the parameters for all others + MF_* actions also (anybody got a doc on ChangeMenu?). + */ + + switch(flags & (MF_APPEND | MF_DELETE | MF_CHANGE | MF_REMOVE | MF_INSERT)) + { + case MF_APPEND : + return AppendMenuW(hMenu, flags &~ MF_APPEND, cmdInsert, lpszNewItem); + + case MF_DELETE : + return DeleteMenu(hMenu, cmd, flags &~ MF_DELETE); + + case MF_CHANGE : + return ModifyMenuW(hMenu, cmd, flags &~ MF_CHANGE, cmdInsert, lpszNewItem); + + case MF_REMOVE : + return RemoveMenu(hMenu, flags & MF_BYPOSITION ? cmd : cmdInsert, + flags &~ MF_REMOVE); + + default : /* MF_INSERT */ + return InsertMenuW(hMenu, cmd, flags, cmdInsert, lpszNewItem); + }; +} + +/* + * @implemented + */ +BOOL +WINAPI +ChangeMenuA( + HMENU hMenu, + UINT cmd, + LPCSTR lpszNewItem, + UINT cmdInsert, + UINT flags) +{ + /* + FIXME: Word passes the item id in 'cmd' and 0 or 0xffff as cmdInsert + for MF_DELETE. We should check the parameters for all others + MF_* actions also (anybody got a doc on ChangeMenu?). + */ + + switch(flags & (MF_APPEND | MF_DELETE | MF_CHANGE | MF_REMOVE | MF_INSERT)) + { + case MF_APPEND : + return AppendMenuA(hMenu, flags &~ MF_APPEND, cmdInsert, lpszNewItem); + + case MF_DELETE : + return DeleteMenu(hMenu, cmd, flags &~ MF_DELETE); + + case MF_CHANGE : + return ModifyMenuA(hMenu, cmd, flags &~ MF_CHANGE, cmdInsert, lpszNewItem); + + case MF_REMOVE : + return RemoveMenu(hMenu, flags & MF_BYPOSITION ? cmd : cmdInsert, + flags &~ MF_REMOVE); + + default : /* MF_INSERT */ + return InsertMenuA(hMenu, cmd, flags, cmdInsert, lpszNewItem); + }; +} + + + + + diff --cc dll/win32/wininet/CMakeLists.txt index e0e5f3de2ae,00000000000..8beeff2b603 mode 100644,000000..100644 --- a/dll/win32/wininet/CMakeLists.txt +++ b/dll/win32/wininet/CMakeLists.txt @@@ -1,41 -1,0 +1,37 @@@ + - add_definitions(-D__WINESRC__ -D_WINE) - add_definitions(-Dclose=_close) ++add_definitions( ++ -D__WINESRC__ -D_WINE ++ -Dclose=_close) + - include_directories( - ${REACTOS_SOURCE_DIR}/include/reactos/wine - ${REACTOS_SOURCE_DIR}/lib/3rdparty/zlib) ++include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine) + +spec2def(wininet.dll wininet.spec) + +set_rc_compiler() + +list(APPEND SOURCE + cookie.c + dialogs.c + ftp.c + gopher.c + http.c + internet.c + netconnection.c + urlcache.c + utility.c + wininet_main.c + rsrc.rc + version.rc + ${CMAKE_CURRENT_BINARY_DIR}/wininet_stubs.c + ${CMAKE_CURRENT_BINARY_DIR}/wininet.def) + +add_library(wininet SHARED ${SOURCE}) + +set_module_type(wininet win32dll) + - target_link_libraries(wininet - wine - zlib - ${PSEH_LIB}) ++target_link_libraries(wininet wine ${PSEH_LIB}) + +add_importlibs(wininet mpr shlwapi shell32 user32 advapi32 secur32 crypt32 ws2_32 msvcrt kernel32 ntdll) + +add_cab_target(wininet 1) +add_importlib_target(wininet.spec) diff --cc drivers/storage/ide/uniata/id_sata.cpp index 96627dcb829,00000000000..e73ac56280e mode 100644,000000..100644 --- a/drivers/storage/ide/uniata/id_sata.cpp +++ b/drivers/storage/ide/uniata/id_sata.cpp @@@ -1,622 -1,0 +1,657 @@@ +/*++ + +Copyright (c) 2008-2010 Alexandr A. Telyatnikov (Alter) + +Module Name: + id_probe.cpp + +Abstract: + This module handles SATA-related staff + +Author: + Alexander A. Telyatnikov (Alter) + +Environment: + kernel mode only + +Notes: + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Revision History: + +--*/ + +#include "stdafx.h" + +UCHAR +NTAPI +UniataSataConnect( + IN PVOID HwDeviceExtension, + IN ULONG lChannel, // logical channel + IN ULONG pm_port /* for port multipliers */ + ) +{ + PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; + //ULONG Channel = deviceExtension->Channel + lChannel; + PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; + SATA_SSTATUS_REG SStatus; + ULONG i; +/* + UCHAR signatureLow, + signatureHigh; +*/ + UCHAR Status; + + KdPrint2((PRINT_PREFIX "UniataSataConnect:\n")); + + if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) { + KdPrint2((PRINT_PREFIX " no I/O range\n")); + return IDE_STATUS_IDLE; + } + + /* clear SATA error register, some controllers need this */ + UniataSataWritePort4(chan, IDX_SATA_SError, + UniataSataReadPort4(chan, IDX_SATA_SError, pm_port), pm_port); + /* wait up to 1 second for "connect well" */ + for(i=0; i<100; i++) { + SStatus.Reg = UniataSataReadPort4(chan, IDX_SATA_SStatus, pm_port); + if(SStatus.SPD == SStatus_SPD_Gen1 || + SStatus.SPD == SStatus_SPD_Gen2) { + deviceExtension->lun[lChannel*2].TransferMode = ATA_SA150 + (UCHAR)(SStatus.SPD - 1); + break; + } + AtapiStallExecution(10000); + } + if(i >= 100) { + KdPrint2((PRINT_PREFIX "UniataSataConnect: SStatus %8.8x\n", SStatus.Reg)); + return 0xff; + } + /* clear SATA error register */ + UniataSataWritePort4(chan, IDX_SATA_SError, + UniataSataReadPort4(chan, IDX_SATA_SError, pm_port), pm_port); + + Status = WaitOnBaseBusyLong(chan); + if(Status & IDE_STATUS_BUSY) { + return Status; + } +/* + signatureLow = AtapiReadPort1(chan, &deviceExtension->BaseIoAddress1[lChannel].i.CylinderLow); + signatureHigh = AtapiReadPort1(chan, &deviceExtension->baseIoAddress1[lChannel].i.CylinderHigh); + + if (signatureLow == ATAPI_MAGIC_LSB && signatureHigh == ATAPI_MAGIC_MSB) { + } +*/ + KdPrint2((PRINT_PREFIX "UniataSataConnect: OK, ATA status %x\n", Status)); + return IDE_STATUS_IDLE; +} // end UniataSataConnect() + +UCHAR +NTAPI +UniataSataPhyEnable( + IN PVOID HwDeviceExtension, + IN ULONG lChannel, // logical channel + IN ULONG pm_port /* for port multipliers */ + ) +{ + PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; + PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; + SATA_SCONTROL_REG SControl; + int loop, retry; + + KdPrint2((PRINT_PREFIX "UniataSataPhyEnable:\n")); + + if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) { + KdPrint2((PRINT_PREFIX " no I/O range\n")); + return IDE_STATUS_IDLE; + } + + SControl.Reg = UniataSataReadPort4(chan, IDX_SATA_SControl, pm_port); + KdPrint2((PRINT_PREFIX "SControl %x\n", SControl.Reg)); + if(SControl.DET == SControl_DET_Idle) { + return UniataSataConnect(HwDeviceExtension, lChannel, pm_port); + } + + for (retry = 0; retry < 10; retry++) { + KdPrint2((PRINT_PREFIX "UniataSataPhyEnable: retry init %d\n", retry)); + for (loop = 0; loop < 10; loop++) { + SControl.Reg = 0; + SControl.DET = SControl_DET_Init; + UniataSataWritePort4(chan, IDX_SATA_SControl, SControl.Reg, pm_port); + AtapiStallExecution(100); + SControl.Reg = UniataSataReadPort4(chan, IDX_SATA_SControl, pm_port); + KdPrint2((PRINT_PREFIX " SControl %8.8%x\n", SControl.Reg)); + if(SControl.DET == SControl_DET_Init) { + break; + } + } + AtapiStallExecution(5000); + KdPrint2((PRINT_PREFIX "UniataSataPhyEnable: retry idle %d\n", retry)); + for (loop = 0; loop < 10; loop++) { + SControl.Reg = 0; + SControl.DET = SControl_DET_DoNothing; + SControl.IPM = SControl_IPM_NoPartialSlumber; + UniataSataWritePort4(chan, IDX_SATA_SControl, SControl.Reg, pm_port); + AtapiStallExecution(100); + SControl.Reg = UniataSataReadPort4(chan, IDX_SATA_SControl, pm_port); + KdPrint2((PRINT_PREFIX " SControl %8.8%x\n", SControl.Reg)); + if(SControl.DET == SControl_DET_Idle) { + return UniataSataConnect(HwDeviceExtension, lChannel, pm_port); + } + } + } + + KdPrint2((PRINT_PREFIX "UniataSataPhyEnable: failed\n")); + return 0xff; +} // end UniataSataPhyEnable() + +BOOLEAN +NTAPI +UniataSataClearErr( + IN PVOID HwDeviceExtension, + IN ULONG lChannel, // logical channel + IN BOOLEAN do_connect, + IN ULONG pm_port /* for port multipliers */ + ) +{ + PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; + PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; + //ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK; + SATA_SSTATUS_REG SStatus; + SATA_SERROR_REG SError; + + if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) { + //if(ChipFlags & UNIATA_SATA) { + + SStatus.Reg = UniataSataReadPort4(chan, IDX_SATA_SStatus, pm_port); + SError.Reg = UniataSataReadPort4(chan, IDX_SATA_SError, pm_port); + + if(SStatus.Reg) { + KdPrint2((PRINT_PREFIX " SStatus %x\n", SStatus.Reg)); + } + if(SError.Reg) { + KdPrint2((PRINT_PREFIX " SError %x\n", SError.Reg)); + /* clear error bits/interrupt */ + UniataSataWritePort4(chan, IDX_SATA_SError, SError.Reg, pm_port); + + if(do_connect) { + /* if we have a connection event deal with it */ + if(SError.DIAG.N) { + KdPrint2((PRINT_PREFIX " catch SATA connect/disconnect\n")); + if(SStatus.SPD >= SStatus_SPD_Gen1) { + UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH, pm_port); + } else { + UniataSataEvent(deviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH, pm_port); + } + return TRUE; + } + } + } + } + return FALSE; +} // end UniataSataClearErr() + +BOOLEAN +NTAPI +UniataSataEvent( + IN PVOID HwDeviceExtension, + IN ULONG lChannel, // logical channel + IN ULONG Action, + IN ULONG pm_port /* for port multipliers */ + ) +{ + PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; + UCHAR Status; + ULONG ldev = lChannel*2 + (pm_port ? 1 : 0); + + if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) { + return FALSE; + } + + switch(Action) { + case UNIATA_SATA_EVENT_ATTACH: + KdPrint2((PRINT_PREFIX " CONNECTED\n")); + Status = UniataSataConnect(HwDeviceExtension, lChannel, pm_port); + KdPrint2((PRINT_PREFIX " Status %x\n", Status)); + if(Status != IDE_STATUS_IDLE) { + return FALSE; + } + CheckDevice(HwDeviceExtension, lChannel, pm_port ? 1 : 0 /*dev*/, FALSE); + return TRUE; + break; + case UNIATA_SATA_EVENT_DETACH: + KdPrint2((PRINT_PREFIX " DISCONNECTED\n")); + UniataForgetDevice(&(deviceExtension->lun[ldev])); + return TRUE; + break; + } + return FALSE; +} // end UniataSataEvent() + +ULONG +NTAPI +UniataSataReadPort4( + IN PHW_CHANNEL chan, + IN ULONG io_port_ndx, + IN ULONG pm_port /* for port multipliers */ + ) +{ + if(chan && (io_port_ndx < IDX_MAX_REG) && + chan->RegTranslation[io_port_ndx].Proc) { + + PHW_DEVICE_EXTENSION deviceExtension = chan->DeviceExtension; + PVOID HwDeviceExtension = (PVOID)deviceExtension; + ULONG slotNumber = deviceExtension->slotNumber; + ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber; + ULONG VendorID = deviceExtension->DevID & 0xffff; + ULONG offs; + ULONG p; + + switch(VendorID) { + case ATA_INTEL_ID: { + p = pm_port ? 1 : 0; + if(deviceExtension->HwFlags & ICH5) { + offs = 0x50+chan->lun[p]->SATA_lun_map*0x10; + switch(io_port_ndx) { + case IDX_SATA_SStatus: + offs += 0; + break; + case IDX_SATA_SError: + offs += 1*4; + break; + case IDX_SATA_SControl: + offs += 2*4; + break; + default: + return -1; + } + SetPciConfig4(0xa0, offs); + GetPciConfig4(0xa4, offs); + return offs; + } else { + offs = ((deviceExtension->Channel+chan->lChannel)*2+p) * 0x100; + switch(io_port_ndx) { + case IDX_SATA_SStatus: + offs += 0; + break; + case IDX_SATA_SControl: + offs += 1; + break; + case IDX_SATA_SError: + offs += 2; + break; + default: + return -1; + } + AtapiWritePort4(chan, IDX_INDEXED_ADDR, offs); + return AtapiReadPort4(chan, IDX_INDEXED_DATA); + } + } // ATA_INTEL_ID + } // end switch(VendorID) + return -1; + } + return AtapiReadPort4(chan, io_port_ndx); +} // end UniataSataReadPort4() + +VOID +NTAPI +UniataSataWritePort4( + IN PHW_CHANNEL chan, + IN ULONG io_port_ndx, + IN ULONG data, + IN ULONG pm_port /* for port multipliers */ + ) +{ + if(chan && (io_port_ndx < IDX_MAX_REG) && + chan->RegTranslation[io_port_ndx].Proc) { + + PHW_DEVICE_EXTENSION deviceExtension = chan->DeviceExtension; + PVOID HwDeviceExtension = (PVOID)deviceExtension; + ULONG slotNumber = deviceExtension->slotNumber; + ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber; + ULONG VendorID = deviceExtension->DevID & 0xffff; + ULONG offs; + ULONG p; + + switch(VendorID) { + case ATA_INTEL_ID: { + p = pm_port ? 1 : 0; + if(deviceExtension->HwFlags & ICH5) { + offs = 0x50+chan->lun[p]->SATA_lun_map*0x10; + switch(io_port_ndx) { + case IDX_SATA_SStatus: + offs += 0; + break; + case IDX_SATA_SError: + offs += 1*4; + break; + case IDX_SATA_SControl: + offs += 2*4; + break; + default: + return; + } + SetPciConfig4(0xa0, offs); + SetPciConfig4(0xa4, data); + return; + } else { + offs = ((deviceExtension->Channel+chan->lChannel)*2+p) * 0x100; + switch(io_port_ndx) { + case IDX_SATA_SStatus: + offs += 0; + break; + case IDX_SATA_SControl: + offs += 1; + break; + case IDX_SATA_SError: + offs += 2; + break; + default: + return; + } + AtapiWritePort4(chan, IDX_INDEXED_ADDR, offs); + AtapiWritePort4(chan, IDX_INDEXED_DATA, data); + } + } // ATA_INTEL_ID + } // end switch(VendorID) + return; + } + AtapiWritePort4(chan, io_port_ndx, data); +} // end UniataSataWritePort4() + +BOOLEAN +NTAPI +UniataAhciInit( + IN PVOID HwDeviceExtension + ) +{ + PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; + ULONG version; + ULONG c, i, n; + PHW_CHANNEL chan; + ULONG offs; + ULONG BaseMemAddress; + ULONG PI; + ULONG CAP; ++ ULONG GHC; + BOOLEAN MemIo; + ULONGLONG base; + + /* reset AHCI controller */ - AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_GHC, - AtapiReadPortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_GHC) | AHCI_GHC_HR); - AtapiStallExecution(1000000); - if(AtapiReadPortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_GHC) & AHCI_GHC_HR) { ++ GHC = AtapiReadPortEx4(NULL, (ULONG_PTR)&deviceExtension->BaseIoAHCI_0, IDX_AHCI_GHC); ++ KdPrint2((PRINT_PREFIX " reset AHCI controller, GHC %x\n", GHC)); ++ AtapiWritePortEx4(NULL, (ULONG_PTR)&deviceExtension->BaseIoAHCI_0, IDX_AHCI_GHC, ++ GHC | AHCI_GHC_HR); ++ ++ for(i=0; i<1000; i++) { ++ AtapiStallExecution(1000); ++ GHC = AtapiReadPortEx4(NULL, (ULONG_PTR)&deviceExtension->BaseIoAHCI_0, IDX_AHCI_GHC); ++ KdPrint2((PRINT_PREFIX " AHCI GHC %x\n", GHC)); ++ if(!(GHC & AHCI_GHC_HR)) { ++ break; ++ } ++ } ++ if(GHC & AHCI_GHC_HR) { + KdPrint2((PRINT_PREFIX " AHCI reset failed\n")); + return FALSE; + } + + /* enable AHCI mode */ - AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_GHC, - AtapiReadPortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_GHC) | AHCI_GHC_AE); ++ GHC = AtapiReadPortEx4(NULL, (ULONG_PTR)&deviceExtension->BaseIoAHCI_0, IDX_AHCI_GHC); ++ KdPrint2((PRINT_PREFIX " enable AHCI mode, GHC %x\n", GHC)); ++ AtapiWritePortEx4(NULL, (ULONG_PTR)&deviceExtension->BaseIoAHCI_0, IDX_AHCI_GHC, ++ GHC | AHCI_GHC_AE); ++ GHC = AtapiReadPortEx4(NULL, (ULONG_PTR)&deviceExtension->BaseIoAHCI_0, IDX_AHCI_GHC); ++ KdPrint2((PRINT_PREFIX " AHCI GHC %x\n", GHC)); ++ + + CAP = AtapiReadPortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_CAP); + PI = AtapiReadPortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_PI); - /* get the number of HW channels */ - for(i=PI, n=0; i; n++, i=i>>1); - deviceExtension->NumberChannels = - max((CAP & AHCI_CAP_NOP_MASK)+1, n); ++ KdPrint2((PRINT_PREFIX " AHCI CAP %x\n", CAP)); + if(CAP & AHCI_CAP_S64A) { + KdPrint2((PRINT_PREFIX " AHCI 64bit\n")); + deviceExtension->Host64 = TRUE; + } ++ /* get the number of HW channels */ ++ PI = AtapiReadPortEx4(NULL, (ULONG)&deviceExtension->BaseIoAHCI_0, IDX_AHCI_PI); ++ KdPrint2((PRINT_PREFIX " AHCI PI %x\n", PI)); ++ for(i=PI, n=0; i; n++, i=i>>1); ++ deviceExtension->NumberChannels = ++ max((CAP & AHCI_CAP_NOP_MASK)+1, n); ++ ++ switch(deviceExtension->DevID) { ++ case ATA_M88SX6111: ++ deviceExtension->NumberChannels = 1; ++ break; ++ case ATA_M88SX6121: ++ deviceExtension->NumberChannels = 2; ++ break; ++ case ATA_M88SX6141: ++ case ATA_M88SX6145: ++ deviceExtension->NumberChannels = 4; ++ break; ++ } // switch() + + /* clear interrupts */ + AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_IS, + AtapiReadPortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_IS)); + + /* enable AHCI interrupts */ + AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_GHC, + AtapiReadPortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_GHC) | AHCI_GHC_IE); + + version = AtapiReadPortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_VS); - KdPrint2((PRINT_PREFIX " AHCI version %x%x.%x%x controller with %d ports (mask %x) detected\n", - (version >> 24) & 0xff, (version >> 16) & 0xff, - (version >> 8) & 0xff, version & 0xff, deviceExtension->NumberChannels, PI)); ++ KdPrint2((PRINT_PREFIX " AHCI version %x.%02x controller with %d ports (mask %x) detected\n", ++ ((version >> 20) & 0xf0) + ((version >> 16) & 0x0f), ++ ((version >> 4) & 0xf0) + (version & 0x0f), ++ deviceExtension->NumberChannels, PI)); + ++ KdPrint2((PRINT_PREFIX " PM%s supported\n", ++ CAP & AHCI_CAP_SPM ? "" : " not")); + + deviceExtension->HwFlags |= UNIATA_SATA; + deviceExtension->HwFlags |= UNIATA_AHCI; + + BaseMemAddress = deviceExtension->BaseIoAHCI_0.Addr; + MemIo = deviceExtension->BaseIoAHCI_0.MemIo; + + for(c=0; cNumberChannels; c++) { + chan = &deviceExtension->chan[c]; + offs = sizeof(IDE_AHCI_REGISTERS) + c*sizeof(IDE_AHCI_PORT_REGISTERS); + + chan->RegTranslation[IDX_IO1_i_Status ].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, TFD.STS); + chan->RegTranslation[IDX_IO1_i_Status ].MemIo = MemIo; + chan->RegTranslation[IDX_IO2_AltStatus] = chan->RegTranslation[IDX_IO1_i_Status]; + chan->RegTranslation[IDX_IO1_i_Error ].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, TFD.ERR); + chan->RegTranslation[IDX_IO1_i_Error ].MemIo = MemIo; + chan->RegTranslation[IDX_IO1_i_CylinderLow ].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SIG.LbaLow); + chan->RegTranslation[IDX_IO1_i_CylinderLow ].MemIo = MemIo; + chan->RegTranslation[IDX_IO1_i_CylinderHigh].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SIG.LbaHigh); + chan->RegTranslation[IDX_IO1_i_CylinderHigh].MemIo = MemIo; + chan->RegTranslation[IDX_IO1_i_BlockCount ].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SIG.SectorCount); + chan->RegTranslation[IDX_IO1_i_BlockCount ].MemIo = MemIo; + + UniataInitSyncBaseIO(chan); + + chan->RegTranslation[IDX_SATA_SStatus].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SSTS); + chan->RegTranslation[IDX_SATA_SStatus].MemIo = MemIo; + chan->RegTranslation[IDX_SATA_SError].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SERR); + chan->RegTranslation[IDX_SATA_SError].MemIo = MemIo; + chan->RegTranslation[IDX_SATA_SControl].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SCTL); + chan->RegTranslation[IDX_SATA_SControl].MemIo = MemIo; + chan->RegTranslation[IDX_SATA_SActive].Addr = BaseMemAddress + offs + FIELD_OFFSET(IDE_AHCI_PORT_REGISTERS, SACT); + chan->RegTranslation[IDX_SATA_SActive].MemIo = MemIo; + + AtapiDmaAlloc(HwDeviceExtension, NULL, c); + + base = chan->AHCI_CL_PhAddr; + if(!base) { + KdPrint2((PRINT_PREFIX " AHCI buffer allocation failed\n")); + return FALSE; + } + AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), offs + IDX_AHCI_P_CLB, + (ULONG)(base & 0xffffffff)); + AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), offs + IDX_AHCI_P_CLB + 4, + (ULONG)((base >> 32) & 0xffffffff)); + + base = chan->AHCI_CL_PhAddr + ATA_AHCI_MAX_TAGS; + AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), offs + IDX_AHCI_P_FB, + (ULONG)(base & 0xffffffff)); + AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), offs + IDX_AHCI_P_FB + 4, + (ULONG)((base >> 32) & 0xffffffff)); + + chan->ChannelCtrlFlags |= CTRFLAGS_NO_SLAVE; + } + + return TRUE; +} // end UniataAhciInit() + +UCHAR +NTAPI +UniataAhciStatus( + IN PVOID HwDeviceExtension, + IN ULONG lChannel, + IN ULONG DeviceNumber + ) +{ + PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension; + PHW_CHANNEL chan = &deviceExtension->chan[lChannel]; + ULONG Channel = deviceExtension->Channel + lChannel; + ULONG hIS; + ULONG CI; + AHCI_IS_REG IS; + SATA_SSTATUS_REG SStatus; + SATA_SERROR_REG SError; + ULONG offs = sizeof(IDE_AHCI_REGISTERS) + Channel*sizeof(IDE_AHCI_PORT_REGISTERS); + ULONG_PTR base; + ULONG tag=0; + + KdPrint(("UniataAhciStatus:\n")); + + hIS = AtapiReadPortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_IS); + KdPrint((" hIS %x\n", hIS)); + hIS &= (1 << Channel); + if(!hIS) { + return 0; + } + base = (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0 + offs); + IS.Reg = AtapiReadPort4(chan, base + IDX_AHCI_P_IS); + CI = AtapiReadPort4(chan, base + IDX_AHCI_P_CI); + SStatus.Reg = AtapiReadPort4(chan, IDX_SATA_SStatus); + SError.Reg = AtapiReadPort4(chan, IDX_SATA_SError); + + /* clear interrupt(s) */ + AtapiWritePortEx4(NULL, (ULONG_PTR)(&deviceExtension->BaseIoAHCI_0), IDX_AHCI_IS, hIS); + AtapiWritePort4(chan, base + IDX_AHCI_P_IS, IS.Reg); + AtapiWritePort4(chan, IDX_SATA_SError, SError.Reg); + + KdPrint((" AHCI: status=%08x sstatus=%08x error=%08x CI=%08x\n", + IS.Reg, SStatus.Reg, SError.Reg, CI)); + + /* do we have cold connect surprise */ + if(IS.CPDS) { + } + + /* check for and handle connect events */ + if(IS.PCS) { + UniataSataEvent(HwDeviceExtension, lChannel, UNIATA_SATA_EVENT_ATTACH); + } + if(IS.PRCS) { + UniataSataEvent(HwDeviceExtension, lChannel, UNIATA_SATA_EVENT_DETACH); + } + if(CI & (1 << tag)) { + return 1; + } + KdPrint((" AHCI: unexpected\n")); + return 2; + +} // end UniataAhciStatus() + +ULONG +NTAPI +UniataAhciSetupFIS( + IN PHW_DEVICE_EXTENSION deviceExtension, + IN ULONG DeviceNumber, + IN ULONG lChannel, + OUT PUCHAR fis, + IN UCHAR command, + IN ULONGLONG lba, + IN USHORT count, + IN USHORT feature, + IN ULONG flags + ) +{ + ULONG ldev = lChannel*2 + DeviceNumber; + ULONG i; + PUCHAR plba; + + KdPrint2((PRINT_PREFIX " AHCI setup FIS\n" )); + i = 0; + plba = (PUCHAR)&lba; + + if((AtaCommandFlags[command] & ATA_CMD_FLAG_LBAIOsupp) && + CheckIfBadBlock(&(deviceExtension->lun[ldev]), lba, count)) { + KdPrint3((PRINT_PREFIX ": artificial bad block, lba %#I64x count %#x\n", lba, count)); + return IDE_STATUS_ERROR; + //return SRB_STATUS_ERROR; + } + + /* translate command into 48bit version */ + if ((lba >= ATA_MAX_LBA28 || count > 256) && + deviceExtension->lun[ldev].IdentifyData.FeaturesSupport.Address48) { + if(AtaCommandFlags[command] & ATA_CMD_FLAG_48supp) { + command = AtaCommands48[command]; + } else { + KdPrint2((PRINT_PREFIX " unhandled LBA48 command\n")); + return 0; + } + } + + fis[0] = 0x27; /* host to device */ + fis[1] = 0x80; /* command FIS (note PM goes here) */ + fis[2] = command; + fis[3] = (UCHAR)feature; + + fis[4] = plba[0]; + fis[5] = plba[1]; + fis[6] = plba[2]; + fis[7] = IDE_USE_LBA | (DeviceNumber ? IDE_DRIVE_2 : IDE_DRIVE_1); + if ((lba >= ATA_MAX_LBA28 || count > 256) && + deviceExtension->lun[ldev].IdentifyData.FeaturesSupport.Address48) { + i++; + } else { +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4333) // right shift by too large amount, data loss +#endif + fis[7] |= (plba[3] >> 24) & 0x0f; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + } + + fis[8] = plba[3]; + fis[9] = plba[4]; + fis[10] = plba[5]; + fis[11] = (UCHAR)(feature>>8) & 0xff; + + fis[12] = (UCHAR)count & 0xff; + fis[13] = (UCHAR)(count>>8) & 0xff; + fis[14] = 0x00; + fis[15] = IDE_DC_A_4BIT; + + fis[16] = 0x00; + fis[17] = 0x00; + fis[18] = 0x00; + fis[19] = 0x00; + return 20; +} // end UniataAhciSetupFIS() diff --cc include/crt/_mingw_unicode.h index 00000000000,38334bc71e4..38334bc71e4 mode 000000,100644..100644 --- a/include/crt/_mingw_unicode.h +++ b/include/crt/_mingw_unicode.h diff --cc include/ddk/ioaccess.h index d1247302c0a,d1247302c0a..d1247302c0a mode 100755,100644..100644 --- a/include/ddk/ioaccess.h +++ b/include/ddk/ioaccess.h diff --cc include/reactos/wine/config.h index 2d62068fd05,00000000000..6973c336a46 mode 100644,000000..100644 --- a/include/reactos/wine/config.h +++ b/include/reactos/wine/config.h @@@ -1,1065 -1,0 +1,1059 @@@ +/* include/config.h. Generated by configure. */ +/* include/config.h.in. Generated from configure.ac by autoheader. */ + +#include "reactos/buildno.h" + +#define __WINE_CONFIG_H + +/* Define to a function attribute for Microsoft hotpatch assembly prefix. */ +#define DECLSPEC_HOTPATCH + +/* Specifies the compiler flag that forces a short wchar_t */ +#define CC_FLAG_SHORT_WCHAR "-fshort-wchar" + +/* Define to 1 if you have the header file. */ +#define HAVE_MPG123_H 1 + +/* Define if you have ALSA 1.x including devel headers */ +/* #undef HAVE_ALSA */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ALSA_ASOUNDLIB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ARPA_INET_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ARPA_NAMESER_H */ + +/* Define if you have ARTS sound server */ +/* #undef HAVE_ARTS */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ASM_TYPES_H */ + +/* Define to 1 if you have the