[WIN32K:NTUSER]
[reactos.git] / reactos / win32ss / user / ntuser / prop.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Window properties
5 * FILE: win32ss/user/ntuser/prop.c
6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 */
8
9 #include <win32k.h>
10 DBG_DEFAULT_CHANNEL(UserProp);
11
12 /* STATIC FUNCTIONS **********************************************************/
13
14 PPROPERTY
15 FASTCALL
16 IntGetProp(
17 _In_ PWND Window,
18 _In_ ATOM Atom,
19 _In_ BOOLEAN SystemProp)
20 {
21 PLIST_ENTRY ListEntry;
22 PPROPERTY Property;
23 UINT i;
24 WORD SystemFlag = SystemProp ? PROPERTY_FLAG_SYSTEM : 0;
25
26 NT_ASSERT(UserIsEntered());
27 ListEntry = Window->PropListHead.Flink;
28
29 for (i = 0; i < Window->PropListItems; i++)
30 {
31 Property = CONTAINING_RECORD(ListEntry, PROPERTY, PropListEntry);
32 ListEntry = ListEntry->Flink;
33
34 if (Property->Atom == Atom &&
35 (Property->fs & PROPERTY_FLAG_SYSTEM) == SystemFlag)
36 {
37 return Property;
38 }
39 }
40 NT_ASSERT(ListEntry == &Window->PropListHead);
41 return NULL;
42 }
43
44 HANDLE
45 FASTCALL
46 UserGetProp(
47 _In_ PWND Window,
48 _In_ ATOM Atom,
49 _In_ BOOLEAN SystemProp)
50 {
51 PPROPERTY Prop;
52
53 NT_ASSERT(UserIsEntered());
54 Prop = IntGetProp(Window, Atom, SystemProp);
55 return Prop ? Prop->Data : NULL;
56 }
57
58 _Success_(return)
59 HANDLE
60 FASTCALL
61 UserRemoveProp(
62 _In_ PWND Window,
63 _In_ ATOM Atom,
64 _In_ BOOLEAN SystemProp)
65 {
66 PPROPERTY Prop;
67 HANDLE Data;
68
69 NT_ASSERT(UserIsEnteredExclusive());
70 Prop = IntGetProp(Window, Atom, SystemProp);
71 if (Prop == NULL)
72 {
73 return NULL;
74 }
75
76 Data = Prop->Data;
77 RemoveEntryList(&Prop->PropListEntry);
78 UserHeapFree(Prop);
79 Window->PropListItems--;
80 return Data;
81 }
82
83 _Success_(return)
84 BOOL
85 FASTCALL
86 UserSetProp(
87 _In_ PWND Window,
88 _In_ ATOM Atom,
89 _In_ HANDLE Data,
90 _In_ BOOLEAN SystemProp)
91 {
92 PPROPERTY Prop;
93
94 NT_ASSERT(UserIsEnteredExclusive());
95 Prop = IntGetProp(Window, Atom, SystemProp);
96 if (Prop == NULL)
97 {
98 Prop = UserHeapAlloc(sizeof(PROPERTY));
99 if (Prop == NULL)
100 {
101 return FALSE;
102 }
103 Prop->Atom = Atom;
104 Prop->fs = SystemProp ? PROPERTY_FLAG_SYSTEM : 0;
105 InsertTailList(&Window->PropListHead, &Prop->PropListEntry);
106 Window->PropListItems++;
107 }
108
109 Prop->Data = Data;
110 return TRUE;
111 }
112
113 VOID
114 FASTCALL
115 UserRemoveWindowProps(
116 _In_ PWND Window)
117 {
118 PLIST_ENTRY ListEntry;
119 PPROPERTY Property;
120
121 NT_ASSERT(UserIsEnteredExclusive());
122 while (!IsListEmpty(&Window->PropListHead))
123 {
124 ListEntry = Window->PropListHead.Flink;
125 Property = CONTAINING_RECORD(ListEntry, PROPERTY, PropListEntry);
126 RemoveEntryList(&Property->PropListEntry);
127 UserHeapFree(Property);
128 Window->PropListItems--;
129 }
130 return;
131 }
132
133 /* FUNCTIONS *****************************************************************/
134
135 NTSTATUS
136 APIENTRY
137 NtUserBuildPropList(
138 _In_ HWND hWnd,
139 _Out_writes_bytes_to_opt_(BufferSize, *Count * sizeof(PROPLISTITEM)) LPVOID Buffer,
140 _In_ DWORD BufferSize,
141 _Out_opt_ DWORD *Count)
142 {
143 PWND Window;
144 PPROPERTY Property;
145 PLIST_ENTRY ListEntry;
146 PROPLISTITEM listitem, *li;
147 NTSTATUS Status;
148 DWORD Cnt = 0;
149
150 TRACE("Enter NtUserBuildPropList\n");
151 UserEnterShared();
152
153 Window = UserGetWindowObject(hWnd);
154 if (Window == NULL)
155 {
156 Status = STATUS_INVALID_HANDLE;
157 goto Exit;
158 }
159
160 if (Buffer)
161 {
162 if (!BufferSize || (BufferSize % sizeof(PROPLISTITEM) != 0))
163 {
164 Status = STATUS_INVALID_PARAMETER;
165 goto Exit;
166 }
167
168 /* Copy list */
169 li = (PROPLISTITEM *)Buffer;
170 ListEntry = Window->PropListHead.Flink;
171 while ((BufferSize >= sizeof(PROPLISTITEM)) &&
172 (ListEntry != &Window->PropListHead))
173 {
174 Property = CONTAINING_RECORD(ListEntry, PROPERTY, PropListEntry);
175 ListEntry = ListEntry->Flink;
176 if (!(Property->fs & PROPERTY_FLAG_SYSTEM))
177 {
178 listitem.Atom = Property->Atom;
179 listitem.Data = Property->Data;
180
181 Status = MmCopyToCaller(li, &listitem, sizeof(PROPLISTITEM));
182 if (!NT_SUCCESS(Status))
183 {
184 goto Exit;
185 }
186
187 BufferSize -= sizeof(PROPLISTITEM);
188 Cnt++;
189 li++;
190 }
191 }
192
193 }
194 else
195 {
196 /* FIXME: This counts user and system props */
197 Cnt = Window->PropListItems * sizeof(PROPLISTITEM);
198 }
199
200 if (Count)
201 {
202 Status = MmCopyToCaller(Count, &Cnt, sizeof(DWORD));
203 if (!NT_SUCCESS(Status))
204 {
205 goto Exit;
206 }
207 }
208
209 Status = STATUS_SUCCESS;
210
211 Exit:
212 TRACE("Leave NtUserBuildPropList, ret=%lx\n", Status);
213 UserLeave();
214
215 return Status;
216 }
217
218 HANDLE
219 APIENTRY
220 NtUserRemoveProp(
221 _In_ HWND hWnd,
222 _In_ ATOM Atom)
223 {
224 PWND Window;
225 HANDLE Data = NULL;
226
227 TRACE("Enter NtUserRemoveProp\n");
228 UserEnterExclusive();
229
230 Window = UserGetWindowObject(hWnd);
231 if (Window == NULL)
232 {
233 goto Exit;
234 }
235
236 Data = UserRemoveProp(Window, Atom, FALSE);
237
238 Exit:
239 TRACE("Leave NtUserRemoveProp, ret=%p\n", Data);
240 UserLeave();
241
242 return Data;
243 }
244
245 BOOL
246 APIENTRY
247 NtUserSetProp(
248 _In_ HWND hWnd,
249 _In_ ATOM Atom,
250 _In_ HANDLE Data)
251 {
252 PWND Window;
253 BOOL Ret;
254
255 TRACE("Enter NtUserSetProp\n");
256 UserEnterExclusive();
257
258 Window = UserGetWindowObject(hWnd);
259 if (Window == NULL)
260 {
261 Ret = FALSE;
262 goto Exit;
263 }
264
265 Ret = UserSetProp(Window, Atom, Data, FALSE);
266
267 Exit:
268 TRACE("Leave NtUserSetProp, ret=%i\n", Ret);
269 UserLeave();
270
271 return Ret;
272 }
273
274 /* EOF */