Commit 50f067b7 authored by Juergen Schmied's avatar Juergen Schmied Committed by Alexandre Julliard

Basic implementation of shell notifications.

parent f516cd95
......@@ -15,34 +15,16 @@
DEFAULT_DEBUG_CHANNEL(shell)
typedef struct
{
LPCITEMIDLIST pidlPath;
BOOL bWatchSubtree;
} NOTIFYREGISTER, *LPNOTIFYREGISTER;
typedef const LPNOTIFYREGISTER LPCNOTIFYREGISTER;
typedef struct
{
USHORT cb;
DWORD dwItem1;
DWORD dwItem2;
} DWORDITEMID;
static CRITICAL_SECTION SHELL32_ChangenotifyCS;
#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);
LeaveCriticalSection(&SHELL32_ChangenotifyCS);
/* unlock list */
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) */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment