source: trunk/src/shell32/changenotify.c@ 8756

Last change on this file since 8756 was 8756, checked in by sandervl, 23 years ago

KSO: Bad linked list walking. (accessed node after free)

File size: 8.4 KB
Line 
1/*
2 * shell change notification
3 *
4 * Juergen Schmied <juergen.schmied@debitel.de>
5 *
6 */
7#ifdef __WIN32OS2__
8#define ICOM_CINTERFACE 1
9#include <odin.h>
10#endif
11
12#include <string.h>
13
14#include "debugtools.h"
15#include "pidl.h"
16#include "shell32_main.h"
17#include "undocshell.h"
18
19DEFAULT_DEBUG_CHANNEL(shell);
20
21static CRITICAL_SECTION SHELL32_ChangenotifyCS = CRITICAL_SECTION_INIT;
22
23/* internal list of notification clients (internal) */
24typedef struct _NOTIFICATIONLIST
25{
26 struct _NOTIFICATIONLIST *next;
27 struct _NOTIFICATIONLIST *prev;
28 HWND hwnd; /* window to notify */
29 DWORD uMsg; /* message to send */
30 LPNOTIFYREGISTER apidl; /* array of entries to watch*/
31 UINT cidl; /* number of pidls in array */
32 LONG wEventMask; /* subscribed events */
33 DWORD dwFlags; /* client flags */
34} NOTIFICATIONLIST, *LPNOTIFICATIONLIST;
35
36static NOTIFICATIONLIST head;
37static NOTIFICATIONLIST tail;
38
39void InitChangeNotifications()
40{
41 TRACE("head=%p tail=%p\n", &head, &tail);
42 head.next = &tail;
43 tail.prev = &head;
44}
45
46void FreeChangeNotifications()
47{
48 LPNOTIFICATIONLIST ptr, item;
49
50 TRACE("\n");
51
52 EnterCriticalSection(&SHELL32_ChangenotifyCS);
53 ptr = head.next;
54
55 while(ptr != &tail)
56 {
57 int i;
58 item = ptr;
59 ptr = ptr->next;
60
61 TRACE("item=%p\n", item);
62
63 /* free the item */
64 for (i=0; i<item->cidl;i++) SHFree(item->apidl[i].pidlPath);
65 SHFree(item->apidl);
66 SHFree(item);
67 }
68 head.next = NULL;
69 tail.prev = NULL;
70
71 LeaveCriticalSection(&SHELL32_ChangenotifyCS);
72
73 DeleteCriticalSection(&SHELL32_ChangenotifyCS);
74}
75
76static BOOL AddNode(LPNOTIFICATIONLIST item)
77{
78 LPNOTIFICATIONLIST last;
79
80 EnterCriticalSection(&SHELL32_ChangenotifyCS);
81
82 /* get last entry */
83 last = tail.prev;
84
85 /* link items */
86 last->next = item;
87 item->prev = last;
88 item->next = &tail;
89 tail.prev = item;
90 TRACE("item=%p prev=%p next=%p\n", item, item->prev, item->next);
91
92 LeaveCriticalSection(&SHELL32_ChangenotifyCS);
93
94 return TRUE;
95}
96
97static BOOL DeleteNode(LPNOTIFICATIONLIST item)
98{
99 LPNOTIFICATIONLIST ptr;
100 int ret = FALSE;
101
102 TRACE("item=%p\n", item);
103
104 EnterCriticalSection(&SHELL32_ChangenotifyCS);
105
106 ptr = head.next;
107#ifdef __WIN32OS2__
108 while((ptr != &tail)/* && (ret == FALSE) see the rant below */)
109#else
110 while((ptr != &tail) && (ret == FALSE))
111#endif
112 {
113 TRACE("ptr=%p\n", ptr);
114
115 if (ptr == item)
116 {
117 int i;
118
119 TRACE("item=%p prev=%p next=%p\n", item, item->prev, item->next);
120
121 /* remove item from list */
122 item->prev->next = item->next;
123 item->next->prev = item->prev;
124
125 /* free the item */
126 for (i=0; i<item->cidl;i++) SHFree(item->apidl[i].pidlPath);
127 SHFree(item->apidl);
128 SHFree(item);
129#ifdef __WIN32OS2__
130 /* ret = TRUE;
131 * <rant> HEY! Have you guys ever heard about the break keyword?
132 * And please don't test if ret == FALSE. Test !ret!!! </rant>
133 * Anyway, ptr == item, we free item hence the memory shouldn't be
134 * accessed by us any longer. We have to break here so we do NOT do
135 * the next operation below!
136 * -bird-
137 */
138 break;
139#else
140 ret = TRUE;
141#endif
142 }
143 ptr = ptr->next;
144 }
145
146 LeaveCriticalSection(&SHELL32_ChangenotifyCS);
147 return ret;
148
149}
150
151/*************************************************************************
152 * SHChangeNotifyRegister [SHELL32.2]
153 *
154 */
155HANDLE WINAPI
156SHChangeNotifyRegister(
157 HWND hwnd,
158 LONG dwFlags,
159 LONG wEventMask,
160 DWORD uMsg,
161 int cItems,
162 LPCNOTIFYREGISTER lpItems)
163{
164 LPNOTIFICATIONLIST item;
165 int i;
166
167 item = SHAlloc(sizeof(NOTIFICATIONLIST));
168
169 TRACE("(0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08x,%p) item=%p\n",
170 hwnd,dwFlags,wEventMask,uMsg,cItems,lpItems,item);
171
172 item->next = NULL;
173 item->prev = NULL;
174 item->cidl = cItems;
175 item->apidl = SHAlloc(sizeof(NOTIFYREGISTER) * cItems);
176 for(i=0;i<cItems;i++)
177 {
178 item->apidl[i].pidlPath = ILClone(lpItems[i].pidlPath);
179 item->apidl[i].bWatchSubtree = lpItems[i].bWatchSubtree;
180 }
181 item->hwnd = hwnd;
182 item->uMsg = uMsg;
183 item->wEventMask = wEventMask;
184 item->dwFlags = dwFlags;
185 AddNode(item);
186 return (HANDLE)item;
187}
188
189/*************************************************************************
190 * SHChangeNotifyDeregister [SHELL32.4]
191 */
192BOOL WINAPI
193SHChangeNotifyDeregister(
194 HANDLE hNotify)
195{
196 TRACE("(0x%08x)\n",hNotify);
197
198 return DeleteNode((LPNOTIFICATIONLIST)hNotify);;
199}
200
201/*************************************************************************
202 * SHChangeNotifyUpdateEntryList [SHELL32.5]
203 */
204BOOL WINAPI
205SHChangeNotifyUpdateEntryList(DWORD unknown1, DWORD unknown2,
206 DWORD unknown3, DWORD unknown4)
207{
208 FIXME("(0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx)\n",
209 unknown1, unknown2, unknown3, unknown4);
210
211 return -1;
212}
213
214/*************************************************************************
215 * SHChangeNotify [SHELL32.239]
216 */
217void WINAPI SHChangeNotifyW (LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
218{
219 LPITEMIDLIST pidl1=(LPITEMIDLIST)dwItem1, pidl2=(LPITEMIDLIST)dwItem2;
220 LPNOTIFICATIONLIST ptr;
221
222 TRACE("(0x%08lx,0x%08x,%p,%p):stub.\n", wEventId,uFlags,dwItem1,dwItem2);
223
224 /* convert paths in IDLists*/
225 if(uFlags & SHCNF_PATHA)
226 {
227 DWORD dummy;
228 if (dwItem1) SHILCreateFromPathA((LPCSTR)dwItem1, &pidl1, &dummy);
229 if (dwItem2) SHILCreateFromPathA((LPCSTR)dwItem2, &pidl2, &dummy);
230 }
231
232 EnterCriticalSection(&SHELL32_ChangenotifyCS);
233
234 /* loop through the list */
235 ptr = head.next;
236 while(ptr != &tail)
237 {
238 TRACE("trying %p\n", ptr);
239
240 if(wEventId & ptr->wEventMask)
241 {
242 TRACE("notifying\n");
243 SendMessageA(ptr->hwnd, ptr->uMsg, (WPARAM)pidl1, (LPARAM)pidl2);
244 }
245 ptr = ptr->next;
246 }
247
248 LeaveCriticalSection(&SHELL32_ChangenotifyCS);
249
250 if(uFlags & SHCNF_PATHA)
251 {
252 if (pidl1) SHFree(pidl1);
253 if (pidl2) SHFree(pidl2);
254 }
255}
256
257/*************************************************************************
258 * SHChangeNotify [SHELL32.239]
259 */
260void WINAPI SHChangeNotifyA (LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
261{
262 LPITEMIDLIST Pidls[2];
263 LPNOTIFICATIONLIST ptr;
264
265 Pidls[0] = (LPITEMIDLIST)dwItem1;
266 Pidls[1] = (LPITEMIDLIST)dwItem2;
267
268 TRACE("(0x%08lx,0x%08x,%p,%p):stub.\n", wEventId,uFlags,dwItem1,dwItem2);
269
270 /* convert paths in IDLists*/
271 if(uFlags & SHCNF_PATHA)
272 {
273 DWORD dummy;
274 if (Pidls[0]) SHILCreateFromPathA((LPCSTR)dwItem1, &Pidls[0], &dummy);
275 if (Pidls[1]) SHILCreateFromPathA((LPCSTR)dwItem2, &Pidls[1], &dummy);
276 }
277
278 EnterCriticalSection(&SHELL32_ChangenotifyCS);
279
280 /* loop through the list */
281 ptr = head.next;
282 while(ptr != &tail)
283 {
284 TRACE("trying %p\n", ptr);
285
286 if(wEventId & ptr->wEventMask)
287 {
288 TRACE("notifying\n");
289 SendMessageA(ptr->hwnd, ptr->uMsg, (WPARAM)&Pidls, (LPARAM)wEventId);
290 }
291 ptr = ptr->next;
292 }
293
294 LeaveCriticalSection(&SHELL32_ChangenotifyCS);
295
296 /* if we allocated it, free it */
297 if(uFlags & SHCNF_PATHA)
298 {
299 if (Pidls[0]) SHFree(Pidls[0]);
300 if (Pidls[1]) SHFree(Pidls[1]);
301 }
302}
303
304/*************************************************************************
305 * SHChangeNotifyAW [SHELL32.239]
306 */
307void WINAPI SHChangeNotifyAW (LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
308{
309 if(SHELL_OsIsUnicode())
310 SHChangeNotifyW (wEventId, uFlags, dwItem1, dwItem2);
311 else
312 SHChangeNotifyA (wEventId, uFlags, dwItem1, dwItem2);
313}
314
315/*************************************************************************
316 * NTSHChangeNotifyRegister [SHELL32.640]
317 * NOTES
318 * Idlist is an array of structures and Count specifies how many items in the array
319 * (usually just one I think).
320 */
321DWORD WINAPI NTSHChangeNotifyRegister(
322 HWND hwnd,
323 LONG events1,
324 LONG events2,
325 DWORD msg,
326 int count,
327 LPNOTIFYREGISTER idlist)
328{
329 FIXME("(0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08x,%p):stub.\n",
330 hwnd,events1,events2,msg,count,idlist);
331 return 0;
332}
333
334/*************************************************************************
335 * SHChangeNotification_Lock [SHELL32.644]
336 */
337HANDLE WINAPI SHChangeNotification_Lock(
338 HANDLE hMemoryMap,
339 DWORD dwProcessId,
340 LPCITEMIDLIST **lppidls,
341 LPLONG lpwEventId)
342{
343 FIXME("\n");
344 return 0;
345}
346
347/*************************************************************************
348 * SHChangeNotification_Unlock [SHELL32.645]
349 */
350BOOL WINAPI SHChangeNotification_Unlock (
351 HANDLE hLock)
352{
353 FIXME("\n");
354 return 0;
355}
356
357/*************************************************************************
358 * NTSHChangeNotifyDeregister [SHELL32.641]
359 */
360DWORD WINAPI NTSHChangeNotifyDeregister(LONG x1)
361{
362 FIXME("(0x%08lx):stub.\n",x1);
363 return 0;
364}
365
Note: See TracBrowser for help on using the repository browser.