xref: /reactos/win32ss/user/ntuser/prop.c (revision d7fd62d4)
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 = { 0 }, *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 */
275