/* * shell change notification * * Copyright 2000 Juergen Schmied * * 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 */ #include #include "wine/debug.h" #include "pidl.h" #include "shell32_main.h" #include "undocshell.h" WINE_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 entries 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; icidl;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; icidl;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;iapidl[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; }