ReactOS.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
November
October
September
August
July
June
May
April
March
February
January
2018
December
November
October
September
August
July
June
May
April
March
February
January
2017
December
November
October
September
August
July
June
May
April
March
February
January
2016
December
November
October
September
August
July
June
May
April
March
February
January
2015
December
November
October
September
August
July
June
May
April
March
February
January
2014
December
November
October
September
August
July
June
May
April
March
February
January
2013
December
November
October
September
August
July
June
May
April
March
February
January
2012
December
November
October
September
August
July
June
May
April
March
February
January
2011
December
November
October
September
August
July
June
May
April
March
February
January
2010
December
November
October
September
August
July
June
May
April
March
February
January
2009
December
November
October
September
August
July
June
May
April
March
February
January
2008
December
November
October
September
August
July
June
May
April
March
February
January
2007
December
November
October
September
August
July
June
May
April
March
February
January
2006
December
November
October
September
August
July
June
May
April
March
February
January
2005
December
November
October
September
August
July
June
May
April
March
February
January
2004
December
November
October
September
August
July
June
May
April
March
February
List overview
Download
Ros-diffs
July 2006
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
ros-diffs@reactos.org
19 participants
662 discussions
Start a n
N
ew thread
[jimtabor] 22795: -NtUserCreateWindowEx: Removed not about setting WS_CHILD.
by jimtabor@svn.reactos.org
Author: jimtabor Date: Mon Jul 3 11:54:45 2006 New Revision: 22795 URL:
http://svn.reactos.org/svn/reactos?rev=22795&view=rev
Log: -NtUserCreateWindowEx: Removed not about setting WS_CHILD. Modified: trunk/reactos/subsystems/win32/win32k/ntuser/window.c Modified: trunk/reactos/subsystems/win32/win32k/ntuser/window.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/window.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/window.c Mon Jul 3 11:54:45 2006 @@ -1663,9 +1663,6 @@ else { dwStyle &= ~WS_POPUP; -/* - (|| WS_CHILD) is done at the top. So~ Here is just a bit in a 32/64 bit word. -*/ dwStyle |= (WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX); }
18 years, 5 months
1
0
0
0
[jimtabor] 22794: -NtUserCreateWindowEx: Don't force WS_CHILD set, it could be WS_POPUP.
by jimtabor@svn.reactos.org
Author: jimtabor Date: Mon Jul 3 11:52:22 2006 New Revision: 22794 URL:
http://svn.reactos.org/svn/reactos?rev=22794&view=rev
Log: -NtUserCreateWindowEx: Don't force WS_CHILD set, it could be WS_POPUP. Modified: trunk/reactos/subsystems/win32/win32k/ntuser/window.c Modified: trunk/reactos/subsystems/win32/win32k/ntuser/window.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/window.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/window.c Mon Jul 3 11:52:22 2006 @@ -1431,11 +1431,6 @@ ParentWindowHandle = PsGetWin32Thread()->Desktop->DesktopWindow; OwnerWindowHandle = NULL; - if ((!(dwStyle & WS_CHILD)) && (dwExStyle & WS_EX_MDICHILD)) - { - dwStyle |= WS_CHILD; // Forced Child! - } - if (hWndParent == HWND_MESSAGE) { /* @@ -1446,7 +1441,8 @@ } else if (hWndParent) { - if ((dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD) + if (((dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD) || + (dwExStyle & WS_EX_MDICHILD)) ParentWindowHandle = hWndParent; else {
18 years, 5 months
1
0
0
0
[hpoussin] 22793: Add more defines for anonymous structure/union names
by hpoussin@svn.reactos.org
Author: hpoussin Date: Mon Jul 3 11:43:28 2006 New Revision: 22793 URL:
http://svn.reactos.org/svn/reactos?rev=22793&view=rev
Log: Add more defines for anonymous structure/union names Modified: trunk/reactos/include/psdk/windef.h Modified: trunk/reactos/include/psdk/windef.h URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/include/psdk/windef.h?rev=…
============================================================================== --- trunk/reactos/include/psdk/windef.h (original) +++ trunk/reactos/include/psdk/windef.h Mon Jul 3 11:43:28 2006 @@ -171,6 +171,7 @@ #define _ANONYMOUS_UNION #define _UNION_NAME(x) x #define DUMMYUNIONNAME u +#define DUMMYUNIONNAME1 u1 #define DUMMYUNIONNAME2 u2 #define DUMMYUNIONNAME3 u3 #define DUMMYUNIONNAME4 u4 @@ -181,6 +182,7 @@ #else #define _UNION_NAME(x) #define DUMMYUNIONNAME +#define DUMMYUNIONNAME1 #define DUMMYUNIONNAME2 #define DUMMYUNIONNAME3 #define DUMMYUNIONNAME4 @@ -193,13 +195,19 @@ #define _ANONYMOUS_STRUCT #define _STRUCT_NAME(x) x #define DUMMYSTRUCTNAME s +#define DUMMYSTRUCTNAME1 s1 #define DUMMYSTRUCTNAME2 s2 #define DUMMYSTRUCTNAME3 s3 +#define DUMMYSTRUCTNAME4 s4 +#define DUMMYSTRUCTNAME5 s5 #else #define _STRUCT_NAME(x) #define DUMMYSTRUCTNAME +#define DUMMYSTRUCTNAME1 #define DUMMYSTRUCTNAME2 #define DUMMYSTRUCTNAME3 +#define DUMMYSTRUCTNAME4 +#define DUMMYSTRUCTNAME5 #endif #ifndef NO_STRICT
18 years, 5 months
1
0
0
0
[jimtabor] 22792: - NtUser/CreateWindowExA/W: - Add support for WS_EX_MDICHILD. Reordered sequence for setting WindowObject and callers styles. - Synced mdi.c from Wine. Added support function MDI_GetId help return IDMenu. - Thanks to GreatLord for helping.
by jimtabor@svn.reactos.org
Author: jimtabor Date: Mon Jul 3 08:33:29 2006 New Revision: 22792 URL:
http://svn.reactos.org/svn/reactos?rev=22792&view=rev
Log: - NtUser/CreateWindowExA/W: - Add support for WS_EX_MDICHILD. Reordered sequence for setting WindowObject and callers styles. - Synced mdi.c from Wine. Added support function MDI_GetId help return IDMenu. - Thanks to GreatLord for helping. Modified: trunk/reactos/dll/win32/user32/windows/mdi.c trunk/reactos/dll/win32/user32/windows/window.c trunk/reactos/media/doc/README.WINE trunk/reactos/subsystems/win32/win32k/ntuser/window.c Modified: trunk/reactos/dll/win32/user32/windows/mdi.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/windows/m…
============================================================================== --- trunk/reactos/dll/win32/user32/windows/mdi.c (original) +++ trunk/reactos/dll/win32/user32/windows/mdi.c Mon Jul 3 08:33:29 2006 @@ -18,7 +18,7 @@ * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * * Notes: Fairly complete implementation. * Also, Excel and WinWord do _not_ use MDI so if you're trying @@ -84,15 +84,9 @@ #include <wine/debug.h> - WINE_DEFAULT_DEBUG_CHANNEL(mdi); -#define MDI_MAXLISTLENGTH 0x40 #define MDI_MAXTITLELENGTH 0xa1 - -#define MDI_NOFRAMEREPAINT 0 -#define MDI_REPAINTFRAMENOW 1 -#define MDI_REPAINTFRAME 2 #define WM_MDICALCCHILDSCROLL 0x10ac /* this is exactly what Windows uses */ @@ -107,8 +101,9 @@ typedef struct { UINT nActiveChildren; - HWND hwndChildMaximized; HWND hwndActiveChild; + HWND *child; /* array of tracked children */ + HMENU hFrameMenu; HMENU hWindowMenu; UINT idFirstChild; LPWSTR frameTitle; @@ -120,16 +115,15 @@ static HBITMAP hBmpClose = 0; /* ----------------- declarations ----------------- */ -static void MDI_UpdateFrameText( HWND, HWND, BOOL, LPCWSTR); +static void MDI_UpdateFrameText( HWND, HWND, LPCWSTR); static BOOL MDI_AugmentFrameMenu( HWND, HWND ); static BOOL MDI_RestoreFrameMenu( HWND, HWND ); static LONG MDI_ChildActivate( HWND, HWND ); +static LRESULT MDI_RefreshMenu(MDICLIENTINFO *); static HWND MDI_MoreWindowsDialog(HWND); -static void MDI_SwapMenuItems(HWND, UINT, UINT); static LRESULT WINAPI MDIClientWndProcA( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ); static LRESULT WINAPI MDIClientWndProcW( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ); - static HWND* WIN_ListChildren (HWND hWndparent) @@ -169,51 +163,25 @@ return pHwnd; } - - #ifdef __REACTOS__ void WINAPI ScrollChildren(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void WINAPI CalcChildScroll(HWND hwnd, INT scroll); - -BOOL CALLBACK MDI_GetChildByID_EnumProc (HWND hwnd, LPARAM lParam ) -{ - DWORD *control = (DWORD *)lParam; - if(*control == GetWindowLongW( hwnd, GWL_ID )) - { - *control = (DWORD)hwnd; - return FALSE; - } - return TRUE; -} #endif /* -------- Miscellaneous service functions ---------- * * MDI_GetChildByID */ -static HWND MDI_GetChildByID(HWND hwnd, UINT id) -{ -#ifdef __REACTOS__ - DWORD Control = id; - if (hwnd && !EnumChildWindows(hwnd, (WNDENUMPROC)&MDI_GetChildByID_EnumProc, (LPARAM)&Control)) - { - return (HWND)Control; +static HWND MDI_GetChildByID(HWND hwnd, UINT id, MDICLIENTINFO *ci) +{ + int i; + + for (i = 0; ci->nActiveChildren; i++) + { + if (GetWindowLongPtrW( ci->child[i], GWLP_ID ) == id) + return ci->child[i]; } return 0; -#else - HWND ret; - HWND *win_array; - int i; - - if (!(win_array = WIN_ListChildren( hwnd ))) return 0; - for (i = 0; win_array[i]; i++) - { - if (GetWindowLongA( win_array[i], GWL_ID ) == id) break; - } - ret = win_array[i]; - HeapFree( GetProcessHeap(), 0, win_array ); - return ret; -#endif } static void MDI_PostUpdate(HWND hwnd, MDICLIENTINFO* ci, WORD recalc) @@ -233,11 +201,11 @@ const struct builtin_class_descr MDICLIENT_builtin_class = { L"MDIClient", /* name */ - 0, /* style */ - MDIClientWndProcW, /* procW */ - MDIClientWndProcA, /* procA */ - sizeof(MDICLIENTINFO *), /* extra */ - IDC_ARROW, /* cursor */ + 0, /* style */ + MDIClientWndProcW, /* procW */ + MDIClientWndProcA, /* procA */ + sizeof(MDICLIENTINFO), /* extra */ + IDC_ARROW, /* cursor */ (HBRUSH)(COLOR_APPWORKSPACE+1) /* brush */ }; @@ -253,7 +221,7 @@ { if (win == WND_OTHER_PROCESS) { - ERR( "client %p belongs to other process\n", client ); + if (IsWindow(client)) ERR( "client %p belongs to other process\n", client ); return NULL; } if (win->cbWndExtra < sizeof(MDICLIENTINFO)) WARN( "%p is not an MDI client\n", client ); @@ -278,82 +246,16 @@ return TRUE; } -/********************************************************************** - * MDI_MenuModifyItem - */ -static void MDI_MenuModifyItem( HWND client, HWND hWndChild ) -{ - MDICLIENTINFO *clientInfo = get_client_info( client ); - WCHAR buffer[128]; - UINT n, id; - - if (!clientInfo || !clientInfo->hWindowMenu) return; - - id = GetWindowLongA( hWndChild, GWL_ID ); - if (id >= clientInfo->idFirstChild + MDI_MOREWINDOWSLIMIT) return; - buffer[0] = '&'; - buffer[1] = '1' + id - clientInfo->idFirstChild; - buffer[2] = ' '; - GetWindowTextW( hWndChild, buffer + 3, sizeof(buffer)/sizeof(WCHAR) - 3 ); - - n = GetMenuState(clientInfo->hWindowMenu, id, MF_BYCOMMAND); - ModifyMenuW(clientInfo->hWindowMenu, id, MF_BYCOMMAND | MF_STRING, id, buffer ); - CheckMenuItem(clientInfo->hWindowMenu, id, n & MF_CHECKED); -} - -/********************************************************************** - * MDI_MenuDeleteItem - */ -static BOOL MDI_MenuDeleteItem( HWND client, HWND hWndChild ) -{ - WCHAR buffer[128]; - static const WCHAR format[] = {'&','%','d',' ',0}; - MDICLIENTINFO *clientInfo = get_client_info( client ); - UINT index = 0,id,n; - - if( !clientInfo->nActiveChildren || !clientInfo->hWindowMenu ) - return FALSE; - - id = GetWindowLongA( hWndChild, GWL_ID ); - DeleteMenu(clientInfo->hWindowMenu,id,MF_BYCOMMAND); - - /* walk the rest of MDI children to prevent gaps in the id - * sequence and in the menu child list */ - - for( index = id+1; index <= clientInfo->nActiveChildren + - clientInfo->idFirstChild; index++ ) - { - HWND hwnd = MDI_GetChildByID(client,index); - if (!hwnd) - { - TRACE("no window for id=%i\n",index); - continue; - } - - /* set correct id */ - SetWindowLongW( hwnd, GWL_ID, GetWindowLongW( hwnd, GWL_ID ) - 1 ); - - n = wsprintfW(buffer, format ,index - clientInfo->idFirstChild); - GetWindowTextW( hwnd, buffer + n, sizeof(buffer)/sizeof(WCHAR) - n ); - - /* change menu if the current child is to be shown in the - * "Windows" menu - */ - if (index <= clientInfo->idFirstChild + MDI_MOREWINDOWSLIMIT) - ModifyMenuW(clientInfo->hWindowMenu ,index ,MF_BYCOMMAND | MF_STRING, - index - 1 , buffer ); - } - - /* We must restore the "More Windows..." option if there are enough children - */ - if (clientInfo->nActiveChildren - 1 > MDI_MOREWINDOWSLIMIT) - { - WCHAR szTmp[50]; - LoadStringW(User32Instance, IDS_MDI_MOREWINDOWS, szTmp, sizeof(szTmp)/sizeof(szTmp[0])); - AppendMenuW(clientInfo->hWindowMenu, MF_STRING, clientInfo->idFirstChild + MDI_MOREWINDOWSLIMIT, szTmp); - } - return TRUE; -} +#ifdef __REACTOS__ +INT +MDI_GetId(HWND hWndClient) +{ + MDICLIENTINFO * ci = get_client_info( hWndClient ); + if(ci) return ci->idFirstChild + ci->nActiveChildren; + return 0; +} +#endif + /********************************************************************** * MDI_GetWindow @@ -401,21 +303,28 @@ * * It seems that the default height is about 2/3 of the client rect */ -static void MDI_CalcDefaultChildPos( HWND hwnd, WORD n, LPPOINT lpPos, INT delta) +void MDI_CalcDefaultChildPos( HWND hwndClient, INT total, LPPOINT lpPos, INT delta, UINT *id ) { INT nstagger; RECT rect; - INT spacing = GetSystemMetrics(SM_CYCAPTION) + - GetSystemMetrics(SM_CYFRAME) - 1; - - GetClientRect( hwnd, &rect ); + INT spacing = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME) - 1; + + if (total < 0) /* we are called from CreateWindow */ + { + MDICLIENTINFO *ci = get_client_info(hwndClient); + total = ci ? ci->nTotalCreated : 0; + *id = ci->idFirstChild + ci->nActiveChildren; + TRACE("MDI child id %04x\n", *id); + } + + GetClientRect( hwndClient, &rect ); if( rect.bottom - rect.top - delta >= spacing ) rect.bottom -= delta; nstagger = (rect.bottom - rect.top)/(3 * spacing); lpPos[1].x = (rect.right - rect.left - nstagger * spacing); lpPos[1].y = (rect.bottom - rect.top - nstagger * spacing); - lpPos[0].x = lpPos[0].y = spacing * (n%(nstagger+1)); + lpPos[0].x = lpPos[0].y = spacing * (total%(nstagger+1)); } /********************************************************************** @@ -426,7 +335,6 @@ { MDICLIENTINFO *ci; HWND hwndFrame = GetParent(hwnd); - HMENU oldFrameMenu = GetMenu(hwndFrame); TRACE("%p %p %p\n", hwnd, hmenuFrame, hmenuWindow); @@ -444,8 +352,13 @@ if (!(ci = get_client_info( hwnd ))) return 0; - if( ci->hwndChildMaximized && hmenuFrame && hmenuFrame!=oldFrameMenu ) - MDI_RestoreFrameMenu( GetParent(hwnd), ci->hwndChildMaximized ); + if (hmenuFrame) + { + if (hmenuFrame == ci->hFrameMenu) return (LRESULT)hmenuFrame; + + if (IsZoomed(ci->hwndActiveChild)) + MDI_RestoreFrameMenu( hwndFrame, ci->hwndActiveChild ); + } if( hmenuWindow && hmenuWindow != ci->hWindowMenu ) { @@ -454,267 +367,146 @@ /* Agent newsreader calls this function with ci->hWindowMenu == NULL */ if( ci->hWindowMenu && ci->nActiveChildren ) { - INT j; - LPWSTR buffer = NULL; - MENUITEMINFOW mii; - INT nbWindowsMenuItems; /* num of documents shown + "More Windows..." if present */ - INT i = GetMenuItemCount(ci->hWindowMenu) - 1; - INT pos = GetMenuItemCount(hmenuWindow) + 1; - - AppendMenuA( hmenuWindow, MF_SEPARATOR, 0, NULL); - - if (ci->nActiveChildren <= MDI_MOREWINDOWSLIMIT) - nbWindowsMenuItems = ci->nActiveChildren; - else - nbWindowsMenuItems = MDI_MOREWINDOWSLIMIT + 1; - - j = i - nbWindowsMenuItems + 1; - - for( ; i >= j ; i-- ) - { - memset(&mii, 0, sizeof(mii)); - mii.cbSize = sizeof(mii); - mii.fMask = MIIM_CHECKMARKS | MIIM_DATA | MIIM_ID | MIIM_STATE - | MIIM_SUBMENU | MIIM_TYPE | MIIM_BITMAP; - - GetMenuItemInfoW(ci->hWindowMenu, i, TRUE, &mii); - if(mii.cch) { /* Menu is MFT_STRING */ - mii.cch++; /* add room for '\0' */ - buffer = HeapAlloc(GetProcessHeap(), 0, - mii.cch * sizeof(WCHAR)); - mii.dwTypeData = buffer; - GetMenuItemInfoW(ci->hWindowMenu, i, TRUE, &mii); - } - DeleteMenu(ci->hWindowMenu, i, MF_BYPOSITION); - InsertMenuItemW(hmenuWindow, pos, TRUE, &mii); - if(buffer) { - HeapFree(GetProcessHeap(), 0, buffer); - buffer = NULL; - } - } - /* remove separator */ - DeleteMenu(ci->hWindowMenu, i, MF_BYPOSITION); - } - ci->hWindowMenu = hmenuWindow; + UINT nActiveChildren_old = ci->nActiveChildren; + + /* Remove all items from old Window menu */ + ci->nActiveChildren = 0; + MDI_RefreshMenu(ci); + + ci->hWindowMenu = hmenuWindow; + + /* Add items to the new Window menu */ + ci->nActiveChildren = nActiveChildren_old; + MDI_RefreshMenu(ci); + } + else + ci->hWindowMenu = hmenuWindow; } if (hmenuFrame) { SetMenu(hwndFrame, hmenuFrame); - if( hmenuFrame!=oldFrameMenu ) - { - if( ci->hwndChildMaximized ) - MDI_AugmentFrameMenu( GetParent(hwnd), ci->hwndChildMaximized ); + if( hmenuFrame != ci->hFrameMenu ) + { + HMENU oldFrameMenu = ci->hFrameMenu; + + ci->hFrameMenu = hmenuFrame; + if (IsZoomed(ci->hwndActiveChild) && (GetWindowLongW(ci->hwndActiveChild, GWL_STYLE) & WS_VISIBLE)) + MDI_AugmentFrameMenu( hwndFrame, ci->hwndActiveChild ); + return (LRESULT)oldFrameMenu; } } else { - HMENU menu = GetMenu( GetParent(hwnd) ); - INT nItems = GetMenuItemCount(menu) - 1; - UINT iId = GetMenuItemID(menu,nItems) ; - - if( !(iId == SC_RESTORE || iId == SC_CLOSE) ) - { - /* SetMenu() may already have been called, meaning that this window - * already has its menu. But they may have done a SetMenu() on - * an MDI window, and called MDISetMenu() after the fact, meaning - * that the "if" to this "else" wouldn't catch the need to - * augment the frame menu. - */ - if( ci->hwndChildMaximized ) - MDI_AugmentFrameMenu( GetParent(hwnd), ci->hwndChildMaximized ); - } - } + /* SetMenu() may already have been called, meaning that this window + * already has its menu. But they may have done a SetMenu() on + * an MDI window, and called MDISetMenu() after the fact, meaning + * that the "if" to this "else" wouldn't catch the need to + * augment the frame menu. + */ + if( IsZoomed(ci->hwndActiveChild) ) + MDI_AugmentFrameMenu( hwndFrame, ci->hwndActiveChild ); + } + return 0; } /********************************************************************** * MDIRefreshMenu */ -static LRESULT MDIRefreshMenu( HWND hwnd, HMENU hmenuFrame, - HMENU hmenuWindow) -{ - HWND hwndFrame = GetParent(hwnd); - HMENU oldFrameMenu = GetMenu(hwndFrame); - - TRACE("%p %p %p\n", hwnd, hmenuFrame, hmenuWindow); - - FIXME("partially function stub\n"); - - return (LRESULT)oldFrameMenu; +static LRESULT MDI_RefreshMenu(MDICLIENTINFO *ci) +{ + UINT i, count, visible, id; + WCHAR buf[MDI_MAXTITLELENGTH]; + + TRACE("children %u, window menu %p\n", ci->nActiveChildren, ci->hWindowMenu); + + if (!ci->hWindowMenu) + return 0; + + if (!IsMenu(ci->hWindowMenu)) + { + WARN("Window menu handle %p is no more valid\n", ci->hWindowMenu); + return 0; + } + + /* Windows finds the last separator in the menu, and if after it + * there is a menu item with MDI magic ID removes all existing + * menu items after it, and then adds visible MDI children. + */ + count = GetMenuItemCount(ci->hWindowMenu); + for (i = 0; i < count; i++) + { + MENUITEMINFOW mii; + + memset(&mii, 0, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_TYPE; + if (GetMenuItemInfoW(ci->hWindowMenu, i, TRUE, &mii)) + { + if (mii.fType & MF_SEPARATOR) + { + /* Windows checks only ID of the menu item */ + memset(&mii, 0, sizeof(mii)); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_ID; + if (GetMenuItemInfoW(ci->hWindowMenu, i + 1, TRUE, &mii)) + { + if (mii.wID == ci->idFirstChild) + { + TRACE("removing %u items including separator\n", count - i); + while (RemoveMenu(ci->hWindowMenu, i, MF_BYPOSITION)) + /* nothing */; + + break; + } + } + } + } + } + + visible = 0; + for (i = 0; i < ci->nActiveChildren; i++) + { + if (GetWindowLongW(ci->child[i], GWL_STYLE) & WS_VISIBLE) + { + id = ci->idFirstChild + visible; + + if (visible == MDI_MOREWINDOWSLIMIT) + { + LoadStringW(User32Instance, IDS_MDI_MOREWINDOWS, buf, sizeof(buf)/sizeof(WCHAR)); + AppendMenuW(ci->hWindowMenu, MF_STRING, id, buf); + break; + } + + if (!visible) + /* Visio expects that separator has id 0 */ + AppendMenuW(ci->hWindowMenu, MF_SEPARATOR, 0, NULL); + + visible++; + + SetWindowLongPtrW(ci->child[i], GWLP_ID, id); + + buf[0] = '&'; + buf[1] = '0' + visible; + buf[2] = ' '; + InternalGetWindowText(ci->child[i], buf + 3, sizeof(buf)/sizeof(WCHAR) - 3); + TRACE("Adding %p, id %u %s\n", ci->child[i], id, debugstr_w(buf)); + AppendMenuW(ci->hWindowMenu, MF_STRING, id, buf); + + if (ci->child[i] == ci->hwndActiveChild) + CheckMenuItem(ci->hWindowMenu, id, MF_CHECKED); + } + else + TRACE("MDI child %p is not visible, skipping\n", ci->child[i]); + } + + return (LRESULT)ci->hFrameMenu; } /* ------------------ MDI child window functions ---------------------- */ - - -/********************************************************************** - * MDICreateChild - */ -static HWND MDICreateChild( HWND parent, MDICLIENTINFO *ci, - LPMDICREATESTRUCTA cs, BOOL unicode ) -{ - POINT pos[2]; - DWORD style = cs->style | (WS_CHILD | WS_CLIPSIBLINGS); - HWND hwnd, hwndMax = 0; - UINT wIDmenu = ci->idFirstChild + ci->nActiveChildren; -#ifndef __REACTOS__ - WND *wndParent; -#endif - static const WCHAR lpstrDef[] = {'j','u','n','k','!',0}; - - TRACE("origin %i,%i - dim %i,%i, style %08lx\n", - cs->x, cs->y, cs->cx, cs->cy, cs->style); - /* calculate placement */ - MDI_CalcDefaultChildPos(parent, ci->nTotalCreated++, pos, 0); - -#ifndef __REACTOS__ - if (cs->cx == CW_USEDEFAULT || cs->cx == CW_USEDEFAULT16 || !cs->cx) cs->cx = pos[1].x; - if (cs->cy == CW_USEDEFAULT || cs->cy == CW_USEDEFAULT16 || !cs->cy) cs->cy = pos[1].y; - - if (cs->x == CW_USEDEFAULT || cs->x == CW_USEDEFAULT16) -#else - if (cs->cx == CW_USEDEFAULT || !cs->cx) cs->cx = pos[1].x; - if (cs->cy == CW_USEDEFAULT || !cs->cy) cs->cy = pos[1].y; - - if (cs->x == CW_USEDEFAULT) -#endif - { - cs->x = pos[0].x; - cs->y = pos[0].y; - } - - /* restore current maximized child */ - if( (style & WS_VISIBLE) && ci->hwndChildMaximized ) - { - TRACE("Restoring current maximized child %p\n", ci->hwndChildMaximized); - if( style & WS_MAXIMIZE ) - SendMessageW(parent, WM_SETREDRAW, FALSE, 0L); - hwndMax = ci->hwndChildMaximized; - ShowWindow( hwndMax, SW_SHOWNOACTIVATE ); - if( style & WS_MAXIMIZE ) - SendMessageW(parent, WM_SETREDRAW, TRUE, 0L); - } - - if (ci->nActiveChildren <= MDI_MOREWINDOWSLIMIT) - /* this menu is needed to set a check mark in MDI_ChildActivate */ - if (ci->hWindowMenu != 0) - AppendMenuW(ci->hWindowMenu, MF_STRING, wIDmenu, lpstrDef); - - ci->nActiveChildren++; - - /* fix window style */ -#ifndef __REACTOS__ - wndParent = WIN_FindWndPtr( parent ); - if( !(wndParent->dwStyle & MDIS_ALLCHILDSTYLES) ) -#else - if( !(GetWindowLong(parent, GWL_STYLE) & MDIS_ALLCHILDSTYLES) ) -#endif - { - TRACE("MDIS_ALLCHILDSTYLES is missing, fixing window style\n"); - style &= (WS_CHILD | WS_CLIPSIBLINGS | WS_MINIMIZE | WS_MAXIMIZE | - WS_CLIPCHILDREN | WS_DISABLED | WS_VSCROLL | WS_HSCROLL ); - style |= (WS_VISIBLE | WS_OVERLAPPEDWINDOW); - } - -#ifndef __REACTOS__ - if( wndParent->flags & WIN_ISWIN32 ) -#endif - { -#ifndef __REACTOS__ - WIN_ReleaseWndPtr( wndParent ); -#endif - if(unicode) - { - MDICREATESTRUCTW *csW = (MDICREATESTRUCTW *)cs; - hwnd = CreateWindowW( csW->szClass, csW->szTitle, style, - csW->x, csW->y, csW->cx, csW->cy, parent, - (HMENU)wIDmenu, csW->hOwner, csW ); - } - else - hwnd = CreateWindowA( cs->szClass, cs->szTitle, style, - cs->x, cs->y, cs->cx, cs->cy, parent, - (HMENU)wIDmenu, cs->hOwner, cs ); - } -#ifndef __REACTOS__ - else - { - MDICREATESTRUCT16 cs16; - SEGPTR title, cls, seg_cs16; - - WIN_ReleaseWndPtr( wndParent ); - STRUCT32_MDICREATESTRUCT32Ato16( cs, &cs16 ); - cs16.szTitle = title = MapLS( cs->szTitle ); - cs16.szClass = cls = MapLS( cs->szClass ); - seg_cs16 = MapLS( &cs16 ); - hwnd = WIN_Handle32( CreateWindow16( cs->szClass, cs->szTitle, style, - cs16.x, cs16.y, cs16.cx, cs16.cy, - HWND_16(parent), (HMENU16)wIDmenu, - cs16.hOwner, (LPVOID)seg_cs16 )); - UnMapLS( seg_cs16 ); - UnMapLS( title ); - UnMapLS( cls ); - } -#endif - - /* MDI windows are WS_CHILD so they won't be activated by CreateWindow */ - - if (hwnd) - { - /* All MDI child windows have the WS_EX_MDICHILD style */ - SetWindowLongW( hwnd, GWL_EXSTYLE, GetWindowLongW( hwnd, GWL_EXSTYLE ) | WS_EX_MDICHILD ); - - /* If we have more than 9 windows, we must insert the new one at the - * 9th position in order to see it in the "Windows" menu - */ - if (ci->nActiveChildren > MDI_MOREWINDOWSLIMIT) - MDI_SwapMenuItems( parent, GetWindowLongW( hwnd, GWL_ID ), - ci->idFirstChild + MDI_MOREWINDOWSLIMIT - 1); - - MDI_MenuModifyItem(parent, hwnd); - - /* Have we hit the "More Windows..." limit? If so, we must - * add a "More Windows..." option - */ - if (ci->nActiveChildren == MDI_MOREWINDOWSLIMIT + 1) - { - WCHAR szTmp[50]; - LoadStringW(User32Instance, IDS_MDI_MOREWINDOWS, szTmp, sizeof(szTmp)/sizeof(szTmp[0])); - - ModifyMenuW(ci->hWindowMenu, - ci->idFirstChild + MDI_MOREWINDOWSLIMIT, - MF_BYCOMMAND | MF_STRING, - ci->idFirstChild + MDI_MOREWINDOWSLIMIT, - szTmp); - } - - if( IsIconic(hwnd) && ci->hwndActiveChild ) - { - TRACE("Minimizing created MDI child %p\n", hwnd); - ShowWindow( hwnd, SW_SHOWMINNOACTIVE ); - } - else - { - /* WS_VISIBLE is clear if a) the MDI client has - * MDIS_ALLCHILDSTYLES style and 2) the flag is cleared in the - * MDICreateStruct. If so the created window is not shown nor - * activated. - */ - if (IsWindowVisible(hwnd)) ShowWindow(hwnd, SW_SHOW); - } - TRACE("created child - %p\n",hwnd); - } - else - { - ci->nActiveChildren--; - DeleteMenu(ci->hWindowMenu,wIDmenu,MF_BYCOMMAND); - if( IsWindow(hwndMax) ) - ShowWindow(hwndMax, SW_SHOWMAXIMIZED); - } - - return hwnd; -} /********************************************************************** * MDI_ChildGetMinMaxInfo @@ -746,29 +538,32 @@ * Note: SetWindowPos sends WM_CHILDACTIVATE to the child window that is * being activated */ -static void MDI_SwitchActiveChild( HWND clientHwnd, HWND childHwnd, - BOOL bNextWindow ) -{ - HWND hwndTo = 0; - HWND hwndPrev = 0; - MDICLIENTINFO *ci = get_client_info( clientHwnd ); - - hwndTo = MDI_GetWindow(ci, childHwnd, bNextWindow, 0); - - TRACE("from %p, to %p\n",childHwnd,hwndTo); - - if ( !hwndTo ) return; /* no window to switch to */ +static void MDI_SwitchActiveChild( MDICLIENTINFO *ci, HWND hwndTo, BOOL activate ) +{ + HWND hwndPrev; hwndPrev = ci->hwndActiveChild; + TRACE("from %p, to %p\n", hwndPrev, hwndTo); + if ( hwndTo != hwndPrev ) { - SetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE ); - - if( bNextWindow && hwndPrev ) - SetWindowPos( hwndPrev, HWND_BOTTOM, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE ); + BOOL was_zoomed = IsZoomed(hwndPrev); + + if (was_zoomed) + { + /* restore old MDI child */ + SendMessageW( hwndPrev, WM_SETREDRAW, FALSE, 0 ); + ShowWindow( hwndPrev, SW_RESTORE ); + SendMessageW( hwndPrev, WM_SETREDRAW, TRUE, 0 ); + + /* activate new MDI child */ + SetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE ); + /* maximize new MDI child */ + ShowWindow( hwndTo, SW_MAXIMIZE ); + } + /* activate new MDI child */ + SetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | (activate ? 0 : SWP_NOACTIVATE) ); } } @@ -776,39 +571,55 @@ /********************************************************************** * MDIDestroyChild */ -static LRESULT MDIDestroyChild( HWND parent, MDICLIENTINFO *ci, +static LRESULT MDIDestroyChild( HWND client, MDICLIENTINFO *ci, HWND child, BOOL flagDestroy ) { + UINT i; + + TRACE("# of managed children %u\n", ci->nActiveChildren); + if( child == ci->hwndActiveChild ) { - MDI_SwitchActiveChild(parent, child, TRUE); - - if( child == ci->hwndActiveChild ) - { - ShowWindow( child, SW_HIDE); - if( child == ci->hwndChildMaximized ) + HWND next = MDI_GetWindow(ci, child, TRUE, 0); + if (next) + MDI_SwitchActiveChild(ci, next, TRUE); + else + { + ShowWindow(child, SW_HIDE); + if (IsZoomed(child)) { - HWND frame = GetParent(parent); - MDI_RestoreFrameMenu( frame, child ); - ci->hwndChildMaximized = 0; - MDI_UpdateFrameText( frame, parent, TRUE, NULL); + MDI_RestoreFrameMenu(GetParent(client), child); + MDI_UpdateFrameText(GetParent(client), client, NULL); } - - MDI_ChildActivate(parent, 0); - } - } - - MDI_MenuDeleteItem(parent, child); - - ci->nActiveChildren--; - - TRACE("child destroyed - %p\n",child); + MDI_ChildActivate(client, 0); + } + } + + for (i = 0; i < ci->nActiveChildren; i++) + { + if (ci->child[i] == child) + { + HWND *new_child = HeapAlloc(GetProcessHeap(), 0, (ci->nActiveChildren - 1) * sizeof(HWND)); + memcpy(new_child, ci->child, i * sizeof(HWND)); + if (i + 1 < ci->nActiveChildren) + memcpy(new_child + i, ci->child + i + 1, (ci->nActiveChildren - i - 1) * sizeof(HWND)); + HeapFree(GetProcessHeap(), 0, ci->child); + ci->child = new_child; + + ci->nActiveChildren--; + break; + } + } + + SendMessageW(client, WM_MDIREFRESHMENU, 0, 0); if (flagDestroy) { MDI_PostUpdate(GetParent(child), ci, SB_BOTH+1); DestroyWindow(child); } + + TRACE("child destroyed - %p\n", child); return 0; } @@ -816,100 +627,44 @@ /********************************************************************** * MDI_ChildActivate * - * Note: hWndChild is NULL when last child is being destroyed + * Called in response to WM_CHILDACTIVATE, or when last MDI child + * is being deactivated. */ static LONG MDI_ChildActivate( HWND client, HWND child ) { - MDICLIENTINFO *clientInfo = get_client_info( client ); - HWND prevActiveWnd = clientInfo->hwndActiveChild; + MDICLIENTINFO *clientInfo; + HWND prevActiveWnd, frame; BOOL isActiveFrameWnd; - if (child && (!IsWindowEnabled( child ))) return 0; - - /* Don't activate if it is already active. Might happen - since ShowWindow DOES activate MDI children */ + clientInfo = get_client_info( client ); + if (clientInfo->hwndActiveChild == child) return 0; TRACE("%p\n", child); - isActiveFrameWnd = (GetActiveWindow() == GetParent(client)); + frame = GetParent(client); + isActiveFrameWnd = (GetActiveWindow() == frame); + prevActiveWnd = clientInfo->hwndActiveChild; /* deactivate prev. active child */ if(prevActiveWnd) { - SetWindowLongA( prevActiveWnd, GWL_STYLE, - GetWindowLongA( prevActiveWnd, GWL_STYLE ) | WS_SYSMENU ); - SendMessageA( prevActiveWnd, WM_NCACTIVATE, FALSE, 0L ); - SendMessageA( prevActiveWnd, WM_MDIACTIVATE, (WPARAM)prevActiveWnd, (LPARAM)child); - /* uncheck menu item */ - if( clientInfo->hWindowMenu ) - { - UINT prevID = GetWindowLongA( prevActiveWnd, GWL_ID ); - - if (prevID - clientInfo->idFirstChild < MDI_MOREWINDOWSLIMIT) - CheckMenuItem( clientInfo->hWindowMenu, prevID, 0); - else - CheckMenuItem( clientInfo->hWindowMenu, - clientInfo->idFirstChild + MDI_MOREWINDOWSLIMIT - 1, 0); - } - } - - /* set appearance */ - if (clientInfo->hwndChildMaximized && clientInfo->hwndChildMaximized != child) - { - INT cmd = SW_SHOWNORMAL; - - if( child ) - { - UINT state = GetMenuState(GetSystemMenu(child, FALSE), SC_MAXIMIZE, MF_BYCOMMAND); - if (state != 0xFFFFFFFF && (state & (MF_DISABLED | MF_GRAYED))) - SendMessageW(clientInfo->hwndChildMaximized, WM_SYSCOMMAND, SC_RESTORE, 0); - else - cmd = SW_SHOWMAXIMIZED; - - clientInfo->hwndActiveChild = child; - } - - ShowWindow( clientInfo->hwndActiveChild, cmd ); - } - + SendMessageW( prevActiveWnd, WM_NCACTIVATE, FALSE, 0L ); + SendMessageW( prevActiveWnd, WM_MDIACTIVATE, (WPARAM)prevActiveWnd, (LPARAM)child); + } + + MDI_SwitchActiveChild( clientInfo, child, FALSE ); clientInfo->hwndActiveChild = child; - /* check if we have any children left */ - if( !child ) - { - if( isActiveFrameWnd ) - SetFocus( client ); - return 0; - } - - /* check menu item */ - if( clientInfo->hWindowMenu ) - { - UINT id = GetWindowLongA( child, GWL_ID ); - /* The window to be activated must be displayed in the "Windows" menu */ - if (id >= clientInfo->idFirstChild + MDI_MOREWINDOWSLIMIT) - { - MDI_SwapMenuItems( GetParent(child), - id, clientInfo->idFirstChild + MDI_MOREWINDOWSLIMIT - 1); - id = clientInfo->idFirstChild + MDI_MOREWINDOWSLIMIT - 1; - MDI_MenuModifyItem( GetParent(child), child ); - } - - CheckMenuItem(clientInfo->hWindowMenu, id, MF_CHECKED); - } - /* bring active child to the top */ - SetWindowPos( child, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); + MDI_RefreshMenu(clientInfo); if( isActiveFrameWnd ) { - SendMessageA( child, WM_NCACTIVATE, TRUE, 0L); - if( GetFocus() == client ) - SendMessageA( client, WM_SETFOCUS, (WPARAM)client, 0L ); - else - SetFocus( client ); - } - SendMessageA( child, WM_MDIACTIVATE, (WPARAM)prevActiveWnd, (LPARAM)child ); + SendMessageW( child, WM_NCACTIVATE, TRUE, 0L); + SetFocus( client ); + } + + SendMessageW( child, WM_MDIACTIVATE, (WPARAM)prevActiveWnd, (LPARAM)child ); return TRUE; } @@ -922,7 +677,7 @@ { HDC hDCSrc = CreateCompatibleDC(0); HDC hDCDest = CreateCompatibleDC(hDCSrc); - HBITMAP hbClose = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE) ); + HBITMAP hbClose = LoadBitmapW(0, MAKEINTRESOURCEW(OBM_OLD_CLOSE) ); HBITMAP hbCopy; HBITMAP hobjSrc, hobjDest; @@ -949,9 +704,6 @@ return hbCopy; } - - - /********************************************************************** * MDICascade */ @@ -961,11 +713,8 @@ BOOL has_icons = FALSE; int i, total; -DbgPrint("MDICascade\n"); - - if (ci->hwndChildMaximized) - SendMessageA( client, WM_MDIRESTORE, - (WPARAM)ci->hwndChildMaximized, 0); + if (IsZoomed(ci->hwndActiveChild)) + SendMessageW(client, WM_MDIRESTORE, (WPARAM)ci->hwndActiveChild, 0); if (ci->nActiveChildren == 0) return 0; @@ -997,7 +746,7 @@ TRACE("move %p to (%ld,%ld) size [%ld,%ld]\n", win_array[i], pos[0].x, pos[0].y, pos[1].x, pos[1].y); - MDI_CalcDefaultChildPos(client, n++, pos, delta); + MDI_CalcDefaultChildPos(client, n++, pos, delta, NULL); SetWindowPos( win_array[i], 0, pos[0].x, pos[0].y, pos[1].x, pos[1].y, SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER); } @@ -1017,10 +766,8 @@ int i, total; BOOL has_icons = FALSE; -DbgPrint("MDITile\n"); - - if (ci->hwndChildMaximized) - SendMessageA( client, WM_MDIRESTORE, (WPARAM)ci->hwndChildMaximized, 0); + if (IsZoomed(ci->hwndActiveChild)) + SendMessageW(client, WM_MDIRESTORE, (WPARAM)ci->hwndActiveChild, 0); if (ci->nActiveChildren == 0) return; @@ -1131,11 +878,11 @@ (LPCWSTR)HBMMENU_MBAR_CLOSE : (LPCWSTR)HBMMENU_MBAR_CLOSE_D ); /* The system menu is replaced by the child icon */ - hIcon = (HICON)GetClassLongW(hChild, GCL_HICONSM); + hIcon = (HICON)GetClassLongPtrW(hChild, GCLP_HICONSM); if (!hIcon) - hIcon = (HICON)GetClassLongW(hChild, GCL_HICON); + hIcon = (HICON)GetClassLongPtrW(hChild, GCLP_HICON); if (!hIcon) - hIcon = LoadIconW(NULL, IDI_APPLICATION); + hIcon = LoadImageW(0, MAKEINTRESOURCEW(IDI_WINLOGO), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR); if (hIcon) { HDC hMemDC; @@ -1193,6 +940,9 @@ TRACE("frame %p,child %p,nIt=%d,iId=%d\n",frame,hChild,nItems,iId); + if( !menu ) return 0; + + /* if there is no system buttons then nothing to do */ if(!(iId == SC_RESTORE || iId == SC_CLOSE) ) return 0; @@ -1202,7 +952,7 @@ */ memset(&menuInfo, 0, sizeof(menuInfo)); menuInfo.cbSize = sizeof(menuInfo); - menuInfo.fMask = MIIM_DATA | MIIM_TYPE | MIIM_BITMAP; + menuInfo.fMask = MIIM_DATA | MIIM_TYPE; GetMenuItemInfoW(menu, 0, @@ -1211,15 +961,22 @@ RemoveMenu(menu,0,MF_BYPOSITION); + if ( (menuInfo.fType & MFT_BITMAP) && + (menuInfo.dwTypeData != 0) && + (menuInfo.dwTypeData != (LPWSTR)hBmpClose) ) + { + DeleteObject(menuInfo.dwTypeData); + } + if ( menuInfo.hbmpItem != 0 ) - DeleteObject(menuInfo.hbmpItem); - + DeleteObject(menuInfo.hbmpItem); + /* close */ - DeleteMenu(menu,GetMenuItemCount(menu) - 1,MF_BYPOSITION); + DeleteMenu(menu, SC_CLOSE, MF_BYCOMMAND); /* restore */ - DeleteMenu(menu,GetMenuItemCount(menu) - 1,MF_BYPOSITION); + DeleteMenu(menu, SC_RESTORE, MF_BYCOMMAND); /* minimize */ - DeleteMenu(menu,GetMenuItemCount(menu) - 1,MF_BYPOSITION); + DeleteMenu(menu, SC_MINIMIZE, MF_BYCOMMAND); DrawMenuBar(frame); @@ -1234,13 +991,12 @@ * * Note: lpTitle can be NULL */ -static void MDI_UpdateFrameText( HWND frame, HWND hClient, - BOOL repaint, LPCWSTR lpTitle ) +static void MDI_UpdateFrameText( HWND frame, HWND hClient, LPCWSTR lpTitle ) { WCHAR lpBuffer[MDI_MAXTITLELENGTH+1]; MDICLIENTINFO *ci = get_client_info( hClient ); - TRACE("repaint %i, frameText %s\n", repaint, debugstr_w(lpTitle)); + TRACE("frameText %s\n", debugstr_w(lpTitle)); if (!ci) return; @@ -1253,14 +1009,14 @@ /* store new "default" title if lpTitle is not NULL */ if (lpTitle) { - if (ci->frameTitle) HeapFree( GetProcessHeap(), 0, ci->frameTitle ); + HeapFree( GetProcessHeap(), 0, ci->frameTitle ); if ((ci->frameTitle = HeapAlloc( GetProcessHeap(), 0, (strlenW(lpTitle)+1)*sizeof(WCHAR)))) strcpyW( ci->frameTitle, lpTitle ); } if (ci->frameTitle) { - if (ci->hwndChildMaximized) + if (IsZoomed(ci->hwndActiveChild) && IsWindowVisible(ci->hwndActiveChild)) { /* combine frame title and child title if possible */ @@ -1273,7 +1029,7 @@ if( i_frame_text_length + 6 < MDI_MAXTITLELENGTH ) { strcatW( lpBuffer, lpBracket ); - if (GetWindowTextW( ci->hwndChildMaximized, lpBuffer + i_frame_text_length + 4, + if (GetWindowTextW( ci->hwndActiveChild, lpBuffer + i_frame_text_length + 4, MDI_MAXTITLELENGTH - i_frame_text_length - 5 )) strcatW( lpBuffer, lpBracket2 ); else @@ -1289,9 +1045,6 @@ lpBuffer[0] = '\0'; DefWindowProcW( frame, WM_SETTEXT, 0, (LPARAM)lpBuffer ); - if( repaint == MDI_REPAINTFRAME) - SetWindowPos( frame, 0,0,0,0,0, SWP_FRAMECHANGED | - SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER ); } @@ -1306,11 +1059,16 @@ { MDICLIENTINFO *ci = NULL; - if (WM_NCCREATE != message - && NULL == (ci = get_client_info(hwnd))) +// TRACE("%p %04x (%s) %08x %08lx\n", hwnd, message, SPY_GetMsgName(message, hwnd), wParam, lParam); + + if (WM_NCCREATE != message && NULL == (ci = get_client_info(hwnd))) { return 0; } + +#ifndef __REACTOS__ + if (!(ci = get_client_info( hwnd ))) return 0; +#endif switch (message) { @@ -1324,14 +1082,14 @@ case WM_CREATE: { - RECT rect; /* Since we are using only cs->lpCreateParams, we can safely * cast to LPCREATESTRUCTA here */ LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam; #ifndef __REACTOS__ WND *wndPtr = WIN_GetPtr( hwnd ); + + wndPtr->flags |= WIN_ISMDICLIENT; #endif - /* Translation layer doesn't know what's in the cs->lpCreateParams * so we have to keep track of what environment we're in. */ @@ -1339,7 +1097,7 @@ if( wndPtr->flags & WIN_ISWIN32 ) #endif { -#define ccs ((LPCLIENTCREATESTRUCT)cs->lpCreateParams) +#define ccs ((LPCLIENTCREATESTRUCT) cs->lpCreateParams) ci->hWindowMenu = ccs->hWindowMenu; ci->idFirstChild = ccs->idFirstChild; #undef ccs @@ -1353,42 +1111,30 @@ } WIN_ReleasePtr( wndPtr ); #endif - - ci->hwndChildMaximized = 0; + ci->child = NULL; ci->nActiveChildren = 0; ci->nTotalCreated = 0; ci->frameTitle = NULL; ci->mdiFlags = 0; - SetWindowLongW( hwnd, GWL_STYLE, GetWindowLongW(hwnd,GWL_STYLE) | WS_CLIPCHILDREN ); + ci->hFrameMenu = GetMenu(cs->hwndParent); if (!hBmpClose) hBmpClose = CreateMDIMenuBitmap(); - if (ci->hWindowMenu != 0) - AppendMenuW( ci->hWindowMenu, MF_SEPARATOR, 0, NULL ); - - GetClientRect( GetParent(hwnd), &rect); - MoveWindow( hwnd, 0, 0, rect.right, rect.bottom, FALSE ); - - MDI_UpdateFrameText( GetParent(hwnd), hwnd, MDI_NOFRAMEREPAINT, NULL); - - TRACE("Client created - hwnd = %p, idFirst = %u\n", hwnd, ci->idFirstChild ); + TRACE("Client created: hwnd %p, Window menu %p, idFirst = %04x\n", + hwnd, ci->hWindowMenu, ci->idFirstChild ); return 0; } case WM_DESTROY: { - INT nItems; - if( ci->hwndChildMaximized ) - MDI_RestoreFrameMenu( GetParent(hwnd), ci->hwndChildMaximized); - if((ci->hWindowMenu != 0) && - (nItems = GetMenuItemCount(ci->hWindowMenu)) > 0) - { - ci->idFirstChild = nItems - 1; - ci->nActiveChildren++; /* to delete a separator */ - while( ci->nActiveChildren-- ) - DeleteMenu(ci->hWindowMenu,MF_BYPOSITION,ci->idFirstChild--); - } - if (ci->frameTitle) HeapFree( GetProcessHeap(), 0, ci->frameTitle ); + if( IsZoomed(ci->hwndActiveChild) ) + MDI_RestoreFrameMenu(GetParent(hwnd), ci->hwndActiveChild); + + ci->nActiveChildren = 0; + MDI_RefreshMenu(ci); + + HeapFree( GetProcessHeap(), 0, ci->child ); + HeapFree( GetProcessHeap(), 0, ci->frameTitle ); #ifdef __REACTOS__ HeapFree( GetProcessHeap(), 0, ci ); SetWindowLongPtrW( hwnd, 0, 0 ); @@ -1397,16 +1143,45 @@ } case WM_MDIACTIVATE: - if( ci->hwndActiveChild != (HWND)wParam ) - SetWindowPos((HWND)wParam, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE); + { + MDI_SwitchActiveChild( ci, (HWND)wParam, TRUE ); return 0; + } case WM_MDICASCADE: return MDICascade(hwnd, ci); case WM_MDICREATE: if (lParam) - return (LRESULT)MDICreateChild( hwnd, ci, (MDICREATESTRUCTA *)lParam, unicode ); + { + HWND child; + + if (unicode) + { + MDICREATESTRUCTW *csW = (MDICREATESTRUCTW *)lParam; + child = CreateWindowExW(WS_EX_MDICHILD, csW->szClass, + csW->szTitle, csW->style, + csW->x, csW->y, csW->cx, csW->cy, + hwnd, 0, csW->hOwner, + (LPVOID)csW->lParam); + } + else + { + MDICREATESTRUCTA *csA = (MDICREATESTRUCTA *)lParam; + child = CreateWindowExA(WS_EX_MDICHILD, csA->szClass, + csA->szTitle, csA->style, + csA->x, csA->y, csA->cx, csA->cy, + hwnd, 0, csA->hOwner, + (LPVOID)csA->lParam); + } + + if (IsZoomed(ci->hwndActiveChild)) + { + MDI_AugmentFrameMenu(GetParent(hwnd), child); + MDI_UpdateFrameText(GetParent(hwnd), hwnd, NULL); + } + return (LRESULT)child; + } return 0; case WM_MDIDESTROY: @@ -1415,9 +1190,8 @@ #else return MDIDestroyChild( hwnd, ci, (HWND)wParam, TRUE ); #endif - case WM_MDIGETACTIVE: - if (lParam) *(BOOL *)lParam = (ci->hwndChildMaximized != 0); + if (lParam) *(BOOL *)lParam = IsZoomed(ci->hwndActiveChild); return (LRESULT)ci->hwndActiveChild; case WM_MDIICONARRANGE: @@ -1432,12 +1206,15 @@ return 0; case WM_MDINEXT: /* lParam != 0 means previous window */ + { #ifndef __REACTOS__ - MDI_SwitchActiveChild( hwnd, WIN_GetFullHandle( (HWND)wParam ), !lParam ); + HWND next = MDI_GetWindow( ci, WIN_GetFullHandle( (HWND)wParam ), !lParam, 0 ); #else - MDI_SwitchActiveChild( hwnd, (HWND)wParam, !lParam ); + HWND next = MDI_GetWindow( ci, (HWND)wParam, !lParam, 0 ); #endif + MDI_SwitchActiveChild( ci, next, TRUE ); break; + } case WM_MDIRESTORE: SendMessageW( (HWND)wParam, WM_SYSCOMMAND, SC_RESTORE, 0); @@ -1447,7 +1224,7 @@ return MDISetMenu( hwnd, (HMENU)wParam, (HMENU)lParam ); case WM_MDIREFRESHMENU: - return MDIRefreshMenu( hwnd, (HMENU)wParam, (HMENU)lParam ); + return MDI_RefreshMenu( ci ); case WM_MDITILE: ci->mdiFlags |= MDIF_NEEDUPDATE; @@ -1474,8 +1251,25 @@ break; case WM_PARENTNOTIFY: - if (LOWORD(wParam) == WM_LBUTTONDOWN) - { + switch (LOWORD(wParam)) + { + case WM_CREATE: + if (GetWindowLongW((HWND)lParam, GWL_EXSTYLE) & WS_EX_MDICHILD) + { + ci->nTotalCreated++; + ci->nActiveChildren++; + + if (!ci->child) + ci->child = HeapAlloc(GetProcessHeap(), 0, sizeof(HWND)); + else + ci->child = HeapReAlloc(GetProcessHeap(), 0, ci->child, sizeof(HWND) * ci->nActiveChildren); + + ci->child[ci->nActiveChildren - 1] = (HWND)lParam; + } + break; + + case WM_LBUTTONDOWN: + { HWND child; POINT pt; pt.x = (short)LOWORD(lParam); @@ -1486,11 +1280,14 @@ if( child && child != hwnd && child != ci->hwndActiveChild ) SetWindowPos(child, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE ); + break; + } } return 0; case WM_SIZE: - if( IsWindow(ci->hwndChildMaximized) ) + if( IsWindow(ci->hwndActiveChild) && IsZoomed(ci->hwndActiveChild) && + (GetWindowLongW(ci->hwndActiveChild, GWL_STYLE) & WS_VISIBLE) ) { RECT rect; @@ -1499,9 +1296,9 @@ rect.right = LOWORD(lParam); rect.bottom = HIWORD(lParam); - AdjustWindowRectEx(&rect, GetWindowLongA(ci->hwndChildMaximized,GWL_STYLE), - 0, GetWindowLongA(ci->hwndChildMaximized,GWL_EXSTYLE) ); - MoveWindow(ci->hwndChildMaximized, rect.left, rect.top, + AdjustWindowRectEx(&rect, GetWindowLongA(ci->hwndActiveChild, GWL_STYLE), + 0, GetWindowLongA(ci->hwndActiveChild, GWL_EXSTYLE) ); + MoveWindow(ci->hwndActiveChild, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, 1); } else @@ -1540,38 +1337,6 @@ return MDIClientWndProc_common( hwnd, message, wParam, lParam, TRUE ); } -#ifndef __REACTOS__ -/*********************************************************************** - * DefFrameProc (USER.445) - */ -LRESULT WINAPI DefFrameProc16( HWND16 hwnd, HWND16 hwndMDIClient, - UINT16 message, WPARAM16 wParam, LPARAM lParam ) -{ - switch (message) - { - case WM_SETTEXT: - lParam = (LPARAM)MapSL(lParam); - /* fall through */ - case WM_COMMAND: - case WM_NCACTIVATE: - case WM_SETFOCUS: - case WM_SIZE: - return DefFrameProcA( WIN_Handle32(hwnd), WIN_Handle32(hwndMDIClient), - message, wParam, lParam ); - - case WM_NEXTMENU: - { - MDINEXTMENU next_menu; - DefFrameProcW( WIN_Handle32(hwnd), WIN_Handle32(hwndMDIClient), - message, wParam, (LPARAM)&next_menu ); - return MAKELONG( HMENU_16(next_menu.hmenuNext), HWND_16(next_menu.hwndNext) ); - } - default: - return DefWindowProc16(hwnd, message, wParam, lParam); - } -} -#endif - /*********************************************************************** * DefFrameProcA (USER32.@) */ @@ -1587,7 +1352,7 @@ DWORD len = MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, NULL, 0 ); LPWSTR text = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ); MultiByteToWideChar( CP_ACP, 0, (LPSTR)lParam, -1, text, len ); - MDI_UpdateFrameText(hwnd, hwndMDIClient, MDI_REPAINTFRAME, text ); + MDI_UpdateFrameText( hwnd, hwndMDIClient, text ); HeapFree( GetProcessHeap(), 0, text ); } return 1; /* success. FIXME: check text length */ @@ -1611,6 +1376,8 @@ UINT message, WPARAM wParam, LPARAM lParam) { MDICLIENTINFO *ci = get_client_info( hwndMDIClient ); + +// TRACE("%p %p %04x (%s) %08x %08lx\n", hwnd, hwndMDIClient, message, SPY_GetMsgName(message, hwnd), wParam, lParam); if (ci) { @@ -1623,7 +1390,7 @@ if (id < ci->idFirstChild || id >= ci->idFirstChild + ci->nActiveChildren) { if( (id - 0xf000) & 0xf00f ) break; - if( !ci->hwndChildMaximized ) break; + if( !IsZoomed(ci->hwndActiveChild) ) break; switch( id ) { case SC_CLOSE: @@ -1635,7 +1402,7 @@ case SC_NEXTWINDOW: case SC_PREVWINDOW: case SC_RESTORE: - return SendMessageW( ci->hwndChildMaximized, WM_SYSCOMMAND, + return SendMessageW( ci->hwndActiveChild, WM_SYSCOMMAND, wParam, lParam); } } @@ -1647,7 +1414,7 @@ childHwnd = MDI_MoreWindowsDialog(hwndMDIClient); else /* User chose one of the windows listed in the "Windows" menu */ - childHwnd = MDI_GetChildByID(hwndMDIClient,id); + childHwnd = MDI_GetChildByID(hwndMDIClient, id, ci); if( childHwnd ) SendMessageW( hwndMDIClient, WM_MDIACTIVATE, (WPARAM)childHwnd, 0 ); @@ -1660,7 +1427,7 @@ break; case WM_SETTEXT: - MDI_UpdateFrameText(hwnd, hwndMDIClient, MDI_REPAINTFRAME, (LPWSTR)lParam ); + MDI_UpdateFrameText( hwnd, hwndMDIClient, (LPWSTR)lParam ); return 1; /* success. FIXME: check text length */ case WM_SETFOCUS: @@ -1673,27 +1440,24 @@ case WM_NEXTMENU: { -/* FIXME */ -#ifndef __REACTOS__ MDINEXTMENU *next_menu = (MDINEXTMENU *)lParam; - if (!IsIconic(hwnd) && ci->hwndActiveChild && !ci->hwndChildMaximized) + if (!IsIconic(hwnd) && ci->hwndActiveChild && !IsZoomed(ci->hwndActiveChild)) { /* control menu is between the frame system menu and * the first entry of menu bar */ - WND *wndPtr = WIN_GetPtr(hwnd); +// WND *wndPtr = WIN_GetPtr(hwnd); if( (wParam == VK_LEFT && GetMenu(hwnd) == next_menu->hmenuIn) || - (wParam == VK_RIGHT && GetSubMenu(wndPtr->hSysMenu, 0) == next_menu->hmenuIn) ) + (wParam == VK_RIGHT && GetSubMenu(GetMenu(hwnd), 0) == next_menu->hmenuIn) ) { - WIN_ReleasePtr(wndPtr); - wndPtr = WIN_GetPtr(ci->hwndActiveChild); - next_menu->hmenuNext = GetSubMenu(wndPtr->hSysMenu, 0); +// WIN_ReleasePtr(wndPtr); +// wndPtr = WIN_GetPtr(ci->hwndActiveChild); + next_menu->hmenuNext = GetSubMenu(GetMenu(ci->hwndActiveChild), 0); next_menu->hwndNext = ci->hwndActiveChild; } - WIN_ReleasePtr(wndPtr); +// WIN_ReleasePtr(wndPtr); } -#endif return 0; } } @@ -1702,49 +1466,6 @@ return DefWindowProcW( hwnd, message, wParam, lParam ); } - -#ifndef __REACTOS__ -/*********************************************************************** - * DefMDIChildProc (USER.447) - */ -LRESULT WINAPI DefMDIChildProc16( HWND16 hwnd, UINT16 message, - WPARAM16 wParam, LPARAM lParam ) -{ - switch (message) - { - case WM_SETTEXT: - return DefMDIChildProcA( WIN_Handle32(hwnd), message, wParam, (LPARAM)MapSL(lParam) ); - case WM_MENUCHAR: - case WM_CLOSE: - case WM_SETFOCUS: - case WM_CHILDACTIVATE: - case WM_SYSCOMMAND: - case WM_SETVISIBLE: - case WM_SIZE: - case WM_SYSCHAR: - return DefMDIChildProcW( WIN_Handle32(hwnd), message, wParam, lParam ); - case WM_GETMINMAXINFO: - { - MINMAXINFO16 *mmi16 = (MINMAXINFO16 *)MapSL(lParam); - MINMAXINFO mmi; - STRUCT32_MINMAXINFO16to32( mmi16, &mmi ); - DefMDIChildProcW( WIN_Handle32(hwnd), message, wParam, (LPARAM)&mmi ); - STRUCT32_MINMAXINFO32to16( &mmi, mmi16 ); - return 0; - } - case WM_NEXTMENU: - { - MDINEXTMENU next_menu; - DefMDIChildProcW( WIN_Handle32(hwnd), message, wParam, (LPARAM)&next_menu ); - return MAKELONG( HMENU_16(next_menu.hmenuNext), HWND_16(next_menu.hwndNext) ); - } - default: - return DefWindowProc16(hwnd, message, wParam, lParam); - } -} -#endif - - /*********************************************************************** * DefMDIChildProcA (USER32.@) */ @@ -1754,6 +1475,7 @@ HWND client = GetParent(hwnd); MDICLIENTINFO *ci = get_client_info( client ); +// TRACE("%p %04x (%s) %08x %08lx\n", hwnd, message, SPY_GetMsgName(message, hwnd), wParam, lParam); #ifndef __REACTOS__ hwnd = WIN_GetFullHandle( hwnd ); #endif @@ -1763,9 +1485,8 @@ { case WM_SETTEXT: DefWindowProcA(hwnd, message, wParam, lParam); - MDI_MenuModifyItem( client, hwnd ); - if( ci->hwndChildMaximized == hwnd ) - MDI_UpdateFrameText( GetParent(client), client, MDI_REPAINTFRAME, NULL ); + if( ci->hwndActiveChild == hwnd && IsZoomed(ci->hwndActiveChild) ) + MDI_UpdateFrameText( GetParent(client), client, NULL ); return 1; /* success. FIXME: check text length */ case WM_GETMINMAXINFO: @@ -1774,13 +1495,14 @@ case WM_SETFOCUS: case WM_CHILDACTIVATE: case WM_SYSCOMMAND: + case WM_SHOWWINDOW: #ifndef __REACTOS__ case WM_SETVISIBLE: #endif - case WM_SHOWWINDOW: case WM_SIZE: case WM_NEXTMENU: case WM_SYSCHAR: + case WM_DESTROY: return DefMDIChildProcW( hwnd, message, wParam, lParam ); } return DefWindowProcA(hwnd, message, wParam, lParam); @@ -1796,18 +1518,18 @@ HWND client = GetParent(hwnd); MDICLIENTINFO *ci = get_client_info( client ); +// TRACE("%p %04x (%s) %08x %08lx\n", hwnd, message, SPY_GetMsgName(message, hwnd), wParam, lParam); #ifndef __REACTOS__ hwnd = WIN_GetFullHandle( hwnd ); -#endif +#endif if (!ci) return DefWindowProcW( hwnd, message, wParam, lParam ); switch (message) { case WM_SETTEXT: DefWindowProcW(hwnd, message, wParam, lParam); - MDI_MenuModifyItem( client, hwnd ); - if( ci->hwndChildMaximized == hwnd ) - MDI_UpdateFrameText( GetParent(client), client, MDI_REPAINTFRAME, NULL ); + if( ci->hwndActiveChild == hwnd && IsZoomed(ci->hwndActiveChild) ) + MDI_UpdateFrameText( GetParent(client), client, NULL ); return 1; /* success. FIXME: check text length */ case WM_GETMINMAXINFO: @@ -1821,10 +1543,6 @@ SendMessageW( client, WM_MDIDESTROY, (WPARAM)hwnd, 0 ); return 0; - case WM_SETFOCUS: - if (ci->hwndActiveChild != hwnd) MDI_ChildActivate( client, hwnd ); - break; - case WM_CHILDACTIVATE: MDI_ChildActivate( client, hwnd ); return 0; @@ -1833,18 +1551,15 @@ switch( wParam ) { case SC_MOVE: - if( ci->hwndChildMaximized == hwnd) return 0; + if( ci->hwndActiveChild == hwnd && IsZoomed(ci->hwndActiveChild)) + return 0; break; case SC_RESTORE: case SC_MINIMIZE: - SetWindowLongW( hwnd, GWL_STYLE, - GetWindowLongW( hwnd, GWL_STYLE ) | WS_SYSMENU ); break; case SC_MAXIMIZE: - if (ci->hwndChildMaximized == hwnd) + if (ci->hwndActiveChild == hwnd && IsZoomed(ci->hwndActiveChild)) return SendMessageW( GetParent(client), message, wParam, lParam); - SetWindowLongW( hwnd, GWL_STYLE, - GetWindowLongW( hwnd, GWL_STYLE ) & ~WS_SYSMENU ); break; case SC_NEXTWINDOW: SendMessageW( client, WM_MDINEXT, 0, 0); @@ -1855,73 +1570,48 @@ } break; + case WM_SHOWWINDOW: #ifndef __REACTOS__ case WM_SETVISIBLE: #endif - case WM_SHOWWINDOW: - if( ci->hwndChildMaximized) ci->mdiFlags &= ~MDIF_NEEDUPDATE; + if (IsZoomed(ci->hwndActiveChild)) ci->mdiFlags &= ~MDIF_NEEDUPDATE; else MDI_PostUpdate(client, ci, SB_BOTH+1); break; case WM_SIZE: - if( ci->hwndActiveChild == hwnd && wParam != SIZE_MAXIMIZED ) - { - ci->hwndChildMaximized = 0; - MDI_RestoreFrameMenu( GetParent(client), hwnd ); - MDI_UpdateFrameText( GetParent(client), client, MDI_REPAINTFRAME, NULL ); - } - - if( wParam == SIZE_MAXIMIZED ) - { - HWND hMaxChild = ci->hwndChildMaximized; - - if( hMaxChild == hwnd ) break; - if( hMaxChild) + if( hwnd == ci->hwndActiveChild ) + { + if( wParam == SIZE_MAXIMIZED ) { - SendMessageW( hMaxChild, WM_SETREDRAW, FALSE, 0 ); - MDI_RestoreFrameMenu( GetParent(client), hMaxChild ); - ShowWindow( hMaxChild, SW_SHOWNOACTIVATE ); - SendMessageW( hMaxChild, WM_SETREDRAW, TRUE, 0 ); + TRACE("maximizing child %p\n", hwnd ); + + MDI_AugmentFrameMenu( GetParent(client), hwnd ); } - TRACE("maximizing child %p\n", hwnd ); - - /* keep track of the maximized window. */ - ci->hwndChildMaximized = hwnd; /* !!! */ - - /* The maximized window should also be the active window */ - MDI_ChildActivate( client, hwnd ); - MDI_AugmentFrameMenu( GetParent(client), hwnd ); - MDI_UpdateFrameText( GetParent(client), client, MDI_REPAINTFRAME, NULL ); - } - - if( wParam == SIZE_MINIMIZED ) - { - HWND switchTo = MDI_GetWindow(ci, hwnd, TRUE, WS_MINIMIZE); - - if (switchTo) SendMessageW( switchTo, WM_CHILDACTIVATE, 0, 0); - } + else + MDI_RestoreFrameMenu( GetParent(client), hwnd ); + } + + MDI_UpdateFrameText( GetParent(client), client, NULL ); + MDI_RefreshMenu(ci); MDI_PostUpdate(client, ci, SB_BOTH+1); break; case WM_NEXTMENU: { -/* FIXME */ -#ifndef __REACTOS__ MDINEXTMENU *next_menu = (MDINEXTMENU *)lParam; HWND parent = GetParent(client); if( wParam == VK_LEFT ) /* switch to frame system menu */ { - WND *wndPtr = WIN_GetPtr( parent ); - next_menu->hmenuNext = GetSubMenu( wndPtr->hSysMenu, 0 ); - WIN_ReleasePtr( wndPtr ); +// WND *wndPtr = WIN_GetPtr( parent ); + next_menu->hmenuNext = GetSubMenu( GetMenu(parent), 0 ); +// WIN_ReleasePtr( wndPtr ); } if( wParam == VK_RIGHT ) /* to frame menu bar */ { next_menu->hmenuNext = GetMenu(parent); } next_menu->hwndNext = parent; -#endif return 0; } @@ -1931,6 +1621,11 @@ SendMessageW( hwnd, WM_SYSCOMMAND, (WPARAM)SC_KEYMENU, (DWORD)VK_SPACE); return 0; } + break; + + case WM_DESTROY: + /* Remove itself from the Window menu */ + MDI_RefreshMenu(ci); break; } return DefWindowProcW(hwnd, message, wParam, lParam); @@ -1955,29 +1650,13 @@ HINSTANCE hInstance, /* [in] Handle to application instance */ LPARAM lParam) /* [in] Application-defined value */ { - MDICLIENTINFO *pCi = get_client_info( hWndParent ); - MDICREATESTRUCTA cs; - - TRACE("(%s,%s,%ld,%d,%d,%d,%d,%p,%p,%ld)\n", + TRACE("(%s,%s,%08lx,%d,%d,%d,%d,%p,%p,%08lx)\n", debugstr_a(lpClassName),debugstr_a(lpWindowName),dwStyle,X,Y, nWidth,nHeight,hWndParent,hInstance,lParam); - if (!pCi) - { - ERR("bad hwnd for MDI-client: %p\n", hWndParent); - return 0; - } - cs.szClass=lpClassName; - cs.szTitle=lpWindowName; - cs.hOwner=hInstance; - cs.x=X; - cs.y=Y; - cs.cx=nWidth; - cs.cy=nHeight; - cs.style=dwStyle; - cs.lParam=lParam; - - return MDICreateChild(hWndParent, pCi, &cs, FALSE); + return CreateWindowExA(WS_EX_MDICHILD, lpClassName, lpWindowName, + dwStyle, X, Y, nWidth, nHeight, hWndParent, + 0, hInstance, (LPVOID)lParam); } /*********************************************************************** @@ -1999,29 +1678,13 @@ HINSTANCE hInstance, /* [in] Handle to application instance */ LPARAM lParam) /* [in] Application-defined value */ { - MDICLIENTINFO *pCi = get_client_info( hWndParent ); - MDICREATESTRUCTW cs; - - TRACE("(%s,%s,%ld,%d,%d,%d,%d,%p,%p,%ld)\n", + TRACE("(%s,%s,%08lx,%d,%d,%d,%d,%p,%p,%08lx)\n", debugstr_w(lpClassName), debugstr_w(lpWindowName), dwStyle, X, Y, nWidth, nHeight, hWndParent, hInstance, lParam); - if (!pCi) - { - ERR("bad hwnd for MDI-client: %p\n", hWndParent); - return 0; - } - cs.szClass = lpClassName; - cs.szTitle = lpWindowName; - cs.hOwner = hInstance; - cs.x = X; - cs.y = Y; - cs.cx = nWidth; - cs.cy = nHeight; - cs.style = dwStyle; - cs.lParam = lParam; - - return MDICreateChild(hWndParent, pCi, (MDICREATESTRUCTA *)&cs, TRUE); + return CreateWindowExW(WS_EX_MDICHILD, lpClassName, lpWindowName, + dwStyle, X, Y, nWidth, nHeight, hWndParent, + 0, hInstance, (LPVOID)lParam); } /********************************************************************** @@ -2072,24 +1735,26 @@ { SCROLLINFO info; RECT childRect, clientRect; -#ifndef __REACTOS__ HWND *list; -#else WINDOWINFO WindowInfo; - HWND hWndCurrent; -#endif - /* The rectangle returned by GetClientRect always has 0,0 as top left - * because it is in client coordinates. The rectangles returned by - * GetWindowRect are in screen coordinates to make this complicated. - * - * Apparently (in ReactOS at least) the rcClient returned by GetWindowInfo - * is in screen coordinates too. - */ GetClientRect( hwnd, &clientRect ); SetRectEmpty( &childRect ); -#ifndef __REACTOS__ + /* The rectangle returned by GetClientRect always has 0,0 as top left + * because it is in client coordinates. The rectangles returned by + * GetWindowRect are in screen coordinates to make this complicated. + * + * Apparently (in ReactOS at least) the rcClient returned by GetWindowInfo + * is in screen coordinates too. + */ + WindowInfo.cbSize = sizeof(WindowInfo); + if (!GetWindowInfo(hwnd, &WindowInfo)) + { + ERR("Can't get window info\n"); + return; + } + if ((list = WIN_ListChildren( hwnd ))) { int i; @@ -2104,71 +1769,37 @@ } if (style & WS_VISIBLE) { - WND *pWnd = WIN_FindWndPtr( list[i] ); - UnionRect( &childRect, &pWnd->rectWindow, &childRect ); - WIN_ReleaseWndPtr( pWnd ); + RECT rect; + GetWindowRect( list[i], &rect ); + OffsetRect(&rect, -WindowInfo.rcClient.left, + -WindowInfo.rcClient.top); + UnionRect( &childRect, &rect, &childRect ); } } HeapFree( GetProcessHeap(), 0, list ); } -#else - WindowInfo.cbSize = sizeof(WindowInfo); - if (!GetWindowInfo(hwnd, &WindowInfo)) - { - ERR("Can't get window info\n"); - return; - } - - hWndCurrent = GetWindow(hwnd, GW_CHILD); - while (hWndCurrent != NULL) - { - DWORD style = GetWindowLongW( hWndCurrent, GWL_STYLE ); - if (style & WS_MAXIMIZE) - { - ShowScrollBar( hwnd, SB_BOTH, FALSE ); - return; - } - if (style & WS_VISIBLE) - { - RECT WindowRect; - - GetWindowRect( hWndCurrent, &WindowRect ); - OffsetRect(&WindowRect, - -WindowInfo.rcClient.left, - -WindowInfo.rcClient.top); - UnionRect( &childRect, &WindowRect, &childRect ); - } - hWndCurrent = GetWindow(hWndCurrent, GW_HWNDNEXT); - } -#endif + MapWindowPoints( 0, hwnd, (POINT *)&childRect, 2 ); UnionRect( &childRect, &clientRect, &childRect ); /* set common info values */ info.cbSize = sizeof(info); - info.fMask = SIF_POS | SIF_RANGE | SIF_PAGE; - - /* set the specific scrollbars*/ - /* Note how we set nPos to 0 because we scroll the clients instead of - * the window, and we set nPage to 1 bigger than the clientRect because - * otherwise the scrollbar never disables. This causes a somewhat ugly - * effect though while scrolling. - */ + info.fMask = SIF_POS | SIF_RANGE; + + /* set the specific */ switch( scroll ) { case SB_BOTH: case SB_HORZ: info.nMin = childRect.left; - info.nMax = childRect.right; - info.nPos = 0; - info.nPage = 1 + clientRect.right - clientRect.left; + info.nMax = childRect.right - clientRect.right; + info.nPos = clientRect.left - childRect.left; SetScrollInfo(hwnd, SB_HORZ, &info, TRUE); if (scroll == SB_HORZ) break; /* fall through */ case SB_VERT: info.nMin = childRect.top; - info.nMax = childRect.bottom; - info.nPos = 0; - info.nPage = 1 + clientRect.bottom - clientRect.top; + info.nMax = childRect.bottom - clientRect.bottom; + info.nPos = clientRect.top - childRect.top; SetScrollInfo(hwnd, SB_VERT, &info, TRUE); break; } @@ -2310,32 +1941,15 @@ UINT i; MDICLIENTINFO *ci = get_client_info( (HWND)lParam ); HWND hListBox = GetDlgItem(hDlg, MDI_IDC_LISTBOX); - HWND *list, *sorted_list; - - if (!(list = WIN_ListChildren( (HWND)lParam ))) return TRUE; - if (!(sorted_list = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, - sizeof(HWND) * ci->nActiveChildren ))) - { - HeapFree( GetProcessHeap(), 0, list ); - return FALSE; - } - - /* Fill the list, sorted by id... */ - for (i = 0; list[i]; i++) - { - UINT id = GetWindowLongW( list[i], GWL_ID ) - ci->idFirstChild; - if (id < ci->nActiveChildren) sorted_list[id] = list[i]; - } - HeapFree( GetProcessHeap(), 0, list ); for (i = 0; i < ci->nActiveChildren; i++) { - WCHAR buffer[128]; - - if (!GetWindowTextW( sorted_list[i], buffer, sizeof(buffer)/sizeof(WCHAR) )) + WCHAR buffer[MDI_MAXTITLELENGTH]; + + if (!InternalGetWindowText( ci->child[i], buffer, sizeof(buffer)/sizeof(WCHAR) )) continue; SendMessageW(hListBox, LB_ADDSTRING, 0, (LPARAM)buffer ); - SendMessageW(hListBox, LB_SETITEMDATA, i, (LPARAM)sorted_list[i] ); + SendMessageW(hListBox, LB_SETITEMDATA, i, (LPARAM)ci->child[i] ); length = strlenW(buffer); /* FIXME: should use GetTextExtentPoint */ if (length > widest) widest = length; @@ -2396,7 +2010,7 @@ if (hRes == 0) return 0; - hDlgTmpl = LoadResource(User32Instance, hRes); + hDlgTmpl = LoadResource(User32Instance, hRes ); if (hDlgTmpl == 0) return 0; @@ -2407,31 +2021,6 @@ return 0; return (HWND) DialogBoxIndirectParamA(User32Instance, - (LPDLGTEMPLATE) template, + (const DLGTEMPLATE*) template, hwnd, MDI_MoreWindowsDlgProc, (LPARAM) hwnd); } - -/* - * - * MDI_SwapMenuItems - * - * Will swap the menu IDs for the given 2 positions. - * pos1 and pos2 are menu IDs - * - * - */ - -static void MDI_SwapMenuItems(HWND parent, UINT pos1, UINT pos2) -{ - HWND *list; - int i; - - if (!(list = WIN_ListChildren( parent ))) return; - for (i = 0; list[i]; i++) - { - UINT id = GetWindowLongW( list[i], GWL_ID ); - if (id == pos1) SetWindowLongW( list[i], GWL_ID, pos2 ); - else if (id == pos2) SetWindowLongW( list[i], GWL_ID, pos1 ); - } - HeapFree( GetProcessHeap(), 0, list ); -} Modified: trunk/reactos/dll/win32/user32/windows/window.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/user32/windows/w…
============================================================================== --- trunk/reactos/dll/win32/user32/windows/window.c (original) +++ trunk/reactos/dll/win32/user32/windows/window.c Mon Jul 3 08:33:29 2006 @@ -18,6 +18,7 @@ BOOL ControlsInitialized = FALSE; LRESULT DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active); +INT MDI_GetId(HWND hWndClient); /* FUNCTIONS *****************************************************************/ @@ -186,10 +187,7 @@ if (dwExStyle & WS_EX_MDICHILD) { - if (!IS_ATOM(lpClassName)) - RtlFreeUnicodeString(&ClassName); - return CreateMDIWindowA(lpClassName, lpWindowName, dwStyle, x, y, - nWidth, nHeight, hWndParent, hInstance, (LPARAM)lpParam); + if (!(dwStyle & WS_POPUP)) hMenu = (HMENU) MDI_GetId(hWndParent); } if (!RtlCreateUnicodeStringFromAsciiz(&WindowName, (PCSZ)lpWindowName)) @@ -221,7 +219,7 @@ nHeight, hWndParent, hMenu, - hInstance, + hInstance, lpParam, SW_SHOW, FALSE); @@ -262,6 +260,9 @@ UNICODE_STRING ClassName; WNDCLASSEXW wce; HANDLE Handle; +#if 0 + DbgPrint("[window] CreateWindowExA style %d, exstyle %d, parent %d\n", dwStyle, dwExStyle, hWndParent); +#endif /* Register built-in controls if not already done */ if (! ControlsInitialized) @@ -270,8 +271,9 @@ } if (dwExStyle & WS_EX_MDICHILD) - return CreateMDIWindowW(lpClassName, lpWindowName, dwStyle, x, y, - nWidth, nHeight, hWndParent, hInstance, (LPARAM)lpParam); + { + if (!(dwStyle & WS_POPUP)) hMenu = (HMENU) MDI_GetId(hWndParent); + } if (IS_ATOM(lpClassName)) { @@ -304,10 +306,14 @@ nHeight, hWndParent, hMenu, - hInstance, + hInstance, lpParam, SW_SHOW, TRUE); + +#if 0 + DbgPrint("[window] NtUserCreateWindowEx() == %d\n", Handle); +#endif return (HWND)Handle; } Modified: trunk/reactos/media/doc/README.WINE URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/media/doc/README.WINE?rev=…
============================================================================== --- trunk/reactos/media/doc/README.WINE (original) +++ trunk/reactos/media/doc/README.WINE Mon Jul 3 08:33:29 2006 @@ -132,7 +132,7 @@ reactos/dll/win32/user32/windows/defwnd.c # Forked reactos/dll/win32/user32/windows/draw.c # Forked at Wine-20020904 (uitools.c) - reactos/dll/win32/user32/windows/mdi.c # Out of sync + reactos/dll/win32/user32/windows/mdi.c # Synced at 20060703 reactos/dll/win32/user32/windows/menu.c # Forked reactos/dll/win32/user32/windows/messagebox.c # Forked reactos/dll/win32/user32/windows/rect.c # Forked (uitools.c) Modified: trunk/reactos/subsystems/win32/win32k/ntuser/window.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/window.c (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/window.c Mon Jul 3 08:33:29 2006 @@ -1411,6 +1411,7 @@ POINT Pos; SIZE Size; PW32THREADINFO ti = NULL; + #if 0 POINT MaxSize, MaxPos, MinTrack, MaxTrack; @@ -1419,6 +1420,7 @@ POINT MaxPos; #endif CREATESTRUCTW Cs; + MDICREATESTRUCTW mdi; CBT_CREATEWNDW CbtCreate; LRESULT Result; BOOL MenuChanged; @@ -1429,6 +1431,11 @@ ParentWindowHandle = PsGetWin32Thread()->Desktop->DesktopWindow; OwnerWindowHandle = NULL; + if ((!(dwStyle & WS_CHILD)) && (dwExStyle & WS_EX_MDICHILD)) + { + dwStyle |= WS_CHILD; // Forced Child! + } + if (hWndParent == HWND_MESSAGE) { /* @@ -1624,6 +1631,62 @@ else { RtlInitUnicodeString(&Window->WindowName, NULL); + } + + if (dwExStyle & WS_EX_MDICHILD) + { + PWINDOW_OBJECT top_child; + + /* lpParams of WM_[NC]CREATE is different for MDI children. + * MDICREATESTRUCT members have the originally passed values. + * + * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW + * have the same layout. + */ + mdi.szClass = (LPWSTR)ClassName; + mdi.szTitle = (LPWSTR)WindowName; + mdi.hOwner = hInstance; + mdi.x = x; + mdi.y = y; + mdi.cx = nWidth; + mdi.cy = nHeight; + mdi.style = dwStyle; + mdi.lParam = (LPARAM)lpParam; + + lpParam = (LPVOID)&mdi; + if (ParentWindow->Style & MDIS_ALLCHILDSTYLES) + { + if (dwStyle & WS_POPUP) + { + DPRINT1("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n"); + SetLastWin32Error(ERROR_INVALID_PARAMETER); + RETURN((HWND)0); + } + dwStyle |= (WS_CHILD | WS_CLIPSIBLINGS); + } + else + { + dwStyle &= ~WS_POPUP; +/* + (|| WS_CHILD) is done at the top. So~ Here is just a bit in a 32/64 bit word. +*/ + dwStyle |= (WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION | + WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX); + } + + top_child = ParentWindow->FirstChild; + + if (top_child) + { + /* Restore current maximized child */ + if((dwStyle & WS_VISIBLE) && (top_child->Style & WS_MAXIMIZE)) + { + DPRINT("Restoring current maximized child %p\n", top_child); + co_IntSendMessage( top_child->hSelf, WM_SETREDRAW, FALSE, 0 ); + co_WinPosShowWindow(top_child, SW_RESTORE); + co_IntSendMessage( top_child->hSelf, WM_SETREDRAW, TRUE, 0 ); + } + } } /* @@ -1636,19 +1699,11 @@ dwExStyle |= WS_EX_WINDOWEDGE; else dwExStyle &= ~WS_EX_WINDOWEDGE; - - /* Correct the window style. */ - if (!(dwStyle & WS_CHILD)) - { - dwStyle |= WS_CLIPSIBLINGS; - DPRINT("3: Style is now %lx\n", dwStyle); - if (!(dwStyle & WS_POPUP)) - { - dwStyle |= WS_CAPTION; - Window->Flags |= WINDOWOBJECT_NEED_SIZE; - DPRINT("4: Style is now %lx\n", dwStyle); - } - } +/* + These affect only the style loading into the WindowObject structure. +*/ + Window->ExStyle = dwExStyle; + Window->Style = dwStyle & ~WS_VISIBLE; /* create system menu */ if((dwStyle & WS_SYSMENU) && @@ -1661,6 +1716,23 @@ IntReleaseMenuObject(SystemMenu); } } + + /* Correct the window style. */ + if (!(Window->Style & WS_CHILD)) + { + Window->Style |= WS_CLIPSIBLINGS; + if (!(Window->Style & WS_POPUP)) + { + Window->Style |= WS_CAPTION; + Window->Flags |= WINDOWOBJECT_NEED_SIZE; + } + } + + if ((Window->ExStyle & WS_EX_DLGMODALFRAME) || + (Window->Style & (WS_DLGFRAME | WS_THICKFRAME))) + Window->ExStyle |= WS_EX_WINDOWEDGE; + else + Window->ExStyle &= ~WS_EX_WINDOWEDGE; /* Insert the window into the thread's window list. */ InsertTailList (&PsGetWin32Thread()->WindowListHead, &Window->ThreadListEntry); @@ -1676,9 +1748,6 @@ Pos.y = y; Size.cx = nWidth; Size.cy = nHeight; - - Window->ExStyle = dwExStyle; - Window->Style = dwStyle & ~WS_VISIBLE; /* call hook */ Cs.lpCreateParams = lpParam; @@ -1735,9 +1804,27 @@ Pos.x = rc.left; Pos.y = rc.top; } - - /* According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and - y is something else */ +/* + According to wine, the ShowMode is set to y if x == CW_USEDEFAULT(16) and + y is something else. and Quote! + */ + +/* Never believe Microsoft's documentation... CreateWindowEx doc says + * that if an overlapped window is created with WS_VISIBLE style bit + * set and the x parameter is set to CW_USEDEFAULT, the system ignores + * the y parameter. However, disassembling NT implementation (WIN32K.SYS) + * reveals that + * + * 1) not only it checks for CW_USEDEFAULT but also for CW_USEDEFAULT16 + * 2) it does not ignore the y parameter as the docs claim; instead, it + * uses it as second parameter to ShowWindow() unless y is either + * CW_USEDEFAULT or CW_USEDEFAULT16. + * + * The fact that we didn't do 2) caused bogus windows pop up when wine + * was running apps that were using this obscure feature. Example - + * calc.exe that comes with Win98 (only Win98, it's different from + * the one that comes with Win95 and NT) + */ if(y != CW_USEDEFAULT && y != CW_USEDEFAULT16) { dwShowMode = y; @@ -1766,20 +1853,51 @@ Pos.x = max(rc.left, 0); if(Pos.y > rc.top) Pos.y = max(rc.top, 0); - } + } } else { - /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */ - if(x == CW_USEDEFAULT || x == CW_USEDEFAULT16) - { - Pos.x = 0; - Pos.y = 0; - } - if(nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16) - { - Size.cx = 0; - Size.cy = 0; + if (dwExStyle & WS_EX_MDICHILD) + { + POINT mPos[2]; + RECT rect; + INT nstagger, total = 0, spacing = UserGetSystemMetrics(SM_CYCAPTION) + + UserGetSystemMetrics(SM_CYFRAME) -1; + PWINDOW_OBJECT Child; + + for (Child = ParentWindow->FirstChild; Child; Child = Child->NextSibling) + ++total; + + IntGetClientRect(ParentWindow, &rect); + + nstagger = (rect.bottom - rect.top)/(3 * spacing); + mPos[1].x = (rect.right - rect.left - nstagger * spacing); + mPos[1].y = (rect.bottom - rect.top - nstagger * spacing); + mPos[0].x = mPos[0].y = spacing * (total%(nstagger+1)); + + if (x == CW_USEDEFAULT || x == CW_USEDEFAULT16) + { + Pos.x = mPos[0].x; + Pos.y = mPos[0].y; + } + if (nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16 || !nWidth) + Size.cx = mPos[1].x; + if (nHeight == CW_USEDEFAULT || nHeight == CW_USEDEFAULT16 || !nHeight) + Size.cy = mPos[1].y; + } + else + { + /* if CW_USEDEFAULT(16) is set for non-overlapped windows, both values are set to zero) */ + if(x == CW_USEDEFAULT || x == CW_USEDEFAULT16) + { + Pos.x = 0; + Pos.y = 0; + } + if(nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16) + { + Size.cx = 0; + Size.cy = 0; + } } } @@ -1985,6 +2103,13 @@ WM_PARENTNOTIFY, MAKEWPARAM(WM_CREATE, Window->IDMenu), (LPARAM)Window->hSelf); + } + + if ((dwStyle & WS_VISIBLE) && (dwExStyle & WS_EX_MDICHILD)) + { + co_IntSendMessage(ParentWindow->hSelf, WM_MDIREFRESHMENU, 0, 0); + co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | + SWP_NOMOVE | SWP_NOSIZE); } if ((!hWndParent) && (!HasOwner))
18 years, 5 months
1
0
0
0
[ion] 22791: - NtQueryDirectoryFile: - Setup a buffer/MDL and the correct IRP flags so that that I/O manager can handle allocation, copy, free for us. - Setup the search pattern as an auxiliary buffer so that the I/O Mgr can track that one for us as well. - Update to use the correct sync semantics/routines. - Use deferred I/O completion. - Outline TODOs and workplan for iofunc.c
by ion@svn.reactos.org
Author: ion Date: Mon Jul 3 06:50:16 2006 New Revision: 22791 URL:
http://svn.reactos.org/svn/reactos?rev=22791&view=rev
Log: - NtQueryDirectoryFile: - Setup a buffer/MDL and the correct IRP flags so that that I/O manager can handle allocation, copy, free for us. - Setup the search pattern as an auxiliary buffer so that the I/O Mgr can track that one for us as well. - Update to use the correct sync semantics/routines. - Use deferred I/O completion. - Outline TODOs and workplan for iofunc.c Modified: trunk/reactos/ntoskrnl/io/iomgr/iofunc.c Modified: trunk/reactos/ntoskrnl/io/iomgr/iofunc.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/iofunc.c…
============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/iofunc.c (original) +++ trunk/reactos/ntoskrnl/io/iomgr/iofunc.c Mon Jul 3 06:50:16 2006 @@ -24,11 +24,17 @@ /// // // TODO: +// - Update to new semantics: // - Lock/Unlock <= DONE // - Query/Set Volume Info <= DONE // - Read/Write file <= DONE +// - QueryDirectoryFile <= DONE // - Query/Set File Info -// - QueryDirectoryFile +// - Add SEH to some places where it's missing (MDLs, etc) +// - Add a generic Cleanup/Exception Routine +// - Add another parameter to IopCleanupFailedIrp +// - Add support for Fast Dispatch I/O +// - Add support for some fast-paths when querying/setting data // /// @@ -533,16 +539,6 @@ /* Return the Length and Status. ReturnedLength is NOT optional */ *ReturnedLength = IoStatusBlock.Information; return Status; -} - -NTSTATUS -NTAPI -IopQueryDirectoryFileCompletion(IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, - IN PVOID Context) -{ - ExFreePool(Context); - return STATUS_SUCCESS; } /* PUBLIC FUNCTIONS **********************************************************/ @@ -1273,7 +1269,7 @@ NTSTATUS NTAPI NtQueryDirectoryFile(IN HANDLE FileHandle, - IN HANDLE PEvent OPTIONAL, + IN HANDLE EventHandle OPTIONAL, IN PIO_APC_ROUTINE ApcRoutine OPTIONAL, IN PVOID ApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, @@ -1286,55 +1282,73 @@ { PIRP Irp; PDEVICE_OBJECT DeviceObject; - PFILE_OBJECT FileObject = NULL; + PFILE_OBJECT FileObject; PIO_STACK_LOCATION StackPtr; KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); NTSTATUS Status = STATUS_SUCCESS; - BOOLEAN LocalEvent = FALSE; + BOOLEAN LockedForSynch = FALSE; PKEVENT Event = NULL; - PUNICODE_STRING SearchPattern = NULL; + PVOID AuxBuffer = NULL; + PMDL Mdl; + UNICODE_STRING CapturedFileName; + PUNICODE_STRING SearchPattern; PAGED_CODE(); - /* Validate User-Mode Buffers */ + /* Check if we came from user mode */ if(PreviousMode != KernelMode) { + /* Enter SEH for probing */ _SEH_TRY { + /* Probe the I/O Status Block */ ProbeForWrite(IoStatusBlock, sizeof(IO_STATUS_BLOCK), sizeof(ULONG)); - ProbeForWrite(FileInformation, - Length, - sizeof(ULONG)); + + /* Probe the file information */ + ProbeForWrite(FileInformation, Length, sizeof(ULONG)); + + /* Check if we have a file name */ if (FileName) { - UNICODE_STRING CapturedFileName; - + /* Capture it */ CapturedFileName = ProbeForReadUnicodeString(FileName); - ProbeForRead(CapturedFileName.Buffer, - CapturedFileName.MaximumLength, - 1); - SearchPattern = ExAllocatePool(NonPagedPool, CapturedFileName.Length + sizeof(WCHAR) + sizeof(UNICODE_STRING)); - if (SearchPattern == NULL) + if (CapturedFileName.Length) { - Status = STATUS_INSUFFICIENT_RESOURCES; - _SEH_LEAVE; + /* Probe its buffer */ + ProbeForRead(CapturedFileName.Buffer, + CapturedFileName.Length, + 1); } - SearchPattern->Buffer = (PWCHAR)((ULONG_PTR)SearchPattern + sizeof(UNICODE_STRING)); - SearchPattern->MaximumLength = CapturedFileName.Length + sizeof(WCHAR); - RtlCopyUnicodeString(SearchPattern, &CapturedFileName); + + /* Allocate the auxiliary buffer */ + AuxBuffer = ExAllocatePoolWithTag(NonPagedPool, + CapturedFileName.Length + + sizeof(UNICODE_STRING), + TAG_SYSB); + RtlCopyMemory((PVOID)((ULONG_PTR)AuxBuffer + + sizeof(UNICODE_STRING)), + CapturedFileName.Buffer, + CapturedFileName.Length); + + /* Setup the search pattern */ + SearchPattern = (PUNICODE_STRING)AuxBuffer; + SearchPattern->Buffer = (PWCHAR)((ULONG_PTR)AuxBuffer + + sizeof(UNICODE_STRING)); + SearchPattern->Length = CapturedFileName.Length; + SearchPattern->MaximumLength = CapturedFileName.Length; } } _SEH_HANDLE { + /* Get exception code and free the buffer */ + if (AuxBuffer) ExFreePool(AuxBuffer); Status = _SEH_GetExceptionCode(); } _SEH_END; - if(!NT_SUCCESS(Status)) - { - goto Cleanup; - } + /* Return status on failure */ + if (!NT_SUCCESS(Status)) return Status; } /* Get File Object */ @@ -1344,53 +1358,53 @@ PreviousMode, (PVOID *)&FileObject, NULL); - if (!NT_SUCCESS(Status)) goto Cleanup; - - /* Get Event Object */ - if (PEvent) - { - Status = ObReferenceObjectByHandle(PEvent, + if (!NT_SUCCESS(Status)) + { + /* Fail */ + if (AuxBuffer) ExFreePool(AuxBuffer); + return Status; + } + + /* Check if we have an even handle */ + if (EventHandle) + { + /* Get its pointer */ + Status = ObReferenceObjectByHandle(EventHandle, EVENT_MODIFY_STATE, ExEventObjectType, PreviousMode, (PVOID *)&Event, NULL); - if (!NT_SUCCESS(Status)) - { - goto Cleanup; - } - + if (!NT_SUCCESS(Status)) + { + /* Fail */ + ObDereferenceObject(FileObject); + return Status; + } + + /* Clear it */ KeClearEvent(Event); } - /* Check if this is a direct open or not */ - if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN) - { - DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject); - } - else - { - DeviceObject = IoGetRelatedDeviceObject(FileObject); - } - - /* Check if we should use Sync IO or not */ + /* Check if this is a file that was opened for Synch I/O */ if (FileObject->Flags & FO_SYNCHRONOUS_IO) { - /* Use File Object event */ - KeClearEvent(&FileObject->Event); - } - else - { - LocalEvent = TRUE; - } + /* Lock it */ + IopLockFileObject(FileObject); + + /* Remember to unlock later */ + LockedForSynch = TRUE; + } + + /* Get the device object */ + DeviceObject = IoGetRelatedDeviceObject(FileObject); + + /* Clear the File Object's event */ + KeClearEvent(&FileObject->Event); /* Allocate the IRP */ - Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); - if (!Irp) - { - Status = STATUS_INSUFFICIENT_RESOURCES; - goto Cleanup; - } + Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE); + if (!Irp) return IopCleanupFailedIrp(FileObject, EventHandle); /* Set up the IRP */ Irp->RequestorMode = PreviousMode; @@ -1398,9 +1412,38 @@ Irp->UserEvent = Event; Irp->Tail.Overlay.Thread = PsGetCurrentThread(); Irp->Tail.Overlay.OriginalFileObject = FileObject; - Irp->UserBuffer = FileInformation; Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; + Irp->MdlAddress = NULL; + Irp->Tail.Overlay.AuxiliaryBuffer = AuxBuffer; + Irp->AssociatedIrp.SystemBuffer = NULL; + + /* Check if this is buffered I/O */ + if (DeviceObject->Flags & DO_BUFFERED_IO) + { + /* Allocate a buffer */ + Irp->AssociatedIrp.SystemBuffer = + ExAllocatePoolWithTag(NonPagedPool, + Length, + TAG_SYSB); + + /* Set the buffer and flags */ + Irp->UserBuffer = FileInformation; + Irp->Flags = (IRP_BUFFERED_IO | + IRP_DEALLOCATE_BUFFER | + IRP_INPUT_OPERATION); + } + else if (DeviceObject->Flags & DO_DIRECT_IO) + { + /* Allocate an MDL */ + Mdl = IoAllocateMdl(FileInformation, Length, FALSE, TRUE, Irp); + MmProbeAndLockPages(Mdl, PreviousMode, IoWriteAccess); + } + else + { + /* No allocation flags, and use the buffer directly */ + Irp->UserBuffer = FileInformation; + } /* Set up Stack Data */ StackPtr = IoGetNextIrpStackLocation(Irp); @@ -1409,48 +1452,26 @@ StackPtr->MinorFunction = IRP_MN_QUERY_DIRECTORY; /* Set Parameters */ - StackPtr->Parameters.QueryDirectory.FileInformationClass = FileInformationClass; - StackPtr->Parameters.QueryDirectory.FileName = SearchPattern ? SearchPattern : FileName; + StackPtr->Parameters.QueryDirectory.FileInformationClass = + FileInformationClass; + StackPtr->Parameters.QueryDirectory.FileName = AuxBuffer; StackPtr->Parameters.QueryDirectory.FileIndex = 0; StackPtr->Parameters.QueryDirectory.Length = Length; StackPtr->Flags = 0; if (RestartScan) StackPtr->Flags = SL_RESTART_SCAN; if (ReturnSingleEntry) StackPtr->Flags |= SL_RETURN_SINGLE_ENTRY; - if (SearchPattern) - { - IoSetCompletionRoutine(Irp, - IopQueryDirectoryFileCompletion, - SearchPattern, - TRUE, - TRUE, - TRUE); - } - - /* Call the Driver */ - Status = IoCallDriver(DeviceObject, Irp); - if (Status == STATUS_PENDING) - { - if (!LocalEvent) - { - KeWaitForSingleObject(&FileObject->Event, - Executive, - PreviousMode, - FileObject->Flags & FO_ALERTABLE_IO, - NULL); - Status = FileObject->FinalStatus; - } - } - - return Status; - -Cleanup: - if (FileObject) ObDereferenceObject(FileObject); - if (Event) ObDereferenceObject(Event); - if (SearchPattern) ExFreePool(SearchPattern); - - /* Return the Status */ - return Status; + /* Set deferred I/O */ + Irp->Flags |= IRP_DEFER_IO_COMPLETION; + + /* Perform the call */ + return IopPerformSynchronousRequest(DeviceObject, + Irp, + FileObject, + TRUE, + PreviousMode, + LockedForSynch, + IopOtherTransfer); } /*
18 years, 5 months
1
0
0
0
[ion] 22790: - NtWriteFile: - Allow async i/o access on mailslots, without a byte offset. - Fix sync semantics just like for the other functions until now. - Fix a potential object leak in a failure case. - Don't call IoBuildSyncronousFsdRequest since we want to build the IRP ourselves. - Use deferred I/O as an optimization.
by ion@svn.reactos.org
Author: ion Date: Mon Jul 3 05:17:14 2006 New Revision: 22790 URL:
http://svn.reactos.org/svn/reactos?rev=22790&view=rev
Log: - NtWriteFile: - Allow async i/o access on mailslots, without a byte offset. - Fix sync semantics just like for the other functions until now. - Fix a potential object leak in a failure case. - Don't call IoBuildSyncronousFsdRequest since we want to build the IRP ourselves. - Use deferred I/O as an optimization. Modified: trunk/reactos/ntoskrnl/io/iomgr/iofunc.c Modified: trunk/reactos/ntoskrnl/io/iomgr/iofunc.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/iofunc.c…
============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/iofunc.c (original) +++ trunk/reactos/ntoskrnl/io/iomgr/iofunc.c Mon Jul 3 05:17:14 2006 @@ -26,9 +26,9 @@ // TODO: // - Lock/Unlock <= DONE // - Query/Set Volume Info <= DONE -// - Read/Write file -// - QuerySet/ File Info -// - NtQueryDirectoryFile +// - Read/Write file <= DONE +// - Query/Set File Info +// - QueryDirectoryFile // /// @@ -2450,20 +2450,19 @@ IN PLARGE_INTEGER ByteOffset OPTIONAL, IN PULONG Key OPTIONAL) { - OBJECT_HANDLE_INFORMATION ObjectHandleInfo; NTSTATUS Status = STATUS_SUCCESS; PFILE_OBJECT FileObject; - PIRP Irp = NULL; + PIRP Irp; PDEVICE_OBJECT DeviceObject; PIO_STACK_LOCATION StackPtr; KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); - BOOLEAN Synchronous = FALSE; PKEVENT EventObject = NULL; LARGE_INTEGER CapturedByteOffset; ULONG CapturedKey = 0; - ACCESS_MASK DesiredAccess = FILE_WRITE_DATA; + BOOLEAN Synchronous = FALSE; + PMDL Mdl; + OBJECT_HANDLE_INFORMATION ObjectHandleInfo; PAGED_CODE(); - CapturedByteOffset.QuadPart = 0; /* Get File Object */ @@ -2475,79 +2474,71 @@ &ObjectHandleInfo); if (!NT_SUCCESS(Status)) return Status; - /* If this is a named pipe, make sure we don't ask for FILE_APPEND_DATA as it - overlaps with the FILE_CREATE_PIPE_INSTANCE access right! */ - if (!(FileObject->Flags & FO_NAMED_PIPE)) - DesiredAccess |= FILE_APPEND_DATA; - /* Validate User-Mode Buffers */ - if (PreviousMode != KernelMode) - { - /* check if the handle has either FILE_WRITE_DATA or FILE_APPEND_DATA was - granted. */ - if (!RtlAreAnyAccessesGranted(ObjectHandleInfo.GrantedAccess, - DesiredAccess)) - { - ObDereferenceObject(FileObject); - return STATUS_ACCESS_DENIED; - } - + if(PreviousMode != KernelMode) + { _SEH_TRY { + /* + * Check if the handle has either FILE_WRITE_DATA or + * FILE_APPEND_DATA granted. However, if this is a named pipe, + * make sure we don't ask for FILE_APPEND_DATA as it interferes + * with the FILE_CREATE_PIPE_INSTANCE access right! + */ + if (!(ObjectHandleInfo.GrantedAccess & + ((!(FileObject->Flags & FO_NAMED_PIPE) ? + FILE_APPEND_DATA : 0) | FILE_WRITE_DATA))) + { + /* We failed */ + ObDereferenceObject(FileObject); + return STATUS_ACCESS_DENIED; + } + + /* Probe the status block */ ProbeForWrite(IoStatusBlock, sizeof(IO_STATUS_BLOCK), sizeof(ULONG)); + + /* Probe the read buffer */ ProbeForRead(Buffer, Length, 1); + /* Check if we got a byte offset */ if (ByteOffset) { + /* Capture and probe it */ CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset); } + /* Capture and probe the key */ if (Key) CapturedKey = ProbeForReadUlong(Key); } _SEH_HANDLE { + /* Get the exception code */ Status = _SEH_GetExceptionCode(); } _SEH_END; - if(!NT_SUCCESS(Status)) return Status; + /* Check for probe failure */ + if (!NT_SUCCESS(Status)) return Status; } else { + /* Kernel mode: capture directly */ if (ByteOffset) CapturedByteOffset = *ByteOffset; if (Key) CapturedKey = *Key; } - /* check if this is an append operation */ - if ((ObjectHandleInfo.GrantedAccess & DesiredAccess) == FILE_APPEND_DATA) + /* Check if this is an append operation */ + if ((ObjectHandleInfo.GrantedAccess & + (FILE_APPEND_DATA | FILE_WRITE_DATA)) == FILE_APPEND_DATA) { /* Give the drivers something to understand */ CapturedByteOffset.u.LowPart = FILE_WRITE_TO_END_OF_FILE; CapturedByteOffset.u.HighPart = -1; } - /* Check if we should use Sync IO or not */ - if (FileObject->Flags & FO_SYNCHRONOUS_IO) - { - if (ByteOffset == NULL || - (CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION && - CapturedByteOffset.u.HighPart == -1)) - { - /* Use the Current Byte OFfset */ - CapturedByteOffset = FileObject->CurrentByteOffset; - } - - Synchronous = TRUE; - } - else if (ByteOffset == NULL && !(FileObject->Flags & FO_NAMED_PIPE)) - { - ObDereferenceObject(FileObject); - return STATUS_INVALID_PARAMETER; - } - - /* Check if we got an event */ + /* Check for event */ if (Event) { /* Reference it */ @@ -2559,89 +2550,133 @@ NULL); if (!NT_SUCCESS(Status)) { + /* Fail */ ObDereferenceObject(FileObject); return Status; } + + /* Otherwise reset the event */ KeClearEvent(EventObject); } - /* Check if this is a direct open or not */ - if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN) - { - DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject); - } - else - { - DeviceObject = IoGetRelatedDeviceObject(FileObject); - } - + /* Check if we should use Sync IO or not */ + if (FileObject->Flags & FO_SYNCHRONOUS_IO) + { + /* Lock the file object */ + IopLockFileObject(FileObject); + + /* Check if we don't have a byte offset avilable */ + if (!(ByteOffset) || + ((CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION) && + (CapturedByteOffset.u.HighPart == -1))) + { + /* Use the Current Byte Offset instead */ + CapturedByteOffset = FileObject->CurrentByteOffset; + } + + /* Rememer we are sync */ + Synchronous = TRUE; + } + else if (!(ByteOffset) && + !(FileObject->Flags & (FO_NAMED_PIPE | FO_MAILSLOT))) + { + /* Otherwise, this was async I/O without a byte offset, so fail */ + if (EventObject) ObDereferenceObject(EventObject); + ObDereferenceObject(FileObject); + return STATUS_INVALID_PARAMETER; + } + + /* Get the device object */ + DeviceObject = IoGetRelatedDeviceObject(FileObject); + + /* Clear the File Object's event */ KeClearEvent(&FileObject->Event); - /* Build the IRP */ - _SEH_TRY - { - Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE, - DeviceObject, - Buffer, - Length, - &CapturedByteOffset, - EventObject, - IoStatusBlock); - if (Irp == NULL) - { - Status = STATUS_INSUFFICIENT_RESOURCES; - } - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - /* Cleanup on failure */ - if (!NT_SUCCESS(Status)) - { - if (Event) ObDereferenceObject(&EventObject); - ObDereferenceObject(FileObject); - return Status; - } - - /* Set up IRP Data */ + /* Allocate the IRP */ + Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); + if (!Irp) return IopCleanupFailedIrp(FileObject, NULL); + + /* Set the IRP */ Irp->Tail.Overlay.OriginalFileObject = FileObject; - Irp->RequestorMode = PreviousMode; + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + Irp->RequestorMode = KernelMode; Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; - Irp->Flags |= IRP_WRITE_OPERATION; -#if 0 - /* FIXME: - * Vfat doesn't handle non cached files correctly. - */ + Irp->UserIosb = IoStatusBlock; + Irp->UserEvent = EventObject; + Irp->PendingReturned = FALSE; + Irp->Cancel = FALSE; + Irp->CancelRoutine = NULL; + Irp->AssociatedIrp.SystemBuffer = NULL; + Irp->MdlAddress = NULL; + + /* Set the Stack Data */ + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->MajorFunction = IRP_MJ_WRITE; + StackPtr->FileObject = FileObject; + StackPtr->Flags = FileObject->Flags & FO_WRITE_THROUGH ? + SL_WRITE_THROUGH : 0; + StackPtr->Parameters.Write.Key = CapturedKey; + StackPtr->Parameters.Write.Length = Length; + StackPtr->Parameters.Write.ByteOffset = CapturedByteOffset; + + /* Check if this is buffered I/O */ + if (DeviceObject->Flags & DO_BUFFERED_IO) + { + /* Check if we have a buffer length */ + if (Length) + { + /* Allocate a buffer */ + Irp->AssociatedIrp.SystemBuffer = + ExAllocatePoolWithTag(NonPagedPool, + Length, + TAG_SYSB); + + /* Copy the buffer and set flags */ + RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, Buffer, Length); + Irp->Flags = (IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER); + } + else + { + /* Not writing anything */ + Irp->Flags = IRP_BUFFERED_IO; + } + } + else if (DeviceObject->Flags & DO_DIRECT_IO) + { + /* Check if we have a buffer length */ + if (Length) + { + /* Allocate an MDL */ + Mdl = IoAllocateMdl(Buffer, Length, FALSE, TRUE, Irp); + MmProbeAndLockPages(Mdl, PreviousMode, IoReadAccess); + } + + /* No allocation flags */ + Irp->Flags = 0; + } + else + { + /* No allocation flags, and use the buffer directly */ + Irp->Flags = 0; + Irp->UserBuffer = Buffer; + } + + /* Now set the deferred read flags */ + Irp->Flags |= (IRP_WRITE_OPERATION | IRP_DEFER_IO_COMPLETION); +#if 0 + /* FIXME: VFAT SUCKS */ if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE; -#endif - - /* Setup Stack Data */ - StackPtr = IoGetNextIrpStackLocation(Irp); - StackPtr->FileObject = FileObject; - StackPtr->Parameters.Write.Key = CapturedKey; - if (FileObject->Flags & FO_WRITE_THROUGH) StackPtr->Flags = SL_WRITE_THROUGH; - - /* Call the Driver */ - Status = IoCallDriver(DeviceObject, Irp); - if (Status == STATUS_PENDING) - { - if (Synchronous) - { - KeWaitForSingleObject(&FileObject->Event, - Executive, - PreviousMode, - FileObject->Flags & FO_ALERTABLE_IO, - NULL); - Status = FileObject->FinalStatus; - } - } - - /* Return the Status */ - return Status; +#endif + + /* Perform the call */ + return IopPerformSynchronousRequest(DeviceObject, + Irp, + FileObject, + TRUE, + PreviousMode, + Synchronous, + IopWriteTransfer); } NTSTATUS
18 years, 5 months
1
0
0
0
[ion] 22789: - NtReadFile: - Allow async i/o access on mailslots, without a byte offset. - Fix sync semantics just like for the other functions until now. - Fix a potential object leak in a failure case. - Don't call IoBuildSyncronousFsdRequest since we want to build the IRP ourselves. - Use deferred I/O as an optimization.
by ion@svn.reactos.org
Author: ion Date: Mon Jul 3 03:02:38 2006 New Revision: 22789 URL:
http://svn.reactos.org/svn/reactos?rev=22789&view=rev
Log: - NtReadFile: - Allow async i/o access on mailslots, without a byte offset. - Fix sync semantics just like for the other functions until now. - Fix a potential object leak in a failure case. - Don't call IoBuildSyncronousFsdRequest since we want to build the IRP ourselves. - Use deferred I/O as an optimization. Modified: trunk/reactos/ntoskrnl/io/iomgr/iofunc.c Modified: trunk/reactos/ntoskrnl/io/iomgr/iofunc.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/iofunc.c…
============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/iofunc.c (original) +++ trunk/reactos/ntoskrnl/io/iomgr/iofunc.c Mon Jul 3 03:02:38 2006 @@ -1699,7 +1699,7 @@ { NTSTATUS Status = STATUS_SUCCESS; PFILE_OBJECT FileObject; - PIRP Irp = NULL; + PIRP Irp; PDEVICE_OBJECT DeviceObject; PIO_STACK_LOCATION StackPtr; KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); @@ -1707,8 +1707,8 @@ LARGE_INTEGER CapturedByteOffset; ULONG CapturedKey = 0; BOOLEAN Synchronous = FALSE; + PMDL Mdl; PAGED_CODE(); - CapturedByteOffset.QuadPart = 0; /* Validate User-Mode Buffers */ @@ -1716,32 +1716,37 @@ { _SEH_TRY { + /* Probe the status block */ ProbeForWrite(IoStatusBlock, sizeof(IO_STATUS_BLOCK), sizeof(ULONG)); - ProbeForWrite(Buffer, - Length, - 1); - + + /* Probe the read buffer */ + ProbeForWrite(Buffer, Length, 1); + + /* Check if we got a byte offset */ if (ByteOffset) { + /* Capture and probe it */ CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset); } + /* Capture and probe the key */ if (Key) CapturedKey = ProbeForReadUlong(Key); - - /* FIXME - probe other pointers and capture information */ } _SEH_HANDLE { + /* Get the exception code */ Status = _SEH_GetExceptionCode(); } _SEH_END; - if(!NT_SUCCESS(Status)) return Status; + /* Check for probe failure */ + if (!NT_SUCCESS(Status)) return Status; } else { + /* Kernel mode: capture directly */ if (ByteOffset) CapturedByteOffset = *ByteOffset; if (Key) CapturedKey = *Key; } @@ -1755,25 +1760,6 @@ NULL); if (!NT_SUCCESS(Status)) return Status; - /* Check if we should use Sync IO or not */ - if (FileObject->Flags & FO_SYNCHRONOUS_IO) - { - if (ByteOffset == NULL || - (CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION && - CapturedByteOffset.u.HighPart == -1)) - { - /* Use the Current Byte OFfset */ - CapturedByteOffset = FileObject->CurrentByteOffset; - } - - Synchronous = TRUE; - } - else if (ByteOffset == NULL && !(FileObject->Flags & FO_NAMED_PIPE)) - { - ObDereferenceObject(FileObject); - return STATUS_INVALID_PARAMETER; - } - /* Check for event */ if (Event) { @@ -1786,89 +1772,133 @@ NULL); if (!NT_SUCCESS(Status)) { + /* Fail */ ObDereferenceObject(FileObject); return Status; } + + /* Otherwise reset the event */ KeClearEvent(EventObject); } - /* Check if this is a direct open or not */ - if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN) - { - DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject); - } - else - { - DeviceObject = IoGetRelatedDeviceObject(FileObject); - } - + /* Check if we should use Sync IO or not */ + if (FileObject->Flags & FO_SYNCHRONOUS_IO) + { + /* Lock the file object */ + IopLockFileObject(FileObject); + + /* Check if we don't have a byte offset avilable */ + if (!(ByteOffset) || + ((CapturedByteOffset.u.LowPart == FILE_USE_FILE_POINTER_POSITION) && + (CapturedByteOffset.u.HighPart == -1))) + { + /* Use the Current Byte Offset instead */ + CapturedByteOffset = FileObject->CurrentByteOffset; + } + + /* Rememer we are sync */ + Synchronous = TRUE; + } + else if (!(ByteOffset) && + !(FileObject->Flags & (FO_NAMED_PIPE | FO_MAILSLOT))) + { + /* Otherwise, this was async I/O without a byte offset, so fail */ + if (EventObject) ObDereferenceObject(EventObject); + ObDereferenceObject(FileObject); + return STATUS_INVALID_PARAMETER; + } + + /* Get the device object */ + DeviceObject = IoGetRelatedDeviceObject(FileObject); + + /* Clear the File Object's event */ KeClearEvent(&FileObject->Event); - /* Create the IRP */ - _SEH_TRY - { - Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, - DeviceObject, - Buffer, - Length, - &CapturedByteOffset, - EventObject, - IoStatusBlock); - - if (Irp == NULL) - { - Status = STATUS_INSUFFICIENT_RESOURCES; - } - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - /* Cleanup if IRP Allocation Failed */ - if (!NT_SUCCESS(Status)) - { - if (Event) ObDereferenceObject(EventObject); - ObDereferenceObject(FileObject); - return Status; - } - - /* Set up IRP Data */ + /* Allocate the IRP */ + Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); + if (!Irp) return IopCleanupFailedIrp(FileObject, NULL); + + /* Set the IRP */ Irp->Tail.Overlay.OriginalFileObject = FileObject; - Irp->RequestorMode = PreviousMode; + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + Irp->RequestorMode = KernelMode; Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine; Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext; - Irp->Flags |= IRP_READ_OPERATION; -#if 0 - /* FIXME: - * Vfat doesn't handle non cached files correctly. - */ - if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE; -#endif - - /* Setup Stack Data */ + Irp->UserIosb = IoStatusBlock; + Irp->UserEvent = EventObject; + Irp->PendingReturned = FALSE; + Irp->Cancel = FALSE; + Irp->CancelRoutine = NULL; + Irp->AssociatedIrp.SystemBuffer = NULL; + Irp->MdlAddress = NULL; + + /* Set the Stack Data */ StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->MajorFunction = IRP_MJ_READ; StackPtr->FileObject = FileObject; StackPtr->Parameters.Read.Key = CapturedKey; - - /* Call the Driver */ - Status = IoCallDriver(DeviceObject, Irp); - if (Status == STATUS_PENDING) - { - if (Synchronous) - { - KeWaitForSingleObject(&FileObject->Event, - Executive, - PreviousMode, - FileObject->Flags & FO_ALERTABLE_IO, - NULL); - Status = FileObject->FinalStatus; - } - } - - /* Return the Status */ - return Status; + StackPtr->Parameters.Read.Length = Length; + StackPtr->Parameters.Read.ByteOffset = CapturedByteOffset; + + /* Check if this is buffered I/O */ + if (DeviceObject->Flags & DO_BUFFERED_IO) + { + /* Check if we have a buffer length */ + if (Length) + { + /* Allocate a buffer */ + Irp->AssociatedIrp.SystemBuffer = + ExAllocatePoolWithTag(NonPagedPool, + Length, + TAG_SYSB); + + /* Set the buffer and flags */ + Irp->UserBuffer = Buffer; + Irp->Flags = (IRP_BUFFERED_IO | + IRP_DEALLOCATE_BUFFER | + IRP_INPUT_OPERATION); + } + else + { + /* Not reading anything */ + Irp->Flags = IRP_BUFFERED_IO | IRP_INPUT_OPERATION; + } + } + else if (DeviceObject->Flags & DO_DIRECT_IO) + { + /* Check if we have a buffer length */ + if (Length) + { + /* Allocate an MDL */ + Mdl = IoAllocateMdl(Buffer, Length, FALSE, TRUE, Irp); + MmProbeAndLockPages(Mdl, PreviousMode, IoWriteAccess); + } + + /* No allocation flags */ + Irp->Flags = 0; + } + else + { + /* No allocation flags, and use the buffer directly */ + Irp->Flags = 0; + Irp->UserBuffer = Buffer; + } + + /* Now set the deferred read flags */ + Irp->Flags |= (IRP_READ_OPERATION | IRP_DEFER_IO_COMPLETION); +#if 0 + /* FIXME: VFAT SUCKS */ + if (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE; +#endif + + /* Perform the call */ + return IopPerformSynchronousRequest(DeviceObject, + Irp, + FileObject, + TRUE, + PreviousMode, + Synchronous, + IopReadTransfer); } NTSTATUS
18 years, 5 months
1
0
0
0
[ion] 22788: - Same sort of changes for NtSetVolumeInformationFile.
by ion@svn.reactos.org
Author: ion Date: Mon Jul 3 02:19:29 2006 New Revision: 22788 URL:
http://svn.reactos.org/svn/reactos?rev=22788&view=rev
Log: - Same sort of changes for NtSetVolumeInformationFile. Modified: trunk/reactos/ntoskrnl/io/iomgr/iofunc.c Modified: trunk/reactos/ntoskrnl/io/iomgr/iofunc.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/iofunc.c…
============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/iofunc.c (original) +++ trunk/reactos/ntoskrnl/io/iomgr/iofunc.c Mon Jul 3 02:19:29 2006 @@ -25,7 +25,7 @@ // // TODO: // - Lock/Unlock <= DONE -// - Query/Set Volume Info +// - Query/Set Volume Info <= DONE // - Read/Write file // - QuerySet/ File Info // - NtQueryDirectoryFile @@ -2649,7 +2649,6 @@ BOOLEAN LocalEvent = FALSE; KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); NTSTATUS Status = STATUS_SUCCESS; - OBJECT_HANDLE_INFORMATION HandleInformation; IO_STATUS_BLOCK KernelIosb; PAGED_CODE(); @@ -2684,7 +2683,7 @@ IoFileObjectType, PreviousMode, (PVOID*)&FileObject, - &HandleInformation); + NULL); if (!NT_SUCCESS(Status)) return Status; /* Check if we should use Sync IO or not */ @@ -2788,125 +2787,135 @@ IN FS_INFORMATION_CLASS FsInformationClass) { PFILE_OBJECT FileObject; + PIRP Irp; + PIO_STACK_LOCATION StackPtr; PDEVICE_OBJECT DeviceObject; - PIRP Irp; + PKEVENT Event = NULL; + BOOLEAN LocalEvent = FALSE; + KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); NTSTATUS Status = STATUS_SUCCESS; - PIO_STACK_LOCATION StackPtr; - PVOID SystemBuffer; - KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); - + IO_STATUS_BLOCK KernelIosb; + PAGED_CODE(); + + /* Check if we're called from user mode */ if (PreviousMode != KernelMode) { + /* Enter SEH for probing */ _SEH_TRY { - if (IoStatusBlock) - { - ProbeForWrite(IoStatusBlock, - sizeof(IO_STATUS_BLOCK), - sizeof(ULONG)); - } - + /* Probe the I/O Status block */ + ProbeForWrite(IoStatusBlock, + sizeof(IO_STATUS_BLOCK), + sizeof(ULONG)); + + /* Probe the information */ if (Length) ProbeForRead(FsInformation, Length, 1); } _SEH_HANDLE { + /* Get the exception code */ Status = _SEH_GetExceptionCode(); } _SEH_END; + /* Check if probing failed */ if (!NT_SUCCESS(Status)) return Status; } + /* Get File Object */ Status = ObReferenceObjectByHandle(FileHandle, - FILE_WRITE_ATTRIBUTES, - NULL, + 0, // FIXME + IoFileObjectType, PreviousMode, (PVOID*)&FileObject, NULL); - if (Status != STATUS_SUCCESS) return Status; - - DeviceObject = FileObject->DeviceObject; - - Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE); - if (!Irp) - { + if (!NT_SUCCESS(Status)) return Status; + + /* Check if we should use Sync IO or not */ + if (FileObject->Flags & FO_SYNCHRONOUS_IO) + { + /* Lock it */ + IopLockFileObject(FileObject); + } + else + { + /* Use local event */ + Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_IO); + KeInitializeEvent(Event, SynchronizationEvent, FALSE); + LocalEvent = TRUE; + } + + /* Get the device object */ + DeviceObject = IoGetRelatedDeviceObject(FileObject); + + /* Clear File Object event */ + KeClearEvent(&FileObject->Event); + + /* Allocate the IRP */ + Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); + if (!Irp) return IopCleanupFailedIrp(FileObject, Event); + + /* Set up the IRP */ + Irp->RequestorMode = PreviousMode; + Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0; + Irp->UserIosb = (LocalEvent) ? &KernelIosb : IoStatusBlock; + Irp->UserEvent = (LocalEvent) ? Event : NULL; + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + Irp->Tail.Overlay.OriginalFileObject = FileObject; + Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; + Irp->UserBuffer = FsInformation; + Irp->AssociatedIrp.SystemBuffer = NULL; + Irp->MdlAddress = NULL; + + /* Set up Stack Data */ + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->MajorFunction = IRP_MJ_SET_VOLUME_INFORMATION; + StackPtr->FileObject = FileObject; + + /* Allocate system buffer */ + Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, + Length, + TAG_SYSB); + if (!Irp->AssociatedIrp.SystemBuffer) + { + /* Fail */ + IoFreeIrp(Irp); + if (Event) ObDereferenceObject(Event); ObDereferenceObject(FileObject); return STATUS_INSUFFICIENT_RESOURCES; } - SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, Length, TAG_SYSB); - if (!SystemBuffer) - { - Status = STATUS_INSUFFICIENT_RESOURCES; - goto failfreeirp; - } - - if (PreviousMode != KernelMode) - { - _SEH_TRY - { - /* no need to probe again */ - RtlCopyMemory(SystemBuffer, FsInformation, Length); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - - if (!NT_SUCCESS(Status)) - { - ExFreePoolWithTag(SystemBuffer, TAG_SYSB); -failfreeirp: - IoFreeIrp(Irp); - ObDereferenceObject(FileObject); - return Status; - } - } - else - { - RtlCopyMemory(SystemBuffer, FsInformation, Length); - } - - /* Trigger FileObject/Event dereferencing */ - Irp->Tail.Overlay.OriginalFileObject = FileObject; - Irp->RequestorMode = PreviousMode; - Irp->AssociatedIrp.SystemBuffer = SystemBuffer; - KeResetEvent( &FileObject->Event ); - Irp->UserEvent = &FileObject->Event; - Irp->UserIosb = IoStatusBlock; - Irp->Tail.Overlay.Thread = PsGetCurrentThread(); - - StackPtr = IoGetNextIrpStackLocation(Irp); - StackPtr->MajorFunction = IRP_MJ_SET_VOLUME_INFORMATION; - StackPtr->MinorFunction = 0; - StackPtr->Flags = 0; - StackPtr->Control = 0; - StackPtr->DeviceObject = DeviceObject; - StackPtr->FileObject = FileObject; + /* Copy the data into the buffer */ + RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, FsInformation, Length); + + /* Set the flags for this buffered + deferred I/O */ + Irp->Flags |= (IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER); + + /* Set Parameters */ StackPtr->Parameters.SetVolume.Length = Length; - StackPtr->Parameters.SetVolume.FsInformationClass = - FsInformationClass; - - Status = IoCallDriver(DeviceObject,Irp); - if (Status == STATUS_PENDING) - { - KeWaitForSingleObject(&FileObject->Event, - UserRequest, - PreviousMode, - FALSE, - NULL); - _SEH_TRY - { - Status = IoStatusBlock->Status; - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - } - - ExFreePool(SystemBuffer); + StackPtr->Parameters.SetVolume.FsInformationClass = FsInformationClass; + + /* Call the Driver */ + Status = IopPerformSynchronousRequest(DeviceObject, + Irp, + FileObject, + TRUE, + PreviousMode, + !LocalEvent, + IopOtherTransfer); + + /* Check if this was async I/O */ + if (LocalEvent) + { + /* It was, finalize this request */ + Status = IopFinalizeAsynchronousIo(Status, + Event, + Irp, + PreviousMode, + &KernelIosb, + IoStatusBlock); + } + + /* Return status */ return Status; }
18 years, 5 months
1
0
0
0
[ion] 22787: - Fix sync usage in NtQueryVolumeInformationFile, set the right IRP flags so that the I/O manager can handle copying the data back and freeing the buffer, and enable deferred completion.
by ion@svn.reactos.org
Author: ion Date: Mon Jul 3 02:14:20 2006 New Revision: 22787 URL:
http://svn.reactos.org/svn/reactos?rev=22787&view=rev
Log: - Fix sync usage in NtQueryVolumeInformationFile, set the right IRP flags so that the I/O manager can handle copying the data back and freeing the buffer, and enable deferred completion. Modified: trunk/reactos/ntoskrnl/io/iomgr/iofunc.c Modified: trunk/reactos/ntoskrnl/io/iomgr/iofunc.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/iofunc.c…
============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/iofunc.c (original) +++ trunk/reactos/ntoskrnl/io/iomgr/iofunc.c Mon Jul 3 02:14:20 2006 @@ -2642,111 +2642,137 @@ IN FS_INFORMATION_CLASS FsInformationClass) { PFILE_OBJECT FileObject; + PIRP Irp; + PIO_STACK_LOCATION StackPtr; PDEVICE_OBJECT DeviceObject; - PIRP Irp; + PKEVENT Event = NULL; + BOOLEAN LocalEvent = FALSE; + KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); NTSTATUS Status = STATUS_SUCCESS; - PIO_STACK_LOCATION StackPtr; - PVOID SystemBuffer; - KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); - + OBJECT_HANDLE_INFORMATION HandleInformation; + IO_STATUS_BLOCK KernelIosb; + PAGED_CODE(); + + /* Check if we're called from user mode */ if (PreviousMode != KernelMode) { + /* Enter SEH for probing */ _SEH_TRY { - if (IoStatusBlock) - { - ProbeForWrite(IoStatusBlock, - sizeof(IO_STATUS_BLOCK), - sizeof(ULONG)); - } - + /* Probe the I/O Status block */ + ProbeForWrite(IoStatusBlock, + sizeof(IO_STATUS_BLOCK), + sizeof(ULONG)); + + /* Probe the information */ if (Length) ProbeForWrite(FsInformation, Length, 1); } _SEH_HANDLE { + /* Get the exception code */ Status = _SEH_GetExceptionCode(); } _SEH_END; - if (!NT_SUCCESS(Status)) - { - return Status; - } - } - + /* Check if probing failed */ + if (!NT_SUCCESS(Status)) return Status; + } + + /* Get File Object */ Status = ObReferenceObjectByHandle(FileHandle, - 0, /* FIXME - depends on the information class! */ + 0, // FIXME IoFileObjectType, PreviousMode, (PVOID*)&FileObject, - NULL); + &HandleInformation); if (!NT_SUCCESS(Status)) return Status; - DeviceObject = FileObject->DeviceObject; - - Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE); - if (!Irp) - { + /* Check if we should use Sync IO or not */ + if (FileObject->Flags & FO_SYNCHRONOUS_IO) + { + /* Lock it */ + IopLockFileObject(FileObject); + } + else + { + /* Use local event */ + Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_IO); + KeInitializeEvent(Event, SynchronizationEvent, FALSE); + LocalEvent = TRUE; + } + + /* Get the device object */ + DeviceObject = IoGetRelatedDeviceObject(FileObject); + + /* Clear File Object event */ + KeClearEvent(&FileObject->Event); + + /* Allocate the IRP */ + Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); + if (!Irp) return IopCleanupFailedIrp(FileObject, Event); + + /* Set up the IRP */ + Irp->RequestorMode = PreviousMode; + Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0; + Irp->UserIosb = (LocalEvent) ? &KernelIosb : IoStatusBlock; + Irp->UserEvent = (LocalEvent) ? Event : NULL; + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + Irp->Tail.Overlay.OriginalFileObject = FileObject; + Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; + Irp->UserBuffer = FsInformation; + Irp->AssociatedIrp.SystemBuffer = NULL; + Irp->MdlAddress = NULL; + + /* Set up Stack Data */ + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION; + StackPtr->FileObject = FileObject; + + /* Allocate system buffer */ + Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, + Length, + TAG_SYSB); + if (!Irp->AssociatedIrp.SystemBuffer) + { + /* Fail */ + IoFreeIrp(Irp); + if (Event) ObDereferenceObject(Event); ObDereferenceObject(FileObject); return STATUS_INSUFFICIENT_RESOURCES; } - SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, Length, TAG_SYSB); - if (!SystemBuffer) - { - IoFreeIrp(Irp); - ObDereferenceObject(FileObject); - return STATUS_INSUFFICIENT_RESOURCES; - } - - /* Trigger FileObject/Event dereferencing */ - Irp->Tail.Overlay.OriginalFileObject = FileObject; - - Irp->RequestorMode = PreviousMode; - Irp->AssociatedIrp.SystemBuffer = SystemBuffer; - KeResetEvent( &FileObject->Event ); - Irp->UserEvent = &FileObject->Event; - Irp->UserIosb = IoStatusBlock; - Irp->Tail.Overlay.Thread = PsGetCurrentThread(); - - StackPtr = IoGetNextIrpStackLocation(Irp); - StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION; - StackPtr->MinorFunction = 0; - StackPtr->Flags = 0; - StackPtr->Control = 0; - StackPtr->DeviceObject = DeviceObject; - StackPtr->FileObject = FileObject; + /* Set the flags for this buffered + deferred I/O */ + Irp->Flags |= (IRP_BUFFERED_IO | + IRP_DEALLOCATE_BUFFER | + IRP_INPUT_OPERATION | + IRP_DEFER_IO_COMPLETION); + + /* Set Parameters */ StackPtr->Parameters.QueryVolume.Length = Length; - StackPtr->Parameters.QueryVolume.FsInformationClass = - FsInformationClass; - - Status = IoCallDriver(DeviceObject, Irp); - if (Status == STATUS_PENDING) - { - KeWaitForSingleObject(&FileObject->Event, - UserRequest, - PreviousMode, - FALSE, - NULL); - Status = IoStatusBlock->Status; - } - - if (NT_SUCCESS(Status)) - { - _SEH_TRY - { - RtlCopyMemory(FsInformation, - SystemBuffer, - IoStatusBlock->Information); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - } - - ExFreePool(SystemBuffer); + StackPtr->Parameters.QueryVolume.FsInformationClass = FsInformationClass; + + /* Call the Driver */ + Status = IopPerformSynchronousRequest(DeviceObject, + Irp, + FileObject, + TRUE, + PreviousMode, + !LocalEvent, + IopOtherTransfer); + + /* Check if this was async I/O */ + if (LocalEvent) + { + /* It was, finalize this request */ + Status = IopFinalizeAsynchronousIo(Status, + Event, + Irp, + PreviousMode, + &KernelIosb, + IoStatusBlock); + } + + /* Return status */ return Status; }
18 years, 5 months
1
0
0
0
[ion] 22786: - Add proper sync handling to NtUnlockFile.
by ion@svn.reactos.org
Author: ion Date: Mon Jul 3 02:07:20 2006 New Revision: 22786 URL:
http://svn.reactos.org/svn/reactos?rev=22786&view=rev
Log: - Add proper sync handling to NtUnlockFile. Modified: trunk/reactos/ntoskrnl/io/iomgr/iofunc.c Modified: trunk/reactos/ntoskrnl/io/iomgr/iofunc.c URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/iofunc.c…
============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/iofunc.c (original) +++ trunk/reactos/ntoskrnl/io/iomgr/iofunc.c Mon Jul 3 02:07:20 2006 @@ -20,6 +20,17 @@ __FUNCTION__, Irp); #endif + +/// +// +// TODO: +// - Lock/Unlock <= DONE +// - Query/Set Volume Info +// - Read/Write file +// - QuerySet/ File Info +// - NtQueryDirectoryFile +// +/// /* PRIVATE FUNCTIONS *********************************************************/ @@ -1104,8 +1115,8 @@ IN BOOLEAN ExclusiveLock) { PFILE_OBJECT FileObject; - PLARGE_INTEGER LocalLength = NULL; - PIRP Irp = NULL; + PLARGE_INTEGER LocalLength; + PIRP Irp; PIO_STACK_LOCATION StackPtr; PDEVICE_OBJECT DeviceObject; PKEVENT Event = NULL; @@ -2231,19 +2242,19 @@ IN PLARGE_INTEGER Length, IN ULONG Key OPTIONAL) { - PFILE_OBJECT FileObject = NULL; - PLARGE_INTEGER LocalLength = NULL; - PIRP Irp = NULL; + PFILE_OBJECT FileObject; + PLARGE_INTEGER LocalLength; + PIRP Irp; PIO_STACK_LOCATION StackPtr; PDEVICE_OBJECT DeviceObject; - KEVENT Event; + PKEVENT Event = NULL; BOOLEAN LocalEvent = FALSE; KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); + LARGE_INTEGER CapturedByteOffset, CapturedLength; NTSTATUS Status = STATUS_SUCCESS; - LARGE_INTEGER CapturedByteOffset, CapturedLength; OBJECT_HANDLE_INFORMATION HandleInformation; + IO_STATUS_BLOCK KernelIosb; PAGED_CODE(); - CapturedByteOffset.QuadPart = 0; CapturedLength.QuadPart = 0; @@ -2256,38 +2267,47 @@ &HandleInformation); if (!NT_SUCCESS(Status)) return Status; + /* Check if we're called from user mode */ if (PreviousMode != KernelMode) { - /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access unless we're - in KernelMode! */ - if (!(HandleInformation.GrantedAccess & (FILE_WRITE_DATA | FILE_READ_DATA))) + /* Must have either FILE_READ_DATA or FILE_WRITE_DATA access */ + if (!(HandleInformation.GrantedAccess & + (FILE_WRITE_DATA | FILE_READ_DATA))) { ObDereferenceObject(FileObject); return STATUS_ACCESS_DENIED; } + /* Enter SEH for probing */ _SEH_TRY { + /* Probe the I/O Status block */ ProbeForWrite(IoStatusBlock, sizeof(IO_STATUS_BLOCK), sizeof(ULONG)); + + /* Probe and capture the large integers */ CapturedByteOffset = ProbeForReadLargeInteger(ByteOffset); CapturedLength = ProbeForReadLargeInteger(Length); } _SEH_HANDLE { + /* Get the exception code */ Status = _SEH_GetExceptionCode(); } _SEH_END; + /* Check if probing failed */ if (!NT_SUCCESS(Status)) { + /* Dereference the object and return exception code */ ObDereferenceObject(FileObject); return Status; } } else { + /* Otherwise, capture them directly */ CapturedByteOffset = *ByteOffset; CapturedLength = *Length; } @@ -2305,23 +2325,38 @@ /* Check if we should use Sync IO or not */ if (FileObject->Flags & FO_SYNCHRONOUS_IO) { - /* Use File Object event */ - KeClearEvent(&FileObject->Event); + /* Lock it */ + IopLockFileObject(FileObject); } else { /* Use local event */ - KeInitializeEvent(&Event, SynchronizationEvent, FALSE); + Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_IO); + KeInitializeEvent(Event, SynchronizationEvent, FALSE); LocalEvent = TRUE; } + + /* Clear File Object event */ + KeClearEvent(&FileObject->Event); /* Allocate the IRP */ Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); - if (!Irp) - { - ObDereferenceObject(FileObject); - return STATUS_INSUFFICIENT_RESOURCES; - } + if (!Irp) return IopCleanupFailedIrp(FileObject, Event); + + /* Set up the IRP */ + Irp->RequestorMode = PreviousMode; + Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0; + Irp->UserIosb = (LocalEvent) ? &KernelIosb : IoStatusBlock; + Irp->UserEvent = (LocalEvent) ? Event : NULL; + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + Irp->Tail.Overlay.OriginalFileObject = FileObject; + Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; + + /* Set up Stack Data */ + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL; + StackPtr->MinorFunction = IRP_MN_UNLOCK_SINGLE; + StackPtr->FileObject = FileObject; /* Allocate local buffer */ LocalLength = ExAllocatePoolWithTag(NonPagedPool, @@ -2329,56 +2364,44 @@ TAG_LOCK); if (!LocalLength) { + /* Fail */ IoFreeIrp(Irp); + if (Event) ObDereferenceObject(Event); ObDereferenceObject(FileObject); return STATUS_INSUFFICIENT_RESOURCES; } + + /* Set the length */ *LocalLength = CapturedLength; - /* Set up the IRP */ - Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0; - Irp->RequestorMode = PreviousMode; - Irp->UserIosb = IoStatusBlock; - Irp->UserEvent = (LocalEvent) ? &Event : NULL; - Irp->Tail.Overlay.Thread = PsGetCurrentThread(); - Irp->Tail.Overlay.OriginalFileObject = FileObject; - - /* Set up Stack Data */ - StackPtr = IoGetNextIrpStackLocation(Irp); - StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL; - StackPtr->MinorFunction = IRP_MN_UNLOCK_SINGLE; - StackPtr->FileObject = FileObject; - /* Set Parameters */ + Irp->Tail.Overlay.AuxiliaryBuffer = (PVOID)LocalLength; StackPtr->Parameters.LockControl.Length = LocalLength; StackPtr->Parameters.LockControl.ByteOffset = CapturedByteOffset; StackPtr->Parameters.LockControl.Key = Key; /* Call the Driver */ - Status = IoCallDriver(DeviceObject, Irp); - if (Status == STATUS_PENDING) - { - if (LocalEvent) - { - KeWaitForSingleObject(&Event, - Executive, - PreviousMode, - FileObject->Flags & FO_ALERTABLE_IO, - NULL); - Status = IoStatusBlock->Status; - } - else - { - KeWaitForSingleObject(&FileObject->Event, - Executive, - PreviousMode, - FileObject->Flags & FO_ALERTABLE_IO, - NULL); - Status = FileObject->FinalStatus; - } - } - - /* Return the Status */ + Status = IopPerformSynchronousRequest(DeviceObject, + Irp, + FileObject, + FALSE, + PreviousMode, + !LocalEvent, + IopOtherTransfer); + + /* Check if this was async I/O */ + if (LocalEvent) + { + /* It was, finalize this request */ + Status = IopFinalizeAsynchronousIo(Status, + Event, + Irp, + PreviousMode, + &KernelIosb, + IoStatusBlock); + } + + /* Return status */ return Status; }
18 years, 5 months
1
0
0
0
← Newer
1
...
58
59
60
61
62
63
64
...
67
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
Results per page:
10
25
50
100
200