X-Git-Url: https://git.reactos.org/?p=reactos.git;a=blobdiff_plain;f=dll%2Fwin32%2Fbrowseui%2Fshellfind%2FCFindFolder.cpp;h=535c1af09d0cdd6314475947eae3f79abcc132fe;hp=4e986bebeb1adfda3ef0f88303441217807499a0;hb=2f3db8d9a3d153855a6adafa1ea8dede7a29756c;hpb=3583900b177ae00410e725c1148ba8d636682186 diff --git a/dll/win32/browseui/shellfind/CFindFolder.cpp b/dll/win32/browseui/shellfind/CFindFolder.cpp index 4e986bebeb1..535c1af09d0 100644 --- a/dll/win32/browseui/shellfind/CFindFolder.cpp +++ b/dll/win32/browseui/shellfind/CFindFolder.cpp @@ -37,10 +37,18 @@ CFindFolder::CFindFolder() : { } -static LPITEMIDLIST _ILCreate(LPCWSTR lpszPath, LPCITEMIDLIST lpcFindDataPidl) +static LPITEMIDLIST _ILCreate(LPCWSTR lpszPath) { + CComHeapPtr lpFSPidl(ILCreateFromPathW(lpszPath)); + if (!(LPITEMIDLIST)lpFSPidl) + { + ERR("Failed to create pidl from path\n"); + return 0; + } + LPITEMIDLIST lpLastFSPidl = ILFindLastID(lpFSPidl); + int pathLen = (wcslen(lpszPath) + 1) * sizeof(WCHAR); - int cbData = sizeof(WORD) + pathLen + lpcFindDataPidl->mkid.cb; + int cbData = sizeof(WORD) + pathLen + lpLastFSPidl->mkid.cb; LPITEMIDLIST pidl = (LPITEMIDLIST) SHAlloc(cbData + sizeof(WORD)); if (!pidl) return NULL; @@ -52,8 +60,8 @@ static LPITEMIDLIST _ILCreate(LPCWSTR lpszPath, LPCITEMIDLIST lpcFindDataPidl) memcpy(p, lpszPath, pathLen); p += pathLen; - memcpy(p, lpcFindDataPidl, lpcFindDataPidl->mkid.cb); - p += lpcFindDataPidl->mkid.cb; + memcpy(p, lpLastFSPidl, lpLastFSPidl->mkid.cb); + p += lpLastFSPidl->mkid.cb; *((WORD *) p) = 0; @@ -75,53 +83,199 @@ static LPCITEMIDLIST _ILGetFSPidl(LPCITEMIDLIST pidl) + ((wcslen((LPCWSTR) pidl->mkid.abID) + 1) * sizeof(WCHAR))); } -LRESULT CFindFolder::AddItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) +struct _SearchData { - if (!lParam) - return 0; + HWND hwnd; + HANDLE hStopEvent; + SearchStart *pSearchParams; +}; - HRESULT hr; - LPWSTR path = (LPWSTR) lParam; +static LPCSTR WINAPI StrStrNA(LPCSTR lpFirst, LPCSTR lpSrch, UINT cchMax) +{ + UINT i; + int len; - CComPtr pShellFolder; - hr = SHGetDesktopFolder(&pShellFolder); - if (FAILED_UNEXPECTEDLY(hr)) + if (!lpFirst || !lpSrch || !*lpSrch || !cchMax) + return NULL; + + len = strlen(lpSrch); + + for (i = cchMax; *lpFirst && (i > 0); i--, lpFirst++) { - LocalFree(path); - return hr; + if (!strncmp(lpFirst, lpSrch, len)) + return (LPCSTR)lpFirst; } - CComHeapPtr lpFSPidl; - DWORD pchEaten; - hr = pShellFolder->ParseDisplayName(NULL, NULL, path, &pchEaten, &lpFSPidl, NULL); - if (FAILED_UNEXPECTEDLY(hr)) + return NULL; +} + +static UINT SearchFile(LPCWSTR lpFilePath, _SearchData *pSearchData) +{ + HANDLE hFile = CreateFileW(lpFilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return 0; + + DWORD size = GetFileSize(hFile, NULL); + HANDLE hFileMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); + CloseHandle(hFile); + if (hFileMap == INVALID_HANDLE_VALUE) + return 0; + + LPBYTE lpFileContent = (LPBYTE) MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0); + CloseHandle(hFileMap); + if (!lpFileContent) + return 0; + + UINT uMatches = 0; + if ((size >= 2) && (lpFileContent[0] == 0xFF) && (lpFileContent[1] == 0xFE)) { - LocalFree(path); - return hr; + // UTF16 LE + LPCWSTR lpSearchPos = (LPCWSTR) lpFileContent; + DWORD dwCharsRemaining = size / sizeof(WCHAR); + const LPCWSTR lpSearchEnd = (LPCWSTR) lpFileContent + dwCharsRemaining; + const LPCWSTR lpszQuery = pSearchData->pSearchParams->szQuery; + const size_t queryLen = wcslen(lpszQuery); + while ((lpSearchPos = StrStrNW(lpSearchPos, lpszQuery, dwCharsRemaining)) + && lpSearchPos < lpSearchEnd) + { + uMatches++; + lpSearchPos += queryLen; + dwCharsRemaining -= queryLen; + } + } + else + { + DWORD len = WideCharToMultiByte(CP_ACP, 0, pSearchData->pSearchParams->szQuery, -1, NULL, 0, NULL, NULL); + const LPSTR lpszQuery = new CHAR[len]; + WideCharToMultiByte(CP_ACP, 0, pSearchData->pSearchParams->szQuery, -1, lpszQuery, len, NULL, NULL); + LPCSTR lpSearchPos = (LPCSTR) lpFileContent; + DWORD dwCharsRemaining = size; + const LPCSTR lpSearchEnd = (LPCSTR) lpFileContent + dwCharsRemaining; + const size_t queryLen = len; + while ((lpSearchPos = StrStrNA(lpSearchPos, lpszQuery, dwCharsRemaining)) + && lpSearchPos < lpSearchEnd) + { + uMatches++; + lpSearchPos += queryLen; + dwCharsRemaining -= queryLen; + } } - LPITEMIDLIST lpLastFSPidl = ILFindLastID(lpFSPidl); - CComHeapPtr lpSearchPidl(_ILCreate(path, lpLastFSPidl)); - LocalFree(path); - if (!lpSearchPidl) + UnmapViewOfFile(lpFileContent); + + return uMatches; +} + +static VOID RecursiveFind(LPCWSTR lpPath, _SearchData *pSearchData) +{ + if (WaitForSingleObject(pSearchData->hStopEvent, 0) != WAIT_TIMEOUT) + return; + + WCHAR szPath[MAX_PATH]; + WIN32_FIND_DATAW FindData; + HANDLE hFindFile; + BOOL bMoreFiles = TRUE; + + PathCombineW(szPath, lpPath, L"*.*"); + + for (hFindFile = FindFirstFileW(szPath, &FindData); + bMoreFiles && hFindFile != INVALID_HANDLE_VALUE; + bMoreFiles = FindNextFileW(hFindFile, &FindData)) { - return E_OUTOFMEMORY; + if (!wcscmp(FindData.cFileName, L".") || !wcscmp(FindData.cFileName, L"..")) + continue; + + PathCombineW(szPath, lpPath, FindData.cFileName); + + if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + CStringW* status = new CStringW(); + status->Format(L"Searching '%s'", FindData.cFileName); + PostMessageW(pSearchData->hwnd, WM_SEARCH_UPDATE_STATUS, 0, (LPARAM) status); + + RecursiveFind(szPath, pSearchData); + } + else if (pSearchData->szFileName.IsEmpty() || PathMatchSpecW(FindData.cFileName, pSearchData->szFileName)) + { + DbgPrint("Searching file: '%S'\n", szPath); + UINT uMatches = SearchFile(szPath, pSearchData); + if (uMatches) + { + ::PostMessageW(pSearchData->hwnd, WM_SEARCH_ADD_RESULT, 0, (LPARAM) StrDupW(szPath)); + } + } } + if (hFindFile != INVALID_HANDLE_VALUE) + FindClose(hFindFile); +} + +static DWORD WINAPI _SearchThreadProc(LPVOID lpParameter) +{ + _SearchData *data = static_cast<_SearchData*>(lpParameter); + + SearchStart* params = (SearchStart *) data->pSearchParams; + + RecursiveFind(params->szPath, data); + + SHFree(params); + SHFree(lpParameter); + + return 0; +} + +LRESULT CFindFolder::StartSearch(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) +{ + if (!lParam) + return 0; + + // Clear all previous search results UINT uItemIndex; - hr = m_shellFolderView->AddObject(lpSearchPidl, &uItemIndex); + m_shellFolderView->RemoveObject(NULL, &uItemIndex); - return hr; + _SearchData* pSearchData = new _SearchData(); + pSearchData->pFindFolder = this; + pSearchData->hwnd = m_hWnd; + if (m_hStopEvent) + SetEvent(m_hStopEvent); + pSearchData->hStopEvent = m_hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + pSearchData->pSearchParams = (SearchStart *) lParam; + + if (!SHCreateThread(_SearchThreadProc, pSearchData, NULL, NULL)) + { + SHFree(pSearchData->pSearchParams); + SHFree(pSearchData); + return HRESULT_FROM_WIN32(GetLastError()); + } + + return S_OK; +} + +LRESULT CFindFolder::AddResult(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) +{ + if (!lParam) + return 0; + + CComHeapPtr lpPath((LPWSTR) lParam); + + CComHeapPtr lpSearchPidl(_ILCreate(lpPath)); + if (lpSearchPidl) + { + UINT uItemIndex; + m_shellFolderView->AddObject(lpSearchPidl, &uItemIndex); + } + + return 0; } LRESULT CFindFolder::UpdateStatus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) { - LPWSTR status = (LPWSTR) lParam; + CStringW *status = (CStringW *) lParam; if (m_shellBrowser) { - m_shellBrowser->SetStatusTextSB(status); + m_shellBrowser->SetStatusTextSB(status->GetBuffer()); } - LocalFree(status); + delete status; return S_OK; }