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