Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
docfind2.c
Package: shell.rar [view]
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 173k
Category:
Windows Kernel
Development Platform:
Visual C++
- //---------------------------------------------------------------------------
- //
- // Copyright (c) Microsoft Corporation 1991-1993
- //
- // File: docfind2.c
- //
- // Description: This file should contains most of the document find code
- // that is specific to the default search filters.
- //
- //
- // History:
- // 12-29-93 KurtE Created.
- //
- //---------------------------------------------------------------------------
- #include "shellprv.h"
- #pragma hdrstop
- #include "fstreex.h"
- #include "docfind.h"
- #include "prop.h"
- #ifndef MAXUSHORT
- #define MAXUSHORT 0xffff
- #endif
- //===========================================================================
- // Define the Default data filter data structures
- //===========================================================================
- //
- // Define the internal structure of our default filter
- typedef struct _CDFFilter // fff
- {
- IDocFindFileFilter dfff;
- LONG cRef;
- HWND hwndTabs;
- HANDLE hMRUSpecs;
- // Added support for Query results to be async...
- IDFEnum *pdfenumAsync;
- // Here are the paths that we are to search on...
- // Data associated with the Look in field
- IShellFolder * psfMyComputer;
- int iMyComputer;
- int iWindowsDrive;
- int iDocumentFolders;
- int iDesktopFolders;
- int ipidlStart;
- // Data associated with the file name.
- BOOL fNameChanged; // The name changed earlier
- LPTSTR pszFileSpec; // $$ the one we do compares with
- LPTSTR pszSpecs; // same as pszFileSpec but with ''s for ';'s
- LPTSTR * apszFileSpecs; // pointers into pszSpecs for each token
- int cFileSpecs; // count of specs
- LPITEMIDLIST pidlStart; // Starting location ID list.
- TCHAR szPath[MAX_PATH]; // Location of where to start search from
- TCHAR szUserInputFileSpec[MAX_PATH]; // File pattern.
- TCHAR szText[MAXSTRLEN]; // Limit text to max editable size
- DWORD uFixedDrives; // The list of fixed drives...
- #ifdef UNICODE
- CHAR szTextA[MAXSTRLEN];
- #endif
- BOOL fTopLevelOnly; // Search on top level only?
- BOOL fShowAllObjects; // $$ Should we show all files?
- BOOL fFilterChanged; // Something in the filter changed.
- BOOL fWeRestoredSomeCriteria; // We need to initilize the pages...
- // Fields associated with the file type
- BOOL fTypeChanged; // Type changed;
- int iType; // Index of the type.
- int iTypeLast; // Save away last type...
- PHASHITEM phiType; // Save away hash item
- TCHAR szTypeName[80]; // The display name for type
- TCHAR szTypeFilePatterns[MAX_PATH]; // $$ The file patterns associated with type
- LPTSTR pszIndexedSearch; // what to search for... (Maybe larger than MAX_PATH because it's a list of paths.
- ULONG ulQueryDialect; // ISQLANG_V1 or ISQLANG_V2
- DWORD dwWarningFlags; // Warning bits (DFW_xxx).
- LPGREPINFO lpgi; // $$ Grep information.
- int iSizeType; // $$ What type of size 0 - none, 1 > 2 <
- DWORD dwSize; // $$ Size comparison
- WORD wDateType; // $$ 0 - none, 1 days before, 2 months before...
- WORD wDateValue; // (Num of months or days)
- WORD dateModifiedBefore; // $$
- WORD dateModifiedAfter; // $$
- BITBOOL fFoldersOnly:1; // $$ Are we searching for folders?
- BITBOOL fTextCaseSen:1; // $$ Case sensitive searching...
- BITBOOL fTextReg:1; // $$ regular expressions.
- BITBOOL fSearchSlowFiles:1; // && probably missleading as file over a 300baud modem is also slow
- int iNextConstraint; // which constraint to look at next...
- } CDFFilter;
- // Lets define some constants to use to define which types of date we are searching on
- #define DFF_DATE_ALL (IDD_MDATE_ALL-IDD_MDATE_ALL)
- #define DFF_DATE_DAYS (IDD_MDATE_DAYS-IDD_MDATE_ALL)
- #define DFF_DATE_MONTHS (IDD_MDATE_MONTHS-IDD_MDATE_ALL)
- #define DFF_DATE_BETWEEN (IDD_MDATE_BETWEEN-IDD_MDATE_ALL)
- #define DFF_DATE_RANGEMASK 0x00ff
- #define DFF_DATE_TYPEMASK 0xff00
- #define DFF_DATE_MODIFIED 0x0000
- #define DFF_DATE_CREATED 0x0100
- #define DFF_DATE_ACCESSED 0x0200
- // Define new criteria to be saved in file...
- #define DFSC_SEARCHFOR 0x5000
- // Define common page data for each of our pages
- typedef struct { // dfpsp
- PROPSHEETPAGE psp;
- HANDLE hThreadInit;
- HWND hwndDlg;
- CDFFilter * pdff;
- DWORD dwState;
- } DOCFINDPROPSHEETPAGE, * LPDOCFINDPROPSHEETPAGE;
- typedef struct { // pdfsli
- DWORD dwVer; // Version
- DWORD dwType; // Type of data (defined below)
- } DOCFINDSAVELOOKIN;
- // Used to enum top level paths
- //
- typedef struct {
- // Stuff to use in the search
- LPTSTR pszPath; // Passed in path from creater
- // Handle cases where we search one level deep like at \compname and the like
- //
- LPCITEMIDLIST pidlStart; // Passed in pidl to begin from
- IShellFolder *psfTopLevel; // Top level shellfolder
- IEnumIDList *penumTopLevel; // Top level enum function.
- BOOL fFirstPass; // Is this the first pass?
- LPTSTR pszPathNext; // filter path enumeration state
- } CDFEStartPaths;
- const COL_DATA c_df_cols[] = {
- {IDFCOL_NAME, IDS_NAME_COL, 20, LVCFMT_LEFT, &SCID_NAME},
- {IDFCOL_PATH, IDS_PATH_COL, 20, (short int)(LVCFMT_LEFT | LVCFMT_COL_HAS_IMAGES), &SCID_DIRECTORY},
- {IDFCOL_RANK, IDS_RANK_COL, 10, LVCFMT_RIGHT, &SCID_RANK},
- {IDFCOL_SIZE, IDS_SIZE_COL, 10, LVCFMT_RIGHT, &SCID_SIZE},
- {IDFCOL_TYPE, IDS_TYPE_COL, 20, LVCFMT_LEFT, &SCID_TYPE},
- {IDFCOL_MODIFIED, IDS_MODIFIED_COL, 30, LVCFMT_LEFT, &SCID_WRITETIME}
- };
- // Functions used enumerate the top level find strings, handling this like MyComputer \AServer
- HRESULT DF_GetSearchPaths(CDFFilter *this, LPCITEMIDLIST pidlStart, LPWSTR *papwszPaths[], UINT *pcPaths);
- BOOL DF_EnumNextTopPath(CDFEStartPaths * pdfesp, LPTSTR pszOut, int cch);
- BOOL IsSuperHidden(DWORD dwAttribs); // for now in docfind.cpp
- HRESULT _IsNTFSDrive(int iDrive); // in docfind.cpp
- typedef struct {
- IDFEnum dfenum;
- UINT cRef;
- IShellFolder *psf; // Pointer to shell folder
- // Stuff to use in the search
- LPITEMIDLIST pidlStart; // PidlStart...
- // List of start paths...
- LPWSTR *apwszPaths; // array of paths
- UINT cPaths; // how many in it...
- UINT iPathNext; // which one to process next...
- // We may have an Async Enum that does some of the paths...
- IDFEnum *pdfenumAsync;
- IShellFolder *psfStart; // The starting folder for the search.
- int cchStart; // How many characters are in the
- DWORD grfFlags; // Flags that control things like recursion
- WIN32_FIND_DATA finddata; // Win32 file data to use
- // filter info...
- LPTSTR pszProgressText; // Path Buffer pointer
- IDocFindFileFilter * pdfff;// The file filter to use...
- TCHAR szTempInternetCachePath[MAX_PATH]; // temporary internet path...
- // enumeration state
- int ichPathFirst; // ich into path string of current path...
- int iFolder; // Which folder are we adding items for?
- BOOL fAddedSubDirs : 1;
- BOOL fObjReturnedInDir : 1; // Has an object been returned in this dir?
- BOOL fFindFirstSucceed : 1; // Did a find first file succeed.
- int depth; // directory level (relative to pszPath)
- HANDLE hfind;
- DIRBUF * pdbStack; // Linked list of DIRBUFs to enum
- DIRBUF * pdbReuse;
- } CDFEnum;
- #define DFSLI_VER 0
- #define DFSLI_TYPE_PIDL 0 // Pidl is streamed after this
- #define DFSLI_TYPE_STRING 1 // cb follows this for length then string...
- // Document folders and children - Warning we assume the order of items after Document Folders
- #define DFSLI_TYPE_DOCUMENTFOLDERS 0x10
- #define DFSLI_TYPE_DESKTOP 0x11
- #define DFSLI_TYPE_PERSONAL 0x12
- // My computer and children...
- #define DFSLI_TYPE_MYCOMPUTER 0x20
- #define DFSLI_TYPE_LOCALDRIVES 0x21
- // BUGBUG I don't get it... why the manual calculation of the structure size?
- #define DOCFINDPSHTSIZE (SIZEOF(PROPSHEETPAGE)+SIZEOF(HANDLE)+SIZEOF(HWND)+SIZEOF(CDFFilter *)+SIZEOF(DWORD))
- #define DFPAGE_INIT 0x0001 /* This page has been initialized */
- #define DFPAGE_CHANGE 0x0002 /* The user has modified the page */
- //------------------------------------------------------------------------------
- // Use same enum and string table between updatefield and getting the constraints
- // back out...
- typedef enum
- {
- CDFFUFE_IndexedSearch = 0,
- CDFFUFE_LookIn,
- CDFFUFE_IncludeSubFolders,
- CDFFUFE_Named,
- CDFFUFE_ContainingText,
- CDFFUFE_FileType,
- CDFFUFE_WhichDate,
- CDFFUFE_DateLE,
- CDFFUFE_DateGE,
- CDFFUFE_DateNDays,
- CDFFUFE_DateNMonths,
- CDFFUFE_SizeLE,
- CDFFUFE_SizeGE,
- CDFFUFE_TextCaseSen,
- CDFFUFE_TextReg,
- CDFFUFE_SearchSlowFiles,
- CDFFUFE_QueryDialect,
- CDFFUFE_WarningFlags,
- } CDFFUFE;
- static const CDFFUF s_cdffuf[] = // Warning: index of fields is used below in case...
- {
- {L"IndexedSearch", VT_BSTR, CDFFUFE_IndexedSearch},
- {L"LookIn", VT_BSTR, CDFFUFE_LookIn},
- {L"IncludeSubFolders", VT_BOOL, CDFFUFE_IncludeSubFolders},
- {L"Named",VT_BSTR, CDFFUFE_Named},
- {L"ContainingText", VT_BSTR, CDFFUFE_ContainingText},
- {L"FileType", VT_BSTR, CDFFUFE_FileType},
- {L"WhichDate", VT_I4, CDFFUFE_WhichDate},
- {L"DateLE", VT_DATE, CDFFUFE_DateLE},
- {L"DateGE", VT_DATE, CDFFUFE_DateGE},
- {L"DateNDays", VT_I4, CDFFUFE_DateNDays},
- {L"DateNMonths", VT_I4, CDFFUFE_DateNMonths},
- {L"SizeLE", VT_UI4, CDFFUFE_SizeLE},
- {L"SizeGE", VT_UI4, CDFFUFE_SizeGE},
- {L"CaseSensitive", VT_BOOL, CDFFUFE_TextCaseSen},
- {L"RegularExpressions", VT_BOOL, CDFFUFE_TextReg},
- {L"SearchSlowFiles", VT_BOOL, CDFFUFE_SearchSlowFiles},
- {L"QueryDialect", VT_UI4, CDFFUFE_QueryDialect},
- {L"WarningFlags", VT_UI4 /*DFW_xxx bits*/, CDFFUFE_WarningFlags},
- {NULL, VT_EMPTY, 0}
- };
- //===========================================================================
- // Copied from comctl32. This is all a hack. Docfind used this internal
- // prsht function because it was too lazy to call CreateDialogIndirect.
- // But comctl32's internal structure has changed, so we have to do it
- // ourselves. Nevermind that the actual function is tiny.
- //===========================================================================
- #include <pshpack2.h>
- typedef struct
- {
- WORD wDlgVer;
- WORD wSignature;
- DWORD dwHelpID;
- DWORD dwExStyle;
- DWORD dwStyle;
- WORD cDlgItems;
- WORD x;
- WORD y;
- WORD cx;
- WORD cy;
- } DLGEXTEMPLATE, FAR *LPDLGEXTEMPLATE;
- #include <poppack.h> /* Resume normal packing */
- HWND DocFindCreatePageDialog(LPPROPSHEETPAGE hpage, HWND hwndParent, LPDLGTEMPLATE pDlgTemplate)
- {
- DWORD lSaveStyle;
- LPDLGEXTEMPLATE pDlgExTemplate = (LPDLGEXTEMPLATE) pDlgTemplate;
- // Note: Don't need to restore the style since we're going
- // to free the memory anyway.
- if (pDlgExTemplate->wSignature == 0xFFFF)
- {
- lSaveStyle = pDlgExTemplate->dwStyle;
- pDlgExTemplate->dwStyle = (lSaveStyle & (DS_SETFONT | DS_LOCALEDIT | WS_CLIPCHILDREN))
- | WS_CHILD | WS_TABSTOP | DS_3DLOOK | DS_CONTROL;
- }
- else
- {
- lSaveStyle = pDlgTemplate->style;
- pDlgTemplate->style = (lSaveStyle & (DS_SETFONT | DS_LOCALEDIT | WS_CLIPCHILDREN))
- | WS_CHILD | WS_TABSTOP | DS_3DLOOK | DS_CONTROL;
- }
- return CreateDialogIndirectParam(
- hpage->hInstance,
- (LPCDLGTEMPLATE)pDlgTemplate,
- hwndParent,
- hpage->pfnDlgProc, (LPARAM)hpage);
- }
- HWND DocFindCreatePage(LPPROPSHEETPAGE ppsp, HWND hwndParent)
- {
- HWND hwndPage = NULL; // NULL indicates an error
- HRSRC hRes;
- // Comctl32.CreatePage supported these flags but we don't use them
- // so we won't support them either.
- ASSERT(!(ppsp->dwFlags & (PSP_USECALLBACK | PSP_IS16 | PSP_DLGINDIRECT)));
- hRes = FindResource(ppsp->hInstance, ppsp->pszTemplate, RT_DIALOG);
- if (hRes)
- {
- const DLGTEMPLATE * pDlgTemplate = LoadResource(ppsp->hInstance, hRes);
- if (pDlgTemplate)
- {
- ULONG cbTemplate=SizeofResource(ppsp->hInstance, hRes);
- LPDLGTEMPLATE pdtCopy = (LPDLGTEMPLATE)Alloc(cbTemplate);
- ASSERT(cbTemplate>=sizeof(DLGTEMPLATE));
- if (pdtCopy)
- {
- hmemcpy(pdtCopy, pDlgTemplate, cbTemplate);
- hwndPage=DocFindCreatePageDialog(ppsp, hwndParent, pdtCopy);
- Free(pdtCopy);
- }
- }
- }
- return hwndPage;
- }
- //===========================================================================
- // Define some other module global data
- //===========================================================================
- const DWORD aNameHelpIDs[] = {
- IDD_STATIC, IDH_FINDFILENAME_NAME,
- IDD_FILESPEC, IDH_FINDFILENAME_NAME,
- IDD_PATH, IDH_FINDFILENAME_LOOKIN,
- IDD_BROWSE, IDH_FINDFILENAME_BROWSE,
- IDD_TOPLEVELONLY, IDH_FINDFILENAME_TOPLEVEL,
- IDD_CONTAINS, IDH_FINDFILECRIT_CONTTEXT,
- 0, 0
- };
- const DWORD aCriteriaHelpIDs[] = {
- IDD_STATIC, IDH_FINDFILECRIT_OFTYPE,
- IDD_TYPECOMBO, IDH_FINDFILECRIT_OFTYPE,
- IDD_SIZECOMP, IDH_FINDFILECRIT_SIZEIS,
- IDD_SIZEVALUE, IDH_FINDFILECRIT_K,
- IDD_SIZEUPDOWN, IDH_FINDFILECRIT_K,
- IDD_SIZELBL, IDH_FINDFILECRIT_K,
- 0, 0
- };
- const DWORD aDateHelpIDs[] = {
- IDD_MDATE_FROM, IDH_FINDFILEDATE_FROM,
- IDD_MDATE_AND, IDH_FINDFILEDATE_TO,
- IDD_MDATE_TO, IDH_FINDFILEDATE_TO,
- IDD_MDATE_ALL, IDH_FINDFILEDATE_ALLFILES,
- IDD_MDATE_PARTIAL, IDH_FINDFILEDATE_CREATEORMOD,
- IDD_MDATE_DAYS, IDH_FINDFILEDATE_DAYS,
- IDD_MDATE_DAYLBL, IDH_FINDFILEDATE_DAYS,
- IDD_MDATE_MONTHS, IDH_FINDFILEDATE_MONTHS,
- IDD_MDATE_MONTHLBL, IDH_FINDFILEDATE_MONTHS,
- IDD_MDATE_BETWEEN, IDH_FINDFILEDATE_RANGE,
- IDD_MDATE_NUMDAYS, IDH_FINDFILEDATE_DAYS,
- IDD_MDATE_DAYSUPDOWN, IDH_FINDFILEDATE_DAYS,
- IDD_MDATE_NUMMONTHS, IDH_FINDFILEDATE_MONTHS,
- IDD_MDATE_MONTHSUPDOWN, IDH_FINDFILEDATE_MONTHS,
- IDD_MDATE_FROM, IDH_FINDFILEDATE_FROM,
- IDD_MDATE_TO, IDH_FINDFILEDATE_TO,
- 0, 0
- };
- //==========================================================================
- //
- // Create the default filter for our find code... They should be completly
- // self contained...
- //
- extern IDocFindFileFilterVtbl c_DFFilterVtbl; // forward
- IDocFindFileFilter * CreateDefaultDocFindFilter()
- {
- CDFFilter *pfff = (void*)LocalAlloc(LPTR, SIZEOF(CDFFilter));
- if (pfff == NULL)
- return(NULL);
- pfff->dfff.lpVtbl = &c_DFFilterVtbl;
- pfff->cRef = 1;
- pfff->wDateType = DFF_DATE_ALL | DFF_DATE_MODIFIED;
- pfff->ulQueryDialect = ISQLANG_V2;
- // We should now simply return the filter
- return &pfff->dfff;
- }
- STDMETHODIMP_(ULONG) CDFFilter_AddRef(IDocFindFileFilter *pdfff);
- STDMETHODIMP CDFFilter_QueryInterface(IDocFindFileFilter *pdfff, REFIID riid, LPVOID * ppvObj)
- {
- if (IsEqualIID(riid, &IID_IUnknown) ||
- IsEqualIID(riid, &IID_IDocFindFileFilter))
- {
- *ppvObj = pdfff;
- }
- else
- {
- *ppvObj = NULL;
- return E_NOINTERFACE;
- }
- CDFFilter_AddRef(pdfff);
- return NOERROR;
- }
- STDMETHODIMP_(ULONG) CDFFilter_AddRef(IDocFindFileFilter *pdfff)
- {
- CDFFilter *this = IToClass(CDFFilter, dfff, pdfff);
- TraceMsg(TF_DOCFIND, "CDFFilter.AddRef %d",this->cRef+1);
- return InterlockedIncrement(&this->cRef);
- }
- STDMETHODIMP_(ULONG) CDFFilter_Release(IDocFindFileFilter *pdfff)
- {
- CDFFilter *this = IToClass(CDFFilter, dfff, pdfff);
- TraceMsg(TF_DOCFIND, "CDFFilter.Release %d",this->cRef-1);
- if (InterlockedDecrement(&this->cRef))
- return this->cRef;
- // Destroy the MRU Lists...
- if (this->hMRUSpecs)
- FreeMRUList(this->hMRUSpecs);
- if (this->lpgi)
- {
- FreeGrepBufs(this->lpgi);
- this->lpgi = NULL;
- }
- // Release our usage of My computer
- if (this->psfMyComputer)
- {
- this->psfMyComputer->lpVtbl->Release(this->psfMyComputer);
- }
- if (this->pidlStart)
- ILFree(this->pidlStart);
- Str_SetPtr(&(this->pszFileSpec), NULL);
- Str_SetPtr(&(this->pszSpecs), NULL);
- LocalFree(this->apszFileSpecs); // elements point to pszSpecs so no free for them
- Str_SetPtr(&(this->pszIndexedSearch), NULL);
- LocalFree((HLOCAL)this);
- return(0);
- }
- //==========================================================================
- // Function to let the find know which icons to display and the top level menu
- //==========================================================================
- STDMETHODIMP CDFFilter_GetIconsAndMenu (IDocFindFileFilter *pdfff,
- HWND hwndDlg, HICON *phiconSmall, HICON *phiconLarge, HMENU *phmenu)
- {
- *phiconSmall = LoadImage(HINST_THISDLL, MAKEINTRESOURCE(IDI_DOCFIND),
- IMAGE_ICON, g_cxSmIcon, g_cySmIcon, LR_DEFAULTCOLOR);
- *phiconLarge = LoadIcon(HINST_THISDLL, MAKEINTRESOURCE(IDI_DOCFIND));
- // BUGBUG:: Still menu to process!
- *phmenu = LoadMenu(HINST_THISDLL, MAKEINTRESOURCE(MENU_FINDDLG));
- return (S_OK);
- }
- //==========================================================================
- // Function to get the string resource index number that is proper for the
- // current type of search.
- //==========================================================================
- STDMETHODIMP CDFFilter_GetStatusMessageIndex (IDocFindFileFilter *pdfff,
- UINT uContext, UINT *puMsgIndex)
- {
- // Currently context is not used
- *puMsgIndex = IDS_FILESFOUND;
- return (S_OK);
- }
- //==========================================================================
- // Function to let find know which menu to load to merge for the folder
- //==========================================================================
- STDMETHODIMP CDFFilter_GetFolderMergeMenuIndex (IDocFindFileFilter *pdfff,
- UINT *puBGMainMergeMenu, UINT *puBGPopupMergeMenu)
- {
- *puBGMainMergeMenu = POPUP_DOCFIND_MERGE;
- *puBGPopupMergeMenu = POPUP_DOCFIND_POPUPMERGE;
- return (S_OK);
- }
- STDMETHODIMP CDFFilter_GetItemContextMenu (IDocFindFileFilter *pdfff, HWND hwndOwner, IDocFindFolder* pdfFolder, IContextMenu **ppcm)
- {
- *ppcm = CDFFolderContextMenuItem_Create(hwndOwner, pdfFolder);
- return (*ppcm) ? S_OK : E_OUTOFMEMORY;
- }
- STDMETHODIMP CDFFilter_GetDefaultSearchGUID(IDocFindFileFilter *pdfff, IShellFolder2 *psf2, LPGUID lpGuid)
- {
- return FindFileOrFolders_GetDefaultSearchGUID(psf2, lpGuid);
- }
- STDMETHODIMP CDFFilter_EnumSearches(IDocFindFileFilter *pdfff, IShellFolder2 *psf2, LPENUMEXTRASEARCH *ppenum)
- {
- return CFSFolder_EnumSearches(psf2, ppenum);
- }
- STDMETHODIMP CDFFilter_GetSearchFolderClassId(IDocFindFileFilter *pdfff, LPGUID lpGuid)
- {
- *lpGuid = CLSID_DocFindFolder;
- return S_OK;
- }
- //==========================================================================
- // Helper function for add page to the IDocFindFileFilter::AddPages
- //==========================================================================
- HRESULT DocFind_AddPages(IDocFindFileFilter *pdfff, HWND hwndTabs,
- const DFPAGELIST *pdfpl, int cdfpl)
- {
- int i;
- TCHAR szTemp[128+50];
- RECT rc;
- int dxMax = 0;
- int dyMax = 0;
- TC_DFITEMEXTRA tie;
- LPDOCFINDPROPSHEETPAGE pdfpsp;
- HWND hwndDlg;
- tie.tci.mask = TCIF_TEXT | TCIF_PARAM;
- tie.hwndPage = NULL;
- tie.tci.pszText = szTemp;
- TabCtrl_SetItemExtra(hwndTabs, CB_DFITEMEXTRA);
- hwndDlg = GetParent(hwndTabs);
- // First go through and create all of the dialog pages.
- //
- for (i=0; i < cdfpl; i++)
- {
- pdfpsp = LocalAlloc(LPTR, SIZEOF(DOCFINDPROPSHEETPAGE));
- if (pdfpsp == NULL)
- break;
- pdfpsp->psp.dwSize = DOCFINDPSHTSIZE;
- pdfpsp->psp.dwFlags = PSP_DEFAULT;
- pdfpsp->psp.hInstance = HINST_THISDLL;
- pdfpsp->psp.lParam = 0;
- pdfpsp->psp.pszTemplate = MAKEINTRESOURCE(pdfpl[i].id);
- pdfpsp->psp.pfnDlgProc = pdfpl[i].pfn;
- pdfpsp->pdff = (struct _CDFFilter *)pdfff;
- pdfpsp->hThreadInit = NULL;
- tie.hwndPage = DocFindCreatePage(&pdfpsp->psp, hwndDlg);
- if (tie.hwndPage != NULL)
- {
- GetWindowText(tie.hwndPage, szTemp, ARRAYSIZE(szTemp));
- GetWindowRect(tie.hwndPage, &rc);
- if ((rc.bottom - rc.top) > dyMax)
- dyMax = rc.bottom - rc.top;
- if ((rc.right - rc.left) > dxMax)
- dxMax = rc.right - rc.left;
- TabCtrl_InsertItem(hwndTabs, 1000, &tie.tci);
- }
- }
- // We now need to resize everything to fit with the dialog templates
- rc.left = rc.top = 0;
- rc.right = dxMax;
- rc.bottom = dyMax;
- TabCtrl_AdjustRect(hwndTabs, TRUE, &rc);
- // Size the page now
- SetWindowPos(hwndTabs, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
- SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
- // Now set the first page as active. We should be able to do this by
- // simply posting a WM_COMMAND to the main dialog
- SendNotify(hwndDlg, hwndTabs, TCN_SELCHANGE, NULL);
- return (S_OK);
- }
- void WaitForPageInitToComplete(LPDOCFINDPROPSHEETPAGE pdfpsp)
- {
- if (pdfpsp && pdfpsp->hThreadInit)
- {
- WaitForSendMessageThread(pdfpsp->hThreadInit, INFINITE);
- CloseHandle(pdfpsp->hThreadInit);
- pdfpsp->hThreadInit = NULL;
- }
- }
- //==========================================================================
- // IDocFindFileFilter::FFilterChanged - Returns S_OK if nothing changed.
- //==========================================================================
- STDMETHODIMP CDFFilter_FFilterChanged(IDocFindFileFilter *pdfff)
- {
- CDFFilter *this = IToClass(CDFFilter, dfff, pdfff);
- BOOL fFilterChanged = this->fFilterChanged;
- this->fFilterChanged = FALSE;
- return fFilterChanged? S_FALSE : S_OK;
- }
- //==========================================================================
- // IDocFindFileFilter::GenerateTitle - Generates the title given the current
- // search criteria.
- //==========================================================================
- STDMETHODIMP CDFFilter_GenerateTitle(IDocFindFileFilter *pdfff,
- LPTSTR *ppszTitle, BOOL fFileName)
- {
- CDFFilter *this = IToClass(CDFFilter, dfff, pdfff);
- BOOL fFilePattern;
- int iRes;
- TCHAR szFindName[80]; // German should not exceed this find: ->???
- LPTSTR pszFileSpec = this->szUserInputFileSpec;
- LPTSTR pszText = this->szText;
- //
- // Lets generate a title for the search. The title will depend on
- // the file patern(s), the type field and the containing text field
- // Complicate this a bit with the search for field...
- //
- fFilePattern = (pszFileSpec[0] != TEXT('')) &&
- (lstrcmp(pszFileSpec, c_szStarDotStar) != 0);
- if (!fFilePattern && (this->pdfenumAsync == NULL) && this->pszIndexedSearch)
- {
- pszFileSpec = this->pszIndexedSearch;
- fFilePattern = (pszFileSpec[0] != TEXT('')) &&
- (lstrcmp(pszFileSpec, c_szStarDotStar) != 0);
- }
- if ((pszText[0] == TEXT('')) && (this->pdfenumAsync != NULL) && this->pszIndexedSearch)
- pszText = this->pszIndexedSearch;
- // First see if there is a type field
- if (this->iType > 0)
- {
- // We have a type field no check for content...
- if (pszText[0] != TEXT(''))
- {
- // There is text!
- // Should now use type but...
- // else see if the name field is not NULL and not *.*
- if (fFilePattern)
- iRes = IDS_FIND_TITLE_TYPE_NAME_TEXT;
- else
- iRes = IDS_FIND_TITLE_TYPE_TEXT;
- }
- else
- {
- // No type or text, see if file pattern
- // Containing not found, first search for type then named
- if (fFilePattern)
- iRes = IDS_FIND_TITLE_TYPE_NAME;
- else
- iRes = IDS_FIND_TITLE_TYPE;
- }
- }
- else
- {
- // No Type field ...
- // first see if there is text to be searched for!
- if (pszText[0] != TEXT(''))
- {
- // There is text!
- // Should now use type but...
- // else see if the name field is not NULL and not *.*
- if (fFilePattern)
- iRes = IDS_FIND_TITLE_NAME_TEXT;
- else
- iRes = IDS_FIND_TITLE_TEXT;
- }
- else
- {
- // No type or text, see if file pattern
- // Containing not found, first search for type then named
- if (fFilePattern)
- iRes = IDS_FIND_TITLE_NAME;
- else
- iRes = IDS_FIND_TITLE_ALL;
- }
- }
- // We put : in for first spot for title bar. For name creation
- // we remove it which will put the number at the end...
- if (!fFileName)
- LoadString(HINST_THISDLL, IDS_FIND_TITLE_FIND,
- szFindName, ARRAYSIZE(szFindName));
- *ppszTitle = ShellConstructMessageString(HINST_THISDLL,
- MAKEINTRESOURCE(iRes),
- fFileName? szNULL : szFindName,
- this->szTypeName, pszFileSpec, pszText);
- return *ppszTitle ? S_OK : E_OUTOFMEMORY;
- }
- //==========================================================================
- // IDocFindFileFilter::ClearSearchCriteria
- //==========================================================================
- STDMETHODIMP CDFFilter_ClearSearchCriteria(IDocFindFileFilter *pdfff)
- {
- int cPages;
- HWND hwndMainDlg;
- TC_DFITEMEXTRA tie;
- CDFFilter *this = IToClass(CDFFilter, dfff, pdfff);
- hwndMainDlg = GetParent(this->hwndTabs);
- for (cPages = TabCtrl_GetItemCount(this->hwndTabs) -1; cPages >= 0; cPages--)
- {
- tie.tci.mask = TCIF_PARAM;
- TabCtrl_GetItem(this->hwndTabs, cPages, &tie.tci);
- SendNotify(tie.hwndPage, hwndMainDlg, PSN_RESET, NULL);
- }
- // Also clear out a few other fields...
- this->szUserInputFileSpec[0] = TEXT('');
- this->iType = 0;
- this->szText[0] = TEXT('');
- return (S_OK);
- }
- //==========================================================================
- // DocFind_SetupWildCardingOnFileSpec - returns TRUE if wildards are in
- // extension. Both "*" and "?" are treated as wildcards.
- //==========================================================================
- BOOL DocFind_SetupWildCardingOnFileSpec(LPTSTR pszSpecIn, LPTSTR *ppszSpecOut)
- {
- LPTSTR pszIn = pszSpecIn;
- LPTSTR pszOut;
- LPTSTR pszStar;
- LPTSTR pszAnyC;
- BOOL fQuote;
- TCHAR szSpecOut[3*MAX_PATH]; // Rather large...
- // allocate a buffer that should be able to hold the resultant
- // string. When all is said and done we'll re-allocate to the
- // correct size.
- pszOut = szSpecOut;
- while (*pszIn != TEXT(''))
- {
- LPTSTR pszT;
- int ich;
- TCHAR c;
- // Strip in leading spaces out of there
- while (*pszIn == TEXT(' '))
- pszIn++;
- if (*pszIn == TEXT(''))
- break;
- if (pszOut != szSpecOut)
- *pszOut++ = TEXT(';');
- if (FALSE != (fQuote = (*pszIn == TEXT('"'))))
- {
- // The user asked for something litteral.
- pszT = pszIn = CharNext(pszIn);
- while (*pszT && (*pszT != TEXT('"')))
- pszT = CharNext(pszT);
- }
- else
- {
- pszT = pszIn + (ich = StrCSpn(pszIn, TEXT(",; ")));
- }
- c = *pszT; // Save away the seperator character that was found
- *pszT = TEXT(''); //
- // Put in a couple of tests for * and *.*
- if ((lstrcmp(pszIn, c_szStar) == 0) ||
- (lstrcmp(pszIn, c_szStarDotStar) == 0))
- {
- // Complete wild card so set a null criteria
- *pszT = c; // Restore char;
- pszOut = szSpecOut; // Set to start of string
- break;
- }
- if (fQuote)
- {
- lstrcpy(pszOut, pszIn);
- pszOut += lstrlen(pszIn);
- }
- else
- {
- // both "*" and "?" are wildcards. When checking for wildcards check
- // for both before we conclude there are no wildcards. If a search
- // string contains both "*" and "?" then we need for pszStar to point
- // to the last occorance of either one (this is assumed in the code
- // below which will add a ".*" when pszStar is the last character).
- // NOTE: I wish there was a StrRPBrk function to do this for me.
- pszStar = StrRChr(pszIn, NULL, TEXT('*'));
- pszAnyC = StrRChr(pszIn, NULL, TEXT('?'));
- if (pszAnyC > pszStar)
- pszStar = pszAnyC;
- if (pszStar == NULL)
- {
- // No wildcards were used:
- *pszOut++ = TEXT('*');
- lstrcpy(pszOut, pszIn);
- pszOut += ich;
- *pszOut++ = TEXT('*');
- }
- else
- {
- // Includes wild cards
- lstrcpy(pszOut, pszIn);
- pszOut += ich;
- // if no extension
- pszAnyC = StrRChr(pszIn, NULL, TEXT('.'));
- if ( pszAnyC == NULL )
- {
- // No extension is given
- if ((*(pszStar+1) == TEXT('')) && (*pszStar == TEXT('*')))
- {
- // The last character is an "*" so this single string will
- // match everything you would expect.
- }
- else
- {
- // in order to get the expected behavior we need to search
- // for two things, the actual string entered and the string
- // with any extension. I.E. given "a*a" we need to search
- // for "a*a" and "a*a.*". Otherwise we won't find both the
- // file "abba" and "abba.wav". As a bonus we also pick up
- // "abc.cba" this way when using "*". This also helps for
- // "a?", allowing it to find "a1.txt" as well as "aa"
- *pszOut++ = TEXT(';'); // seperate the two strings
- lstrcpy(pszOut, pszIn); // add the second variant
- pszOut += ich;
- *pszOut++ = TEXT('.');
- *pszOut++ = TEXT('*'); // Add on .* to the name
- }
- }
- }
- }
- *pszT = c; // Restore char;
- if (c == TEXT(''))
- break;
- // Skip beyond quotes
- if (*pszT == TEXT('"'))
- pszT++;
- if (*pszT != TEXT(''))
- pszT++;
- pszIn = pszT; // setup for the next item
- }
- *pszOut++ = TEXT('');
- // re-alloc the buffer down to the actual size of the string...
- Str_SetPtr(ppszSpecOut, szSpecOut);
- return TRUE;
- }
- //==========================================================================
- // IDocFindFileFilter::PrepareToEnumObjects
- //==========================================================================
- STDMETHODIMP CDFFilter_PrepareToEnumObjects(IDocFindFileFilter *pdfff, DWORD *pdwFlags)
- {
- int cPages;
- TC_DFITEMEXTRA tie;
- SHELLSTATE ss;
- CDFFilter *this = IToClass(CDFFilter, dfff, pdfff);
- if (this->hwndTabs)
- {
- HWND hwndMainDlg;
- hwndMainDlg = GetParent(this->hwndTabs);
- for (cPages = TabCtrl_GetItemCount(this->hwndTabs) -1; cPages >= 0; cPages--)
- {
- tie.tci.mask = TCIF_PARAM;
- TabCtrl_GetItem(this->hwndTabs, cPages, &tie.tci);
- SendNotify(tie.hwndPage, hwndMainDlg, PSN_APPLY, NULL);
- }
- }
- // Update the flags and buffer strings
- if (this->fTopLevelOnly)
- *pdwFlags &= ~DFOO_INCLUDESUBDIRS;
- else
- *pdwFlags |= DFOO_INCLUDESUBDIRS;
- if (this->fTextCaseSen)
- *pdwFlags |= FFLT_CASESEN;
- if (this->fTextReg)
- *pdwFlags |= FFLT_REGULAR;
- // Also get the shell state variables to see if we should show extensions and the like
- SHGetSetSettings(&ss, SSF_SHOWEXTENSIONS|SSF_SHOWALLOBJECTS, FALSE);
- if (ss.fShowExtensions)
- *pdwFlags |= DFOO_SHOWEXTENSIONS;
- else
- *pdwFlags &= ~DFOO_SHOWEXTENSIONS;
- this->fShowAllObjects = ss.fShowAllObjects;
- if (ss.fShowAllObjects)
- *pdwFlags |= DFOO_SHOWALLOBJECTS;
- else
- *pdwFlags &= ~DFOO_SHOWALLOBJECTS;
- // Now lets generate the file patern we will ask the system to look for
- // for now we will simply copy the file spec in...
- // Here is where we try to put some smarts into the file patterns stuff
- // It will go something like:
- // look between each; or , and see if there are any wild cards. If not
- // do something like *patern*.
- // Also if there is no search pattern or if it is * or *.*, set the
- // filter to NULL as to speed it up.
- //
- DocFind_SetupWildCardingOnFileSpec(this->szUserInputFileSpec, &this->pszFileSpec);
- this->cFileSpecs = 0;
- if (this->pszFileSpec && this->pszFileSpec[0])
- {
- Str_SetPtr(&(this->pszSpecs), this->pszFileSpec);
- if (this->pszSpecs)
- {
- int cTokens = 0;
- LPTSTR pszToken = this->pszSpecs;
- while (pszToken)
- {
- // let's walk pszFileSpec to see how many specs we have...
- pszToken = StrChr(pszToken, TEXT(';'));
- if (pszToken)
- pszToken++;
- cTokens++;
- }
- if (cTokens)
- {
- int i;
- // cleanup the previous search
- if (this->apszFileSpecs)
- LocalFree(this->apszFileSpecs);
- this->apszFileSpecs = (LPTSTR *)LocalAlloc(LPTR, cTokens*SIZEOF(LPTSTR *));
- if (this->apszFileSpecs)
- {
- this->cFileSpecs = cTokens;
- pszToken = this->pszSpecs;
- for (i = 0; i < cTokens; i++)
- {
- this->apszFileSpecs[i] = pszToken;
- pszToken = StrChr(pszToken, TEXT(';'));
- if (pszToken)
- *pszToken++ = TEXT('');
- }
- }
- }
- }
- }
- //
- // Also if there is a search string associated with this search
- // criteria, we need to initialize the search to allow greping on
- // it.
- // First check to see if we have an old one to release...
- if (this->lpgi)
- {
- FreeGrepBufs(this->lpgi);
- this->lpgi = NULL;
- }
- if (this->szText[0] != TEXT(''))
- {
- #ifdef UNICODE
- LPSTR lpszText;
- UINT cchLength;
- cchLength = lstrlen(this->szText)+1;
- lpszText = this->szTextA;
- cchLength = WideCharToMultiByte(CP_ACP, 0,
- this->szText, cchLength,
- this->szTextA, ARRAYSIZE(this->szTextA),
- NULL, NULL);
- // Must double NULL terminate lpszText. InitGrepInfo requires
- // this format!
- lpszText[cchLength] = ''; // Do not wrap with TEXT(); should be ANSI
- #ifdef DOCFIND_RESUPPORT
- this->lpgi = InitGrepInfo(lpszText, (LPSTR)szNULL,
- *pdwFlags & (FFLT_REGULAR | FFLT_CASESEN));
- #else
- this->lpgi = InitGrepInfo(lpszText, (LPSTR)szNULL,
- *pdwFlags & (FFLT_CASESEN));
- #endif
- #else
- #ifdef DOCFIND_RESUPPORT
- this->lpgi = InitGrepInfo(this->szText, (LPTSTR)szNULL,
- *pdwFlags & (FFLT_REGULAR | FFLT_CASESEN));
- #else
- this->lpgi = InitGrepInfo(this->szText, (LPTSTR)szNULL,
- *pdwFlags & (FFLT_CASESEN));
- #endif
- #endif
- }
- return S_OK;
- }
- //==========================================================================
- // IDocFindFileFilter::GetDetailsof
- //==========================================================================
- STDMETHODIMP CDFFilter_GetDetailsOf(IDocFindFileFilter *pdfff, HDPA hdpaPidf,
- LPCITEMIDLIST pidl, UINT *piColumn, LPSHELLDETAILS pdi)
- {
- CDFFilter *this = IToClass(CDFFilter, dfff, pdfff);
- HRESULT hr = S_OK;
- if (*piColumn >= ARRAYSIZE(c_df_cols))
- return E_NOTIMPL;
- pdi->str.uType = STRRET_CSTR;
- pdi->str.cStr[0] = 0;
- if (!pidl)
- {
- pdi->fmt = c_df_cols[*piColumn].iFmt;
- pdi->cxChar = c_df_cols[*piColumn].cchCol;
- hr = ResToStrRet(c_df_cols[*piColumn].ids, &pdi->str);
- }
- else
- {
- TCHAR szTemp[MAX_PATH];
- if (*piColumn == IDFCOL_PATH)
- {
- // We need to now get to the idlist of the items folder.
- DFFolderListItem *pdffli = (DFFolderListItem *)DPA_GetPtr(hdpaPidf, DF_IFOLDER(pidl));
- if (pdffli)
- {
- SHGetPathFromIDList(&pdffli->idl, szTemp);
- hr = StringToStrRet(szTemp, &pdi->str);
- if (pdffli->iImage == -1)
- {
- SHFILEINFO sfi;
- SHGetFileInfo((LPCTSTR)&pdffli->idl, 0, &sfi, sizeof(sfi), SHGFI_PIDL | SHGFI_SYSICONINDEX);
- pdffli->iImage = sfi.iIcon;
- }
- }
- }
- else if (*piColumn == IDFCOL_RANK)
- {
- // See if the pidl has extra data or not. If so use it
- PCHIDDENDOCFINDDATA phdfd = (PCHIDDENDOCFINDDATA) ILFindHiddenID(pidl, IDLHID_DOCFINDDATA);
- if (phdfd && (phdfd->wFlags & DFDF_EXTRADATA))
- {
- AddCommas(phdfd->ulRank, szTemp);
- hr = StringToStrRet(szTemp, &pdi->str);
- }
- }
- #ifdef IF_ADD_MORE_COLS
- else if (*piColumn >= IDFCOL_FIRST_QUERY)
- {
- // OK simply return S_FALSE and if we have a query active the caller will handle it.
- *piColumn -= IDFCOL_FIRST_QUERY;
- hr = S_FALSE; // tell caller to do it
- }
- #endif
- else if (*piColumn < ARRAYSIZE(c_df_cols))
- {
- // We need to now get to the idlist of the items folder.
- DFFolderListItem *pdffli = (DFFolderListItem *)DPA_GetPtr(hdpaPidf, DF_IFOLDER(pidl));
- // Let the file system function do it for us...
- if (pdffli)
- {
- IShellFolder *psf = DocFind_GetObjectsIFolder(NULL, pdffli, NULL);
- hr = E_FAIL;
- if (psf)
- {
- IShellFolder2 *psf2;
- hr = psf->lpVtbl->QueryInterface(psf, &IID_IShellFolder2, (void **)&psf2);
- if (SUCCEEDED(hr))
- {
- hr = MapSCIDToDetailsOf(psf2, pidl, c_df_cols[*piColumn].pscid, pdi);
- psf2->lpVtbl->Release(psf2);
- }
- psf->lpVtbl->Release(psf);
- }
- }
- }
- }
- return hr;
- }
- //==========================================================================
- // IDocFindFileFilter::FDoesItemMatchFilter
- //==========================================================================
- STDMETHODIMP CDFFilter_FDoesItemMatchFilter(IDocFindFileFilter *pdfff,
- LPTSTR pszFolder, WIN32_FIND_DATA * pfd,
- IShellFolder *psf, LPITEMIDLIST pidl)
- {
- CDFFilter *this = IToClass(CDFFilter, dfff, pdfff);
- SCODE sc = MAKE_SCODE(0, 0, 1);
- WORD wFileDate, wFileTime;
- FILETIME ftLocal;
- TCHAR szPath[MAX_PATH];
- WIN32_FIND_DATA finddata;
- if (psf)
- {
- STRRET strret;
- HANDLE hfind;
- LPITEMIDLIST pidlLast = ILFindLastID(pidl);
- // This came in through a notify.. We should get enough info to make it work
- // properly... For now this will be gross and we will hit file system...
- // Also we passed through the full pidl to make sure that we could
- // verify properly if this in the tree we are interested in...
- // BUGBUG:: Need to better handle multiple paths!
- if ((this->pidlStart && !ILIsParent(this->pidlStart, pidl, (BOOL)this->fTopLevelOnly))
- || (!this->pidlStart && (BOOL)this->fTopLevelOnly))
- return 0;
- pfd = &finddata;
- if (FAILED(psf->lpVtbl->GetDisplayNameOf(psf, pidlLast, SHGDN_FORPARSING, &strret)))
- return 0;
- if (FAILED(StrRetToBuf(&strret, pidlLast, szPath, ARRAYSIZE(szPath))))
- return 0;
- hfind = FindFirstFile(szPath, pfd);
- if (INVALID_HANDLE_VALUE == hfind)
- return 0;
- FindClose(hfind);
- }
- // Note: We do not use the IDList in this one...
- // This function does filtering of the file information for
- // things that are not part of the standard file filter
- // First things we dont show hidden files
- // If show all is set then we should include hidden files also...
- if (!this->fShowAllObjects &&
- (pfd->dwFileAttributes & FILE_ATTRIBUTE_HIDDEN))
- return (0); // does not match
- if (IsSuperHidden(pfd->dwFileAttributes))
- return (0); // does not match
- // Process the case where we are looking for folders only
- if (this->fFoldersOnly &&
- ((pfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)==0))
- return (0); // does not match
- switch (this->iSizeType)
- {
- case 1: // >
- if (!(pfd->nFileSizeLow > this->dwSize))
- return (0); // does not match
- break;
- case 2: // <
- if (!(pfd->nFileSizeLow < this->dwSize))
- return (0); // does not match
- break;
- }
- // See if we should compare dates...
- switch (this->wDateType & DFF_DATE_TYPEMASK)
- {
- case DFF_DATE_ACCESSED:
- FileTimeToLocalFileTime(&pfd->ftLastAccessTime, &ftLocal);
- break;
- case DFF_DATE_CREATED:
- FileTimeToLocalFileTime(&pfd->ftCreationTime, &ftLocal);
- break;
- case DFF_DATE_MODIFIED:
- FileTimeToLocalFileTime(&pfd->ftLastWriteTime, &ftLocal);
- }
- FileTimeToDosDateTime(&ftLocal, &wFileDate, &wFileTime);
- if (this->dateModifiedBefore != 0)
- {
- if (!(wFileDate <= this->dateModifiedBefore))
- return (0); // does not match
- }
- if (this->dateModifiedAfter != 0)
- {
- if (!(wFileDate >= this->dateModifiedAfter))
- return (0); // does not match
- }
- // Match file specificaitions.
- if (this->pszFileSpec && this->pszFileSpec[0])
- {
- // if we have split up version of the specs we'll use it because PathMatchSpec is pretty stupid
- // and can take up to 5-6 hours for more than 10 wildcard specs
- if (this->cFileSpecs)
- {
- int i;
- BOOL bMatch = FALSE;
- for (i = 0; i < this->cFileSpecs; i++)
- {
- bMatch = PathMatchSpec(pfd->cFileName, this->apszFileSpecs[i]);
- if (bMatch)
- break;
- }
- if (!bMatch)
- return (0);
- }
- else if (!PathMatchSpec(pfd->cFileName, this->pszFileSpec))
- {
- //short file name is never displayed to the user so don't use it to find match
- //&& !PathMatchSpec(pfd->cAlternateFileName, this->pszFileSpec))
- return (0); // does not match
- }
- }
- if (this->szTypeFilePatterns[0])
- {
- // if looking for folders only and file pattern is all folders then no need to check
- // if folder name matches the pattern -- we know it is the folder, otherwise we
- // would have bailed out earlier in the function
- if (!(this->fFoldersOnly && lstrcmp(this->szTypeFilePatterns, TEXT(".")) == 0))
- {
- if (!PathMatchSpec(pfd->cFileName, this->szTypeFilePatterns))
- return (0); // does not match
- }
- }
- //
- // See if we need to do a grep of the file
- if (this->lpgi)
- {
- HANDLE hfil;
- BOOL fMatch = FALSE;
- DWORD dwCFOpts = FILE_FLAG_SEQUENTIAL_SCAN;
- #ifdef WINNT
- if (g_bRunOnNT5 && PathIsHighLatency(pfd->cFileName, pfd->dwFileAttributes))
- {
- if (this->fSearchSlowFiles)
- dwCFOpts |= FILE_FLAG_OPEN_NO_RECALL;
- else
- return (0); // No match returned if files are high latency and user hasn't selected to search high latency files
- }
- #endif
- // Don't grep files with the system bit set.
- // This was added explicitly to not search things like the
- // swap file and the like.
- if (pfd->dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
- return (0); // does not match
- if (!psf)
- {
- lstrcpy(szPath, pszFolder);
- PathAppend(szPath, pfd->cFileName);
- }
- // Pass in File_write_attributes so we can change the file access time. Ya, wierd name
- // to pass in as a access type but this is what kernel looks for...
- // Also try to pass through the no recall flags... If we get access denied again then
- // dond't pass this flag, my guess is that some networks like netware probably don't have
- // support for this flag...
- hfil = CreateFile(szPath,
- GENERIC_READ | FILE_WRITE_ATTRIBUTES,
- FILE_SHARE_READ ,
- 0, OPEN_EXISTING, dwCFOpts, 0);
- if (hfil == INVALID_HANDLE_VALUE)
- {
- // Some readonly shares don't like the FILE_WRITE_ATTRIBUTE, try without
- if (GetLastError() == ERROR_ACCESS_DENIED)
- hfil = CreateFile(szPath, GENERIC_READ, FILE_SHARE_READ , 0, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, 0);
- }
- if (hfil != INVALID_HANDLE_VALUE)
- {
- // Go get around wimpy APIS that set the access date...
- FILETIME ftLastAccess;
- if (GetFileTime(hfil, NULL, &ftLastAccess, NULL))
- SetFileTime(hfil, NULL, &ftLastAccess, NULL);
- fMatch = FileFindGrep(this->lpgi, hfil, FIND_FILE, NULL) != 0;
- CloseHandle(hfil);
- }
- if (!fMatch)
- return (0); // does not match
- }
- return (sc); // return TRUE to imply yes!
- }
- //==========================================================================
- // Helper function for save criteria that will output the string and
- // and id to the specified file. it will also test for NULL and the like
- //==========================================================================
- int Docfind_SaveCriteriaItem(IStream * pstm, WORD wNum,
- LPTSTR psz, WORD fCharType)
- {
- if ((psz == NULL) || (*psz == TEXT('')))
- return 0;
- else
- {
- LPVOID pszText = (LPVOID)psz; // Ptr to output text. Defaults to source.
- #ifdef WINNT
- //
- // These are required to support ANSI-unicode conversions.
- //
- LPSTR pszAnsi = NULL; // For unicode-to-ansi conversion.
- LPWSTR pszWide = NULL; // For ansi-to-unicode conversion.
- #endif
- DFCRITERIA dfc;
- dfc.wNum = wNum;
- dfc.cbText = (WORD) ((lstrlen(psz) + 1) * SIZEOF(TCHAR));
- #ifdef WINNT
- #ifdef UNICODE
- //
- // Source string is Unicode but caller wants to save as ANSI.
- //
- if (DFC_FMT_ANSI == fCharType)
- {
- // Convert to ansi and write ansi.
- dfc.cbText = (WORD) WideCharToMultiByte(CP_ACP, 0L, psz, -1, pszAnsi, 0, NULL, NULL);
- if ((pszAnsi = (LPSTR)LocalAlloc(LMEM_FIXED, dfc.cbText)) != NULL)
- {
- WideCharToMultiByte(CP_ACP, 0L, psz, -1, pszAnsi, dfc.cbText / sizeof(pszAnsi[0]), NULL, NULL);
- pszText = (LPVOID)pszAnsi;
- }
- }
- #else
- //
- // Source string is ANSI but caller wants to save as Unicode.
- //
- if (DFC_FMT_UNICODE == fCharType)
- {
- // Convert to unicode and write unicode.
- dfc.cbText = MultiByteToWideChar(CP_ACP, 0L, psz, -1, pszWide, 0);
- if ((pszWide = (LPWSTR)LocalAlloc(LMEM_FIXED, dfc.cbText)) != NULL)
- {
- MultiByteToWideChar(CP_ACP, 0L, psz, -1, pszWide, dfc.cbText / sizeof(pszWide[0]));
- pszText = (LPVOID)pszWide;
- }
- }
- #endif // UNICODE
- #endif // WINNT
- pstm->lpVtbl->Write(pstm, (LPTSTR)&dfc, SIZEOF(dfc), NULL); // Output index
- pstm->lpVtbl->Write(pstm, pszText, dfc.cbText, NULL); // output string + NULL
- #ifdef WINNT
- //
- // Free up conversion buffers if any were created.
- //
- if (NULL != pszAnsi)
- LocalFree(pszAnsi);
- if (NULL != pszWide)
- LocalFree(pszWide);
- #endif
- }
- return(1);
- }
- //==========================================================================
- // IDocFindFileFilter::SaveCriteria
- //==========================================================================
- STDMETHODIMP CDFFilter_SaveCriteria(IDocFindFileFilter *pdfff, IStream * pstm, WORD fCharType)
- {
- const TCHAR c_szPercentD[] = TEXT("%d");
- //
- CDFFilter *this = IToClass(CDFFilter, dfff, pdfff);
- int cCriteria;
- TCHAR szTemp[40]; // some random size
- LPITEMIDLIST pidlMyComputer;
- // The caller should have already validated the stuff and updated
- // everything for the current filter information.
- // we need to walk through and check each of the items to see if we
- // have a criteria to save away. this includes:
- // (Name, Path, Type, Contents, size, modification dates)
- cCriteria = Docfind_SaveCriteriaItem(pstm, IDD_FILESPEC, this->szUserInputFileSpec, fCharType);
- pidlMyComputer = SHCloneSpecialIDList(NULL, CSIDL_DRIVES, FALSE);
- if (this->pidlStart && ILIsEqual(this->pidlStart, pidlMyComputer))
- {
- cCriteria += Docfind_SaveCriteriaItem(pstm, IDD_PATH,
- TEXT("::"), fCharType);
- }
- else
- cCriteria += Docfind_SaveCriteriaItem(pstm, IDD_PATH,
- this->szPath, fCharType);
- ILFree(pidlMyComputer);
- cCriteria += Docfind_SaveCriteriaItem(pstm, DFSC_SEARCHFOR,
- this->pszIndexedSearch, fCharType);
- cCriteria += Docfind_SaveCriteriaItem(pstm, IDD_TYPECOMBO,
- this->szTypeFilePatterns, fCharType);
- cCriteria += Docfind_SaveCriteriaItem(pstm, IDD_CONTAINS,
- this->szText, fCharType);
- // Also save away the state of the top level only
- wsprintf(szTemp, c_szPercentD, this->fTopLevelOnly);
- cCriteria += Docfind_SaveCriteriaItem(pstm, IDD_TOPLEVELONLY, szTemp, fCharType);
- // The Size field is little more fun!
- if (this->iSizeType != 0)
- {
- wsprintf(szTemp, TEXT("%d %ld"), this->iSizeType, this->dwSize);
- cCriteria += Docfind_SaveCriteriaItem(pstm, IDD_SIZECOMP, szTemp, fCharType);
- }
- // Likewise for the dates, should be fun as we need to save it depending on
- // how the date was specified
- switch (this->wDateType & DFF_DATE_RANGEMASK)
- {
- case DFF_DATE_ALL:
- // nothing to store
- break;
- case DFF_DATE_DAYS:
- wsprintf(szTemp, c_szPercentD, this->wDateValue);
- cCriteria += Docfind_SaveCriteriaItem(pstm, IDD_MDATE_NUMDAYS, szTemp, fCharType);
- break;
- case DFF_DATE_MONTHS:
- wsprintf(szTemp, c_szPercentD, this->wDateValue);
- cCriteria += Docfind_SaveCriteriaItem(pstm, IDD_MDATE_NUMMONTHS, szTemp, fCharType);
- break;
- case DFF_DATE_BETWEEN:
- if (this->dateModifiedAfter != 0)
- {
- wsprintf(szTemp, c_szPercentD, this->dateModifiedAfter);
- cCriteria += Docfind_SaveCriteriaItem(pstm, IDD_MDATE_FROM, szTemp, fCharType);
- }
- if (this->dateModifiedBefore != 0)
- {
- wsprintf(szTemp, c_szPercentD, this->dateModifiedBefore);
- cCriteria += Docfind_SaveCriteriaItem(pstm, IDD_MDATE_TO, szTemp, fCharType);
- }
- break;
- }
- if (((this->wDateType & DFF_DATE_RANGEMASK) != DFF_DATE_ALL) &&
- (this->wDateType & DFF_DATE_TYPEMASK))
- {
- wsprintf(szTemp, c_szPercentD, this->wDateType & DFF_DATE_TYPEMASK);
- cCriteria += Docfind_SaveCriteriaItem(pstm, IDD_MDATE_TYPE, szTemp, fCharType);
- }
- if( this->fTextCaseSen )
- {
- wsprintf( szTemp, TEXT("%d"), this->fTextCaseSen );
- cCriteria += Docfind_SaveCriteriaItem(pstm, IDD_TEXTCASESEN, szTemp, fCharType);
- }
- if( this->fTextReg )
- {
- wsprintf( szTemp, TEXT("%d"), this->fTextReg );
- cCriteria += Docfind_SaveCriteriaItem(pstm, IDD_TEXTREG, szTemp, fCharType);
- }
- if( this->fSearchSlowFiles )
- {
- wsprintf( szTemp, TEXT("%d"), this->fSearchSlowFiles );
- cCriteria += Docfind_SaveCriteriaItem(pstm, IDD_SEARCHSLOWFILES, szTemp, fCharType);
- }
- return (MAKE_SCODE(0, 0, cCriteria));
- }
- //==========================================================================
- // IDocFindFileFilter::RestoreCriteria
- //==========================================================================
- STDMETHODIMP CDFFilter_RestoreCriteria(IDocFindFileFilter *pdfff,
- IStream * pstm, int cCriteria, WORD fCharType)
- {
- CDFFilter *this = IToClass(CDFFilter, dfff, pdfff);
- TCHAR szTemp[MAX_PATH]; // some random size
- if (cCriteria > 0)
- this->fWeRestoredSomeCriteria = TRUE;
- while (cCriteria--)
- {
- // BUGBUG(DavePl) I'm assuming that if UNICODE chars are written in this
- // stream, the cb is written accordingly. ie: what you put in the stream
- // is your own business, but write the cb as a byte count, not char count
- DFCRITERIA dfc;
- int cb;
- if (FAILED(pstm->lpVtbl->Read(pstm, &dfc, SIZEOF(dfc), &cb))
- || (cb != SIZEOF(dfc)) || (dfc.cbText > SIZEOF(szTemp)))
- break;
- #ifdef WINNT
- #ifdef UNICODE
- if (DFC_FMT_UNICODE == fCharType)
- {
- //
- // Destination is Unicode and we're reading Unicode data from stream.
- // No conversion required.
- //
- if (FAILED(pstm->lpVtbl->Read(pstm, szTemp, dfc.cbText, &cb))
- || (cb != dfc.cbText))
- break;
- }
- else
- {
- char szAnsi[MAX_PATH];
- //
- // Destination is Unicode but we're reading ANSI data from stream.
- // Read ansi. Convert to unicode.
- //
- if (FAILED(pstm->lpVtbl->Read(pstm, szAnsi, dfc.cbText, &cb))
- || (cb != dfc.cbText))
- break;
- MultiByteToWideChar(CP_ACP, 0L, szAnsi, -1, szTemp, ARRAYSIZE(szTemp));
- }
- #else
- if (DFC_FMT_ANSI == fCharType)
- {
- //
- // Destination is ANSI and we're reading ANSI data from stream.
- // No conversion required.
- //
- if (FAILED(pstm->lpVtbl->Read(pstm, szTemp, dfc.cbText, &cb))
- || (cb != dfc.cbText))
- break;
- }
- else
- {
- //
- // Destination is ANSI but we're reading Unicode data from stream.
- // Read unicode. Convert to ansi.
- //
- WCHAR szWide[MAX_PATH];
- if (FAILED(pstm->lpVtbl->Read(pstm, szWide, dfc.cbText, &cb))
- || (cb != dfc.cbText))
- break;
- WideCharToMultiByte(CP_ACP, 0L, szWide, -1, szTemp, ARRAYSIZE(szTemp), NULL, NULL);
- }
- #endif // UNICODE
- #else
- if (FAILED(pstm->lpVtbl->Read(pstm, &szTemp, dfc.cbText, &cb))
- || (cb != dfc.cbText))
- break;
- #endif // WINNT
- switch (dfc.wNum)
- {
- case IDD_FILESPEC:
- lstrcpy(this->szUserInputFileSpec, szTemp);
- break;
- case DFSC_SEARCHFOR:
- Str_SetPtr(&(this->pszIndexedSearch), szTemp);
- break;
- case IDD_PATH:
- if (lstrcmp(szTemp, TEXT("::")) == 0)
- {
- this->pidlStart = SHCloneSpecialIDList(NULL, CSIDL_DRIVES, FALSE);
- szTemp[0] = TEXT('');
- }
- else if (StrChr(szTemp,TEXT(';')) == NULL)
- {
- // Simple pidl...
- this->pidlStart = ILCreateFromPath(szTemp);
- }
- lstrcpy(this->szPath, szTemp);
- break;
- case IDD_TOPLEVELONLY:
- this->fTopLevelOnly = StrToInt(szTemp);
- break;
- case IDD_TYPECOMBO:
- lstrcpy(this->szTypeFilePatterns, szTemp);
- break;
- case IDD_CONTAINS:
- lstrcpy(this->szText, szTemp);
- break;
- case IDD_SIZECOMP:
- // we need to extract off the two parts, the type and
- // the value
- this->iSizeType = szTemp[0] - TEXT('0');
- this->dwSize = StrToInt(&szTemp[2]);
- break;
- case IDD_MDATE_NUMDAYS:
- this->wDateType = DFF_DATE_DAYS;
- this->wDateValue = (WORD) StrToInt(szTemp);
- break;
- case IDD_MDATE_NUMMONTHS:
- this->wDateType = DFF_DATE_MONTHS;
- this->wDateValue = (WORD) StrToInt(szTemp);
- break;
- case IDD_MDATE_FROM:
- this->wDateType = DFF_DATE_BETWEEN;
- this->dateModifiedAfter = (WORD) StrToInt(szTemp);
- break;
- case IDD_MDATE_TO:
- this->wDateType = DFF_DATE_BETWEEN;
- this->dateModifiedBefore = (WORD) StrToInt(szTemp);
- break;
- case IDD_MDATE_TYPE:
- this->wDateType |= (WORD)StrToInt(szTemp);
- break;
- case IDD_TEXTCASESEN:
- this->fTextCaseSen = (BITBOOL)StrToInt(szTemp);
- break;
- case IDD_TEXTREG:
- this->fTextReg = (BITBOOL)StrToInt(szTemp);
- break;
- case IDD_SEARCHSLOWFILES:
- this->fSearchSlowFiles = (BITBOOL)StrToInt(szTemp);
- break;
- }
- }
- return (S_OK);
- }
- //==========================================================================
- // IDocFindFileFilter::GetColSaveStream
- //==========================================================================
- STDMETHODIMP CDFFilter_GetColSaveStream(IDocFindFileFilter *pnetf, WPARAM wParam, IStream **ppstm)
- {
- *ppstm = OpenRegStream(HKEY_CURRENT_USER, REGSTR_PATH_EXPLORER, TEXT("DocFindColsX"), (DWORD) wParam);
- return(*ppstm ? S_OK : E_FAIL);
- }
- DWORD AddToQuery(LPWSTR *ppszBuf, DWORD *pcchBuf, LPWSTR pszAdd)
- {
- DWORD cchAdd = lstrlenW(pszAdd);
- if (*ppszBuf && *pcchBuf > cchAdd)
- {
- StrCpyNW(*ppszBuf, pszAdd, *pcchBuf);
- *pcchBuf -= cchAdd;
- *ppszBuf += cchAdd;
- }
- return cchAdd;
- }
- DWORD AddQuerySep(DWORD *pcchBuf, LPWSTR *ppszCurrent, WCHAR bSep)
- {
- LPWSTR pszCurrent = *ppszCurrent;
- // make sure we have room for us plus terminator...
- if (*ppszCurrent && *pcchBuf >= 4)
- {
- *pszCurrent++ = L' ';
- *pszCurrent++ = bSep;
- *pszCurrent++ = L' ';
- *ppszCurrent = pszCurrent;
- *pcchBuf -= 3;
- }
- return 3; // size necessary
- }
- DWORD PrepareQueryParam(BOOL *pbFirst, DWORD *pcchBuf, LPWSTR *ppszCurrent)
- {
- if (*pbFirst)
- {
- *pbFirst = FALSE;
- return 0; // no size necessary
- }
- // we're not the first property
- return AddQuerySep(pcchBuf, ppszCurrent, L'&');
- }
- // pick the longest date query so we can avoid checking the buffer size each time we
- // add something to the string
- #define LONGEST_DATE 50 //lstrlen(TEXT("{prop name=access} <= 2000/12/31 23:59:59{/prop}"))+2
- DWORD QueryDosDate(BOOL *pbFirst, DWORD *pcchBuf, LPWSTR *ppszCurrent, WORD wDate, WORD wDateType, BOOL bBefore)
- {
- FILETIME ftLocal, ftGMT;
- SYSTEMTIME st;
- LPWSTR pszCurrent = *ppszCurrent;
- DWORD cchNeeded = PrepareQueryParam(pbFirst, pcchBuf, &pszCurrent);
- if (pszCurrent && *pcchBuf > LONGEST_DATE)
- {
- DosDateTimeToFileTime(wDate, 0, &ftLocal);
- LocalFileTimeToFileTime(&ftLocal, &ftGMT);
- FileTimeToSystemTime(&ftGMT, &st);
- switch (wDateType & DFF_DATE_TYPEMASK)
- {
- case DFF_DATE_ACCESSED:
- StrCpyNW(pszCurrent, L"{prop name=access} ", *pcchBuf);
- break;
- case DFF_DATE_CREATED:
- StrCpyNW(pszCurrent, L"{prop name=create} ", *pcchBuf);
- break;
- case DFF_DATE_MODIFIED:
- StrCpyNW(pszCurrent, L"{prop name=write} ", *pcchBuf);
- break;
- }
- pszCurrent += lstrlenW(pszCurrent);
- if (bBefore)
- {
- *pszCurrent++ = L'<';
- // BUGBUG:: if you ask for a range like: 2/20/98 - 2/20/98 then we get no time at all
- // So for before, convert H:m:ss to 23:59:59...
- st.wHour = 23;
- st.wMinute = 59;
- st.wSecond = 59;
- }
- else
- *pszCurrent++ = L'>';
- *pszCurrent++ = L'=';
- wnsprintfW(pszCurrent, *pcchBuf, L" %d/%d/%d %d:%d:%d{/prop}", st.wYear, st.wMonth, st.wDay,
- st.wHour, st.wMinute, st.wSecond);
- pszCurrent += lstrlenW(pszCurrent);
- *ppszCurrent = pszCurrent;
- *pcchBuf -= LONGEST_DATE;
- }
- return cchNeeded + LONGEST_DATE;
- }
- DWORD CIQueryFilePatterns(BOOL *pbFirst, DWORD *pcchBuf, LPWSTR *ppszCurrent, LPWSTR pszFilePatterns)
- {
- WCHAR szNextPattern[MAX_PATH]; // overkill in size
- BOOL fFirst = TRUE;
- LPCWSTR pszNextPattern = pszFilePatterns;
- DWORD cchNeeded = PrepareQueryParam(pbFirst, pcchBuf, ppszCurrent);
- // Currently will have to long hand the query, may try to find shorter format once bugs
- // are fixed...
- //
- cchNeeded += AddToQuery(ppszCurrent, pcchBuf, L"(");
- while ((pszNextPattern = NextPathW(pszNextPattern, szNextPattern, ARRAYSIZE(szNextPattern))) != NULL)
- {
- if (!fFirst)
- {
- cchNeeded += AddToQuery(ppszCurrent, pcchBuf, L" | ");
- }
- fFirst = FALSE;
- cchNeeded += AddToQuery(ppszCurrent, pcchBuf, L"#filename ");
- cchNeeded += AddToQuery(ppszCurrent, pcchBuf, szNextPattern);
- }
- cchNeeded += AddToQuery(ppszCurrent, pcchBuf, L")");
- return cchNeeded;
- }
- DWORD CIQueryTextPatterns(BOOL *pbFirst, DWORD *pcchBuf, LPWSTR *ppszCurrent, LPWSTR pszText, BOOL bTextReg)
- {
- DWORD cchNeeded = PrepareQueryParam(pbFirst, pcchBuf, ppszCurrent);
- cchNeeded += AddToQuery(ppszCurrent, pcchBuf, L"{prop name=all}");
- cchNeeded += AddToQuery(ppszCurrent, pcchBuf, bTextReg? L"{regex}" : L"{phrase}");
- cchNeeded += AddToQuery(ppszCurrent, pcchBuf, pszText);
- cchNeeded += AddToQuery(ppszCurrent, pcchBuf, bTextReg? L"{/regex}{/prop}" : L"{/phrase}{/prop}");
- return cchNeeded;
- }
- #define MAX_DWORD_LEN 18
- DWORD CIQuerySize(BOOL *pbFirst, DWORD *pcchBuf, LPWSTR *ppszCurrent, DWORD dwSize, int iSizeType)
- {
- WCHAR szSize[MAX_DWORD_LEN+8]; // +8 for " {/prop}"
- DWORD cchNeeded = PrepareQueryParam(pbFirst, pcchBuf, ppszCurrent);
- cchNeeded += AddToQuery(ppszCurrent, pcchBuf, L"{prop name=size} ");
- cchNeeded += AddToQuery(ppszCurrent, pcchBuf, iSizeType == 1? L">" : L"<");
- wnsprintfW(szSize, *pcchBuf, L" %d{/prop}", dwSize);
- cchNeeded += AddToQuery(ppszCurrent, pcchBuf, szSize);
- return cchNeeded;
- }
- DWORD CIQueryIndex(BOOL *pbFirst, DWORD *pcchBuf, LPWSTR *ppszCurrent, LPWSTR pszText)
- {
- DWORD cchNeeded = PrepareQueryParam(pbFirst, pcchBuf, ppszCurrent);
- cchNeeded += AddToQuery(ppszCurrent, pcchBuf, pszText);
- return cchNeeded;
- }
- DWORD CIQueryShellSettings(BOOL *pbFirst, DWORD *pcchBuf, LPWSTR *ppszCurrent)
- {
- DWORD cchNeeded = 0;
- if (!ShowSuperHidden())
- {
- cchNeeded += PrepareQueryParam(pbFirst, pcchBuf, ppszCurrent);
- cchNeeded += AddToQuery(ppszCurrent, pcchBuf, L"NOT @attrib ^a 0x6 ");// don't show files w/ hidden and system bit on
- }
- {
- SHELLSTATE ss;
- SHGetSetSettings(&ss, SSF_SHOWALLOBJECTS, FALSE);
- if (!ss.fShowAllObjects)
- {
- cchNeeded += PrepareQueryParam(pbFirst, pcchBuf, ppszCurrent);
- cchNeeded += AddToQuery(ppszCurrent, pcchBuf, L"NOT @attrib ^a 0x2 "); // don't show files w/ hidden bit on
- }
- }
- return cchNeeded;
- }
- void CDFFilter_GenerateQueryHelper(CDFFilter *this, LPWSTR pwszQuery, DWORD *pcchQuery)
- {
- DWORD cchNeeded = 0, cchLeft = *pcchQuery;
- LPWSTR pszCurrent = pwszQuery;
- BOOL bFirst = TRUE; // first property
- USES_CONVERSION;
- if (this->pszFileSpec && this->pszFileSpec[0])
- {
- cchNeeded += CIQueryFilePatterns(&bFirst, &cchLeft, &pszCurrent, T2W(this->pszFileSpec));
- }
- // fFoldersOnly = TRUE implies szTypeFilePatterns = "."
- // we cannot pass "." to CI because they won't understand it as give me the folder types
- // we could check for @attrib ^a FILE_ATTRIBUTE_DIRECTORY (0x10) but ci doesn't index the folder names by default
- // so we normally won't get any results...
- if (!this->fFoldersOnly && this->szTypeFilePatterns[0])
- {
- cchNeeded += CIQueryFilePatterns(&bFirst, &cchLeft, &pszCurrent, T2W(this->szTypeFilePatterns));
- }
- // Date:
- if (this->dateModifiedBefore != 0)
- {
- cchNeeded += QueryDosDate(&bFirst, &cchLeft, &pszCurrent, this->dateModifiedBefore, this->wDateType, TRUE);
- }
- if (this->dateModifiedAfter != 0)
- {
- cchNeeded += QueryDosDate(&bFirst, &cchLeft, &pszCurrent, this->dateModifiedAfter, this->wDateType, FALSE);
- }
- // Size:
- if (this->iSizeType != 0)
- {
- cchNeeded += CIQuerySize(&bFirst, &cchLeft, &pszCurrent, this->dwSize, this->iSizeType);
- }
- // Indexed Search: raw query
- if (this->pszIndexedSearch && (this->pszIndexedSearch[0] != TEXT('')))
- {
- // HACK Alert if first Char is ! then we assume Raw and pass it through directly to CI...
- // Likewise if it starts with @ or # pass through, but remember the @...
- cchNeeded += CIQueryIndex(&bFirst, &cchLeft, &pszCurrent, T2W(this->pszIndexedSearch));
- }
- // Containing Text:
- if (this->szText[0] != TEXT(''))
- {
- // Try not to quote the strings unless we need to. This allows more flexability to do the
- // searching for example: "cat near dog" is different than: cat near dog
- cchNeeded += CIQueryTextPatterns(&bFirst, &cchLeft, &pszCurrent, T2W(this->szText), this->fTextReg);
- }
- cchNeeded += CIQueryShellSettings(&bFirst, &cchLeft, &pszCurrent);
- #ifdef WINNT
- // assume TCHAR = WCHAR bellow
- {
- HKEY hkey;
- UINT cPaths;
- LPWSTR *apwszPaths;
- TCHAR szPath[MAX_PATH];
- // don't search recycle bin folder. we add both nt4's recycled and nt5's recycler
- // for every drive we search.
- if (SUCCEEDED(DF_GetSearchPaths(this, NULL, &apwszPaths, &cPaths)))
- {
- int i;
- for (i = cPaths-1; i >= 0; i--)
- {
- if (PathStripToRootW(apwszPaths[i]))
- {
- int iBin=0, cBins=2;
- HRESULT hr;
- static LPCWSTR s_awszRecycleBins[] = { L"Recycled\*", L"Recycler\*", };
- #define NTFS_RBIN 1 // recycle bin on an ntfs drive is called recycler
- #define FAT_RBIN 0 // || recycled
- #define CCH_EXTRA lstrlen(TEXT(" & !#PATH "))
- hr = _IsNTFSDrive(PathGetDriveNumber(apwszPaths[i]));
- // in the failiure case we exclude both recycler and recycled
- if (SUCCEEDED(hr))
- {
- iBin = hr == S_OK? NTFS_RBIN : FAT_RBIN;
- cBins = 1;
- }
- for (; iBin < ARRAYSIZE(s_awszRecycleBins) && cBins > 0; iBin++, cBins--)
- {
- if (PathCombine(szPath, apwszPaths[i], s_awszRecycleBins[iBin]))
- {
- DWORD cchSize = lstrlen(szPath)+CCH_EXTRA;
- // don't bail out early if we are asked for size of query
- if (pwszQuery && cchSize > cchLeft)
- break;
- cchNeeded += AddToQuery(&pszCurrent, &cchLeft, L" & !#PATH ");
- cchNeeded += AddToQuery(&pszCurrent, &cchLeft, szPath);
- }
- }
- }
- }
- // we must exclude the special folders from the results or ci will find items that
- // we cannot get pidls for.
- if (RegOpenKeyEx(HKEY_CURRENT_USER, CI_SPECIAL_FOLDERS, 0, KEY_READ, &hkey) == ERROR_SUCCESS)
- {
- DWORD cValues = 0; // init to zero in case query info bellow fails
- TCHAR szName[10];
- RegQueryInfoKey(hkey, NULL, NULL, NULL, NULL, NULL, NULL, &cValues, NULL, NULL, NULL, NULL);
- if (cValues)
- {
- DWORD i;
- for (i=0; i < cValues; i++)
- {
- DWORD cb = ARRAYSIZE(szPath)*SIZEOF(TCHAR);;
- wsprintf(szName, TEXT("%d"), i);
- if (RegQueryValueEx(hkey, szName, NULL, NULL, (BYTE *)szPath, &cb) == ERROR_SUCCESS)
- {
- // no +1 since 0 is already in szQuery
- DWORD cchSize;
- UINT iDrive;
- BOOL bInclude = FALSE;
- for (iDrive=0; iDrive < cPaths; iDrive++)
- {
- // szPath has " as the first char so skip it..
- if (PathGetDriveNumber(apwszPaths[iDrive]) == PathGetDriveNumber(szPath+1))
- {
- bInclude = TRUE;
- break;
- }
- }
- if (!bInclude)
- continue;
- cchSize = lstrlen(szPath)+CCH_EXTRA;
- // don't bail out early if we are asked for size of query
- if (pwszQuery && cchSize > cchLeft)
- break;
- cchNeeded += AddToQuery(&pszCurrent, &cchLeft, L" & !#PATH ");
- cchNeeded += AddToQuery(&pszCurrent, &cchLeft, szPath);
- }
- }
- }
- RegCloseKey(hkey);
- }
- // clean up
- for (i = cPaths-1; i >= 0; i--)
- {
- LocalFree((HLOCAL)apwszPaths[i]);
- }
- LocalFree((HLOCAL)apwszPaths);
- }
- }
- #endif
- // If no constraints are set, CI errors out, so instead give it a dummy one of filename
- // *.*
- if (pwszQuery && pszCurrent == pwszQuery)
- CIQueryFilePatterns(&bFirst, &cchLeft, &pszCurrent, L"*.*");
- if (pszCurrent)
- {
- // Make sure we terminate the string at the end...
- *pszCurrent = TEXT('');
- }
- if (!pwszQuery)
- {
- *pcchQuery = cchNeeded;
- }
- else
- {
- ASSERT(*pcchQuery > cchNeeded);
- }
- }
- //==========================================================================
- // Create a query command string out of the search criteria
- //==========================================================================
- STDMETHODIMP CDFFilter_GenerateQueryRestrictions(IDocFindFileFilter *pdfff, LPWSTR *ppwszQuery,
- DWORD *pdwGQR_Flags)
- {
- CDFFilter *this = IToClass(CDFFilter, dfff, pdfff);
- // we should be able to make use of ci no matter what (exceptions at the end of the function)
- DWORD dwGQR_Flags = GQR_MAKES_USE_OF_CI;
- HRESULT hres = S_OK;
- // Named: or Of type:
- // Match file specificaitions.
- if (ppwszQuery)
- {
- DWORD cchNeeded = 0;
- CDFFilter_GenerateQueryHelper(this, NULL, &cchNeeded);
- cchNeeded++; // for
- *ppwszQuery = (LPWSTR)LocalAlloc(LMEM_FIXED, cchNeeded * sizeof(WCHAR));
- if (! *ppwszQuery)
- return E_OUTOFMEMORY;
- CDFFilter_GenerateQueryHelper(this, *ppwszQuery, &cchNeeded);
- }
- if (this->pszIndexedSearch && (this->pszIndexedSearch[0] != TEXT('')))
- dwGQR_Flags |= GQR_REQUIRES_CI;
- // ci is not case sensitive, so if user wanted case sensitive search we cannot use ci
- // also ci doesn't index folder names by default so to be safe we just default to our
- // disk traversal algorithm...
- if (this->fTextCaseSen || this->fFoldersOnly)
- {
- if (dwGQR_Flags & GQR_REQUIRES_CI && this->fTextCaseSen)
- hres = MAKE_HRESULT(3, FACILITY_SEARCHCOMMAND, SCEE_CASESENINDEX);
- else if (dwGQR_Flags & GQR_MAKES_USE_OF_CI)
- dwGQR_Flags &= ~GQR_MAKES_USE_OF_CI;
- }
- *pdwGQR_Flags = dwGQR_Flags; // return calculated Flags...
- return hres;
- }
- STDMETHODIMP CDFFilter_ReleaseQuery(IDocFindFileFilter *pdfff)
- {
- #ifdef WINNT
- CDFFilter *this = IToClass(CDFFilter, dfff, pdfff);
- if (this->pdfenumAsync)
- {
- this->pdfenumAsync->lpVtbl->Release(this->pdfenumAsync);
- this->pdfenumAsync = NULL;
- }
- #endif
- return S_OK;
- }
- STDMETHODIMP CDFFilter_GetQueryLanguageDialect(IDocFindFileFilter *pdfff, ULONG* pulDialect)
- {
- CDFFilter *this = IToClass(CDFFilter, dfff, pdfff);
- if(NULL == this || NULL == pulDialect)
- return E_POINTER;
- *pulDialect = this->ulQueryDialect;
- return S_OK;
- }
- STDMETHODIMP CDFFilter_GetWarningFlags(IDocFindFileFilter *pdfff, DWORD* pdwWarningFlags)
- {
- CDFFilter *this = IToClass(CDFFilter, dfff, pdfff);
- if(NULL == this || NULL == pdwWarningFlags)
- return E_POINTER;
- *pdwWarningFlags = this->dwWarningFlags;
- return S_OK;
- }
- ////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////
- // Now starting the code for the name and location page
- ////////////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////////////
- //=========================================================================
- void DocFind_SizeControl(HWND hwndDlg, int id, int cx, BOOL fCombo)
- {
- RECT rc;
- RECT rcList;
- HWND hwndCtl;
- GetWindowRect(hwndCtl = GetDlgItem(hwndDlg, id), &rc);
- MapWindowPoints(HWND_DESKTOP, hwndDlg, (POINT *)&rc, 2);
- if (fCombo)
- {
- // These guys are comboboxes so work with them...
- SendMessage(hwndCtl, CB_GETDROPPEDCONTROLRECT, 0,
- (LPARAM)(RECT *)&rcList);
- rc.bottom += (rcList.bottom - rcList.top);
- }
- SetWindowPos(hwndCtl, NULL, 0, 0, cx - rc.left,
- rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
- }
- //==========================================================================
- //
- // Process the WM_SIZE of the details page
- //
- void DocFind_DFNameLocOnSize(HWND hwndDlg, UINT state, int cx, int cy)
- {
- RECT rc;
- int cxMargin;
- HWND hwndCtl;
- if (state == SIZE_MINIMIZED)
- return; // don't bother when we are minimized...
- // Get the location of first static to calculate margin
- GetWindowRect(GetDlgItem(hwndDlg, IDD_STATIC), &rc);
- MapWindowPoints(HWND_DESKTOP, hwndDlg, (POINT *)&rc, 2);
- cxMargin = rc.left;
- cx -= cxMargin;
- DocFind_SizeControl(hwndDlg, IDD_FILESPEC, cx, TRUE);
- DocFind_SizeControl(hwndDlg, IDD_CONTAINS, cx, FALSE);
- // Now move the browse button
- GetWindowRect(hwndCtl = GetDlgItem(hwndDlg, IDD_BROWSE), &rc);
- MapWindowPoints(HWND_DESKTOP, hwndDlg, (POINT *)&rc, 2);
- SetWindowPos(hwndCtl, NULL, cx - (rc.right - rc.left), rc.top, 0, 0,
- SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
- // And size the path field
- #if 1
- DocFind_SizeControl(hwndDlg, IDD_PATH, cx, TRUE);
- #else
- DocFind_SizeControl(hwndDlg, IDD_PATH, cx - cxMargin - (rc.right - rc.left), TRUE);
- #endif
- }
- //==========================================================================
- // Add a string to our name location list...
- //==========================================================================
- int DFNameLocAddString(LPDOCFINDPROPSHEETPAGE pdfpsp, LPTSTR pszPath)
- {
- LPTSTR pszT;
- LPITEMIDLIST pidl;
- int iSel;
- LPITEMIDLIST pidlT;
- HWND hwndCtl = GetDlgItem(pdfpsp->hwndDlg, IDD_PATH);
- TCHAR szPath[MAX_PATH];
- int iNew = CB_ERR;
- // Don't muck with original as it might have been passed to us by someone who
- // allocated an exact size...
- lstrcpy(szPath, pszPath);
- // If we only have one path
- pszT = szPath + StrCSpn(szPath, TEXT(",;"));
- if (*pszT == TEXT(''))
- {
- // Try to parse the display name into a Pidl
- PathQualify(szPath);
- pidl = ILCreateFromPath(szPath);
- if (!pidl)
- {
- TCHAR szDisplayName[MAX_PATH];
- int cch;
- // See if the beginning of the string matches the
- // start of an item in the list. If so we should
- // Try to see if we can convert it to a valid
- // pidl/string...
- for (iSel=(int)SendMessage(hwndCtl,
- CB_GETCOUNT, 0, 0); iSel >= 1; iSel--)
- {
- SendMessage(hwndCtl, CB_GETLBTEXT,
- (WPARAM)iSel, (LPARAM)szDisplayName);
- cch = lstrlen(szDisplayName);
- if ((CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
- szDisplayName, cch, szPath, cch) == 2) &&
- (szPath[cch] == TEXT('\')))
- {
- pidlT = (LPITEMIDLIST)SendMessage(hwndCtl,
- CB_GETITEMDATA, (WPARAM)iSel, 0);
- // Don't blow up if we get a failure here
- if (pidlT != (LPITEMIDLIST)-1)
- {
- SHGetPathFromIDList(pidlT, szDisplayName);
- PathAppend(szDisplayName, CharNext(szPath+cch));
- pidl = ILCreateFromPath(szDisplayName);
- if (pidl)
- {
- lstrcpy(szPath, szDisplayName);
- break;
- }
- }
- #ifdef DEBUG
- else
- {
- DebugMsg(DM_TRACE, TEXT("DFNameLocAddString - CBItem ptr = -1"));
- }
- #endif
- }
- }
- }
- }
- else
- {
- // Multiple things let it run by itself...
- pidl = NULL; // dont have a pidl to begin with...
- }
- if (pidl)
- {
- IShellFolder *psfParent;
- HRESULT hres = SHBindToIDListParent(pidl, &IID_IShellFolder, (void **)&psfParent, NULL);
- if (SUCCEEDED(hres))
- {
- // DocFind_LocCBAddPidl fist ILCombine()s parent and child, since
- // we didn't separate the parent from the child, pass in the full
- // pidl and NULL child -- they'll get ILCombine()d appropriately.
- iNew = DocFind_LocCBAddPidl(hwndCtl, psfParent, pidl, NULL, NULL, TRUE, 0);
- psfParent->lpVtbl->Release(psfParent);
- }
- ILFree(pidl);
- }
- else
- {
- // Add the whole string as an item...
- iNew = DocFind_LocCBAddItem(hwndCtl, NULL, -1, 0, -1, szPath);
- }
- if (iNew != CB_ERR)
- SendMessage(hwndCtl, CB_SETCURSEL, iNew, 0);
- return iNew;
- }
- /*----------------------------------------------------------------------------
- / build_drive_string implementation
- / ------------------
- / Purpose:
- / Convert from a bit stream ( 1 bit per drive ) to a comma seperated
- / list of drives.
- /
- / Notes:
- /
- / In:
- / uDrives = 1 bit per drive (bit 0 == A:, bit 25 == Z:) bit == 1 indicates drive
- / to be listed.
- / pszBiffer -> buffer to place text into
- / iBufferSize = size of the buffer.
- / pSepStr -> seperating string used to seperate drive names
- /
- / Out:
- / -
- /----------------------------------------------------------------------------*/
- static void build_drive_string( UINT uDrives, LPTSTR pBuffer, int iSize, LPTSTR pSepStr )
- {
- TCHAR szDrive[] = TEXT("A:");
- int iMaxStrLen = lstrlen( szDrive ) + lstrlen( pSepStr );
- ASSERT( pBuffer != NULL ); // sanitise the parameters
- ASSERT( iSize > 0 );
- *pBuffer = L'';
- while ( uDrives && ( iSize > iMaxStrLen ) )
- {
- if ( uDrives & 1 )
- {
- lstrcat( pBuffer, szDrive );
- if ( uDrives & ~1 )
- lstrcat( pBuffer, pSepStr );
- iSize -= iMaxStrLen;
- }
- szDrive[0]++;
- uDrives >>= 1;
- }
- }
- //=============================================================================
- // Helper function to build the string of
- // "<Desktop Directory>;<My Documents Directory>"
- //=============================================================================
- void build_documentfolders_string(LPDOCFINDPROPSHEETPAGE pdfpsp, LPTSTR pszPath, BOOL bDesktopOnly)
- {
- LPITEMIDLIST pidlDeskDir;
- TCHAR szTemp[MAX_PATH];
- *pszPath = TEXT('');
- // add the all user desktop directory...
- if (SHGetSpecialFolderLocation(pdfpsp->hwndDlg, CSIDL_COMMON_DESKTOPDIRECTORY, &pidlDeskDir) == S_OK)
- {
- SHGetPathFromIDList(pidlDeskDir, pszPath);
- ILFree(pidlDeskDir);
- pidlDeskDir = NULL;
- }
- // Add the desktop directory...
- if (SHGetSpecialFolderLocation(pdfpsp->hwndDlg, CSIDL_DESKTOPDIRECTORY, &pidlDeskDir) == S_OK)
- {
- SHGetPathFromIDList(pidlDeskDir, szTemp);
- if (szTemp[0] && lstrlen(szTemp)+lstrlen(pszPath) + 1 < ARRAYSIZE(szTemp))
- {
- lstrcat(pszPath,TEXT(";"));
- lstrcat(pszPath,szTemp);
- }
- }
- if (!bDesktopOnly)
- {
- LPITEMIDLIST pidlMyDocuments;
- // Check to see if the "My Documents" directory should be added or
- // whether it will implicitly be picked up because of disk hierarchy
- // and search options...
- if (SHGetSpecialFolderLocation(pdfpsp->hwndDlg, CSIDL_PERSONAL, &pidlMyDocuments) == S_OK)
- {
- BOOL fParent = ILIsParent(pidlDeskDir, pidlMyDocuments, FALSE);
- if (!fParent || (fParent && !pdfpsp->pdff->fTopLevelOnly))
- {
- SHGetPathFromIDList(pidlMyDocuments, szTemp);
- if (szTemp[0] && lstrlen(szTemp)+lstrlen(pszPath) + 1 < ARRAYSIZE(szTemp))
- {
- lstrcat(pszPath,TEXT(";"));
- lstrcat(pszPath,szTemp);
- }
- }
- }
- if (pidlMyDocuments)
- ILFree(pidlMyDocuments);
- }
- if (pidlDeskDir)
- ILFree(pidlDeskDir);
- }
- STDAPI_(BOOL) NextIDL(IEnumIDList *penum, LPITEMIDLIST *ppidl)
- {
- UINT celt;
- *ppidl = NULL;
- return penum->lpVtbl->Next(penum, 1, ppidl, &celt) == NOERROR && celt == 1;
- }
- //==========================================================================
- // Initialize the Name and loacation page
- //==========================================================================
- DWORD CALLBACK DocFind_RealDFNameLocInit(LPVOID lpThreadParameters)
- {
- LPDOCFINDPROPSHEETPAGE pdfpsp = lpThreadParameters;
- CDFFilter *pdff = pdfpsp->pdff;
- // We process the message after the WM_CREATE or WM_INITDLG as to
- // allow the dialog to come up quicker...
- TCHAR szPath[MAX_PATH];
- LPITEMIDLIST pidlWindows;
- IShellFolder * psf;
- HWND hwndCtl;
- HRESULT hres;
- LPITEMIDLIST pidlAbs, pidlTemp, pidlStart = pdff->pidlStart;
- int ipidlStart = -1; // If pidl passed in and in our list already...
- int iLocalDrives = -1;
- HANDLE hEnum;
- UINT uFixedDrives = 0; // 1 bit per 'fixed' drive, start at 0.
- int iMyComputer;
- int iDrive;
- IShellFolder *psfDesktop;
- DOCFINDSAVELOOKIN dfsli = {DFSLI_VER, DFSLI_TYPE_DOCUMENTFOLDERS};
- CoInitialize(0);
- SHGetDesktopFolder(&psfDesktop);
- hwndCtl = GetDlgItem(pdfpsp->hwndDlg, IDD_PATH);
- SendMessage(hwndCtl, CBEM_SETEXSTYLE, CBES_EX_PATHWORDBREAKPROC, 0L);
- // If we do not have a pidl Start, default to last place we searched.
- if (!pidlStart)
- {
- // May move this to helper function...
- // Stream format:
- // DWORD: Version=0
- // DWORD: Type: 0 - Pidl, 1 = Local Drives, 2 = Document Folder
- // Pidl if Type = 0
- IStream *pstm = OpenRegStream(HKEY_CURRENT_USER, REGSTR_PATH_EXPLORER, TEXT("DocFindLastLookIn"), STGM_READ);
- if (pstm)
- {
- int cb;