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