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