changenotify.c 8.44 KB
Newer Older
1 2 3
/*
 *	shell change notification
 *
4
 * Copyright 2000 Juergen Schmied
5
 *
6 7 8 9 10 11 12 13 14 15 16 17 18
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 20 21 22
 */

#include <string.h>

23
#include "wine/debug.h"
24 25
#include "pidl.h"
#include "shell32_main.h"
26
#include "undocshell.h"
27

28
WINE_DEFAULT_DEBUG_CHANNEL(shell);
29

30
static CRITICAL_SECTION SHELL32_ChangenotifyCS = CRITICAL_SECTION_INIT("SHELL32_ChangenotifyCS");
31

32
/* internal list of notification clients (internal) */
33 34 35
typedef struct _NOTIFICATIONLIST
{
	struct _NOTIFICATIONLIST *next;
36
	struct _NOTIFICATIONLIST *prev;
37 38
	HWND hwnd;		/* window to notify */
	DWORD uMsg;		/* message to send */
39
	LPNOTIFYREGISTER apidl; /* array of entries to watch*/
40 41 42 43 44
	UINT cidl;		/* number of pidls in array */
	LONG wEventMask;	/* subscribed events */
	DWORD dwFlags;		/* client flags */
} NOTIFICATIONLIST, *LPNOTIFICATIONLIST;

45 46
static NOTIFICATIONLIST head;
static NOTIFICATIONLIST tail;
47 48 49

void InitChangeNotifications()
{
50
	TRACE("head=%p tail=%p\n", &head, &tail);
51 52 53 54 55 56 57 58
	head.next = &tail;
	tail.prev = &head;
}

void FreeChangeNotifications()
{
	LPNOTIFICATIONLIST ptr, item;

59 60 61
	TRACE("\n");

	EnterCriticalSection(&SHELL32_ChangenotifyCS);
62 63 64
	ptr = head.next;

	while(ptr != &tail)
65
	{
66
	  UINT i;
67 68 69
	  item = ptr;
	  ptr = ptr->next;

70
	  TRACE("item=%p\n", item);
71

72
	  /* free the item */
73
	  for (i=0; i<item->cidl;i++) SHFree(item->apidl[i].pidlPath);
74 75 76 77 78
	  SHFree(item->apidl);
	  SHFree(item);
	}
	head.next = NULL;
	tail.prev = NULL;
79 80 81 82

	LeaveCriticalSection(&SHELL32_ChangenotifyCS);

	DeleteCriticalSection(&SHELL32_ChangenotifyCS);
83 84 85 86 87
}

static BOOL AddNode(LPNOTIFICATIONLIST item)
{
	LPNOTIFICATIONLIST last;
88

89
	EnterCriticalSection(&SHELL32_ChangenotifyCS);
90 91 92 93 94 95 96 97 98

	/* get last entry */
	last = tail.prev;

	/* link items */
	last->next = item;
	item->prev = last;
	item->next = &tail;
	tail.prev = item;
99 100 101
	TRACE("item=%p prev=%p next=%p\n", item, item->prev, item->next);

	LeaveCriticalSection(&SHELL32_ChangenotifyCS);
102

103
	return TRUE;
104 105 106 107 108 109 110
}

static BOOL DeleteNode(LPNOTIFICATIONLIST item)
{
	LPNOTIFICATIONLIST ptr;
	int ret = FALSE;

111 112 113
	TRACE("item=%p\n", item);

	EnterCriticalSection(&SHELL32_ChangenotifyCS);
114 115

	ptr = head.next;
116
	while(ptr != &tail)
117
	{
118
	  TRACE("ptr=%p\n", ptr);
119

120 121
	  if (ptr == item)
	  {
122
	    UINT i;
123

124 125
	    TRACE("item=%p prev=%p next=%p\n", item, item->prev, item->next);

126 127 128 129 130
	    /* remove item from list */
	    item->prev->next = item->next;
	    item->next->prev = item->prev;

	    /* free the item */
131
	    for (i=0; i<item->cidl;i++) SHFree(item->apidl[i].pidlPath);
132 133
	    SHFree(item->apidl);
	    SHFree(item);
134

135
	    ret = TRUE;
136
	    break;
137
	  }
138
	  ptr = ptr->next;
139
	}
140

141
	LeaveCriticalSection(&SHELL32_ChangenotifyCS);
142
	return ret;
143

144 145 146 147 148 149 150 151 152 153 154 155 156
}

/*************************************************************************
 * SHChangeNotifyRegister			[SHELL32.2]
 *
 */
HANDLE WINAPI
SHChangeNotifyRegister(
    HWND hwnd,
    LONG dwFlags,
    LONG wEventMask,
    DWORD uMsg,
    int cItems,
157
    LPCNOTIFYREGISTER lpItems)
158 159 160 161 162
{
	LPNOTIFICATIONLIST item;
	int i;

	item = SHAlloc(sizeof(NOTIFICATIONLIST));
163

164
	TRACE("(%p,0x%08lx,0x%08lx,0x%08lx,0x%08x,%p) item=%p\n",
165
		hwnd,dwFlags,wEventMask,uMsg,cItems,lpItems,item);
166

167 168 169 170 171 172
	item->next = NULL;
	item->prev = NULL;
	item->cidl = cItems;
	item->apidl = SHAlloc(sizeof(NOTIFYREGISTER) * cItems);
	for(i=0;i<cItems;i++)
	{
173 174
	  item->apidl[i].pidlPath = ILClone(lpItems[i].pidlPath);
	  item->apidl[i].bWatchSubtree = lpItems[i].bWatchSubtree;
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
	}
	item->hwnd = hwnd;
	item->uMsg = uMsg;
	item->wEventMask = wEventMask;
	item->dwFlags = dwFlags;
	AddNode(item);
	return (HANDLE)item;
}

/*************************************************************************
 * SHChangeNotifyDeregister			[SHELL32.4]
 */
BOOL WINAPI
SHChangeNotifyDeregister(
	HANDLE hNotify)
{
191
	TRACE("(%p)\n",hNotify);
192

193
	return DeleteNode((LPNOTIFICATIONLIST)hNotify);
194 195
}

196 197 198 199 200 201 202 203 204 205 206 207 208
/*************************************************************************
 * SHChangeNotifyUpdateEntryList       		[SHELL32.5]
 */
BOOL WINAPI
SHChangeNotifyUpdateEntryList(DWORD unknown1, DWORD unknown2,
			      DWORD unknown3, DWORD unknown4)
{
	FIXME("(0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx)\n",
	      unknown1, unknown2, unknown3, unknown4);

	return -1;
}

209
/*************************************************************************
210
 * SHChangeNotify				[SHELL32.@]
211 212 213
 */
void WINAPI SHChangeNotifyW (LONG wEventId, UINT  uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
{
214 215
	LPITEMIDLIST pidl1=(LPITEMIDLIST)dwItem1, pidl2=(LPITEMIDLIST)dwItem2;
	LPNOTIFICATIONLIST ptr;
216

217 218 219 220 221 222 223 224 225
	TRACE("(0x%08lx,0x%08x,%p,%p):stub.\n", wEventId,uFlags,dwItem1,dwItem2);

	/* convert paths in IDLists*/
	if(uFlags & SHCNF_PATHA)
	{
	  DWORD dummy;
	  if (dwItem1) SHILCreateFromPathA((LPCSTR)dwItem1, &pidl1, &dummy);
	  if (dwItem2) SHILCreateFromPathA((LPCSTR)dwItem2, &pidl2, &dummy);
	}
226

227
	EnterCriticalSection(&SHELL32_ChangenotifyCS);
228

229 230 231 232 233
	/* loop through the list */
	ptr = head.next;
	while(ptr != &tail)
	{
	  TRACE("trying %p\n", ptr);
234

235 236 237 238 239 240 241
	  if(wEventId & ptr->wEventMask)
	  {
	    TRACE("notifying\n");
	    SendMessageA(ptr->hwnd, ptr->uMsg, (WPARAM)pidl1, (LPARAM)pidl2);
	  }
	  ptr = ptr->next;
	}
242

243 244 245 246
	LeaveCriticalSection(&SHELL32_ChangenotifyCS);

	if(uFlags & SHCNF_PATHA)
	{
247 248
            if (pidl1) SHFree(pidl1);
            if (pidl2) SHFree(pidl2);
249
	}
250 251
}

252
/*************************************************************************
253
 * SHChangeNotify				[SHELL32.@]
254
 */
255 256
void WINAPI SHChangeNotifyA (LONG wEventId, UINT  uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
{
257 258
	LPITEMIDLIST Pidls[2];
	LPNOTIFICATIONLIST ptr;
259

260 261 262 263 264 265 266 267 268 269 270 271
	Pidls[0] = (LPITEMIDLIST)dwItem1;
	Pidls[1] = (LPITEMIDLIST)dwItem2;

	TRACE("(0x%08lx,0x%08x,%p,%p):stub.\n", wEventId,uFlags,dwItem1,dwItem2);

	/* convert paths in IDLists*/
	if(uFlags & SHCNF_PATHA)
	{
	  DWORD dummy;
	  if (Pidls[0]) SHILCreateFromPathA((LPCSTR)dwItem1, &Pidls[0], &dummy);
	  if (Pidls[1]) SHILCreateFromPathA((LPCSTR)dwItem2, &Pidls[1], &dummy);
	}
272

273
	EnterCriticalSection(&SHELL32_ChangenotifyCS);
274

275 276 277 278 279
	/* loop through the list */
	ptr = head.next;
	while(ptr != &tail)
	{
	  TRACE("trying %p\n", ptr);
280

281 282 283 284 285 286 287
	  if(wEventId & ptr->wEventMask)
	  {
	    TRACE("notifying\n");
	    SendMessageA(ptr->hwnd, ptr->uMsg, (WPARAM)&Pidls, (LPARAM)wEventId);
	  }
	  ptr = ptr->next;
	}
288

289 290 291 292 293
	LeaveCriticalSection(&SHELL32_ChangenotifyCS);

	/* if we allocated it, free it */
	if(uFlags & SHCNF_PATHA)
	{
294 295
            if (Pidls[0]) SHFree(Pidls[0]);
            if (Pidls[1]) SHFree(Pidls[1]);
296
	}
297 298
}

299
/*************************************************************************
Patrik Stridvall's avatar
Patrik Stridvall committed
300
 * SHChangeNotify				[SHELL32.@]
301
 */
302 303
void WINAPI SHChangeNotifyAW (LONG wEventId, UINT  uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
{
304
	if(SHELL_OsIsUnicode())
305 306 307
	  SHChangeNotifyW (wEventId, uFlags, dwItem1, dwItem2);
	else
	  SHChangeNotifyA (wEventId, uFlags, dwItem1, dwItem2);
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
}

/*************************************************************************
 * NTSHChangeNotifyRegister			[SHELL32.640]
 * NOTES
 *   Idlist is an array of structures and Count specifies how many items in the array
 *   (usually just one I think).
 */
DWORD WINAPI NTSHChangeNotifyRegister(
    HWND hwnd,
    LONG events1,
    LONG events2,
    DWORD msg,
    int count,
    LPNOTIFYREGISTER idlist)
{
324
	FIXME("(%p,0x%08lx,0x%08lx,0x%08lx,0x%08x,%p):stub.\n",
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
		hwnd,events1,events2,msg,count,idlist);
	return 0;
}

/*************************************************************************
 * SHChangeNotification_Lock			[SHELL32.644]
 */
HANDLE WINAPI SHChangeNotification_Lock(
	HANDLE hMemoryMap,
	DWORD dwProcessId,
	LPCITEMIDLIST **lppidls,
	LPLONG lpwEventId)
{
	FIXME("\n");
	return 0;
}

/*************************************************************************
 * SHChangeNotification_Unlock			[SHELL32.645]
 */
BOOL WINAPI SHChangeNotification_Unlock (
	HANDLE hLock)
{
	FIXME("\n");
	return 0;
}

/*************************************************************************
 * NTSHChangeNotifyDeregister			[SHELL32.641]
 */
DWORD WINAPI NTSHChangeNotifyDeregister(LONG x1)
{
	FIXME("(0x%08lx):stub.\n",x1);
	return 0;
}