dc8496dd431e96eb4daaa51d8dceffe616a67c0c
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / callproc.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Window classes
5 * FILE: subsystems/win32/win32k/ntuser/class.c
6 * PROGRAMER: Thomas Weidenmueller <w3seek@reactos.com>
7 * REVISION HISTORY:
8 * 06-06-2001 CSH Created
9 */
10 /* INCLUDES ******************************************************************/
11
12 #include <win32k.h>
13
14 #define NDEBUG
15 #include <debug.h>
16
17 /* CALLPROC ******************************************************************/
18
19 WNDPROC
20 GetCallProcHandle(IN PCALLPROCDATA CallProc)
21 {
22 /* FIXME - check for 64 bit architectures... */
23 return (WNDPROC)((ULONG_PTR)UserHMGetHandle(CallProc) | 0xFFFF0000);
24 }
25
26 VOID
27 DestroyCallProc(IN PDESKTOPINFO Desktop,
28 IN OUT PCALLPROCDATA CallProc)
29 {
30 UserDeleteObject(UserHMGetHandle(CallProc), otCallProc);
31 }
32
33 PCALLPROCDATA
34 CloneCallProc(IN PDESKTOP Desktop,
35 IN PCALLPROCDATA CallProc)
36 {
37 PCALLPROCDATA NewCallProc;
38 HANDLE Handle;
39
40 NewCallProc = (PCALLPROCDATA)UserCreateObject(gHandleTable,
41 Desktop,
42 &Handle,
43 otCallProc,
44 sizeof(CALLPROCDATA));
45 if (NewCallProc != NULL)
46 {
47 NewCallProc->pfnClientPrevious = CallProc->pfnClientPrevious;
48 NewCallProc->wType = CallProc->wType;
49 NewCallProc->spcpdNext = NULL;
50 }
51
52 return NewCallProc;
53 }
54
55 PCALLPROCDATA
56 CreateCallProc(IN PDESKTOP Desktop,
57 IN WNDPROC WndProc,
58 IN BOOL Unicode,
59 IN PPROCESSINFO pi)
60 {
61 PCALLPROCDATA NewCallProc;
62 HANDLE Handle;
63
64 NewCallProc = (PCALLPROCDATA)UserCreateObject(gHandleTable,
65 Desktop,
66 &Handle,
67 otCallProc,
68 sizeof(CALLPROCDATA));
69 if (NewCallProc != NULL)
70 {
71 NewCallProc->pfnClientPrevious = WndProc;
72 NewCallProc->wType |= Unicode ? UserGetCPDA2U : UserGetCPDU2A ;
73 NewCallProc->spcpdNext = NULL;
74 }
75
76 return NewCallProc;
77 }
78
79 BOOL
80 UserGetCallProcInfo(IN HANDLE hCallProc,
81 OUT PWNDPROC_INFO wpInfo)
82 {
83 PCALLPROCDATA CallProc;
84
85 /* NOTE: Accessing the WNDPROC_INFO structure may raise an exception! */
86
87 CallProc = UserGetObject(gHandleTable,
88 hCallProc,
89 otCallProc);
90 if (CallProc == NULL)
91 {
92 return FALSE;
93 }
94
95 /* Use Handle pEntry->ppi!
96 if (CallProc->pi != GetW32ProcessInfo())
97 {
98 return FALSE;
99 }*/
100
101 wpInfo->WindowProc = CallProc->pfnClientPrevious;
102 wpInfo->IsUnicode = !!(CallProc->wType & UserGetCPDA2U);
103
104 return TRUE;
105 }
106
107 /*
108 Based on UserFindCallProc.
109 */
110 PCALLPROCDATA
111 FASTCALL
112 UserSearchForCallProc(
113 PCALLPROCDATA pcpd,
114 WNDPROC WndProc,
115 GETCPD Type)
116 {
117 while ( pcpd && (pcpd->pfnClientPrevious != WndProc || pcpd->wType != Type) )
118 {
119 pcpd = pcpd->spcpdNext;
120 }
121 return pcpd;
122 }
123
124 /*
125 Get Call Proc Data handle for the window proc being requested or create a
126 new Call Proc Data handle to be return for the requested window proc.
127 */
128 ULONG_PTR
129 FASTCALL
130 UserGetCPD(
131 PVOID pvClsWnd,
132 GETCPD Flags,
133 ULONG_PTR ProcIn)
134 {
135 PCLS pCls;
136 PWND pWnd;
137 PCALLPROCDATA CallProc = NULL;
138 PTHREADINFO pti;
139
140 pti = PsGetCurrentThreadWin32Thread();
141
142 if ( Flags & (UserGetCPDWindow|UserGetCPDDialog) ||
143 Flags & UserGetCPDWndtoCls)
144 {
145 pWnd = pvClsWnd;
146 pCls = pWnd->pcls;
147 }
148 else
149 pCls = pvClsWnd;
150
151 // Search Class call proc data list.
152 if (pCls->spcpdFirst)
153 CallProc = UserSearchForCallProc( pCls->spcpdFirst, (WNDPROC)ProcIn, Flags);
154
155 // No luck, create a new one for the requested proc.
156 if (!CallProc)
157 {
158 CallProc = CreateCallProc( NULL,
159 (WNDPROC)ProcIn,
160 !!(Flags & UserGetCPDA2U),
161 pti->ppi);
162 if (CallProc)
163 {
164 CallProc->spcpdNext = pCls->spcpdFirst;
165 (void)InterlockedExchangePointer((PVOID*)&pCls->spcpdFirst,
166 CallProc);
167 CallProc->wType = Flags;
168 }
169 }
170 return (ULONG_PTR)(CallProc ? GetCallProcHandle(CallProc) : NULL);
171 }
172
173 /* SYSCALLS *****************************************************************/
174
175 /*
176 Retrieve the WinProcA/W or CallProcData handle for Class, Dialog or Window.
177 This Function called from user space uses Window handle for class, window
178 and dialog procs only.
179
180 Note:
181 ProcIn is the default proc from pCls/pDlg/pWnd->lpfnXxyz, caller is
182 looking for another type of proc if the original lpfnXxyz proc is preset
183 to Ansi or Unicode.
184
185 Example:
186 If pWnd is created from Ansi and lpfnXxyz is assumed to be Ansi, caller
187 will ask for Unicode Proc return Proc or CallProcData handle.
188
189 This function should replaced NtUserGetClassLong and NtUserGetWindowLong.
190 */
191 ULONG_PTR
192 APIENTRY
193 NtUserGetCPD(
194 HWND hWnd,
195 GETCPD Flags,
196 ULONG_PTR ProcIn)
197 {
198 PWINDOW_OBJECT Window;
199 PWND Wnd;
200 ULONG_PTR Result = 0;
201
202 UserEnterExclusive();
203 if (!(Window = UserGetWindowObject(hWnd)) || !Window->Wnd)
204 {
205 goto Cleanup;
206 }
207 Wnd = Window->Wnd;
208
209 // Processing Window only from User space.
210 if ((Flags & ~(UserGetCPDU2A|UserGetCPDA2U)) != UserGetCPDClass)
211 Result = UserGetCPD(Wnd, Flags, ProcIn);
212
213 Cleanup:
214 UserLeave();
215 return Result;
216 }
217