When including 'wine/port.h', include it first.
[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 "undocshell.h"
14
15 DEFAULT_DEBUG_CHANNEL(shell);
16
17 static CRITICAL_SECTION SHELL32_ChangenotifyCS = CRITICAL_SECTION_INIT("SHELL32_ChangenotifyCS");
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  * SHChangeNotifyUpdateEntryList                [SHELL32.5]
183  */
184 BOOL WINAPI
185 SHChangeNotifyUpdateEntryList(DWORD unknown1, DWORD unknown2,
186                               DWORD unknown3, DWORD unknown4)
187 {
188         FIXME("(0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx)\n",
189               unknown1, unknown2, unknown3, unknown4);
190
191         return -1;
192 }
193
194 /*************************************************************************
195  * SHChangeNotify                               [SHELL32.@]
196  */
197 void WINAPI SHChangeNotifyW (LONG wEventId, UINT  uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
198 {
199         LPITEMIDLIST pidl1=(LPITEMIDLIST)dwItem1, pidl2=(LPITEMIDLIST)dwItem2;
200         LPNOTIFICATIONLIST ptr;
201         
202         TRACE("(0x%08lx,0x%08x,%p,%p):stub.\n", wEventId,uFlags,dwItem1,dwItem2);
203
204         /* convert paths in IDLists*/
205         if(uFlags & SHCNF_PATHA)
206         {
207           DWORD dummy;
208           if (dwItem1) SHILCreateFromPathA((LPCSTR)dwItem1, &pidl1, &dummy);
209           if (dwItem2) SHILCreateFromPathA((LPCSTR)dwItem2, &pidl2, &dummy);
210         }
211         
212         EnterCriticalSection(&SHELL32_ChangenotifyCS);
213         
214         /* loop through the list */
215         ptr = head.next;
216         while(ptr != &tail)
217         {
218           TRACE("trying %p\n", ptr);
219           
220           if(wEventId & ptr->wEventMask)
221           {
222             TRACE("notifying\n");
223             SendMessageA(ptr->hwnd, ptr->uMsg, (WPARAM)pidl1, (LPARAM)pidl2);
224           }
225           ptr = ptr->next;
226         }
227         
228         LeaveCriticalSection(&SHELL32_ChangenotifyCS);
229
230         if(uFlags & SHCNF_PATHA)
231         {
232             if (pidl1) SHFree(pidl1);
233             if (pidl2) SHFree(pidl2);
234         }
235 }
236
237 /*************************************************************************
238  * SHChangeNotify                               [SHELL32.@]
239  */
240 void WINAPI SHChangeNotifyA (LONG wEventId, UINT  uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
241 {
242         LPITEMIDLIST Pidls[2];
243         LPNOTIFICATIONLIST ptr;
244         
245         Pidls[0] = (LPITEMIDLIST)dwItem1;
246         Pidls[1] = (LPITEMIDLIST)dwItem2;
247
248         TRACE("(0x%08lx,0x%08x,%p,%p):stub.\n", wEventId,uFlags,dwItem1,dwItem2);
249
250         /* convert paths in IDLists*/
251         if(uFlags & SHCNF_PATHA)
252         {
253           DWORD dummy;
254           if (Pidls[0]) SHILCreateFromPathA((LPCSTR)dwItem1, &Pidls[0], &dummy);
255           if (Pidls[1]) SHILCreateFromPathA((LPCSTR)dwItem2, &Pidls[1], &dummy);
256         }
257         
258         EnterCriticalSection(&SHELL32_ChangenotifyCS);
259         
260         /* loop through the list */
261         ptr = head.next;
262         while(ptr != &tail)
263         {
264           TRACE("trying %p\n", ptr);
265           
266           if(wEventId & ptr->wEventMask)
267           {
268             TRACE("notifying\n");
269             SendMessageA(ptr->hwnd, ptr->uMsg, (WPARAM)&Pidls, (LPARAM)wEventId);
270           }
271           ptr = ptr->next;
272         }
273         
274         LeaveCriticalSection(&SHELL32_ChangenotifyCS);
275
276         /* if we allocated it, free it */
277         if(uFlags & SHCNF_PATHA)
278         {
279             if (Pidls[0]) SHFree(Pidls[0]);
280             if (Pidls[1]) SHFree(Pidls[1]);
281         }
282 }
283
284 /*************************************************************************
285  * SHChangeNotify                               [SHELL32.@]
286  */
287 void WINAPI SHChangeNotifyAW (LONG wEventId, UINT  uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
288 {
289         if(SHELL_OsIsUnicode())
290           SHChangeNotifyW (wEventId, uFlags, dwItem1, dwItem2);
291         else
292           SHChangeNotifyA (wEventId, uFlags, dwItem1, dwItem2);
293 }
294
295 /*************************************************************************
296  * NTSHChangeNotifyRegister                     [SHELL32.640]
297  * NOTES
298  *   Idlist is an array of structures and Count specifies how many items in the array
299  *   (usually just one I think).
300  */
301 DWORD WINAPI NTSHChangeNotifyRegister(
302     HWND hwnd,
303     LONG events1,
304     LONG events2,
305     DWORD msg,
306     int count,
307     LPNOTIFYREGISTER idlist)
308 {
309         FIXME("(0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08x,%p):stub.\n",
310                 hwnd,events1,events2,msg,count,idlist);
311         return 0;
312 }
313
314 /*************************************************************************
315  * SHChangeNotification_Lock                    [SHELL32.644]
316  */
317 HANDLE WINAPI SHChangeNotification_Lock(
318         HANDLE hMemoryMap,
319         DWORD dwProcessId,
320         LPCITEMIDLIST **lppidls,
321         LPLONG lpwEventId)
322 {
323         FIXME("\n");
324         return 0;
325 }
326
327 /*************************************************************************
328  * SHChangeNotification_Unlock                  [SHELL32.645]
329  */
330 BOOL WINAPI SHChangeNotification_Unlock (
331         HANDLE hLock)
332 {
333         FIXME("\n");
334         return 0;
335 }
336
337 /*************************************************************************
338  * NTSHChangeNotifyDeregister                   [SHELL32.641]
339  */
340 DWORD WINAPI NTSHChangeNotifyDeregister(LONG x1)
341 {
342         FIXME("(0x%08lx):stub.\n",x1);
343         return 0;
344 }
345