[WIN32K]
[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: 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 VOID
21 DestroyCallProc(IN PDESKTOPINFO Desktop,
22 IN OUT PCALLPROCDATA CallProc)
23 {
24 UserDeleteObject(UserHMGetHandle(CallProc), otCallProc);
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 NewCallProc = (PCALLPROCDATA)UserCreateObject(gHandleTable,
37 Desktop,
38 &Handle,
39 otCallProc,
40 sizeof(CALLPROCDATA));
41 if (NewCallProc != NULL)
42 {
43 NewCallProc->pfnClientPrevious = WndProc;
44 NewCallProc->wType |= Unicode ? UserGetCPDA2U : UserGetCPDU2A ;
45 NewCallProc->spcpdNext = NULL;
46 }
47
48 return NewCallProc;
49 }
50
51 BOOL
52 UserGetCallProcInfo(IN HANDLE hCallProc,
53 OUT PWNDPROC_INFO wpInfo)
54 {
55 PCALLPROCDATA CallProc;
56
57 CallProc = UserGetObject(gHandleTable,
58 hCallProc,
59 otCallProc);
60 if (CallProc == NULL)
61 {
62 return FALSE;
63 }
64
65 /* Use Handle pEntry->ppi!
66 if (CallProc->pi != GetW32ProcessInfo())
67 {
68 return FALSE;
69 }*/
70
71 wpInfo->WindowProc = CallProc->pfnClientPrevious;
72 wpInfo->IsUnicode = !!(CallProc->wType & UserGetCPDA2U);
73
74 return TRUE;
75 }
76
77 /*
78 Based on UserFindCallProc.
79 */
80 PCALLPROCDATA
81 FASTCALL
82 UserSearchForCallProc(
83 PCALLPROCDATA pcpd,
84 WNDPROC WndProc,
85 GETCPD Type)
86 {
87 while ( pcpd && (pcpd->pfnClientPrevious != WndProc || pcpd->wType != Type) )
88 {
89 pcpd = pcpd->spcpdNext;
90 }
91 return pcpd;
92 }
93
94 /*
95 Get Call Proc Data handle for the window proc being requested or create a
96 new Call Proc Data handle to be return for the requested window proc.
97 */
98 ULONG_PTR
99 FASTCALL
100 UserGetCPD(
101 PVOID pvClsWnd,
102 GETCPD Flags,
103 ULONG_PTR ProcIn)
104 {
105 PCLS pCls;
106 PWND pWnd;
107 PCALLPROCDATA CallProc = NULL;
108 PTHREADINFO pti;
109
110 pti = PsGetCurrentThreadWin32Thread();
111
112 if ( Flags & (UserGetCPDWindow|UserGetCPDDialog) ||
113 Flags & UserGetCPDWndtoCls)
114 {
115 pWnd = pvClsWnd;
116 pCls = pWnd->pcls;
117 }
118 else
119 pCls = pvClsWnd;
120
121 // Search Class call proc data list.
122 if (pCls->spcpdFirst)
123 CallProc = UserSearchForCallProc( pCls->spcpdFirst, (WNDPROC)ProcIn, Flags);
124
125 // No luck, create a new one for the requested proc.
126 if (!CallProc)
127 {
128 CallProc = CreateCallProc( NULL,
129 (WNDPROC)ProcIn,
130 !!(Flags & UserGetCPDA2U),
131 pti->ppi);
132 if (CallProc)
133 {
134 CallProc->spcpdNext = pCls->spcpdFirst;
135 (void)InterlockedExchangePointer((PVOID*)&pCls->spcpdFirst,
136 CallProc);
137 CallProc->wType = Flags;
138 }
139 }
140 return (ULONG_PTR)(CallProc ? GetCallProcHandle(CallProc) : NULL);
141 }
142
143 /* SYSCALLS *****************************************************************/
144
145 /*
146 Retrieve the WinProcA/W or CallProcData handle for Class, Dialog or Window.
147 This Function called from user space uses Window handle for class, window
148 and dialog procs only.
149
150 Note:
151 ProcIn is the default proc from pCls/pDlg/pWnd->lpfnXxyz, caller is
152 looking for another type of proc if the original lpfnXxyz proc is preset
153 to Ansi or Unicode.
154
155 Example:
156 If pWnd is created from Ansi and lpfnXxyz is assumed to be Ansi, caller
157 will ask for Unicode Proc return Proc or CallProcData handle.
158 */
159 ULONG_PTR
160 APIENTRY
161 NtUserGetCPD(
162 HWND hWnd,
163 GETCPD Flags,
164 ULONG_PTR ProcIn)
165 {
166 PWND Wnd;
167 ULONG_PTR Result = 0;
168
169 UserEnterExclusive();
170 if (!(Wnd = UserGetWindowObject(hWnd)))
171 {
172 goto Cleanup;
173 }
174
175 // Processing Window only from User space.
176 if ((Flags & ~(UserGetCPDU2A|UserGetCPDA2U)) != UserGetCPDClass)
177 Result = UserGetCPD(Wnd, Flags, ProcIn);
178
179 Cleanup:
180 UserLeave();
181 return Result;
182 }
183