- Properly remove window properties when destroying the window.
[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: subsys/win32k/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 FASTCALL
15 IntGetProp(PWND Window, ATOM Atom)
16 {
17 PLIST_ENTRY ListEntry;
18 PPROPERTY Property;
19 int i;
20
21 ListEntry = Window->PropListHead.Flink;
22 for (i = 0; i < Window->PropListItems; i++ )
23 {
24 Property = CONTAINING_RECORD(ListEntry, PROPERTY, PropListEntry);
25 if (Property->Atom == Atom)
26 {
27 return(Property);
28 }
29 ListEntry = ListEntry->Flink;
30 }
31 return(NULL);
32 }
33
34 HANDLE
35 FASTCALL
36 UserGetProp(PWND pWnd, ATOM Atom)
37 {
38 PPROPERTY Prop;
39 Prop = IntGetProp(pWnd, Atom);
40 return Prop ? Prop->Data : NULL;
41 }
42
43 BOOL FASTCALL
44 IntRemoveProp(PWND Window, ATOM Atom)
45 {
46 PPROPERTY Prop;
47 Prop = IntGetProp(Window, Atom);
48
49 if (Prop == NULL)
50 {
51 return FALSE;
52 }
53 RemoveEntryList(&Prop->PropListEntry);
54 UserHeapFree(Prop);
55 Window->PropListItems--;
56 return TRUE;
57 }
58
59 BOOL FASTCALL
60 IntSetProp(PWND pWnd, ATOM Atom, HANDLE Data)
61 {
62 PPROPERTY Prop;
63
64 Prop = IntGetProp(pWnd, Atom);
65
66 if (Prop == NULL)
67 {
68 Prop = UserHeapAlloc(sizeof(PROPERTY));
69 if (Prop == NULL)
70 {
71 return FALSE;
72 }
73 Prop->Atom = Atom;
74 InsertTailList(&pWnd->PropListHead, &Prop->PropListEntry);
75 pWnd->PropListItems++;
76 }
77
78 Prop->Data = Data;
79 return TRUE;
80 }
81
82 VOID FASTCALL
83 IntRemoveWindowProp(PWND Window)
84 {
85 PLIST_ENTRY ListEntry;
86 PPROPERTY Property;
87 int i, Count = Window->PropListItems;
88
89 ListEntry = Window->PropListHead.Flink;
90 for (i = 0; i < Count; i++ )
91 {
92 Property = CONTAINING_RECORD(ListEntry, PROPERTY, PropListEntry);
93 ListEntry = ListEntry->Flink;
94 RemoveEntryList(&Property->PropListEntry);
95 UserHeapFree(Property);
96 Window->PropListItems--;
97 }
98 return;
99 }
100
101 /* FUNCTIONS *****************************************************************/
102
103 NTSTATUS APIENTRY
104 NtUserBuildPropList(HWND hWnd,
105 LPVOID Buffer,
106 DWORD BufferSize,
107 DWORD *Count)
108 {
109 PWND Window;
110 PPROPERTY Property;
111 PLIST_ENTRY ListEntry;
112 PROPLISTITEM listitem, *li;
113 NTSTATUS Status;
114 DWORD Cnt = 0;
115 DECLARE_RETURN(NTSTATUS);
116
117 TRACE("Enter NtUserBuildPropList\n");
118 UserEnterShared();
119
120 if (!(Window = UserGetWindowObject(hWnd)))
121 {
122 RETURN( STATUS_INVALID_HANDLE);
123 }
124
125 if(Buffer)
126 {
127 if(!BufferSize || (BufferSize % sizeof(PROPLISTITEM) != 0))
128 {
129 RETURN( STATUS_INVALID_PARAMETER);
130 }
131
132 /* Copy list */
133 li = (PROPLISTITEM *)Buffer;
134 ListEntry = Window->PropListHead.Flink;
135 while((BufferSize >= sizeof(PROPLISTITEM)) && (ListEntry != &Window->PropListHead))
136 {
137 Property = CONTAINING_RECORD(ListEntry, PROPERTY, PropListEntry);
138 listitem.Atom = Property->Atom;
139 listitem.Data = Property->Data;
140
141 Status = MmCopyToCaller(li, &listitem, sizeof(PROPLISTITEM));
142 if(!NT_SUCCESS(Status))
143 {
144 RETURN( Status);
145 }
146
147 BufferSize -= sizeof(PROPLISTITEM);
148 Cnt++;
149 li++;
150 ListEntry = ListEntry->Flink;
151 }
152
153 }
154 else
155 {
156 Cnt = Window->PropListItems * sizeof(PROPLISTITEM);
157 }
158
159 if(Count)
160 {
161 Status = MmCopyToCaller(Count, &Cnt, sizeof(DWORD));
162 if(!NT_SUCCESS(Status))
163 {
164 RETURN( Status);
165 }
166 }
167
168 RETURN( STATUS_SUCCESS);
169
170 CLEANUP:
171 TRACE("Leave NtUserBuildPropList, ret=%i\n",_ret_);
172 UserLeave();
173 END_CLEANUP;
174 }
175
176 HANDLE APIENTRY
177 NtUserRemoveProp(HWND hWnd, ATOM Atom)
178 {
179 PWND Window;
180 PPROPERTY Prop;
181 HANDLE Data;
182 DECLARE_RETURN(HANDLE);
183
184 TRACE("Enter NtUserRemoveProp\n");
185 UserEnterExclusive();
186
187 if (!(Window = UserGetWindowObject(hWnd)))
188 {
189 RETURN( NULL);
190 }
191
192 Prop = IntGetProp(Window, Atom);
193
194 if (Prop == NULL)
195 {
196 RETURN(NULL);
197 }
198 Data = Prop->Data;
199 RemoveEntryList(&Prop->PropListEntry);
200 UserHeapFree(Prop);
201 Window->PropListItems--;
202
203 RETURN(Data);
204
205 CLEANUP:
206 TRACE("Leave NtUserRemoveProp, ret=%p\n", _ret_);
207 UserLeave();
208 END_CLEANUP;
209 }
210
211 BOOL APIENTRY
212 NtUserSetProp(HWND hWnd, ATOM Atom, HANDLE Data)
213 {
214 PWND Window;
215 DECLARE_RETURN(BOOL);
216
217 TRACE("Enter NtUserSetProp\n");
218 UserEnterExclusive();
219
220 if (!(Window = UserGetWindowObject(hWnd)))
221 {
222 RETURN( FALSE);
223 }
224
225 RETURN( IntSetProp(Window, Atom, Data));
226
227 CLEANUP:
228 TRACE("Leave NtUserSetProp, ret=%i\n",_ret_);
229 UserLeave();
230 END_CLEANUP;
231 }
232
233 /* EOF */