ReactOS 0.4.15-dev-7196-g0fe0b40
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 1292 of file class.c.

1298{
1299 BOOL Ret = FALSE;
1300
1301 if (ClassName->Length != 0)
1302 {
1303 WCHAR szBuf[65];
1304 PWSTR AtomName = szBuf;
1306
1307 *Atom = 0;
1308
1309 /* NOTE: Caller has to protect the call with SEH! */
1310 if (ClassName->Length + sizeof(UNICODE_NULL) > sizeof(szBuf))
1311 {
1313 ClassName->Length + sizeof(UNICODE_NULL),
1314 TAG_USTR);
1315 if (AtomName == NULL)
1316 {
1318 return FALSE;
1319 }
1320 }
1321
1322 _SEH2_TRY
1323 {
1324 RtlCopyMemory(AtomName,
1325 ClassName->Buffer,
1326 ClassName->Length);
1327 }
1329 {
1330 if (AtomName != szBuf)
1331 ExFreePoolWithTag(AtomName, TAG_USTR);
1333 _SEH2_YIELD(return FALSE);
1334 }
1335 _SEH2_END;
1336 AtomName[ClassName->Length / sizeof(WCHAR)] = UNICODE_NULL;
1337
1338 /* Lookup the atom */
1340
1341 if (AtomName != szBuf)
1342 ExFreePoolWithTag(AtomName, TAG_USTR);
1343
1344 if (NT_SUCCESS(Status))
1345 {
1346 Ret = TRUE;
1347 }
1348 else
1349 {
1351 {
1353 }
1354 }
1355 }
1356 else
1357 {
1358 ASSERT(IS_ATOM(ClassName->Buffer));
1359 *Atom = (RTL_ATOM)((ULONG_PTR)ClassName->Buffer);
1360 Ret = TRUE;
1361 }
1362
1363 return Ret;
1364}
LONG NTSTATUS
Definition: precomp.h:26
_Out_ RTL_ATOM * Atom
Definition: class.h:54
#define IS_ATOM(x)
Definition: class.h:3
#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:32
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PagedPool
Definition: env_spec_w32.h:308
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
unsigned int BOOL
Definition: ntddk_ex.h:94
Status
Definition: gdiplustypes.h:25
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define ASSERT(a)
Definition: mode.c:44
#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:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
#define TAG_USTR
Definition: tag.h:145
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(NTSTATUS Status)
Definition: error.c:37
PRTL_ATOM_TABLE gAtomTable
Definition: session.c:13
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:28
__wchar_t WCHAR
Definition: xmlstorage.h:180

◆ DBG_DEFAULT_CHANNEL()

DBG_DEFAULT_CHANNEL ( UserClass  )

◆ DestroyProcessClasses()

void FASTCALL DestroyProcessClasses ( PPROCESSINFO  Process)

Definition at line 303 of file class.c.

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

Referenced by ExitThreadCallback().

◆ IntCheckDesktopClasses()

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

Definition at line 946 of file class.c.

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

Referenced by IntCheckProcessDesktopClasses().

◆ IntCheckProcessDesktopClasses()

BOOL IntCheckProcessDesktopClasses ( IN PDESKTOP  Desktop,
IN BOOL  FreeOnFailure 
)

Definition at line 1015 of file class.c.

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

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

1053{
1054 SIZE_T ClassSize;
1055 PCLS Class = NULL;
1056 RTL_ATOM Atom, verAtom;
1058 PWSTR pszMenuName = NULL;
1060
1061 TRACE("lpwcx=%p ClassName=%wZ MenuName=%wZ dwFlags=%08x Desktop=%p pi=%p\n",
1062 lpwcx, ClassName, MenuName, dwFlags, Desktop, pi);
1063
1064 if (!IntRegisterClassAtom(ClassName,
1065 &Atom))
1066 {
1067 ERR("Failed to register class atom!\n");
1068 return NULL;
1069 }
1070
1071 if (!IntRegisterClassAtom(ClassVersion,
1072 &verAtom))
1073 {
1074 ERR("Failed to register version class atom!\n");
1076 return NULL;
1077 }
1078
1079 ClassSize = sizeof(*Class) + lpwcx->cbClsExtra;
1080 if (MenuName->Length != 0)
1081 {
1082 pszMenuName = UserHeapAlloc(MenuName->Length + sizeof(UNICODE_NULL) +
1083 RtlUnicodeStringToAnsiSize(MenuName));
1084 if (pszMenuName == NULL)
1085 goto NoMem;
1086 }
1087
1088 if (Desktop != NULL)
1089 {
1091 ClassSize);
1092 }
1093 else
1094 {
1095 /* FIXME: The class was created before being connected
1096 to a desktop. It is possible for the desktop window,
1097 but should it be allowed for any other case? */
1098 TRACE("This CLASS has no Desktop to heap from! Atom %u\n",Atom);
1099 Class = UserHeapAlloc(ClassSize);
1100 }
1101
1102 if (Class != NULL)
1103 {
1104 int iCls = 0;
1105
1106 RtlZeroMemory(Class, ClassSize);
1107
1108 Class->rpdeskParent = Desktop;
1109 Class->pclsBase = Class;
1110 Class->atomClassName = verAtom;
1111 Class->atomNVClassName = Atom;
1112 Class->fnid = fnID;
1113 Class->CSF_flags = dwFlags;
1114
1115 if (LookupFnIdToiCls(Class->fnid, &iCls) && gpsi->atomSysClass[iCls] == 0)
1116 {
1117 gpsi->atomSysClass[iCls] = Class->atomClassName;
1118 }
1119
1120 _SEH2_TRY
1121 {
1122 PWSTR pszMenuNameBuffer = pszMenuName;
1123
1124 /* Need to protect with SEH since accessing the WNDCLASSEX structure
1125 and string buffers might raise an exception! We don't want to
1126 leak memory... */
1127 // What?! If the user interface was written correctly this would not be an issue!
1128 Class->lpfnWndProc = lpwcx->lpfnWndProc;
1129 Class->style = lpwcx->style;
1130 Class->cbclsExtra = lpwcx->cbClsExtra;
1131 Class->cbwndExtra = lpwcx->cbWndExtra;
1132 Class->hModule = lpwcx->hInstance;
1133 Class->spicn = lpwcx->hIcon ? UserGetCurIconObject(lpwcx->hIcon) : NULL;
1134 Class->spcur = lpwcx->hCursor ? UserGetCurIconObject(lpwcx->hCursor) : NULL;
1135 Class->spicnSm = lpwcx->hIconSm ? UserGetCurIconObject(lpwcx->hIconSm) : NULL;
1137 Class->hbrBackground = lpwcx->hbrBackground;
1138
1139 /* Make a copy of the string */
1140 if (pszMenuNameBuffer != NULL)
1141 {
1142 Class->MenuNameIsString = TRUE;
1143
1144 Class->lpszClientUnicodeMenuName = pszMenuNameBuffer;
1145 RtlCopyMemory(Class->lpszClientUnicodeMenuName,
1146 MenuName->Buffer,
1147 MenuName->Length);
1148 Class->lpszClientUnicodeMenuName[MenuName->Length / sizeof(WCHAR)] = UNICODE_NULL;
1149
1150 pszMenuNameBuffer += (MenuName->Length / sizeof(WCHAR)) + 1;
1151 }
1152 else
1153 Class->lpszClientUnicodeMenuName = MenuName->Buffer;
1154
1155 /* Save an ANSI copy of the string */
1156 if (pszMenuNameBuffer != NULL)
1157 {
1159
1160 Class->lpszClientAnsiMenuName = (PSTR)pszMenuNameBuffer;
1161 AnsiString.MaximumLength = (USHORT)RtlUnicodeStringToAnsiSize(MenuName);
1162 AnsiString.Buffer = Class->lpszClientAnsiMenuName;
1164 MenuName,
1165 FALSE);
1166 if (!NT_SUCCESS(Status))
1167 {
1168 ERR("Failed to convert unicode menu name to ansi!\n");
1169
1170 /* Life would've been much prettier if ntoskrnl exported RtlRaiseStatus()... */
1172 }
1173 }
1174 else
1175 Class->lpszClientAnsiMenuName = (PSTR)MenuName->Buffer;
1176
1177 /* Save kernel use menu name and ansi class name */
1178 Class->lpszMenuName = Class->lpszClientUnicodeMenuName; // FIXME!
1179 //Class->lpszAnsiClassName = FIXME
1180
1181 /* Server Side overrides class calling type (A/W)!
1182 User32 whine test_builtinproc: "deftest"
1183 built-in winproc - window A/W type automatically detected */
1184 if (!(Class->CSF_flags & CSF_SERVERSIDEPROC))
1185 {
1186 int i;
1187 WndProc = NULL;
1188 /* Due to the wine class "deftest" and most likely no FNID to reference
1189 from, sort through the Server Side list and compare proc addresses
1190 for match. This method will be used in related code.
1191 */
1192 for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
1193 { // Open ANSI or Unicode, just match, set and break.
1194 if (GETPFNCLIENTW(i) == Class->lpfnWndProc)
1195 {
1197 break;
1198 }
1199 if (GETPFNCLIENTA(i) == Class->lpfnWndProc)
1200 {
1202 break;
1203 }
1204 }
1205 if (WndProc)
1206 { // If a hit, we are Server Side so set the right flags and proc.
1207 Class->CSF_flags |= CSF_SERVERSIDEPROC;
1208 Class->CSF_flags &= ~CSF_ANSIPROC;
1209 Class->lpfnWndProc = WndProc;
1210 }
1211 }
1212
1213 if (!(Class->CSF_flags & CSF_ANSIPROC))
1214 Class->Unicode = TRUE;
1215
1216 if (Class->style & CS_GLOBALCLASS)
1217 Class->Global = TRUE;
1218 }
1220 {
1222 }
1223 _SEH2_END;
1224
1225 if (!NT_SUCCESS(Status))
1226 {
1227 ERR("Failed creating the class: 0x%x\n", Status);
1228
1230
1231 if (pszMenuName != NULL)
1232 UserHeapFree(pszMenuName);
1233
1235 Class);
1236 Class = NULL;
1237
1238 IntDeregisterClassAtom(verAtom);
1240 }
1241 }
1242 else
1243 {
1244NoMem:
1245 ERR("Failed to allocate class on Desktop 0x%p\n", Desktop);
1246
1247 if (pszMenuName != NULL)
1248 UserHeapFree(pszMenuName);
1249
1251 IntDeregisterClassAtom(verAtom);
1252
1254 }
1255
1256 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",
1257 Class, ClassName, Class ? Class->lpfnWndProc : NULL, Atom, verAtom,
1258 Class ? Class->hModule : NULL , Class ? Class->Global : 0);
1259
1260 return Class;
1261}
PSERVERINFO gpsi
Definition: imm.c:18
@ AnsiString
Definition: dnslib.h:19
#define _SEH2_LEAVE
Definition: filesup.c:20
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:864
#define GETPFNCLIENTW(fnid)
Definition: ntuser.h:905
#define GETPFNCLIENTA(fnid)
Definition: ntuser.h:903
#define CSF_ANSIPROC
Definition: ntuser.h:556
#define FNID_FIRST
Definition: ntuser.h:857
#define GETPFNSERVER(fnid)
Definition: ntuser.h:908
#define CSF_SERVERSIDEPROC
Definition: ntuser.h:555
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 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:1059
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:337
static NTSTATUS IntDeregisterClassAtom(IN RTL_ATOM Atom)
Definition: class.c:419
BOOL FASTCALL LookupFnIdToiCls(int FnId, int *iCls)
Definition: class.c:131
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:2905
#define RtlUnicodeStringToAnsiSize(String)
Definition: rtlfuncs.h:1005

Referenced by UserRegisterClass(), and UserRegisterSystemClasses().

◆ IntDereferenceClass()

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

Definition at line 818 of file class.c.

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

Referenced by co_UserCreateWindowEx(), and co_UserFreeWindow().

◆ IntDeregisterClassAtom()

static NTSTATUS IntDeregisterClassAtom ( IN RTL_ATOM  Atom)
static

Definition at line 419 of file class.c.

420{
422 Atom);
423}
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 231 of file class.c.

232{
233 PDESKTOP pDesk;
234
235 /* There shouldn't be any clones anymore */
236 ASSERT(Class->cWndReferenceCount == 0);
237 ASSERT(Class->pclsClone == NULL);
238
239 if (Class->pclsBase == Class)
240 {
241 PCALLPROCDATA CallProc, NextCallProc;
242
243 /* Destroy allocated callproc handles */
244 CallProc = Class->spcpdFirst;
245 while (CallProc != NULL)
246 {
247 NextCallProc = CallProc->spcpdNext;
248
249 CallProc->spcpdNext = NULL;
250 DestroyCallProc(CallProc);
251
252 CallProc = NextCallProc;
253 }
254
255 // Fixes running the static test then run class test issue.
256 // Some applications do not use UnregisterClass before exiting.
257 // Keep from reusing the same atom with case insensitive
258 // comparisons, remove registration of the atom if not zeroed.
259 if (Class->atomClassName)
260 IntDeregisterClassAtom(Class->atomClassName);
261 // Dereference non-versioned class name
262 if (Class->atomNVClassName)
263 IntDeregisterClassAtom(Class->atomNVClassName);
264
265 if (Class->pdce)
266 {
267 DceFreeClassDCE(Class->pdce);
268 Class->pdce = NULL;
269 }
270
272 }
273
274 if (Class->spicn)
276 if (Class->spcur)
278 if (Class->spicnSm)
279 {
281 /* Destroy the icon if we own it */
282 if ((Class->CSF_flags & CSF_CACHEDSMICON)
285 }
286
287 pDesk = Class->rpdeskParent;
288 Class->rpdeskParent = NULL;
289
290 /* Free the structure */
291 if (pDesk != NULL)
292 {
293 DesktopHeapFree(pDesk, Class);
294 }
295 else
296 {
298 }
299}
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:561
struct _CALLPROCDATA * spcpdNext
Definition: ntuser.h:550
static VOID IntFreeClassMenuName(IN OUT PCLS Class)
Definition: class.c:219
BOOLEAN IntDestroyCurIconObject(_In_ PVOID Object)
Definition: cursoricon.c:313
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 1264 of file class.c.

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

Referenced by IntGetClassAtom(), and UserRegisterClass().

◆ IntFreeClassMenuName()

static VOID IntFreeClassMenuName ( IN OUT PCLS  Class)
static

Definition at line 219 of file class.c.

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

Referenced by IntDestroyClass(), and IntSetClassMenuName().

◆ IntGetAndReferenceClass()

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

Definition at line 1440 of file class.c.

1441{
1442 PCLS *ClassLink, Class = NULL;
1443 RTL_ATOM ClassAtom;
1444 PTHREADINFO pti;
1445
1446 if (bDesktopThread)
1447 pti = gptiDesktopThread;
1448 else
1450
1451 if ( !(pti->ppi->W32PF_flags & W32PF_CLASSESREGISTERED ))
1452 {
1454 }
1455
1456 /* Check the class. */
1457
1458 TRACE("Finding Class %wZ for hInstance 0x%p\n", ClassName, hInstance);
1459
1460 ClassAtom = IntGetClassAtom(ClassName,
1461 hInstance,
1462 pti->ppi,
1463 &Class,
1464 &ClassLink);
1465
1466 if (ClassAtom == (RTL_ATOM)0)
1467 {
1468 if (IS_ATOM(ClassName->Buffer))
1469 {
1470 ERR("Class 0x%p not found\n", ClassName->Buffer);
1471 }
1472 else
1473 {
1474 ERR("Class \"%wZ\" not found\n", ClassName);
1475 }
1476
1477 return NULL;
1478 }
1479
1480 TRACE("Referencing Class 0x%p with atom 0x%x\n", Class, ClassAtom);
1482 ClassLink,
1483 pti->rpdesk);
1484 if (Class == NULL)
1485 {
1486 ERR("Failed to reference window class!\n");
1487 return NULL;
1488 }
1489
1490 return Class;
1491}
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:752
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:1367
BOOL FASTCALL UserRegisterSystemClasses(VOID)
Definition: class.c:2309
PTHREADINFO gptiDesktopThread
Definition: desktop.c:37

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

1373{
1374 RTL_ATOM Atom = (RTL_ATOM)0;
1375
1376 ASSERT(BaseClass != NULL);
1377
1378 if (IntGetAtomFromStringOrAtom(ClassName, &Atom) &&
1379 Atom != (RTL_ATOM)0)
1380 {
1381 PCLS Class;
1382
1383 /* Attempt to locate the class object */
1384
1385 ASSERT(pi != NULL);
1386
1387 /* Step 1: Try to find an exact match of locally registered classes */
1389 hInstance,
1390 &pi->pclsPrivateList,
1391 Link);
1392 if (Class != NULL)
1393 { TRACE("Step 1: 0x%p\n",Class );
1394 goto FoundClass;
1395 }
1396
1397 /* Step 2: Try to find any globally registered class. The hInstance
1398 is not relevant for global classes */
1400 NULL,
1401 &pi->pclsPublicList,
1402 Link);
1403 if (Class != NULL)
1404 { TRACE("Step 2: 0x%p 0x%p\n",Class, Class->hModule);
1405 goto FoundClass;
1406 }
1407
1408 /* Step 3: Try to find any local class registered by user32 */
1410 hModClient,
1411 &pi->pclsPrivateList,
1412 Link);
1413 if (Class != NULL)
1414 { TRACE("Step 3: 0x%p\n",Class );
1415 goto FoundClass;
1416 }
1417
1418 /* Step 4: Try to find any global class registered by user32 */
1420 hModClient,
1421 &pi->pclsPublicList,
1422 Link);
1423 if (Class == NULL)
1424 {
1425 return (RTL_ATOM)0;
1426 }else{TRACE("Step 4: 0x%p\n",Class );}
1427
1428FoundClass:
1429 *BaseClass = Class;
1430 }
1431 else
1432 {
1433 Atom = 0;
1434 }
1435
1436 return Atom;
1437}
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:1264

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

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

Referenced by IntReferenceClass().

◆ IntGetClassWndProc()

WNDPROC FASTCALL IntGetClassWndProc ( PCLS  Class,
BOOL  Ansi 
)

Definition at line 497 of file class.c.

498{
499 INT i;
500 WNDPROC gcpd = NULL, Ret = NULL;
501
502 if (Class->CSF_flags & CSF_SERVERSIDEPROC)
503 {
504 for ( i = FNID_FIRST; i <= FNID_SWITCH; i++)
505 {
506 if (GETPFNSERVER(i) == Class->lpfnWndProc)
507 {
508 if (Ansi)
509 Ret = GETPFNCLIENTA(i);
510 else
511 Ret = GETPFNCLIENTW(i);
512 }
513 }
514 return Ret;
515 }
516 Ret = Class->lpfnWndProc;
517
518 if (Class->fnid <= FNID_GHOST && Class->fnid >= FNID_BUTTON)
519 {
520 if (Ansi)
521 {
522 if (GETPFNCLIENTW(Class->fnid) == Class->lpfnWndProc)
523 Ret = GETPFNCLIENTA(Class->fnid);
524 }
525 else
526 {
527 if (GETPFNCLIENTA(Class->fnid) == Class->lpfnWndProc)
528 Ret = GETPFNCLIENTW(Class->fnid);
529 }
530 }
531
532 if ( Ret != Class->lpfnWndProc ||
533 Ansi == !!(Class->CSF_flags & CSF_ANSIPROC) )
534 return Ret;
535
536 gcpd = (WNDPROC)UserGetCPD( Class,
538 (ULONG_PTR)Ret);
539
540 return (gcpd ? gcpd : Ret);
541}
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:541
@ UserGetCPDU2A
Definition: ntuser.h:540
@ UserGetCPDA2U
Definition: ntuser.h:539
int32_t INT
Definition: typedefs.h:58

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

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

Referenced by IntDereferenceClass().

◆ IntMoveClassToSharedHeap()

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

Definition at line 900 of file class.c.

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

Referenced by IntCheckDesktopClasses().

◆ IntReferenceClass()

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

Definition at line 752 of file class.c.

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

Referenced by IntGetAndReferenceClass().

◆ IntRegisterClassAtom()

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

Definition at line 337 of file class.c.

339{
340 WCHAR szBuf[65];
341 PWSTR AtomName = szBuf;
343
344 if (ClassName->Length != 0)
345 {
346 if (ClassName->Length + sizeof(UNICODE_NULL) > sizeof(szBuf))
347 {
349 ClassName->Length + sizeof(UNICODE_NULL),
350 TAG_USTR);
351
352 if (AtomName == NULL)
353 {
355 return FALSE;
356 }
357 }
358
360 {
361 RtlCopyMemory(AtomName,
362 ClassName->Buffer,
363 ClassName->Length);
364 }
366 {
367 if (AtomName != szBuf)
368 ExFreePoolWithTag(AtomName, TAG_USTR);
370 _SEH2_YIELD(return FALSE);
371 }
372 _SEH2_END;
373 AtomName[ClassName->Length / sizeof(WCHAR)] = UNICODE_NULL;
374 }
375 else
376 {
377 ASSERT(IS_ATOM(ClassName->Buffer));
378 AtomName = ClassName->Buffer;
379 }
380
382 AtomName,
383 pAtom);
384
385 if (AtomName != ClassName->Buffer && AtomName != szBuf)
386 ExFreePoolWithTag(AtomName, TAG_USTR);
387
388
389 if (!NT_SUCCESS(Status))
390 {
392 return FALSE;
393 }
394
395 return TRUE;
396}
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 448 of file class.c.

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

Referenced by UserSetClassLongPtr().

◆ IntSetClassMenuName()

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

Definition at line 1757 of file class.c.

1759{
1760 BOOL Ret = FALSE;
1761
1762 /* Change the base class first */
1763 Class = Class->pclsBase;
1764
1765 if (MenuName->Length != 0)
1766 {
1768 PWSTR strBufW;
1769
1770 AnsiString.MaximumLength = (USHORT)RtlUnicodeStringToAnsiSize(MenuName);
1771
1772 strBufW = UserHeapAlloc(MenuName->Length + sizeof(UNICODE_NULL) +
1773 AnsiString.MaximumLength);
1774 if (strBufW != NULL)
1775 {
1776 _SEH2_TRY
1777 {
1779
1780 /* Copy the unicode string */
1781 RtlCopyMemory(strBufW,
1782 MenuName->Buffer,
1783 MenuName->Length);
1784 strBufW[MenuName->Length / sizeof(WCHAR)] = UNICODE_NULL;
1785
1786 /* Create an ANSI copy of the string */
1787 AnsiString.Buffer = (PSTR)(strBufW + (MenuName->Length / sizeof(WCHAR)) + 1);
1789 MenuName,
1790 FALSE);
1791 if (!NT_SUCCESS(Status))
1792 {
1795 }
1796
1797 Ret = TRUE;
1798 }
1800 {
1802 }
1803 _SEH2_END;
1804
1805 if (Ret)
1806 {
1807 /* Update the base class */
1809 Class->lpszClientUnicodeMenuName = strBufW;
1810 Class->lpszClientAnsiMenuName = AnsiString.Buffer;
1811 Class->MenuNameIsString = TRUE;
1812
1813 /* Update the clones */
1814 Class = Class->pclsClone;
1815 while (Class != NULL)
1816 {
1817 Class->lpszClientUnicodeMenuName = strBufW;
1818 Class->lpszClientAnsiMenuName = AnsiString.Buffer;
1819 Class->MenuNameIsString = TRUE;
1820
1821 Class = Class->pclsNext;
1822 }
1823 }
1824 else
1825 {
1826 ERR("Failed to copy class menu name!\n");
1827 UserHeapFree(strBufW);
1828 }
1829 }
1830 else
1832 }
1833 else
1834 {
1835 ASSERT(IS_INTRESOURCE(MenuName->Buffer));
1836
1837 /* Update the base class */
1839 Class->lpszClientUnicodeMenuName = MenuName->Buffer;
1840 Class->lpszClientAnsiMenuName = (PSTR)MenuName->Buffer;
1841 Class->MenuNameIsString = FALSE;
1842
1843 /* Update the clones */
1844 Class = Class->pclsClone;
1845 while (Class != NULL)
1846 {
1847 Class->lpszClientUnicodeMenuName = MenuName->Buffer;
1848 Class->lpszClientAnsiMenuName = (PSTR)MenuName->Buffer;
1849 Class->MenuNameIsString = FALSE;
1850
1851 Class = Class->pclsNext;
1852 }
1853
1854 Ret = TRUE;
1855 }
1856
1857 return Ret;
1858}
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
#define IS_INTRESOURCE(i)
Definition: winuser.h:580

Referenced by UserSetClassLongPtr().

◆ IntSetClassWndProc()

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

Definition at line 546 of file class.c.

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

2729{
2730 UNICODE_STRING SafeClassName;
2731 WNDCLASSEXW Safewcexw;
2732 PCLS Class;
2733 RTL_ATOM ClassAtom = 0;
2734 PPROCESSINFO ppi;
2735 BOOL Ret = TRUE;
2737
2738 _SEH2_TRY
2739 {
2740 ProbeForWrite( lpWndClassEx, sizeof(WNDCLASSEXW), sizeof(ULONG));
2741 RtlCopyMemory( &Safewcexw, lpWndClassEx, sizeof(WNDCLASSEXW));
2742 if (ppszMenuName)
2743 {
2744 ProbeForWrite(ppszMenuName, sizeof(*ppszMenuName), sizeof(PVOID));
2745 }
2746 }
2748 {
2750 _SEH2_YIELD(return FALSE);
2751 }
2752 _SEH2_END;
2753
2754 Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassName);
2755 if (!NT_SUCCESS(Status))
2756 {
2757 ERR("Error capturing the class name\n");
2759 return FALSE;
2760 }
2761
2762 // If null instance use client.
2764
2765 TRACE("GetClassInfo(%wZ, %p)\n", &SafeClassName, hInstance);
2766
2767 /* NOTE: Need exclusive lock because getting the wndproc might require the
2768 creation of a call procedure handle */
2770
2771 ppi = GetW32ProcessInfo();
2772 if (!(ppi->W32PF_flags & W32PF_CLASSESREGISTERED))
2773 {
2775 }
2776
2777 ClassAtom = IntGetClassAtom(&SafeClassName,
2778 hInstance,
2779 ppi,
2780 &Class,
2781 NULL);
2782 if (ClassAtom != (RTL_ATOM)0)
2783 {
2784 ClassAtom = Class->atomNVClassName;
2785 Ret = UserGetClassInfo(Class, &Safewcexw, bAnsi, hInstance);
2786 }
2787 else
2788 {
2790 Ret = FALSE;
2791 }
2792
2793 UserLeave();
2794
2795 if (Ret)
2796 {
2797 _SEH2_TRY
2798 {
2799 /* Emulate Function. */
2800 if (ppszMenuName) *ppszMenuName = (LPWSTR)Safewcexw.lpszMenuName;
2801
2802 RtlCopyMemory(lpWndClassEx, &Safewcexw, sizeof(WNDCLASSEXW));
2803
2804 // From Wine:
2805 /* We must return the atom of the class here instead of just TRUE. */
2806 /* Undocumented behavior! Return the class atom as a BOOL! */
2807 Ret = (BOOL)ClassAtom;
2808 }
2810 {
2812 Ret = FALSE;
2813 }
2814 _SEH2_END;
2815 }
2816
2817 if (!IS_ATOM(SafeClassName.Buffer))
2818 ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING);
2819
2820 return Ret;
2821}
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define BOOL
Definition: nt_native.h:43
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:251
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:242
#define TAG_STRING
Definition: oslist.h:22
LPCWSTR lpszMenuName
Definition: winuser.h:3224
uint32_t ULONG
Definition: typedefs.h:59
static BOOL UserGetClassInfo(IN PCLS Class, OUT PWNDCLASSEXW lpwcx, IN BOOL Ansi, HINSTANCE hInstance)
Definition: class.c:2252
_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
#define ERROR_CLASS_DOES_NOT_EXIST
Definition: winerror.h:892
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 2825 of file class.c.

2828{
2829 PWND Window;
2830 UNICODE_STRING CapturedClassName;
2831 INT iCls, Ret = 0;
2832 RTL_ATOM Atom = 0;
2833
2835
2837 if (Window != NULL)
2838 {
2839 if (Real && Window->fnid && !(Window->fnid & FNID_DESTROY))
2840 {
2841 if (LookupFnIdToiCls(Window->fnid, &iCls))
2842 {
2843 Atom = gpsi->atomSysClass[iCls];
2844 }
2845 }
2846
2847 _SEH2_TRY
2848 {
2849 ProbeForWriteUnicodeString(ClassName);
2850 CapturedClassName = *ClassName;
2851 if (CapturedClassName.Length != 0)
2852 {
2853 ProbeForRead(CapturedClassName.Buffer,
2854 CapturedClassName.Length,
2855 sizeof(WCHAR));
2856 }
2857
2858 /* Get the class name */
2859 Ret = UserGetClassName(Window->pcls,
2860 &CapturedClassName,
2861 Atom,
2862 FALSE);
2863
2864 if (Ret != 0)
2865 {
2866 /* Update the Length field */
2867 ClassName->Length = CapturedClassName.Length;
2868 }
2869 }
2871 {
2873 }
2874 _SEH2_END;
2875 }
2876
2877 UserLeave();
2878
2879 return Ret;
2880}
HWND hWnd
Definition: settings.c:17
float Real
Definition: definitions.h:36
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
#define FNID_DESTROY
Definition: ntuser.h:897
VOID FASTCALL UserEnterShared(VOID)
Definition: ntuser.c:235
#define ProbeForWriteUnicodeString(Ptr)
Definition: probe.h:48
Definition: window.c:28
Definition: ntuser.h:693
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:122
INT UserGetClassName(IN PCLS Class, IN OUT PUNICODE_STRING ClassName, IN RTL_ATOM Atom, IN BOOL Ansi)
Definition: class.c:1637

Referenced by GetClassNameW(), and RealGetWindowClassW().

◆ NtUserGetWOWClass()

PCLS APIENTRY NtUserGetWOWClass ( HINSTANCE  hInstance,
PUNICODE_STRING  ClassName 
)

Definition at line 2885 of file class.c.

2888{
2889 UNICODE_STRING SafeClassName;
2891 PCLS Class = NULL;
2892 RTL_ATOM ClassAtom = 0;
2894
2895 Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassName);
2896 if (!NT_SUCCESS(Status))
2897 {
2898 ERR("Error capturing the class name\n");
2900 return FALSE;
2901 }
2902
2904
2906
2907 ClassAtom = IntGetClassAtom(&SafeClassName,
2908 hInstance,
2909 pi,
2910 &Class,
2911 NULL);
2912 if (!ClassAtom)
2913 {
2915 }
2916
2917
2918 if (SafeClassName.Buffer && !IS_ATOM(SafeClassName.Buffer))
2919 ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING);
2920
2921 UserLeave();
2922//
2923// Don't forget to use DesktopPtrToUser( ? ) with return pointer in user space.
2924//
2925 return Class;
2926}

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

2434{
2435 WNDCLASSEXW CapturedClassInfo = {0};
2436 UNICODE_STRING CapturedName = {0}, CapturedMenuName = {0}, CapturedVersion = {0};
2437 RTL_ATOM Ret = (RTL_ATOM)0;
2439 BOOL Exception = FALSE;
2440
2441 if (Flags & ~(CSF_ANSIPROC))
2442 {
2443 ERR("NtUserRegisterClassExWOW Bad Flags!\n");
2445 return Ret;
2446 }
2447
2449
2450 TRACE("NtUserRegisterClassExWOW ClsN %wZ\n",ClassName);
2451
2452 if ( !(ppi->W32PF_flags & W32PF_CLASSESREGISTERED ))
2453 {
2455 }
2456
2457 _SEH2_TRY
2458 {
2459 /* Probe the parameters and basic parameter checks */
2460 if (ProbeForReadUint(&lpwcx->cbSize) != sizeof(WNDCLASSEXW))
2461 {
2462 ERR("NtUserRegisterClassExWOW Wrong cbSize!\n");
2463 goto InvalidParameter;
2464 }
2465
2466 ProbeForRead(lpwcx,
2467 sizeof(WNDCLASSEXW),
2468 sizeof(ULONG));
2469 RtlCopyMemory(&CapturedClassInfo,
2470 lpwcx,
2471 sizeof(WNDCLASSEXW));
2472
2473 CapturedName = ProbeForReadUnicodeString(ClassName);
2474 CapturedVersion = ProbeForReadUnicodeString(ClsVersion);
2475
2476 ProbeForRead(pClassMenuName,
2477 sizeof(CLSMENUNAME),
2478 1);
2479
2480 CapturedMenuName = ProbeForReadUnicodeString(pClassMenuName->pusMenuName);
2481
2482 if ( (CapturedName.Length & 1) ||
2483 (CapturedMenuName.Length & 1) ||
2484 (CapturedClassInfo.cbClsExtra < 0) ||
2485 ((CapturedClassInfo.cbClsExtra + CapturedName.Length +
2486 CapturedMenuName.Length + sizeof(CLS))
2487 < (ULONG)CapturedClassInfo.cbClsExtra) ||
2488 (CapturedClassInfo.cbWndExtra < 0) ||
2489 (CapturedClassInfo.hInstance == NULL) )
2490 {
2491 ERR("NtUserRegisterClassExWOW Invalid Parameter Error!\n");
2492 goto InvalidParameter;
2493 }
2494
2495 if (CapturedName.Length != 0)
2496 {
2497 ProbeForRead(CapturedName.Buffer,
2498 CapturedName.Length,
2499 sizeof(WCHAR));
2500 }
2501 else
2502 {
2503 if (!IS_ATOM(CapturedName.Buffer))
2504 {
2505 ERR("NtUserRegisterClassExWOW ClassName Error!\n");
2506 goto InvalidParameter;
2507 }
2508 }
2509
2510 if (CapturedVersion.Length != 0)
2511 {
2512 ProbeForRead(CapturedVersion.Buffer,
2513 CapturedVersion.Length,
2514 sizeof(WCHAR));
2515 }
2516 else
2517 {
2518 if (!IS_ATOM(CapturedVersion.Buffer))
2519 {
2520 ERR("NtUserRegisterClassExWOW ClassName Error!\n");
2521 goto InvalidParameter;
2522 }
2523 }
2524
2525 if (CapturedMenuName.Length != 0)
2526 {
2527 ProbeForRead(CapturedMenuName.Buffer,
2528 CapturedMenuName.Length,
2529 sizeof(WCHAR));
2530 }
2531 else if (CapturedMenuName.Buffer != NULL &&
2532 !IS_INTRESOURCE(CapturedMenuName.Buffer))
2533 {
2534 ERR("NtUserRegisterClassExWOW MenuName Error!\n");
2538 }
2539
2540 if (IsCallProcHandle(lpwcx->lpfnWndProc))
2541 { // Never seen this yet, but I'm sure it's a little haxxy trick!
2542 // If this pops up we know what todo!
2543 ERR("NtUserRegisterClassExWOW WndProc is CallProc!!\n");
2544 }
2545
2546 TRACE("NtUserRegisterClassExWOW MnuN %wZ\n",&CapturedMenuName);
2547 }
2549 {
2550 ERR("NtUserRegisterClassExWOW Exception Error!\n");
2552 Exception = TRUE;
2553 }
2554 _SEH2_END;
2555
2556 if (!Exception)
2557 {
2558 /* Register the class */
2559 Ret = UserRegisterClass(&CapturedClassInfo,
2560 &CapturedName,
2561 &CapturedVersion,
2562 &CapturedMenuName,
2563 fnID,
2564 Flags);
2565 }
2566
2567 if (!Ret)
2568 {
2569 TRACE("NtUserRegisterClassExWOW Null Return!\n");
2570 }
2571
2572 UserLeave();
2573
2574 return Ret;
2575}
@ InvalidParameter
Definition: gdiplustypes.h:28
#define ProbeForReadUint(Ptr)
Definition: probe.h:67
#define ProbeForReadUnicodeString(Ptr)
Definition: probe.h:77
PUNICODE_STRING pusMenuName
Definition: ntuser.h:499
WNDPROC lpfnWndProc
Definition: winuser.h:3217
UINT cbSize
Definition: winuser.h:3215
int cbWndExtra
Definition: winuser.h:3219
HINSTANCE hInstance
Definition: winuser.h:3220
int cbClsExtra
Definition: winuser.h:3218
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:1494
#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 ( HWND  hWnd,
INT  Offset,
ULONG_PTR  dwNewLong,
BOOL  Ansi 
)

Definition at line 2578 of file class.c.

2582{
2584 PWND Window;
2585 ULONG_PTR Ret = 0;
2586
2588
2590
2592 if (Window != NULL)
2593 {
2594 if (Window->head.pti->ppi != pi)
2595 {
2597 goto Cleanup;
2598 }
2599
2600 _SEH2_TRY
2601 {
2603
2604 /* Probe the parameters */
2605 if (Offset == GCW_ATOM || Offset == GCLP_MENUNAME)
2606 {
2607 /* FIXME: Resource ID can be passed directly without UNICODE_STRING ? */
2608 if (IS_ATOM(dwNewLong))
2609 {
2610 Value.MaximumLength = 0;
2611 Value.Length = 0;
2612 Value.Buffer = (PWSTR)dwNewLong;
2613 }
2614 else
2615 {
2617 }
2618
2619 if (Value.Length & 1)
2620 {
2621 goto InvalidParameter;
2622 }
2623
2624 if (Value.Length != 0)
2625 {
2626 ProbeForRead(Value.Buffer,
2627 Value.Length,
2628 sizeof(WCHAR));
2629 }
2630 else
2631 {
2632 if (Offset == GCW_ATOM && !IS_ATOM(Value.Buffer))
2633 {
2634 goto InvalidParameter;
2635 }
2636 else if (Offset == GCLP_MENUNAME && !IS_INTRESOURCE(Value.Buffer))
2637 {
2641 }
2642 }
2643
2644 dwNewLong = (ULONG_PTR)&Value;
2645 }
2646
2647 Ret = UserSetClassLongPtr(Window->pcls,
2648 Offset,
2649 dwNewLong,
2650 Ansi);
2651 switch(Offset)
2652 {
2653 case GCLP_HICONSM:
2654 case GCLP_HICON:
2655 {
2656 if (Ret && Ret != dwNewLong)
2658 }
2659 }
2660 }
2662 {
2664 }
2665 _SEH2_END;
2666 }
2667
2668Cleanup:
2669 UserLeave();
2670
2671 return Ret;
2672}
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
static const WCHAR Cleanup[]
Definition: register.c:80
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
BOOL UserPaintCaption(PWND pWnd, INT Flags)
Definition: defwnd.c:398
USHORT MaximumLength
Definition: env_spec_w32.h:370
_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)
Definition: class.c:1861
#define GCLP_MENUNAME
Definition: winuser.h:677
#define GCLP_HICONSM
Definition: winuser.h:675
#define GCLP_HICON
Definition: winuser.h:674
#define DC_ICON
Definition: winuser.h:429
#define GCW_ATOM
Definition: winuser.h:661

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

◆ NtUserSetClassWord()

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

Definition at line 2676 of file class.c.

2680{
2681/*
2682 * NOTE: Obsoleted in 32-bit windows
2683 */
2684 return(0);
2685}

◆ NtUserUnregisterClass()

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

Definition at line 2689 of file class.c.

2693{
2694 UNICODE_STRING SafeClassName;
2696 BOOL Ret;
2697
2698 Status = ProbeAndCaptureUnicodeStringOrAtom(&SafeClassName, ClassNameOrAtom);
2699 if (!NT_SUCCESS(Status))
2700 {
2701 ERR("Error capturing the class name\n");
2703 return FALSE;
2704 }
2705
2707
2708 /* Unregister the class */
2709 Ret = UserUnregisterClass(&SafeClassName, hInstance, NULL); // Null for now~
2710
2711 UserLeave();
2712
2713 if (SafeClassName.Buffer && !IS_ATOM(SafeClassName.Buffer))
2714 ExFreePoolWithTag(SafeClassName.Buffer, TAG_STRING);
2715
2716 return Ret;
2717}
BOOL UserUnregisterClass(IN PUNICODE_STRING ClassName, IN HINSTANCE hInstance, OUT PCLSMENUNAME pClassMenuName)
Definition: class.c:1581

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 UNICODE_STRING ustrCopy;
156
157 /* Default to NULL */
158 RtlInitEmptyUnicodeString(pustrOut, NULL, 0);
159
161 {
162 ProbeForRead(pustrUnsafe, sizeof(UNICODE_STRING), 1);
163
164 ustrCopy = *pustrUnsafe;
165
166 /* Validate the string */
167 if ((ustrCopy.Length & 1) || (ustrCopy.Buffer == NULL))
168 {
169 /* This is not legal */
171 }
172
173 /* Check if this is an atom */
174 if (IS_ATOM(ustrCopy.Buffer))
175 {
176 /* Copy the atom, length is 0 */
177 pustrOut->MaximumLength = pustrOut->Length = 0;
178 pustrOut->Buffer = ustrCopy.Buffer;
179 }
180 else
181 {
182 /* Get the length, maximum length includes zero termination */
183 pustrOut->Length = ustrCopy.Length;
184 pustrOut->MaximumLength = pustrOut->Length + sizeof(WCHAR);
185
186 /* Allocate a buffer */
187 pustrOut->Buffer = ExAllocatePoolWithTag(PagedPool,
188 pustrOut->MaximumLength,
189 TAG_STRING);
190 if (!pustrOut->Buffer)
191 {
193 }
194
195 /* Copy the string and zero terminate it */
196 ProbeForRead(ustrCopy.Buffer, pustrOut->Length, 1);
197 RtlCopyMemory(pustrOut->Buffer, ustrCopy.Buffer, pustrOut->Length);
198 pustrOut->Buffer[pustrOut->Length / sizeof(WCHAR)] = L'\0';
199 }
200 }
202 {
203 /* Check if we already allocated a buffer */
204 if (pustrOut->Buffer)
205 {
206 /* Free the buffer */
207 ExFreePoolWithTag(pustrOut->Buffer, TAG_STRING);
209 }
210 }
211 _SEH2_END;
212
213 return Status;
214}
#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 399 of file class.c.

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

Referenced by InitUserAtoms().

◆ UserAddCallProcToClass()

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

Definition at line 426 of file class.c.

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

Referenced by IntCreateWindow().

◆ UserGetClassInfo()

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

Definition at line 2252 of file class.c.

2256{
2257 if (!Class) return FALSE;
2258
2259 lpwcx->style = Class->style;
2260
2261 // If fnId is set, clear the global bit. See wine class test check_style.
2262 if (Class->fnid)
2263 lpwcx->style &= ~CS_GLOBALCLASS;
2264
2265 lpwcx->lpfnWndProc = IntGetClassWndProc(Class, Ansi);
2266
2267 lpwcx->cbClsExtra = Class->cbclsExtra;
2268 lpwcx->cbWndExtra = Class->cbwndExtra;
2269 lpwcx->hIcon = Class->spicn ? UserHMGetHandle(Class->spicn) : NULL;
2270 lpwcx->hCursor = Class->spcur ? UserHMGetHandle(Class->spcur) : NULL;
2271 lpwcx->hIconSm = Class->spicnSm ? UserHMGetHandle(Class->spicnSm) : NULL;
2272 lpwcx->hbrBackground = Class->hbrBackground;
2273
2274 /* Copy non-string to user first. */
2275 if (Ansi)
2276 ((PWNDCLASSEXA)lpwcx)->lpszMenuName = Class->lpszClientAnsiMenuName;
2277 else
2278 lpwcx->lpszMenuName = Class->lpszClientUnicodeMenuName;
2279/*
2280 * FIXME: CLSMENUNAME has the answers! Copy the already made buffers from there!
2281 * Cls: lpszMenuName and lpszAnsiClassName should be used by kernel space.
2282 * lpszClientXxxMenuName should already be mapped to user space.
2283 */
2284 /* Copy string ptr to user. */
2285 if ( Class->lpszClientUnicodeMenuName != NULL &&
2286 Class->MenuNameIsString)
2287 {
2288 lpwcx->lpszMenuName = UserHeapAddressToUser(Ansi ?
2289 (PVOID)Class->lpszClientAnsiMenuName :
2290 (PVOID)Class->lpszClientUnicodeMenuName);
2291 }
2292
2293 if (hInstance == hModClient)
2294 lpwcx->hInstance = NULL;
2295 else
2296 lpwcx->hInstance = hInstance;
2297
2298 /* FIXME: Return the string? Okay! This is performed in User32! */
2299 //lpwcx->lpszClassName = (LPCWSTR)((ULONG_PTR)Class->atomClassName);
2300
2301 return TRUE;
2302}
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 1637 of file class.c.

1641{
1643 WCHAR szStaticTemp[32];
1644 PWSTR szTemp = NULL;
1645 ULONG BufLen = sizeof(szStaticTemp);
1646 INT Ret = 0;
1647
1648 /* Note: Accessing the buffer in ClassName may raise an exception! */
1649
1650 _SEH2_TRY
1651 {
1652 if (Ansi)
1653 {
1654 PANSI_STRING AnsiClassName = (PANSI_STRING)ClassName;
1655 UNICODE_STRING UnicodeClassName;
1656
1657 /* Limit the size of the static buffer on the stack to the
1658 size of the buffer provided by the caller */
1659 if (BufLen / sizeof(WCHAR) > AnsiClassName->MaximumLength)
1660 {
1661 BufLen = AnsiClassName->MaximumLength * sizeof(WCHAR);
1662 }
1663
1664 /* Find out how big the buffer needs to be */
1666 Class->atomClassName,
1667 NULL,
1668 NULL,
1669 szStaticTemp,
1670 &BufLen);
1672 {
1673 if (BufLen / sizeof(WCHAR) > AnsiClassName->MaximumLength)
1674 {
1675 /* The buffer required exceeds the ansi buffer provided,
1676 pretend like we're using the ansi buffer and limit the
1677 size to the buffer size provided */
1678 BufLen = AnsiClassName->MaximumLength * sizeof(WCHAR);
1679 }
1680
1681 /* Allocate a temporary buffer that can hold the unicode class name */
1683 BufLen,
1685 if (szTemp == NULL)
1686 {
1689 }
1690
1691 /* Query the class name */
1693 Atom ? Atom : Class->atomNVClassName,
1694 NULL,
1695 NULL,
1696 szTemp,
1697 &BufLen);
1698 }
1699 else
1700 szTemp = szStaticTemp;
1701
1702 if (NT_SUCCESS(Status))
1703 {
1704 /* Convert the atom name to ansi */
1705
1706 RtlInitUnicodeString(&UnicodeClassName,
1707 szTemp);
1708
1709 Status = RtlUnicodeStringToAnsiString(AnsiClassName,
1710 &UnicodeClassName,
1711 FALSE);
1712 if (!NT_SUCCESS(Status))
1713 {
1716 }
1717 }
1718
1719 Ret = BufLen / sizeof(WCHAR);
1720 }
1721 else /* !ANSI */
1722 {
1723 BufLen = ClassName->MaximumLength;
1724
1725 /* Query the atom name */
1727 Atom ? Atom : Class->atomNVClassName,
1728 NULL,
1729 NULL,
1730 ClassName->Buffer,
1731 &BufLen);
1732
1733 if (!NT_SUCCESS(Status))
1734 {
1737 }
1738
1739 Ret = BufLen / sizeof(WCHAR);
1740 }
1741 }
1743 {
1745 }
1746 _SEH2_END;
1747
1748 if (Ansi && szTemp != NULL && szTemp != szStaticTemp)
1749 {
1751 }
1752
1753 return Ret;
1754}
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 1494 of file class.c.

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

Referenced by NtUserRegisterClassExWOW().

◆ UserRegisterSystemClasses()

BOOL FASTCALL UserRegisterSystemClasses ( VOID  )

Definition at line 2309 of file class.c.

2310{
2311 UINT i;
2312 UNICODE_STRING ClassName, MenuName;
2314 WNDCLASSEXW wc;
2315 PCLS Class;
2316 BOOL Ret = TRUE;
2317 HBRUSH hBrush;
2318 DWORD Flags = 0;
2319
2320 if (ppi->W32PF_flags & W32PF_CLASSESREGISTERED)
2321 return TRUE;
2322
2323 if ( hModClient == NULL)
2324 return FALSE;
2325
2326 RtlZeroMemory(&ClassName, sizeof(ClassName));
2327 RtlZeroMemory(&MenuName, sizeof(MenuName));
2328
2329 for (i = 0; i != ARRAYSIZE(DefaultServerClasses); i++)
2330 {
2331 if (!IS_ATOM(DefaultServerClasses[i].ClassName))
2332 {
2333 RtlInitUnicodeString(&ClassName, DefaultServerClasses[i].ClassName);
2334 }
2335 else
2336 {
2337 ClassName.Buffer = DefaultServerClasses[i].ClassName;
2338 ClassName.Length = 0;
2339 ClassName.MaximumLength = 0;
2340 }
2341
2342 wc.cbSize = sizeof(wc);
2344
2346
2347 if (DefaultServerClasses[i].ProcW)
2348 {
2350 wc.hInstance = hModuleWin;
2351 }
2352 else
2353 {
2355 wc.hInstance = hModClient;
2356 }
2357
2358 wc.cbClsExtra = 0;
2360 wc.hIcon = NULL;
2361
2363 wc.hCursor = NULL;
2364 if (DefaultServerClasses[i].hCursor == (HICON)OCR_NORMAL)
2365 {
2366 if (SYSTEMCUR(ARROW) == NULL)
2367 {
2368 ERR("SYSTEMCUR(ARROW) == NULL, should not happen!!\n");
2369 }
2370 else
2371 {
2372 wc.hCursor = UserHMGetHandle(SYSTEMCUR(ARROW));
2373 }
2374 }
2375
2376 hBrush = DefaultServerClasses[i].hBrush;
2377 if (hBrush <= (HBRUSH)COLOR_MENUBAR)
2378 {
2379 hBrush = IntGetSysColorBrush(HandleToUlong(hBrush));
2380 }
2381 wc.hbrBackground = hBrush;
2382 wc.lpszMenuName = NULL;
2383 wc.lpszClassName = ClassName.Buffer;
2384 wc.hIconSm = NULL;
2385
2386 Class = IntCreateClass( &wc,
2387 &ClassName,
2388 &ClassName,
2389 &MenuName,
2390 DefaultServerClasses[i].fiId,
2391 Flags,
2392 NULL,
2393 ppi);
2394 if (Class != NULL)
2395 {
2396 Class->pclsNext = ppi->pclsPublicList;
2398 Class);
2399
2401 }
2402 else
2403 {
2404 ERR("!!! Registering system class failed!\n");
2405 Ret = FALSE;
2406 }
2407 }
2408 if (Ret) ppi->W32PF_flags |= W32PF_CLASSESREGISTERED;
2409 return Ret;
2410}
#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:901
HGDIOBJ FASTCALL IntGetSysColorBrush(INT Object)
Definition: stockobj.c:317
static HICON
Definition: imagelist.c:84
unsigned int UINT
Definition: ndis.h:50
DWORD dwRegisteredClasses
Definition: win32.h:280
struct _CLS * pclsPublicList
Definition: win32.h:260
WNDPROC ProcW
Definition: ntuser.h:487
LPCWSTR lpszClassName
Definition: winuser.h:3225
HBRUSH hbrBackground
Definition: winuser.h:3223
HCURSOR hCursor
Definition: winuser.h:3222
HICON hIconSm
Definition: winuser.h:3226
UINT style
Definition: winuser.h:3216
HICON hIcon
Definition: winuser.h:3221
REGISTER_SYSCLASS DefaultServerClasses[]
Definition: class.c:35
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 
)

Definition at line 1861 of file class.c.

1865{
1866 ULONG_PTR Ret = 0;
1867
1868 /* NOTE: For GCLP_MENUNAME and GCW_ATOM this function may raise an exception! */
1869
1870 /* Change the information in the base class first, then update the clones */
1871 Class = Class->pclsBase;
1872
1873 if (Index >= 0)
1874 {
1876
1877 TRACE("SetClassLong(%d, %x)\n", Index, NewLong);
1878
1879 if (((ULONG)Index + sizeof(ULONG_PTR)) < (ULONG)Index ||
1880 ((ULONG)Index + sizeof(ULONG_PTR)) > (ULONG)Class->cbclsExtra)
1881 {
1883 return 0;
1884 }
1885
1886 Data = (PULONG_PTR)((ULONG_PTR)(Class + 1) + Index);
1887
1888 /* FIXME: Data might be a unaligned pointer! Might be a problem on
1889 certain architectures, maybe using RtlCopyMemory is a
1890 better choice for those architectures! */
1891 Ret = *Data;
1892 *Data = NewLong;
1893
1894 /* Update the clones */
1895 Class = Class->pclsClone;
1896 while (Class != NULL)
1897 {
1898 *(PULONG_PTR)((ULONG_PTR)(Class + 1) + Index) = NewLong;
1899 Class = Class->pclsNext;
1900 }
1901
1902 return Ret;
1903 }
1904
1905 switch (Index)
1906 {
1907 case GCL_CBWNDEXTRA:
1908 Ret = (ULONG_PTR)Class->cbwndExtra;
1909 Class->cbwndExtra = (INT)NewLong;
1910
1911 /* Update the clones */
1912 Class = Class->pclsClone;
1913 while (Class != NULL)
1914 {
1915 Class->cbwndExtra = (INT)NewLong;
1916 Class = Class->pclsNext;
1917 }
1918
1919 break;
1920
1921 case GCL_CBCLSEXTRA:
1923 break;
1924
1925 case GCLP_HBRBACKGROUND:
1926 Ret = (ULONG_PTR)Class->hbrBackground;
1927 Class->hbrBackground = (HBRUSH)NewLong;
1928
1929 /* Update the clones */
1930 Class = Class->pclsClone;
1931 while (Class != NULL)
1932 {
1933 Class->hbrBackground = (HBRUSH)NewLong;
1934 Class = Class->pclsNext;
1935 }
1936 break;
1937
1938 case GCLP_HCURSOR:
1939 {
1940 PCURICON_OBJECT NewCursor = NULL;
1941
1942 if (NewLong)
1943 {
1944 NewCursor = UserGetCurIconObject((HCURSOR)NewLong);
1945 if (!NewCursor)
1946 {
1948 return 0;
1949 }
1950 }
1951
1952 if (Class->spcur)
1953 {
1954 Ret = (ULONG_PTR)UserHMGetHandle(Class->spcur);
1956 }
1957 else
1958 {
1959 Ret = 0;
1960 }
1961
1962 if (Ret == NewLong)
1963 {
1964 /* It's a nop */
1965 return Ret;
1966 }
1967
1968 Class->spcur = NewCursor;
1969
1970 /* Update the clones */
1971 Class = Class->pclsClone;
1972 while (Class != NULL)
1973 {
1974 if (Class->spcur)
1976 if (NewCursor)
1977 UserReferenceObject(NewCursor);
1978 Class->spcur = NewCursor;
1979 Class = Class->pclsNext;
1980 }
1981
1982 break;
1983 }
1984
1985 // MSDN:
1986 // hIconSm, A handle to a small icon that is associated with the window class.
1987 // If this member is NULL, the system searches the icon resource specified by
1988 // the hIcon member for an icon of the appropriate size to use as the small icon.
1989 //
1990 case GCLP_HICON:
1991 {
1992 PCURICON_OBJECT NewIcon = NULL;
1993 PCURICON_OBJECT NewSmallIcon = NULL;
1994
1995 if (NewLong)
1996 {
1997 NewIcon = UserGetCurIconObject((HCURSOR)NewLong);
1998 if (!NewIcon)
1999 {
2001 return 0;
2002 }
2003 }
2004
2005 if (Class->spicn)
2006 {
2007 Ret = (ULONG_PTR)UserHMGetHandle(Class->spicn);
2009 }
2010 else
2011 {
2012 Ret = 0;
2013 }
2014
2015 if (Ret == NewLong)
2016 {
2017 /* It's a nop */
2018 return Ret;
2019 }
2020
2021 if (Ret && (Class->CSF_flags & CSF_CACHEDSMICON))
2022 {
2023 /* We will change the small icon */
2024 UserDereferenceObject(Class->spicnSm);
2026 Class->spicnSm = NULL;
2027 Class->CSF_flags &= ~CSF_CACHEDSMICON;
2028 }
2029
2030 if (NewLong && !Class->spicnSm)
2031 {
2032 /* Create the new small icon from the new large(?) one */
2033 HICON SmallIconHandle = NULL;
2036 {
2037 SmallIconHandle = co_IntCopyImage(
2038 (HICON)NewLong,
2039 IMAGE_ICON,
2043 }
2044 if (!SmallIconHandle)
2045 {
2046 /* Retry without copying from resource */
2047 SmallIconHandle = co_IntCopyImage(
2048 (HICON)NewLong,
2049 IMAGE_ICON,
2052 0);
2053 }
2054 if (SmallIconHandle)
2055 {
2056 /* So use it */
2057 NewSmallIcon = Class->spicnSm = UserGetCurIconObject(SmallIconHandle);
2058 Class->CSF_flags |= CSF_CACHEDSMICON;
2059 }
2060 }
2061
2062 Class->spicn = NewIcon;
2063
2064 /* Update the clones */
2065 Class = Class->pclsClone;
2066 while (Class != NULL)
2067 {
2068 if (Class->spicn)
2070 if (NewIcon)
2071 UserReferenceObject(NewIcon);
2072 Class->spicn = NewIcon;
2073 if (NewSmallIcon)
2074 {
2075 if (Class->spicnSm)
2076 UserDereferenceObject(Class->spicnSm);
2077 UserReferenceObject(NewSmallIcon);
2078 Class->spicnSm = NewSmallIcon;
2079 Class->CSF_flags |= CSF_CACHEDSMICON;
2080 }
2081 Class = Class->pclsNext;
2082 }
2083 break;
2084 }
2085
2086 case GCLP_HICONSM:
2087 {
2088 PCURICON_OBJECT NewSmallIcon = NULL;
2089 BOOLEAN NewIconFromCache = FALSE;
2090
2091 if (NewLong)
2092 {
2093 NewSmallIcon = UserGetCurIconObject((HCURSOR)NewLong);
2094 if (!NewSmallIcon)
2095 {
2097 return 0;
2098 }
2099 }
2100 else
2101 {
2102 /* Create the new small icon from the large one */
2103 HICON SmallIconHandle = NULL;
2104 if((Class->spicn->CURSORF_flags & (CURSORF_LRSHARED | CURSORF_FROMRESOURCE))
2106 {
2107 SmallIconHandle = co_IntCopyImage(
2108 UserHMGetHandle(Class->spicn),
2109 IMAGE_ICON,
2113 }
2114 if (!SmallIconHandle)
2115 {
2116 /* Retry without copying from resource */
2117 SmallIconHandle = co_IntCopyImage(
2118 UserHMGetHandle(Class->spicn),
2119 IMAGE_ICON,
2122 0);
2123 }
2124 if (SmallIconHandle)
2125 {
2126 /* So use it */
2127 NewSmallIcon = UserGetCurIconObject(SmallIconHandle);
2128 NewIconFromCache = TRUE;
2129 }
2130 else
2131 {
2132 ERR("Failed getting a small icon for the class.\n");
2133 }
2134 }
2135
2136 if (Class->spicnSm)
2137 {
2138 if (Class->CSF_flags & CSF_CACHEDSMICON)
2139 {
2140 /* We must destroy the icon if we own it */
2142 Ret = 0;
2143 }
2144 else
2145 {
2146 Ret = (ULONG_PTR)UserHMGetHandle(Class->spicnSm);
2147 }
2148 UserDereferenceObject(Class->spicnSm);
2149 }
2150 else
2151 {
2152 Ret = 0;
2153 }
2154
2155 if (NewIconFromCache)
2156 Class->CSF_flags |= CSF_CACHEDSMICON;
2157 else
2158 Class->CSF_flags &= ~CSF_CACHEDSMICON;
2159 Class->spicnSm = NewSmallIcon;
2160
2161 /* Update the clones */
2162 Class = Class->pclsClone;
2163 while (Class != NULL)
2164 {
2165 if (Class->spicnSm)
2166 UserDereferenceObject(Class->spicnSm);
2167 if (NewSmallIcon)
2168 UserReferenceObject(NewSmallIcon);
2169 if (NewIconFromCache)
2170 Class->CSF_flags |= CSF_CACHEDSMICON;
2171 else
2172 Class->CSF_flags &= ~CSF_CACHEDSMICON;
2173 Class->spicnSm = NewSmallIcon;
2174 Class = Class->pclsNext;
2175 }
2176 }
2177 break;
2178
2179 case GCLP_HMODULE:
2180 Ret = (ULONG_PTR)Class->hModule;
2181 Class->hModule = (HINSTANCE)NewLong;
2182
2183 /* Update the clones */
2184 Class = Class->pclsClone;
2185 while (Class != NULL)
2186 {
2187 Class->hModule = (HINSTANCE)NewLong;
2188 Class = Class->pclsNext;
2189 }
2190 break;
2191
2192 case GCLP_MENUNAME:
2193 {
2195
2197 Value))
2198 {
2199 ERR("Setting the class menu name failed!\n");
2200 }
2201
2202 /* FIXME: Really return NULL? Wine does so... */
2203 break;
2204 }
2205
2206 case GCL_STYLE:
2207 Ret = (ULONG_PTR)Class->style;
2208 Class->style = (UINT)NewLong;
2209
2210 /* FIXME: What if the CS_GLOBALCLASS style is changed? should we
2211 move the class to the appropriate list? For now, we save
2212 the original value in Class->Global, so we can always
2213 locate the appropriate list */
2214
2215 /* Update the clones */
2216 Class = Class->pclsClone;
2217 while (Class != NULL)
2218 {
2219 Class->style = (UINT)NewLong;
2220 Class = Class->pclsNext;
2221 }
2222 break;
2223
2224 case GCLP_WNDPROC:
2226 (WNDPROC)NewLong,
2227 Ansi);
2228 break;
2229
2230 case GCW_ATOM:
2231 {
2233
2234 Ret = (ULONG_PTR)Class->atomNVClassName;
2236 Value))
2237 {
2238 Ret = 0;
2239 }
2240 break;
2241 }
2242
2243 default:
2245 break;
2246 }
2247
2248 return Ret;
2249}
unsigned char BOOLEAN
UNICODE_STRING * PUNICODE_STRING
Definition: env_spec_w32.h:373
#define CURSORF_LRSHARED
Definition: ntuser.h:1200
#define CURSORF_FROMRESOURCE
Definition: ntuser.h:1198
#define INT
Definition: polytest.cpp:20
ULONG CURSORF_flags
Definition: cursoricon.h:16
HANDLE HINSTANCE
Definition: typedefs.h:77
uint32_t * PULONG_PTR
Definition: typedefs.h:65
_In_ WDFCOLLECTION _In_ ULONG Index
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:1757
static BOOL IntSetClassAtom(IN OUT PCLS Class, IN PUNICODE_STRING ClassName)
Definition: class.c:448
static WNDPROC FASTCALL IntSetClassWndProc(IN OUT PCLS Class, IN WNDPROC WndProc, IN BOOL Ansi)
Definition: class.c:546
LONG NTAPI UserGetSystemMetrics(ULONG Index)
Definition: metric.c:208
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:1098
#define GCLP_WNDPROC
Definition: winuser.h:678
#define SM_CYSMICON
Definition: winuser.h:1012
#define GCLP_HCURSOR
Definition: winuser.h:673
#define GCL_CBWNDEXTRA
Definition: winuser.h:663
#define SM_CXSMICON
Definition: winuser.h:1011
#define GCLP_HBRBACKGROUND
Definition: winuser.h:672
#define GCL_STYLE
Definition: winuser.h:670
#define GCL_CBCLSEXTRA
Definition: winuser.h:662

Referenced by NtUserSetClassLong().

◆ UserUnregisterClass()

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

Definition at line 1581 of file class.c.

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

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",
}

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().

◆ 

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

Referenced by LookupFnIdToiCls().