[WIN32K, USER32]
[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 ULONG_PTR
190 APIENTRY
191 NtUserGetCPD(
192 HWND hWnd,
193 GETCPD Flags,
194 ULONG_PTR ProcIn)
195 {
196 PWINDOW_OBJECT Window;
197 PWND Wnd;
198 ULONG_PTR Result = 0;
199
200 UserEnterExclusive();
201 if (!(Window = UserGetWindowObject(hWnd)) || !Window->Wnd)
202 {
203 goto Cleanup;
204 }
205 Wnd = Window->Wnd;
206
207 // Processing Window only from User space.
208 if ((Flags & ~(UserGetCPDU2A|UserGetCPDA2U)) != UserGetCPDClass)
209 Result = UserGetCPD(Wnd, Flags, ProcIn);
210
211 Cleanup:
212 UserLeave();
213 return Result;
214 }
215