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