Basic implementation of shell notifications.
This commit is contained in:
parent
f516cd9554
commit
50f067b726
|
@ -15,34 +15,16 @@
|
|||
|
||||
DEFAULT_DEBUG_CHANNEL(shell)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LPCITEMIDLIST pidlPath;
|
||||
BOOL bWatchSubtree;
|
||||
} NOTIFYREGISTER, *LPNOTIFYREGISTER;
|
||||
static CRITICAL_SECTION SHELL32_ChangenotifyCS;
|
||||
|
||||
typedef const LPNOTIFYREGISTER LPCNOTIFYREGISTER;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
USHORT cb;
|
||||
DWORD dwItem1;
|
||||
DWORD dwItem2;
|
||||
} DWORDITEMID;
|
||||
|
||||
|
||||
#define SHCNF_ACCEPT_INTERRUPTS 0x0001
|
||||
#define SHCNF_ACCEPT_NON_INTERRUPTS 0x0002
|
||||
#define SHCNF_NO_PROXY 0x8001
|
||||
|
||||
/* internal list of notification clients */
|
||||
/* 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*/
|
||||
LPNOTIFYREGISTER apidl; /* array of entrys to watch*/
|
||||
UINT cidl; /* number of pidls in array */
|
||||
LONG wEventMask; /* subscribed events */
|
||||
DWORD dwFlags; /* client flags */
|
||||
|
@ -53,6 +35,10 @@ NOTIFICATIONLIST tail;
|
|||
|
||||
void InitChangeNotifications()
|
||||
{
|
||||
TRACE("head=%p tail=%p\n", &head, &tail);
|
||||
|
||||
InitializeCriticalSection(&SHELL32_ChangenotifyCS);
|
||||
MakeCriticalSectionGlobal(&SHELL32_ChangenotifyCS);
|
||||
ZeroMemory(&head, sizeof(NOTIFICATIONLIST));
|
||||
ZeroMemory(&tail, sizeof(NOTIFICATIONLIST));
|
||||
head.next = &tail;
|
||||
|
@ -63,6 +49,9 @@ void FreeChangeNotifications()
|
|||
{
|
||||
LPNOTIFICATIONLIST ptr, item;
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
EnterCriticalSection(&SHELL32_ChangenotifyCS);
|
||||
ptr = head.next;
|
||||
|
||||
while(ptr != &tail)
|
||||
|
@ -71,20 +60,26 @@ void FreeChangeNotifications()
|
|||
item = ptr;
|
||||
ptr = ptr->next;
|
||||
|
||||
TRACE("item=%p\n", item);
|
||||
|
||||
/* free the item */
|
||||
for (i=0; i<item->cidl;i++) SHFree(item->apidl[i]);
|
||||
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;
|
||||
|
||||
/* lock list */
|
||||
EnterCriticalSection(&SHELL32_ChangenotifyCS);
|
||||
|
||||
/* get last entry */
|
||||
last = tail.prev;
|
||||
|
@ -94,9 +89,11 @@ static BOOL AddNode(LPNOTIFICATIONLIST item)
|
|||
item->prev = last;
|
||||
item->next = &tail;
|
||||
tail.prev = item;
|
||||
return TRUE;
|
||||
TRACE("item=%p prev=%p next=%p\n", item, item->prev, item->next);
|
||||
|
||||
/* unlock list */
|
||||
LeaveCriticalSection(&SHELL32_ChangenotifyCS);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL DeleteNode(LPNOTIFICATIONLIST item)
|
||||
|
@ -104,28 +101,35 @@ static BOOL DeleteNode(LPNOTIFICATIONLIST item)
|
|||
LPNOTIFICATIONLIST ptr;
|
||||
int ret = FALSE;
|
||||
|
||||
/* lock list */
|
||||
TRACE("item=%p\n", item);
|
||||
|
||||
EnterCriticalSection(&SHELL32_ChangenotifyCS);
|
||||
|
||||
ptr = head.next;
|
||||
while(ptr != &tail)
|
||||
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]);
|
||||
for (i=0; i<item->cidl;i++) SHFree(item->apidl[i].pidlPath);
|
||||
SHFree(item->apidl);
|
||||
SHFree(item);
|
||||
ret = TRUE;
|
||||
}
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
/* unlock list */
|
||||
LeaveCriticalSection(&SHELL32_ChangenotifyCS);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
@ -141,23 +145,24 @@ SHChangeNotifyRegister(
|
|||
LONG wEventMask,
|
||||
DWORD uMsg,
|
||||
int cItems,
|
||||
LPCNOTIFYREGISTER *lpItems)
|
||||
LPCNOTIFYREGISTER lpItems)
|
||||
{
|
||||
LPNOTIFICATIONLIST item;
|
||||
int i;
|
||||
|
||||
TRACE("(0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08x,%p)\n",
|
||||
hwnd,wEventMask,wEventMask,uMsg,cItems,lpItems);
|
||||
|
||||
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->apidl[i].pidlPath = ILClone(lpItems[i].pidlPath);
|
||||
item->apidl[i].bWatchSubtree = lpItems[i].bWatchSubtree;
|
||||
}
|
||||
item->hwnd = hwnd;
|
||||
item->uMsg = uMsg;
|
||||
|
@ -184,12 +189,86 @@ SHChangeNotifyDeregister(
|
|||
*/
|
||||
void WINAPI SHChangeNotifyW (LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
|
||||
{
|
||||
FIXME("(0x%08lx,0x%08x,%p,%p):stub.\n", wEventId,uFlags,dwItem1,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)
|
||||
{
|
||||
SHFree(pidl1);
|
||||
SHFree(pidl2);
|
||||
}
|
||||
}
|
||||
|
||||
void WINAPI SHChangeNotifyA (LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
|
||||
{
|
||||
FIXME("(0x%08lx,0x%08x,%p,%p):stub.\n", wEventId,uFlags,dwItem1,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)
|
||||
{
|
||||
SHFree(Pidls[0]);
|
||||
SHFree(Pidls[1]);
|
||||
}
|
||||
}
|
||||
|
||||
void WINAPI SHChangeNotifyAW (LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
|
||||
|
|
|
@ -108,7 +108,7 @@ DWORD WINAPI SHGetFileInfoA(LPCSTR path,DWORD dwFileAttributes,
|
|||
int iIndex;
|
||||
DWORD ret = TRUE, dwAttributes = 0;
|
||||
IShellFolder * psfParent = NULL;
|
||||
IExtractIcon * pei = NULL;
|
||||
IExtractIconA * pei = NULL;
|
||||
LPITEMIDLIST pidlLast, pidl = NULL;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
|
@ -179,9 +179,6 @@ DWORD WINAPI SHGetFileInfoA(LPCSTR path,DWORD dwFileAttributes,
|
|||
if (flags & SHGFI_LINKOVERLAY)
|
||||
FIXME("set icon to link, stub\n");
|
||||
|
||||
if (flags & SHGFI_OPENICON)
|
||||
FIXME("set to open icon, stub\n");
|
||||
|
||||
if (flags & SHGFI_SELECTED)
|
||||
FIXME("set icon to selected, stub\n");
|
||||
|
||||
|
@ -196,7 +193,7 @@ DWORD WINAPI SHGetFileInfoA(LPCSTR path,DWORD dwFileAttributes,
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = IExtractIconA_GetIconLocation(pei, 0, szLoaction, MAX_PATH, &iIndex, &uFlags);
|
||||
hr = IExtractIconA_GetIconLocation(pei, (flags & SHGFI_OPENICON)? GIL_OPENICON : 0,szLoaction, MAX_PATH, &iIndex, &uFlags);
|
||||
/* fixme what to do with the index? */
|
||||
|
||||
if(uFlags != GIL_NOTFILENAME)
|
||||
|
@ -238,20 +235,21 @@ DWORD WINAPI SHGetFileInfoA(LPCSTR path,DWORD dwFileAttributes,
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!(PidlToSicIndex(psfParent, pidlLast, (flags && SHGFI_LARGEICON), &(psfi->iIcon))))
|
||||
if (!(PidlToSicIndex(psfParent, pidlLast, (flags & SHGFI_LARGEICON),
|
||||
(flags & SHGFI_OPENICON)? GIL_OPENICON : 0, &(psfi->iIcon))))
|
||||
{
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
ret = (DWORD) ((flags && SHGFI_LARGEICON) ? ShellBigIconList : ShellSmallIconList);
|
||||
ret = (DWORD) ((flags & SHGFI_LARGEICON) ? ShellBigIconList : ShellSmallIconList);
|
||||
}
|
||||
}
|
||||
|
||||
/* icon handle */
|
||||
if (SUCCEEDED(hr) && (flags & SHGFI_ICON))
|
||||
psfi->hIcon = pImageList_GetIcon((flags && SHGFI_LARGEICON) ? ShellBigIconList:ShellSmallIconList, psfi->iIcon, ILD_NORMAL);
|
||||
psfi->hIcon = pImageList_GetIcon((flags & SHGFI_LARGEICON) ? ShellBigIconList:ShellSmallIconList, psfi->iIcon, ILD_NORMAL);
|
||||
|
||||
|
||||
if (flags & SHGFI_EXETYPE)
|
||||
|
@ -267,8 +265,8 @@ DWORD WINAPI SHGetFileInfoA(LPCSTR path,DWORD dwFileAttributes,
|
|||
ret = FALSE;
|
||||
|
||||
#ifdef MORE_DEBUG
|
||||
TRACE ("icon=0x%08x index=0x%08x attr=0x%08lx name=%s type=%s\n",
|
||||
psfi->hIcon, psfi->iIcon, psfi->dwAttributes, psfi->szDisplayName, psfi->szTypeName);
|
||||
TRACE ("icon=0x%08x index=0x%08x attr=0x%08lx name=%s type=%s ret=0x%08lx\n",
|
||||
psfi->hIcon, psfi->iIcon, psfi->dwAttributes, psfi->szDisplayName, psfi->szTypeName, ret);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
@ -782,11 +780,7 @@ BOOL WINAPI Shell32LibMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
|
|||
if (shell32_hInstance)
|
||||
{
|
||||
ERR("shell32.dll instantiated twice in one address space!\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we only want to call this the first time shell32 is instantiated */
|
||||
SHInitRestricted(NULL, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
shell32_hInstance = hinstDLL;
|
||||
|
@ -830,7 +824,8 @@ BOOL WINAPI Shell32LibMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
|
|||
|
||||
SIC_Initialize();
|
||||
SYSTRAY_Init();
|
||||
|
||||
InitChangeNotifications();
|
||||
SHInitRestricted(NULL, NULL);
|
||||
break;
|
||||
|
||||
case DLL_THREAD_ATTACH:
|
||||
|
@ -855,7 +850,8 @@ BOOL WINAPI Shell32LibMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
|
|||
}
|
||||
|
||||
SIC_Destroy();
|
||||
|
||||
FreeChangeNotifications();
|
||||
|
||||
/* this one is here to check if AddRef/Release is balanced */
|
||||
if (shell32_ObjCount)
|
||||
{
|
||||
|
|
|
@ -71,7 +71,7 @@ HRESULT WINAPI StrRetToStrN (LPVOID dest, DWORD len, LPSTRRET src, LPITEMIDLIST
|
|||
#define INVALID_INDEX -1
|
||||
BOOL SIC_Initialize(void);
|
||||
void SIC_Destroy(void);
|
||||
BOOL PidlToSicIndex (IShellFolder * sh, LPITEMIDLIST pidl, BOOL bBigIcon, UINT * pIndex);
|
||||
BOOL PidlToSicIndex (IShellFolder * sh, LPITEMIDLIST pidl, BOOL bBigIcon, UINT uFlags, UINT * pIndex);
|
||||
|
||||
/* Classes Root */
|
||||
BOOL HCR_MapTypeToValue ( LPCSTR szExtension, LPSTR szFileType, DWORD len, BOOL bPrependDot);
|
||||
|
@ -167,4 +167,7 @@ HGLOBAL RenderPREFEREDDROPEFFECT (DWORD dwFlags);
|
|||
/* Change Notification */
|
||||
void InitChangeNotifications(void);
|
||||
void FreeChangeNotifications(void);
|
||||
|
||||
/* file operation */
|
||||
BOOL SHELL_DeleteDirectoryA(LPCSTR pszDir);
|
||||
#endif
|
||||
|
|
|
@ -52,6 +52,43 @@ HRESULT WINAPI StrRetToStrNAW (LPVOID dest, DWORD len, LPSTRRET src, LPITEMIDLIS
|
|||
|
||||
HRESULT WINAPI StrRetToBufA (LPSTRRET src, LPITEMIDLIST pidl, LPSTR dest, DWORD len);
|
||||
HRESULT WINAPI StrRetToBufW (LPSTRRET src, LPITEMIDLIST pidl, LPWSTR dest, DWORD len);
|
||||
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* SHChangeNotifyRegister API
|
||||
*/
|
||||
#define SHCNF_ACCEPT_INTERRUPTS 0x0001
|
||||
#define SHCNF_ACCEPT_NON_INTERRUPTS 0x0002
|
||||
#define SHCNF_NO_PROXY 0x8001
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LPCITEMIDLIST pidlPath;
|
||||
BOOL bWatchSubtree;
|
||||
} NOTIFYREGISTER, *LPNOTIFYREGISTER;
|
||||
|
||||
typedef const LPNOTIFYREGISTER LPCNOTIFYREGISTER;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
USHORT cb;
|
||||
DWORD dwItem1;
|
||||
DWORD dwItem2;
|
||||
} DWORDITEMID;
|
||||
|
||||
HANDLE WINAPI SHChangeNotifyRegister(
|
||||
HWND hwnd,
|
||||
LONG dwFlags,
|
||||
LONG wEventMask,
|
||||
DWORD uMsg,
|
||||
int cItems,
|
||||
LPCNOTIFYREGISTER lpItems);
|
||||
|
||||
BOOL WINAPI SHChangeNotifyDeregister( HANDLE hNotify);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* defined(__cplusplus) */
|
||||
|
|
Loading…
Reference in New Issue