diff --git a/dlls/shell32/changenotify.c b/dlls/shell32/changenotify.c index f880dc1795c..e56e44c4042 100644 --- a/dlls/shell32/changenotify.c +++ b/dlls/shell32/changenotify.c @@ -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; icidl;i++) SHFree(item->apidl[i]); + 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; - /* 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; icidl;i++) SHFree(item->apidl[i]); + for (i=0; icidl;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;iapidl[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) diff --git a/dlls/shell32/shell32_main.c b/dlls/shell32/shell32_main.c index 30c87284cd1..1e11e25d88a 100644 --- a/dlls/shell32/shell32_main.c +++ b/dlls/shell32/shell32_main.c @@ -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) { diff --git a/dlls/shell32/shell32_main.h b/dlls/shell32/shell32_main.h index e60e85b15e2..1b7a711e0b3 100644 --- a/dlls/shell32/shell32_main.h +++ b/dlls/shell32/shell32_main.h @@ -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 diff --git a/include/wine/undocshell.h b/include/wine/undocshell.h index 5b7f69b5ed4..1bdd0394e68 100644 --- a/include/wine/undocshell.h +++ b/include/wine/undocshell.h @@ -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) */