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