mirror of
https://github.com/reactos/reactos.git
synced 2024-11-09 16:20:37 +00:00
2b82fe44ea
- Create a branch to drop my ndisuio work svn path=/branches/wlan-bringup/; revision=54809
1600 lines
35 KiB
C
1600 lines
35 KiB
C
/*
|
|
* PROJECT: ReactOS user32.dll
|
|
* COPYRIGHT: GPL - See COPYING in the top level directory
|
|
* FILE: dll/win32/user32/windows/class.c
|
|
* PURPOSE: Window classes
|
|
* PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
|
|
* UPDATE HISTORY:
|
|
* 09-05-2001 CSH Created
|
|
*/
|
|
|
|
#include <user32.h>
|
|
|
|
#include <wine/debug.h>
|
|
WINE_DEFAULT_DEBUG_CHANNEL(user32);
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
GetClassInfoExA(
|
|
HINSTANCE hInstance,
|
|
LPCSTR lpszClass,
|
|
LPWNDCLASSEXA lpwcx)
|
|
{
|
|
UNICODE_STRING ClassName = {0};
|
|
BOOL Ret;
|
|
LPCSTR pszMenuName;
|
|
|
|
TRACE("%p class/atom: %s/%04x %p\n", hInstance,
|
|
IS_ATOM(lpszClass) ? NULL : lpszClass,
|
|
IS_ATOM(lpszClass) ? lpszClass : 0,
|
|
lpwcx);
|
|
|
|
if (!lpwcx)
|
|
{
|
|
SetLastError( ERROR_NOACCESS );
|
|
return FALSE;
|
|
}
|
|
|
|
if (hInstance == User32Instance)
|
|
{
|
|
hInstance = NULL;
|
|
}
|
|
|
|
if (lpszClass == NULL)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!RegisterDefaultClasses)
|
|
{
|
|
ERR("GetClassInfoExA RegisterSystemControls\n");
|
|
RegisterSystemControls();
|
|
}
|
|
|
|
if (IS_ATOM(lpszClass))
|
|
{
|
|
ClassName.Buffer = (PWSTR)((ULONG_PTR)lpszClass);
|
|
}
|
|
else
|
|
{
|
|
if (!RtlCreateUnicodeStringFromAsciiz(&ClassName,
|
|
lpszClass))
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
Ret = NtUserGetClassInfo(hInstance,
|
|
&ClassName,
|
|
(LPWNDCLASSEXW)lpwcx,
|
|
(LPWSTR *)&pszMenuName,
|
|
TRUE);
|
|
if (Ret)
|
|
{
|
|
lpwcx->lpszClassName = lpszClass;
|
|
// lpwcx->lpszMenuName = pszMenuName;
|
|
}
|
|
|
|
if (!IS_ATOM(lpszClass))
|
|
{
|
|
RtlFreeUnicodeString(&ClassName);
|
|
}
|
|
|
|
return Ret;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
GetClassInfoExW(
|
|
HINSTANCE hInstance,
|
|
LPCWSTR lpszClass,
|
|
LPWNDCLASSEXW lpwcx)
|
|
{
|
|
UNICODE_STRING ClassName = {0};
|
|
BOOL Ret;
|
|
LPWSTR pszMenuName;
|
|
|
|
TRACE("%p class/atom: %S/%04x %p\n", hInstance,
|
|
IS_ATOM(lpszClass) ? NULL : lpszClass,
|
|
IS_ATOM(lpszClass) ? lpszClass : 0,
|
|
lpwcx);
|
|
|
|
/* From wine, for speed only, ReactOS supports the correct return in
|
|
* Win32k. cbSize is ignored.
|
|
*/
|
|
if (!lpwcx)
|
|
{
|
|
SetLastError( ERROR_NOACCESS );
|
|
return FALSE;
|
|
}
|
|
|
|
if (hInstance == User32Instance)
|
|
{
|
|
hInstance = NULL;
|
|
}
|
|
|
|
if (lpszClass == NULL)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!RegisterDefaultClasses)
|
|
{
|
|
ERR("GetClassInfoExW RegisterSystemControls\n");
|
|
RegisterSystemControls();
|
|
}
|
|
|
|
if (IS_ATOM(lpszClass))
|
|
{
|
|
ClassName.Buffer = (PWSTR)((ULONG_PTR)lpszClass);
|
|
}
|
|
else
|
|
{
|
|
RtlInitUnicodeString(&ClassName,
|
|
lpszClass);
|
|
}
|
|
|
|
Ret = NtUserGetClassInfo( hInstance,
|
|
&ClassName,
|
|
lpwcx,
|
|
&pszMenuName,
|
|
FALSE);
|
|
if (Ret)
|
|
{
|
|
lpwcx->lpszClassName = lpszClass;
|
|
// lpwcx->lpszMenuName = pszMenuName;
|
|
}
|
|
return Ret;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
GetClassInfoA(
|
|
HINSTANCE hInstance,
|
|
LPCSTR lpClassName,
|
|
LPWNDCLASSA lpWndClass)
|
|
{
|
|
WNDCLASSEXA wcex;
|
|
BOOL retval;
|
|
|
|
retval = GetClassInfoExA(hInstance, lpClassName, &wcex);
|
|
if (retval)
|
|
{
|
|
lpWndClass->style = wcex.style;
|
|
lpWndClass->lpfnWndProc = wcex.lpfnWndProc;
|
|
lpWndClass->cbClsExtra = wcex.cbClsExtra;
|
|
lpWndClass->cbWndExtra = wcex.cbWndExtra;
|
|
lpWndClass->hInstance = wcex.hInstance;
|
|
lpWndClass->hIcon = wcex.hIcon;
|
|
lpWndClass->hCursor = wcex.hCursor;
|
|
lpWndClass->hbrBackground = wcex.hbrBackground;
|
|
lpWndClass->lpszMenuName = wcex.lpszMenuName;
|
|
lpWndClass->lpszClassName = wcex.lpszClassName;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
GetClassInfoW(
|
|
HINSTANCE hInstance,
|
|
LPCWSTR lpClassName,
|
|
LPWNDCLASSW lpWndClass)
|
|
{
|
|
WNDCLASSEXW wcex;
|
|
BOOL retval;
|
|
|
|
retval = GetClassInfoExW(hInstance, lpClassName, &wcex);
|
|
if (retval)
|
|
{
|
|
lpWndClass->style = wcex.style;
|
|
lpWndClass->lpfnWndProc = wcex.lpfnWndProc;
|
|
lpWndClass->cbClsExtra = wcex.cbClsExtra;
|
|
lpWndClass->cbWndExtra = wcex.cbWndExtra;
|
|
lpWndClass->hInstance = wcex.hInstance;
|
|
lpWndClass->hIcon = wcex.hIcon;
|
|
lpWndClass->hCursor = wcex.hCursor;
|
|
lpWndClass->hbrBackground = wcex.hbrBackground;
|
|
lpWndClass->lpszMenuName = wcex.lpszMenuName;
|
|
lpWndClass->lpszClassName = wcex.lpszClassName;
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
//
|
|
// Based on find_winproc... Fixes many whine tests......
|
|
//
|
|
ULONG_PTR FASTCALL
|
|
IntGetClsWndProc(PWND pWnd, PCLS Class, BOOL Ansi)
|
|
{
|
|
INT i;
|
|
ULONG_PTR gcpd, Ret = 0;
|
|
// If server side, sweep through proc list and return the client side proc.
|
|
if (Class->CSF_flags & CSF_SERVERSIDEPROC)
|
|
{ // Always scan through the list due to wine class "deftest".
|
|
for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
|
|
{
|
|
if (GETPFNSERVER(i) == Class->lpfnWndProc)
|
|
{
|
|
if (Ansi)
|
|
Ret = (ULONG_PTR)GETPFNCLIENTA(i);
|
|
else
|
|
Ret = (ULONG_PTR)GETPFNCLIENTW(i);
|
|
}
|
|
}
|
|
return Ret;
|
|
}
|
|
// Set return proc.
|
|
Ret = (ULONG_PTR)Class->lpfnWndProc;
|
|
// Return the proc if one of the FnId default class type.
|
|
if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON)
|
|
{
|
|
if (Ansi)
|
|
{ // If match return the right proc by type.
|
|
if (GETPFNCLIENTW(Class->fnid) == Class->lpfnWndProc)
|
|
Ret = (ULONG_PTR)GETPFNCLIENTA(Class->fnid);
|
|
}
|
|
else
|
|
{
|
|
if (GETPFNCLIENTA(Class->fnid) == Class->lpfnWndProc)
|
|
Ret = (ULONG_PTR)GETPFNCLIENTW(Class->fnid);
|
|
}
|
|
}
|
|
// Return on change or Ansi/Unicode proc equal.
|
|
if ( Ret != (ULONG_PTR)Class->lpfnWndProc ||
|
|
Ansi == !!(Class->CSF_flags & CSF_ANSIPROC) )
|
|
return Ret;
|
|
|
|
/* We have an Ansi and Unicode swap! If Ansi create Unicode proc handle.
|
|
This will force CallWindowProc to deal with it. */
|
|
gcpd = NtUserGetCPD( UserHMGetHandle(pWnd),
|
|
(Ansi ? UserGetCPDA2U : UserGetCPDU2A )|UserGetCPDWndtoCls,
|
|
Ret);
|
|
|
|
return (gcpd ? gcpd : Ret);
|
|
}
|
|
|
|
//
|
|
// Based on IntGetClsWndProc
|
|
//
|
|
WNDPROC FASTCALL
|
|
IntGetWndProc(PWND pWnd, BOOL Ansi)
|
|
{
|
|
INT i;
|
|
WNDPROC gcpd, Ret = 0;
|
|
PCLS Class = DesktopPtrToUser(pWnd->pcls);
|
|
|
|
if (!Class) return Ret;
|
|
|
|
if (pWnd->state & WNDS_SERVERSIDEWINDOWPROC)
|
|
{
|
|
for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
|
|
{
|
|
if (GETPFNSERVER(i) == pWnd->lpfnWndProc)
|
|
{
|
|
if (Ansi)
|
|
Ret = GETPFNCLIENTA(i);
|
|
else
|
|
Ret = GETPFNCLIENTW(i);
|
|
}
|
|
}
|
|
return Ret;
|
|
}
|
|
// Wine Class tests:
|
|
/* Edit controls are special - they return a wndproc handle when
|
|
GetWindowLongPtr is called with a different A/W.
|
|
On the other hand there is no W->A->W conversion so this control
|
|
is treated specially.
|
|
*/
|
|
if (Class->fnid == FNID_EDIT)
|
|
Ret = pWnd->lpfnWndProc;
|
|
else
|
|
{
|
|
// Set return proc.
|
|
Ret = pWnd->lpfnWndProc;
|
|
|
|
if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON)
|
|
{
|
|
if (Ansi)
|
|
{
|
|
if (GETPFNCLIENTW(Class->fnid) == pWnd->lpfnWndProc)
|
|
Ret = GETPFNCLIENTA(Class->fnid);
|
|
}
|
|
else
|
|
{
|
|
if (GETPFNCLIENTA(Class->fnid) == pWnd->lpfnWndProc)
|
|
Ret = GETPFNCLIENTW(Class->fnid);
|
|
}
|
|
}
|
|
// Return on the change.
|
|
if ( Ret != pWnd->lpfnWndProc)
|
|
return Ret;
|
|
}
|
|
|
|
if ( Ansi == !!(pWnd->state & WNDS_ANSIWINDOWPROC) )
|
|
return Ret;
|
|
|
|
gcpd = (WNDPROC)NtUserGetCPD( UserHMGetHandle(pWnd),
|
|
(Ansi ? UserGetCPDA2U : UserGetCPDU2A )|UserGetCPDWindow,
|
|
(ULONG_PTR)Ret);
|
|
|
|
return (gcpd ? gcpd : Ret);
|
|
}
|
|
|
|
static ULONG_PTR FASTCALL
|
|
IntGetClassLongA(PWND Wnd, PCLS Class, int nIndex)
|
|
{
|
|
ULONG_PTR Ret = 0;
|
|
|
|
if (nIndex >= 0)
|
|
{
|
|
if (nIndex + sizeof(ULONG_PTR) < nIndex ||
|
|
nIndex + sizeof(ULONG_PTR) > Class->cbclsExtra)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
}
|
|
else
|
|
Ret = *(PULONG_PTR)((ULONG_PTR)(Class + 1) + nIndex);
|
|
}
|
|
else
|
|
{
|
|
switch (nIndex)
|
|
{
|
|
case GCL_CBWNDEXTRA:
|
|
Ret = (ULONG_PTR)Class->cbwndExtra;
|
|
break;
|
|
|
|
case GCL_CBCLSEXTRA:
|
|
Ret = (ULONG_PTR)Class->cbclsExtra;
|
|
break;
|
|
|
|
case GCL_HBRBACKGROUND:
|
|
Ret = (ULONG_PTR)Class->hbrBackground;
|
|
if (Ret != 0 && Ret < 0x4000)
|
|
Ret = (ULONG_PTR)GetSysColorBrush((ULONG)Ret - 1);
|
|
break;
|
|
|
|
case GCL_HMODULE:
|
|
//ERR("Cls 0x%x GCL_HMODULE 0x%x\n", Wnd->pcls, Class->hModule);
|
|
Ret = (ULONG_PTR)Class->hModule;
|
|
break;
|
|
|
|
case GCL_MENUNAME:
|
|
Ret = (ULONG_PTR)Class->lpszClientAnsiMenuName;
|
|
break;
|
|
|
|
case GCL_STYLE:
|
|
Ret = (ULONG_PTR)Class->style;
|
|
break;
|
|
|
|
case GCW_ATOM:
|
|
Ret = (ULONG_PTR)Class->atomClassName;
|
|
break;
|
|
|
|
case GCLP_HCURSOR:
|
|
/* FIXME - get handle from pointer to CURSOR object */
|
|
Ret = (ULONG_PTR)Class->hCursor;
|
|
break;
|
|
|
|
case GCLP_HICON:
|
|
/* FIXME - get handle from pointer to ICON object */
|
|
Ret = (ULONG_PTR)Class->hIcon;
|
|
break;
|
|
|
|
case GCLP_HICONSM:
|
|
/* FIXME - get handle from pointer to ICON object */
|
|
Ret = (ULONG_PTR)Class->hIconSm;
|
|
break;
|
|
|
|
case GCLP_WNDPROC:
|
|
Ret = IntGetClsWndProc(Wnd, Class, TRUE);
|
|
break;
|
|
|
|
default:
|
|
SetLastError(ERROR_INVALID_INDEX);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return Ret;
|
|
}
|
|
|
|
static ULONG_PTR FASTCALL
|
|
IntGetClassLongW (PWND Wnd, PCLS Class, int nIndex)
|
|
{
|
|
ULONG_PTR Ret = 0;
|
|
|
|
if (nIndex >= 0)
|
|
{
|
|
if (nIndex + sizeof(ULONG_PTR) < nIndex ||
|
|
nIndex + sizeof(ULONG_PTR) > Class->cbclsExtra)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
}
|
|
else
|
|
Ret = *(PULONG_PTR)((ULONG_PTR)(Class + 1) + nIndex);
|
|
}
|
|
else
|
|
{
|
|
switch (nIndex)
|
|
{
|
|
case GCL_CBWNDEXTRA:
|
|
Ret = (ULONG_PTR)Class->cbwndExtra;
|
|
break;
|
|
|
|
case GCL_CBCLSEXTRA:
|
|
Ret = (ULONG_PTR)Class->cbclsExtra;
|
|
break;
|
|
|
|
case GCLP_HBRBACKGROUND:
|
|
Ret = (ULONG_PTR)Class->hbrBackground;
|
|
if (Ret != 0 && Ret < 0x4000)
|
|
Ret = (ULONG_PTR)GetSysColorBrush((ULONG)Ret - 1);
|
|
break;
|
|
|
|
case GCL_HMODULE:
|
|
Ret = (ULONG_PTR)Class->hModule;
|
|
break;
|
|
|
|
case GCLP_MENUNAME:
|
|
Ret = (ULONG_PTR)Class->lpszClientUnicodeMenuName;
|
|
break;
|
|
|
|
case GCL_STYLE:
|
|
Ret = (ULONG_PTR)Class->style;
|
|
break;
|
|
|
|
case GCW_ATOM:
|
|
Ret = (ULONG_PTR)Class->atomClassName;
|
|
break;
|
|
|
|
case GCLP_HCURSOR:
|
|
/* FIXME - get handle from pointer to CURSOR object */
|
|
Ret = (ULONG_PTR)Class->hCursor;
|
|
break;
|
|
|
|
case GCLP_HICON:
|
|
/* FIXME - get handle from pointer to ICON object */
|
|
Ret = (ULONG_PTR)Class->hIcon;
|
|
break;
|
|
|
|
case GCLP_HICONSM:
|
|
/* FIXME - get handle from pointer to ICON object */
|
|
Ret = (ULONG_PTR)Class->hIconSm;
|
|
break;
|
|
|
|
case GCLP_WNDPROC:
|
|
Ret = IntGetClsWndProc(Wnd, Class, FALSE);
|
|
break;
|
|
|
|
default:
|
|
SetLastError(ERROR_INVALID_INDEX);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return Ret;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
DWORD WINAPI
|
|
GetClassLongA(HWND hWnd, int nIndex)
|
|
{
|
|
PWND Wnd;
|
|
PCLS Class;
|
|
ULONG_PTR Ret = 0;
|
|
|
|
TRACE("%p %d\n", hWnd, nIndex);
|
|
|
|
Wnd = ValidateHwnd(hWnd);
|
|
if (!Wnd)
|
|
return 0;
|
|
|
|
_SEH2_TRY
|
|
{
|
|
Class = DesktopPtrToUser(Wnd->pcls);
|
|
if (Class != NULL)
|
|
{
|
|
#ifdef _WIN64
|
|
switch (nIndex)
|
|
{
|
|
case GCLP_HBRBACKGROUND:
|
|
case GCLP_HCURSOR:
|
|
case GCLP_HICON:
|
|
case GCLP_HICONSM:
|
|
case GCLP_HMODULE:
|
|
case GCLP_MENUNAME:
|
|
case GCLP_WNDPROC:
|
|
SetLastError(ERROR_INVALID_INDEX);
|
|
break;
|
|
|
|
default:
|
|
Ret = IntGetClassLongA(Wnd, Class, nIndex);
|
|
break;
|
|
}
|
|
#else
|
|
Ret = IntGetClassLongA(Wnd, Class, nIndex);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
WARN("Invalid class for hwnd 0x%p!\n", hWnd);
|
|
}
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Ret = 0;
|
|
}
|
|
_SEH2_END;
|
|
|
|
return (DWORD)Ret;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
DWORD WINAPI
|
|
GetClassLongW ( HWND hWnd, int nIndex )
|
|
{
|
|
PWND Wnd;
|
|
PCLS Class;
|
|
ULONG_PTR Ret = 0;
|
|
|
|
TRACE("%p %d\n", hWnd, nIndex);
|
|
|
|
Wnd = ValidateHwnd(hWnd);
|
|
if (!Wnd)
|
|
return 0;
|
|
|
|
_SEH2_TRY
|
|
{
|
|
Class = DesktopPtrToUser(Wnd->pcls);
|
|
if (Class != NULL)
|
|
{
|
|
#ifdef _WIN64
|
|
switch (nIndex)
|
|
{
|
|
case GCLP_HBRBACKGROUND:
|
|
case GCLP_HCURSOR:
|
|
case GCLP_HICON:
|
|
case GCLP_HICONSM:
|
|
case GCLP_HMODULE:
|
|
case GCLP_MENUNAME:
|
|
case GCLP_WNDPROC:
|
|
SetLastError(ERROR_INVALID_INDEX);
|
|
break;
|
|
|
|
default:
|
|
Ret = IntGetClassLongW(Wnd, Class, nIndex);
|
|
break;
|
|
}
|
|
#else
|
|
Ret = IntGetClassLongW(Wnd, Class, nIndex);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
WARN("Invalid class for hwnd 0x%p!\n", hWnd);
|
|
}
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Ret = 0;
|
|
}
|
|
_SEH2_END;
|
|
|
|
return (DWORD)Ret;
|
|
}
|
|
|
|
#ifdef _WIN64
|
|
/*
|
|
* @implemented
|
|
*/
|
|
ULONG_PTR
|
|
WINAPI
|
|
GetClassLongPtrA(HWND hWnd,
|
|
INT nIndex)
|
|
{
|
|
PWND Wnd;
|
|
PCLS Class;
|
|
ULONG_PTR Ret = 0;
|
|
|
|
TRACE("%p %d\n", hWnd, nIndex);
|
|
|
|
Wnd = ValidateHwnd(hWnd);
|
|
if (!Wnd)
|
|
return 0;
|
|
|
|
_SEH2_TRY
|
|
{
|
|
Class = DesktopPtrToUser(Wnd->pcls);
|
|
if (Class != NULL)
|
|
{
|
|
Ret = IntGetClassLongA(Wnd, Class, nIndex);
|
|
}
|
|
else
|
|
{
|
|
WARN("Invalid class for hwnd 0x%p!\n", hWnd);
|
|
}
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Ret = 0;
|
|
}
|
|
_SEH2_END;
|
|
|
|
return Ret;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
ULONG_PTR
|
|
WINAPI
|
|
GetClassLongPtrW(HWND hWnd,
|
|
INT nIndex)
|
|
{
|
|
PWND Wnd;
|
|
PCLS Class;
|
|
ULONG_PTR Ret = 0;
|
|
|
|
TRACE("%p %d\n", hWnd, nIndex);
|
|
|
|
Wnd = ValidateHwnd(hWnd);
|
|
if (!Wnd)
|
|
return 0;
|
|
|
|
_SEH2_TRY
|
|
{
|
|
Class = DesktopPtrToUser(Wnd->pcls);
|
|
if (Class != NULL)
|
|
{
|
|
Ret = IntGetClassLongW(Wnd, Class, nIndex);
|
|
}
|
|
else
|
|
{
|
|
WARN("Invalid class for hwnd 0x%p!\n", hWnd);
|
|
}
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
Ret = 0;
|
|
}
|
|
_SEH2_END;
|
|
|
|
return Ret;
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
int WINAPI
|
|
GetClassNameA(
|
|
HWND hWnd,
|
|
LPSTR lpClassName,
|
|
int nMaxCount)
|
|
{
|
|
WCHAR tmpbuf[MAX_ATOM_LEN + 1];
|
|
int len;
|
|
|
|
if (nMaxCount <= 0) return 0;
|
|
if (!GetClassNameW( hWnd, tmpbuf, sizeof(tmpbuf)/sizeof(WCHAR) )) return 0;
|
|
RtlUnicodeToMultiByteN( lpClassName, nMaxCount - 1, (PULONG)&len, tmpbuf, strlenW(tmpbuf) * sizeof(WCHAR) );
|
|
lpClassName[len] = 0;
|
|
|
|
TRACE("%p class/atom: %s/%04x %x\n", hWnd,
|
|
IS_ATOM(lpClassName) ? NULL : lpClassName,
|
|
IS_ATOM(lpClassName) ? lpClassName : 0,
|
|
nMaxCount);
|
|
|
|
return len;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
int
|
|
WINAPI
|
|
GetClassNameW(
|
|
HWND hWnd,
|
|
LPWSTR lpClassName,
|
|
int nMaxCount)
|
|
{
|
|
UNICODE_STRING ClassName;
|
|
int Result;
|
|
|
|
ClassName.MaximumLength = nMaxCount * sizeof(WCHAR);
|
|
ClassName.Buffer = lpClassName;
|
|
|
|
Result = NtUserGetClassName(hWnd,
|
|
FALSE,
|
|
&ClassName);
|
|
|
|
TRACE("%p class/atom: %S/%04x %x\n", hWnd,
|
|
IS_ATOM(lpClassName) ? NULL : lpClassName,
|
|
IS_ATOM(lpClassName) ? lpClassName : 0,
|
|
nMaxCount);
|
|
|
|
return Result;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WORD
|
|
WINAPI
|
|
GetClassWord(
|
|
HWND hwnd,
|
|
int offset)
|
|
{
|
|
PWND Wnd;
|
|
PCLS class;
|
|
WORD retvalue = 0;
|
|
|
|
if (offset < 0) return GetClassLongA( hwnd, offset );
|
|
|
|
Wnd = ValidateHwnd(hwnd);
|
|
if (!Wnd)
|
|
return 0;
|
|
|
|
class = DesktopPtrToUser(Wnd->pcls);
|
|
if (class == NULL) return 0;
|
|
|
|
if (offset <= class->cbclsExtra - sizeof(WORD))
|
|
memcpy( &retvalue, (char *)(class + 1) + offset, sizeof(retvalue) );
|
|
else
|
|
SetLastError( ERROR_INVALID_INDEX );
|
|
|
|
return retvalue;
|
|
}
|
|
|
|
|
|
LONG_PTR IntGetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
|
|
{
|
|
LONG_PTR retvalue = 0;
|
|
WND *wndPtr;
|
|
|
|
if (offset == GWLP_HWNDPARENT)
|
|
{
|
|
HWND parent = GetAncestor( hwnd, GA_PARENT );
|
|
if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
|
|
return (ULONG_PTR)parent;
|
|
}
|
|
|
|
if (!(wndPtr = ValidateHwnd( hwnd )))
|
|
{
|
|
SetLastError( ERROR_INVALID_WINDOW_HANDLE );
|
|
return 0;
|
|
}
|
|
|
|
if (offset >= 0)
|
|
{
|
|
if (offset > (int)(wndPtr->cbwndExtra - size))
|
|
{
|
|
WARN("Invalid offset %d\n", offset );
|
|
SetLastError( ERROR_INVALID_INDEX );
|
|
return 0;
|
|
}
|
|
retvalue = *((LONG_PTR *)((PCHAR)(wndPtr + 1) + offset));
|
|
|
|
/* WINE: special case for dialog window procedure */
|
|
//if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
|
|
// retvalue = (LONG_PTR)IntGetWndProc( (WNDPROC)retvalue, unicode );
|
|
return retvalue;
|
|
}
|
|
|
|
switch(offset)
|
|
{
|
|
case GWLP_USERDATA: retvalue = wndPtr->dwUserData; break;
|
|
case GWL_STYLE: retvalue = wndPtr->style; break;
|
|
case GWL_EXSTYLE: retvalue = wndPtr->ExStyle; break;
|
|
case GWLP_ID: retvalue = wndPtr->IDMenu; break;
|
|
case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hModule; break;
|
|
case GWLP_WNDPROC:
|
|
{
|
|
if (!TestWindowProcess(wndPtr))
|
|
{
|
|
SetLastError(ERROR_ACCESS_DENIED);
|
|
retvalue = 0;
|
|
}
|
|
retvalue = (ULONG_PTR)IntGetWndProc(wndPtr, !unicode);
|
|
break;
|
|
}
|
|
default:
|
|
WARN("Unknown offset %d\n", offset );
|
|
SetLastError( ERROR_INVALID_INDEX );
|
|
break;
|
|
}
|
|
return retvalue;
|
|
|
|
}
|
|
/*
|
|
* @implemented
|
|
*/
|
|
LONG
|
|
WINAPI
|
|
GetWindowLongA ( HWND hWnd, int nIndex )
|
|
{
|
|
return IntGetWindowLong( hWnd, nIndex, sizeof(LONG), FALSE );
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
LONG
|
|
WINAPI
|
|
GetWindowLongW(HWND hWnd, int nIndex)
|
|
{
|
|
return IntGetWindowLong( hWnd, nIndex, sizeof(LONG), TRUE );
|
|
}
|
|
|
|
#ifdef _WIN64
|
|
/*
|
|
* @implemented
|
|
*/
|
|
LONG_PTR
|
|
WINAPI
|
|
GetWindowLongPtrA(HWND hWnd,
|
|
INT nIndex)
|
|
{
|
|
return IntGetWindowLong( hWnd, nIndex, sizeof(LONG_PTR), FALSE );
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
LONG_PTR
|
|
WINAPI
|
|
GetWindowLongPtrW(HWND hWnd,
|
|
INT nIndex)
|
|
{
|
|
return IntGetWindowLong( hWnd, nIndex, sizeof(LONG_PTR), TRUE );
|
|
|
|
}
|
|
#endif // _WIN64
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WORD
|
|
WINAPI
|
|
GetWindowWord(HWND hWnd, int nIndex)
|
|
{
|
|
switch(nIndex)
|
|
{
|
|
case GWLP_ID:
|
|
case GWLP_HINSTANCE:
|
|
case GWLP_HWNDPARENT:
|
|
break;
|
|
default:
|
|
if (nIndex < 0)
|
|
{
|
|
WARN("Invalid offset %d\n", nIndex );
|
|
SetLastError( ERROR_INVALID_INDEX );
|
|
return 0;
|
|
}
|
|
break;
|
|
}
|
|
return IntGetWindowLong( hWnd, nIndex, sizeof(WORD), FALSE );
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
UINT
|
|
WINAPI
|
|
RealGetWindowClassW(
|
|
HWND hwnd,
|
|
LPWSTR pszType,
|
|
UINT cchType)
|
|
{
|
|
UNICODE_STRING ClassName;
|
|
ClassName.MaximumLength = cchType * sizeof(WCHAR);
|
|
ClassName.Buffer = (PWSTR)pszType;
|
|
|
|
return NtUserGetClassName(hwnd,TRUE,&ClassName);
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
UINT
|
|
WINAPI
|
|
RealGetWindowClassA(
|
|
HWND hwnd,
|
|
LPSTR pszType,
|
|
UINT cchType)
|
|
{
|
|
WCHAR tmpbuf[MAX_ATOM_LEN + 1];
|
|
UINT len;
|
|
|
|
if ((INT)cchType <= 0) return 0;
|
|
if (!RealGetWindowClassW( hwnd, tmpbuf, sizeof(tmpbuf)/sizeof(WCHAR) )) return 0;
|
|
RtlUnicodeToMultiByteN( pszType, cchType - 1, (PULONG)&len, tmpbuf, strlenW(tmpbuf) * sizeof(WCHAR) );
|
|
pszType[len] = 0;
|
|
return len;
|
|
}
|
|
|
|
/*
|
|
* Create a small icon based on a standard icon
|
|
*/
|
|
static HICON
|
|
CreateSmallIcon(HICON StdIcon)
|
|
{
|
|
HICON SmallIcon = NULL;
|
|
ICONINFO StdInfo;
|
|
int SmallIconWidth;
|
|
int SmallIconHeight;
|
|
BITMAP StdBitmapInfo;
|
|
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))
|
|
{
|
|
ERR("Failed to get icon info for icon 0x%x\n", StdIcon);
|
|
goto cleanup;
|
|
}
|
|
if (! GetObjectW(StdInfo.hbmMask, sizeof(BITMAP), &StdBitmapInfo))
|
|
{
|
|
ERR("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;
|
|
}
|
|
|
|
hSourceDc = CreateCompatibleDC(NULL);
|
|
if (NULL == hSourceDc)
|
|
{
|
|
ERR("Failed to create source DC\n");
|
|
goto cleanup;
|
|
}
|
|
hDestDc = CreateCompatibleDC(NULL);
|
|
if (NULL == hDestDc)
|
|
{
|
|
ERR("Failed to create dest DC\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
OldSourceBitmap = SelectObject(hSourceDc, StdInfo.hbmColor);
|
|
if (NULL == OldSourceBitmap)
|
|
{
|
|
ERR("Failed to select source color bitmap\n");
|
|
goto cleanup;
|
|
}
|
|
SmallInfo.hbmColor = CreateCompatibleBitmap(hSourceDc, SmallIconWidth,
|
|
SmallIconHeight);
|
|
if (NULL == SmallInfo.hbmColor)
|
|
{
|
|
ERR("Failed to create color bitmap\n");
|
|
goto cleanup;
|
|
}
|
|
OldDestBitmap = SelectObject(hDestDc, SmallInfo.hbmColor);
|
|
if (NULL == OldDestBitmap)
|
|
{
|
|
ERR("Failed to select dest color bitmap\n");
|
|
goto cleanup;
|
|
}
|
|
if (! StretchBlt(hDestDc, 0, 0, SmallIconWidth, SmallIconHeight,
|
|
hSourceDc, 0, 0, StdBitmapInfo.bmWidth,
|
|
StdBitmapInfo.bmHeight, SRCCOPY))
|
|
{
|
|
ERR("Failed to stretch color bitmap\n");
|
|
goto cleanup;
|
|
}
|
|
|
|
if (NULL == SelectObject(hSourceDc, StdInfo.hbmMask))
|
|
{
|
|
ERR("Failed to select source mask bitmap\n");
|
|
goto cleanup;
|
|
}
|
|
SmallInfo.hbmMask = CreateCompatibleBitmap(hSourceDc, SmallIconWidth, SmallIconHeight);
|
|
if (NULL == SmallInfo.hbmMask)
|
|
{
|
|
ERR("Failed to create mask bitmap\n");
|
|
goto cleanup;
|
|
}
|
|
if (NULL == SelectObject(hDestDc, SmallInfo.hbmMask))
|
|
{
|
|
ERR("Failed to select dest mask bitmap\n");
|
|
goto cleanup;
|
|
}
|
|
if (! StretchBlt(hDestDc, 0, 0, SmallIconWidth, SmallIconHeight,
|
|
hSourceDc, 0, 0, StdBitmapInfo.bmWidth,
|
|
StdBitmapInfo.bmHeight, SRCCOPY))
|
|
{
|
|
ERR("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)
|
|
{
|
|
ERR("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);
|
|
}
|
|
|
|
return SmallIcon;
|
|
}
|
|
|
|
|
|
ATOM WINAPI
|
|
RegisterClassExWOWW(WNDCLASSEXW *lpwcx,
|
|
LPDWORD pdwWowData,
|
|
WORD fnID,
|
|
DWORD dwFlags,
|
|
BOOL ChkRegCls)
|
|
{
|
|
ATOM Atom;
|
|
WNDCLASSEXW WndClass;
|
|
UNICODE_STRING ClassName;
|
|
UNICODE_STRING MenuName = {0};
|
|
CLSMENUNAME clsMenuName;
|
|
ANSI_STRING AnsiMenuName;
|
|
|
|
if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) ||
|
|
lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 ||
|
|
lpwcx->lpszClassName == NULL)
|
|
{
|
|
TRACE("RegisterClassExWOWW Invalid Parameter Error!\n");
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return 0;
|
|
}
|
|
|
|
if (ChkRegCls)
|
|
{
|
|
if (!RegisterDefaultClasses) RegisterSystemControls();
|
|
}
|
|
/*
|
|
* 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
|
|
|
|
GetWin32ClientInfo()->dwExpWinVer & (WINVER == 0x400)
|
|
*/
|
|
if (lpwcx->hInstance == User32Instance)
|
|
{
|
|
TRACE("RegisterClassExWOWW User32Instance!\n");
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return 0;
|
|
}
|
|
/* Yes, this is correct. We should modify the passed structure. */
|
|
if (lpwcx->hInstance == NULL)
|
|
((WNDCLASSEXW*)lpwcx)->hInstance = GetModuleHandleW(NULL);
|
|
|
|
RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXW));
|
|
|
|
if (NULL == WndClass.hIconSm)
|
|
{
|
|
WndClass.hIconSm = CreateSmallIcon(WndClass.hIcon);
|
|
}
|
|
|
|
if (WndClass.lpszMenuName != NULL)
|
|
{
|
|
if (!IS_INTRESOURCE(WndClass.lpszMenuName))
|
|
{
|
|
if (WndClass.lpszMenuName[0])
|
|
{
|
|
RtlInitUnicodeString(&MenuName, WndClass.lpszMenuName);
|
|
RtlUnicodeStringToAnsiString( &AnsiMenuName, &MenuName, TRUE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MenuName.Buffer = (LPWSTR)WndClass.lpszMenuName;
|
|
AnsiMenuName.Buffer = (PCHAR)WndClass.lpszMenuName;
|
|
}
|
|
}
|
|
|
|
if (IS_ATOM(WndClass.lpszClassName))
|
|
{
|
|
ClassName.Length =
|
|
ClassName.MaximumLength = 0;
|
|
ClassName.Buffer = (LPWSTR)WndClass.lpszClassName;
|
|
}
|
|
else
|
|
{
|
|
RtlInitUnicodeString(&ClassName, WndClass.lpszClassName);
|
|
}
|
|
|
|
clsMenuName.pszClientAnsiMenuName = AnsiMenuName.Buffer;
|
|
clsMenuName.pwszClientUnicodeMenuName = MenuName.Buffer;
|
|
clsMenuName.pusMenuName = &MenuName;
|
|
|
|
Atom = NtUserRegisterClassExWOW( &WndClass,
|
|
&ClassName,
|
|
NULL, //PUNICODE_STRING ClsNVersion,
|
|
&clsMenuName,
|
|
fnID,
|
|
dwFlags,
|
|
pdwWowData);
|
|
|
|
TRACE("atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
|
|
Atom, lpwcx->lpfnWndProc, lpwcx->hInstance, lpwcx->hbrBackground,
|
|
lpwcx->style, lpwcx->cbClsExtra, lpwcx->cbWndExtra, WndClass);
|
|
|
|
return Atom;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
ATOM WINAPI
|
|
RegisterClassExA(CONST WNDCLASSEXA *lpwcx)
|
|
{
|
|
RTL_ATOM Atom;
|
|
WNDCLASSEXW WndClass;
|
|
WCHAR mname[MAX_BUFFER_LEN];
|
|
WCHAR cname[MAX_BUFFER_LEN];
|
|
|
|
RtlCopyMemory(&WndClass, lpwcx, sizeof(WNDCLASSEXA));
|
|
|
|
if (WndClass.lpszMenuName != NULL)
|
|
{
|
|
if (!IS_INTRESOURCE(WndClass.lpszMenuName))
|
|
{
|
|
if (WndClass.lpszMenuName[0])
|
|
{
|
|
if (!MultiByteToWideChar( CP_ACP, 0, lpwcx->lpszMenuName, -1, mname, MAX_ATOM_LEN + 1 )) return 0;
|
|
|
|
WndClass.lpszMenuName = mname;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!IS_ATOM(WndClass.lpszClassName))
|
|
{
|
|
if (!MultiByteToWideChar( CP_ACP, 0, lpwcx->lpszClassName, -1, cname, MAX_ATOM_LEN + 1 )) return 0;
|
|
|
|
WndClass.lpszClassName = cname;
|
|
}
|
|
|
|
Atom = RegisterClassExWOWW( &WndClass,
|
|
0,
|
|
0,
|
|
CSF_ANSIPROC,
|
|
TRUE);
|
|
|
|
TRACE("A atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
|
|
Atom, lpwcx->lpfnWndProc, lpwcx->hInstance, lpwcx->hbrBackground,
|
|
lpwcx->style, lpwcx->cbClsExtra, lpwcx->cbWndExtra, WndClass);
|
|
|
|
return (ATOM)Atom;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
ATOM WINAPI
|
|
RegisterClassExW(CONST WNDCLASSEXW *lpwcx)
|
|
{
|
|
ATOM Atom;
|
|
|
|
Atom = RegisterClassExWOWW( (WNDCLASSEXW *)lpwcx, 0, 0, 0, TRUE);
|
|
|
|
TRACE("W atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d\n",
|
|
Atom, lpwcx->lpfnWndProc, lpwcx->hInstance, lpwcx->hbrBackground,
|
|
lpwcx->style, lpwcx->cbClsExtra, lpwcx->cbWndExtra);
|
|
|
|
return Atom;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
ATOM WINAPI
|
|
RegisterClassA(CONST WNDCLASSA *lpWndClass)
|
|
{
|
|
WNDCLASSEXA Class;
|
|
|
|
if (lpWndClass == NULL)
|
|
return 0;
|
|
|
|
RtlCopyMemory(&Class.style, lpWndClass, sizeof(WNDCLASSA));
|
|
Class.cbSize = sizeof(WNDCLASSEXA);
|
|
Class.hIconSm = NULL;
|
|
|
|
return RegisterClassExA(&Class);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
ATOM WINAPI
|
|
RegisterClassW(CONST WNDCLASSW *lpWndClass)
|
|
{
|
|
WNDCLASSEXW Class;
|
|
|
|
if (lpWndClass == NULL)
|
|
return 0;
|
|
|
|
RtlCopyMemory(&Class.style, lpWndClass, sizeof(WNDCLASSW));
|
|
Class.cbSize = sizeof(WNDCLASSEXW);
|
|
Class.hIconSm = NULL;
|
|
|
|
return RegisterClassExW(&Class);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
DWORD
|
|
WINAPI
|
|
SetClassLongA (HWND hWnd,
|
|
int nIndex,
|
|
LONG dwNewLong)
|
|
{
|
|
PSTR lpStr = (PSTR)(ULONG_PTR)dwNewLong;
|
|
UNICODE_STRING Value = {0};
|
|
BOOL Allocated = FALSE;
|
|
DWORD Ret;
|
|
|
|
/* FIXME - portability!!!! */
|
|
|
|
if (nIndex == GCL_MENUNAME && lpStr != NULL)
|
|
{
|
|
if (!IS_INTRESOURCE(lpStr))
|
|
{
|
|
if (!RtlCreateUnicodeStringFromAsciiz(&Value,
|
|
lpStr))
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return 0;
|
|
}
|
|
|
|
Allocated = TRUE;
|
|
}
|
|
else
|
|
Value.Buffer = (PWSTR)lpStr;
|
|
|
|
dwNewLong = (LONG_PTR)&Value;
|
|
}
|
|
else if (nIndex == GCW_ATOM && lpStr != NULL)
|
|
{
|
|
if (!IS_ATOM(lpStr))
|
|
{
|
|
if (!RtlCreateUnicodeStringFromAsciiz(&Value,
|
|
lpStr))
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return 0;
|
|
}
|
|
|
|
Allocated = TRUE;
|
|
}
|
|
else
|
|
Value.Buffer = (PWSTR)lpStr;
|
|
|
|
dwNewLong = (LONG_PTR)&Value;
|
|
}
|
|
|
|
Ret = (DWORD)NtUserSetClassLong(hWnd,
|
|
nIndex,
|
|
dwNewLong,
|
|
TRUE);
|
|
|
|
if (Allocated)
|
|
{
|
|
RtlFreeUnicodeString(&Value);
|
|
}
|
|
|
|
return Ret;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
DWORD
|
|
WINAPI
|
|
SetClassLongW(HWND hWnd,
|
|
int nIndex,
|
|
LONG dwNewLong)
|
|
{
|
|
PWSTR lpStr = (PWSTR)(ULONG_PTR)dwNewLong;
|
|
UNICODE_STRING Value = {0};
|
|
|
|
TRACE("%p %d %lx\n", hWnd, nIndex, dwNewLong);
|
|
|
|
/* FIXME - portability!!!! */
|
|
|
|
if (nIndex == GCL_MENUNAME && lpStr != NULL)
|
|
{
|
|
if (!IS_INTRESOURCE(lpStr))
|
|
{
|
|
RtlInitUnicodeString(&Value,
|
|
lpStr);
|
|
}
|
|
else
|
|
Value.Buffer = lpStr;
|
|
|
|
dwNewLong = (LONG_PTR)&Value;
|
|
}
|
|
else if (nIndex == GCW_ATOM && lpStr != NULL)
|
|
{
|
|
if (!IS_ATOM(lpStr))
|
|
{
|
|
RtlInitUnicodeString(&Value,
|
|
lpStr);
|
|
}
|
|
else
|
|
Value.Buffer = lpStr;
|
|
|
|
dwNewLong = (LONG_PTR)&Value;
|
|
}
|
|
|
|
return (DWORD)NtUserSetClassLong(hWnd,
|
|
nIndex,
|
|
dwNewLong,
|
|
FALSE);
|
|
}
|
|
|
|
#ifdef _WIN64
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
ULONG_PTR
|
|
WINAPI
|
|
SetClassLongPtrA(HWND hWnd,
|
|
INT nIndex,
|
|
LONG_PTR dwNewLong)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* @unimplemented
|
|
*/
|
|
ULONG_PTR
|
|
WINAPI
|
|
SetClassLongPtrW(HWND hWnd,
|
|
INT nIndex,
|
|
LONG_PTR dwNewLong)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return 0;
|
|
}
|
|
#endif // _WIN64
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WORD
|
|
WINAPI
|
|
SetClassWord(
|
|
HWND hWnd,
|
|
int nIndex,
|
|
WORD wNewWord)
|
|
/*
|
|
* NOTE: Obsoleted in 32-bit windows
|
|
*/
|
|
{
|
|
if ((nIndex < 0) && (nIndex != GCW_ATOM))
|
|
return 0;
|
|
|
|
return (WORD) SetClassLongW ( hWnd, nIndex, wNewWord );
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
WORD
|
|
WINAPI
|
|
SetWindowWord ( HWND hWnd,int nIndex,WORD wNewWord )
|
|
{
|
|
switch(nIndex)
|
|
{
|
|
case GWLP_ID:
|
|
case GWLP_HINSTANCE:
|
|
case GWLP_HWNDPARENT:
|
|
break;
|
|
default:
|
|
if (nIndex < 0)
|
|
{
|
|
WARN("Invalid offset %d\n", nIndex );
|
|
SetLastError( ERROR_INVALID_INDEX );
|
|
return 0;
|
|
}
|
|
break;
|
|
}
|
|
return NtUserSetWindowLong( hWnd, nIndex, wNewWord, FALSE );
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
LONG
|
|
WINAPI
|
|
SetWindowLongA(
|
|
HWND hWnd,
|
|
int nIndex,
|
|
LONG dwNewLong)
|
|
{
|
|
return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, TRUE);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
LONG
|
|
WINAPI
|
|
SetWindowLongW(
|
|
HWND hWnd,
|
|
int nIndex,
|
|
LONG dwNewLong)
|
|
{
|
|
return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, FALSE);
|
|
}
|
|
|
|
#ifdef _WIN64
|
|
/*
|
|
* @implemented
|
|
*/
|
|
LONG_PTR
|
|
WINAPI
|
|
SetWindowLongPtrA(HWND hWnd,
|
|
INT nIndex,
|
|
LONG_PTR dwNewLong)
|
|
{
|
|
return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, FALSE);
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
LONG_PTR
|
|
WINAPI
|
|
SetWindowLongPtrW(HWND hWnd,
|
|
INT nIndex,
|
|
LONG_PTR dwNewLong)
|
|
{
|
|
return NtUserSetWindowLong(hWnd, nIndex, dwNewLong, FALSE);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
UnregisterClassA(
|
|
LPCSTR lpClassName,
|
|
HINSTANCE hInstance)
|
|
{
|
|
UNICODE_STRING ClassName = {0};
|
|
BOOL Ret;
|
|
|
|
TRACE("class/atom: %s/%04x %p\n",
|
|
IS_ATOM(lpClassName) ? NULL : lpClassName,
|
|
IS_ATOM(lpClassName) ? lpClassName : 0,
|
|
hInstance);
|
|
|
|
if (!IS_ATOM(lpClassName))
|
|
{
|
|
if (!RtlCreateUnicodeStringFromAsciiz(&ClassName,
|
|
lpClassName))
|
|
{
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName);
|
|
|
|
Ret = NtUserUnregisterClass(&ClassName,
|
|
hInstance,
|
|
0);
|
|
|
|
if (!IS_ATOM(lpClassName))
|
|
RtlFreeUnicodeString(&ClassName);
|
|
|
|
return Ret;
|
|
}
|
|
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
WINAPI
|
|
UnregisterClassW(
|
|
LPCWSTR lpClassName,
|
|
HINSTANCE hInstance)
|
|
{
|
|
UNICODE_STRING ClassName = {0};
|
|
|
|
TRACE("class/atom: %S/%04x %p\n",
|
|
IS_ATOM(lpClassName) ? NULL : lpClassName,
|
|
IS_ATOM(lpClassName) ? lpClassName : 0,
|
|
hInstance);
|
|
|
|
if (!IS_ATOM(lpClassName))
|
|
{
|
|
RtlInitUnicodeString(&ClassName,
|
|
lpClassName);
|
|
}
|
|
else
|
|
ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName);
|
|
|
|
return NtUserUnregisterClass(&ClassName,
|
|
hInstance,
|
|
0);
|
|
}
|
|
|
|
/* EOF */
|