{
}
-static LPITEMIDLIST _ILCreate(LPCWSTR lpszPath, LPCITEMIDLIST lpcFindDataPidl)
+static LPITEMIDLIST _ILCreate(LPCWSTR lpszPath)
{
+ CComHeapPtr<ITEMIDLIST> 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;
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;
+ ((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<IShellFolder> 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<ITEMIDLIST> 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<ITEMIDLIST> 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<WCHAR> lpPath((LPWSTR) lParam);
+
+ CComHeapPtr<ITEMIDLIST> 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;
}
m_hWnd, NULL,
_AtlBaseModule.GetModuleInstance(), NULL);
- CreateWindowExW(0, WC_STATIC, L"A &word or phrase in the file:",
+ CreateWindowExW(0, WC_STATIC, L"All or part &of the file name:",
WS_CHILD | WS_VISIBLE,
10, 50, 500, 20,
m_hWnd, NULL,
_AtlBaseModule.GetModuleInstance(), NULL);
- CreateWindowExW(WS_EX_CLIENTEDGE, WC_EDITW, NULL,
+ m_fileName = CreateWindowExW(WS_EX_CLIENTEDGE, WC_EDITW, NULL,
WS_BORDER | WS_CHILD | WS_VISIBLE,
10, 70, 100, 20,
m_hWnd, NULL,
_AtlBaseModule.GetModuleInstance(), NULL);
- CreateWindowExW(0, WC_STATIC, L"&Look in:",
+ CreateWindowExW(0, WC_STATIC, L"A &word or phrase in the file:",
WS_CHILD | WS_VISIBLE,
10, 100, 500, 20,
m_hWnd, NULL,
_AtlBaseModule.GetModuleInstance(), NULL);
- CreateWindowExW(WS_EX_CLIENTEDGE, WC_EDITW, NULL,
+ m_query = CreateWindowExW(WS_EX_CLIENTEDGE, WC_EDITW, NULL,
WS_BORDER | WS_CHILD | WS_VISIBLE,
10, 120, 100, 20,
m_hWnd, NULL,
_AtlBaseModule.GetModuleInstance(), NULL);
+ Edit_LimitText(m_query, MAX_PATH);
CreateWindowExW(0, WC_STATIC, L"&Look in:",
WS_CHILD | WS_VISIBLE,
10, 150, 500, 20,
m_hWnd, NULL,
_AtlBaseModule.GetModuleInstance(), NULL);
- CreateWindowExW(WS_EX_CLIENTEDGE, WC_EDITW, NULL,
+ m_path = CreateWindowExW(WS_EX_CLIENTEDGE, WC_EDITW, NULL,
WS_BORDER | WS_CHILD | WS_VISIBLE,
10, 180, 100, 20,
m_hWnd, NULL,
return hr;
}
- GetSearchResultsFolder(&pShellBrowser, &hwnd, NULL);
- if (hwnd)
+ hr = GetSearchResultsFolder(*pShellBrowser, &hwnd, NULL);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
::PostMessageW(hwnd, WM_SEARCH_START, 0, (LPARAM) StrDupW(L"Starting search..."));
return S_OK;