ReactOS  0.4.15-dev-1150-g593bcce
class.c File Reference
#include <win32k.h>
Include dependency graph for class.c:

Go to the source code of this file.

Functions

 DBG_DEFAULT_CHANNEL (UserClass)
 
static NTSTATUS IntDeregisterClassAtom (IN RTL_ATOM Atom)
 
BOOL FASTCALL LookupFnIdToiCls (int FnId, int *iCls)
 
_Must_inspect_result_ NTSTATUS NTAPI ProbeAndCaptureUnicodeStringOrAtom (_Out_ _When_(return >=0, _At_(pustrOut->Buffer, _Post_ _Notnull_)) PUNICODE_STRING pustrOut, __in_data_source(USER_MODE) _In_ PUNICODE_STRING pustrUnsafe)
 
static VOID IntFreeClassMenuName (IN OUT PCLS Class)
 
static VOID IntDestroyClass (IN OUT PCLS Class)
 
void FASTCALL DestroyProcessClasses (PPROCESSINFO Process)
 
static BOOL IntRegisterClassAtom (IN PUNICODE_STRING ClassName, OUT RTL_ATOM *pAtom)
 
BOOL FASTCALL RegisterControlAtoms (VOID)
 
VOID UserAddCallProcToClass (IN OUT PCLS Class, IN PCALLPROCDATA CallProc)
 
static BOOL IntSetClassAtom (IN OUT PCLS Class, IN PUNICODE_STRING ClassName)
 
WNDPROC FASTCALL IntGetClassWndProc (PCLS Class, BOOL Ansi)
 
static WNDPROC FASTCALL IntSetClassWndProc (IN OUT PCLS Class, IN WNDPROC WndProc, IN BOOL Ansi)
 
static PCLS IntGetClassForDesktop (IN OUT PCLS BaseClass, IN OUT PCLS *ClassLink, IN PDESKTOP Desktop)
 
PCLS IntReferenceClass (IN OUT PCLS BaseClass, IN OUT PCLS *ClassLink, IN PDESKTOP Desktop)
 
static VOID IntMakeCloneBaseClass (IN OUT PCLS Class, IN OUT PCLS *BaseClassLink, IN OUT PCLS *CloneLink)
 
VOID IntDereferenceClass (IN OUT PCLS Class, IN PDESKTOPINFO Desktop, IN PPROCESSINFO pi)
 
static BOOL IntMoveClassToSharedHeap (IN OUT PCLS Class, IN OUT PCLS **ClassLinkPtr)
 
static VOID IntCheckDesktopClasses (IN PDESKTOP Desktop, IN OUT PCLS *ClassList, IN BOOL FreeOnFailure, OUT BOOL *Ret)
 
BOOL IntCheckProcessDesktopClasses (IN PDESKTOP Desktop, IN BOOL FreeOnFailure)
 
PCLS FASTCALL IntCreateClass (IN CONST WNDCLASSEXW *lpwcx, IN PUNICODE_STRING ClassName, IN PUNICODE_STRING ClassVersion, IN PUNICODE_STRING MenuName, IN DWORD fnID, IN DWORD dwFlags, IN PDESKTOP Desktop, IN PPROCESSINFO pi)
 
static PCLS IntFindClass (IN RTL_ATOM Atom, IN HINSTANCE hInstance, IN PCLS *ClassList, OUT PCLS **Link OPTIONAL)
 
 _Success_ (return)
 
RTL_ATOM IntGetClassAtom (_In_ PUNICODE_STRING ClassName, IN HINSTANCE hInstance OPTIONAL, IN PPROCESSINFO pi OPTIONAL, OUT PCLS *BaseClass OPTIONAL, OUT PCLS **Link OPTIONAL)
 
PCLS IntGetAndReferenceClass (PUNICODE_STRING ClassName, HINSTANCE hInstance, BOOL bDesktopThread)
 
RTL_ATOM UserRegisterClass (IN CONST WNDCLASSEXW *lpwcx, IN PUNICODE_STRING ClassName, IN PUNICODE_STRING ClassVersion, IN PUNICODE_STRING MenuName, IN DWORD fnID, IN DWORD dwFlags)
 
BOOL UserUnregisterClass (IN PUNICODE_STRING ClassName, IN HINSTANCE hInstance, OUT PCLSMENUNAME pClassMenuName)
 
INT UserGetClassName (IN PCLS Class, IN OUT PUNICODE_STRING ClassName, IN RTL_ATOM Atom, IN BOOL Ansi)
 
static BOOL IntSetClassMenuName (IN PCLS Class, IN PUNICODE_STRING MenuName)
 
ULONG_PTR UserSetClassLongPtr (IN PCLS Class, IN INT Index, IN ULONG_PTR NewLong, IN BOOL Ansi)
 
static BOOL UserGetClassInfo (IN PCLS Class, OUT PWNDCLASSEXW lpwcx, IN BOOL Ansi, HINSTANCE hInstance)
 
BOOL FASTCALL UserRegisterSystemClasses (VOID)
 
RTL_ATOM APIENTRY NtUserRegisterClassExWOW (WNDCLASSEXW *lpwcx, PUNICODE_STRING ClassName, PUNICODE_STRING ClsVersion, PCLSMENUNAME pClassMenuName, DWORD fnID, DWORD Flags, LPDWORD pWow)
 
ULONG_PTR APIENTRY NtUserSetClassLong (HWND hWnd, INT Offset, ULONG_PTR dwNewLong, BOOL Ansi)
 
WORD APIENTRY NtUserSetClassWord (HWND hWnd, INT nIndex, WORD wNewWord)
 
BOOL APIENTRY NtUserUnregisterClass (IN PUNICODE_STRING ClassNameOrAtom, IN HINSTANCE hInstance, OUT PCLSMENUNAME pClassMenuName)
 
BOOL APIENTRY NtUserGetClassInfo (HINSTANCE hInstance, PUNICODE_STRING ClassName, LPWNDCLASSEXW lpWndClassEx, LPWSTR *ppszMenuName, BOOL bAnsi)
 
INT APIENTRY NtUserGetClassName (IN HWND hWnd, IN BOOL Real, OUT PUNICODE_STRING ClassName)
 
PCLS APIENTRY NtUserGetWOWClass (HINSTANCE hInstance, PUNICODE_STRING ClassName)
 

Variables

static PWSTR ControlsList []
 
REGISTER_SYSCLASS DefaultServerClasses []
 
struct {
   int   FnId
 
   int   ClsId
 
FnidToiCls []
 

Function Documentation

◆ _Success_()

_Success_ ( return  )

Definition at line 1289 of file class.c.

1295 {
1296  BOOL Ret = FALSE;
1297 
1298  if (ClassName->Length != 0)
1299  {
1300  WCHAR szBuf[65];
1301  PWSTR AtomName = szBuf;
1303 
1304  *Atom = 0;
1305 
1306  /* NOTE: Caller has to protect the call with SEH! */
1307  if (ClassName->Length + sizeof(UNICODE_NULL) > sizeof(szBuf))
1308  {
1309  AtomName = ExAllocatePoolWithTag(PagedPool,
1310  ClassName->Length + sizeof(UNICODE_NULL),
1311  TAG_USTR);
1312  if (AtomName == NULL)
1313  {
1315  return FALSE;
1316  }
1317  }
1318 
1319  _SEH2_TRY
1320  {
1321  RtlCopyMemory(AtomName,
1322  ClassName->Buffer,
1323  ClassName->Length);
1324  }
1326  {
1327  if (AtomName != szBuf)
1328  ExFreePoolWithTag(AtomName, TAG_USTR);
1330  _SEH2_YIELD(return FALSE);
1331  }
1332  _SEH2_END;
1333  AtomName[ClassName->Length / sizeof(WCHAR)] = UNICODE_NULL;
1334 
1335  /* Lookup the atom */
1337 
1338  if (AtomName != szBuf)
1339  ExFreePoolWithTag(AtomName, TAG_USTR);
1340 
1341  if (NT_SUCCESS(Status))
1342  {
1343  Ret = TRUE;
1344  }
1345  else
1346  {
1348  {
1350  }
1351  }
1352  }
1353  else
1354  {
1355  ASSERT(IS_ATOM(ClassName->Buffer));
1356  *Atom = (RTL_ATOM)((ULONG_PTR)ClassName->Buffer);
1357  Ret = TRUE;
1358  }
1359 
1360  return Ret;
1361 }
NTSYSAPI NTSTATUS NTAPI RtlLookupAtomInAtomTable(_In_ PRTL_ATOM_TABLE AtomTable, _In_ PWSTR AtomName, _Out_ PRTL_ATOM Atom)
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
unsigned short RTL_ATOM
Definition: atom.c:42
#define TRUE
Definition: types.h:120
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
uint16_t * PWSTR
Definition: typedefs.h:56
LONG NTSTATUS
Definition: precomp.h:26
PRTL_ATOM_TABLE gAtomTable
Definition: session.c:13
_Out_ RTL_ATOM * Atom
Definition: class.h:54
_SEH2_TRY
Definition: create.c:4226
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
unsigned int BOOL
Definition: ntddk_ex.h:94
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Status
Definition: gdiplustypes.h:24
VOID FASTCALL SetLastNtError(NTSTATUS Status)
Definition: error.c:36
#define TAG_USTR
Definition: libsupp.c:111
_SEH2_END
Definition: create.c:4400
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
#define IS_ATOM(x)
Definition: class.h:3
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13

◆ DBG_DEFAULT_CHANNEL()

DBG_DEFAULT_CHANNEL ( UserClass  )

◆ DestroyProcessClasses()

void FASTCALL DestroyProcessClasses ( PPROCESSINFO  Process)

Definition at line 300 of file class.c.

301 {
302  PCLS Class;
304 
305  if (pi != NULL)
306  {
307  /* Free all local classes */
308  Class = pi->pclsPrivateList;
309  while (Class != NULL)
310  {
311  pi->pclsPrivateList = Class->pclsNext;
312 
313  ASSERT(Class->pclsBase == Class);
315 
316  Class = pi->pclsPrivateList;
317  }
318 
319  /* Free all global classes */
320  Class = pi->pclsPublicList;
321  while (Class != NULL)
322  {
323  pi->pclsPublicList = Class->pclsNext;
324 
325  ASSERT(Class->pclsBase == Class);
327 
328  Class = pi->pclsPublicList;
329  }
330  }
331 }
static const WCHAR Class[]
Definition: cfgmgr.c:39
struct _PROCESSINFO * PPROCESSINFO
Definition: ntwin32.h:5
static VOID IntDestroyClass(IN OUT PCLS Class)
Definition: class.c:228
smooth NULL
Definition: ftsmooth.c:416
Definition: ntuser.h:533
static refpint_t pi[]
Definition: server.c:96
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219

Referenced by ExitThreadCallback().

◆ IntCheckDesktopClasses()

static VOID IntCheckDesktopClasses ( IN PDESKTOP  Desktop,
IN OUT PCLS ClassList,
IN BOOL  FreeOnFailure,
OUT BOOL Ret 
)
static

Definition at line 943 of file class.c.

947 {
948  PCLS Class, NextClass, *Link;
949 
950  /* NOTE: We only need to check base classes! When classes are no longer needed
951  on a desktop, the clones will be freed automatically as soon as possible.
952  However, we need to move base classes to the shared heap, as soon as
953  the last desktop heap where a class is allocated on is about to be destroyed.
954  If we didn't move the class to the shared heap, the class would become
955  inaccessible! */
956 
957  ASSERT(Desktop != NULL);
958 
959  Link = ClassList;
960  Class = *Link;
961  while (Class != NULL)
962  {
963  NextClass = Class->pclsNext;
964 
965  ASSERT(Class->pclsBase == Class);
966 
967  if (Class->rpdeskParent == Desktop &&
968  Class->cWndReferenceCount == 0)
969  {
970  /* There shouldn't be any clones around anymore! */
971  ASSERT(Class->pclsClone == NULL);
972 
973  /* FIXME: If process is terminating, don't move the class but rather destroy it! */
974  /* FIXME: We could move the class to another desktop heap if there's still desktops
975  mapped into the process... */
976 
977  /* Move the class to the shared heap */
979  &Link))
980  {
981  ASSERT(*Link == NextClass);
982  }
983  else
984  {
985  ASSERT(NextClass == Class->pclsNext);
986 
987  if (FreeOnFailure)
988  {
989  /* Unlink the base class */
991  Class->pclsNext);
992 
993  /* We can free the old base class now */
994  Class->pclsBase = NULL;
996  }
997  else
998  {
999  Link = &Class->pclsNext;
1000  *Ret = FALSE;
1001  }
1002  }
1003  }
1004  else
1005  Link = &Class->pclsNext;
1006 
1007  Class = NextClass;
1008  }
1009 }
static const WCHAR Class[]
Definition: cfgmgr.c:39
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
static VOID IntDestroyClass(IN OUT PCLS Class)
Definition: class.c:228
static int Link(const char **args)
Definition: vfdcmd.c:2414
#define FALSE
Definition: types.h:117
smooth NULL
Definition: ftsmooth.c:416
Definition: ntuser.h:533
static BOOL IntMoveClassToSharedHeap(IN OUT PCLS Class, IN OUT PCLS **ClassLinkPtr)
Definition: class.c:897
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)

Referenced by IntCheckProcessDesktopClasses().

◆ IntCheckProcessDesktopClasses()

BOOL IntCheckProcessDesktopClasses ( IN PDESKTOP  Desktop,
IN BOOL  FreeOnFailure 
)

Definition at line 1012 of file class.c.

1014 {
1015  PPROCESSINFO pi;
1016  BOOL Ret = TRUE;
1017 
1018  pi = GetW32ProcessInfo();
1019 
1020  /* Check all local classes */
1022  &pi->pclsPrivateList,
1023  FreeOnFailure,
1024  &Ret);
1025 
1026  /* Check all global classes */
1028  &pi->pclsPublicList,
1029  FreeOnFailure,
1030  &Ret);
1031  if (!Ret)
1032  {
1033  ERR("Failed to move process classes from desktop 0x%p to the shared heap!\n", Desktop);
1035  }
1036 
1037  return Ret;
1038 }
#define TRUE
Definition: types.h:120
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
unsigned int BOOL
Definition: ntddk_ex.h:94
struct _PROCESSINFO * GetW32ProcessInfo(VOID)
Definition: misc.c:773
static VOID IntCheckDesktopClasses(IN PDESKTOP Desktop, IN OUT PCLS *ClassList, IN BOOL FreeOnFailure, OUT BOOL *Ret)
Definition: class.c:943
static refpint_t pi[]
Definition: server.c:96
#define ERR(fmt,...)
Definition: debug.h:110
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27

Referenced by IntSetThreadDesktop().

◆ IntCreateClass()

PCLS FASTCALL IntCreateClass ( IN CONST WNDCLASSEXW lpwcx,
IN PUNICODE_STRING  ClassName,
IN PUNICODE_STRING  ClassVersion,
IN PUNICODE_STRING  MenuName,
IN DWORD  fnID,
IN DWORD  dwFlags,
IN PDESKTOP  Desktop,
IN PPROCESSINFO  pi 
)

Definition at line 1042 of file class.c.

1050 {
1051  SIZE_T ClassSize;
1052  PCLS Class = NULL;
1053  RTL_ATOM Atom, verAtom;
1054  WNDPROC WndProc;
1055  PWSTR pszMenuName = NULL;
1057 
1058  TRACE("lpwcx=%p ClassName=%wZ MenuName=%wZ dwFlags=%08x Desktop=%p pi=%p\n",
1059  lpwcx, ClassName, MenuName, dwFlags, Desktop, pi);
1060 
1061  if (!IntRegisterClassAtom(ClassName,
1062  &Atom))
1063  {
1064  ERR("Failed to register class atom!\n");
1065  return NULL;
1066  }
1067 
1068  if (!IntRegisterClassAtom(ClassVersion,
1069  &verAtom))
1070  {
1071  ERR("Failed to register version class atom!\n");
1073  return NULL;
1074  }
1075 
1076  ClassSize = sizeof(*Class) + lpwcx->cbClsExtra;
1077  if (MenuName->Length != 0)
1078  {
1079  pszMenuName = UserHeapAlloc(MenuName->Length + sizeof(UNICODE_NULL) +
1080  RtlUnicodeStringToAnsiSize(MenuName));
1081  if (pszMenuName == NULL)
1082  goto NoMem;
1083  }
1084 
1085  if (Desktop != NULL)
1086  {
1088  ClassSize);
1089  }
1090  else
1091  {
1092  /* FIXME: The class was created before being connected
1093  to a desktop. It is possible for the desktop window,
1094  but should it be allowed for any other case? */
1095  TRACE("This CLASS has no Desktop to heap from! Atom %u\n",Atom);
1096  Class = UserHeapAlloc(ClassSize);
1097  }
1098 
1099  if (Class != NULL)
1100  {
1101  int iCls = 0;
1102 
1103  RtlZeroMemory(Class, ClassSize);
1104 
1105  Class->rpdeskParent = Desktop;
1106  Class->pclsBase = Class;
1107  Class->atomClassName = verAtom;
1108  Class->atomNVClassName = Atom;
1109  Class->fnid = fnID;
1110  Class->CSF_flags = dwFlags;
1111 
1112  if (LookupFnIdToiCls(Class->fnid, &iCls) && gpsi->atomSysClass[iCls] == 0)
1113  {
1114  gpsi->atomSysClass[iCls] = Class->atomClassName;
1115  }
1116 
1117  _SEH2_TRY
1118  {
1119  PWSTR pszMenuNameBuffer = pszMenuName;
1120 
1121  /* Need to protect with SEH since accessing the WNDCLASSEX structure
1122  and string buffers might raise an exception! We don't want to
1123  leak memory... */
1124  // What?! If the user interface was written correctly this would not be an issue!
1125  Class->lpfnWndProc = lpwcx->lpfnWndProc;
1126  Class->style = lpwcx->style;
1127  Class->cbclsExtra = lpwcx->cbClsExtra;
1128  Class->cbwndExtra = lpwcx->cbWndExtra;
1129  Class->hModule = lpwcx->hInstance;
1130  Class->spicn = lpwcx->hIcon ? UserGetCurIconObject(lpwcx->hIcon) : NULL;
1131  Class->spcur = lpwcx->hCursor ? UserGetCurIconObject(lpwcx->hCursor) : NULL;
1132  Class->spicnSm = lpwcx->hIconSm ? UserGetCurIconObject(lpwcx->hIconSm) : NULL;
1134  Class->hbrBackground = lpwcx->hbrBackground;
1135 
1136  /* Make a copy of the string */
1137  if (pszMenuNameBuffer != NULL)
1138  {
1139  Class->MenuNameIsString = TRUE;
1140 
1141  Class->lpszClientUnicodeMenuName = pszMenuNameBuffer;
1142  RtlCopyMemory(Class->lpszClientUnicodeMenuName,
1143  MenuName->Buffer,
1144  MenuName->Length);
1145  Class->lpszClientUnicodeMenuName[MenuName->Length / sizeof(WCHAR)] = UNICODE_NULL;
1146 
1147  pszMenuNameBuffer += (MenuName->Length / sizeof(WCHAR)) + 1;
1148  }
1149  else
1150  Class->lpszClientUnicodeMenuName = MenuName->Buffer;
1151 
1152  /* Save an ANSI copy of the string */
1153  if (pszMenuNameBuffer != NULL)
1154  {
1156 
1157  Class->lpszClientAnsiMenuName = (PSTR)pszMenuNameBuffer;
1158  AnsiString.MaximumLength = (USHORT)RtlUnicodeStringToAnsiSize(MenuName);
1159  AnsiString.Buffer = Class->lpszClientAnsiMenuName;
1161  MenuName,
1162  FALSE);
1163  if (!NT_SUCCESS(Status))
1164  {
1165  ERR("Failed to convert unicode menu name to ansi!\n");
1166 
1167  /* Life would've been much prettier if ntoskrnl exported RtlRaiseStatus()... */
1168  _SEH2_LEAVE;
1169  }
1170  }
1171  else
1172  Class->lpszClientAnsiMenuName = (PSTR)MenuName->Buffer;
1173 
1174  /* Save kernel use menu name and ansi class name */
1175  Class->lpszMenuName = Class->lpszClientUnicodeMenuName; // FIXME!
1176  //Class->lpszAnsiClassName = FIXME
1177 
1178  /* Server Side overrides class calling type (A/W)!
1179  User32 whine test_builtinproc: "deftest"
1180  built-in winproc - window A/W type automatically detected */
1181  if (!(Class->CSF_flags & CSF_SERVERSIDEPROC))
1182  {
1183  int i;
1184  WndProc = NULL;
1185  /* Due to the wine class "deftest" and most likely no FNID to reference
1186  from, sort through the Server Side list and compare proc addresses
1187  for match. This method will be used in related code.
1188  */
1189  for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
1190  { // Open ANSI or Unicode, just match, set and break.
1191  if (GETPFNCLIENTW(i) == Class->lpfnWndProc)
1192  {
1193  WndProc = GETPFNSERVER(i);
1194  break;
1195  }
1196  if (GETPFNCLIENTA(i) == Class->lpfnWndProc)
1197  {
1198  WndProc = GETPFNSERVER(i);
1199  break;
1200  }
1201  }
1202  if (WndProc)
1203  { // If a hit, we are Server Side so set the right flags and proc.
1204  Class->CSF_flags |= CSF_SERVERSIDEPROC;
1205  Class->CSF_flags &= ~CSF_ANSIPROC;
1206  Class->lpfnWndProc = WndProc;
1207  }
1208  }
1209 
1210  if (!(Class->CSF_flags & CSF_ANSIPROC))
1211  Class->Unicode = TRUE;
1212 
1213  if (Class->style & CS_GLOBALCLASS)
1214  Class->Global = TRUE;
1215  }
1217  {
1219  }
1220  _SEH2_END;
1221 
1222  if (!NT_SUCCESS(Status))
1223  {
1224  ERR("Failed creating the class: 0x%x\n", Status);
1225 
1227 
1228  if (pszMenuName != NULL)
1229  UserHeapFree(pszMenuName);
1230 
1232  Class);
1233  Class = NULL;
1234 
1235  IntDeregisterClassAtom(verAtom);
1237  }
1238  }
1239  else
1240  {
1241 NoMem:
1242  ERR("Failed to allocate class on Desktop 0x%p\n", Desktop);
1243 
1244  if (pszMenuName != NULL)
1245  UserHeapFree(pszMenuName);
1246 
1248  IntDeregisterClassAtom(verAtom);
1249 
1251  }
1252 
1253  TRACE("Created class 0x%p with name %wZ and proc 0x%p for atom 0x%x and version atom 0x%x and hInstance 0x%p, global %u\n",
1254  Class, ClassName, Class ? Class->lpfnWndProc : NULL, Atom, verAtom,
1255  Class ? Class->hModule : NULL , Class ? Class->Global : 0);
1256 
1257  return Class;
1258 }
static const WCHAR Class[]
Definition: cfgmgr.c:39
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define GETPFNSERVER(fnid)
Definition: ntuser.h:870
unsigned short RTL_ATOM
Definition: atom.c:42
PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon)
Definition: cursoricon.c:200
#define GETPFNCLIENTW(fnid)
Definition: ntuser.h:867
#define TRUE
Definition: types.h:120
uint16_t * PWSTR
Definition: typedefs.h:56
LONG NTSTATUS
Definition: precomp.h:26
static __inline BOOL UserHeapFree(PVOID lpMem)
Definition: usrheap.h:42
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
static __inline PVOID UserHeapAlloc(SIZE_T Bytes)
Definition: usrheap.h:34
_Out_ RTL_ATOM * Atom
Definition: class.h:54
PSERVERINFO gpsi
Definition: main.c:27
_SEH2_TRY
Definition: create.c:4226
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static __inline PVOID DesktopHeapAlloc(IN PDESKTOP Desktop, IN SIZE_T Bytes)
Definition: desktop.h:230
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
Definition: ntuser.h:533
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
static CHAR Desktop[MAX_PATH]
Definition: dem.c:256
static NTSTATUS IntDeregisterClassAtom(IN RTL_ATOM Atom)
Definition: class.c:416
#define TRACE(s)
Definition: solgame.cpp:4
#define FNID_SWITCH
Definition: ntuser.h:827
if(!(yy_init))
Definition: macro.lex.yy.c:714
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static refpint_t pi[]
Definition: server.c:96
#define CS_GLOBALCLASS
Definition: winuser.h:647
Status
Definition: gdiplustypes.h:24
#define CSF_SERVERSIDEPROC
Definition: ntuser.h:524
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
#define GETPFNCLIENTA(fnid)
Definition: ntuser.h:865
#define CSF_ANSIPROC
Definition: ntuser.h:525
VOID FASTCALL SetLastNtError(NTSTATUS Status)
Definition: error.c:36
NTSYSAPI DWORD WINAPI RtlUnicodeStringToAnsiSize(const UNICODE_STRING *)
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
Definition: solitaire.cpp:598
LRESULT(CALLBACK * WNDPROC)(HWND, UINT, WPARAM, LPARAM)
Definition: winuser.h:2881
#define ERR(fmt,...)
Definition: debug.h:110
ULONG_PTR SIZE_T
Definition: typedefs.h:80
_SEH2_END
Definition: create.c:4400
unsigned short USHORT
Definition: pedump.c:61
signed char * PSTR
Definition: retypes.h:7
BOOL FASTCALL LookupFnIdToiCls(int FnId, int *iCls)
Definition: class.c:131
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
static __inline BOOL DesktopHeapFree(IN PDESKTOP Desktop, IN PVOID lpMem)
Definition: desktop.h:239
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
#define _SEH2_LEAVE
Definition: filesup.c:20
static BOOL IntRegisterClassAtom(IN PUNICODE_STRING ClassName, OUT RTL_ATOM *pAtom)
Definition: class.c:334
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define FNID_FIRST
Definition: ntuser.h:820
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27
ATOM atomSysClass[ICLS_NOTUSED+1]
Definition: ntuser.h:1013

Referenced by UserRegisterClass(), and UserRegisterSystemClasses().

◆ IntDereferenceClass()

VOID IntDereferenceClass ( IN OUT PCLS  Class,
IN PDESKTOPINFO  Desktop,
IN PPROCESSINFO  pi 
)

Definition at line 815 of file class.c.

818 {
819  PCLS *PrevLink, BaseClass, CurrentClass;
820 
821  ASSERT(Class->cWndReferenceCount >= 1);
822 
823  BaseClass = Class->pclsBase;
824 
825  if (--Class->cWndReferenceCount == 0)
826  {
827  if (BaseClass == Class)
828  {
829  ASSERT(Class->pclsBase == Class);
830 
831  TRACE("IntDereferenceClass 0x%p\n", Class);
832  /* Check if there are clones of the class on other desktops,
833  link the first clone in if possible. If there are no clones
834  then leave the class on the desktop heap. It will get moved
835  to the shared heap when the thread detaches. */
836  if (BaseClass->pclsClone != NULL)
837  {
838  if (BaseClass->Global)
839  PrevLink = &pi->pclsPublicList;
840  else
841  PrevLink = &pi->pclsPrivateList;
842 
843  CurrentClass = *PrevLink;
844  while (CurrentClass != BaseClass)
845  {
846  ASSERT(CurrentClass != NULL);
847 
848  PrevLink = &CurrentClass->pclsNext;
849  CurrentClass = CurrentClass->pclsNext;
850  }
851 
852  ASSERT(*PrevLink == BaseClass);
853 
854  /* Make the first clone become the new base class */
855  IntMakeCloneBaseClass(BaseClass->pclsClone,
856  PrevLink,
857  &BaseClass->pclsClone);
858 
859  /* Destroy the class, there's still another clone of the class
860  that now serves as a base class. Make sure we don't destruct
861  resources shared by all classes (Base = NULL)! */
862  BaseClass->pclsBase = NULL;
863  BaseClass->pclsClone = NULL;
864  IntDestroyClass(BaseClass);
865  }
866  }
867  else
868  {
869  TRACE("IntDereferenceClass1 0x%p\n", Class);
870 
871  /* Locate the cloned class and unlink it */
872  PrevLink = &BaseClass->pclsClone;
873  CurrentClass = BaseClass->pclsClone;
874  while (CurrentClass != Class)
875  {
876  ASSERT(CurrentClass != NULL);
877 
878  PrevLink = &CurrentClass->pclsNext;
879  CurrentClass = CurrentClass->pclsNext;
880  }
881 
882  ASSERT(CurrentClass == Class);
883 
885  Class->pclsNext);
886 
887  ASSERT(Class->pclsBase == BaseClass);
888  ASSERT(Class->pclsClone == NULL);
889 
890  /* The class was just a clone, we don't need it anymore */
892  }
893  }
894 }
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
UINT Global
Definition: ntuser.h:561
static VOID IntDestroyClass(IN OUT PCLS Class)
Definition: class.c:228
struct _CLS * pclsClone
Definition: ntuser.h:546
static VOID IntMakeCloneBaseClass(IN OUT PCLS Class, IN OUT PCLS *BaseClassLink, IN OUT PCLS *CloneLink)
Definition: class.c:777
smooth NULL
Definition: ftsmooth.c:416
Definition: ntuser.h:533
#define TRACE(s)
Definition: solgame.cpp:4
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
static refpint_t pi[]
Definition: server.c:96
struct _CLS * pclsBase
Definition: ntuser.h:545
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
struct _CLS * pclsNext
Definition: ntuser.h:535

Referenced by co_UserCreateWindowEx(), and co_UserFreeWindow().

◆ IntDeregisterClassAtom()

static NTSTATUS IntDeregisterClassAtom ( IN RTL_ATOM  Atom)
static

Definition at line 416 of file class.c.

417 {
419  Atom);
420 }
PRTL_ATOM_TABLE gAtomTable
Definition: session.c:13
_Out_ RTL_ATOM * Atom
Definition: class.h:54
NTSYSAPI NTSTATUS NTAPI RtlDeleteAtomFromAtomTable(_In_ PRTL_ATOM_TABLE AtomTable, _In_ RTL_ATOM Atom)

Referenced by IntCreateClass(), IntDestroyClass(), IntSetClassAtom(), and UserUnregisterClass().

◆ IntDestroyClass()

static VOID IntDestroyClass ( IN OUT PCLS  Class)
static

Definition at line 228 of file class.c.

229 {
230  PDESKTOP pDesk;
231 
232  /* There shouldn't be any clones anymore */
233  ASSERT(Class->cWndReferenceCount == 0);
234  ASSERT(Class->pclsClone == NULL);
235 
236  if (Class->pclsBase == Class)
237  {
238  PCALLPROCDATA CallProc, NextCallProc;
239 
240  /* Destroy allocated callproc handles */
241  CallProc = Class->spcpdFirst;
242  while (CallProc != NULL)
243  {
244  NextCallProc = CallProc->spcpdNext;
245 
246  CallProc->spcpdNext = NULL;
247  DestroyCallProc(CallProc);
248 
249  CallProc = NextCallProc;
250  }
251 
252  // Fixes running the static test then run class test issue.
253  // Some applications do not use UnregisterClass before exiting.
254  // Keep from reusing the same atom with case insensitive
255  // comparisons, remove registration of the atom if not zeroed.
256  if (Class->atomClassName)
257  IntDeregisterClassAtom(Class->atomClassName);
258  // Dereference non-versioned class name
259  if (Class->atomNVClassName)
260  IntDeregisterClassAtom(Class->atomNVClassName);
261 
262  if (Class->pdce)
263  {
264  DceFreeClassDCE(Class->pdce);
265  Class->pdce = NULL;
266  }
267 
269  }
270 
271  if (Class->spicn)
273  if (Class->spcur)
275  if (Class->spicnSm)
276  {
277  UserDereferenceObject(Class->spicnSm);
278  /* Destroy the icon if we own it */
279  if ((Class->CSF_flags & CSF_CACHEDSMICON)
280  && !(UserObjectInDestroy(UserHMGetHandle(Class->spicnSm))))
281  IntDestroyCurIconObject(Class->spicnSm);
282  }
283 
284  pDesk = Class->rpdeskParent;
285  Class->rpdeskParent = NULL;
286 
287  /* Free the structure */
288  if (pDesk != NULL)
289  {
290  DesktopHeapFree(pDesk, Class);
291  }
292  else
293  {
295  }
296 }
static VOID IntFreeClassMenuName(IN OUT PCLS Class)
Definition: class.c:216
static __inline BOOL UserHeapFree(PVOID lpMem)
Definition: usrheap.h:42
BOOL FASTCALL UserDereferenceObject(PVOID Object)
Definition: object.c:610
struct _CALLPROCDATA * spcpdNext
Definition: ntuser.h:519
#define CSF_CACHEDSMICON
Definition: ntuser.h:530
BOOLEAN DestroyCallProc(_Inout_ PVOID Object)
Definition: callproc.c:22
smooth NULL
Definition: ftsmooth.c:416
BOOL FASTCALL UserObjectInDestroy(HANDLE h)
Definition: object.c:669
#define UserHMGetHandle(obj)
Definition: ntuser.h:208
static NTSTATUS IntDeregisterClassAtom(IN RTL_ATOM Atom)
Definition: class.c:416
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
BOOLEAN IntDestroyCurIconObject(_In_ PVOID Object)
Definition: cursoricon.c:313
static __inline BOOL DesktopHeapFree(IN PDESKTOP Desktop, IN PVOID lpMem)
Definition: desktop.h:239
void FASTCALL DceFreeClassDCE(PDCE)
Definition: windc.c:761

Referenced by DestroyProcessClasses(), IntCheckDesktopClasses(), IntDereferenceClass(), IntGetClassForDesktop(), IntMoveClassToSharedHeap(), and UserUnregisterClass().

◆ IntFindClass()

static PCLS IntFindClass ( IN RTL_ATOM  Atom,
IN HINSTANCE  hInstance,
IN PCLS ClassList,
OUT PCLS **Link  OPTIONAL 
)
static

Definition at line 1261 of file class.c.

1265 {
1266  PCLS Class, *PrevLink = ClassList;
1267 
1268  Class = *PrevLink;
1269  while (Class != NULL)
1270  {
1271  if (Class->atomClassName == Atom &&
1272  (hInstance == NULL || Class->hModule == hInstance) &&
1273  !(Class->CSF_flags & CSF_WOWDEFERDESTROY))
1274  {
1275  ASSERT(Class->pclsBase == Class);
1276 
1277  if (Link != NULL)
1278  *Link = PrevLink;
1279  break;
1280  }
1281 
1282  PrevLink = &Class->pclsNext;
1283  Class = Class->pclsNext;
1284  }
1285 
1286  return Class;
1287 }
static const WCHAR Class[]
Definition: cfgmgr.c:39
_Out_ RTL_ATOM * Atom
Definition: class.h:54
static int Link(const char **args)
Definition: vfdcmd.c:2414
HINSTANCE hInstance
Definition: charmap.c:20
smooth NULL
Definition: ftsmooth.c:416
Definition: ntuser.h:533
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define CSF_WOWDEFERDESTROY
Definition: ntuser.h:526

Referenced by IntGetClassAtom(), and UserRegisterClass().

◆ IntFreeClassMenuName()

static VOID IntFreeClassMenuName ( IN OUT PCLS  Class)
static

Definition at line 216 of file class.c.

217 {
218  /* Free the menu name, if it was changed and allocated */
219  if (Class->lpszClientUnicodeMenuName != NULL && Class->MenuNameIsString)
220  {
221  UserHeapFree(Class->lpszClientUnicodeMenuName);
222  Class->lpszClientUnicodeMenuName = NULL;
223  Class->lpszClientAnsiMenuName = NULL;
224  }
225 }
static __inline BOOL UserHeapFree(PVOID lpMem)
Definition: usrheap.h:42
smooth NULL
Definition: ftsmooth.c:416

Referenced by IntDestroyClass(), and IntSetClassMenuName().

◆ IntGetAndReferenceClass()

PCLS IntGetAndReferenceClass ( PUNICODE_STRING  ClassName,
HINSTANCE  hInstance,
BOOL  bDesktopThread 
)

Definition at line 1437 of file class.c.

1438 {
1439  PCLS *ClassLink, Class = NULL;
1440  RTL_ATOM ClassAtom;
1441  PTHREADINFO pti;
1442 
1443  if (bDesktopThread)
1444  pti = gptiDesktopThread;
1445  else
1447 
1448  if ( !(pti->ppi->W32PF_flags & W32PF_CLASSESREGISTERED ))
1449  {
1451  }
1452 
1453  /* Check the class. */
1454 
1455  TRACE("Finding Class %wZ for hInstance 0x%p\n", ClassName, hInstance);
1456 
1457  ClassAtom = IntGetClassAtom(ClassName,
1458  hInstance,
1459  pti->ppi,
1460  &Class,
1461  &ClassLink);
1462 
1463  if (ClassAtom == (RTL_ATOM)0)
1464  {
1465  if (IS_ATOM(ClassName->Buffer))
1466  {
1467  ERR("Class 0x%p not found\n", ClassName->Buffer);
1468  }
1469  else
1470  {
1471  ERR("Class \"%wZ\" not found\n", ClassName);
1472  }
1473 
1474  return NULL;
1475  }
1476 
1477  TRACE("Referencing Class 0x%p with atom 0x%x\n", Class, ClassAtom);
1479  ClassLink,
1480  pti->rpdesk);
1481  if (Class == NULL)
1482  {
1483  ERR("Failed to reference window class!\n");
1484  return NULL;
1485  }
1486 
1487  return Class;
1488 }
static const WCHAR Class[]
Definition: cfgmgr.c:39
unsigned short RTL_ATOM
Definition: atom.c:42
BOOL FASTCALL UserRegisterSystemClasses(VOID)
Definition: class.c:2306
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
struct _DESKTOP * rpdesk
Definition: win32.h:91
PPROCESSINFO ppi
Definition: win32.h:87
PTHREADINFO gptiDesktopThread
Definition: desktop.c:37
HINSTANCE hInstance
Definition: charmap.c:20
smooth NULL
Definition: ftsmooth.c:416
Definition: ntuser.h:533
#define TRACE(s)
Definition: solgame.cpp:4
#define ERR(fmt,...)
Definition: debug.h:110
#define W32PF_CLASSESREGISTERED
Definition: win32.h:17
PCLS IntReferenceClass(IN OUT PCLS BaseClass, IN OUT PCLS *ClassLink, IN PDESKTOP Desktop)
Definition: class.c:749
RTL_ATOM IntGetClassAtom(_In_ PUNICODE_STRING ClassName, IN HINSTANCE hInstance OPTIONAL, IN PPROCESSINFO pi OPTIONAL, OUT PCLS *BaseClass OPTIONAL, OUT PCLS **Link OPTIONAL)
Definition: class.c:1364
#define IS_ATOM(x)
Definition: class.h:3

Referenced by co_UserCreateWindowEx(), and IntCreateDesktop().

◆ IntGetClassAtom()

RTL_ATOM IntGetClassAtom ( _In_ PUNICODE_STRING  ClassName,
IN HINSTANCE hInstance  OPTIONAL,
IN PPROCESSINFO pi  OPTIONAL,
OUT PCLS *BaseClass  OPTIONAL,
OUT PCLS **Link  OPTIONAL 
)

Definition at line 1364 of file class.c.

1370 {
1371  RTL_ATOM Atom = (RTL_ATOM)0;
1372 
1373  ASSERT(BaseClass != NULL);
1374 
1375  if (IntGetAtomFromStringOrAtom(ClassName, &Atom) &&
1376  Atom != (RTL_ATOM)0)
1377  {
1378  PCLS Class;
1379 
1380  /* Attempt to locate the class object */
1381 
1382  ASSERT(pi != NULL);
1383 
1384  /* Step 1: Try to find an exact match of locally registered classes */
1386  hInstance,
1387  &pi->pclsPrivateList,
1388  Link);
1389  if (Class != NULL)
1390  { TRACE("Step 1: 0x%p\n",Class );
1391  goto FoundClass;
1392  }
1393 
1394  /* Step 2: Try to find any globally registered class. The hInstance
1395  is not relevant for global classes */
1397  NULL,
1398  &pi->pclsPublicList,
1399  Link);
1400  if (Class != NULL)
1401  { TRACE("Step 2: 0x%p 0x%p\n",Class, Class->hModule);
1402  goto FoundClass;
1403  }
1404 
1405  /* Step 3: Try to find any local class registered by user32 */
1407  hModClient,
1408  &pi->pclsPrivateList,
1409  Link);
1410  if (Class != NULL)
1411  { TRACE("Step 3: 0x%p\n",Class );
1412  goto FoundClass;
1413  }
1414 
1415  /* Step 4: Try to find any global class registered by user32 */
1417  hModClient,
1418  &pi->pclsPublicList,
1419  Link);
1420  if (Class == NULL)
1421  {
1422  return (RTL_ATOM)0;
1423  }else{TRACE("Step 4: 0x%p\n",Class );}
1424 
1425 FoundClass:
1426  *BaseClass = Class;
1427  }
1428  else
1429  {
1430  Atom = 0;
1431  }
1432 
1433  return Atom;
1434 }
static const WCHAR Class[]
Definition: cfgmgr.c:39
unsigned short RTL_ATOM
Definition: atom.c:42
_Out_ RTL_ATOM * Atom
Definition: class.h:54
static int Link(const char **args)
Definition: vfdcmd.c:2414
HINSTANCE hInstance
Definition: charmap.c:20
smooth NULL
Definition: ftsmooth.c:416
Definition: ntuser.h:533
#define TRACE(s)
Definition: solgame.cpp:4
static refpint_t pi[]
Definition: server.c:96
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
static PCLS IntFindClass(IN RTL_ATOM Atom, IN HINSTANCE hInstance, IN PCLS *ClassList, OUT PCLS **Link OPTIONAL)
Definition: class.c:1261
HINSTANCE hModClient
Definition: ntuser.c:25

Referenced by IntGetAndReferenceClass(), NtUserGetClassInfo(), NtUserGetWOWClass(), and UserUnregisterClass().

◆ IntGetClassForDesktop()

static PCLS IntGetClassForDesktop ( IN OUT PCLS  BaseClass,
IN OUT PCLS ClassLink,
IN PDESKTOP  Desktop 
)
static

Definition at line 625 of file class.c.

628 {
629  SIZE_T ClassSize;
630  PCLS Class;
631 
632  ASSERT(Desktop != NULL);
633  ASSERT(BaseClass->pclsBase == BaseClass);
634 
635  if (BaseClass->rpdeskParent == Desktop)
636  {
637  /* It is most likely that a window is created on the same
638  desktop as the window class. */
639 
640  return BaseClass;
641  }
642 
643  if (BaseClass->rpdeskParent == NULL)
644  {
645  ASSERT(BaseClass->cWndReferenceCount == 0);
646  ASSERT(BaseClass->pclsClone == NULL);
647 
648  /* Classes are also located in the shared heap when the class
649  was created before the thread attached to a desktop. As soon
650  as a window is created for such a class located on the shared
651  heap, the class is cloned into the desktop heap on which the
652  window is created. */
653  Class = NULL;
654  }
655  else
656  {
657  /* The user is asking for a class object on a different desktop,
658  try to find one! */
659  Class = BaseClass->pclsClone;
660  while (Class != NULL)
661  {
662  if (Class->rpdeskParent == Desktop)
663  {
664  ASSERT(Class->pclsBase == BaseClass);
665  ASSERT(Class->pclsClone == NULL);
666  break;
667  }
668 
669  Class = Class->pclsNext;
670  }
671  }
672 
673  if (Class == NULL)
674  {
675  /* The window is created on a different desktop, we need to
676  clone the class object to the desktop heap of the window! */
677  ClassSize = sizeof(*BaseClass) + (SIZE_T)BaseClass->cbclsExtra;
678 
680  ClassSize);
681 
682  if (Class != NULL)
683  {
684  /* Simply clone the class */
685  RtlCopyMemory( Class, BaseClass, ClassSize);
686 
687  /* Reference our objects */
688  if (Class->spcur)
689  UserReferenceObject(Class->spcur);
690  if (Class->spicn)
691  UserReferenceObject(Class->spicn);
692  if (Class->spicnSm)
693  UserReferenceObject(Class->spicnSm);
694 
695  TRACE("Clone Class 0x%p hM 0x%p\n %S\n",Class, Class->hModule, Class->lpszClientUnicodeMenuName);
696 
697  /* Restore module address if default user class Ref: Bug 4778 */
698  if ( Class->hModule != hModClient &&
699  Class->fnid <= FNID_GHOST &&
700  Class->fnid >= FNID_BUTTON )
701  {
702  Class->hModule = hModClient;
703  TRACE("Clone Class 0x%p Reset hM 0x%p\n",Class, Class->hModule);
704  }
705 
706  /* Update some pointers and link the class */
707  Class->rpdeskParent = Desktop;
708  Class->cWndReferenceCount = 0;
709 
710  if (BaseClass->rpdeskParent == NULL)
711  {
712  /* We don't really need the base class on the shared
713  heap anymore, delete it so the only class left is
714  the clone we just created, which now serves as the
715  new base class */
716  ASSERT(BaseClass->pclsClone == NULL);
717  ASSERT(Class->pclsClone == NULL);
718  Class->pclsBase = Class;
719  Class->pclsNext = BaseClass->pclsNext;
720 
721  /* Replace the base class */
723  Class);
724 
725  /* Destroy the obsolete copy on the shared heap */
726  BaseClass->pclsBase = NULL;
727  BaseClass->pclsClone = NULL;
728  IntDestroyClass(BaseClass);
729  }
730  else
731  {
732  /* Link in the clone */
733  Class->pclsClone = NULL;
734  Class->pclsBase = BaseClass;
735  Class->pclsNext = BaseClass->pclsClone;
736  (void)InterlockedExchangePointer((PVOID*)&BaseClass->pclsClone,
737  Class);
738  }
739  }
740  else
741  {
743  }
744  }
745  return Class;
746 }
static const WCHAR Class[]
Definition: cfgmgr.c:39
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
static VOID IntDestroyClass(IN OUT PCLS Class)
Definition: class.c:228
static __inline PVOID DesktopHeapAlloc(IN PDESKTOP Desktop, IN SIZE_T Bytes)
Definition: desktop.h:230
smooth NULL
Definition: ftsmooth.c:416
Definition: ntuser.h:533
static CHAR Desktop[MAX_PATH]
Definition: dem.c:256
#define TRACE(s)
Definition: solgame.cpp:4
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define FNID_GHOST
Definition: ntuser.h:837
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define FNID_BUTTON
Definition: ntuser.h:828
HINSTANCE hModClient
Definition: ntuser.c:25
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27
VOID FASTCALL UserReferenceObject(PVOID obj)
Definition: object.c:697

Referenced by IntReferenceClass().

◆ IntGetClassWndProc()

WNDPROC FASTCALL IntGetClassWndProc ( PCLS  Class,
BOOL  Ansi 
)

Definition at line 494 of file class.c.

495 {
496  INT i;
497  WNDPROC gcpd = NULL, Ret = NULL;
498 
499  if (Class->CSF_flags & CSF_SERVERSIDEPROC)
500  {
501  for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
502  {
503  if (GETPFNSERVER(i) == Class->lpfnWndProc)
504  {
505  if (Ansi)
506  Ret = GETPFNCLIENTA(i);
507  else
508  Ret = GETPFNCLIENTW(i);
509  }
510  }
511  return Ret;
512  }
513  Ret = Class->lpfnWndProc;
514 
515  if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON)
516  {
517  if (Ansi)
518  {
519  if (GETPFNCLIENTW(Class->fnid) == Class->lpfnWndProc)
520  Ret = GETPFNCLIENTA(Class->fnid);
521  }
522  else
523  {
524  if (GETPFNCLIENTA(Class->fnid) == Class->lpfnWndProc)
525  Ret = GETPFNCLIENTW(Class->fnid);
526  }
527  }
528 
529  if ( Ret != Class->lpfnWndProc ||
530  Ansi == !!(Class->CSF_flags & CSF_ANSIPROC) )
531  return Ret;
532 
533  gcpd = (WNDPROC)UserGetCPD( Class,
535  (ULONG_PTR)Ret);
536 
537  return (gcpd ? gcpd : Ret);
538 }
#define GETPFNSERVER(fnid)
Definition: ntuser.h:870
#define GETPFNCLIENTW(fnid)
Definition: ntuser.h:867
ULONG_PTR FASTCALL UserGetCPD(PVOID pvClsWnd, GETCPD Flags, ULONG_PTR ProcIn)
Definition: callproc.c:107
int32_t INT
Definition: typedefs.h:58
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
smooth NULL
Definition: ftsmooth.c:416
#define FNID_SWITCH
Definition: ntuser.h:827
#define CSF_SERVERSIDEPROC
Definition: ntuser.h:524
#define GETPFNCLIENTA(fnid)
Definition: ntuser.h:865
#define CSF_ANSIPROC
Definition: ntuser.h:525
LRESULT(CALLBACK * WNDPROC)(HWND, UINT, WPARAM, LPARAM)
Definition: winuser.h:2881
#define FNID_GHOST
Definition: ntuser.h:837
#define FNID_BUTTON
Definition: ntuser.h:828
#define ULONG_PTR
Definition: config.h:101
#define FNID_FIRST
Definition: ntuser.h:820

Referenced by IntSetClassWndProc(), and UserGetClassInfo().

◆ IntMakeCloneBaseClass()

static VOID IntMakeCloneBaseClass ( IN OUT PCLS  Class,
IN OUT PCLS BaseClassLink,
IN OUT PCLS CloneLink 
)
static

Definition at line 777 of file class.c.

780 {
781  PCLS Clone;
782 
783  ASSERT(Class->pclsBase != Class);
784  ASSERT(Class->pclsBase->pclsClone != NULL);
785  ASSERT(Class->rpdeskParent != NULL);
786  ASSERT(Class->cWndReferenceCount != 0);
787  ASSERT(Class->pclsBase->rpdeskParent != NULL);
788  ASSERT(Class->pclsBase->cWndReferenceCount == 0);
789 
790  /* Unlink the clone */
791  *CloneLink = Class->pclsNext;
792  Class->pclsClone = Class->pclsBase->pclsClone;
793 
794  /* Update the class information to make it a base class */
795  Class->pclsBase = Class;
796  Class->pclsNext = (*BaseClassLink)->pclsNext;
797 
798  /* Update all clones */
799  Clone = Class->pclsClone;
800  while (Clone != NULL)
801  {
802  ASSERT(Clone->pclsClone == NULL);
803  Clone->pclsBase = Class;
804 
805  Clone = Clone->pclsNext;
806  }
807 
808  /* Link in the new base class */
809  (void)InterlockedExchangePointer((PVOID*)BaseClassLink,
810  Class);
811 }
static const WCHAR Class[]
Definition: cfgmgr.c:39
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
struct _CLS * pclsClone
Definition: ntuser.h:546
smooth NULL
Definition: ftsmooth.c:416
Definition: ntuser.h:533
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
struct _CLS * pclsBase
Definition: ntuser.h:545
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
struct _CLS * pclsNext
Definition: ntuser.h:535

Referenced by IntDereferenceClass().

◆ IntMoveClassToSharedHeap()

static BOOL IntMoveClassToSharedHeap ( IN OUT PCLS  Class,
IN OUT PCLS **  ClassLinkPtr 
)
static

Definition at line 897 of file class.c.

899 {
900  PCLS NewClass;
901  SIZE_T ClassSize;
902 
903  ASSERT(Class->pclsBase == Class);
904  ASSERT(Class->rpdeskParent != NULL);
905  ASSERT(Class->cWndReferenceCount == 0);
906  ASSERT(Class->pclsClone == NULL);
907 
908  ClassSize = sizeof(*Class) + (SIZE_T)Class->cbclsExtra;
909 
910  /* Allocate the new base class on the shared heap */
911  NewClass = UserHeapAlloc(ClassSize);
912  if (NewClass != NULL)
913  {
914  RtlCopyMemory(NewClass,
915  Class,
916  ClassSize);
917 
918  NewClass->rpdeskParent = NULL;
919  NewClass->pclsBase = NewClass;
920 
921  if (NewClass->spcur)
922  UserReferenceObject(NewClass->spcur);
923  if (NewClass->spicn)
924  UserReferenceObject(NewClass->spicn);
925  if (NewClass->spicnSm)
926  UserReferenceObject(NewClass->spicnSm);
927 
928  /* Replace the class in the list */
929  (void)InterlockedExchangePointer((PVOID*)*ClassLinkPtr,
930  NewClass);
931  *ClassLinkPtr = &NewClass->pclsNext;
932 
933  /* Free the obsolete class on the desktop heap */
934  Class->pclsBase = NULL;
936  return TRUE;
937  }
938 
939  return FALSE;
940 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
struct _DESKTOP * rpdeskParent
Definition: ntuser.h:539
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
#define TRUE
Definition: types.h:120
struct _CURICON_OBJECT * spcur
Definition: ntuser.h:554
static __inline PVOID UserHeapAlloc(SIZE_T Bytes)
Definition: usrheap.h:34
static VOID IntDestroyClass(IN OUT PCLS Class)
Definition: class.c:228
struct _CURICON_OBJECT * spicn
Definition: ntuser.h:553
#define FALSE
Definition: types.h:117
struct _CURICON_OBJECT * spicnSm
Definition: ntuser.h:558
smooth NULL
Definition: ftsmooth.c:416
Definition: ntuser.h:533
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
struct _CLS * pclsBase
Definition: ntuser.h:545
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
ULONG_PTR SIZE_T
Definition: typedefs.h:80
struct _CLS * pclsNext
Definition: ntuser.h:535
VOID FASTCALL UserReferenceObject(PVOID obj)
Definition: object.c:697

Referenced by IntCheckDesktopClasses().

◆ IntReferenceClass()

PCLS IntReferenceClass ( IN OUT PCLS  BaseClass,
IN OUT PCLS ClassLink,
IN PDESKTOP  Desktop 
)

Definition at line 749 of file class.c.

752 {
753  PCLS Class;
754  ASSERT(BaseClass->pclsBase == BaseClass);
755 
756  if (Desktop != NULL)
757  {
758  Class = IntGetClassForDesktop(BaseClass,
759  ClassLink,
760  Desktop);
761  }
762  else
763  {
764  Class = BaseClass;
765  }
766 
767  if (Class != NULL)
768  {
769  Class->cWndReferenceCount++;
770  }
771 
772  return Class;
773 }
static const WCHAR Class[]
Definition: cfgmgr.c:39
static PCLS IntGetClassForDesktop(IN OUT PCLS BaseClass, IN OUT PCLS *ClassLink, IN PDESKTOP Desktop)
Definition: class.c:625
smooth NULL
Definition: ftsmooth.c:416
Definition: ntuser.h:533
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)

Referenced by IntGetAndReferenceClass().

◆ IntRegisterClassAtom()

static BOOL IntRegisterClassAtom ( IN PUNICODE_STRING  ClassName,
OUT RTL_ATOM pAtom 
)
static

Definition at line 334 of file class.c.

336 {
337  WCHAR szBuf[65];
338  PWSTR AtomName = szBuf;
340 
341  if (ClassName->Length != 0)
342  {
343  if (ClassName->Length + sizeof(UNICODE_NULL) > sizeof(szBuf))
344  {
345  AtomName = ExAllocatePoolWithTag(PagedPool,
346  ClassName->Length + sizeof(UNICODE_NULL),
347  TAG_USTR);
348 
349  if (AtomName == NULL)
350  {
352  return FALSE;
353  }
354  }
355 
356  _SEH2_TRY
357  {
358  RtlCopyMemory(AtomName,
359  ClassName->Buffer,
360  ClassName->Length);
361  }
363  {
364  if (AtomName != szBuf)
365  ExFreePoolWithTag(AtomName, TAG_USTR);
367  _SEH2_YIELD(return FALSE);
368  }
369  _SEH2_END;
370  AtomName[ClassName->Length / sizeof(WCHAR)] = UNICODE_NULL;
371  }
372  else
373  {
374  ASSERT(IS_ATOM(ClassName->Buffer));
375  AtomName = ClassName->Buffer;
376  }
377 
379  AtomName,
380  pAtom);
381 
382  if (AtomName != ClassName->Buffer && AtomName != szBuf)
383  ExFreePoolWithTag(AtomName, TAG_USTR);
384 
385 
386  if (!NT_SUCCESS(Status))
387  {
389  return FALSE;
390  }
391 
392  return TRUE;
393 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define TRUE
Definition: types.h:120
uint16_t * PWSTR
Definition: typedefs.h:56
NTSYSAPI NTSTATUS NTAPI RtlAddAtomToAtomTable(_In_ PRTL_ATOM_TABLE AtomTable, _In_ PWSTR AtomName, _Out_ PRTL_ATOM Atom)
LONG NTSTATUS
Definition: precomp.h:26
PRTL_ATOM_TABLE gAtomTable
Definition: session.c:13
_SEH2_TRY
Definition: create.c:4226
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Status
Definition: gdiplustypes.h:24
VOID FASTCALL SetLastNtError(NTSTATUS Status)
Definition: error.c:36
#define TAG_USTR
Definition: libsupp.c:111
_SEH2_END
Definition: create.c:4400
#define IS_ATOM(x)
Definition: class.h:3
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13

Referenced by IntCreateClass(), IntSetClassAtom(), and RegisterControlAtoms().

◆ IntSetClassAtom()

static BOOL IntSetClassAtom ( IN OUT PCLS  Class,
IN PUNICODE_STRING  ClassName 
)
static

Definition at line 445 of file class.c.

447 {
448  RTL_ATOM Atom = (RTL_ATOM)0;
449 
450  /* Update the base class first */
451  Class = Class->pclsBase;
452  if (ClassName->Length > 0)
453  {
454  if (!IntRegisterClassAtom(ClassName,
455  &Atom))
456  {
457  ERR("RegisterClassAtom failed ! %x\n", EngGetLastError());
458  return FALSE;
459  }
460  }
461  else
462  {
463  if (IS_ATOM(ClassName->Buffer))
464  {
465  Atom = (ATOM)((ULONG_PTR)ClassName->Buffer & 0xffff); // XXX: are we missing refcount here ?
466  }
467  else
468  {
470  return FALSE;
471  }
472  }
473 
474  IntDeregisterClassAtom(Class->atomNVClassName);
475 
476  Class->atomNVClassName = Atom;
477 
478  /* Update the clones */
479  Class = Class->pclsClone;
480  while (Class != NULL)
481  {
482  Class->atomNVClassName = Atom;
483 
484  Class = Class->pclsNext;
485  }
486 
487  return TRUE;
488 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
ENGAPI ULONG APIENTRY EngGetLastError(VOID)
Definition: error.c:12
unsigned short RTL_ATOM
Definition: atom.c:42
WORD ATOM
Definition: dimm.idl:113
#define TRUE
Definition: types.h:120
_Out_ RTL_ATOM * Atom
Definition: class.h:54
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define FALSE
Definition: types.h:117
smooth NULL
Definition: ftsmooth.c:416
static NTSTATUS IntDeregisterClassAtom(IN RTL_ATOM Atom)
Definition: class.c:416
#define ERR(fmt,...)
Definition: debug.h:110
#define IS_ATOM(x)
Definition: class.h:3
static BOOL IntRegisterClassAtom(IN PUNICODE_STRING ClassName, OUT RTL_ATOM *pAtom)
Definition: class.c:334
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27

Referenced by UserSetClassLongPtr().

◆ IntSetClassMenuName()

static BOOL IntSetClassMenuName ( IN PCLS  Class,
IN PUNICODE_STRING  MenuName 
)
static

Definition at line 1754 of file class.c.

1756 {
1757  BOOL Ret = FALSE;
1758 
1759  /* Change the base class first */
1760  Class = Class->pclsBase;
1761 
1762  if (MenuName->Length != 0)
1763  {
1765  PWSTR strBufW;
1766 
1767  AnsiString.MaximumLength = (USHORT)RtlUnicodeStringToAnsiSize(MenuName);
1768 
1769  strBufW = UserHeapAlloc(MenuName->Length + sizeof(UNICODE_NULL) +
1770  AnsiString.MaximumLength);
1771  if (strBufW != NULL)
1772  {
1773  _SEH2_TRY
1774  {
1775  NTSTATUS Status;
1776 
1777  /* Copy the unicode string */
1778  RtlCopyMemory(strBufW,
1779  MenuName->Buffer,
1780  MenuName->Length);
1781  strBufW[MenuName->Length / sizeof(WCHAR)] = UNICODE_NULL;
1782 
1783  /* Create an ANSI copy of the string */
1784  AnsiString.Buffer = (PSTR)(strBufW + (MenuName->Length / sizeof(WCHAR)) + 1);
1786  MenuName,
1787  FALSE);
1788  if (!NT_SUCCESS(Status))
1789  {
1791  _SEH2_LEAVE;
1792  }
1793 
1794  Ret = TRUE;
1795  }
1797  {
1799  }
1800  _SEH2_END;
1801 
1802  if (Ret)
1803  {
1804  /* Update the base class */
1806  Class->lpszClientUnicodeMenuName = strBufW;
1807  Class->lpszClientAnsiMenuName = AnsiString.Buffer;
1808  Class->MenuNameIsString = TRUE;
1809 
1810  /* Update the clones */
1811  Class = Class->pclsClone;
1812  while (Class != NULL)
1813  {
1814  Class->lpszClientUnicodeMenuName = strBufW;
1815  Class->lpszClientAnsiMenuName = AnsiString.Buffer;
1816  Class->MenuNameIsString = TRUE;
1817 
1818  Class = Class->pclsNext;
1819  }
1820  }
1821  else
1822  {
1823  ERR("Failed to copy class menu name!\n");
1824  UserHeapFree(strBufW);
1825  }
1826  }
1827  else
1829  }
1830  else
1831  {
1832  ASSERT(IS_INTRESOURCE(MenuName->Buffer));
1833 
1834  /* Update the base class */
1836  Class->lpszClientUnicodeMenuName = MenuName->Buffer;
1837  Class->lpszClientAnsiMenuName = (PSTR)MenuName->Buffer;
1838  Class->MenuNameIsString = FALSE;
1839 
1840  /* Update the clones */
1841  Class = Class->pclsClone;
1842  while (Class != NULL)
1843  {
1844  Class->lpszClientUnicodeMenuName = MenuName->Buffer;
1845  Class->lpszClientAnsiMenuName = (PSTR)MenuName->Buffer;
1846  Class->MenuNameIsString = FALSE;
1847 
1848  Class = Class->pclsNext;
1849  }
1850 
1851  Ret = TRUE;
1852  }
1853 
1854  return Ret;
1855 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define TRUE
Definition: types.h:120
uint16_t * PWSTR
Definition: typedefs.h:56
LONG NTSTATUS
Definition: precomp.h:26
static VOID IntFreeClassMenuName(IN OUT PCLS Class)
Definition: class.c:216
static __inline BOOL UserHeapFree(PVOID lpMem)
Definition: usrheap.h:42
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
static __inline PVOID UserHeapAlloc(SIZE_T Bytes)
Definition: usrheap.h:34
_SEH2_TRY
Definition: create.c:4226
while(1)
Definition: macro.lex.yy.c:740
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
unsigned int BOOL
Definition: ntddk_ex.h:94
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
#define IS_INTRESOURCE(i)
Definition: winuser.h:580
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
Status
Definition: gdiplustypes.h:24
VOID FASTCALL SetLastNtError(NTSTATUS Status)
Definition: error.c:36
NTSYSAPI DWORD WINAPI RtlUnicodeStringToAnsiSize(const UNICODE_STRING *)
#define ERR(fmt,...)
Definition: debug.h:110
_SEH2_END
Definition: create.c:4400
unsigned short USHORT
Definition: pedump.c:61
signed char * PSTR
Definition: retypes.h:7
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
#define _SEH2_LEAVE
Definition: filesup.c:20
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27

Referenced by UserSetClassLongPtr().

◆ IntSetClassWndProc()

static WNDPROC FASTCALL IntSetClassWndProc ( IN OUT PCLS  Class,
IN WNDPROC  WndProc,
IN BOOL  Ansi 
)
static

Definition at line 543 of file class.c.

546 {
547  INT i;
548  PCALLPROCDATA pcpd;
549  WNDPROC Ret, chWndProc;
550 
551  Ret = IntGetClassWndProc(Class, Ansi);
552 
553  // If Server Side, downgrade to Client Side.
554  if (Class->CSF_flags & CSF_SERVERSIDEPROC)
555  {
556  if (Ansi) Class->CSF_flags |= CSF_ANSIPROC;
557  Class->CSF_flags &= ~CSF_SERVERSIDEPROC;
558  Class->Unicode = !Ansi;
559  }
560 
561  if (!WndProc) WndProc = Class->lpfnWndProc;
562 
563  chWndProc = WndProc;
564 
565  // Check if CallProc handle and retrieve previous call proc address and set.
567  {
569  if (pcpd) chWndProc = pcpd->pfnClientPrevious;
570  }
571 
572  Class->lpfnWndProc = chWndProc;
573 
574  // Clear test proc.
575  chWndProc = NULL;
576 
577  // Switch from Client Side call to Server Side call if match. Ref: "deftest".
578  for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
579  {
580  if (GETPFNCLIENTW(i) == Class->lpfnWndProc)
581  {
582  chWndProc = GETPFNSERVER(i);
583  break;
584  }
585  if (GETPFNCLIENTA(i) == Class->lpfnWndProc)
586  {
587  chWndProc = GETPFNSERVER(i);
588  break;
589  }
590  }
591  // If match, set/reset to Server Side and clear ansi.
592  if (chWndProc)
593  {
594  Class->lpfnWndProc = chWndProc;
595  Class->Unicode = TRUE;
596  Class->CSF_flags &= ~CSF_ANSIPROC;
597  Class->CSF_flags |= CSF_SERVERSIDEPROC;
598  }
599  else
600  {
601  Class->Unicode = !Ansi;
602 
603  if (Ansi)
604  Class->CSF_flags |= CSF_ANSIPROC;
605  else
606  Class->CSF_flags &= ~CSF_ANSIPROC;
607  }
608 
609  /* Update the clones */
610  chWndProc = Class->lpfnWndProc;
611 
612  Class = Class->pclsClone;
613  while (Class != NULL)
614  {
615  Class->Unicode = !Ansi;
616  Class->lpfnWndProc = chWndProc;
617 
618  Class = Class->pclsNext;
619  }
620 
621  return Ret;
622 }
#define GETPFNSERVER(fnid)
Definition: ntuser.h:870
WNDPROC pfnClientPrevious
Definition: ntuser.h:520
#define GETPFNCLIENTW(fnid)
Definition: ntuser.h:867
#define TRUE
Definition: types.h:120
int32_t INT
Definition: typedefs.h:58
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
smooth NULL
Definition: ftsmooth.c:416
#define FNID_SWITCH
Definition: ntuser.h:827
#define CSF_SERVERSIDEPROC
Definition: ntuser.h:524
#define GETPFNCLIENTA(fnid)
Definition: ntuser.h:865
#define CSF_ANSIPROC
Definition: ntuser.h:525
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
Definition: solitaire.cpp:598
LRESULT(CALLBACK * WNDPROC)(HWND, UINT, WPARAM, LPARAM)
Definition: winuser.h:2881
PVOID UserGetObject(PUSER_HANDLE_TABLE ht, HANDLE handle, HANDLE_TYPE type)
Definition: object.c:462
WNDPROC FASTCALL IntGetClassWndProc(PCLS Class, BOOL Ansi)
Definition: class.c:494
static __inline BOOL IsCallProcHandle(IN WNDPROC lpWndProc)
Definition: class.h:13
PUSER_HANDLE_TABLE gHandleTable
Definition: object.c:13
#define FNID_FIRST
Definition: ntuser.h:820

Referenced by UserSetClassLongPtr().

◆ LookupFnIdToiCls()

BOOL FASTCALL LookupFnIdToiCls ( int  FnId,
int iCls 
)

Definition at line 131 of file class.c.

132 {
133  int i;
134 
135  for ( i = 0; i < ARRAYSIZE(FnidToiCls); i++)
136  {
137  if (FnidToiCls[i].FnId == FnId)
138  {
139  if (iCls) *iCls = FnidToiCls[i].ClsId;
140  return TRUE;
141  }
142  }
143  if (iCls) *iCls = 0;
144  return FALSE;
145 }
static struct @4267 FnidToiCls[]
#define TRUE
Definition: types.h:120
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
int FnId
Definition: class.c:106
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define FALSE
Definition: types.h:117

Referenced by IntCreateClass(), IntIsGhostWindow(), and NtUserGetClassName().

◆ NtUserGetClassInfo()

BOOL APIENTRY NtUserGetClassInfo ( HINSTANCE  hInstance,
PUNICODE_STRING  ClassName,
LPWNDCLASSEXW  lpWndClassEx,
LPWSTR ppszMenuName,
BOOL  bAnsi 
)

Definition at line 2720 of file class.c.

2726 {
2727  UNICODE_STRING SafeClassName;
2728  WNDCLASSEXW Safewcexw;
2729  PCLS Class;
2730  RTL_ATOM ClassAtom = 0;
2731  PPROCESSINFO ppi;
2732  BOOL Ret = TRUE;
2733  NTSTATUS Status;
2734 
2735  _SEH2_TRY
2736  {
2737  ProbeForWrite( lpWndClassEx, sizeof(WNDCLASSEXW), sizeof(ULONG));
2738  RtlCopyMemory( &Safewcexw, lpWndClassEx, sizeof(WNDCLASSEXW));
2739  if (ppszMenuName)
2740  {
2741  ProbeForWrite(ppszMenuName, sizeof(*ppszMenuName), sizeof(PVOID));
2742  }
2743  }
2745  {
2747  _SEH2_YIELD(return FALSE);
2748  }
2749  _SEH2_END;
2750 
2751  Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassName);
2752  if (!NT_SUCCESS(Status))
2753  {
2754  ERR("Error capturing the class name\n");
2756  return FALSE;
2757  }
2758 
2759  // If null instance use client.
2760  if (!hInstance) hInstance = hModClient;
2761 
2762  TRACE("GetClassInfo(%wZ, %p)\n", &SafeClassName, hInstance);
2763 
2764  /* NOTE: Need exclusive lock because getting the wndproc might require the
2765  creation of a call procedure handle */
2767 
2768  ppi = GetW32ProcessInfo();
2769  if (!(ppi->W32PF_flags & W32PF_CLASSESREGISTERED))
2770  {
2772  }
2773 
2774  ClassAtom = IntGetClassAtom(&SafeClassName,
2775  hInstance,
2776  ppi,
2777  &Class,
2778  NULL);
2779  if (ClassAtom != (RTL_ATOM)0)
2780  {
2781  ClassAtom = Class->atomNVClassName;
2782  Ret = UserGetClassInfo(Class, &Safewcexw, bAnsi, hInstance);
2783  }
2784  else
2785  {
2787  Ret = FALSE;
2788  }
2789 
2790  UserLeave();
2791 
2792  if (Ret)
2793  {
2794  _SEH2_TRY
2795  {
2796  /* Emulate Function. */
2797  if (ppszMenuName) *ppszMenuName = (LPWSTR)Safewcexw.lpszMenuName;
2798 
2799  RtlCopyMemory(lpWndClassEx, &Safewcexw, sizeof(WNDCLASSEXW));
2800 
2801  // From Wine:
2802  /* We must return the atom of the class here instead of just TRUE. */
2803  /* Undocumented behavior! Return the class atom as a BOOL! */
2804  Ret = (BOOL)ClassAtom;
2805  }
2807  {
2809  Ret = FALSE;
2810  }
2811  _SEH2_END;
2812  }
2813 
2814  if (!IS_ATOM(SafeClassName.Buffer))
2815  ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING);
2816 
2817  return Ret;
2818 }
static const WCHAR Class[]
Definition: cfgmgr.c:39
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
unsigned short RTL_ATOM
Definition: atom.c:42
static BOOL UserGetClassInfo(IN PCLS Class, OUT PWNDCLASSEXW lpwcx, IN BOOL Ansi, HINSTANCE hInstance)
Definition: class.c:2249
#define TRUE
Definition: types.h:120
BOOL FASTCALL UserRegisterSystemClasses(VOID)
Definition: class.c:2306
LONG NTSTATUS
Definition: precomp.h:26
#define BOOL
Definition: nt_native.h:43
_Must_inspect_result_ NTSTATUS NTAPI ProbeAndCaptureUnicodeStringOrAtom(_Out_ _When_(return >=0, _At_(pustrOut->Buffer, _Post_ _Notnull_)) PUNICODE_STRING pustrOut, __in_data_source(USER_MODE) _In_ PUNICODE_STRING pustrUnsafe)
Definition: class.c:150
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
_SEH2_TRY
Definition: create.c:4226
HINSTANCE hInstance
Definition: charmap.c:20
LPCWSTR lpszMenuName
Definition: winuser.h:3200
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
#define TAG_STRING
Definition: oslist.h:22
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
Definition: ntuser.h:533
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:247
struct _PROCESSINFO * GetW32ProcessInfo(VOID)
Definition: misc.c:773
#define TRACE(s)
Definition: solgame.cpp:4
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Status
Definition: gdiplustypes.h:24
VOID FASTCALL SetLastNtError(NTSTATUS Status)
Definition: error.c:36
#define ERR(fmt,...)
Definition: debug.h:110
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:255
_SEH2_END
Definition: create.c:4400
#define W32PF_CLASSESREGISTERED
Definition: win32.h:17
unsigned int ULONG
Definition: retypes.h:1
RTL_ATOM IntGetClassAtom(_In_ PUNICODE_STRING ClassName, IN HINSTANCE hInstance OPTIONAL, IN PPROCESSINFO pi OPTIONAL, OUT PCLS *BaseClass OPTIONAL, OUT PCLS **Link OPTIONAL)
Definition: class.c:1364
#define IS_ATOM(x)
Definition: class.h:3
HINSTANCE hModClient
Definition: ntuser.c:25
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define ERROR_CLASS_DOES_NOT_EXIST
Definition: winerror.h:892
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27

Referenced by GetClassInfoExA(), GetClassInfoExW(), and START_TEST().

◆ NtUserGetClassName()

INT APIENTRY NtUserGetClassName ( IN HWND  hWnd,
IN BOOL  Real,
OUT PUNICODE_STRING  ClassName 
)

Definition at line 2822 of file class.c.

2825 {
2826  PWND Window;
2827  UNICODE_STRING CapturedClassName;
2828  INT iCls, Ret = 0;
2829  RTL_ATOM Atom = 0;
2830 
2831  UserEnterShared();
2832 
2834  if (Window != NULL)
2835  {
2836  if (Real && Window->fnid && !(Window->fnid & FNID_DESTROY))
2837  {
2838  if (LookupFnIdToiCls(Window->fnid, &iCls))
2839  {
2840  Atom = gpsi->atomSysClass[iCls];
2841  }
2842  }
2843 
2844  _SEH2_TRY
2845  {
2846  ProbeForWriteUnicodeString(ClassName);
2847  CapturedClassName = *ClassName;
2848  if (CapturedClassName.Length != 0)
2849  {
2850  ProbeForRead(CapturedClassName.Buffer,
2851  CapturedClassName.Length,
2852  sizeof(WCHAR));
2853  }
2854 
2855  /* Get the class name */
2856  Ret = UserGetClassName(Window->pcls,
2857  &CapturedClassName,
2858  Atom,
2859  FALSE);
2860 
2861  if (Ret != 0)
2862  {
2863  /* Update the Length field */
2864  ClassName->Length = CapturedClassName.Length;
2865  }
2866  }
2868  {
2870  }
2871  _SEH2_END;
2872  }
2873 
2874  UserLeave();
2875 
2876  return Ret;
2877 }
VOID FASTCALL UserEnterShared(VOID)
Definition: ntuser.c:241
unsigned short RTL_ATOM
Definition: atom.c:42
HWND hWnd
Definition: settings.c:17
#define FNID_DESTROY
Definition: ntuser.h:859
_Out_ RTL_ATOM * Atom
Definition: class.h:54
PSERVERINFO gpsi
Definition: main.c:27
int32_t INT
Definition: typedefs.h:58
_SEH2_TRY
Definition: create.c:4226
Definition: window.c:28
#define FALSE
Definition: types.h:117
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
INT UserGetClassName(IN PCLS Class, IN OUT PUNICODE_STRING ClassName, IN RTL_ATOM Atom, IN BOOL Ansi)
Definition: class.c:1634
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:103
#define ProbeForWriteUnicodeString(Ptr)
Definition: probe.h:48
__wchar_t WCHAR
Definition: xmlstorage.h:180
int Window
Definition: x11stubs.h:26
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
VOID FASTCALL SetLastNtError(NTSTATUS Status)
Definition: error.c:36
Definition: ntuser.h:657
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:255
_SEH2_END
Definition: create.c:4400
BOOL FASTCALL LookupFnIdToiCls(int FnId, int *iCls)
Definition: class.c:131
float Real
Definition: definitions.h:36
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
ATOM atomSysClass[ICLS_NOTUSED+1]
Definition: ntuser.h:1013

Referenced by GetClassNameW(), and RealGetWindowClassW().

◆ NtUserGetWOWClass()

PCLS APIENTRY NtUserGetWOWClass ( HINSTANCE  hInstance,
PUNICODE_STRING  ClassName 
)

Definition at line 2882 of file class.c.

2885 {
2886  UNICODE_STRING SafeClassName;
2887  PPROCESSINFO pi;
2888  PCLS Class = NULL;
2889  RTL_ATOM ClassAtom = 0;
2890  NTSTATUS Status;
2891 
2892  Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassName);
2893  if (!NT_SUCCESS(Status))
2894  {
2895  ERR("Error capturing the class name\n");
2897  return FALSE;
2898  }
2899 
2901 
2902  pi = GetW32ProcessInfo();
2903 
2904  ClassAtom = IntGetClassAtom(&SafeClassName,
2905  hInstance,
2906  pi,
2907  &Class,
2908  NULL);
2909  if (!ClassAtom)
2910  {
2912  }
2913 
2914 
2915  if (SafeClassName.Buffer && !IS_ATOM(SafeClassName.Buffer))
2916  ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING);
2917 
2918  UserLeave();
2919 //
2920 // Don't forget to use DesktopPtrToUser( ? ) with return pointer in user space.
2921 //
2922  return Class;
2923 }
static const WCHAR Class[]
Definition: cfgmgr.c:39
unsigned short RTL_ATOM
Definition: atom.c:42
LONG NTSTATUS
Definition: precomp.h:26
_Must_inspect_result_ NTSTATUS NTAPI ProbeAndCaptureUnicodeStringOrAtom(_Out_ _When_(return >=0, _At_(pustrOut->Buffer, _Post_ _Notnull_)) PUNICODE_STRING pustrOut, __in_data_source(USER_MODE) _In_ PUNICODE_STRING pustrUnsafe)
Definition: class.c:150
HINSTANCE hInstance
Definition: charmap.c:20
#define FALSE
Definition: types.h:117
#define TAG_STRING
Definition: oslist.h:22
smooth NULL
Definition: ftsmooth.c:416
Definition: ntuser.h:533
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:247
struct _PROCESSINFO * GetW32ProcessInfo(VOID)
Definition: misc.c:773
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static refpint_t pi[]
Definition: server.c:96
Status
Definition: gdiplustypes.h:24
VOID FASTCALL SetLastNtError(NTSTATUS Status)
Definition: error.c:36
#define ERR(fmt,...)
Definition: debug.h:110
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:255
RTL_ATOM IntGetClassAtom(_In_ PUNICODE_STRING ClassName, IN HINSTANCE hInstance OPTIONAL, IN PPROCESSINFO pi OPTIONAL, OUT PCLS *BaseClass OPTIONAL, OUT PCLS **Link OPTIONAL)
Definition: class.c:1364
#define IS_ATOM(x)
Definition: class.h:3
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define ERROR_CLASS_DOES_NOT_EXIST
Definition: winerror.h:892
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27

Referenced by START_TEST().

◆ NtUserRegisterClassExWOW()

RTL_ATOM APIENTRY NtUserRegisterClassExWOW ( WNDCLASSEXW lpwcx,
PUNICODE_STRING  ClassName,
PUNICODE_STRING  ClsVersion,
PCLSMENUNAME  pClassMenuName,
DWORD  fnID,
DWORD  Flags,
LPDWORD  pWow 
)

Definition at line 2413 of file class.c.

2431 {
2432  WNDCLASSEXW CapturedClassInfo = {0};
2433  UNICODE_STRING CapturedName = {0}, CapturedMenuName = {0}, CapturedVersion = {0};
2434  RTL_ATOM Ret = (RTL_ATOM)0;
2436  BOOL Exception = FALSE;
2437 
2438  if (Flags & ~(CSF_ANSIPROC))
2439  {
2440  ERR("NtUserRegisterClassExWOW Bad Flags!\n");
2442  return Ret;
2443  }
2444 
2446 
2447  TRACE("NtUserRegisterClassExWOW ClsN %wZ\n",ClassName);
2448 
2449  if ( !(ppi->W32PF_flags & W32PF_CLASSESREGISTERED ))
2450  {
2452  }
2453 
2454  _SEH2_TRY
2455  {
2456  /* Probe the parameters and basic parameter checks */
2457  if (ProbeForReadUint(&lpwcx->cbSize) != sizeof(WNDCLASSEXW))
2458  {
2459  ERR("NtUserRegisterClassExWOW Wrong cbSize!\n");
2460  goto InvalidParameter;
2461  }
2462 
2463  ProbeForRead(lpwcx,
2464  sizeof(WNDCLASSEXW),
2465  sizeof(ULONG));
2466  RtlCopyMemory(&CapturedClassInfo,
2467  lpwcx,
2468  sizeof(WNDCLASSEXW));
2469 
2470  CapturedName = ProbeForReadUnicodeString(ClassName);
2471  CapturedVersion = ProbeForReadUnicodeString(ClsVersion);
2472 
2473  ProbeForRead(pClassMenuName,
2474  sizeof(CLSMENUNAME),
2475  1);
2476 
2477  CapturedMenuName = ProbeForReadUnicodeString(pClassMenuName->pusMenuName);
2478 
2479  if ( (CapturedName.Length & 1) ||
2480  (CapturedMenuName.Length & 1) ||
2481  (CapturedClassInfo.cbClsExtra < 0) ||
2482  ((CapturedClassInfo.cbClsExtra + CapturedName.Length +
2483  CapturedMenuName.Length + sizeof(CLS))
2484  < (ULONG)CapturedClassInfo.cbClsExtra) ||
2485  (CapturedClassInfo.cbWndExtra < 0) ||
2486  (CapturedClassInfo.hInstance == NULL) )
2487  {
2488  ERR("NtUserRegisterClassExWOW Invalid Parameter Error!\n");
2489  goto InvalidParameter;
2490  }
2491 
2492  if (CapturedName.Length != 0)
2493  {
2494  ProbeForRead(CapturedName.Buffer,
2495  CapturedName.Length,
2496  sizeof(WCHAR));
2497  }
2498  else
2499  {
2500  if (!IS_ATOM(CapturedName.Buffer))
2501  {
2502  ERR("NtUserRegisterClassExWOW ClassName Error!\n");
2503  goto InvalidParameter;
2504  }
2505  }
2506 
2507  if (CapturedVersion.Length != 0)
2508  {
2509  ProbeForRead(CapturedVersion.Buffer,
2510  CapturedVersion.Length,
2511  sizeof(WCHAR));
2512  }
2513  else
2514  {
2515  if (!IS_ATOM(CapturedVersion.Buffer))
2516  {
2517  ERR("NtUserRegisterClassExWOW ClassName Error!\n");
2518  goto InvalidParameter;
2519  }
2520  }
2521 
2522  if (CapturedMenuName.Length != 0)
2523  {
2524  ProbeForRead(CapturedMenuName.Buffer,
2525  CapturedMenuName.Length,
2526  sizeof(WCHAR));
2527  }
2528  else if (CapturedMenuName.Buffer != NULL &&
2529  !IS_INTRESOURCE(CapturedMenuName.Buffer))
2530  {
2531  ERR("NtUserRegisterClassExWOW MenuName Error!\n");
2534  _SEH2_LEAVE;
2535  }
2536 
2537  if (IsCallProcHandle(lpwcx->lpfnWndProc))
2538  { // Never seen this yet, but I'm sure it's a little haxxy trick!
2539  // If this pops up we know what todo!
2540  ERR("NtUserRegisterClassExWOW WndProc is CallProc!!\n");
2541  }
2542 
2543  TRACE("NtUserRegisterClassExWOW MnuN %wZ\n",&CapturedMenuName);
2544  }
2546  {
2547  ERR("NtUserRegisterClassExWOW Exception Error!\n");
2549  Exception = TRUE;
2550  }
2551  _SEH2_END;
2552 
2553  if (!Exception)
2554  {
2555  /* Register the class */
2556  Ret = UserRegisterClass(&CapturedClassInfo,
2557  &CapturedName,
2558  &CapturedVersion,
2559  &CapturedMenuName,
2560  fnID,
2561  Flags);
2562  }
2563 
2564  if (!Ret)
2565  {
2566  TRACE("NtUserRegisterClassExWOW Null Return!\n");
2567  }
2568 
2569  UserLeave();
2570 
2571  return Ret;
2572 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
unsigned short RTL_ATOM
Definition: atom.c:42
int cbWndExtra
Definition: winuser.h:3195
#define TRUE
Definition: types.h:120
BOOL FASTCALL UserRegisterSystemClasses(VOID)
Definition: class.c:2306
_SEH2_TRY
Definition: create.c:4226
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
Definition: ntuser.h:533
int cbClsExtra
Definition: winuser.h:3194
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:247
struct _PROCESSINFO * GetW32ProcessInfo(VOID)
Definition: misc.c:773
#define TRACE(s)
Definition: solgame.cpp:4
#define IS_INTRESOURCE(i)
Definition: winuser.h:580
#define ProbeForReadUint(Ptr)
Definition: probe.h:67
__wchar_t WCHAR
Definition: xmlstorage.h:180
UINT cbSize
Definition: winuser.h:3191
HINSTANCE hInstance
Definition: winuser.h:3196
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
#define CSF_ANSIPROC
Definition: ntuser.h:525
VOID FASTCALL SetLastNtError(NTSTATUS Status)
Definition: error.c:36
WNDPROC lpfnWndProc
Definition: winuser.h:3193
#define ERR(fmt,...)
Definition: debug.h:110
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:255
_SEH2_END
Definition: create.c:4400
#define W32PF_CLASSESREGISTERED
Definition: win32.h:17
PUNICODE_STRING pusMenuName
Definition: ntuser.h:468
#define ProbeForReadUnicodeString(Ptr)
Definition: probe.h:77
unsigned int ULONG
Definition: retypes.h:1
#define IS_ATOM(x)
Definition: class.h:3
RTL_ATOM UserRegisterClass(IN CONST WNDCLASSEXW *lpwcx, IN PUNICODE_STRING ClassName, IN PUNICODE_STRING ClassVersion, IN PUNICODE_STRING MenuName, IN DWORD fnID, IN DWORD dwFlags)
Definition: class.c:1491
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
#define _SEH2_LEAVE
Definition: filesup.c:20
static __inline BOOL IsCallProcHandle(IN WNDPROC lpWndProc)
Definition: class.h:13
#define ERROR_INVALID_FLAGS
Definition: winerror.h:583
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27

Referenced by RegisterClassExWOWW(), and START_TEST().

◆ NtUserSetClassLong()

ULONG_PTR APIENTRY NtUserSetClassLong ( HWND  hWnd,
INT  Offset,
ULONG_PTR  dwNewLong,
BOOL  Ansi 
)

Definition at line 2575 of file class.c.

2579 {
2580  PPROCESSINFO pi;
2581  PWND Window;
2582  ULONG_PTR Ret = 0;
2583 
2585 
2586  pi = GetW32ProcessInfo();
2587 
2589  if (Window != NULL)
2590  {
2591  if (Window->head.pti->ppi != pi)
2592  {
2594  goto Cleanup;
2595  }
2596 
2597  _SEH2_TRY
2598  {
2600 
2601  /* Probe the parameters */
2602  if (Offset == GCW_ATOM || Offset == GCLP_MENUNAME)
2603  {
2604  /* FIXME: Resource ID can be passed directly without UNICODE_STRING ? */
2605  if (IS_ATOM(dwNewLong))
2606  {
2607  Value.MaximumLength = 0;
2608  Value.Length = 0;
2609  Value.Buffer = (PWSTR)dwNewLong;
2610  }
2611  else
2612  {
2614  }
2615 
2616  if (Value.Length & 1)
2617  {
2618  goto InvalidParameter;
2619  }
2620 
2621  if (Value.Length != 0)
2622  {
2623  ProbeForRead(Value.Buffer,
2624  Value.Length,
2625  sizeof(WCHAR));
2626  }
2627  else
2628  {
2629  if (Offset == GCW_ATOM && !IS_ATOM(Value.Buffer))
2630  {
2631  goto InvalidParameter;
2632  }
2633  else if (Offset == GCLP_MENUNAME && !IS_INTRESOURCE(Value.Buffer))
2634  {
2637  _SEH2_LEAVE;
2638  }
2639  }
2640 
2641  dwNewLong = (ULONG_PTR)&Value;
2642  }
2643 
2644  Ret = UserSetClassLongPtr(Window->pcls,
2645  Offset,
2646  dwNewLong,
2647  Ansi);
2648  switch(Offset)
2649  {
2650  case GCLP_HICONSM:
2651  case GCLP_HICON:
2652  {
2653  if (Ret && Ret != dwNewLong)
2655  }
2656  }
2657  }
2659  {
2661  }
2662  _SEH2_END;
2663  }
2664 
2665 Cleanup:
2666  UserLeave();
2667 
2668  return Ret;
2669 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
uint16_t * PWSTR
Definition: typedefs.h:56
HWND hWnd
Definition: settings.c:17
#define GCW_ATOM
Definition: winuser.h:656
#define GCLP_MENUNAME
Definition: winuser.h:672
IN UCHAR Value
Definition: halp.h:394
_SEH2_TRY
Definition: create.c:4226
#define DC_ICON
Definition: winuser.h:429
uint32_t ULONG_PTR
Definition: typedefs.h:65
Definition: window.c:28
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:103
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:247
#define GCLP_HICONSM
Definition: winuser.h:670
struct _PROCESSINFO * GetW32ProcessInfo(VOID)
Definition: misc.c:773
#define IS_INTRESOURCE(i)
Definition: winuser.h:580
__wchar_t WCHAR
Definition: xmlstorage.h:180
static refpint_t pi[]
Definition: server.c:96
int Window
Definition: x11stubs.h:26
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
#define GCLP_HICON
Definition: winuser.h:669
static const WCHAR Cleanup[]
Definition: register.c:80
VOID FASTCALL SetLastNtError(NTSTATUS Status)
Definition: error.c:36
Definition: ntuser.h:657
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:255
_SEH2_END
Definition: create.c:4400
ULONG_PTR UserSetClassLongPtr(IN PCLS Class, IN INT Index, IN ULONG_PTR NewLong, IN BOOL Ansi)
Definition: class.c:1858
BOOL UserPaintCaption(PWND pWnd, INT Flags)
Definition: defwnd.c:396
#define ProbeForReadUnicodeString(Ptr)
Definition: probe.h:77
#define ULONG_PTR
Definition: config.h:101
#define IS_ATOM(x)
Definition: class.h:3
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
#define _SEH2_LEAVE
Definition: filesup.c:20
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27

Referenced by SetClassLongA(), SetClassLongW(), and START_TEST().

◆ NtUserSetClassWord()

WORD APIENTRY NtUserSetClassWord ( HWND  hWnd,
INT  nIndex,
WORD  wNewWord 
)

Definition at line 2673 of file class.c.

2677 {
2678 /*
2679  * NOTE: Obsoleted in 32-bit windows
2680  */
2681  return(0);
2682 }

◆ NtUserUnregisterClass()

BOOL APIENTRY NtUserUnregisterClass ( IN PUNICODE_STRING  ClassNameOrAtom,
IN HINSTANCE  hInstance,
OUT PCLSMENUNAME  pClassMenuName 
)

Definition at line 2686 of file class.c.

2690 {
2691  UNICODE_STRING SafeClassName;
2692  NTSTATUS Status;
2693  BOOL Ret;
2694 
2695  Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassNameOrAtom);
2696  if (!NT_SUCCESS(Status))
2697  {
2698  ERR("Error capturing the class name\n");
2700  return FALSE;
2701  }
2702 
2704 
2705  /* Unregister the class */
2706  Ret = UserUnregisterClass(&SafeClassName, hInstance, NULL); // Null for now~
2707 
2708  UserLeave();
2709 
2710  if (SafeClassName.Buffer && !IS_ATOM(SafeClassName.Buffer))
2711  ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING);
2712 
2713  return Ret;
2714 }
BOOL UserUnregisterClass(IN PUNICODE_STRING ClassName, IN HINSTANCE hInstance, OUT PCLSMENUNAME pClassMenuName)
Definition: class.c:1578
LONG NTSTATUS
Definition: precomp.h:26
_Must_inspect_result_ NTSTATUS NTAPI ProbeAndCaptureUnicodeStringOrAtom(_Out_ _When_(return >=0, _At_(pustrOut->Buffer, _Post_ _Notnull_)) PUNICODE_STRING pustrOut, __in_data_source(USER_MODE) _In_ PUNICODE_STRING pustrUnsafe)
Definition: class.c:150
HINSTANCE hInstance
Definition: charmap.c:20
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
#define TAG_STRING
Definition: oslist.h:22
smooth NULL
Definition: ftsmooth.c:416
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:247
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
Status
Definition: gdiplustypes.h:24
VOID FASTCALL SetLastNtError(NTSTATUS Status)
Definition: error.c:36
#define ERR(fmt,...)
Definition: debug.h:110
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:255
#define IS_ATOM(x)
Definition: class.h:3
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099

Referenced by UnregisterClassA(), and UnregisterClassW().

◆ ProbeAndCaptureUnicodeStringOrAtom()

_Must_inspect_result_ NTSTATUS NTAPI ProbeAndCaptureUnicodeStringOrAtom ( _Out_ _When_(return >=0, _At_(pustrOut->Buffer, _Post_ _Notnull_)) PUNICODE_STRING  pustrOut,
__in_data_source(USER_MODE) _In_ PUNICODE_STRING  pustrUnsafe 
)

Definition at line 150 of file class.c.

153 {
155 
156  /* Default to NULL */
157  pustrOut->Buffer = NULL;
158 
159  _SEH2_TRY
160  {
161  ProbeForRead(pustrUnsafe, sizeof(UNICODE_STRING), 1);
162 
163  /* Validate the string */
164  if ((pustrUnsafe->Length & 1) || (pustrUnsafe->Buffer == NULL))
165  {
166  /* This is not legal */
168  }
169 
170  /* Check if this is an atom */
171  if (IS_ATOM(pustrUnsafe->Buffer))
172  {
173  /* Copy the atom, length is 0 */
174  pustrOut->MaximumLength = pustrOut->Length = 0;
175  pustrOut->Buffer = pustrUnsafe->Buffer;
176  }
177  else
178  {
179  /* Get the length, maximum length includes zero termination */
180  pustrOut->Length = pustrUnsafe->Length;
181  pustrOut->MaximumLength = pustrOut->Length + sizeof(WCHAR);
182 
183  /* Allocate a buffer */
184  pustrOut->Buffer = ExAllocatePoolWithTag(PagedPool,
185  pustrOut->MaximumLength,
186  TAG_STRING);
187  if (!pustrOut->Buffer)
188  {
190  }
191 
192  /* Copy the string and zero terminate it */
193  ProbeForRead(pustrUnsafe->Buffer, pustrOut->Length, 1);
194  RtlCopyMemory(pustrOut->Buffer, pustrUnsafe->Buffer, pustrOut->Length);
195  pustrOut->Buffer[pustrOut->Length / sizeof(WCHAR)] = L'\0';
196  }
197  }
199  {
200  /* Check if we already allocated a buffer */
201  if (pustrOut->Buffer)
202  {
203  /* Free the buffer */
204  ExFreePoolWithTag(pustrOut->Buffer, TAG_STRING);
206  }
207  }
208  _SEH2_END;
209 
210  return Status;
211 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LONG NTSTATUS
Definition: precomp.h:26
_SEH2_TRY
Definition: create.c:4226
#define TAG_STRING
Definition: oslist.h:22
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Status
Definition: gdiplustypes.h:24
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
static const WCHAR L[]
Definition: oid.c:1250
_SEH2_END
Definition: create.c:4400
#define IS_ATOM(x)
Definition: class.h:3
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
return STATUS_SUCCESS
Definition: btrfs.c:3014

Referenced by NtUserFindExistingCursorIcon(), NtUserGetClassInfo(), NtUserGetWOWClass(), NtUserSetCursorIconData(), and NtUserUnregisterClass().

◆ RegisterControlAtoms()

BOOL FASTCALL RegisterControlAtoms ( VOID  )

Definition at line 396 of file class.c.

397 {
398  RTL_ATOM Atom;
399  UNICODE_STRING ClassName;
400  INT i = 0;
401 
402  while ( i < ICLS_DESKTOP)
403  {
404  RtlInitUnicodeString(&ClassName, ControlsList[i]);
405  if (IntRegisterClassAtom(&ClassName, &Atom))
406  {
407  gpsi->atomSysClass[i] = Atom;
408  TRACE("Reg Control Atom %ls: 0x%x\n", ControlsList[i], Atom);
409  }
410  i++;
411  }
412  return TRUE;
413 }
unsigned short RTL_ATOM
Definition: atom.c:42
#define TRUE
Definition: types.h:120
#define ICLS_DESKTOP
Definition: ntuser.h:890
_Out_ RTL_ATOM * Atom
Definition: class.h:54
PSERVERINFO gpsi
Definition: main.c:27
int32_t INT
Definition: typedefs.h:58
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define TRACE(s)
Definition: solgame.cpp:4
static PWSTR ControlsList[]
Definition: class.c:12
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
static BOOL IntRegisterClassAtom(IN PUNICODE_STRING ClassName, OUT RTL_ATOM *pAtom)
Definition: class.c:334
ATOM atomSysClass[ICLS_NOTUSED+1]
Definition: ntuser.h:1013

Referenced by InitUserAtoms().

◆ UserAddCallProcToClass()

VOID UserAddCallProcToClass ( IN OUT PCLS  Class,
IN PCALLPROCDATA  CallProc 
)

Definition at line 423 of file class.c.

425 {
426  PCLS BaseClass;
427 
428  ASSERT(CallProc->spcpdNext == NULL);
429 
430  BaseClass = Class->pclsBase;
431  ASSERT(CallProc->spcpdNext == NULL);
432  CallProc->spcpdNext = BaseClass->spcpdFirst;
433  BaseClass->spcpdFirst = CallProc;
434 
435  /* Update all clones */
436  Class = Class->pclsClone;
437  while (Class != NULL)
438  {
439  Class->spcpdFirst = BaseClass->spcpdFirst;
440  Class = Class->pclsNext;
441  }
442 }
smooth NULL
Definition: ftsmooth.c:416
Definition: ntuser.h:533
PCALLPROCDATA spcpdFirst
Definition: ntuser.h:544
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)

Referenced by IntCreateWindow().

◆ UserGetClassInfo()

static BOOL UserGetClassInfo ( IN PCLS  Class,
OUT PWNDCLASSEXW  lpwcx,
IN BOOL  Ansi,
HINSTANCE  hInstance 
)
static

Definition at line 2249 of file class.c.

2253 {
2254  if (!Class) return FALSE;
2255 
2256  lpwcx->style = Class->style;
2257 
2258  // If fnId is set, clear the global bit. See wine class test check_style.
2259  if (Class->fnid)
2260  lpwcx->style &= ~CS_GLOBALCLASS;
2261 
2262  lpwcx->lpfnWndProc = IntGetClassWndProc(Class, Ansi);
2263 
2264  lpwcx->cbClsExtra = Class->cbclsExtra;
2265  lpwcx->cbWndExtra = Class->cbwndExtra;
2266  lpwcx->hIcon = Class->spicn ? UserHMGetHandle(Class->spicn) : NULL;
2267  lpwcx->hCursor = Class->spcur ? UserHMGetHandle(Class->spcur) : NULL;
2268  lpwcx->hIconSm = Class->spicnSm ? UserHMGetHandle(Class->spicnSm) : NULL;
2269  lpwcx->hbrBackground = Class->hbrBackground;
2270 
2271  /* Copy non-string to user first. */
2272  if (Ansi)
2273  ((PWNDCLASSEXA)lpwcx)->lpszMenuName = Class->lpszClientAnsiMenuName;
2274  else
2275  lpwcx->lpszMenuName = Class->lpszClientUnicodeMenuName;
2276 /*
2277  * FIXME: CLSMENUNAME has the answers! Copy the already made buffers from there!
2278  * Cls: lpszMenuName and lpszAnsiClassName should be used by kernel space.
2279  * lpszClientXxxMenuName should already be mapped to user space.
2280  */
2281  /* Copy string ptr to user. */
2282  if ( Class->lpszClientUnicodeMenuName != NULL &&
2283  Class->MenuNameIsString)
2284  {
2285  lpwcx->lpszMenuName = UserHeapAddressToUser(Ansi ?
2286  (PVOID)Class->lpszClientAnsiMenuName :
2287  (PVOID)Class->lpszClientUnicodeMenuName);
2288  }
2289 
2290  if (hInstance == hModClient)
2291  lpwcx->hInstance = NULL;
2292  else
2293  lpwcx->hInstance = hInstance;
2294 
2295  /* FIXME: Return the string? Okay! This is performed in User32! */
2296  //lpwcx->lpszClassName = (LPCWSTR)((ULONG_PTR)Class->atomClassName);
2297 
2298  return TRUE;
2299 }
struct _WNDCLASSEXA * PWNDCLASSEXA
#define TRUE
Definition: types.h:120
HINSTANCE hInstance
Definition: charmap.c:20
#define FALSE
Definition: types.h:117
smooth NULL
Definition: ftsmooth.c:416
#define UserHMGetHandle(obj)
Definition: ntuser.h:208
#define CS_GLOBALCLASS
Definition: winuser.h:647
static __inline PVOID UserHeapAddressToUser(PVOID lpMem)
Definition: usrheap.h:92
WNDPROC FASTCALL IntGetClassWndProc(PCLS Class, BOOL Ansi)
Definition: class.c:494
HINSTANCE hModClient
Definition: ntuser.c:25

Referenced by NtUserGetClassInfo().

◆ UserGetClassName()

INT UserGetClassName ( IN PCLS  Class,
IN OUT PUNICODE_STRING  ClassName,
IN RTL_ATOM  Atom,
IN BOOL  Ansi 
)

Definition at line 1634 of file class.c.

1638 {
1640  WCHAR szStaticTemp[32];
1641  PWSTR szTemp = NULL;
1642  ULONG BufLen = sizeof(szStaticTemp);
1643  INT Ret = 0;
1644 
1645  /* Note: Accessing the buffer in ClassName may raise an exception! */
1646 
1647  _SEH2_TRY
1648  {
1649  if (Ansi)
1650  {
1651  PANSI_STRING AnsiClassName = (PANSI_STRING)ClassName;
1652  UNICODE_STRING UnicodeClassName;
1653 
1654  /* Limit the size of the static buffer on the stack to the
1655  size of the buffer provided by the caller */
1656  if (BufLen / sizeof(WCHAR) > AnsiClassName->MaximumLength)
1657  {
1658  BufLen = AnsiClassName->MaximumLength * sizeof(WCHAR);
1659  }
1660 
1661  /* Find out how big the buffer needs to be */
1663  Class->atomClassName,
1664  NULL,
1665  NULL,
1666  szStaticTemp,
1667  &BufLen);
1669  {
1670  if (BufLen / sizeof(WCHAR) > AnsiClassName->MaximumLength)
1671  {
1672  /* The buffer required exceeds the ansi buffer provided,
1673  pretend like we're using the ansi buffer and limit the
1674  size to the buffer size provided */
1675  BufLen = AnsiClassName->MaximumLength * sizeof(WCHAR);
1676  }
1677 
1678  /* Allocate a temporary buffer that can hold the unicode class name */
1680  BufLen,
1681  USERTAG_CLASS);
1682  if (szTemp == NULL)
1683  {
1685  _SEH2_LEAVE;
1686  }
1687 
1688  /* Query the class name */
1690  Atom ? Atom : Class->atomNVClassName,
1691  NULL,
1692  NULL,
1693  szTemp,
1694  &BufLen);
1695  }
1696  else
1697  szTemp = szStaticTemp;
1698 
1699  if (NT_SUCCESS(Status))
1700  {
1701  /* Convert the atom name to ansi */
1702 
1703  RtlInitUnicodeString(&UnicodeClassName,
1704  szTemp);
1705 
1706  Status = RtlUnicodeStringToAnsiString(AnsiClassName,
1707  &UnicodeClassName,
1708  FALSE);
1709  if (!NT_SUCCESS(Status))
1710  {
1712  _SEH2_LEAVE;
1713  }
1714  }
1715 
1716  Ret = BufLen / sizeof(WCHAR);
1717  }
1718  else /* !ANSI */
1719  {
1720  BufLen = ClassName->MaximumLength;
1721 
1722  /* Query the atom name */
1724  Atom ? Atom : Class->atomNVClassName,
1725  NULL,
1726  NULL,
1727  ClassName->Buffer,
1728  &BufLen);
1729 
1730  if (!NT_SUCCESS(Status))
1731  {
1733  _SEH2_LEAVE;
1734  }
1735 
1736  Ret = BufLen / sizeof(WCHAR);
1737  }
1738  }
1740  {
1742  }
1743  _SEH2_END;
1744 
1745  if (Ansi && szTemp != NULL && szTemp != szStaticTemp)
1746  {
1748  }
1749 
1750  return Ret;
1751 }
#define BufLen
Definition: fatfs.h:167
#define USERTAG_CLASS
Definition: tags.h:203
uint16_t * PWSTR
Definition: typedefs.h:56
LONG NTSTATUS
Definition: precomp.h:26
PRTL_ATOM_TABLE gAtomTable
Definition: session.c:13
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
_Out_ RTL_ATOM * Atom
Definition: class.h:54
int32_t INT
Definition: typedefs.h:58
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
_SEH2_TRY
Definition: create.c:4226
#define FALSE
Definition: types.h:117
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
USHORT MaximumLength
Definition: env_spec_w32.h:377
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
ANSI_STRING * PANSI_STRING
Definition: env_spec_w32.h:380
NTSYSAPI NTSTATUS NTAPI RtlQueryAtomInAtomTable(_In_ PRTL_ATOM_TABLE AtomTable, _In_ RTL_ATOM Atom, _Out_opt_ PULONG RefCount, _Out_opt_ PULONG PinCount, _Out_opt_z_bytecap_(*NameLength) PWSTR AtomName, _Inout_opt_ PULONG NameLength)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
Status
Definition: gdiplustypes.h:24
VOID FASTCALL SetLastNtError(NTSTATUS Status)
Definition: error.c:36
_SEH2_END
Definition: create.c:4400
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
#define _SEH2_LEAVE
Definition: filesup.c:20
return STATUS_SUCCESS
Definition: btrfs.c:3014
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27

Referenced by IntIsGhostWindow(), and NtUserGetClassName().

◆ UserRegisterClass()

RTL_ATOM UserRegisterClass ( IN CONST WNDCLASSEXW lpwcx,
IN PUNICODE_STRING  ClassName,
IN PUNICODE_STRING  ClassVersion,
IN PUNICODE_STRING  MenuName,
IN DWORD  fnID,
IN DWORD  dwFlags 
)

Definition at line 1491 of file class.c.

1497 {
1498  PTHREADINFO pti;
1499  PPROCESSINFO pi;
1500  PCLS Class;
1501  RTL_ATOM ClassAtom;
1502  RTL_ATOM Ret = (RTL_ATOM)0;
1503 
1504  /* NOTE: Accessing the buffers in ClassName and MenuName may raise exceptions! */
1505 
1506  pti = GetW32ThreadInfo();
1507 
1508  pi = pti->ppi;
1509 
1510  // Need only to test for two conditions not four....... Fix more whine tests....
1511  if ( IntGetAtomFromStringOrAtom( ClassVersion, &ClassAtom) &&
1512  ClassAtom != (RTL_ATOM)0 &&
1513  !(dwFlags & CSF_SERVERSIDEPROC) ) // Bypass Server Sides
1514  {
1515  Class = IntFindClass( ClassAtom,
1516  lpwcx->hInstance,
1517  &pi->pclsPrivateList,
1518  NULL);
1519 
1520  if (Class != NULL && !Class->Global)
1521  {
1522  // Local class already exists
1523  TRACE("Local Class 0x%x does already exist!\n", ClassAtom);
1525  return (RTL_ATOM)0;
1526  }
1527 
1528  if (lpwcx->style & CS_GLOBALCLASS)
1529  {
1530  Class = IntFindClass( ClassAtom,
1531  NULL,
1532  &pi->pclsPublicList,
1533  NULL);
1534 
1535  if (Class != NULL && Class->Global)
1536  {
1537  TRACE("Global Class 0x%x does already exist!\n", ClassAtom);
1539  return (RTL_ATOM)0;
1540  }
1541  }
1542  }
1543 
1544  Class = IntCreateClass(lpwcx,
1545  ClassName,
1546  ClassVersion,
1547  MenuName,
1548  fnID,
1549  dwFlags,
1550  pti->rpdesk,
1551  pi);
1552 
1553  if (Class != NULL)
1554  {
1555  PCLS *List;
1556 
1557  /* Register the class */
1558  if (Class->Global)
1559  List = &pi->pclsPublicList;
1560  else
1561  List = &pi->pclsPrivateList;
1562 
1563  Class->pclsNext = *List;
1565  Class);
1566 
1567  Ret = Class->atomNVClassName;
1568  }
1569  else
1570  {
1571  ERR("UserRegisterClass: Yes, that is right, you have no Class!\n");
1572  }
1573 
1574  return Ret;
1575 }
static const WCHAR Class[]
Definition: cfgmgr.c:39
unsigned short RTL_ATOM
Definition: atom.c:42
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
PCLS FASTCALL IntCreateClass(IN CONST WNDCLASSEXW *lpwcx, IN PUNICODE_STRING ClassName, IN PUNICODE_STRING ClassVersion, IN PUNICODE_STRING MenuName, IN DWORD fnID, IN DWORD dwFlags, IN PDESKTOP Desktop, IN PPROCESSINFO pi)
Definition: class.c:1042
struct _DESKTOP * rpdesk
Definition: win32.h:91
struct _THREADINFO * GetW32ThreadInfo(VOID)
Definition: misc.c:779
PPROCESSINFO ppi
Definition: win32.h:87
smooth NULL
Definition: ftsmooth.c:416
#define ERROR_CLASS_ALREADY_EXISTS
Definition: winerror.h:891
Definition: ntuser.h:533
#define TRACE(s)
Definition: solgame.cpp:4
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
LIST_ENTRY List
Definition: psmgr.c:57
static refpint_t pi[]
Definition: server.c:96
#define CS_GLOBALCLASS
Definition: winuser.h:647
#define CSF_SERVERSIDEPROC
Definition: ntuser.h:524
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
#define ERR(fmt,...)
Definition: debug.h:110
static PCLS IntFindClass(IN RTL_ATOM Atom, IN HINSTANCE hInstance, IN PCLS *ClassList, OUT PCLS **Link OPTIONAL)
Definition: class.c:1261
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27

Referenced by NtUserRegisterClassExWOW().

◆ UserRegisterSystemClasses()

BOOL FASTCALL UserRegisterSystemClasses ( VOID  )

Definition at line 2306 of file class.c.

2307 {
2308  UINT i;
2309  UNICODE_STRING ClassName, MenuName;
2311  WNDCLASSEXW wc;
2312  PCLS Class;
2313  BOOL Ret = TRUE;
2314  HBRUSH hBrush;
2315  DWORD Flags = 0;
2316 
2317  if (ppi->W32PF_flags & W32PF_CLASSESREGISTERED)
2318  return TRUE;
2319 
2320  if ( hModClient == NULL)
2321  return FALSE;
2322 
2323  RtlZeroMemory(&ClassName, sizeof(ClassName));
2324  RtlZeroMemory(&MenuName, sizeof(MenuName));
2325 
2326  for (i = 0; i != ARRAYSIZE(DefaultServerClasses); i++)
2327  {
2328  if (!IS_ATOM(DefaultServerClasses[i].ClassName))
2329  {
2330  RtlInitUnicodeString(&ClassName, DefaultServerClasses[i].ClassName);
2331  }
2332  else
2333  {
2334  ClassName.Buffer = DefaultServerClasses[i].ClassName;
2335  ClassName.Length = 0;
2336  ClassName.MaximumLength = 0;
2337  }
2338 
2339  wc.cbSize = sizeof(wc);
2341 
2343 
2344  if (DefaultServerClasses[i].ProcW)
2345  {
2347  wc.hInstance = hModuleWin;
2348  }
2349  else
2350  {
2352  wc.hInstance = hModClient;
2353  }
2354 
2355  wc.cbClsExtra = 0;
2357  wc.hIcon = NULL;
2358 
2360  wc.hCursor = NULL;
2361  if (DefaultServerClasses[i].hCursor == (HICON)OCR_NORMAL)
2362  {
2363  if (SYSTEMCUR(ARROW) == NULL)
2364  {
2365  ERR("SYSTEMCUR(ARROW) == NULL, should not happen!!\n");
2366  }
2367  else
2368  {
2369  wc.hCursor = UserHMGetHandle(SYSTEMCUR(ARROW));
2370  }
2371  }
2372 
2373  hBrush = DefaultServerClasses[i].hBrush;
2374  if (hBrush <= (HBRUSH)COLOR_MENUBAR)
2375  {
2376  hBrush = IntGetSysColorBrush(HandleToUlong(hBrush));
2377  }
2378  wc.hbrBackground = hBrush;
2379  wc.lpszMenuName = NULL;
2380  wc.lpszClassName = ClassName.Buffer;
2381  wc.hIconSm = NULL;
2382 
2383  Class = IntCreateClass( &wc,
2384  &ClassName,
2385  &ClassName,
2386  &MenuName,
2387  DefaultServerClasses[i].fiId,
2388  Flags,
2389  NULL,
2390  ppi);
2391  if (Class != NULL)
2392  {
2393  Class->pclsNext = ppi->pclsPublicList;
2395  Class);
2396 
2398  }
2399  else
2400  {
2401  ERR("!!! Registering system class failed!\n");
2402  Ret = FALSE;
2403  }
2404  }
2405  if (Ret) ppi->W32PF_flags |= W32PF_CLASSESREGISTERED;
2406  return Ret;
2407 }
static const WCHAR Class[]
Definition: cfgmgr.c:39
static HICON
Definition: imagelist.c:84
#define GETPFNSERVER(fnid)
Definition: ntuser.h:870
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
int cbWndExtra
Definition: winuser.h:3195
DWORD dwRegisteredClasses
Definition: win32.h:272
HGDIOBJ FASTCALL IntGetSysColorBrush(INT Object)
Definition: stockobj.c:317
#define TRUE
Definition: types.h:120
#define HandleToUlong(h)
Definition: basetsd.h:79
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
HICON hIcon
Definition: winuser.h:3197
PCLS FASTCALL IntCreateClass(IN CONST WNDCLASSEXW *lpwcx, IN PUNICODE_STRING ClassName, IN PUNICODE_STRING ClassVersion, IN PUNICODE_STRING MenuName, IN DWORD fnID, IN DWORD dwFlags, IN PDESKTOP Desktop, IN PPROCESSINFO pi)
Definition: class.c:1042
REGISTER_SYSCLASS DefaultServerClasses[]
Definition: class.c:35
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
LPCWSTR lpszMenuName
Definition: winuser.h:3200
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
smooth NULL
Definition: ftsmooth.c:416
Definition: ntuser.h:533
int cbClsExtra
Definition: winuser.h:3194
LPCWSTR lpszClassName
Definition: winuser.h:3201
#define UserHMGetHandle(obj)
Definition: ntuser.h:208
struct _PROCESSINFO * GetW32ProcessInfo(VOID)
Definition: misc.c:773
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
struct _CLS * pclsPublicList
Definition: win32.h:252
HBRUSH hbrBackground
Definition: winuser.h:3199
UINT cbSize
Definition: winuser.h:3191
unsigned long DWORD
Definition: ntddk_ex.h:95
WNDPROC ProcW
Definition: ntuser.h:456
HINSTANCE hInstance
Definition: winuser.h:3196
#define CSF_SERVERSIDEPROC
Definition: ntuser.h:524
HCURSOR hCursor
Definition: winuser.h:3198
UINT style
Definition: winuser.h:3192
WNDPROC lpfnWndProc
Definition: winuser.h:3193
#define ERR(fmt,...)
Definition: debug.h:110
#define OCR_NORMAL
Definition: winuser.h:1132
#define W32PF_CLASSESREGISTERED
Definition: win32.h:17
unsigned int UINT
Definition: ndis.h:50
HANDLE hModuleWin
Definition: main.c:16
HICON hIconSm
Definition: winuser.h:3202
#define ICLASS_TO_MASK(iCls)
Definition: ntuser.h:863
#define SYSTEMCUR(func)
Definition: cursoricon.h:129
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define IS_ATOM(x)
Definition: class.h:3
HINSTANCE hModClient
Definition: ntuser.c:25

Referenced by DesktopThreadMain(), IntGetAndReferenceClass(), NtUserGetClassInfo(), and NtUserRegisterClassExWOW().

◆ UserSetClassLongPtr()

ULONG_PTR UserSetClassLongPtr ( IN PCLS  Class,
IN INT  Index,
IN ULONG_PTR  NewLong,
IN BOOL  Ansi 
)

Definition at line 1858 of file class.c.

1862 {
1863  ULONG_PTR Ret = 0;
1864 
1865  /* NOTE: For GCLP_MENUNAME and GCW_ATOM this function may raise an exception! */
1866 
1867  /* Change the information in the base class first, then update the clones */
1868  Class = Class->pclsBase;
1869 
1870  if (Index >= 0)
1871  {
1872  PULONG_PTR Data;
1873 
1874  TRACE("SetClassLong(%d, %x)\n", Index, NewLong);
1875 
1876  if (((ULONG)Index + sizeof(ULONG_PTR)) < (ULONG)Index ||
1877  ((ULONG)Index + sizeof(ULONG_PTR)) > (ULONG)Class->cbclsExtra)
1878  {
1880  return 0;
1881  }
1882 
1883  Data = (PULONG_PTR)((ULONG_PTR)(Class + 1) + Index);
1884 
1885  /* FIXME: Data might be a unaligned pointer! Might be a problem on
1886  certain architectures, maybe using RtlCopyMemory is a
1887  better choice for those architectures! */
1888  Ret = *Data;
1889  *Data = NewLong;
1890 
1891  /* Update the clones */
1892  Class = Class->pclsClone;
1893  while (Class != NULL)
1894  {
1895  *(PULONG_PTR)((ULONG_PTR)(Class + 1) + Index) = NewLong;
1896  Class = Class->pclsNext;
1897  }
1898 
1899  return Ret;
1900  }
1901 
1902  switch (Index)
1903  {
1904  case GCL_CBWNDEXTRA:
1905  Ret = (ULONG_PTR)Class->cbwndExtra;
1906  Class->cbwndExtra = (INT)NewLong;
1907 
1908  /* Update the clones */
1909  Class = Class->pclsClone;
1910  while (Class != NULL)
1911  {
1912  Class->cbwndExtra = (INT)NewLong;
1913  Class = Class->pclsNext;
1914  }
1915 
1916  break;
1917 
1918  case GCL_CBCLSEXTRA:
1920  break;
1921 
1922  case GCLP_HBRBACKGROUND:
1923  Ret = (ULONG_PTR)Class->hbrBackground;
1924  Class->hbrBackground = (HBRUSH)NewLong;
1925 
1926  /* Update the clones */
1927  Class = Class->pclsClone;
1928  while (Class != NULL)
1929  {
1930  Class->hbrBackground = (HBRUSH)NewLong;
1931  Class = Class->pclsNext;
1932  }
1933  break;
1934 
1935  case GCLP_HCURSOR:
1936  {
1937  PCURICON_OBJECT NewCursor = NULL;
1938 
1939  if (NewLong)
1940  {
1941  NewCursor = UserGetCurIconObject((HCURSOR)NewLong);
1942  if (!NewCursor)
1943  {
1945  return 0;
1946  }
1947  }
1948 
1949  if (Class->spcur)
1950  {
1951  Ret = (ULONG_PTR)UserHMGetHandle(Class->spcur);
1952  UserDereferenceObject(Class->spcur);
1953  }
1954  else
1955  {
1956  Ret = 0;
1957  }
1958 
1959  if (Ret == NewLong)
1960  {
1961  /* It's a nop */
1962  return Ret;
1963  }
1964 
1965  Class->spcur = NewCursor;
1966 
1967  /* Update the clones */
1968  Class = Class->pclsClone;
1969  while (Class != NULL)
1970  {
1971  if (Class->spcur)
1972  UserDereferenceObject(Class->spcur);
1973  if (NewCursor)
1974  UserReferenceObject(NewCursor);
1975  Class->spcur = NewCursor;
1976  Class = Class->pclsNext;
1977  }
1978 
1979  break;
1980  }
1981 
1982  // MSDN:
1983  // hIconSm, A handle to a small icon that is associated with the window class.
1984  // If this member is NULL, the system searches the icon resource specified by
1985  // the hIcon member for an icon of the appropriate size to use as the small icon.
1986  //
1987  case GCLP_HICON:
1988  {
1989  PCURICON_OBJECT NewIcon = NULL;
1990  PCURICON_OBJECT NewSmallIcon = NULL;
1991 
1992  if (NewLong)
1993  {
1994  NewIcon = UserGetCurIconObject((HCURSOR)NewLong);
1995  if (!NewIcon)
1996  {
1998  return 0;
1999  }
2000  }
2001 
2002  if (Class->spicn)
2003  {
2004  Ret = (ULONG_PTR)UserHMGetHandle(Class->spicn);
2005  UserDereferenceObject(Class->spicn);
2006  }
2007  else
2008  {
2009  Ret = 0;
2010  }
2011 
2012  if (Ret == NewLong)
2013  {
2014  /* It's a nop */
2015  return Ret;
2016  }
2017 
2018  if (Ret && (Class->CSF_flags & CSF_CACHEDSMICON))
2019  {
2020  /* We will change the small icon */
2021  UserDereferenceObject(Class->spicnSm);
2022  IntDestroyCurIconObject(Class->spicnSm);
2023  Class->spicnSm = NULL;
2024  Class->CSF_flags &= ~CSF_CACHEDSMICON;
2025  }
2026 
2027  if (NewLong && !Class->spicnSm)
2028  {
2029  /* Create the new small icon from the new large(?) one */
2030  HICON SmallIconHandle = NULL;
2033  {
2034  SmallIconHandle = co_IntCopyImage(
2035  (HICON)NewLong,
2036  IMAGE_ICON,
2040  }
2041  if (!SmallIconHandle)
2042  {
2043  /* Retry without copying from resource */
2044  SmallIconHandle = co_IntCopyImage(
2045  (HICON)NewLong,
2046  IMAGE_ICON,
2049  0);
2050  }
2051  if (SmallIconHandle)
2052  {
2053  /* So use it */
2054  NewSmallIcon = Class->spicnSm = UserGetCurIconObject(SmallIconHandle);
2055  Class->CSF_flags |= CSF_CACHEDSMICON;
2056  }
2057  }
2058 
2059  Class->spicn = NewIcon;
2060 
2061  /* Update the clones */
2062  Class = Class->pclsClone;
2063  while (Class != NULL)
2064  {
2065  if (Class->spicn)
2066  UserDereferenceObject(Class->spicn);
2067  if (NewIcon)
2068  UserReferenceObject(NewIcon);
2069  Class->spicn = NewIcon;
2070  if (NewSmallIcon)
2071  {
2072  if (Class->spicnSm)
2073  UserDereferenceObject(Class->spicnSm);
2074  UserReferenceObject(NewSmallIcon);
2075  Class->spicnSm = NewSmallIcon;
2076  Class->CSF_flags |= CSF_CACHEDSMICON;
2077  }
2078  Class = Class->pclsNext;
2079  }
2080  break;
2081  }
2082 
2083  case GCLP_HICONSM:
2084  {
2085  PCURICON_OBJECT NewSmallIcon = NULL;
2086  BOOLEAN NewIconFromCache = FALSE;
2087 
2088  if (NewLong)
2089  {
2090  NewSmallIcon = UserGetCurIconObject((HCURSOR)NewLong);
2091  if (!NewSmallIcon)
2092  {
2094  return 0;
2095  }
2096  }
2097  else
2098  {
2099  /* Create the new small icon from the large one */
2100  HICON SmallIconHandle = NULL;
2101  if((Class->spicn->CURSORF_flags & (CURSORF_LRSHARED | CURSORF_FROMRESOURCE))
2103  {
2104  SmallIconHandle = co_IntCopyImage(
2105  UserHMGetHandle(Class->spicn),
2106  IMAGE_ICON,
2110  }
2111  if (!SmallIconHandle)
2112  {
2113  /* Retry without copying from resource */
2114  SmallIconHandle = co_IntCopyImage(
2115  UserHMGetHandle(Class->spicn),
2116  IMAGE_ICON,
2119  0);
2120  }
2121  if (SmallIconHandle)
2122  {
2123  /* So use it */
2124  NewSmallIcon = UserGetCurIconObject(SmallIconHandle);
2125  NewIconFromCache = TRUE;
2126  }
2127  else
2128  {
2129  ERR("Failed getting a small icon for the class.\n");
2130  }
2131  }
2132 
2133  if (Class->spicnSm)
2134  {
2135  if (Class->CSF_flags & CSF_CACHEDSMICON)
2136  {
2137  /* We must destroy the icon if we own it */
2138  IntDestroyCurIconObject(Class->spicnSm);
2139  Ret = 0;
2140  }
2141  else
2142  {
2143  Ret = (ULONG_PTR)UserHMGetHandle(Class->spicnSm);
2144  }
2145  UserDereferenceObject(Class->spicnSm);
2146  }
2147  else
2148  {
2149  Ret = 0;
2150  }
2151 
2152  if (NewIconFromCache)
2153  Class->CSF_flags |= CSF_CACHEDSMICON;
2154  else
2155  Class->CSF_flags &= ~CSF_CACHEDSMICON;
2156  Class->spicnSm = NewSmallIcon;
2157 
2158  /* Update the clones */
2159  Class = Class->pclsClone;
2160  while (Class != NULL)
2161  {
2162  if (Class->spicnSm)
2163  UserDereferenceObject(Class->spicnSm);
2164  if (NewSmallIcon)
2165  UserReferenceObject(NewSmallIcon);
2166  if (NewIconFromCache)
2167  Class->CSF_flags |= CSF_CACHEDSMICON;
2168  else
2169  Class->CSF_flags &= ~CSF_CACHEDSMICON;
2170  Class->spicnSm = NewSmallIcon;
2171  Class = Class->pclsNext;
2172  }
2173  }
2174  break;
2175 
2176  case GCLP_HMODULE:
2177  Ret = (ULONG_PTR)Class->hModule;
2178  Class->hModule = (HINSTANCE)NewLong;
2179 
2180  /* Update the clones */
2181  Class = Class->pclsClone;
2182  while (Class != NULL)
2183  {
2184  Class->hModule = (HINSTANCE)NewLong;
2185  Class = Class->pclsNext;
2186  }
2187  break;
2188 
2189  case GCLP_MENUNAME:
2190  {
2192 
2194  Value))
2195  {
2196  ERR("Setting the class menu name failed!\n");
2197  }
2198 
2199  /* FIXME: Really return NULL? Wine does so... */
2200  break;
2201  }
2202 
2203  case GCL_STYLE:
2204  Ret = (ULONG_PTR)Class->style;
2205  Class->style = (UINT)NewLong;
2206 
2207  /* FIXME: What if the CS_GLOBALCLASS style is changed? should we
2208  move the class to the appropriate list? For now, we save
2209  the original value in Class->Global, so we can always
2210  locate the appropriate list */
2211 
2212  /* Update the clones */
2213  Class = Class->pclsClone;
2214  while (Class != NULL)
2215  {
2216  Class->style = (UINT)NewLong;
2217  Class = Class->pclsNext;
2218  }
2219  break;
2220 
2221  case GCLP_WNDPROC:
2223  (WNDPROC)NewLong,
2224  Ansi);
2225  break;
2226 
2227  case GCW_ATOM:
2228  {
2230 
2231  Ret = (ULONG_PTR)Class->atomNVClassName;
2233  Value))
2234  {
2235  Ret = 0;
2236  }
2237  break;
2238  }
2239 
2240  default:
2242  break;
2243  }
2244 
2245  return Ret;
2246 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define ERROR_INVALID_CURSOR_HANDLE
Definition: winerror.h:883
static HICON
Definition: imagelist.c:84
#define IMAGE_ICON
Definition: winuser.h:212
PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon)
Definition: cursoricon.c:200
#define TRUE
Definition: types.h:120
#define CURSORF_FROMRESOURCE
Definition: ntuser.h:1148
#define INT
Definition: polytest.cpp:20
#define GCLP_HCURSOR
Definition: winuser.h:668
static WNDPROC FASTCALL IntSetClassWndProc(IN OUT PCLS Class, IN WNDPROC WndProc, IN BOOL Ansi)
Definition: class.c:543
#define SM_CYSMICON
Definition: winuser.h:1003
BOOL FASTCALL UserDereferenceObject(PVOID Object)
Definition: object.c:610
HICON HCURSOR
Definition: windef.h:299
#define GCLP_WNDPROC
Definition: winuser.h:673
int32_t INT
Definition: typedefs.h:58
#define GCW_ATOM
Definition: winuser.h:656
#define GCLP_MENUNAME
Definition: winuser.h:672
IN UCHAR Value
Definition: halp.h:394
uint32_t ULONG_PTR
Definition: typedefs.h:65
static BOOL IntSetClassAtom(IN OUT PCLS Class, IN PUNICODE_STRING ClassName)
Definition: class.c:445
#define GCLP_HMODULE
Definition: winuser.h:671
#define ERROR_INVALID_ICON_HANDLE
Definition: winerror.h:895
#define GCL_STYLE
Definition: winuser.h:665
#define CSF_CACHEDSMICON
Definition: ntuser.h:530
#define FALSE
Definition: types.h:117
#define CURSORF_LRSHARED
Definition: ntuser.h:1150
#define GCLP_HBRBACKGROUND
Definition: winuser.h:667
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
HANDLE FASTCALL co_IntCopyImage(HANDLE hnd, UINT type, INT desiredx, INT desiredy, UINT flags)
Definition: callback.c:985
LONG NTAPI UserGetSystemMetrics(ULONG Index)
Definition: metric.c:180
#define UserHMGetHandle(obj)
Definition: ntuser.h:208
#define GCLP_HICONSM
Definition: winuser.h:670
#define TRACE(s)
Definition: solgame.cpp:4
if(!(yy_init))
Definition: macro.lex.yy.c:714
#define GCL_CBWNDEXTRA
Definition: winuser.h:658
static const UCHAR Index[8]
Definition: usbohci.c:18
#define GCL_CBCLSEXTRA
Definition: winuser.h:657
#define SM_CXSMICON
Definition: winuser.h:1002
HANDLE HINSTANCE
Definition: typedefs.h:77
#define GCLP_HICON
Definition: winuser.h:669
ULONG CURSORF_flags
Definition: cursoricon.h:16
LRESULT(CALLBACK * WNDPROC)(HWND, UINT, WPARAM, LPARAM)
Definition: winuser.h:2881
#define ERR(fmt,...)
Definition: debug.h:110
#define LR_COPYFROMRESOURCE
Definition: winuser.h:1089
BOOLEAN IntDestroyCurIconObject(_In_ PVOID Object)
Definition: cursoricon.c:313
unsigned int UINT
Definition: ndis.h:50
UNICODE_STRING * PUNICODE_STRING
Definition: env_spec_w32.h:373
#define ERROR_INVALID_INDEX
Definition: winerror.h:894
unsigned int ULONG
Definition: retypes.h:1
#define ULONG_PTR
Definition: config.h:101
uint32_t * PULONG_PTR
Definition: typedefs.h:65
static BOOL IntSetClassMenuName(IN PCLS Class, IN PUNICODE_STRING MenuName)
Definition: class.c:1754
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27
_In_ ULONG_PTR Data
Definition: cdrom.h:947
VOID FASTCALL UserReferenceObject(PVOID obj)
Definition: object.c:697

Referenced by NtUserSetClassLong().

◆ UserUnregisterClass()

BOOL UserUnregisterClass ( IN PUNICODE_STRING  ClassName,
IN HINSTANCE  hInstance,
OUT PCLSMENUNAME  pClassMenuName 
)

Definition at line 1578 of file class.c.

1581 {
1582  PCLS *Link;
1583  PPROCESSINFO pi;
1584  RTL_ATOM ClassAtom;
1585  PCLS Class;
1586 
1587  pi = GetW32ProcessInfo();
1588 
1589  TRACE("UserUnregisterClass(%wZ, 0x%p)\n", ClassName, hInstance);
1590 
1591  /* NOTE: Accessing the buffer in ClassName may raise an exception! */
1592  ClassAtom = IntGetClassAtom(ClassName,
1593  hInstance,
1594  pi,
1595  &Class,
1596  &Link);
1597  if (ClassAtom == (RTL_ATOM)0)
1598  {
1600  TRACE("UserUnregisterClass: No Class found.\n");
1601  return FALSE;
1602  }
1603 
1604  ASSERT(Class != NULL);
1605 
1606  if (Class->cWndReferenceCount != 0 ||
1607  Class->pclsClone != NULL)
1608  {
1609  TRACE("UserUnregisterClass: Class has a Window. Ct %u : Clone 0x%p\n", Class->cWndReferenceCount, Class->pclsClone);
1611  return FALSE;
1612  }
1613 
1614  /* Must be a base class! */
1615  ASSERT(Class->pclsBase == Class);
1616 
1617  /* Unlink the class */
1618  *Link = Class->pclsNext;
1619 
1620  if (NT_SUCCESS(IntDeregisterClassAtom(Class->atomClassName)))
1621  {
1622  TRACE("Class 0x%p\n", Class);
1623  TRACE("UserUnregisterClass: Good Exit!\n");
1624  Class->atomClassName = 0; // Don't let it linger...
1625  /* Finally free the resources */
1627  return TRUE;
1628  }
1629  ERR("UserUnregisterClass: Can not deregister Class Atom.\n");
1630  return FALSE;
1631 }
static const WCHAR Class[]
Definition: cfgmgr.c:39
unsigned short RTL_ATOM
Definition: atom.c:42
#define TRUE
Definition: types.h:120
static VOID IntDestroyClass(IN OUT PCLS Class)
Definition: class.c:228
static int Link(const char **args)
Definition: vfdcmd.c:2414
HINSTANCE hInstance
Definition: charmap.c:20
#define FALSE
Definition: types.h:117
#define ERROR_CLASS_HAS_WINDOWS
Definition: winerror.h:893
smooth NULL
Definition: ftsmooth.c:416
Definition: ntuser.h:533
static NTSTATUS IntDeregisterClassAtom(IN RTL_ATOM Atom)
Definition: class.c:416
struct _PROCESSINFO * GetW32ProcessInfo(VOID)
Definition: misc.c:773
#define TRACE(s)
Definition: solgame.cpp:4
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
static refpint_t pi[]
Definition: server.c:96
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ERR(fmt,...)
Definition: debug.h:110
RTL_ATOM IntGetClassAtom(_In_ PUNICODE_STRING ClassName, IN HINSTANCE hInstance OPTIONAL, IN PPROCESSINFO pi OPTIONAL, OUT PCLS *BaseClass OPTIONAL, OUT PCLS **Link OPTIONAL)
Definition: class.c:1364
#define ERROR_CLASS_DOES_NOT_EXIST
Definition: winerror.h:892
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27

Referenced by NtUserUnregisterClass().

Variable Documentation

◆ ClsId

int ClsId

Definition at line 107 of file class.c.

◆ ControlsList

PWSTR ControlsList[]
static
Initial value:
=
{
L"Button",
L"Edit",
L"Static",
L"ListBox",
L"ScrollBar",
L"ComboBox",
L"MDIClient",
L"ComboLBox",
L"DDEMLEvent",
L"DDEMLMom",
L"DMGClass",
L"DDEMLAnsiClient",
L"DDEMLUnicodeClient",
L"DDEMLAnsiServer",
L"DDEMLUnicodeServer",
L"IME",
L"Ghost",
}
static const WCHAR L[]
Definition: oid.c:1250

Definition at line 12 of file class.c.

Referenced by RegisterControlAtoms().

◆ DefaultServerClasses

REGISTER_SYSCLASS DefaultServerClasses[]

Definition at line 35 of file class.c.

Referenced by UserRegisterSystemClasses().

◆ FnId

int FnId

Definition at line 106 of file class.c.

Referenced by LookupFnIdToiCls().

◆ FnidToiCls

struct { ... } FnidToiCls[]
Initial value:
=
{
{ FNID_MESSAGEWND, ICLS_HWNDMESSAGE},
}
#define FNID_EDIT
Definition: ntuser.h:832
#define ICLS_ICONTITLE
Definition: ntuser.h:894
#define ICLS_MDICLIENT
Definition: ntuser.h:879
#define FNID_COMBOBOX
Definition: ntuser.h:829
#define ICLS_SCROLLBAR
Definition: ntuser.h:877
#define FNID_MENU
Definition: ntuser.h:823
#define ICLS_EDIT
Definition: ntuser.h:874
#define FNID_ICONTITLE
Definition: ntuser.h:822
#define ICLS_DESKTOP
Definition: ntuser.h:890
#define ICLS_DIALOG
Definition: ntuser.h:891
#define FNID_MESSAGEWND
Definition: ntuser.h:826
#define ICLS_LISTBOX
Definition: ntuser.h:876
#define FNID_DESKTOP
Definition: ntuser.h:824
#define FNID_DIALOG
Definition: ntuser.h:831
#define ICLS_GHOST
Definition: ntuser.h:889
#define FNID_MDICLIENT
Definition: ntuser.h:834
#define ICLS_STATIC
Definition: ntuser.h:875
#define ICLS_TOOLTIPS
Definition: ntuser.h:895
#define FNID_SWITCH
Definition: ntuser.h:827
#define ICLS_SWITCH
Definition: ntuser.h:893
#define FNID_TOOLTIPS
Definition: ntuser.h:850
#define ICLS_IME
Definition: ntuser.h:888
#define FNID_COMBOLBOX
Definition: ntuser.h:830
#define FNID_LISTBOX
Definition: ntuser.h:833
#define ICLS_COMBOLBOX
Definition: ntuser.h:880
#define FNID_GHOST
Definition: ntuser.h:837
#define FNID_SCROLLBAR
Definition: ntuser.h:821
#define FNID_BUTTON
Definition: ntuser.h:828
#define ICLS_BUTTON
Definition: ntuser.h:873
#define ICLS_MENU
Definition: ntuser.h:892
#define FNID_STATIC
Definition: ntuser.h:835
#define FNID_IME
Definition: ntuser.h:836
#define ICLS_COMBOBOX
Definition: ntuser.h:878

Referenced by LookupFnIdToiCls().