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