OVERLAPPED overlapped; /* Overlapped structure */
BYTE *buffer; /* Async buffer to fill */
BYTE *backBuffer; /* Back buffer to swap buffer into */
+ struct _NOTIFICATIONLIST * pParent;
} SHChangeNotifyEntryInternal, *LPNOTIFYREGISTER;
#else
typedef SHChangeNotifyEntry *LPNOTIFYREGISTER;
LONG wEventMask; /* subscribed events */
DWORD dwFlags; /* client flags */
ULONG id;
+#ifdef __REACTOS__
+ volatile LONG wQueuedCount;
+#endif
} NOTIFICATIONLIST, *LPNOTIFICATIONLIST;
#ifdef __REACTOS__
static void DeleteNode(LPNOTIFICATIONLIST item)
{
UINT i;
+#ifdef __REACTOS__
+ LONG queued;
+#endif
TRACE("item=%p\n", item);
+#ifdef __REACTOS__
+ queued = InterlockedCompareExchange(&item->wQueuedCount, 0, 0);
+ if (queued != 0)
+ {
+ TRACE("Not freeing, still %d queued events\n", queued);
+ return;
+ }
+ TRACE("Freeing for real! %p (%d) \n", item, item->cidl);
+#endif
+
/* remove item from list */
list_remove( &item->entry );
item->cidl = cItems;
#ifdef __REACTOS__
item->apidl = SHAlloc(sizeof(SHChangeNotifyEntryInternal) * cItems);
+ item->wQueuedCount = 0;
#else
item->apidl = SHAlloc(sizeof(SHChangeNotifyEntry) * cItems);
#endif
item->apidl[i].buffer = SHAlloc(BUFFER_SIZE);
item->apidl[i].backBuffer = SHAlloc(BUFFER_SIZE);
item->apidl[i].overlapped.hEvent = &item->apidl[i];
+ item->apidl[i].pParent = item;
- if (fSources & SHCNRF_InterruptLevel && _OpenDirectory( &item->apidl[i] ))
- QueueUserAPC(_AddDirectoryProc, m_hThread, (ULONG_PTR) &item->apidl[i] );
- else ERR("_OpenDirectory Failed\n");
+ if (fSources & SHCNRF_InterruptLevel)
+ {
+ if (_OpenDirectory( &item->apidl[i] ))
+ {
+ InterlockedIncrement(&item->wQueuedCount);
+ QueueUserAPC( _AddDirectoryProc, m_hThread, (ULONG_PTR) &item->apidl[i] );
+ }
+ else
+ {
+ CHAR buffer[MAX_PATH];
+ if (!SHGetPathFromIDListA( item->apidl[i].pidl, buffer ))
+ strcpy( buffer, "<unknown>" );
+ ERR("_OpenDirectory failed for %s\n", buffer);
+ }
+ }
#endif
}
item->hwnd = hwnd;
}
if( ( ( wEventId & SHCNE_NOITEMEVENTS ) &&
- ( wEventId & ~SHCNE_NOITEMEVENTS ) ) ||
+ ( wEventId & ~(SHCNE_NOITEMEVENTS | SHCNE_INTERRUPT) ) ) ||
( ( wEventId & SHCNE_ONEITEMEVENTS ) &&
- ( wEventId & ~SHCNE_ONEITEMEVENTS ) ) ||
+ ( wEventId & ~(SHCNE_ONEITEMEVENTS | SHCNE_INTERRUPT) ) ) ||
( ( wEventId & SHCNE_TWOITEMEVENTS ) &&
- ( wEventId & ~SHCNE_TWOITEMEVENTS ) ) )
+ ( wEventId & ~(SHCNE_TWOITEMEVENTS | SHCNE_INTERRUPT) ) ) )
{
WARN("mutually incompatible events listed\n");
return;
return FALSE;
hr = IShellFolder_GetDisplayNameOf(psfDesktop, item->pidl, SHGDN_FORPARSING, &strFile);
+ IShellFolder_Release(psfDesktop);
if (!SUCCEEDED(hr))
return FALSE;
static void CALLBACK _RequestTermination(ULONG_PTR arg)
{
LPNOTIFYREGISTER item = (LPNOTIFYREGISTER) arg;
- TRACE("_RequestTermination %p \n", item->hDirectory);
+ TRACE("_RequestTermination %p %p \n", item, item->hDirectory);
if (!item->hDirectory || item->hDirectory == INVALID_HANDLE_VALUE) return;
CancelIo(item->hDirectory);
LPNOTIFYREGISTER item = (LPNOTIFYREGISTER) lpOverlapped->hEvent;
TRACE("_NotificationCompletion\n");
+#if 0
if (dwErrorCode == ERROR_OPERATION_ABORTED)
{
/* Command was induced by CancelIo in the shutdown procedure. */
TRACE("_NotificationCompletion ended.\n");
return;
}
+#endif
+
+#ifdef __REACTOS__
+ /* If the FSD doesn't support directory change notifications, there's no
+ * no need to retry and requeue notification
+ */
+ if (dwErrorCode == ERROR_INVALID_FUNCTION)
+ {
+ WARN("Directory watching not supported\n");
+ goto quit;
+ }
+#endif
/* This likely means overflow, so force whole directory refresh. */
if (!dwNumberOfBytesTransfered)
item->pidl,
NULL);
+#ifdef __REACTOS__
+ goto quit;
+#else
return;
+#endif
}
/*
_BeginRead(item);
_ProcessNotification(item);
+
+#ifdef __REACTOS__
+quit:
+ InterlockedDecrement(&item->pParent->wQueuedCount);
+ DeleteNode(item->pParent);
+#endif
}
static VOID _BeginRead(LPNOTIFYREGISTER item )
{
TRACE("_BeginRead %p \n", item->hDirectory);
+#ifdef __REACTOS__
+ InterlockedIncrement(&item->pParent->wQueuedCount);
+#endif
/* This call needs to be reissued after every APC. */
if (!ReadDirectoryChangesW(item->hDirectory, // handle to directory
item->buffer, // read results buffer
NULL, // bytes returned
&item->overlapped, // overlapped buffer
_NotificationCompletion)) // completion routine
- ERR("ReadDirectoryChangesW failed. (%p, %p, %p, %p) Code: %u \n",
+#ifdef __REACTOS__
+ {
+#endif
+ ERR("ReadDirectoryChangesW failed. (%p, %p, %p, %p, %p, %p) Code: %u \n",
+ item,
+ item->pParent,
item->hDirectory,
item->buffer,
&item->overlapped,
_NotificationCompletion,
GetLastError());
+#ifdef __REACTOS__
+ InterlockedDecrement(&item->pParent->wQueuedCount);
+ DeleteNode(item->pParent);
+ }
+#endif
}
DWORD _MapAction(DWORD dwAction, BOOL isDir)