/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS user32.dll
- * FILE: lib/user32/windows/window.c
+ * FILE: win32ss/user/user32/windows/window.c
* PURPOSE: Window management
- * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
* UPDATE HISTORY:
* 06-06-2001 CSH Created
*/
-/* INCLUDES ******************************************************************/
#define DEBUG
#include <user32.h>
-#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(user32);
-LRESULT DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active);
void MDI_CalcDefaultChildPos( HWND hwndClient, INT total, LPPOINT lpPos, INT delta, UINT *id );
+extern LPCWSTR FASTCALL ClassNameToVersion(const void *lpszClass, LPCWSTR lpszMenuName, LPCWSTR *plpLibFileName, HANDLE *pContext, BOOL bAnsi);
/* FUNCTIONS *****************************************************************/
VOID WINAPI
-SwitchToThisWindow(HWND hwnd, BOOL fUnknown)
+SwitchToThisWindow(HWND hwnd, BOOL bUnknown)
{
- ShowWindow(hwnd, SW_SHOW);
+ NtUserxSwitchToThisWindow(hwnd, bUnknown);
}
BOOL WINAPI
CloseWindow(HWND hWnd)
{
- SendMessageA(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0);
-
- return HandleToUlong(hWnd);
+ /* NOTE: CloseWindow does minimizes, and doesn't close. */
+ SetActiveWindow(hWnd);
+ return ShowWindow(hWnd, SW_SHOWMINIMIZED);
}
-VOID
FORCEINLINE
+VOID
RtlInitLargeString(
OUT PLARGE_STRING plstr,
LPCVOID psz,
{
LARGE_STRING WindowName;
LARGE_STRING lstrClassName, *plstrClassName;
+ LARGE_STRING lstrClassVersion, *plstrClassVersion;
UNICODE_STRING ClassName;
+ UNICODE_STRING ClassVersion;
WNDCLASSEXA wceA;
WNDCLASSEXW wceW;
- BOOL Unicode;
+ HMODULE hLibModule = NULL;
+ DWORD dwLastError;
+ BOOL Unicode, ClassFound = FALSE;
HWND Handle = NULL;
+ LPCWSTR lpszClsVersion;
+ LPCWSTR lpLibFileName = NULL;
+ HANDLE pCtx = NULL;
#if 0
DbgPrint("[window] User32CreateWindowEx style %d, exstyle %d, parent %d\n", dwStyle, dwExStyle, hWndParent);
if (!RegisterDefaultClasses)
{
- ERR("User32CreateWindowEx RegisterSystemControls\n");
- RegisterSystemControls();
+ TRACE("RegisterSystemControls\n");
+ RegisterSystemControls();
}
Unicode = !(dwFlags & NUCWE_ANSI);
}
else
{
- if(Unicode)
+ if (Unicode)
+ {
RtlInitUnicodeString(&ClassName, (PCWSTR)lpClassName);
+ }
else
{
if (!RtlCreateUnicodeStringFromAsciiz(&ClassName, (PCSZ)lpClassName))
{
SetLastError(ERROR_OUTOFMEMORY);
- return (HWND)0;
+ return NULL;
}
}
-
+
/* Copy it to a LARGE_STRING */
lstrClassName.Buffer = ClassName.Buffer;
lstrClassName.Length = ClassName.Length;
NTSTATUS Status;
PSTR AnsiBuffer = WindowName.Buffer;
ULONG AnsiLength = WindowName.Length;
-
+
WindowName.Length = 0;
WindowName.MaximumLength = AnsiLength * sizeof(WCHAR);
WindowName.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
}
}
- if(!hMenu && (dwStyle & (WS_OVERLAPPEDWINDOW | WS_POPUP)))
+ if (!hMenu && (dwStyle & (WS_OVERLAPPEDWINDOW | WS_POPUP)))
{
- if(Unicode)
+ if (Unicode)
{
- wceW.cbSize = sizeof(WNDCLASSEXW);
- if(GetClassInfoExW(hInstance, (LPCWSTR)lpClassName, &wceW) && wceW.lpszMenuName)
+ wceW.cbSize = sizeof(wceW);
+ if (GetClassInfoExW(hInstance, (LPCWSTR)lpClassName, &wceW) && wceW.lpszMenuName)
{
hMenu = LoadMenuW(hInstance, wceW.lpszMenuName);
}
}
else
{
- wceA.cbSize = sizeof(WNDCLASSEXA);
- if(GetClassInfoExA(hInstance, lpClassName, &wceA) && wceA.lpszMenuName)
+ wceA.cbSize = sizeof(wceA);
+ if (GetClassInfoExA(hInstance, lpClassName, &wceA) && wceA.lpszMenuName)
{
hMenu = LoadMenuA(hInstance, wceA.lpszMenuName);
}
if (!Unicode) dwExStyle |= WS_EX_SETANSICREATOR;
- Handle = NtUserCreateWindowEx(dwExStyle,
- plstrClassName,
- NULL,
- &WindowName,
- dwStyle,
- x,
- y,
- nWidth,
- nHeight,
- hWndParent,
- hMenu,
- hInstance,
- lpParam,
- dwFlags,
- NULL);
+ lpszClsVersion = ClassNameToVersion(lpClassName, NULL, &lpLibFileName, &pCtx, !Unicode);
+ if (!lpszClsVersion)
+ {
+ plstrClassVersion = plstrClassName;
+ }
+ else
+ {
+ RtlInitUnicodeString(&ClassVersion, lpszClsVersion);
+ lstrClassVersion.Buffer = ClassVersion.Buffer;
+ lstrClassVersion.Length = ClassVersion.Length;
+ lstrClassVersion.MaximumLength = ClassVersion.MaximumLength;
+ plstrClassVersion = &lstrClassVersion;
+ }
+
+ for (;;)
+ {
+ Handle = NtUserCreateWindowEx(dwExStyle,
+ plstrClassName,
+ plstrClassVersion,
+ &WindowName,
+ dwStyle,
+ x,
+ y,
+ nWidth,
+ nHeight,
+ hWndParent,
+ hMenu,
+ hInstance,
+ lpParam,
+ dwFlags,
+ NULL);
+ if (Handle) break;
+ if (!lpLibFileName) break;
+ if (!ClassFound)
+ {
+ dwLastError = GetLastError();
+ if (dwLastError == ERROR_CANNOT_FIND_WND_CLASS)
+ {
+ ClassFound = VersionRegisterClass(ClassName.Buffer, lpLibFileName, pCtx, &hLibModule);
+ if (ClassFound) continue;
+ }
+ }
+ if (hLibModule)
+ {
+ dwLastError = GetLastError();
+ FreeLibrary(hLibModule);
+ SetLastError(dwLastError);
+ hLibModule = NULL;
+ }
+ break;
+ }
#if 0
DbgPrint("[window] NtUserCreateWindowEx() == %d\n", Handle);
#endif
+
cleanup:
- if(!Unicode)
+ if (!Unicode)
{
if (!IS_ATOM(lpClassName))
- {
RtlFreeUnicodeString(&ClassName);
- }
-
+
RtlFreeLargeString(&WindowName);
}
/*
* @implemented
*/
-HWND WINAPI
+HWND
+WINAPI
+DECLSPEC_HOTPATCH
CreateWindowExA(DWORD dwExStyle,
LPCSTR lpClassName,
LPCSTR lpWindowName,
if (!RegisterDefaultClasses)
{
- ERR("CreateWindowExA RegisterSystemControls\n");
+ TRACE("CreateWindowExA RegisterSystemControls\n");
RegisterSystemControls();
}
/*
* @implemented
*/
-HWND WINAPI
+HWND
+WINAPI
+DECLSPEC_HOTPATCH
CreateWindowExW(DWORD dwExStyle,
LPCWSTR lpClassName,
LPCWSTR lpWindowName,
WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", hWndParent);
return NULL;
}
-
+
/* lpParams of WM_[NC]CREATE is different for MDI children.
* MDICREATESTRUCT members have the originally passed values.
*/
}
hwnd = User32CreateWindowEx(dwExStyle,
- (LPCSTR) lpClassName,
- (LPCSTR) lpWindowName,
+ (LPCSTR)lpClassName,
+ (LPCSTR)lpWindowName,
dwStyle,
x,
y,
if (!NT_SUCCESS(Status))
return FALSE;
+ if (!dwCount)
+ {
+ if (!dwThreadId)
+ return FALSE;
+ else
+ return TRUE;
+ }
+
/* allocate buffer to receive HWND handles */
hHeap = GetProcessHeap();
pHwnd = HeapAlloc(hHeap, 0, sizeof(HWND)*(dwCount+1));
return FALSE;
}
- if (!dwCount)
- {
- if (!dwThreadId)
- return FALSE;
- else
- return TRUE;
- }
-
/* call the user's callback function until we're done or
they tell us to quit */
for ( i = 0; i < dwCount; i++ )
/* FIXME I'm only getting NULLs from Thread Enumeration, and it's
* probably because I'm not doing it right in NtUserBuildHwndList.
* Once that's fixed, we shouldn't have to check for a NULL HWND
- * here
+ * here
* This is now fixed in revision 50205. (jt)
*/
if (!pHwnd[i]) /* don't enumerate a NULL HWND */
/*
- * @unimplemented
+ * @implemented
*/
BOOL WINAPI
GetAltTabInfoA(HWND hwnd,
LPSTR pszItemText,
UINT cchItemText)
{
- UNIMPLEMENTED;
- return FALSE;
+ return NtUserGetAltTabInfo(hwnd,iItem,pati,(LPWSTR)pszItemText,cchItemText,TRUE);
}
/*
- * @unimplemented
+ * @implemented
*/
BOOL WINAPI
GetAltTabInfoW(HWND hwnd,
LPWSTR pszItemText,
UINT cchItemText)
{
- UNIMPLEMENTED;
- return FALSE;
+ return NtUserGetAltTabInfo(hwnd,iItem,pati,pszItemText,cchItemText,FALSE);
}
{
HWND Ret = NULL;
PWND Ancestor, Wnd;
-
+
Wnd = ValidateHwnd(hwnd);
if (!Wnd)
return NULL;
lpRect->bottom = GetSystemMetrics(SM_CYMINIMIZED);
return TRUE;
}
- if ( hWnd != GetDesktopWindow()) // Wnd->fnid != FNID_DESKTOP )
+ if ( hWnd != GetDesktopWindow()) // Wnd->fnid != FNID_DESKTOP )
{
/* lpRect->left = lpRect->top = 0;
lpRect->right = Wnd->rcClient.right - Wnd->rcClient.left;
/* Do this until Init bug is fixed. This sets 640x480, see InitMetrics.
lpRect->right = GetSystemMetrics(SM_CXSCREEN);
lpRect->bottom = GetSystemMetrics(SM_CYSCREEN);
-*/ }
+*/ }
return TRUE;
}
if (Wnd->spwndPrev != NULL)
FoundWnd = DesktopPtrToUser(Wnd->spwndPrev);
break;
-
+
case GW_CHILD:
if (Wnd->spwndChild != NULL)
FoundWnd = DesktopPtrToUser(Wnd->spwndChild);
/*
* @implemented
*/
-BOOL WINAPI
+BOOL
+WINAPI
+DECLSPEC_HOTPATCH
GetWindowInfo(HWND hWnd,
PWINDOWINFO pwi)
{
pwi->cxWindowBorders = Size.cx;
pwi->cyWindowBorders = Size.cy;
pwi->dwWindowStatus = 0;
- if (pWnd->state & WNDS_ACTIVEFRAME)
+ if (pWnd->state & WNDS_ACTIVEFRAME || (GetActiveWindow() == hWnd))
pwi->dwWindowStatus = WS_ACTIVECAPTION;
pwi->atomWindowType = (pCls ? pCls->atomClassName : 0 );
return GetModuleFileNameW( Wnd->hModule, lpszFileName, cchFileNameMax );
}
-
/*
* @implemented
*/
return TRUE;
}
-
/*
* @implemented
*/
GetWindowTextA(HWND hWnd, LPSTR lpString, int nMaxCount)
{
PWND Wnd;
- PCWSTR Buffer;
INT Length = 0;
- if (lpString == NULL)
+ if (lpString == NULL || nMaxCount == 0)
return 0;
Wnd = ValidateHwnd(hWnd);
if (!Wnd)
return 0;
- _SEH2_TRY
+ lpString[0] = '\0';
+
+ if (!TestWindowProcess(Wnd))
{
- if (!TestWindowProcess( Wnd))
+ _SEH2_TRY
{
- if (nMaxCount > 0)
- {
- /* do not send WM_GETTEXT messages to other processes */
- Length = Wnd->strName.Length / sizeof(WCHAR);
- if (Length != 0)
- {
- Buffer = DesktopPtrToUser(Wnd->strName.Buffer);
- if (Buffer != NULL)
- {
- if (!WideCharToMultiByte(CP_ACP,
- 0,
- Buffer,
- Length + 1,
- lpString,
- nMaxCount,
- NULL,
- NULL))
- {
- lpString[nMaxCount - 1] = '\0';
- }
- }
- else
- {
- Length = 0;
- lpString[0] = '\0';
- }
- }
- else
- lpString[0] = '\0';
- }
-
- Wnd = NULL; /* Don't send a message */
+ Length = DefWindowProcA(hWnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Length = 0;
}
+ _SEH2_END;
}
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ else
{
- lpString[0] = '\0';
- Length = 0;
- Wnd = NULL; /* Don't send a message */
- }
- _SEH2_END;
-
- if (Wnd != NULL)
Length = SendMessageA(hWnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
-
+ }
+ //ERR("GWTA Len %d : %s\n",Length,lpString);
return Length;
}
-
/*
* @implemented
*/
int WINAPI
GetWindowTextLengthA(HWND hWnd)
{
- return(SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0));
-}
+ PWND Wnd;
+ Wnd = ValidateHwnd(hWnd);
+ if (!Wnd)
+ return 0;
+
+ if (!TestWindowProcess(Wnd))
+ {
+ return DefWindowProcA(hWnd, WM_GETTEXTLENGTH, 0, 0);
+ }
+ else
+ {
+ return SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0);
+ }
+}
/*
* @implemented
int WINAPI
GetWindowTextLengthW(HWND hWnd)
{
- return(SendMessageW(hWnd, WM_GETTEXTLENGTH, 0, 0));
-}
+ PWND Wnd;
+
+ Wnd = ValidateHwnd(hWnd);
+ if (!Wnd)
+ return 0;
+ if (!TestWindowProcess(Wnd))
+ {
+ return DefWindowProcW(hWnd, WM_GETTEXTLENGTH, 0, 0);
+ }
+ else
+ {
+ return SendMessageW(hWnd, WM_GETTEXTLENGTH, 0, 0);
+ }
+}
/*
* @implemented
GetWindowTextW(HWND hWnd, LPWSTR lpString, int nMaxCount)
{
PWND Wnd;
- PCWSTR Buffer;
INT Length = 0;
- if (lpString == NULL)
+ if (lpString == NULL || nMaxCount == 0)
return 0;
Wnd = ValidateHwnd(hWnd);
if (!Wnd)
return 0;
- _SEH2_TRY
+ lpString[0] = L'\0';
+
+ if (!TestWindowProcess(Wnd))
{
- if (!TestWindowProcess( Wnd))
+ _SEH2_TRY
{
- if (nMaxCount > 0)
- {
- /* do not send WM_GETTEXT messages to other processes */
- Length = Wnd->strName.Length / sizeof(WCHAR);
- if (Length != 0)
- {
- Buffer = DesktopPtrToUser(Wnd->strName.Buffer);
- if (Buffer != NULL)
- {
- RtlCopyMemory(lpString,
- Buffer,
- (Length + 1) * sizeof(WCHAR));
- }
- else
- {
- Length = 0;
- lpString[0] = '\0';
- }
- }
- else
- lpString[0] = '\0';
- }
-
- Wnd = NULL; /* Don't send a message */
+ Length = DefWindowProcW(hWnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Length = 0;
}
+ _SEH2_END;
}
- _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ else
{
- lpString[0] = '\0';
- Length = 0;
- Wnd = NULL; /* Don't send a message */
- }
- _SEH2_END;
-
- if (Wnd != NULL)
Length = SendMessageW(hWnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString);
-
+ }
+ //ERR("GWTW Len %d : %S\n",Length,lpString);
return Length;
}
if (!pWnd) return Ret;
ti = pWnd->head.pti;
-
+
if (ti)
{
if (ti == GetW32ThreadInfo())
/*
* @implemented
*/
-BOOL WINAPI
+BOOL
+WINAPI
+DECLSPEC_HOTPATCH
SetWindowTextA(HWND hWnd,
LPCSTR lpString)
{
/*
* @implemented
*/
-BOOL WINAPI
+BOOL
+WINAPI
+DECLSPEC_HOTPATCH
SetWindowTextW(HWND hWnd,
LPCWSTR lpString)
{
BLENDFUNCTION *pbl,
DWORD dwFlags)
{
- if ( dwFlags & ULW_EX_NORESIZE)
- dwFlags = ~(ULW_EX_NORESIZE|ULW_OPAQUE|ULW_ALPHA|ULW_COLORKEY);
+ if (dwFlags & ULW_EX_NORESIZE) /* only valid for UpdateLayeredWindowIndirect */
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
return NtUserUpdateLayeredWindow( hwnd,
hdcDst,
pptDst,
InternalGetWindowText(HWND hWnd, LPWSTR lpString, int nMaxCount)
{
INT Ret = NtUserInternalGetWindowText(hWnd, lpString, nMaxCount);
- if (Ret == 0)
+ if (Ret == 0 && lpString)
*lpString = L'\0';
return Ret;
}