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

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

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

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