blob: 1451890444c01a9f0a9d1e548ca27bc9e5a7274e [file] [log] [blame]
/*
* shell change notification
*
* Juergen Schmied <juergen.schmied@debitel.de>
*
*/
#include <string.h>
#include "debugtools.h"
#include "pidl.h"
#include "shell32_main.h"
#include "undocshell.h"
DEFAULT_DEBUG_CHANNEL(shell);
static CRITICAL_SECTION SHELL32_ChangenotifyCS = CRITICAL_SECTION_INIT("SHELL32_ChangenotifyCS");
/* internal list of notification clients (internal) */
typedef struct _NOTIFICATIONLIST
{
struct _NOTIFICATIONLIST *next;
struct _NOTIFICATIONLIST *prev;
HWND hwnd; /* window to notify */
DWORD uMsg; /* message to send */
LPNOTIFYREGISTER apidl; /* array of entrys to watch*/
UINT cidl; /* number of pidls in array */
LONG wEventMask; /* subscribed events */
DWORD dwFlags; /* client flags */
} NOTIFICATIONLIST, *LPNOTIFICATIONLIST;
static NOTIFICATIONLIST head;
static NOTIFICATIONLIST tail;
void InitChangeNotifications()
{
TRACE("head=%p tail=%p\n", &head, &tail);
head.next = &tail;
tail.prev = &head;
}
void FreeChangeNotifications()
{
LPNOTIFICATIONLIST ptr, item;
TRACE("\n");
EnterCriticalSection(&SHELL32_ChangenotifyCS);
ptr = head.next;
while(ptr != &tail)
{
int i;
item = ptr;
ptr = ptr->next;
TRACE("item=%p\n", item);
/* free the item */
for (i=0; i<item->cidl;i++) SHFree(item->apidl[i].pidlPath);
SHFree(item->apidl);
SHFree(item);
}
head.next = NULL;
tail.prev = NULL;
LeaveCriticalSection(&SHELL32_ChangenotifyCS);
DeleteCriticalSection(&SHELL32_ChangenotifyCS);
}
static BOOL AddNode(LPNOTIFICATIONLIST item)
{
LPNOTIFICATIONLIST last;
EnterCriticalSection(&SHELL32_ChangenotifyCS);
/* get last entry */
last = tail.prev;
/* link items */
last->next = item;
item->prev = last;
item->next = &tail;
tail.prev = item;
TRACE("item=%p prev=%p next=%p\n", item, item->prev, item->next);
LeaveCriticalSection(&SHELL32_ChangenotifyCS);
return TRUE;
}
static BOOL DeleteNode(LPNOTIFICATIONLIST item)
{
LPNOTIFICATIONLIST ptr;
int ret = FALSE;
TRACE("item=%p\n", item);
EnterCriticalSection(&SHELL32_ChangenotifyCS);
ptr = head.next;
while((ptr != &tail) && (ret == FALSE))
{
TRACE("ptr=%p\n", ptr);
if (ptr == item)
{
int i;
TRACE("item=%p prev=%p next=%p\n", item, item->prev, item->next);
/* remove item from list */
item->prev->next = item->next;
item->next->prev = item->prev;
/* free the item */
for (i=0; i<item->cidl;i++) SHFree(item->apidl[i].pidlPath);
SHFree(item->apidl);
SHFree(item);
ret = TRUE;
}
ptr = ptr->next;
}
LeaveCriticalSection(&SHELL32_ChangenotifyCS);
return ret;
}
/*************************************************************************
* SHChangeNotifyRegister [SHELL32.2]
*
*/
HANDLE WINAPI
SHChangeNotifyRegister(
HWND hwnd,
LONG dwFlags,
LONG wEventMask,
DWORD uMsg,
int cItems,
LPCNOTIFYREGISTER lpItems)
{
LPNOTIFICATIONLIST item;
int i;
item = SHAlloc(sizeof(NOTIFICATIONLIST));
TRACE("(0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08x,%p) item=%p\n",
hwnd,dwFlags,wEventMask,uMsg,cItems,lpItems,item);
item->next = NULL;
item->prev = NULL;
item->cidl = cItems;
item->apidl = SHAlloc(sizeof(NOTIFYREGISTER) * cItems);
for(i=0;i<cItems;i++)
{
item->apidl[i].pidlPath = ILClone(lpItems[i].pidlPath);
item->apidl[i].bWatchSubtree = lpItems[i].bWatchSubtree;
}
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)
{
TRACE("(0x%08x)\n",hNotify);
return DeleteNode((LPNOTIFICATIONLIST)hNotify);;
}
/*************************************************************************
* 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;
}
/*************************************************************************
* SHChangeNotify [SHELL32.@]
*/
void WINAPI SHChangeNotifyW (LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
{
LPITEMIDLIST pidl1=(LPITEMIDLIST)dwItem1, pidl2=(LPITEMIDLIST)dwItem2;
LPNOTIFICATIONLIST ptr;
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);
}
EnterCriticalSection(&SHELL32_ChangenotifyCS);
/* loop through the list */
ptr = head.next;
while(ptr != &tail)
{
TRACE("trying %p\n", ptr);
if(wEventId & ptr->wEventMask)
{
TRACE("notifying\n");
SendMessageA(ptr->hwnd, ptr->uMsg, (WPARAM)pidl1, (LPARAM)pidl2);
}
ptr = ptr->next;
}
LeaveCriticalSection(&SHELL32_ChangenotifyCS);
if(uFlags & SHCNF_PATHA)
{
if (pidl1) SHFree(pidl1);
if (pidl2) SHFree(pidl2);
}
}
/*************************************************************************
* SHChangeNotify [SHELL32.@]
*/
void WINAPI SHChangeNotifyA (LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
{
LPITEMIDLIST Pidls[2];
LPNOTIFICATIONLIST ptr;
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);
}
EnterCriticalSection(&SHELL32_ChangenotifyCS);
/* loop through the list */
ptr = head.next;
while(ptr != &tail)
{
TRACE("trying %p\n", ptr);
if(wEventId & ptr->wEventMask)
{
TRACE("notifying\n");
SendMessageA(ptr->hwnd, ptr->uMsg, (WPARAM)&Pidls, (LPARAM)wEventId);
}
ptr = ptr->next;
}
LeaveCriticalSection(&SHELL32_ChangenotifyCS);
/* if we allocated it, free it */
if(uFlags & SHCNF_PATHA)
{
if (Pidls[0]) SHFree(Pidls[0]);
if (Pidls[1]) SHFree(Pidls[1]);
}
}
/*************************************************************************
* SHChangeNotify [SHELL32.@]
*/
void WINAPI SHChangeNotifyAW (LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
{
if(SHELL_OsIsUnicode())
SHChangeNotifyW (wEventId, uFlags, dwItem1, dwItem2);
else
SHChangeNotifyA (wEventId, uFlags, dwItem1, dwItem2);
}
/*************************************************************************
* 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)
{
FIXME("(0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08x,%p):stub.\n",
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;
}