diff --git a/dll/win32/shell32/wine/changenotify.c b/dll/win32/shell32/wine/changenotify.c index 1873f4a487..0d80c5533a 100644 --- a/dll/win32/shell32/wine/changenotify.c +++ b/dll/win32/shell32/wine/changenotify.c @@ -49,20 +49,7 @@ static CRITICAL_SECTION_DEBUG critsect_debug = }; static CRITICAL_SECTION SHELL32_ChangenotifyCS = { &critsect_debug, -1, 0, 0, 0, 0 }; -#ifdef __REACTOS__ -typedef struct { - PCIDLIST_ABSOLUTE pidl; - BOOL fRecursive; - /* File system notification items */ - HANDLE hDirectory; /* Directory handle */ - WCHAR wstrDirectory[MAX_PATH]; /* Directory name */ - OVERLAPPED overlapped; /* Overlapped structure */ - BYTE *buffer; /* Async buffer to fill */ - BYTE *backBuffer; /* Back buffer to swap buffer into */ -} SHChangeNotifyEntryInternal, *LPNOTIFYREGISTER; -#else typedef SHChangeNotifyEntry *LPNOTIFYREGISTER; -#endif /* internal list of notification clients (internal) */ typedef struct _NOTIFICATIONLIST @@ -77,25 +64,9 @@ typedef struct _NOTIFICATIONLIST ULONG id; } NOTIFICATIONLIST, *LPNOTIFICATIONLIST; -#ifdef __REACTOS__ -VOID _ProcessNotification(LPNOTIFYREGISTER item); -BOOL _OpenDirectory(LPNOTIFYREGISTER item); -static void CALLBACK _RequestTermination(ULONG_PTR arg); -static void CALLBACK _RequestAllTermination(ULONG_PTR arg); -static void CALLBACK _AddDirectoryProc(ULONG_PTR arg); -static VOID _BeginRead(LPNOTIFYREGISTER item); -static unsigned int WINAPI _RunAsyncThreadProc(LPVOID arg); -#endif - static struct list notifications = LIST_INIT( notifications ); static LONG next_id; -#ifdef __REACTOS__ -HANDLE m_hThread; -UINT m_dwThreadId; -BOOL m_bTerminate; -#endif - #define SHCNE_NOITEMEVENTS ( \ SHCNE_ASSOCCHANGED ) @@ -165,26 +136,13 @@ static void DeleteNode(LPNOTIFICATIONLIST item) /* free the item */ for (i=0; icidl; i++) -#ifdef __REACTOS__ - { - QueueUserAPC(_RequestTermination, m_hThread, (ULONG_PTR) &item->apidl[i] ); - WaitForSingleObjectEx(m_hThread, 100, FALSE); -#endif SHFree((LPITEMIDLIST)item->apidl[i].pidl); -#ifdef __REACTOS__ - SHFree(item->apidl[i].buffer); - SHFree(item->apidl[i].backBuffer); - } -#endif SHFree(item->apidl); SHFree(item); } void InitChangeNotifications(void) { -#ifdef __REACTOS__ - m_hThread = NULL; -#endif } void FreeChangeNotifications(void) @@ -200,10 +158,6 @@ void FreeChangeNotifications(void) LeaveCriticalSection(&SHELL32_ChangenotifyCS); -#ifdef __REACTOS__ - QueueUserAPC(_RequestAllTermination, m_hThread, (ULONG_PTR) NULL ); -#endif - DeleteCriticalSection(&SHELL32_ChangenotifyCS); } @@ -228,37 +182,12 @@ SHChangeNotifyRegister( TRACE("(%p,0x%08x,0x%08x,0x%08x,%d,%p) item=%p\n", hwnd, fSources, wEventMask, uMsg, cItems, lpItems, item); -#ifdef __REACTOS__ - if (!m_hThread) - m_hThread = (HANDLE) _beginthreadex(NULL, 0, _RunAsyncThreadProc, NULL, 0, &m_dwThreadId); -#endif - item->cidl = cItems; -#ifdef __REACTOS__ - item->apidl = SHAlloc(sizeof(SHChangeNotifyEntryInternal) * cItems); -#else item->apidl = SHAlloc(sizeof(SHChangeNotifyEntry) * cItems); -#endif for(i=0;iapidl[i], sizeof(SHChangeNotifyEntryInternal)); -#endif item->apidl[i].pidl = ILClone(lpItems[i].pidl); item->apidl[i].fRecursive = lpItems[i].fRecursive; -#ifdef __REACTOS__ - item->apidl[i].buffer = SHAlloc(BUFFER_SIZE); - item->apidl[i].backBuffer = SHAlloc(BUFFER_SIZE); - item->apidl[i].overlapped.hEvent = &item->apidl[i]; - - if (fSources & SHCNRF_InterruptLevel) - { - if (_OpenDirectory( &item->apidl[i] )) - { - QueueUserAPC( _AddDirectoryProc, m_hThread, (ULONG_PTR) &item->apidl[i] ); - } - } -#endif } item->hwnd = hwnd; item->uMsg = uMsg; @@ -394,43 +323,6 @@ void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID case SHCNF_PATHW: if (dwItem1) Pidls[0] = SHSimpleIDListFromPathW(dwItem1); if (dwItem2) Pidls[1] = SHSimpleIDListFromPathW(dwItem2); -#ifdef __REACTOS__ - if (wEventId & (SHCNE_MKDIR | SHCNE_RMDIR | SHCNE_UPDATEDIR | SHCNE_RENAMEFOLDER)) - { - /* - * The last items in the ID are currently files. So we chop off the last - * entry, and create a new one using a find data struct. - */ - if (dwItem1 && Pidls[0]){ - WIN32_FIND_DATAW wfd; - LPITEMIDLIST oldpidl, newpidl; - LPWSTR p = PathFindFileNameW((LPCWSTR)dwItem1); - ILRemoveLastID(Pidls[0]); - lstrcpynW(&wfd.cFileName[0], p, MAX_PATH); - wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; - newpidl = _ILCreateFromFindDataW(&wfd); - oldpidl = ILClone(Pidls[0]); - ILFree(Pidls[0]); - Pidls[0] = ILCombine(oldpidl, newpidl); - ILFree(newpidl); - ILFree(oldpidl); - } - if (dwItem2 && Pidls[1]){ - WIN32_FIND_DATAW wfd; - LPITEMIDLIST oldpidl, newpidl; - LPWSTR p = PathFindFileNameW((LPCWSTR)dwItem2); - ILRemoveLastID(Pidls[1]); - lstrcpynW(&wfd.cFileName[0], p, MAX_PATH); - wfd.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY; - newpidl = _ILCreateFromFindDataW(&wfd); - oldpidl = ILClone(Pidls[0]); - ILFree(Pidls[1]); - Pidls[1] = ILCombine(oldpidl, newpidl); - ILFree(newpidl); - ILFree(oldpidl); - } - } -#endif break; case SHCNF_IDLIST: Pidls[0] = ILClone(dwItem1); @@ -612,255 +504,3 @@ DWORD WINAPI NTSHChangeNotifyDeregister(ULONG x1) return SHChangeNotifyDeregister( x1 ); } - -#ifdef __REACTOS__ - -static -void -CALLBACK -_AddDirectoryProc(ULONG_PTR arg) -{ - LPNOTIFYREGISTER item = (LPNOTIFYREGISTER)arg; - _BeginRead(item); -} - -BOOL _OpenDirectory(LPNOTIFYREGISTER item) -{ - STRRET strFile; - IShellFolder *psf; - HRESULT hr; - LPCITEMIDLIST child; - ULONG ulAttrs; - - // Makes function idempotent - if (item->hDirectory && !(item->hDirectory == INVALID_HANDLE_VALUE)) - return TRUE; - - hr = SHBindToParent(item->pidl, &IID_IShellFolder, (LPVOID*)&psf, &child); - if (FAILED_UNEXPECTEDLY(hr)) - return hr; - - ulAttrs = SFGAO_FILESYSTEM | SFGAO_FOLDER; - hr = IShellFolder_GetAttributesOf(psf, 1, (LPCITEMIDLIST*)&child, &ulAttrs); - if (SUCCEEDED(hr)) - hr = IShellFolder_GetDisplayNameOf(psf, child, SHGDN_FORPARSING, &strFile); - - IShellFolder_Release(psf); - if (FAILED_UNEXPECTEDLY(hr)) - return FALSE; - - hr = StrRetToBufW(&strFile, NULL, item->wstrDirectory, _countof(item->wstrDirectory)); - if (FAILED_UNEXPECTEDLY(hr)) - return FALSE; - - if ((ulAttrs & (SFGAO_FILESYSTEM | SFGAO_FOLDER)) != (SFGAO_FILESYSTEM | SFGAO_FOLDER)) - { - TRACE("_OpenDirectory ignoring %s\n", debugstr_w(item->wstrDirectory)); - item->hDirectory = INVALID_HANDLE_VALUE; - return FALSE; - } - - TRACE("_OpenDirectory %s\n", debugstr_w(item->wstrDirectory)); - - item->hDirectory = CreateFileW(item->wstrDirectory, // pointer to the file name - GENERIC_READ | FILE_LIST_DIRECTORY, // access (read/write) mode - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, // share mode - NULL, // security descriptor - OPEN_EXISTING, // how to create - FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, // file attributes - NULL); // file with attributes to copy - - if (item->hDirectory == INVALID_HANDLE_VALUE) - { - ERR("_OpenDirectory failed for %s\n", debugstr_w(item->wstrDirectory)); - return FALSE; - } - return TRUE; -} - -static void CALLBACK _RequestTermination(ULONG_PTR arg) -{ - LPNOTIFYREGISTER item = (LPNOTIFYREGISTER) arg; - TRACE("_RequestTermination %p %p \n", item, item->hDirectory); - if (!item->hDirectory || item->hDirectory == INVALID_HANDLE_VALUE) return; - - CancelIo(item->hDirectory); - CloseHandle(item->hDirectory); - item->hDirectory = NULL; -} - -static -void -CALLBACK -_NotificationCompletion(DWORD dwErrorCode, // completion code - DWORD dwNumberOfBytesTransfered, // number of bytes transferred - LPOVERLAPPED lpOverlapped) // I/O information buffer -{ - /* MSDN: The hEvent member of the OVERLAPPED structure is not used by the - system, so you can use it yourself. We do just this, storing a pointer - to the working struct in the overlapped structure. */ - 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"); - return; - } - - /* Also, if the notify operation was canceled (like, user moved to another - * directory), then, don't requeue notification - */ - if (dwErrorCode == ERROR_OPERATION_ABORTED) - { - TRACE("Notification aborted\n"); - return; - } - - if (!item) - { - ERR("item == NULL\n"); - return; - } - -#endif - - /* This likely means overflow, so force whole directory refresh. */ - if (!dwNumberOfBytesTransfered) - { - ERR("_NotificationCompletion overflow\n"); - - ZeroMemory(item->buffer, BUFFER_SIZE); - _BeginRead(item); - - SHChangeNotify(SHCNE_UPDATEITEM | SHCNE_INTERRUPT, - SHCNF_IDLIST, - item->pidl, - NULL); - - return; - } - - /* - * Get the new read issued as fast as possible (before we do the - * processing and message posting). All of the file notification - * occur on one thread so the buffers should not collide with one another. - * The extra zero mems are because the FNI size isn't written correctly. - */ - - ZeroMemory(item->backBuffer, BUFFER_SIZE); - memcpy(item->backBuffer, item->buffer, dwNumberOfBytesTransfered); - ZeroMemory(item->buffer, BUFFER_SIZE); - - _BeginRead(item); - - _ProcessNotification(item); -} - -static VOID _BeginRead(LPNOTIFYREGISTER item ) -{ - TRACE("_BeginRead %p \n", item->hDirectory); - - /* This call needs to be reissued after every APC. */ - if (!ReadDirectoryChangesW(item->hDirectory, // handle to directory - item->buffer, // read results buffer - BUFFER_SIZE, // length of buffer - FALSE, // monitoring option (recursion) - FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_FILE_NAME, // filter conditions - NULL, // bytes returned - &item->overlapped, // overlapped buffer - _NotificationCompletion)) // completion routine - ERR("ReadDirectoryChangesW failed. (%p, %p, %p, %p, %p) Code: %u \n", - item, - item->hDirectory, - item->buffer, - &item->overlapped, - _NotificationCompletion, - GetLastError()); -} - -DWORD _MapAction(DWORD dwAction, BOOL isDir) -{ - switch (dwAction) - { - case FILE_ACTION_ADDED : return isDir ? SHCNE_MKDIR : SHCNE_CREATE; - case FILE_ACTION_REMOVED : return isDir ? SHCNE_RMDIR : SHCNE_DELETE; - case FILE_ACTION_MODIFIED : return isDir ? SHCNE_UPDATEDIR : SHCNE_UPDATEITEM; - case FILE_ACTION_RENAMED_OLD_NAME : return isDir ? SHCNE_UPDATEDIR : SHCNE_UPDATEITEM; - case FILE_ACTION_RENAMED_NEW_NAME : return isDir ? SHCNE_UPDATEDIR : SHCNE_UPDATEITEM; - default: return SHCNE_UPDATEITEM; - } -} - -VOID _ProcessNotification(LPNOTIFYREGISTER item) -{ - BYTE* pBase = item->backBuffer; - TRACE("_ProcessNotification\n"); - - for (;;) - { - FILE_NOTIFY_INFORMATION* fni = (FILE_NOTIFY_INFORMATION*)pBase; - LPWSTR wszFilename; - INT len = 0; - WCHAR wstrFilename[MAX_PATH]; - WCHAR tmp[MAX_PATH]; - StringCchCopy(tmp, fni->FileNameLength, fni->FileName); - - PathCombine(wstrFilename, item->wstrDirectory, tmp); - - /* If it could be a short filename, expand it. */ - wszFilename = PathFindFileNameW(wstrFilename); - - len = lstrlenW(wszFilename); - /* The maximum length of an 8.3 filename is twelve, including the dot. */ - if (len <= 12 && wcschr(wszFilename, L'~')) - { - /* Convert to the long filename form. Unfortunately, this - does not work for deletions, so it's an imperfect fix. */ - wchar_t wbuf[MAX_PATH]; - if (GetLongPathName(wstrFilename, wbuf, _countof (wbuf)) > 0) - StringCchCopyW(wstrFilename, MAX_PATH, wbuf); - } - - /* On deletion of a folder PathIsDirectory will return false even if - it *was* a directory, so, again, imperfect. */ - SHChangeNotify(_MapAction(fni->Action, PathIsDirectory(wstrFilename)) | SHCNE_INTERRUPT, - SHCNF_PATHW, - wstrFilename, - NULL); - - if (!fni->NextEntryOffset) - break; - pBase += fni->NextEntryOffset; - } -} - -static void CALLBACK _RequestAllTermination(ULONG_PTR arg) -{ - m_bTerminate = TRUE; -} - -static unsigned int WINAPI _RunAsyncThreadProc(LPVOID arg) -{ - m_bTerminate = FALSE; - while (!m_bTerminate) - { - SleepEx(INFINITE, TRUE); - } - return 0; -} - -#endif /* __REACTOS__ */