-/* $Id: class.c,v 1.26 2003/08/07 04:03:24 royce Exp $
+/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS user32.dll
* UPDATE HISTORY:
* 09-05-2001 CSH Created
*/
-#include <windows.h>
+
#include <user32.h>
-#include <string.h>
-#include <stdlib.h>
-#include <debug.h>
-#include <window.h> /* for IS_ATOM */
-
-/* copied from menu.c */
-NTSTATUS
-STATIC HEAP_strdupA2W ( HANDLE hHeap, LPWSTR* ppszW, LPCSTR lpszA, UINT* NewLen )
+
+static BOOL GetClassInfoExCommon(
+ HINSTANCE hInst,
+ LPCWSTR lpszClass,
+ LPWNDCLASSEXW lpwcx,
+ BOOL unicode)
{
- ULONG len;
+ LPWSTR str;
+ UNICODE_STRING str2, str3;
+ WNDCLASSEXW w;
+ BOOL retval;
NTSTATUS Status;
- *ppszW = NULL;
- if ( !lpszA )
- return STATUS_SUCCESS;
- len = lstrlenA(lpszA);
- *ppszW = RtlAllocateHeap ( hHeap, 0, (len+1) * sizeof(WCHAR) );
- if ( !*ppszW )
- return STATUS_NO_MEMORY;
- Status = RtlMultiByteToUnicodeN ( *ppszW, len*sizeof(WCHAR), NULL, (PCHAR)lpszA, len );
- (*ppszW)[len] = L'\0';
- if(NewLen) (*NewLen) = (UINT)len;
- return Status;
-}
-/*
- * @unimplemented
- */
-WINBOOL
-STDCALL
-GetClassInfoA(
- HINSTANCE hInstance,
- LPCSTR lpClassName,
- LPWNDCLASSA lpWndClass)
-{
- UNIMPLEMENTED;
- return FALSE;
+ if ( !lpszClass || !lpwcx )
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ if(IS_ATOM(lpszClass))
+ str = (LPWSTR)lpszClass;
+ else
+ {
+ extern BOOL ControlsInitialized;
+
+ if (unicode)
+ {
+ str = HEAP_strdupW ( lpszClass, wcslen(lpszClass) );
+
+ if ( !str )
+ {
+ SetLastError (ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+ }
+
+ else
+ {
+ Status = HEAP_strdupAtoW(&str, (LPCSTR)lpszClass, NULL);
+
+ if (! NT_SUCCESS(Status))
+ {
+ SetLastError(RtlNtStatusToDosError(Status));
+ return FALSE;
+ }
+ }
+
+ /* Register built-in controls if not already done */
+ if ( !ControlsInitialized )
+ {
+ ControlsInitialized = ControlsInit(str);
+ }
+ }
+
+ str2.Length = str3.Length = 0;
+ str2.MaximumLength = str3.MaximumLength = 255;
+ str2.Buffer = (PWSTR)HEAP_alloc ( str2.MaximumLength * sizeof(WCHAR) );
+ if ( !str2.Buffer )
+ {
+ SetLastError (ERROR_OUTOFMEMORY);
+ if ( !IS_ATOM(str) )
+ HEAP_free ( str );
+ return FALSE;
+ }
+
+ str3.Buffer = (PWSTR)HEAP_alloc ( str3.MaximumLength * sizeof(WCHAR) );
+ if ( !str3.Buffer )
+ {
+ SetLastError (ERROR_OUTOFMEMORY);
+ HEAP_free ( str2.Buffer );
+ if ( !IS_ATOM(str) )
+ HEAP_free ( str );
+ return FALSE;
+ }
+
+ w.lpszMenuName = (LPCWSTR)&str2;
+ w.lpszClassName = (LPCWSTR)&str3;
+
+ /* get info about system classes? */
+ if (!hInst) hInst = User32Instance;
+
+ retval = (BOOL)NtUserGetClassInfo(hInst, str, &w, TRUE, 0);
+
+ w.hInstance = (hInst == User32Instance) ? 0 : hInst;
+
+ if ( !IS_ATOM(str) )
+ HEAP_free(str);
+
+ RtlCopyMemory ( lpwcx, &w, sizeof(WNDCLASSEXW) );
+
+ if ( !IS_INTRESOURCE(w.lpszMenuName) && w.lpszMenuName )
+ {
+ if (unicode)
+ lpwcx->lpszMenuName = heap_string_poolW ( str2.Buffer, str2.Length );
+ else
+ ((LPWNDCLASSEXA) lpwcx)->lpszMenuName = heap_string_poolA ( str2.Buffer, str2.Length );
+ }
+
+ if ( !IS_ATOM(w.lpszClassName) && w.lpszClassName )
+ {
+ if (unicode)
+ lpwcx->lpszClassName = heap_string_poolW ( str3.Buffer, str3.Length );
+ else
+ ((LPWNDCLASSEXA) lpwcx)->lpszClassName = heap_string_poolA ( str3.Buffer, str3.Length );
+ }
+
+ HEAP_free ( str2.Buffer );
+ HEAP_free ( str3.Buffer );
+
+ return retval;
}
/*
- * @unimplemented
+ * @implemented
*/
-WINBOOL
+BOOL
STDCALL
GetClassInfoExA(
HINSTANCE hinst,
LPCSTR lpszClass,
LPWNDCLASSEXA lpwcx)
{
- UNIMPLEMENTED;
- return FALSE;
+ return GetClassInfoExCommon(hinst, (LPWSTR)lpszClass, (LPWNDCLASSEXW)lpwcx, FALSE);
}
/*
- * @unimplemented
+ * @implemented
*/
-WINBOOL
+BOOL
STDCALL
GetClassInfoExW(
HINSTANCE hinst,
LPCWSTR lpszClass,
LPWNDCLASSEXW lpwcx)
{
- UNIMPLEMENTED;
- return FALSE;
+ return GetClassInfoExCommon(hinst, lpszClass, lpwcx, TRUE);
}
/*
- * @unimplemented
+ * @implemented
+ */
+BOOL
+STDCALL
+GetClassInfoA(
+ HINSTANCE hInstance,
+ LPCSTR lpClassName,
+ LPWNDCLASSA lpWndClass)
+{
+ WNDCLASSEXA w;
+ BOOL retval;
+
+ if ( !lpClassName || !lpWndClass )
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ retval = GetClassInfoExA(hInstance,lpClassName,&w);
+ if (retval)
+ {
+ RtlCopyMemory ( lpWndClass, &w.style, sizeof(WNDCLASSA) );
+ }
+ return retval;
+}
+
+/*
+ * @implemented
*/
-WINBOOL
+BOOL
STDCALL
GetClassInfoW(
HINSTANCE hInstance,
LPCWSTR lpClassName,
LPWNDCLASSW lpWndClass)
{
- UNIMPLEMENTED;
- return FALSE;
+ WNDCLASSEXW w;
+ BOOL retval;
+
+ if(!lpClassName || !lpWndClass)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ retval = GetClassInfoExW(hInstance,lpClassName,&w);
+ RtlCopyMemory (lpWndClass,&w.style,sizeof(WNDCLASSW));
+ return retval;
}
/*
- * @unimplemented
+ * @implemented
*/
DWORD STDCALL
GetClassLongA(HWND hWnd, int nIndex)
{
- /*
- * FIXME - for GCL_MENUNAME, we need to allocate a buffer
- * in thread-local storage and convert the results back
- * to that. Subsequent calls should be sure and clean that
- * up
- */
- return(NtUserGetClassLong(hWnd, nIndex, TRUE));
+ switch (nIndex)
+ {
+ case GCL_HBRBACKGROUND:
+ {
+ DWORD hBrush = NtUserGetClassLong(hWnd, GCL_HBRBACKGROUND, TRUE);
+ if (hBrush != 0 && hBrush < 0x4000)
+ hBrush = (DWORD)GetSysColorBrush((ULONG)hBrush - 1);
+ return hBrush;
+ }
+
+ case GCL_MENUNAME:
+ {
+ PUNICODE_STRING Name;
+ Name = (PUNICODE_STRING)NtUserGetClassLong(hWnd, nIndex, TRUE);
+ if (IS_INTRESOURCE(Name))
+ return (DWORD)Name;
+ else
+ return (DWORD)heap_string_poolA(Name->Buffer, Name->Length);
+ }
+
+ default:
+ return NtUserGetClassLong(hWnd, nIndex, TRUE);
+ }
}
/*
* @implemented
*/
DWORD STDCALL
-GetClassLongW(HWND hWnd, int nIndex)
+GetClassLongW ( HWND hWnd, int nIndex )
{
- return(NtUserGetClassLong(hWnd, nIndex, FALSE));
+ switch (nIndex)
+ {
+ case GCL_HBRBACKGROUND:
+ {
+ DWORD hBrush = NtUserGetClassLong(hWnd, GCL_HBRBACKGROUND, TRUE);
+ if (hBrush != 0 && hBrush < 0x4000)
+ hBrush = (DWORD)GetSysColorBrush((ULONG)hBrush - 1);
+ return hBrush;
+ }
+
+ case GCL_MENUNAME:
+ {
+ PUNICODE_STRING Name;
+ Name = (PUNICODE_STRING)NtUserGetClassLong(hWnd, nIndex, FALSE);
+ if (IS_INTRESOURCE(Name))
+ return (DWORD)Name;
+ else
+ return (DWORD)heap_string_poolW(Name->Buffer, Name->Length);
+ }
+
+ default:
+ return NtUserGetClassLong(hWnd, nIndex, FALSE);
+ }
}
/*
* @implemented
*/
-int
-STDCALL
+int STDCALL
GetClassNameA(
HWND hWnd,
LPSTR lpClassName,
int nMaxCount)
{
- int result;
- LPWSTR ClassName;
- NTSTATUS Status;
- ClassName = RtlAllocateHeap(RtlGetProcessHeap(),HEAP_ZERO_MEMORY,nMaxCount);
- result = NtUserGetClassName(hWnd, ClassName, nMaxCount);
- Status = RtlUnicodeToMultiByteN (lpClassName,
- result,
- NULL,
- ClassName,
- result);
- if (!NT_SUCCESS(Status))
- {
- return 0;
- }
- RtlFreeHeap(RtlGetProcessHeap(),0,ClassName);
- return result;
+ int result;
+ LPWSTR ClassNameW;
+ NTSTATUS Status;
+
+ if(!lpClassName)
+ return 0;
+
+ ClassNameW = HEAP_alloc ( (nMaxCount+1)*sizeof(WCHAR) );
+
+ result = NtUserGetClassName ( hWnd, ClassNameW, nMaxCount );
+
+ Status = HEAP_strcpyWtoA ( lpClassName, ClassNameW, result );
+
+ HEAP_free ( ClassNameW );
+
+ if ( !NT_SUCCESS(Status) )
+ return 0;
+
+ return result;
}
LPWSTR lpClassName,
int nMaxCount)
{
- int result;
- LPWSTR ClassName;
- ClassName = RtlAllocateHeap(RtlGetProcessHeap(),HEAP_ZERO_MEMORY,nMaxCount);
- result = NtUserGetClassName(hWnd, ClassName, nMaxCount);
- RtlCopyMemory(ClassName,lpClassName,result);
- RtlFreeHeap(RtlGetProcessHeap(),0,ClassName);
- return result;
+ return NtUserGetClassName(hWnd, lpClassName, nMaxCount);
}
/*
- * @unimplemented
+ * @implemented
*/
WORD
STDCALL
* NOTE: Obsoleted in 32-bit windows
*/
{
- UNIMPLEMENTED;
- return 0;
+ if ((nIndex < 0) && (nIndex != GCW_ATOM))
+ return 0;
+
+ return (WORD) NtUserGetClassLong ( hWnd, nIndex, TRUE );
}
/*
* @implemented
*/
-LONG STDCALL
-GetWindowLongA(HWND hWnd, int nIndex)
+LONG
+STDCALL
+GetWindowLongA ( HWND hWnd, int nIndex )
{
return NtUserGetWindowLong(hWnd, nIndex, TRUE);
}
/*
* @implemented
*/
-LONG STDCALL
+LONG
+STDCALL
GetWindowLongW(HWND hWnd, int nIndex)
{
return NtUserGetWindowLong(hWnd, nIndex, FALSE);
/*
* @implemented
*/
-WORD STDCALL
+WORD
+STDCALL
GetWindowWord(HWND hWnd, int nIndex)
{
return (WORD)NtUserGetWindowLong(hWnd, nIndex, TRUE);
}
/*
- * @unimplemented
+ * @implemented
+ */
+WORD
+STDCALL
+SetWindowWord ( HWND hWnd,int nIndex,WORD wNewWord )
+{
+ return (WORD)NtUserSetWindowLong ( hWnd, nIndex, (LONG)wNewWord, TRUE );
+}
+
+/*
+ * @implemented
*/
UINT
STDCALL
RealGetWindowClassW(
HWND hwnd,
- LPSTR pszType,
+ LPWSTR pszType,
UINT cchType)
{
- UNIMPLEMENTED;
- return 0;
+ /* FIXME: Implement correct functionality of RealGetWindowClass */
+ return GetClassNameW(hwnd,pszType,cchType);
}
/*
- * @unimplemented
+ * @implemented
*/
UINT
STDCALL
LPSTR pszType,
UINT cchType)
{
- UNIMPLEMENTED;
- return 0;
+ /* FIXME: Implement correct functionality of RealGetWindowClass */
+ return GetClassNameA(hwnd,pszType,cchType);
}
/*
- * @implemented
+ * Create a small icon based on a standard icon
*/
-ATOM STDCALL
-RegisterClassA(CONST WNDCLASSA *lpWndClass)
+static HICON
+CreateSmallIcon(HICON StdIcon)
{
- WNDCLASSEXA Class;
-
- if ( !lpWndClass ) return (ATOM)0;
-
- RtlMoveMemory ( &Class.style, lpWndClass, sizeof(WNDCLASSA) );
-
- Class.cbSize = sizeof(WNDCLASSEXA);
- Class.hIconSm = INVALID_HANDLE_VALUE;
-
- return RegisterClassExA ( &Class );
+ HICON SmallIcon = NULL;
+ ICONINFO StdInfo;
+ int SmallIconWidth;
+ int SmallIconHeight;
+ BITMAP StdBitmapInfo;
+ HDC hInfoDc = NULL;
+ HDC hSourceDc = NULL;
+ HDC hDestDc = NULL;
+ ICONINFO SmallInfo;
+ HBITMAP OldSourceBitmap = NULL;
+ HBITMAP OldDestBitmap = NULL;
+
+ SmallInfo.hbmColor = NULL;
+ SmallInfo.hbmMask = NULL;
+
+ /* We need something to work with... */
+ if (NULL == StdIcon)
+ {
+ goto cleanup;
+ }
+
+ SmallIconWidth = GetSystemMetrics(SM_CXSMICON);
+ SmallIconHeight = GetSystemMetrics(SM_CYSMICON);
+ if (! GetIconInfo(StdIcon, &StdInfo))
+ {
+ DPRINT1("Failed to get icon info for icon 0x%x\n", StdIcon);
+ goto cleanup;
+ }
+ if (! GetObjectW(StdInfo.hbmMask, sizeof(BITMAP), &StdBitmapInfo))
+ {
+ DPRINT1("Failed to get bitmap info for icon 0x%x bitmap 0x%x\n",
+ StdIcon, StdInfo.hbmColor);
+ goto cleanup;
+ }
+ if (StdBitmapInfo.bmWidth == SmallIconWidth &&
+ StdBitmapInfo.bmHeight == SmallIconHeight)
+ {
+ /* Icon already has the correct dimensions */
+ return StdIcon;
+ }
+
+ /* Get a handle to a info DC and handles to DCs which can be used to
+ select a bitmap into. This is done to avoid triggering a switch to
+ graphics mode (if we're currently in text/blue screen mode) */
+ hInfoDc = CreateICW(NULL, NULL, NULL, NULL);
+ if (NULL == hInfoDc)
+ {
+ DPRINT1("Failed to create info DC\n");
+ goto cleanup;
+ }
+ hSourceDc = CreateCompatibleDC(NULL);
+ if (NULL == hSourceDc)
+ {
+ DPRINT1("Failed to create source DC\n");
+ goto cleanup;
+ }
+ hDestDc = CreateCompatibleDC(NULL);
+ if (NULL == hDestDc)
+ {
+ DPRINT1("Failed to create dest DC\n");
+ goto cleanup;
+ }
+
+ OldSourceBitmap = SelectObject(hSourceDc, StdInfo.hbmColor);
+ if (NULL == OldSourceBitmap)
+ {
+ DPRINT1("Failed to select source color bitmap\n");
+ goto cleanup;
+ }
+ SmallInfo.hbmColor = CreateCompatibleBitmap(hInfoDc, SmallIconWidth,
+ SmallIconHeight);
+ if (NULL == SmallInfo.hbmColor)
+ {
+ DPRINT1("Failed to create color bitmap\n");
+ goto cleanup;
+ }
+ OldDestBitmap = SelectObject(hDestDc, SmallInfo.hbmColor);
+ if (NULL == OldDestBitmap)
+ {
+ DPRINT1("Failed to select dest color bitmap\n");
+ goto cleanup;
+ }
+ if (! StretchBlt(hDestDc, 0, 0, SmallIconWidth, SmallIconHeight,
+ hSourceDc, 0, 0, StdBitmapInfo.bmWidth,
+ StdBitmapInfo.bmHeight, SRCCOPY))
+ {
+ DPRINT1("Failed to stretch color bitmap\n");
+ goto cleanup;
+ }
+
+ if (NULL == SelectObject(hSourceDc, StdInfo.hbmMask))
+ {
+ DPRINT1("Failed to select source mask bitmap\n");
+ goto cleanup;
+ }
+ SmallInfo.hbmMask = CreateBitmap(SmallIconWidth, SmallIconHeight, 1, 1,
+ NULL);
+ if (NULL == SmallInfo.hbmMask)
+ {
+ DPRINT1("Failed to create mask bitmap\n");
+ goto cleanup;
+ }
+ if (NULL == SelectObject(hDestDc, SmallInfo.hbmMask))
+ {
+ DPRINT1("Failed to select dest mask bitmap\n");
+ goto cleanup;
+ }
+ if (! StretchBlt(hDestDc, 0, 0, SmallIconWidth, SmallIconHeight,
+ hSourceDc, 0, 0, StdBitmapInfo.bmWidth,
+ StdBitmapInfo.bmHeight, SRCCOPY))
+ {
+ DPRINT1("Failed to stretch mask bitmap\n");
+ goto cleanup;
+ }
+
+ SmallInfo.fIcon = TRUE;
+ SmallInfo.xHotspot = SmallIconWidth / 2;
+ SmallInfo.yHotspot = SmallIconHeight / 2;
+ SmallIcon = CreateIconIndirect(&SmallInfo);
+ if (NULL == SmallIcon)
+ {
+ DPRINT1("Failed to create icon\n");
+ goto cleanup;
+ }
+
+cleanup:
+ if (NULL != SmallInfo.hbmMask)
+ {
+ DeleteObject(SmallInfo.hbmMask);
+ }
+ if (NULL != OldDestBitmap)
+ {
+ SelectObject(hDestDc, OldDestBitmap);
+ }
+ if (NULL != SmallInfo.hbmColor)
+ {
+ DeleteObject(SmallInfo.hbmColor);
+ }
+ if (NULL != hDestDc)
+ {
+ DeleteDC(hDestDc);
+ }
+ if (NULL != OldSourceBitmap)
+ {
+ SelectObject(hSourceDc, OldSourceBitmap);
+ }
+ if (NULL != hSourceDc)
+ {
+ DeleteDC(hSourceDc);
+ }
+ if (NULL != hInfoDc)
+ {
+ DeleteDC(hInfoDc);
+ }
+
+ return SmallIcon;
}
/*
ATOM STDCALL
RegisterClassExA(CONST WNDCLASSEXA *lpwcx)
{
- RTL_ATOM Atom;
- WNDCLASSEXW wndclass;
- HANDLE hHeap;
- NTSTATUS Status;
- LPWSTR ClassName = NULL;
- LPWSTR MenuName = NULL;
-
- if(!lpwcx || (lpwcx->cbSize != sizeof(WNDCLASSEXA)))
- return (ATOM)0;
-
- if(!lpwcx->lpszClassName) return (ATOM)0;
-
- hHeap = RtlGetProcessHeap();
- RtlMoveMemory(&wndclass, lpwcx, sizeof(WNDCLASSEXW));
-
- if ( !IS_ATOM(lpwcx->lpszClassName) )
- {
- Status = HEAP_strdupA2W (hHeap, &ClassName, (LPCSTR)lpwcx->lpszClassName, NULL);
- if (!NT_SUCCESS (Status))
- {
- SetLastError (RtlNtStatusToDosError(Status));
+ RTL_ATOM Atom;
+ WNDCLASSEXA WndClass;
+ UNICODE_STRING ClassName;
+ UNICODE_STRING MenuName;
+ HMENU hMenu;
+
+ if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXA) ||
+ lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||
+ lpwcx->lpszClassName == NULL)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
return 0;
- }
- wndclass.lpszClassName = ClassName;
- }
-
- if ( !IS_ATOM(lpwcx->lpszMenuName) )
- {
- Status = HEAP_strdupA2W (hHeap, &MenuName, (LPCSTR)lpwcx->lpszMenuName, NULL);
- if (!NT_SUCCESS (Status))
- {
- if(HIWORD(lpwcx->lpszClassName))
- {
- RtlFreeHeap (hHeap, 0, ClassName);
- }
- SetLastError (RtlNtStatusToDosError(Status));
+ }
+
+ /*
+ * On real Windows this looks more like:
+ * if (lpwcx->hInstance == User32Instance &&
+ * *(PULONG)((ULONG_PTR)NtCurrentTeb() + 0x6D4) & 0x400)
+ * But since I have no idea what the magic field in the
+ * TEB structure means, I rather decided to omit that.
+ * -- Filip Navara
+ */
+ if (lpwcx->hInstance == User32Instance)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
return 0;
- }
- wndclass.lpszMenuName = MenuName;
- }
-
- Atom = NtUserRegisterClassExWOW (
- &wndclass,
- FALSE,
- 0,
- 0,
- 0);
+ }
- /* free strings if neccessary */
- if(MenuName) RtlFreeHeap (hHeap, 0, MenuName);
- if(ClassName) RtlFreeHeap (hHeap, 0, ClassName);
+ /* Yes, this is correct. We should modify the passed structure. */
+ if (lpwcx->hInstance == NULL)
+ ((WNDCLASSEXA*)lpwcx)->hInstance = GetModuleHandleW(NULL);
- return (ATOM)Atom;
-}
+ RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXA));
+ if (NULL == WndClass.hIconSm)
+ {
+ WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon);
+ }
+ if HIWORD(lpwcx->lpszMenuName)
+ {
+ hMenu = 0;
+ RtlCreateUnicodeStringFromAsciiz(&MenuName, WndClass.lpszMenuName);
+ }
+ else
+ {
+ MenuName.Length =
+ MenuName.MaximumLength = 0;
+ MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName;
+ hMenu = LoadMenuA(WndClass.hInstance, lpwcx->lpszMenuName);
+ }
+
+ if (IS_ATOM(WndClass.lpszClassName))
+ {
+ ClassName.Length =
+ ClassName.MaximumLength = 0;
+ ClassName.Buffer = (LPWSTR)WndClass.lpszClassName;
+ } else
+ {
+ RtlCreateUnicodeStringFromAsciiz(&ClassName, WndClass.lpszClassName);
+ }
+
+ Atom = NtUserRegisterClassExWOW(
+ (WNDCLASSEXW*)&WndClass,
+ &ClassName,
+ &ClassName,
+ &MenuName,
+ NULL,
+ REGISTERCLASS_ANSI,
+ 0,
+ hMenu);
+
+ if (!IS_ATOM(WndClass.lpszMenuName))
+ RtlFreeUnicodeString(&MenuName);
+ if (!IS_ATOM(WndClass.lpszClassName))
+ RtlFreeUnicodeString(&ClassName);
+
+ return (ATOM)Atom;
+}
/*
* @implemented
ATOM STDCALL
RegisterClassExW(CONST WNDCLASSEXW *lpwcx)
{
- RTL_ATOM Atom;
- HANDLE hHeap;
- WNDCLASSEXW wndclass;
- LPWSTR ClassName = NULL;
- LPWSTR MenuName = NULL;
- ULONG len;
-
- if(!lpwcx || (lpwcx->cbSize != sizeof(WNDCLASSEXA)))
- return (ATOM)0;
+ WNDCLASSEXW WndClass;
+ UNICODE_STRING ClassName;
+ UNICODE_STRING MenuName;
+ HMENU hMenu;
+
+ if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) ||
+ lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||
+ lpwcx->lpszClassName == NULL)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+
+ /*
+ * On real Windows this looks more like:
+ * if (lpwcx->hInstance == User32Instance &&
+ * *(PULONG)((ULONG_PTR)NtCurrentTeb() + 0x6D4) & 0x400)
+ * But since I have no idea what the magic field in the
+ * TEB structure means, I rather decided to omit that.
+ * -- Filip Navara
+ */
+ if (lpwcx->hInstance == User32Instance)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
- if(!lpwcx->lpszClassName) return (ATOM)0;
+ /* Yes, this is correct. We should modify the passed structure. */
+ if (lpwcx->hInstance == NULL)
+ ((WNDCLASSEXW*)lpwcx)->hInstance = GetModuleHandleW(NULL);
- hHeap = RtlGetProcessHeap();
- RtlMoveMemory(&wndclass, lpwcx, sizeof(WNDCLASSEXW));
+ RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXW));
- /* copy strings if needed */
+ if (NULL == WndClass.hIconSm)
+ {
+ WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon);
+ }
- if ( !IS_ATOM(lpwcx->lpszClassName) )
- {
- len = lstrlenW(lpwcx->lpszClassName);
- ClassName = RtlAllocateHeap (hHeap, 0, (len + 1) * sizeof(WCHAR));
- if(!ClassName)
- {
- SetLastError(RtlNtStatusToDosError(STATUS_NO_MEMORY));
- return 0;
+ if HIWORD(lpwcx->lpszMenuName)
+ {
+ hMenu = 0;
+ RtlInitUnicodeString(&MenuName, WndClass.lpszMenuName);
}
- RtlMoveMemory(&ClassName, &lpwcx->lpszClassName, len);
+ else
+ {
+ MenuName.Length =
+ MenuName.MaximumLength = 0;
+ MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName;
+ hMenu = LoadMenuW(WndClass.hInstance, lpwcx->lpszMenuName);
+ }
+
+ if (IS_ATOM(WndClass.lpszClassName))
+ {
+ ClassName.Length =
+ ClassName.MaximumLength = 0;
+ ClassName.Buffer = (LPWSTR)WndClass.lpszClassName;
+ } else
+ {
+ RtlInitUnicodeString(&ClassName, WndClass.lpszClassName);
+ }
+
+ return (ATOM)NtUserRegisterClassExWOW(
+ &WndClass,
+ &ClassName,
+ &ClassName,
+ &MenuName,
+ NULL,
+ 0,
+ 0,
+ hMenu);
+}
- wndclass.lpszClassName = ClassName;
- }
+/*
+ * @implemented
+ */
+ATOM STDCALL
+RegisterClassA(CONST WNDCLASSA *lpWndClass)
+{
+ WNDCLASSEXA Class;
- if ( !IS_ATOM(lpwcx->lpszMenuName) )
- {
- len = lstrlenW(lpwcx->lpszMenuName);
- MenuName = RtlAllocateHeap (hHeap, 0, (len + 1) * sizeof(WCHAR));
- if(!MenuName)
- {
- if(HIWORD(lpwcx->lpszClassName))
- {
- RtlFreeHeap (hHeap, 0, MenuName);
- }
- SetLastError(RtlNtStatusToDosError(STATUS_NO_MEMORY));
+ if (lpWndClass == NULL)
return 0;
- }
- RtlMoveMemory(&MenuName, &lpwcx->lpszMenuName, len);
-
- wndclass.lpszMenuName = MenuName;
- }
- Atom = NtUserRegisterClassExWOW (
- &wndclass,
- TRUE,
- 0,
- 0,
- 0);
+ RtlCopyMemory(&Class.style, lpWndClass, sizeof(WNDCLASSA));
+ Class.cbSize = sizeof(WNDCLASSEXA);
+ Class.hIconSm = NULL;
- /* free strings if neccessary */
- if(MenuName) RtlFreeHeap (hHeap, 0, MenuName);
- if(ClassName) RtlFreeHeap (hHeap, 0, ClassName);
-
- return (ATOM)Atom;
+ return RegisterClassExA(&Class);
}
/*
ATOM STDCALL
RegisterClassW(CONST WNDCLASSW *lpWndClass)
{
- WNDCLASSEXW Class;
+ WNDCLASSEXW Class;
- if ( !lpWndClass ) return (ATOM)0;
+ if (lpWndClass == NULL)
+ return 0;
- RtlMoveMemory ( &Class.style, lpWndClass, sizeof(WNDCLASSW) );
- Class.cbSize = sizeof(WNDCLASSEXW);
- Class.hIconSm = INVALID_HANDLE_VALUE;
- return RegisterClassExW ( &Class );
+ RtlCopyMemory(&Class.style, lpWndClass, sizeof(WNDCLASSW));
+ Class.cbSize = sizeof(WNDCLASSEXW);
+ Class.hIconSm = NULL;
+
+ return RegisterClassExW(&Class);
}
/*
- * @unimplemented
+ * @implemented
*/
DWORD
STDCALL
-SetClassLongA(
+SetClassLongA (
HWND hWnd,
int nIndex,
LONG dwNewLong)
{
- /* FIXME - handle GCL_MENUNAME special case */
- return(NtUserSetClassLong(hWnd, nIndex, dwNewLong, TRUE));
+ UNICODE_STRING str2buf;
+ PUNICODE_STRING str;
+ PUNICODE_STRING str2 = &str2buf;
+
+ if ( nIndex != GCL_MENUNAME )
+ {
+ return NtUserSetClassLong ( hWnd, nIndex, dwNewLong, TRUE );
+ }
+ if ( IS_INTRESOURCE(dwNewLong) )
+ {
+ str2 = (PUNICODE_STRING)dwNewLong;
+ }
+ else
+ {
+ RtlCreateUnicodeStringFromAsciiz ( &str2buf,(LPSTR)dwNewLong );
+ }
+
+ str = (PUNICODE_STRING)NtUserSetClassLong(hWnd, nIndex, (DWORD)str2, TRUE);
+
+ if ( !IS_INTRESOURCE(dwNewLong) )
+ {
+ RtlFreeUnicodeString ( str2 );
+ }
+ if ( IS_INTRESOURCE(str) )
+ {
+ return (DWORD)str;
+ }
+ else
+ {
+ return (DWORD)heap_string_poolA ( str->Buffer, str->Length );
+ }
}
/*
- * @unimplemented
+ * @implemented
*/
DWORD
STDCALL
int nIndex,
LONG dwNewLong)
{
- /* FIXME - handle GCL_MENUNAME special case */
- return(NtUserSetClassLong(hWnd, nIndex, dwNewLong, FALSE));
+ UNICODE_STRING str2buf;
+ PUNICODE_STRING str;
+ PUNICODE_STRING str2 = &str2buf;
+
+ if (nIndex != GCL_MENUNAME )
+ {
+ return NtUserSetClassLong ( hWnd, nIndex, dwNewLong, FALSE );
+ }
+ if ( IS_INTRESOURCE(dwNewLong) )
+ {
+ str2 = (PUNICODE_STRING)dwNewLong;
+ }
+ else
+ {
+ RtlCreateUnicodeString ( &str2buf, (LPWSTR)dwNewLong );
+ }
+
+ str = (PUNICODE_STRING)NtUserSetClassLong(hWnd, nIndex, (DWORD)str2, TRUE);
+
+ if ( !IS_INTRESOURCE(dwNewLong) )
+ {
+ RtlFreeUnicodeString(str2);
+ }
+ if ( IS_INTRESOURCE(str) )
+ {
+ return (DWORD)str;
+ }
+ else
+ {
+ return (DWORD)heap_string_poolW ( str->Buffer, str->Length );
+ }
}
/*
- * @unimplemented
+ * @implemented
*/
WORD
STDCALL
* NOTE: Obsoleted in 32-bit windows
*/
{
- UNIMPLEMENTED;
- return 0;
+ if ((nIndex < 0) && (nIndex != GCW_ATOM))
+ return 0;
+
+ return (WORD) NtUserSetClassLong ( hWnd, nIndex, wNewWord, TRUE );
}
/*
- * @unimplemented
+ * @implemented
*/
-WINBOOL
+BOOL
STDCALL
UnregisterClassA(
LPCSTR lpClassName,
HINSTANCE hInstance)
{
- UNIMPLEMENTED;
- return FALSE;
+ LPWSTR ClassName;
+ NTSTATUS Status;
+ BOOL Result;
+
+ if(!IS_ATOM(lpClassName))
+ {
+ Status = HEAP_strdupAtoW(&ClassName, lpClassName, NULL);
+ if(!NT_SUCCESS(Status))
+ {
+ SetLastError(RtlNtStatusToDosError(Status));
+ return FALSE;
+ }
+ }
+ else
+ ClassName = (LPWSTR)lpClassName;
+
+ Result = (BOOL)NtUserUnregisterClass((LPCWSTR)ClassName, hInstance, 0);
+
+ if(ClassName && !IS_ATOM(lpClassName))
+ HEAP_free(ClassName);
+
+ return Result;
}
/*
- * @unimplemented
+ * @implemented
*/
-WINBOOL
+BOOL
STDCALL
UnregisterClassW(
LPCWSTR lpClassName,
HINSTANCE hInstance)
{
- UNIMPLEMENTED;
- return FALSE;
+ return (BOOL)NtUserUnregisterClass(lpClassName, hInstance, 0);
}
/* EOF */