ReactOS 0.4.16-dev-457-g087979e
class.c File Reference
#include <win32k.h>
#include <unaligned.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)
 
static ULONG_PTR IntGetSetClassLongPtr (PCLS Class, ULONG Index, ULONG_PTR NewValue, ULONG Size)
 
ULONG_PTR UserSetClassLongPtr (IN PCLS Class, IN INT Index, IN ULONG_PTR NewLong, IN BOOL Ansi, IN ULONG Size)
 
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 IntNtUserSetClassLongPtr (HWND hWnd, INT Offset, ULONG_PTR dwNewLong, BOOL Ansi, ULONG Size)
 
ULONG_PTR APIENTRY NtUserSetClassLong (_In_ HWND hWnd, _In_ INT Offset, _In_ ULONG dwNewLong, _In_ 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 1294 of file class.c.

1300{
1301 BOOL Ret = FALSE;
1302
1303 if (ClassName->Length != 0)
1304 {
1305 WCHAR szBuf[65];
1306 PWSTR AtomName = szBuf;
1308
1309 *Atom = 0;
1310
1311 /* NOTE: Caller has to protect the call with SEH! */
1312 if (ClassName->Length + sizeof(UNICODE_NULL) > sizeof(szBuf))
1313 {
1315 ClassName->Length + sizeof(UNICODE_NULL),
1316 TAG_USTR);
1317 if (AtomName == NULL)
1318 {
1320 return FALSE;
1321 }
1322 }
1323
1324 _SEH2_TRY
1325 {
1326 RtlCopyMemory(AtomName,
1327 ClassName->Buffer,
1328 ClassName->Length);
1329 }
1331 {
1332 if (AtomName != szBuf)
1333 ExFreePoolWithTag(AtomName, TAG_USTR);
1335 _SEH2_YIELD(return FALSE);
1336 }
1337 _SEH2_END;
1338 AtomName[ClassName->Length / sizeof(WCHAR)] = UNICODE_NULL;
1339
1340 /* Lookup the atom */
1342
1343 if (AtomName != szBuf)
1344 ExFreePoolWithTag(AtomName, TAG_USTR);
1345
1346 if (NT_SUCCESS(Status))
1347 {
1348 Ret = TRUE;
1349 }
1350 else
1351 {
1353 {
1355 }
1356 }
1357 }
1358 else
1359 {
1360 if (ClassName->Buffer)
1361 {
1362 *Atom = (RTL_ATOM)((ULONG_PTR)ClassName->Buffer);
1363 Ret = TRUE;
1364 }
1365 else
1366 {
1367 *Atom = 0;
1369 Ret = FALSE;
1370 }
1371 }
1372
1373 return Ret;
1374}
LONG NTSTATUS
Definition: precomp.h:26
_Out_ RTL_ATOM * Atom
Definition: class.h:54
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define TAG_USTR
Definition: libsupp.c:997
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PagedPool
Definition: env_spec_w32.h:308
unsigned int BOOL
Definition: ntddk_ex.h:94
Status
Definition: gdiplustypes.h:25
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
unsigned short RTL_ATOM
Definition: atom.c:42
NTSYSAPI NTSTATUS NTAPI RtlLookupAtomInAtomTable(_In_ PRTL_ATOM_TABLE AtomTable, _In_ PWSTR AtomName, _Out_ PRTL_ATOM Atom)
#define UNICODE_NULL
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_END
Definition: pseh2_64.h:155
#define _SEH2_TRY
Definition: pseh2_64.h:55
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
uint16_t * PWSTR
Definition: typedefs.h:56
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
VOID FASTCALL SetLastNtError(_In_ NTSTATUS Status)
Definition: error.c:31
PRTL_ATOM_TABLE gAtomTable
Definition: session.c:13
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:22
#define ERROR_CLASS_DOES_NOT_EXIST
Definition: winerror.h:892
__wchar_t WCHAR
Definition: xmlstorage.h:180

◆ DBG_DEFAULT_CHANNEL()

DBG_DEFAULT_CHANNEL ( UserClass  )

◆ DestroyProcessClasses()

void FASTCALL DestroyProcessClasses ( PPROCESSINFO  Process)

Definition at line 305 of file class.c.

306{
307 PCLS Class;
309
310 if (pi != NULL)
311 {
312 /* Free all local classes */
313 Class = pi->pclsPrivateList;
314 while (Class != NULL)
315 {
316 pi->pclsPrivateList = Class->pclsNext;
317
318 ASSERT(Class->pclsBase == Class);
320
321 Class = pi->pclsPrivateList;
322 }
323
324 /* Free all global classes */
325 Class = pi->pclsPublicList;
326 while (Class != NULL)
327 {
328 pi->pclsPublicList = Class->pclsNext;
329
330 ASSERT(Class->pclsBase == Class);
332
333 Class = pi->pclsPublicList;
334 }
335 }
336}
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
#define ASSERT(a)
Definition: mode.c:44
static refpint_t pi[]
Definition: server.c:96
struct _PROCESSINFO * PPROCESSINFO
Definition: ntwin32.h:5
Definition: ntuser.h:566
static VOID IntDestroyClass(IN OUT PCLS Class)
Definition: class.c:233

Referenced by ExitThreadCallback().

◆ IntCheckDesktopClasses()

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

Definition at line 948 of file class.c.

952{
953 PCLS Class, NextClass, *Link;
954
955 /* NOTE: We only need to check base classes! When classes are no longer needed
956 on a desktop, the clones will be freed automatically as soon as possible.
957 However, we need to move base classes to the shared heap, as soon as
958 the last desktop heap where a class is allocated on is about to be destroyed.
959 If we didn't move the class to the shared heap, the class would become
960 inaccessible! */
961
962 ASSERT(Desktop != NULL);
963
964 Link = ClassList;
965 Class = *Link;
966 while (Class != NULL)
967 {
968 NextClass = Class->pclsNext;
969
970 ASSERT(Class->pclsBase == Class);
971
972 if (Class->rpdeskParent == Desktop &&
973 Class->cWndReferenceCount == 0)
974 {
975 /* There shouldn't be any clones around anymore! */
976 ASSERT(Class->pclsClone == NULL);
977
978 /* FIXME: If process is terminating, don't move the class but rather destroy it! */
979 /* FIXME: We could move the class to another desktop heap if there's still desktops
980 mapped into the process... */
981
982 /* Move the class to the shared heap */
984 &Link))
985 {
986 ASSERT(*Link == NextClass);
987 }
988 else
989 {
990 ASSERT(NextClass == Class->pclsNext);
991
992 if (FreeOnFailure)
993 {
994 /* Unlink the base class */
996 Class->pclsNext);
997
998 /* We can free the old base class now */
999 Class->pclsBase = NULL;
1001 }
1002 else
1003 {
1004 Link = &Class->pclsNext;
1005 *Ret = FALSE;
1006 }
1007 }
1008 }
1009 else
1010 Link = &Class->pclsNext;
1011
1012 Class = NextClass;
1013 }
1014}
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
static int Link(const char **args)
Definition: vfdcmd.c:2414
static BOOL IntMoveClassToSharedHeap(IN OUT PCLS Class, IN OUT PCLS **ClassLinkPtr)
Definition: class.c:902

Referenced by IntCheckProcessDesktopClasses().

◆ IntCheckProcessDesktopClasses()

BOOL IntCheckProcessDesktopClasses ( IN PDESKTOP  Desktop,
IN BOOL  FreeOnFailure 
)

Definition at line 1017 of file class.c.

1019{
1021 BOOL Ret = TRUE;
1022
1024
1025 /* Check all local classes */
1027 &pi->pclsPrivateList,
1028 FreeOnFailure,
1029 &Ret);
1030
1031 /* Check all global classes */
1033 &pi->pclsPublicList,
1034 FreeOnFailure,
1035 &Ret);
1036 if (!Ret)
1037 {
1038 ERR("Failed to move process classes from desktop 0x%p to the shared heap!\n", Desktop);
1040 }
1041
1042 return Ret;
1043}
#define ERR(fmt,...)
Definition: precomp.h:57
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
struct _PROCESSINFO * GetW32ProcessInfo(VOID)
Definition: misc.c:801
static VOID IntCheckDesktopClasses(IN PDESKTOP Desktop, IN OUT PCLS *ClassList, IN BOOL FreeOnFailure, OUT BOOL *Ret)
Definition: class.c:948

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 1047 of file class.c.

1055{
1056 SIZE_T ClassSize;
1057 PCLS Class = NULL;
1058 RTL_ATOM Atom, verAtom;
1060 PWSTR pszMenuName = NULL;
1062
1063 TRACE("lpwcx=%p ClassName=%wZ MenuName=%wZ dwFlags=%08x Desktop=%p pi=%p\n",
1064 lpwcx, ClassName, MenuName, dwFlags, Desktop, pi);
1065
1066 if (!IntRegisterClassAtom(ClassName,
1067 &Atom))
1068 {
1069 ERR("Failed to register class atom!\n");
1070 return NULL;
1071 }
1072
1073 if (!IntRegisterClassAtom(ClassVersion,
1074 &verAtom))
1075 {
1076 ERR("Failed to register version class atom!\n");
1078 return NULL;
1079 }
1080
1081 ClassSize = sizeof(*Class) + lpwcx->cbClsExtra;
1082 if (MenuName->Length != 0)
1083 {
1084 pszMenuName = UserHeapAlloc(MenuName->Length + sizeof(UNICODE_NULL) +
1085 RtlUnicodeStringToAnsiSize(MenuName));
1086 if (pszMenuName == NULL)
1087 goto NoMem;
1088 }
1089
1090 if (Desktop != NULL)
1091 {
1093 ClassSize);
1094 }
1095 else
1096 {
1097 /* FIXME: The class was created before being connected
1098 to a desktop. It is possible for the desktop window,
1099 but should it be allowed for any other case? */
1100 TRACE("This CLASS has no Desktop to heap from! Atom %u\n",Atom);
1101 Class = UserHeapAlloc(ClassSize);
1102 }
1103
1104 if (Class != NULL)
1105 {
1106 int iCls = 0;
1107
1108 RtlZeroMemory(Class, ClassSize);
1109
1110 Class->rpdeskParent = Desktop;
1111 Class->pclsBase = Class;
1112 Class->atomClassName = verAtom;
1113 Class->atomNVClassName = Atom;
1114 Class->fnid = fnID;
1115 Class->CSF_flags = dwFlags;
1116
1117 if (LookupFnIdToiCls(Class->fnid, &iCls) && gpsi->atomSysClass[iCls] == 0)
1118 {
1119 gpsi->atomSysClass[iCls] = Class->atomClassName;
1120 }
1121
1122 _SEH2_TRY
1123 {
1124 PWSTR pszMenuNameBuffer = pszMenuName;
1125
1126 /* Need to protect with SEH since accessing the WNDCLASSEX structure
1127 and string buffers might raise an exception! We don't want to
1128 leak memory... */
1129 // What?! If the user interface was written correctly this would not be an issue!
1130 Class->lpfnWndProc = lpwcx->lpfnWndProc;
1131 Class->style = lpwcx->style;
1132 Class->cbclsExtra = lpwcx->cbClsExtra;
1133 Class->cbwndExtra = lpwcx->cbWndExtra;
1134 Class->hModule = lpwcx->hInstance;
1135 Class->spicn = lpwcx->hIcon ? UserGetCurIconObject(lpwcx->hIcon) : NULL;
1136 Class->spcur = lpwcx->hCursor ? UserGetCurIconObject(lpwcx->hCursor) : NULL;
1137 Class->spicnSm = lpwcx->hIconSm ? UserGetCurIconObject(lpwcx->hIconSm) : NULL;
1139 Class->hbrBackground = lpwcx->hbrBackground;
1140
1141 /* Make a copy of the string */
1142 if (pszMenuNameBuffer != NULL)
1143 {
1144 Class->MenuNameIsString = TRUE;
1145
1146 Class->lpszClientUnicodeMenuName = pszMenuNameBuffer;
1147 RtlCopyMemory(Class->lpszClientUnicodeMenuName,
1148 MenuName->Buffer,
1149 MenuName->Length);
1150 Class->lpszClientUnicodeMenuName[MenuName->Length / sizeof(WCHAR)] = UNICODE_NULL;
1151
1152 pszMenuNameBuffer += (MenuName->Length / sizeof(WCHAR)) + 1;
1153 }
1154 else
1155 Class->lpszClientUnicodeMenuName = MenuName->Buffer;
1156
1157 /* Save an ANSI copy of the string */
1158 if (pszMenuNameBuffer != NULL)
1159 {
1161
1162 Class->lpszClientAnsiMenuName = (PSTR)pszMenuNameBuffer;
1163 AnsiString.MaximumLength = (USHORT)RtlUnicodeStringToAnsiSize(MenuName);
1164 AnsiString.Buffer = Class->lpszClientAnsiMenuName;
1166 MenuName,
1167 FALSE);
1168 if (!NT_SUCCESS(Status))
1169 {
1170 ERR("Failed to convert unicode menu name to ansi!\n");
1171
1172 /* Life would've been much prettier if ntoskrnl exported RtlRaiseStatus()... */
1174 }
1175 }
1176 else
1177 Class->lpszClientAnsiMenuName = (PSTR)MenuName->Buffer;
1178
1179 /* Save kernel use menu name and ansi class name */
1180 Class->lpszMenuName = Class->lpszClientUnicodeMenuName; // FIXME!
1181 //Class->lpszAnsiClassName = FIXME
1182
1183 /* Server Side overrides class calling type (A/W)!
1184 User32 whine test_builtinproc: "deftest"
1185 built-in winproc - window A/W type automatically detected */
1186 if (!(Class->CSF_flags & CSF_SERVERSIDEPROC))
1187 {
1188 int i;
1189 WndProc = NULL;
1190 /* Due to the wine class "deftest" and most likely no FNID to reference
1191 from, sort through the Server Side list and compare proc addresses
1192 for match. This method will be used in related code.
1193 */
1194 for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
1195 { // Open ANSI or Unicode, just match, set and break.
1196 if (GETPFNCLIENTW(i) == Class->lpfnWndProc)
1197 {
1199 break;
1200 }
1201 if (GETPFNCLIENTA(i) == Class->lpfnWndProc)
1202 {
1204 break;
1205 }
1206 }
1207 if (WndProc)
1208 { // If a hit, we are Server Side so set the right flags and proc.
1209 Class->CSF_flags |= CSF_SERVERSIDEPROC;
1210 Class->CSF_flags &= ~CSF_ANSIPROC;
1211 Class->lpfnWndProc = WndProc;
1212 }
1213 }
1214
1215 if (!(Class->CSF_flags & CSF_ANSIPROC))
1216 Class->Unicode = TRUE;
1217
1218 if (Class->style & CS_GLOBALCLASS)
1219 Class->Global = TRUE;
1220 }
1222 {
1224 }
1225 _SEH2_END;
1226
1227 if (!NT_SUCCESS(Status))
1228 {
1229 ERR("Failed creating the class: 0x%x\n", Status);
1230
1232
1233 if (pszMenuName != NULL)
1234 UserHeapFree(pszMenuName);
1235
1237 Class);
1238 Class = NULL;
1239
1240 IntDeregisterClassAtom(verAtom);
1242 }
1243 }
1244 else
1245 {
1246NoMem:
1247 ERR("Failed to allocate class on Desktop 0x%p\n", Desktop);
1248
1249 if (pszMenuName != NULL)
1250 UserHeapFree(pszMenuName);
1251
1253 IntDeregisterClassAtom(verAtom);
1254
1256 }
1257
1258 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",
1259 Class, ClassName, Class ? Class->lpfnWndProc : NULL, Atom, verAtom,
1260 Class ? Class->hModule : NULL , Class ? Class->Global : 0);
1261
1262 return Class;
1263}
PSERVERINFO gpsi
Definition: imm.c:18
@ AnsiString
Definition: dnslib.h:19
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 FNID_SWITCH
Definition: ntuser.h:865
#define GETPFNCLIENTW(fnid)
Definition: ntuser.h:906
#define GETPFNCLIENTA(fnid)
Definition: ntuser.h:904
#define CSF_ANSIPROC
Definition: ntuser.h:557
#define FNID_FIRST
Definition: ntuser.h:858
#define GETPFNSERVER(fnid)
Definition: ntuser.h:909
#define CSF_SERVERSIDEPROC
Definition: ntuser.h:556
if(dx< 0)
Definition: linetemp.h:194
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToAnsiString(PANSI_STRING DestinationString, PUNICODE_STRING SourceString, BOOLEAN AllocateDestinationString)
unsigned short USHORT
Definition: pedump.c:61
#define _SEH2_LEAVE
Definition: pseh2_64.h:167
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE(s)
Definition: solgame.cpp:4
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
Definition: solitaire.cpp:614
ATOM atomSysClass[ICLS_NOTUSED+1]
Definition: ntuser.h:1060
char * PSTR
Definition: typedefs.h:51
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
static __inline PVOID UserHeapAlloc(SIZE_T Bytes)
Definition: usrheap.h:34
static __inline BOOL UserHeapFree(PVOID lpMem)
Definition: usrheap.h:44
static BOOL IntRegisterClassAtom(IN PUNICODE_STRING ClassName, OUT RTL_ATOM *pAtom)
Definition: class.c:339
static NTSTATUS IntDeregisterClassAtom(IN RTL_ATOM Atom)
Definition: class.c:421
BOOL FASTCALL LookupFnIdToiCls(int FnId, int *iCls)
Definition: class.c:133
PCURICON_OBJECT FASTCALL UserGetCurIconObject(HCURSOR hCurIcon)
Definition: cursoricon.c:200
static __inline PVOID DesktopHeapAlloc(IN PDESKTOP Desktop, IN SIZE_T Bytes)
Definition: desktop.h:204
static __inline BOOL DesktopHeapFree(IN PDESKTOP Desktop, IN PVOID lpMem)
Definition: desktop.h:215
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
#define CS_GLOBALCLASS
Definition: winuser.h:652
LRESULT(CALLBACK * WNDPROC)(HWND, UINT, WPARAM, LPARAM)
Definition: winuser.h:2909
#define RtlUnicodeStringToAnsiSize(String)
Definition: rtlfuncs.h:1022

Referenced by UserRegisterClass(), and UserRegisterSystemClasses().

◆ IntDereferenceClass()

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

Definition at line 820 of file class.c.

823{
824 PCLS *PrevLink, BaseClass, CurrentClass;
825
826 ASSERT(Class->cWndReferenceCount >= 1);
827
828 BaseClass = Class->pclsBase;
829
830 if (--Class->cWndReferenceCount == 0)
831 {
832 if (BaseClass == Class)
833 {
834 ASSERT(Class->pclsBase == Class);
835
836 TRACE("IntDereferenceClass 0x%p\n", Class);
837 /* Check if there are clones of the class on other desktops,
838 link the first clone in if possible. If there are no clones
839 then leave the class on the desktop heap. It will get moved
840 to the shared heap when the thread detaches. */
841 if (BaseClass->pclsClone != NULL)
842 {
843 if (BaseClass->Global)
844 PrevLink = &pi->pclsPublicList;
845 else
846 PrevLink = &pi->pclsPrivateList;
847
848 CurrentClass = *PrevLink;
849 while (CurrentClass != BaseClass)
850 {
851 ASSERT(CurrentClass != NULL);
852
853 PrevLink = &CurrentClass->pclsNext;
854 CurrentClass = CurrentClass->pclsNext;
855 }
856
857 ASSERT(*PrevLink == BaseClass);
858
859 /* Make the first clone become the new base class */
861 PrevLink,
862 &BaseClass->pclsClone);
863
864 /* Destroy the class, there's still another clone of the class
865 that now serves as a base class. Make sure we don't destruct
866 resources shared by all classes (Base = NULL)! */
867 BaseClass->pclsBase = NULL;
868 BaseClass->pclsClone = NULL;
869 IntDestroyClass(BaseClass);
870 }
871 }
872 else
873 {
874 TRACE("IntDereferenceClass1 0x%p\n", Class);
875
876 /* Locate the cloned class and unlink it */
877 PrevLink = &BaseClass->pclsClone;
878 CurrentClass = BaseClass->pclsClone;
879 while (CurrentClass != Class)
880 {
881 ASSERT(CurrentClass != NULL);
882
883 PrevLink = &CurrentClass->pclsNext;
884 CurrentClass = CurrentClass->pclsNext;
885 }
886
887 ASSERT(CurrentClass == Class);
888
890 Class->pclsNext);
891
892 ASSERT(Class->pclsBase == BaseClass);
893 ASSERT(Class->pclsClone == NULL);
894
895 /* The class was just a clone, we don't need it anymore */
897 }
898 }
899}
struct _CLS * pclsBase
Definition: ntuser.h:577
UINT Global
Definition: ntuser.h:593
struct _CLS * pclsClone
Definition: ntuser.h:578
struct _CLS * pclsNext
Definition: ntuser.h:567
static VOID IntMakeCloneBaseClass(IN OUT PCLS Class, IN OUT PCLS *BaseClassLink, IN OUT PCLS *CloneLink)
Definition: class.c:782

Referenced by co_UserCreateWindowEx(), and co_UserFreeWindow().

◆ IntDeregisterClassAtom()

static NTSTATUS IntDeregisterClassAtom ( IN RTL_ATOM  Atom)
static

Definition at line 421 of file class.c.

422{
424 Atom);
425}
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 233 of file class.c.

234{
235 PDESKTOP pDesk;
236
237 /* There shouldn't be any clones anymore */
238 ASSERT(Class->cWndReferenceCount == 0);
239 ASSERT(Class->pclsClone == NULL);
240
241 if (Class->pclsBase == Class)
242 {
243 PCALLPROCDATA CallProc, NextCallProc;
244
245 /* Destroy allocated callproc handles */
246 CallProc = Class->spcpdFirst;
247 while (CallProc != NULL)
248 {
249 NextCallProc = CallProc->spcpdNext;
250
251 CallProc->spcpdNext = NULL;
252 DestroyCallProc(CallProc);
253
254 CallProc = NextCallProc;
255 }
256
257 // Fixes running the static test then run class test issue.
258 // Some applications do not use UnregisterClass before exiting.
259 // Keep from reusing the same atom with case insensitive
260 // comparisons, remove registration of the atom if not zeroed.
261 if (Class->atomClassName)
262 IntDeregisterClassAtom(Class->atomClassName);
263 // Dereference non-versioned class name
264 if (Class->atomNVClassName)
265 IntDeregisterClassAtom(Class->atomNVClassName);
266
267 if (Class->pdce)
268 {
269 DceFreeClassDCE(Class->pdce);
270 Class->pdce = NULL;
271 }
272
274 }
275
276 if (Class->spicn)
278 if (Class->spcur)
280 if (Class->spicnSm)
281 {
283 /* Destroy the icon if we own it */
284 if ((Class->CSF_flags & CSF_CACHEDSMICON)
287 }
288
289 pDesk = Class->rpdeskParent;
290 Class->rpdeskParent = NULL;
291
292 /* Free the structure */
293 if (pDesk != NULL)
294 {
295 DesktopHeapFree(pDesk, Class);
296 }
297 else
298 {
300 }
301}
BOOLEAN DestroyCallProc(_Inout_ PVOID Object)
Definition: callproc.c:22
void FASTCALL DceFreeClassDCE(PDCE)
Definition: windc.c:762
#define UserHMGetHandle(obj)
Definition: ntuser.h:230
#define CSF_CACHEDSMICON
Definition: ntuser.h:562
struct _CALLPROCDATA * spcpdNext
Definition: ntuser.h:551
static VOID IntFreeClassMenuName(IN OUT PCLS Class)
Definition: class.c:221
BOOLEAN IntDestroyCurIconObject(_In_ PVOID Object)
Definition: cursoricon.c:317
BOOL FASTCALL UserDereferenceObject(PVOID Object)
Definition: object.c:644
BOOL FASTCALL UserObjectInDestroy(HANDLE h)
Definition: object.c:703

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 1266 of file class.c.

1270{
1271 PCLS Class, *PrevLink = ClassList;
1272
1273 Class = *PrevLink;
1274 while (Class != NULL)
1275 {
1276 if (Class->atomClassName == Atom &&
1277 (hInstance == NULL || Class->hModule == hInstance) &&
1278 !(Class->CSF_flags & CSF_WOWDEFERDESTROY))
1279 {
1280 ASSERT(Class->pclsBase == Class);
1281
1282 if (Link != NULL)
1283 *Link = PrevLink;
1284 break;
1285 }
1286
1287 PrevLink = &Class->pclsNext;
1288 Class = Class->pclsNext;
1289 }
1290
1291 return Class;
1292}
HINSTANCE hInstance
Definition: charmap.c:19
#define CSF_WOWDEFERDESTROY
Definition: ntuser.h:558

Referenced by IntGetClassAtom(), and UserRegisterClass().

◆ IntFreeClassMenuName()

static VOID IntFreeClassMenuName ( IN OUT PCLS  Class)
static

Definition at line 221 of file class.c.

222{
223 /* Free the menu name, if it was changed and allocated */
224 if (Class->lpszClientUnicodeMenuName != NULL && Class->MenuNameIsString)
225 {
226 UserHeapFree(Class->lpszClientUnicodeMenuName);
227 Class->lpszClientUnicodeMenuName = NULL;
228 Class->lpszClientAnsiMenuName = NULL;
229 }
230}

Referenced by IntDestroyClass(), and IntSetClassMenuName().

◆ IntGetAndReferenceClass()

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

Definition at line 1450 of file class.c.

1451{
1452 PCLS *ClassLink, Class = NULL;
1453 RTL_ATOM ClassAtom;
1454 PTHREADINFO pti;
1455
1456 if (bDesktopThread)
1457 pti = gptiDesktopThread;
1458 else
1460
1461 if ( !(pti->ppi->W32PF_flags & W32PF_CLASSESREGISTERED ))
1462 {
1464 }
1465
1466 /* Check the class. */
1467
1468 TRACE("Finding Class %wZ for hInstance 0x%p\n", ClassName, hInstance);
1469
1470 ClassAtom = IntGetClassAtom(ClassName,
1471 hInstance,
1472 pti->ppi,
1473 &Class,
1474 &ClassLink);
1475
1476 if (ClassAtom == (RTL_ATOM)0)
1477 {
1478 if (IS_ATOM(ClassName->Buffer))
1479 {
1480 ERR("Class 0x%p not found\n", ClassName->Buffer);
1481 }
1482 else
1483 {
1484 ERR("Class \"%wZ\" not found\n", ClassName);
1485 }
1486
1487 return NULL;
1488 }
1489
1490 TRACE("Referencing Class 0x%p with atom 0x%x\n", Class, ClassAtom);
1492 ClassLink,
1493 pti->rpdesk);
1494 if (Class == NULL)
1495 {
1496 ERR("Failed to reference window class!\n");
1497 return NULL;
1498 }
1499
1500 return Class;
1501}
#define IS_ATOM(x)
Definition: class.h:3
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
PPROCESSINFO ppi
Definition: win32.h:88
struct _DESKTOP * rpdesk
Definition: win32.h:92
#define W32PF_CLASSESREGISTERED
Definition: win32.h:17
PCLS IntReferenceClass(IN OUT PCLS BaseClass, IN OUT PCLS *ClassLink, IN PDESKTOP Desktop)
Definition: class.c:754
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:1377
BOOL FASTCALL UserRegisterSystemClasses(VOID)
Definition: class.c:2337
PTHREADINFO gptiDesktopThread
Definition: desktop.c:54

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 1377 of file class.c.

1383{
1384 RTL_ATOM Atom = (RTL_ATOM)0;
1385
1386 ASSERT(BaseClass != NULL);
1387
1388 if (IntGetAtomFromStringOrAtom(ClassName, &Atom) &&
1389 Atom != (RTL_ATOM)0)
1390 {
1391 PCLS Class;
1392
1393 /* Attempt to locate the class object */
1394
1395 ASSERT(pi != NULL);
1396
1397 /* Step 1: Try to find an exact match of locally registered classes */
1399 hInstance,
1400 &pi->pclsPrivateList,
1401 Link);
1402 if (Class != NULL)
1403 { TRACE("Step 1: 0x%p\n",Class );
1404 goto FoundClass;
1405 }
1406
1407 /* Step 2: Try to find any globally registered class. The hInstance
1408 is not relevant for global classes */
1410 NULL,
1411 &pi->pclsPublicList,
1412 Link);
1413 if (Class != NULL)
1414 { TRACE("Step 2: 0x%p 0x%p\n",Class, Class->hModule);
1415 goto FoundClass;
1416 }
1417
1418 /* Step 3: Try to find any local class registered by user32 */
1420 hModClient,
1421 &pi->pclsPrivateList,
1422 Link);
1423 if (Class != NULL)
1424 { TRACE("Step 3: 0x%p\n",Class );
1425 goto FoundClass;
1426 }
1427
1428 /* Step 4: Try to find any global class registered by user32 */
1430 hModClient,
1431 &pi->pclsPublicList,
1432 Link);
1433 if (Class == NULL)
1434 {
1435 return (RTL_ATOM)0;
1436 }else{TRACE("Step 4: 0x%p\n",Class );}
1437
1438FoundClass:
1439 *BaseClass = Class;
1440 }
1441 else
1442 {
1443 Atom = 0;
1444 }
1445
1446 return Atom;
1447}
HINSTANCE hModClient
Definition: ntuser.c:25
static PCLS IntFindClass(IN RTL_ATOM Atom, IN HINSTANCE hInstance, IN PCLS *ClassList, OUT PCLS **Link OPTIONAL)
Definition: class.c:1266

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 630 of file class.c.

633{
634 SIZE_T ClassSize;
635 PCLS Class;
636
637 ASSERT(Desktop != NULL);
638 ASSERT(BaseClass->pclsBase == BaseClass);
639
640 if (BaseClass->rpdeskParent == Desktop)
641 {
642 /* It is most likely that a window is created on the same
643 desktop as the window class. */
644
645 return BaseClass;
646 }
647
648 if (BaseClass->rpdeskParent == NULL)
649 {
650 ASSERT(BaseClass->cWndReferenceCount == 0);
651 ASSERT(BaseClass->pclsClone == NULL);
652
653 /* Classes are also located in the shared heap when the class
654 was created before the thread attached to a desktop. As soon
655 as a window is created for such a class located on the shared
656 heap, the class is cloned into the desktop heap on which the
657 window is created. */
658 Class = NULL;
659 }
660 else
661 {
662 /* The user is asking for a class object on a different desktop,
663 try to find one! */
664 Class = BaseClass->pclsClone;
665 while (Class != NULL)
666 {
667 if (Class->rpdeskParent == Desktop)
668 {
669 ASSERT(Class->pclsBase == BaseClass);
670 ASSERT(Class->pclsClone == NULL);
671 break;
672 }
673
674 Class = Class->pclsNext;
675 }
676 }
677
678 if (Class == NULL)
679 {
680 /* The window is created on a different desktop, we need to
681 clone the class object to the desktop heap of the window! */
682 ClassSize = sizeof(*BaseClass) + (SIZE_T)BaseClass->cbclsExtra;
683
685 ClassSize);
686
687 if (Class != NULL)
688 {
689 /* Simply clone the class */
690 RtlCopyMemory( Class, BaseClass, ClassSize);
691
692 /* Reference our objects */
693 if (Class->spcur)
695 if (Class->spicn)
697 if (Class->spicnSm)
698 UserReferenceObject(Class->spicnSm);
699
700 TRACE("Clone Class 0x%p hM 0x%p\n %S\n",Class, Class->hModule, Class->lpszClientUnicodeMenuName);
701
702 /* Restore module address if default user class Ref: Bug 4778 */
703 if ( Class->hModule != hModClient &&
704 Class->fnid <= FNID_GHOST &&
705 Class->fnid >= FNID_BUTTON )
706 {
707 Class->hModule = hModClient;
708 TRACE("Clone Class 0x%p Reset hM 0x%p\n",Class, Class->hModule);
709 }
710
711 /* Update some pointers and link the class */
712 Class->rpdeskParent = Desktop;
713 Class->cWndReferenceCount = 0;
714
715 if (BaseClass->rpdeskParent == NULL)
716 {
717 /* We don't really need the base class on the shared
718 heap anymore, delete it so the only class left is
719 the clone we just created, which now serves as the
720 new base class */
721 ASSERT(BaseClass->pclsClone == NULL);
722 ASSERT(Class->pclsClone == NULL);
723 Class->pclsBase = Class;
724 Class->pclsNext = BaseClass->pclsNext;
725
726 /* Replace the base class */
728 Class);
729
730 /* Destroy the obsolete copy on the shared heap */
731 BaseClass->pclsBase = NULL;
732 BaseClass->pclsClone = NULL;
733 IntDestroyClass(BaseClass);
734 }
735 else
736 {
737 /* Link in the clone */
738 Class->pclsClone = NULL;
739 Class->pclsBase = BaseClass;
740 Class->pclsNext = BaseClass->pclsClone;
741 (void)InterlockedExchangePointer((PVOID*)&BaseClass->pclsClone,
742 Class);
743 }
744 }
745 else
746 {
748 }
749 }
750 return Class;
751}
#define FNID_BUTTON
Definition: ntuser.h:866
#define FNID_GHOST
Definition: ntuser.h:875
VOID FASTCALL UserReferenceObject(PVOID obj)
Definition: object.c:731

Referenced by IntReferenceClass().

◆ IntGetClassWndProc()

WNDPROC FASTCALL IntGetClassWndProc ( PCLS  Class,
BOOL  Ansi 
)

Definition at line 499 of file class.c.

500{
501 INT i;
502 WNDPROC gcpd = NULL, Ret = NULL;
503
504 if (Class->CSF_flags & CSF_SERVERSIDEPROC)
505 {
506 for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
507 {
508 if (GETPFNSERVER(i) == Class->lpfnWndProc)
509 {
510 if (Ansi)
511 Ret = GETPFNCLIENTA(i);
512 else
513 Ret = GETPFNCLIENTW(i);
514 }
515 }
516 return Ret;
517 }
518 Ret = Class->lpfnWndProc;
519
520 if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON)
521 {
522 if (Ansi)
523 {
524 if (GETPFNCLIENTW(Class->fnid) == Class->lpfnWndProc)
525 Ret = GETPFNCLIENTA(Class->fnid);
526 }
527 else
528 {
529 if (GETPFNCLIENTA(Class->fnid) == Class->lpfnWndProc)
530 Ret = GETPFNCLIENTW(Class->fnid);
531 }
532 }
533
534 if ( Ret != Class->lpfnWndProc ||
535 Ansi == !!(Class->CSF_flags & CSF_ANSIPROC) )
536 return Ret;
537
538 gcpd = (WNDPROC)UserGetCPD( Class,
540 (ULONG_PTR)Ret);
541
542 return (gcpd ? gcpd : Ret);
543}
ULONG_PTR FASTCALL UserGetCPD(PVOID pvClsWnd, GETCPD Flags, ULONG_PTR ProcIn)
Definition: callproc.c:107
#define ULONG_PTR
Definition: config.h:101
@ UserGetCPDClass
Definition: ntuser.h:542
@ UserGetCPDU2A
Definition: ntuser.h:541
@ UserGetCPDA2U
Definition: ntuser.h:540
int32_t INT
Definition: typedefs.h:58

Referenced by IntSetClassWndProc(), and UserGetClassInfo().

◆ IntGetSetClassLongPtr()

static ULONG_PTR IntGetSetClassLongPtr ( PCLS  Class,
ULONG  Index,
ULONG_PTR  NewValue,
ULONG  Size 
)
inlinestatic

Definition at line 1872 of file class.c.

1873{
1874 PVOID Address = (PUCHAR)(&Class[1]) + Index;
1875 ULONG_PTR OldValue;
1876
1877#ifdef _WIN64
1878 if (Size == sizeof(LONG))
1879 {
1880 /* Values might be unaligned */
1881 OldValue = ReadUnalignedU32(Address);
1882 WriteUnalignedU32(Address, NewValue);
1883 }
1884 else
1885#endif
1886 {
1887 /* Values might be unaligned */
1888 OldValue = ReadUnalignedUlongPtr(Address);
1890 }
1891
1892 return OldValue;
1893}
long LONG
Definition: pedump.c:60
static WCHAR Address[46]
Definition: ping.c:68
unsigned char * PUCHAR
Definition: typedefs.h:53
#define WriteUnalignedUlongPtr
Definition: unaligned.h:142
__forceinline unsigned long ReadUnalignedU32(const unsigned long *p)
Definition: unaligned.h:76
#define ReadUnalignedUlongPtr
Definition: unaligned.h:141
__forceinline void WriteUnalignedU32(unsigned long *p, unsigned long val)
Definition: unaligned.h:111
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533

Referenced by UserSetClassLongPtr().

◆ IntMakeCloneBaseClass()

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

Definition at line 782 of file class.c.

785{
786 PCLS Clone;
787
788 ASSERT(Class->pclsBase != Class);
789 ASSERT(Class->pclsBase->pclsClone != NULL);
790 ASSERT(Class->rpdeskParent != NULL);
791 ASSERT(Class->cWndReferenceCount != 0);
792 ASSERT(Class->pclsBase->rpdeskParent != NULL);
793 ASSERT(Class->pclsBase->cWndReferenceCount == 0);
794
795 /* Unlink the clone */
796 *CloneLink = Class->pclsNext;
797 Class->pclsClone = Class->pclsBase->pclsClone;
798
799 /* Update the class information to make it a base class */
800 Class->pclsBase = Class;
801 Class->pclsNext = (*BaseClassLink)->pclsNext;
802
803 /* Update all clones */
804 Clone = Class->pclsClone;
805 while (Clone != NULL)
806 {
807 ASSERT(Clone->pclsClone == NULL);
808 Clone->pclsBase = Class;
809
810 Clone = Clone->pclsNext;
811 }
812
813 /* Link in the new base class */
814 (void)InterlockedExchangePointer((PVOID*)BaseClassLink,
815 Class);
816}

Referenced by IntDereferenceClass().

◆ IntMoveClassToSharedHeap()

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

Definition at line 902 of file class.c.

904{
905 PCLS NewClass;
906 SIZE_T ClassSize;
907
908 ASSERT(Class->pclsBase == Class);
909 ASSERT(Class->rpdeskParent != NULL);
910 ASSERT(Class->cWndReferenceCount == 0);
911 ASSERT(Class->pclsClone == NULL);
912
913 ClassSize = sizeof(*Class) + (SIZE_T)Class->cbclsExtra;
914
915 /* Allocate the new base class on the shared heap */
916 NewClass = UserHeapAlloc(ClassSize);
917 if (NewClass != NULL)
918 {
919 RtlCopyMemory(NewClass,
920 Class,
921 ClassSize);
922
923 NewClass->rpdeskParent = NULL;
924 NewClass->pclsBase = NewClass;
925
926 if (NewClass->spcur)
927 UserReferenceObject(NewClass->spcur);
928 if (NewClass->spicn)
929 UserReferenceObject(NewClass->spicn);
930 if (NewClass->spicnSm)
931 UserReferenceObject(NewClass->spicnSm);
932
933 /* Replace the class in the list */
934 (void)InterlockedExchangePointer((PVOID*)*ClassLinkPtr,
935 NewClass);
936 *ClassLinkPtr = &NewClass->pclsNext;
937
938 /* Free the obsolete class on the desktop heap */
939 Class->pclsBase = NULL;
941 return TRUE;
942 }
943
944 return FALSE;
945}
struct _CURICON_OBJECT * spcur
Definition: ntuser.h:586
struct _DESKTOP * rpdeskParent
Definition: ntuser.h:571
struct _CURICON_OBJECT * spicn
Definition: ntuser.h:585
struct _CURICON_OBJECT * spicnSm
Definition: ntuser.h:590

Referenced by IntCheckDesktopClasses().

◆ IntNtUserSetClassLongPtr()

ULONG_PTR APIENTRY IntNtUserSetClassLongPtr ( HWND  hWnd,
INT  Offset,
ULONG_PTR  dwNewLong,
BOOL  Ansi,
ULONG  Size 
)

Definition at line 2606 of file class.c.

2611{
2613 PWND Window;
2614 ULONG_PTR Ret = 0;
2615
2617
2619
2621 if (Window != NULL)
2622 {
2623 if (Window->head.pti->ppi != pi)
2624 {
2626 goto Cleanup;
2627 }
2628
2629 _SEH2_TRY
2630 {
2632
2633 /* Probe the parameters */
2634 if (Offset == GCW_ATOM || Offset == GCLP_MENUNAME)
2635 {
2636 /* FIXME: Resource ID can be passed directly without UNICODE_STRING ? */
2637 if (IS_ATOM(dwNewLong))
2638 {
2639 Value.MaximumLength = 0;
2640 Value.Length = 0;
2641 Value.Buffer = (PWSTR)dwNewLong;
2642 }
2643 else
2644 {
2646 }
2647
2648 if (Value.Length & 1)
2649 {
2650 goto InvalidParameter;
2651 }
2652
2653 if (Value.Length != 0)
2654 {
2655 ProbeForRead(Value.Buffer,
2656 Value.Length,
2657 sizeof(WCHAR));
2658 }
2659 else
2660 {
2661 if (Offset == GCW_ATOM && !IS_ATOM(Value.Buffer))
2662 {
2663 goto InvalidParameter;
2664 }
2665 else if (Offset == GCLP_MENUNAME && !IS_INTRESOURCE(Value.Buffer))
2666 {
2670 }
2671 }
2672
2673 dwNewLong = (ULONG_PTR)&Value;
2674 }
2675
2676 Ret = UserSetClassLongPtr(Window->pcls,
2677 Offset,
2678 dwNewLong,
2679 Ansi,
2680 Size);
2681 switch(Offset)
2682 {
2683 case GCLP_HICONSM:
2684 case GCLP_HICON:
2685 {
2686 if (Ret && Ret != dwNewLong)
2688 }
2689 }
2690 }
2692 {
2694 }
2695 _SEH2_END;
2696 }
2697
2698Cleanup:
2699 UserLeave();
2700
2701 return Ret;
2702}
HWND hWnd
Definition: settings.c:17
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
static const WCHAR Cleanup[]
Definition: register.c:80
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
@ InvalidParameter
Definition: gdiplustypes.h:28
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
BOOL UserPaintCaption(PWND pWnd, INT Flags)
Definition: defwnd.c:398
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:258
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:249
#define ProbeForReadUnicodeString(Ptr)
Definition: probe.h:77
Definition: window.c:28
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: ntuser.h:694
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:124
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
ULONG_PTR UserSetClassLongPtr(IN PCLS Class, IN INT Index, IN ULONG_PTR NewLong, IN BOOL Ansi, IN ULONG Size)
Definition: class.c:1896
#define GCLP_MENUNAME
Definition: winuser.h:677
#define GCLP_HICONSM
Definition: winuser.h:675
#define GCLP_HICON
Definition: winuser.h:674
#define IS_INTRESOURCE(i)
Definition: winuser.h:580
#define DC_ICON
Definition: winuser.h:429
#define GCW_ATOM
Definition: winuser.h:661

Referenced by NtUserSetClassLong().

◆ IntReferenceClass()

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

Definition at line 754 of file class.c.

757{
758 PCLS Class;
759 ASSERT(BaseClass->pclsBase == BaseClass);
760
761 if (Desktop != NULL)
762 {
763 Class = IntGetClassForDesktop(BaseClass,
764 ClassLink,
765 Desktop);
766 }
767 else
768 {
769 Class = BaseClass;
770 }
771
772 if (Class != NULL)
773 {
774 Class->cWndReferenceCount++;
775 }
776
777 return Class;
778}
static PCLS IntGetClassForDesktop(IN OUT PCLS BaseClass, IN OUT PCLS *ClassLink, IN PDESKTOP Desktop)
Definition: class.c:630

Referenced by IntGetAndReferenceClass().

◆ IntRegisterClassAtom()

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

Definition at line 339 of file class.c.

341{
342 WCHAR szBuf[65];
343 PWSTR AtomName = szBuf;
345
346 if (ClassName->Length != 0)
347 {
348 if (ClassName->Length + sizeof(UNICODE_NULL) > sizeof(szBuf))
349 {
351 ClassName->Length + sizeof(UNICODE_NULL),
352 TAG_USTR);
353
354 if (AtomName == NULL)
355 {
357 return FALSE;
358 }
359 }
360
362 {
363 RtlCopyMemory(AtomName,
364 ClassName->Buffer,
365 ClassName->Length);
366 }
368 {
369 if (AtomName != szBuf)
370 ExFreePoolWithTag(AtomName, TAG_USTR);
372 _SEH2_YIELD(return FALSE);
373 }
374 _SEH2_END;
375 AtomName[ClassName->Length / sizeof(WCHAR)] = UNICODE_NULL;
376 }
377 else
378 {
379 ASSERT(IS_ATOM(ClassName->Buffer));
380 AtomName = ClassName->Buffer;
381 }
382
384 AtomName,
385 pAtom);
386
387 if (AtomName != ClassName->Buffer && AtomName != szBuf)
388 ExFreePoolWithTag(AtomName, TAG_USTR);
389
390
391 if (!NT_SUCCESS(Status))
392 {
394 return FALSE;
395 }
396
397 return TRUE;
398}
NTSYSAPI NTSTATUS NTAPI RtlAddAtomToAtomTable(_In_ PRTL_ATOM_TABLE AtomTable, _In_ PWSTR AtomName, _Out_ PRTL_ATOM Atom)

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

◆ IntSetClassAtom()

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

Definition at line 450 of file class.c.

452{
454
455 /* Update the base class first */
456 Class = Class->pclsBase;
457 if (ClassName->Length > 0)
458 {
459 if (!IntRegisterClassAtom(ClassName,
460 &Atom))
461 {
462 ERR("RegisterClassAtom failed ! %x\n", EngGetLastError());
463 return FALSE;
464 }
465 }
466 else
467 {
468 if (IS_ATOM(ClassName->Buffer))
469 {
470 Atom = (ATOM)((ULONG_PTR)ClassName->Buffer & 0xffff); // XXX: are we missing refcount here ?
471 }
472 else
473 {
475 return FALSE;
476 }
477 }
478
479 IntDeregisterClassAtom(Class->atomNVClassName);
480
481 Class->atomNVClassName = Atom;
482
483 /* Update the clones */
484 Class = Class->pclsClone;
485 while (Class != NULL)
486 {
487 Class->atomNVClassName = Atom;
488
489 Class = Class->pclsNext;
490 }
491
492 return TRUE;
493}
WORD ATOM
Definition: dimm.idl:113
ENGAPI ULONG APIENTRY EngGetLastError(VOID)
Definition: error.c:9

Referenced by UserSetClassLongPtr().

◆ IntSetClassMenuName()

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

Definition at line 1767 of file class.c.

1769{
1770 BOOL Ret = FALSE;
1771
1772 /* Change the base class first */
1773 Class = Class->pclsBase;
1774
1775 if (MenuName->Length != 0)
1776 {
1778 PWSTR strBufW;
1779
1780 AnsiString.MaximumLength = (USHORT)RtlUnicodeStringToAnsiSize(MenuName);
1781
1782 strBufW = UserHeapAlloc(MenuName->Length + sizeof(UNICODE_NULL) +
1783 AnsiString.MaximumLength);
1784 if (strBufW != NULL)
1785 {
1786 _SEH2_TRY
1787 {
1789
1790 /* Copy the unicode string */
1791 RtlCopyMemory(strBufW,
1792 MenuName->Buffer,
1793 MenuName->Length);
1794 strBufW[MenuName->Length / sizeof(WCHAR)] = UNICODE_NULL;
1795
1796 /* Create an ANSI copy of the string */
1797 AnsiString.Buffer = (PSTR)(strBufW + (MenuName->Length / sizeof(WCHAR)) + 1);
1799 MenuName,
1800 FALSE);
1801 if (!NT_SUCCESS(Status))
1802 {
1805 }
1806
1807 Ret = TRUE;
1808 }
1810 {
1812 }
1813 _SEH2_END;
1814
1815 if (Ret)
1816 {
1817 /* Update the base class */
1819 Class->lpszClientUnicodeMenuName = strBufW;
1820 Class->lpszClientAnsiMenuName = AnsiString.Buffer;
1821 Class->MenuNameIsString = TRUE;
1822
1823 /* Update the clones */
1824 Class = Class->pclsClone;
1825 while (Class != NULL)
1826 {
1827 Class->lpszClientUnicodeMenuName = strBufW;
1828 Class->lpszClientAnsiMenuName = AnsiString.Buffer;
1829 Class->MenuNameIsString = TRUE;
1830
1831 Class = Class->pclsNext;
1832 }
1833 }
1834 else
1835 {
1836 ERR("Failed to copy class menu name!\n");
1837 UserHeapFree(strBufW);
1838 }
1839 }
1840 else
1842 }
1843 else
1844 {
1845 ASSERT(IS_INTRESOURCE(MenuName->Buffer));
1846
1847 /* Update the base class */
1849 Class->lpszClientUnicodeMenuName = MenuName->Buffer;
1850 Class->lpszClientAnsiMenuName = (PSTR)MenuName->Buffer;
1851 Class->MenuNameIsString = FALSE;
1852
1853 /* Update the clones */
1854 Class = Class->pclsClone;
1855 while (Class != NULL)
1856 {
1857 Class->lpszClientUnicodeMenuName = MenuName->Buffer;
1858 Class->lpszClientAnsiMenuName = (PSTR)MenuName->Buffer;
1859 Class->MenuNameIsString = FALSE;
1860
1861 Class = Class->pclsNext;
1862 }
1863
1864 Ret = TRUE;
1865 }
1866
1867 return Ret;
1868}
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))

Referenced by UserSetClassLongPtr().

◆ IntSetClassWndProc()

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

Definition at line 548 of file class.c.

551{
552 INT i;
553 PCALLPROCDATA pcpd;
554 WNDPROC Ret, chWndProc;
555
556 Ret = IntGetClassWndProc(Class, Ansi);
557
558 // If Server Side, downgrade to Client Side.
559 if (Class->CSF_flags & CSF_SERVERSIDEPROC)
560 {
561 if (Ansi) Class->CSF_flags |= CSF_ANSIPROC;
562 Class->CSF_flags &= ~CSF_SERVERSIDEPROC;
563 Class->Unicode = !Ansi;
564 }
565
566 if (!WndProc) WndProc = Class->lpfnWndProc;
567
568 chWndProc = WndProc;
569
570 // Check if CallProc handle and retrieve previous call proc address and set.
572 {
574 if (pcpd) chWndProc = pcpd->pfnClientPrevious;
575 }
576
577 Class->lpfnWndProc = chWndProc;
578
579 // Clear test proc.
580 chWndProc = NULL;
581
582 // Switch from Client Side call to Server Side call if match. Ref: "deftest".
583 for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
584 {
585 if (GETPFNCLIENTW(i) == Class->lpfnWndProc)
586 {
587 chWndProc = GETPFNSERVER(i);
588 break;
589 }
590 if (GETPFNCLIENTA(i) == Class->lpfnWndProc)
591 {
592 chWndProc = GETPFNSERVER(i);
593 break;
594 }
595 }
596 // If match, set/reset to Server Side and clear ansi.
597 if (chWndProc)
598 {
599 Class->lpfnWndProc = chWndProc;
600 Class->Unicode = TRUE;
601 Class->CSF_flags &= ~CSF_ANSIPROC;
602 Class->CSF_flags |= CSF_SERVERSIDEPROC;
603 }
604 else
605 {
606 Class->Unicode = !Ansi;
607
608 if (Ansi)
609 Class->CSF_flags |= CSF_ANSIPROC;
610 else
611 Class->CSF_flags &= ~CSF_ANSIPROC;
612 }
613
614 /* Update the clones */
615 chWndProc = Class->lpfnWndProc;
616
617 Class = Class->pclsClone;
618 while (Class != NULL)
619 {
620 Class->Unicode = !Ansi;
621 Class->lpfnWndProc = chWndProc;
622
623 Class = Class->pclsNext;
624 }
625
626 return Ret;
627}
static __inline BOOL IsCallProcHandle(IN WNDPROC lpWndProc)
Definition: class.h:13
@ TYPE_CALLPROC
Definition: ntuser.h:47
WNDPROC pfnClientPrevious
Definition: ntuser.h:552
WNDPROC FASTCALL IntGetClassWndProc(PCLS Class, BOOL Ansi)
Definition: class.c:499
PVOID UserGetObject(PUSER_HANDLE_TABLE ht, HANDLE handle, HANDLE_TYPE type)
Definition: object.c:495
PUSER_HANDLE_TABLE gHandleTable
Definition: object.c:13

Referenced by UserSetClassLongPtr().

◆ LookupFnIdToiCls()

BOOL FASTCALL LookupFnIdToiCls ( int  FnId,
int iCls 
)

Definition at line 133 of file class.c.

134{
135 int i;
136
137 for ( i = 0; i < ARRAYSIZE(FnidToiCls); i++)
138 {
139 if (FnidToiCls[i].FnId == FnId)
140 {
141 if (iCls) *iCls = FnidToiCls[i].ClsId;
142 return TRUE;
143 }
144 }
145 if (iCls) *iCls = 0;
146 return FALSE;
147}
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
int FnId
Definition: class.c:108
static struct @5130 FnidToiCls[]

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

◆ NtUserGetClassInfo()

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

Definition at line 2779 of file class.c.

2785{
2786 UNICODE_STRING SafeClassName;
2787 WNDCLASSEXW Safewcexw;
2788 PCLS Class;
2789 RTL_ATOM ClassAtom = 0;
2790 PPROCESSINFO ppi;
2791 BOOL Ret = TRUE;
2793
2794 _SEH2_TRY
2795 {
2796 ProbeForWrite( lpWndClassEx, sizeof(WNDCLASSEXW), sizeof(ULONG));
2797 RtlCopyMemory( &Safewcexw, lpWndClassEx, sizeof(WNDCLASSEXW));
2798 if (ppszMenuName)
2799 {
2800 ProbeForWrite(ppszMenuName, sizeof(*ppszMenuName), sizeof(PVOID));
2801 }
2802 }
2804 {
2806 _SEH2_YIELD(return FALSE);
2807 }
2808 _SEH2_END;
2809
2810 Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassName);
2811 if (!NT_SUCCESS(Status))
2812 {
2813 ERR("Error capturing the class name\n");
2815 return FALSE;
2816 }
2817
2818 // If null instance use client.
2820
2821 TRACE("GetClassInfo(%wZ, %p)\n", &SafeClassName, hInstance);
2822
2823 /* NOTE: Need exclusive lock because getting the wndproc might require the
2824 creation of a call procedure handle */
2826
2827 ppi = GetW32ProcessInfo();
2828 if (!(ppi->W32PF_flags & W32PF_CLASSESREGISTERED))
2829 {
2831 }
2832
2833 ClassAtom = IntGetClassAtom(&SafeClassName,
2834 hInstance,
2835 ppi,
2836 &Class,
2837 NULL);
2838 if (ClassAtom != (RTL_ATOM)0)
2839 {
2840 ClassAtom = Class->atomNVClassName;
2841 Ret = UserGetClassInfo(Class, &Safewcexw, bAnsi, hInstance);
2842 }
2843 else
2844 {
2846 Ret = FALSE;
2847 }
2848
2849 UserLeave();
2850
2851 if (Ret)
2852 {
2853 _SEH2_TRY
2854 {
2855 /* Emulate Function. */
2856 if (ppszMenuName) *ppszMenuName = (LPWSTR)Safewcexw.lpszMenuName;
2857
2858 RtlCopyMemory(lpWndClassEx, &Safewcexw, sizeof(WNDCLASSEXW));
2859
2860 // From Wine:
2861 /* We must return the atom of the class here instead of just TRUE. */
2862 /* Undocumented behavior! Return the class atom as a BOOL! */
2863 Ret = (BOOL)ClassAtom;
2864 }
2866 {
2868 Ret = FALSE;
2869 }
2870 _SEH2_END;
2871 }
2872
2873 if (!IS_ATOM(SafeClassName.Buffer))
2874 ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING);
2875
2876 return Ret;
2877}
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define BOOL
Definition: nt_native.h:43
#define TAG_STRING
Definition: oslist.h:22
LPCWSTR lpszMenuName
Definition: winuser.h:3228
uint32_t ULONG
Definition: typedefs.h:59
static BOOL UserGetClassInfo(IN PCLS Class, OUT PWNDCLASSEXW lpwcx, IN BOOL Ansi, HINSTANCE hInstance)
Definition: class.c:2280
_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:152
WCHAR * LPWSTR
Definition: xmlstorage.h:184

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

◆ NtUserGetClassName()

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

Definition at line 2881 of file class.c.

2884{
2885 PWND Window;
2886 UNICODE_STRING CapturedClassName;
2887 INT iCls, Ret = 0;
2888 RTL_ATOM Atom = 0;
2889
2891
2893 if (Window != NULL)
2894 {
2895 if (Real && Window->fnid && !(Window->fnid & FNID_DESTROY))
2896 {
2897 if (LookupFnIdToiCls(Window->fnid, &iCls))
2898 {
2899 Atom = gpsi->atomSysClass[iCls];
2900 }
2901 }
2902
2903 _SEH2_TRY
2904 {
2905 ProbeForWriteUnicodeString(ClassName);
2906 CapturedClassName = *ClassName;
2907 if (CapturedClassName.Length != 0)
2908 {
2909 ProbeForRead(CapturedClassName.Buffer,
2910 CapturedClassName.Length,
2911 sizeof(WCHAR));
2912 }
2913
2914 /* Get the class name */
2915 Ret = UserGetClassName(Window->pcls,
2916 &CapturedClassName,
2917 Atom,
2918 FALSE);
2919
2920 if (Ret != 0)
2921 {
2922 /* Update the Length field */
2923 ClassName->Length = CapturedClassName.Length;
2924 }
2925 }
2927 {
2929 }
2930 _SEH2_END;
2931 }
2932
2933 UserLeave();
2934
2935 return Ret;
2936}
float Real
Definition: definitions.h:36
#define FNID_DESTROY
Definition: ntuser.h:898
VOID FASTCALL UserEnterShared(VOID)
Definition: ntuser.c:242
#define ProbeForWriteUnicodeString(Ptr)
Definition: probe.h:48
INT UserGetClassName(IN PCLS Class, IN OUT PUNICODE_STRING ClassName, IN RTL_ATOM Atom, IN BOOL Ansi)
Definition: class.c:1647

Referenced by GetClassNameW(), and RealGetWindowClassW().

◆ NtUserGetWOWClass()

PCLS APIENTRY NtUserGetWOWClass ( HINSTANCE  hInstance,
PUNICODE_STRING  ClassName 
)

Definition at line 2941 of file class.c.

2944{
2945 UNICODE_STRING SafeClassName;
2947 PCLS Class = NULL;
2948 RTL_ATOM ClassAtom = 0;
2950
2951 Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassName);
2952 if (!NT_SUCCESS(Status))
2953 {
2954 ERR("Error capturing the class name\n");
2956 return FALSE;
2957 }
2958
2960
2962
2963 ClassAtom = IntGetClassAtom(&SafeClassName,
2964 hInstance,
2965 pi,
2966 &Class,
2967 NULL);
2968 if (!ClassAtom)
2969 {
2971 }
2972
2973
2974 if (SafeClassName.Buffer && !IS_ATOM(SafeClassName.Buffer))
2975 ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING);
2976
2977 UserLeave();
2978//
2979// Don't forget to use DesktopPtrToUser( ? ) with return pointer in user space.
2980//
2981 return Class;
2982}

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 2444 of file class.c.

2462{
2463 WNDCLASSEXW CapturedClassInfo = {0};
2464 UNICODE_STRING CapturedName = {0}, CapturedMenuName = {0}, CapturedVersion = {0};
2465 RTL_ATOM Ret = (RTL_ATOM)0;
2467 BOOL Exception = FALSE;
2468
2469 if (Flags & ~(CSF_ANSIPROC))
2470 {
2471 ERR("NtUserRegisterClassExWOW Bad Flags!\n");
2473 return Ret;
2474 }
2475
2477
2478 TRACE("NtUserRegisterClassExWOW ClsN %wZ\n",ClassName);
2479
2480 if ( !(ppi->W32PF_flags & W32PF_CLASSESREGISTERED ))
2481 {
2483 }
2484
2485 _SEH2_TRY
2486 {
2487 /* Probe the parameters and basic parameter checks */
2488 if (ProbeForReadUint(&lpwcx->cbSize) != sizeof(WNDCLASSEXW))
2489 {
2490 ERR("NtUserRegisterClassExWOW Wrong cbSize!\n");
2491 goto InvalidParameter;
2492 }
2493
2494 ProbeForRead(lpwcx,
2495 sizeof(WNDCLASSEXW),
2496 sizeof(ULONG));
2497 RtlCopyMemory(&CapturedClassInfo,
2498 lpwcx,
2499 sizeof(WNDCLASSEXW));
2500
2501 CapturedName = ProbeForReadUnicodeString(ClassName);
2502 CapturedVersion = ProbeForReadUnicodeString(ClsVersion);
2503
2504 ProbeForRead(pClassMenuName,
2505 sizeof(CLSMENUNAME),
2506 1);
2507
2508 CapturedMenuName = ProbeForReadUnicodeString(pClassMenuName->pusMenuName);
2509
2510 if ( (CapturedName.Length & 1) ||
2511 (CapturedMenuName.Length & 1) ||
2512 (CapturedClassInfo.cbClsExtra < 0) ||
2513 ((CapturedClassInfo.cbClsExtra + CapturedName.Length +
2514 CapturedMenuName.Length + sizeof(CLS))
2515 < (ULONG)CapturedClassInfo.cbClsExtra) ||
2516 (CapturedClassInfo.cbWndExtra < 0) ||
2517 (CapturedClassInfo.hInstance == NULL) )
2518 {
2519 ERR("NtUserRegisterClassExWOW Invalid Parameter Error!\n");
2520 goto InvalidParameter;
2521 }
2522
2523 if (CapturedName.Length != 0)
2524 {
2525 ProbeForRead(CapturedName.Buffer,
2526 CapturedName.Length,
2527 sizeof(WCHAR));
2528 }
2529 else
2530 {
2531 if (!IS_ATOM(CapturedName.Buffer))
2532 {
2533 ERR("NtUserRegisterClassExWOW ClassName Error!\n");
2534 goto InvalidParameter;
2535 }
2536 }
2537
2538 if (CapturedVersion.Length != 0)
2539 {
2540 ProbeForRead(CapturedVersion.Buffer,
2541 CapturedVersion.Length,
2542 sizeof(WCHAR));
2543 }
2544 else
2545 {
2546 if (!IS_ATOM(CapturedVersion.Buffer))
2547 {
2548 ERR("NtUserRegisterClassExWOW ClassName Error!\n");
2549 goto InvalidParameter;
2550 }
2551 }
2552
2553 if (CapturedMenuName.Length != 0)
2554 {
2555 ProbeForRead(CapturedMenuName.Buffer,
2556 CapturedMenuName.Length,
2557 sizeof(WCHAR));
2558 }
2559 else if (CapturedMenuName.Buffer != NULL &&
2560 !IS_INTRESOURCE(CapturedMenuName.Buffer))
2561 {
2562 ERR("NtUserRegisterClassExWOW MenuName Error!\n");
2566 }
2567
2568 if (IsCallProcHandle(lpwcx->lpfnWndProc))
2569 { // Never seen this yet, but I'm sure it's a little haxxy trick!
2570 // If this pops up we know what todo!
2571 ERR("NtUserRegisterClassExWOW WndProc is CallProc!!\n");
2572 }
2573
2574 TRACE("NtUserRegisterClassExWOW MnuN %wZ\n",&CapturedMenuName);
2575 }
2577 {
2578 ERR("NtUserRegisterClassExWOW Exception Error!\n");
2580 Exception = TRUE;
2581 }
2582 _SEH2_END;
2583
2584 if (!Exception)
2585 {
2586 /* Register the class */
2587 Ret = UserRegisterClass(&CapturedClassInfo,
2588 &CapturedName,
2589 &CapturedVersion,
2590 &CapturedMenuName,
2591 fnID,
2592 Flags);
2593 }
2594
2595 if (!Ret)
2596 {
2597 TRACE("NtUserRegisterClassExWOW Null Return!\n");
2598 }
2599
2600 UserLeave();
2601
2602 return Ret;
2603}
#define ProbeForReadUint(Ptr)
Definition: probe.h:67
PUNICODE_STRING pusMenuName
Definition: ntuser.h:500
WNDPROC lpfnWndProc
Definition: winuser.h:3221
UINT cbSize
Definition: winuser.h:3219
int cbWndExtra
Definition: winuser.h:3223
HINSTANCE hInstance
Definition: winuser.h:3224
int cbClsExtra
Definition: winuser.h:3222
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:1504
#define ERROR_INVALID_FLAGS
Definition: winerror.h:583
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170

Referenced by RegisterClassExWOWW(), and START_TEST().

◆ NtUserSetClassLong()

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

Definition at line 2706 of file class.c.

2711{
2712 return IntNtUserSetClassLongPtr(hWnd, Offset, dwNewLong, Ansi, sizeof(LONG));
2713}
ULONG_PTR APIENTRY IntNtUserSetClassLongPtr(HWND hWnd, INT Offset, ULONG_PTR dwNewLong, BOOL Ansi, ULONG Size)
Definition: class.c:2606

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

◆ NtUserSetClassWord()

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

Definition at line 2732 of file class.c.

2736{
2737/*
2738 * NOTE: Obsoleted in 32-bit windows
2739 */
2740 return(0);
2741}

◆ NtUserUnregisterClass()

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

Definition at line 2745 of file class.c.

2749{
2750 UNICODE_STRING SafeClassName;
2752 BOOL Ret;
2753
2754 Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassNameOrAtom);
2755 if (!NT_SUCCESS(Status))
2756 {
2757 ERR("Error capturing the class name\n");
2759 return FALSE;
2760 }
2761
2763
2764 /* Unregister the class */
2765 Ret = UserUnregisterClass(&SafeClassName, hInstance, NULL); // Null for now~
2766
2767 UserLeave();
2768
2769 if (SafeClassName.Buffer && !IS_ATOM(SafeClassName.Buffer))
2770 ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING);
2771
2772 return Ret;
2773}
BOOL UserUnregisterClass(IN PUNICODE_STRING ClassName, IN HINSTANCE hInstance, OUT PCLSMENUNAME pClassMenuName)
Definition: class.c:1591

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 152 of file class.c.

155{
157 UNICODE_STRING ustrCopy;
158
159 /* Default to NULL */
160 RtlInitEmptyUnicodeString(pustrOut, NULL, 0);
161
163 {
164 ProbeForRead(pustrUnsafe, sizeof(UNICODE_STRING), 1);
165
166 ustrCopy = *pustrUnsafe;
167
168 /* Validate the string */
169 if ((ustrCopy.Length & 1) || (ustrCopy.Buffer == NULL))
170 {
171 /* This is not legal */
173 }
174
175 /* Check if this is an atom */
176 if (IS_ATOM(ustrCopy.Buffer))
177 {
178 /* Copy the atom, length is 0 */
179 pustrOut->MaximumLength = pustrOut->Length = 0;
180 pustrOut->Buffer = ustrCopy.Buffer;
181 }
182 else
183 {
184 /* Get the length, maximum length includes zero termination */
185 pustrOut->Length = ustrCopy.Length;
186 pustrOut->MaximumLength = pustrOut->Length + sizeof(WCHAR);
187
188 /* Allocate a buffer */
189 pustrOut->Buffer = ExAllocatePoolWithTag(PagedPool,
190 pustrOut->MaximumLength,
191 TAG_STRING);
192 if (!pustrOut->Buffer)
193 {
195 }
196
197 /* Copy the string and zero terminate it */
198 ProbeForRead(ustrCopy.Buffer, pustrOut->Length, 1);
199 RtlCopyMemory(pustrOut->Buffer, ustrCopy.Buffer, pustrOut->Length);
200 pustrOut->Buffer[pustrOut->Length / sizeof(WCHAR)] = L'\0';
201 }
202 }
204 {
205 /* Check if we already allocated a buffer */
206 if (pustrOut->Buffer)
207 {
208 /* Free the buffer */
209 ExFreePoolWithTag(pustrOut->Buffer, TAG_STRING);
211 }
212 }
213 _SEH2_END;
214
215 return Status;
216}
#define L(x)
Definition: ntvdm.h:50
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158

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

◆ RegisterControlAtoms()

BOOL FASTCALL RegisterControlAtoms ( VOID  )

Definition at line 401 of file class.c.

402{
404 UNICODE_STRING ClassName;
405 INT i = 0;
406
407 while ( i < ICLS_DESKTOP)
408 {
409 RtlInitUnicodeString(&ClassName, ControlsList[i]);
410 if (IntRegisterClassAtom(&ClassName, &Atom))
411 {
413 TRACE("Reg Control Atom %ls: 0x%x\n", ControlsList[i], Atom);
414 }
415 i++;
416 }
417 return TRUE;
418}
#define ICLS_DESKTOP
Definition: ntuser.h:929
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
static PWSTR ControlsList[]
Definition: class.c:14

Referenced by InitUserAtoms().

◆ UserAddCallProcToClass()

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

Definition at line 428 of file class.c.

430{
431 PCLS BaseClass;
432
433 ASSERT(CallProc->spcpdNext == NULL);
434
435 BaseClass = Class->pclsBase;
436 ASSERT(CallProc->spcpdNext == NULL);
437 CallProc->spcpdNext = BaseClass->spcpdFirst;
438 BaseClass->spcpdFirst = CallProc;
439
440 /* Update all clones */
441 Class = Class->pclsClone;
442 while (Class != NULL)
443 {
444 Class->spcpdFirst = BaseClass->spcpdFirst;
445 Class = Class->pclsNext;
446 }
447}
PCALLPROCDATA spcpdFirst
Definition: ntuser.h:576

Referenced by IntCreateWindow().

◆ UserGetClassInfo()

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

Definition at line 2280 of file class.c.

2284{
2285 if (!Class) return FALSE;
2286
2287 lpwcx->style = Class->style;
2288
2289 // If fnId is set, clear the global bit. See wine class test check_style.
2290 if (Class->fnid)
2291 lpwcx->style &= ~CS_GLOBALCLASS;
2292
2293 lpwcx->lpfnWndProc = IntGetClassWndProc(Class, Ansi);
2294
2295 lpwcx->cbClsExtra = Class->cbclsExtra;
2296 lpwcx->cbWndExtra = Class->cbwndExtra;
2297 lpwcx->hIcon = Class->spicn ? UserHMGetHandle(Class->spicn) : NULL;
2298 lpwcx->hCursor = Class->spcur ? UserHMGetHandle(Class->spcur) : NULL;
2299 lpwcx->hIconSm = Class->spicnSm ? UserHMGetHandle(Class->spicnSm) : NULL;
2300 lpwcx->hbrBackground = Class->hbrBackground;
2301
2302 /* Copy non-string to user first. */
2303 if (Ansi)
2304 ((PWNDCLASSEXA)lpwcx)->lpszMenuName = Class->lpszClientAnsiMenuName;
2305 else
2306 lpwcx->lpszMenuName = Class->lpszClientUnicodeMenuName;
2307/*
2308 * FIXME: CLSMENUNAME has the answers! Copy the already made buffers from there!
2309 * Cls: lpszMenuName and lpszAnsiClassName should be used by kernel space.
2310 * lpszClientXxxMenuName should already be mapped to user space.
2311 */
2312 /* Copy string ptr to user. */
2313 if ( Class->lpszClientUnicodeMenuName != NULL &&
2314 Class->MenuNameIsString)
2315 {
2316 lpwcx->lpszMenuName = UserHeapAddressToUser(Ansi ?
2317 (PVOID)Class->lpszClientAnsiMenuName :
2318 (PVOID)Class->lpszClientUnicodeMenuName);
2319 }
2320
2321 if (hInstance == hModClient)
2322 lpwcx->hInstance = NULL;
2323 else
2324 lpwcx->hInstance = hInstance;
2325
2326 /* FIXME: Return the string? Okay! This is performed in User32! */
2327 //lpwcx->lpszClassName = (LPCWSTR)((ULONG_PTR)Class->atomClassName);
2328
2329 return TRUE;
2330}
static __inline PVOID UserHeapAddressToUser(PVOID lpMem)
Definition: usrheap.h:99
struct _WNDCLASSEXA * PWNDCLASSEXA

Referenced by NtUserGetClassInfo().

◆ UserGetClassName()

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

Definition at line 1647 of file class.c.

1651{
1653 WCHAR szStaticTemp[32];
1654 PWSTR szTemp = NULL;
1655 ULONG BufLen = sizeof(szStaticTemp);
1656 INT Ret = 0;
1657
1658 /* Note: Accessing the buffer in ClassName may raise an exception! */
1659
1660 _SEH2_TRY
1661 {
1662 if (Ansi)
1663 {
1664 PANSI_STRING AnsiClassName = (PANSI_STRING)ClassName;
1665 UNICODE_STRING UnicodeClassName;
1666
1667 /* Limit the size of the static buffer on the stack to the
1668 size of the buffer provided by the caller */
1669 if (BufLen / sizeof(WCHAR) > AnsiClassName->MaximumLength)
1670 {
1671 BufLen = AnsiClassName->MaximumLength * sizeof(WCHAR);
1672 }
1673
1674 /* Find out how big the buffer needs to be */
1676 Class->atomClassName,
1677 NULL,
1678 NULL,
1679 szStaticTemp,
1680 &BufLen);
1682 {
1683 if (BufLen / sizeof(WCHAR) > AnsiClassName->MaximumLength)
1684 {
1685 /* The buffer required exceeds the ansi buffer provided,
1686 pretend like we're using the ansi buffer and limit the
1687 size to the buffer size provided */
1688 BufLen = AnsiClassName->MaximumLength * sizeof(WCHAR);
1689 }
1690
1691 /* Allocate a temporary buffer that can hold the unicode class name */
1693 BufLen,
1695 if (szTemp == NULL)
1696 {
1699 }
1700
1701 /* Query the class name */
1703 Atom ? Atom : Class->atomNVClassName,
1704 NULL,
1705 NULL,
1706 szTemp,
1707 &BufLen);
1708 }
1709 else
1710 szTemp = szStaticTemp;
1711
1712 if (NT_SUCCESS(Status))
1713 {
1714 /* Convert the atom name to ansi */
1715
1716 RtlInitUnicodeString(&UnicodeClassName,
1717 szTemp);
1718
1719 Status = RtlUnicodeStringToAnsiString(AnsiClassName,
1720 &UnicodeClassName,
1721 FALSE);
1722 if (!NT_SUCCESS(Status))
1723 {
1726 }
1727 }
1728
1729 Ret = BufLen / sizeof(WCHAR);
1730 }
1731 else /* !ANSI */
1732 {
1733 BufLen = ClassName->MaximumLength;
1734
1735 /* Query the atom name */
1737 Atom ? Atom : Class->atomNVClassName,
1738 NULL,
1739 NULL,
1740 ClassName->Buffer,
1741 &BufLen);
1742
1743 if (!NT_SUCCESS(Status))
1744 {
1747 }
1748
1749 Ret = BufLen / sizeof(WCHAR);
1750 }
1751 }
1753 {
1755 }
1756 _SEH2_END;
1757
1758 if (Ansi && szTemp != NULL && szTemp != szStaticTemp)
1759 {
1761 }
1762
1763 return Ret;
1764}
ANSI_STRING * PANSI_STRING
Definition: env_spec_w32.h:380
#define BufLen
Definition: fatfs.h:167
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 STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
USHORT MaximumLength
Definition: env_spec_w32.h:377
#define USERTAG_CLASS
Definition: tags.h:204

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 1504 of file class.c.

1510{
1511 PTHREADINFO pti;
1513 PCLS Class;
1514 RTL_ATOM ClassAtom;
1515 RTL_ATOM Ret = (RTL_ATOM)0;
1516
1517 /* NOTE: Accessing the buffers in ClassName and MenuName may raise exceptions! */
1518
1519 pti = GetW32ThreadInfo();
1520
1521 pi = pti->ppi;
1522
1523 // Need only to test for two conditions not four....... Fix more whine tests....
1524 if ( IntGetAtomFromStringOrAtom( ClassVersion, &ClassAtom) &&
1525 ClassAtom != (RTL_ATOM)0 &&
1526 !(dwFlags & CSF_SERVERSIDEPROC) ) // Bypass Server Sides
1527 {
1528 Class = IntFindClass( ClassAtom,
1529 lpwcx->hInstance,
1530 &pi->pclsPrivateList,
1531 NULL);
1532
1533 if (Class != NULL && !Class->Global)
1534 {
1535 // Local class already exists
1536 TRACE("Local Class 0x%x does already exist!\n", ClassAtom);
1538 return (RTL_ATOM)0;
1539 }
1540
1541 if (lpwcx->style & CS_GLOBALCLASS)
1542 {
1543 Class = IntFindClass( ClassAtom,
1544 NULL,
1545 &pi->pclsPublicList,
1546 NULL);
1547
1548 if (Class != NULL && Class->Global)
1549 {
1550 TRACE("Global Class 0x%x does already exist!\n", ClassAtom);
1552 return (RTL_ATOM)0;
1553 }
1554 }
1555 }
1556
1557 Class = IntCreateClass(lpwcx,
1558 ClassName,
1559 ClassVersion,
1560 MenuName,
1561 fnID,
1562 dwFlags,
1563 pti->rpdesk,
1564 pi);
1565
1566 if (Class != NULL)
1567 {
1568 PCLS *List;
1569
1570 /* Register the class */
1571 if (Class->Global)
1572 List = &pi->pclsPublicList;
1573 else
1574 List = &pi->pclsPrivateList;
1575
1576 Class->pclsNext = *List;
1578 Class);
1579
1580 Ret = Class->atomNVClassName;
1581 }
1582 else
1583 {
1584 ERR("UserRegisterClass: Yes, that is right, you have no Class!\n");
1585 }
1586
1587 return Ret;
1588}
struct _THREADINFO * GetW32ThreadInfo(VOID)
Definition: misc.c:807
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
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:1047
#define ERROR_CLASS_ALREADY_EXISTS
Definition: winerror.h:891

Referenced by NtUserRegisterClassExWOW().

◆ UserRegisterSystemClasses()

BOOL FASTCALL UserRegisterSystemClasses ( VOID  )

Definition at line 2337 of file class.c.

2338{
2339 UINT i;
2340 UNICODE_STRING ClassName, MenuName;
2342 WNDCLASSEXW wc;
2343 PCLS Class;
2344 BOOL Ret = TRUE;
2345 HBRUSH hBrush;
2346 DWORD Flags = 0;
2347
2348 if (ppi->W32PF_flags & W32PF_CLASSESREGISTERED)
2349 return TRUE;
2350
2351 if ( hModClient == NULL)
2352 return FALSE;
2353
2354 RtlZeroMemory(&ClassName, sizeof(ClassName));
2355 RtlZeroMemory(&MenuName, sizeof(MenuName));
2356
2357 for (i = 0; i != ARRAYSIZE(DefaultServerClasses); i++)
2358 {
2359 if (!IS_ATOM(DefaultServerClasses[i].ClassName))
2360 {
2361 RtlInitUnicodeString(&ClassName, DefaultServerClasses[i].ClassName);
2362 }
2363 else
2364 {
2365 ClassName.Buffer = DefaultServerClasses[i].ClassName;
2366 ClassName.Length = 0;
2367 ClassName.MaximumLength = 0;
2368 }
2369
2370 wc.cbSize = sizeof(wc);
2372
2374
2375 if (DefaultServerClasses[i].ProcW)
2376 {
2378 wc.hInstance = hModuleWin;
2379 }
2380 else
2381 {
2383 wc.hInstance = hModClient;
2384 }
2385
2386 wc.cbClsExtra = 0;
2388 wc.hIcon = NULL;
2389
2391 wc.hCursor = NULL;
2392 if (DefaultServerClasses[i].hCursor == (HICON)OCR_NORMAL)
2393 {
2394 if (SYSTEMCUR(ARROW) == NULL)
2395 {
2396 ERR("SYSTEMCUR(ARROW) == NULL, should not happen!!\n");
2397 }
2398 else
2399 {
2400 wc.hCursor = UserHMGetHandle(SYSTEMCUR(ARROW));
2401 }
2402 }
2403
2404 hBrush = DefaultServerClasses[i].hBrush;
2405 if (hBrush <= (HBRUSH)COLOR_MENUBAR)
2406 {
2407 hBrush = IntGetSysColorBrush(HandleToUlong(hBrush));
2408 }
2409 wc.hbrBackground = hBrush;
2410 wc.lpszMenuName = NULL;
2411 wc.lpszClassName = ClassName.Buffer;
2412 wc.hIconSm = NULL;
2413
2414 Class = IntCreateClass( &wc,
2415 &ClassName,
2416 &ClassName,
2417 &MenuName,
2418 DefaultServerClasses[i].fiId,
2419 Flags,
2420 NULL,
2421 ppi);
2422 if (Class != NULL)
2423 {
2424 Class->pclsNext = ppi->pclsPublicList;
2426 Class);
2427
2429 }
2430 else
2431 {
2432 ERR("!!! Registering system class failed!\n");
2433 Ret = FALSE;
2434 }
2435 }
2436 if (Ret) ppi->W32PF_flags |= W32PF_CLASSESREGISTERED;
2437 return Ret;
2438}
#define HandleToUlong(h)
Definition: basetsd.h:79
#define SYSTEMCUR(func)
Definition: cursoricon.h:129
unsigned long DWORD
Definition: ntddk_ex.h:95
#define ICLASS_TO_MASK(iCls)
Definition: ntuser.h:902
HGDIOBJ FASTCALL IntGetSysColorBrush(INT Object)
Definition: stockobj.c:317
static HICON
Definition: imagelist.c:80
unsigned int UINT
Definition: ndis.h:50
DWORD dwRegisteredClasses
Definition: win32.h:281
struct _CLS * pclsPublicList
Definition: win32.h:261
WNDPROC ProcW
Definition: ntuser.h:488
LPCWSTR lpszClassName
Definition: winuser.h:3229
HBRUSH hbrBackground
Definition: winuser.h:3227
HCURSOR hCursor
Definition: winuser.h:3226
HICON hIconSm
Definition: winuser.h:3230
UINT style
Definition: winuser.h:3220
HICON hIcon
Definition: winuser.h:3225
REGISTER_SYSCLASS DefaultServerClasses[]
Definition: class.c:37
HANDLE hModuleWin
Definition: main.c:16

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

◆ UserSetClassLongPtr()

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

Definition at line 1896 of file class.c.

1901{
1902 ULONG_PTR Ret = 0;
1903
1904 /* NOTE: For GCLP_MENUNAME and GCW_ATOM this function may raise an exception! */
1905
1906 /* Change the information in the base class first, then update the clones */
1907 Class = Class->pclsBase;
1908
1909 if (Index >= 0)
1910 {
1911 TRACE("SetClassLong(%d, %x)\n", Index, NewLong);
1912
1913 if (((ULONG)Index + Size) < (ULONG)Index ||
1914 ((ULONG)Index + Size) > (ULONG)Class->cbclsExtra)
1915 {
1917 return 0;
1918 }
1919
1920 Ret = IntGetSetClassLongPtr(Class, Index, NewLong, Size);
1921
1922 /* Update the clones */
1923 Class = Class->pclsClone;
1924 while (Class != NULL)
1925 {
1927 Class = Class->pclsNext;
1928 }
1929
1930 return Ret;
1931 }
1932
1933 switch (Index)
1934 {
1935 case GCL_CBWNDEXTRA:
1936 Ret = (ULONG_PTR)Class->cbwndExtra;
1937 Class->cbwndExtra = (INT)NewLong;
1938
1939 /* Update the clones */
1940 Class = Class->pclsClone;
1941 while (Class != NULL)
1942 {
1943 Class->cbwndExtra = (INT)NewLong;
1944 Class = Class->pclsNext;
1945 }
1946
1947 break;
1948
1949 case GCL_CBCLSEXTRA:
1951 break;
1952
1953 case GCLP_HBRBACKGROUND:
1954 Ret = (ULONG_PTR)Class->hbrBackground;
1955 Class->hbrBackground = (HBRUSH)NewLong;
1956
1957 /* Update the clones */
1958 Class = Class->pclsClone;
1959 while (Class != NULL)
1960 {
1961 Class->hbrBackground = (HBRUSH)NewLong;
1962 Class = Class->pclsNext;
1963 }
1964 break;
1965
1966 case GCLP_HCURSOR:
1967 {
1968 PCURICON_OBJECT NewCursor = NULL;
1969
1970 if (NewLong)
1971 {
1972 NewCursor = UserGetCurIconObject((HCURSOR)NewLong);
1973 if (!NewCursor)
1974 {
1976 return 0;
1977 }
1978 }
1979
1980 if (Class->spcur)
1981 {
1982 Ret = (ULONG_PTR)UserHMGetHandle(Class->spcur);
1984 }
1985 else
1986 {
1987 Ret = 0;
1988 }
1989
1990 if (Ret == NewLong)
1991 {
1992 /* It's a nop */
1993 return Ret;
1994 }
1995
1996 Class->spcur = NewCursor;
1997
1998 /* Update the clones */
1999 Class = Class->pclsClone;
2000 while (Class != NULL)
2001 {
2002 if (Class->spcur)
2004 if (NewCursor)
2005 UserReferenceObject(NewCursor);
2006 Class->spcur = NewCursor;
2007 Class = Class->pclsNext;
2008 }
2009
2010 break;
2011 }
2012
2013 // MSDN:
2014 // hIconSm, A handle to a small icon that is associated with the window class.
2015 // If this member is NULL, the system searches the icon resource specified by
2016 // the hIcon member for an icon of the appropriate size to use as the small icon.
2017 //
2018 case GCLP_HICON:
2019 {
2020 PCURICON_OBJECT NewIcon = NULL;
2021 PCURICON_OBJECT NewSmallIcon = NULL;
2022
2023 if (NewLong)
2024 {
2025 NewIcon = UserGetCurIconObject((HCURSOR)NewLong);
2026 if (!NewIcon)
2027 {
2029 return 0;
2030 }
2031 }
2032
2033 if (Class->spicn)
2034 {
2035 Ret = (ULONG_PTR)UserHMGetHandle(Class->spicn);
2037 }
2038 else
2039 {
2040 Ret = 0;
2041 }
2042
2043 if (Ret == NewLong)
2044 {
2045 /* It's a nop */
2046 return Ret;
2047 }
2048
2049 if (Ret && (Class->CSF_flags & CSF_CACHEDSMICON))
2050 {
2051 /* We will change the small icon */
2052 UserDereferenceObject(Class->spicnSm);
2054 Class->spicnSm = NULL;
2055 Class->CSF_flags &= ~CSF_CACHEDSMICON;
2056 }
2057
2058 if (NewLong && !Class->spicnSm)
2059 {
2060 /* Create the new small icon from the new large(?) one */
2061 HICON SmallIconHandle = NULL;
2064 {
2065 SmallIconHandle = co_IntCopyImage(
2066 (HICON)NewLong,
2067 IMAGE_ICON,
2071 }
2072 if (!SmallIconHandle)
2073 {
2074 /* Retry without copying from resource */
2075 SmallIconHandle = co_IntCopyImage(
2076 (HICON)NewLong,
2077 IMAGE_ICON,
2080 0);
2081 }
2082 if (SmallIconHandle)
2083 {
2084 /* So use it */
2085 NewSmallIcon = Class->spicnSm = UserGetCurIconObject(SmallIconHandle);
2086 Class->CSF_flags |= CSF_CACHEDSMICON;
2087 }
2088 }
2089
2090 Class->spicn = NewIcon;
2091
2092 /* Update the clones */
2093 Class = Class->pclsClone;
2094 while (Class != NULL)
2095 {
2096 if (Class->spicn)
2098 if (NewIcon)
2099 UserReferenceObject(NewIcon);
2100 Class->spicn = NewIcon;
2101 if (NewSmallIcon)
2102 {
2103 if (Class->spicnSm)
2104 UserDereferenceObject(Class->spicnSm);
2105 UserReferenceObject(NewSmallIcon);
2106 Class->spicnSm = NewSmallIcon;
2107 Class->CSF_flags |= CSF_CACHEDSMICON;
2108 }
2109 Class = Class->pclsNext;
2110 }
2111 break;
2112 }
2113
2114 case GCLP_HICONSM:
2115 {
2116 PCURICON_OBJECT NewSmallIcon = NULL;
2117 BOOLEAN NewIconFromCache = FALSE;
2118
2119 if (NewLong)
2120 {
2121 NewSmallIcon = UserGetCurIconObject((HCURSOR)NewLong);
2122 if (!NewSmallIcon)
2123 {
2125 return 0;
2126 }
2127 }
2128 else
2129 {
2130 /* Create the new small icon from the large one */
2131 HICON SmallIconHandle = NULL;
2132 if((Class->spicn->CURSORF_flags & (CURSORF_LRSHARED | CURSORF_FROMRESOURCE))
2134 {
2135 SmallIconHandle = co_IntCopyImage(
2136 UserHMGetHandle(Class->spicn),
2137 IMAGE_ICON,
2141 }
2142 if (!SmallIconHandle)
2143 {
2144 /* Retry without copying from resource */
2145 SmallIconHandle = co_IntCopyImage(
2146 UserHMGetHandle(Class->spicn),
2147 IMAGE_ICON,
2150 0);
2151 }
2152 if (SmallIconHandle)
2153 {
2154 /* So use it */
2155 NewSmallIcon = UserGetCurIconObject(SmallIconHandle);
2156 NewIconFromCache = TRUE;
2157 }
2158 else
2159 {
2160 ERR("Failed getting a small icon for the class.\n");
2161 }
2162 }
2163
2164 if (Class->spicnSm)
2165 {
2166 if (Class->CSF_flags & CSF_CACHEDSMICON)
2167 {
2168 /* We must destroy the icon if we own it */
2170 Ret = 0;
2171 }
2172 else
2173 {
2174 Ret = (ULONG_PTR)UserHMGetHandle(Class->spicnSm);
2175 }
2176 UserDereferenceObject(Class->spicnSm);
2177 }
2178 else
2179 {
2180 Ret = 0;
2181 }
2182
2183 if (NewIconFromCache)
2184 Class->CSF_flags |= CSF_CACHEDSMICON;
2185 else
2186 Class->CSF_flags &= ~CSF_CACHEDSMICON;
2187 Class->spicnSm = NewSmallIcon;
2188
2189 /* Update the clones */
2190 Class = Class->pclsClone;
2191 while (Class != NULL)
2192 {
2193 if (Class->spicnSm)
2194 UserDereferenceObject(Class->spicnSm);
2195 if (NewSmallIcon)
2196 UserReferenceObject(NewSmallIcon);
2197 if (NewIconFromCache)
2198 Class->CSF_flags |= CSF_CACHEDSMICON;
2199 else
2200 Class->CSF_flags &= ~CSF_CACHEDSMICON;
2201 Class->spicnSm = NewSmallIcon;
2202 Class = Class->pclsNext;
2203 }
2204 }
2205 break;
2206
2207 case GCLP_HMODULE:
2208 Ret = (ULONG_PTR)Class->hModule;
2209 Class->hModule = (HINSTANCE)NewLong;
2210
2211 /* Update the clones */
2212 Class = Class->pclsClone;
2213 while (Class != NULL)
2214 {
2215 Class->hModule = (HINSTANCE)NewLong;
2216 Class = Class->pclsNext;
2217 }
2218 break;
2219
2220 case GCLP_MENUNAME:
2221 {
2223
2225 Value))
2226 {
2227 ERR("Setting the class menu name failed!\n");
2228 }
2229
2230 /* FIXME: Really return NULL? Wine does so... */
2231 break;
2232 }
2233
2234 case GCL_STYLE:
2235 Ret = (ULONG_PTR)Class->style;
2236 Class->style = (UINT)NewLong;
2237
2238 /* FIXME: What if the CS_GLOBALCLASS style is changed? should we
2239 move the class to the appropriate list? For now, we save
2240 the original value in Class->Global, so we can always
2241 locate the appropriate list */
2242
2243 /* Update the clones */
2244 Class = Class->pclsClone;
2245 while (Class != NULL)
2246 {
2247 Class->style = (UINT)NewLong;
2248 Class = Class->pclsNext;
2249 }
2250 break;
2251
2252 case GCLP_WNDPROC:
2254 (WNDPROC)NewLong,
2255 Ansi);
2256 break;
2257
2258 case GCW_ATOM:
2259 {
2261
2262 Ret = (ULONG_PTR)Class->atomNVClassName;
2264 Value))
2265 {
2266 Ret = 0;
2267 }
2268 break;
2269 }
2270
2271 default:
2273 break;
2274 }
2275
2276 return Ret;
2277}
unsigned char BOOLEAN
UNICODE_STRING * PUNICODE_STRING
Definition: env_spec_w32.h:373
#define CURSORF_LRSHARED
Definition: ntuser.h:1201
#define CURSORF_FROMRESOURCE
Definition: ntuser.h:1199
#define INT
Definition: polytest.cpp:20
ULONG CURSORF_flags
Definition: cursoricon.h:16
HANDLE HINSTANCE
Definition: typedefs.h:77
HANDLE FASTCALL co_IntCopyImage(HANDLE hnd, UINT type, INT desiredx, INT desiredy, UINT flags)
Definition: callback.c:985
static BOOL IntSetClassMenuName(IN PCLS Class, IN PUNICODE_STRING MenuName)
Definition: class.c:1767
static BOOL IntSetClassAtom(IN OUT PCLS Class, IN PUNICODE_STRING ClassName)
Definition: class.c:450
static ULONG_PTR IntGetSetClassLongPtr(PCLS Class, ULONG Index, ULONG_PTR NewValue, ULONG Size)
Definition: class.c:1872
static WNDPROC FASTCALL IntSetClassWndProc(IN OUT PCLS Class, IN WNDPROC WndProc, IN BOOL Ansi)
Definition: class.c:548
LONG NTAPI UserGetSystemMetrics(ULONG Index)
Definition: metric.c:214
HICON HCURSOR
Definition: windef.h:299
#define ERROR_INVALID_INDEX
Definition: winerror.h:894
#define ERROR_INVALID_CURSOR_HANDLE
Definition: winerror.h:883
#define ERROR_INVALID_ICON_HANDLE
Definition: winerror.h:895
#define GCLP_HMODULE
Definition: winuser.h:676
#define IMAGE_ICON
Definition: winuser.h:212
#define LR_COPYFROMRESOURCE
Definition: winuser.h:1102
#define GCLP_WNDPROC
Definition: winuser.h:678
#define SM_CYSMICON
Definition: winuser.h:1016
#define GCLP_HCURSOR
Definition: winuser.h:673
#define GCL_CBWNDEXTRA
Definition: winuser.h:663
#define SM_CXSMICON
Definition: winuser.h:1015
#define GCLP_HBRBACKGROUND
Definition: winuser.h:672
#define GCL_STYLE
Definition: winuser.h:670
#define GCL_CBCLSEXTRA
Definition: winuser.h:662

Referenced by IntNtUserSetClassLongPtr().

◆ UserUnregisterClass()

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

Definition at line 1591 of file class.c.

1594{
1595 PCLS *Link;
1597 RTL_ATOM ClassAtom;
1598 PCLS Class;
1599
1601
1602 TRACE("UserUnregisterClass(%wZ, 0x%p)\n", ClassName, hInstance);
1603
1604 /* NOTE: Accessing the buffer in ClassName may raise an exception! */
1605 ClassAtom = IntGetClassAtom(ClassName,
1606 hInstance,
1607 pi,
1608 &Class,
1609 &Link);
1610 if (ClassAtom == (RTL_ATOM)0)
1611 {
1613 TRACE("UserUnregisterClass: No Class found.\n");
1614 return FALSE;
1615 }
1616
1617 ASSERT(Class != NULL);
1618
1619 if (Class->cWndReferenceCount != 0 ||
1620 Class->pclsClone != NULL)
1621 {
1622 TRACE("UserUnregisterClass: Class has a Window. Ct %u : Clone 0x%p\n", Class->cWndReferenceCount, Class->pclsClone);
1624 return FALSE;
1625 }
1626
1627 /* Must be a base class! */
1628 ASSERT(Class->pclsBase == Class);
1629
1630 /* Unlink the class */
1631 *Link = Class->pclsNext;
1632
1633 if (NT_SUCCESS(IntDeregisterClassAtom(Class->atomClassName)))
1634 {
1635 TRACE("Class 0x%p\n", Class);
1636 TRACE("UserUnregisterClass: Good Exit!\n");
1637 Class->atomClassName = 0; // Don't let it linger...
1638 /* Finally free the resources */
1640 return TRUE;
1641 }
1642 ERR("UserUnregisterClass: Can not deregister Class Atom.\n");
1643 return FALSE;
1644}
#define ERROR_CLASS_HAS_WINDOWS
Definition: winerror.h:893

Referenced by NtUserUnregisterClass().

Variable Documentation

◆ ClsId

int ClsId

Definition at line 109 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",
}

Definition at line 14 of file class.c.

Referenced by RegisterControlAtoms().

◆ DefaultServerClasses

REGISTER_SYSCLASS DefaultServerClasses[]

Definition at line 37 of file class.c.

Referenced by UserRegisterSystemClasses().

◆ FnId

int FnId

Definition at line 108 of file class.c.

Referenced by LookupFnIdToiCls().

◆ 

struct { ... } FnidToiCls[]
Initial value:
=
{
{ FNID_MESSAGEWND, ICLS_HWNDMESSAGE},
}
#define ICLS_IME
Definition: ntuser.h:927
#define ICLS_DIALOG
Definition: ntuser.h:930
#define ICLS_LISTBOX
Definition: ntuser.h:915
#define ICLS_EDIT
Definition: ntuser.h:913
#define ICLS_GHOST
Definition: ntuser.h:928
#define ICLS_COMBOBOX
Definition: ntuser.h:917
#define ICLS_STATIC
Definition: ntuser.h:914
#define FNID_SCROLLBAR
Definition: ntuser.h:859
#define FNID_ICONTITLE
Definition: ntuser.h:860
#define FNID_DESKTOP
Definition: ntuser.h:862
#define FNID_LISTBOX
Definition: ntuser.h:871
#define ICLS_ICONTITLE
Definition: ntuser.h:933
#define FNID_COMBOBOX
Definition: ntuser.h:867
#define ICLS_SCROLLBAR
Definition: ntuser.h:916
#define FNID_DIALOG
Definition: ntuser.h:869
#define ICLS_MENU
Definition: ntuser.h:931
#define ICLS_COMBOLBOX
Definition: ntuser.h:919
#define ICLS_SWITCH
Definition: ntuser.h:932
#define FNID_STATIC
Definition: ntuser.h:873
#define FNID_EDIT
Definition: ntuser.h:870
#define ICLS_BUTTON
Definition: ntuser.h:912
#define FNID_IME
Definition: ntuser.h:874
#define FNID_MENU
Definition: ntuser.h:861
#define ICLS_TOOLTIPS
Definition: ntuser.h:934
#define ICLS_MDICLIENT
Definition: ntuser.h:918
#define FNID_MESSAGEWND
Definition: ntuser.h:864
#define FNID_COMBOLBOX
Definition: ntuser.h:868
#define FNID_TOOLTIPS
Definition: ntuser.h:888
#define FNID_MDICLIENT
Definition: ntuser.h:872

Referenced by LookupFnIdToiCls().