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