Skip to content
Snippets Groups Projects
Commit 50f067b7 authored by Juergen Schmied's avatar Juergen Schmied Committed by Alexandre Julliard
Browse files

Basic implementation of shell notifications.

parent f516cd95
No related branches found
No related tags found
No related merge requests found
......@@ -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) */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment