mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
393 lines
14 KiB
393 lines
14 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1995
|
|
//
|
|
// File: synquery.cpp
|
|
//
|
|
// Contents: COFSFolder::SynchronousQuery - Runs a synchronous filesystem
|
|
// query
|
|
//
|
|
// History: 6-29-95 DavePl,JonBe Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include "precomp.h"
|
|
|
|
//
|
|
// The maximum number of rows fetched at once through pRowset->GetData()
|
|
//
|
|
|
|
#define MAX_FETCHED_AT_ONCE 100
|
|
|
|
GUID guidSystem = PSGUID_STORAGE;
|
|
|
|
//
|
|
// Buffer into which we read data from the rowsets
|
|
//
|
|
|
|
typedef WCHAR NAMEBUF[MAX_PATH]; // Longest allowable NT filesystem path
|
|
typedef WCHAR SNAMEBUF[13]; // 8+1+3+1 => 8.3 name plus NULL
|
|
|
|
struct SRowBuf
|
|
{
|
|
FILETIME ftLastWriteTime;
|
|
LONGLONG llFileSize;
|
|
DWORD dwFileAttributes;
|
|
NAMEBUF awchName;
|
|
SNAMEBUF awchShortName;
|
|
};
|
|
|
|
DBBINDING aOutColumns[] =
|
|
{
|
|
{ DBCOLUMNPART_VALUE, 0, 0, VT_FILETIME, NULL, NULL, offsetof(SRowBuf, ftLastWriteTime), SIZEOF(FILETIME), {0,0,0}, 0, 0 },
|
|
{ DBCOLUMNPART_VALUE, 0, 0, DBTYPE_I8, NULL, NULL, offsetof(SRowBuf, llFileSize), SIZEOF(LONGLONG), {0,0,0}, 0, 0 },
|
|
{ DBCOLUMNPART_VALUE, 0, 0, DBTYPE_I4, NULL, NULL, offsetof(SRowBuf, dwFileAttributes), SIZEOF(DWORD), {0,0,0}, 0, 0 },
|
|
{ DBCOLUMNPART_VALUE, 0, 0, DBTYPE_WSTR, NULL, NULL, offsetof(SRowBuf, awchName), MAX_PATH * SIZEOF(WCHAR), {0,0,0}, 0, 0 },
|
|
{ DBCOLUMNPART_VALUE, 0, 0, DBTYPE_WSTR, NULL, NULL, offsetof(SRowBuf, awchShortName), 13 * SIZEOF(WCHAR), {0,0,0}, 0, 0 }
|
|
};
|
|
const int cOutColumns = ARRAYSIZE(aOutColumns);
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Member: SynchronousQuery
|
|
//
|
|
// Synopsis: Given an enumerator and a path, runs a query to locate
|
|
// all filesystem objects at that path and adds them all
|
|
// (as pidls) to the enumerator
|
|
//
|
|
// Notes:
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
HRESULT COFSFolder::SynchronousQuery(TCHAR* szFolder,
|
|
DWORD grfFlags,
|
|
CEnumOLEDB* pEnumOLEDB)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
|
|
CPropertyRestriction * prst = NULL;
|
|
IOldQuery * pQuery = NULL;
|
|
IRowset * pRowset = NULL;
|
|
IAccessor * pIAccessor = NULL;
|
|
IColumnsInfo * pIColumnsInfo = NULL;
|
|
HACCESSOR hAccessor = NULL;
|
|
|
|
ULONG cHiddenFiles = 0; // Count of hidden files. Used to update
|
|
// folder's count at end of enumeration
|
|
DWORD dwSize = 0; // Total size of files enumerated. Used to
|
|
// update folder's size at end of enumeration
|
|
|
|
TRY
|
|
{
|
|
// BUGBUG Scope
|
|
|
|
const DBID dbcolLastWriteTime = {PSGUID_STORAGE, DBKIND_GUID_PROPID, (LPWSTR)PID_STG_WRITETIME};
|
|
const DBID dbcolSize = {PSGUID_STORAGE, DBKIND_GUID_PROPID, (LPWSTR)PID_STG_SIZE};
|
|
const DBID dbcolAttributes = {PSGUID_STORAGE, DBKIND_GUID_PROPID, (LPWSTR)PID_STG_ATTRIBUTES};
|
|
const DBID dbcolName = {PSGUID_STORAGE, DBKIND_GUID_PROPID, (LPWSTR)PID_STG_NAME};
|
|
const DBID dbcolShortName = {PSGUID_STORAGE, DBKIND_GUID_PROPID, (LPWSTR)PID_STG_SHORTNAME};
|
|
|
|
CFullPropSpec psWriteTime (guidSystem, PID_STG_WRITETIME);
|
|
CFullPropSpec psSize (guidSystem, PID_STG_SIZE);
|
|
CFullPropSpec psAttributes(guidSystem, PID_STG_ATTRIBUTES);
|
|
CFullPropSpec psName (guidSystem, PID_STG_NAME);
|
|
CFullPropSpec psShortName (guidSystem, PID_STG_SHORTNAME);
|
|
|
|
CRestriction *prstQuery = 0;
|
|
|
|
pQuery = EvalQuery4(szFolder, 0);
|
|
if (NULL == pQuery)
|
|
{
|
|
hr = E_FAIL;
|
|
dprintf(TEXT("COFSFolder::SynchronousQuery - EvalQuery4 failed"));
|
|
LEAVE;
|
|
}
|
|
|
|
//
|
|
// Columns returned by the query
|
|
//
|
|
CColumns cols(cOutColumns);
|
|
VERIFY( cols.Add(psWriteTime, 0) );
|
|
VERIFY( cols.Add(psSize, 1) );
|
|
VERIFY( cols.Add(psAttributes, 2) );
|
|
VERIFY( cols.Add(psName, 3) );
|
|
VERIFY( cols.Add(psShortName, 4) );
|
|
|
|
//
|
|
// Make a restriction
|
|
//
|
|
prst = new CPropertyRestriction();
|
|
if (NULL == prst)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
LEAVE;
|
|
}
|
|
|
|
prstQuery = prst;
|
|
prst->SetRelation( PRRE );
|
|
prst->SetProperty( psName );
|
|
prst->SetValue ( L"*" );
|
|
|
|
hr = pQuery->ExecuteQuery(QUERY_SHALLOW, // Depth
|
|
prstQuery->CastToStruct(), // Restriction
|
|
cols.CastToStruct(), // Output
|
|
0, // Sort
|
|
eSequentialCursor, // Flags
|
|
IID_IRowset, // IID for i/f to return
|
|
(IUnknown **)&pRowset ); // Return interface
|
|
LEAVE_IF( FAILED(hr) );
|
|
|
|
// map the column ids from guid form to column numbers needed to
|
|
// create the accessor
|
|
|
|
DBID aDbCols[cOutColumns];
|
|
aDbCols[0] = dbcolLastWriteTime;
|
|
aDbCols[1] = dbcolSize;
|
|
aDbCols[2] = dbcolAttributes;
|
|
aDbCols[3] = dbcolName;
|
|
aDbCols[4] = dbcolShortName;
|
|
|
|
hr = pRowset->QueryInterface(IID_IColumnsInfo, (void**)&pIColumnsInfo);
|
|
LEAVE_IF( FAILED(hr) );
|
|
|
|
hr = pRowset->QueryInterface(IID_IAccessor, (void**)&pIAccessor);
|
|
LEAVE_IF( FAILED(hr) );
|
|
|
|
LONG aColIds[cOutColumns];
|
|
hr = pIColumnsInfo->MapColumnIDs(cOutColumns,aDbCols,aColIds);
|
|
LEAVE_IF( FAILED(hr) );
|
|
|
|
for (ULONG c = 0; c < cOutColumns; c++)
|
|
{
|
|
aOutColumns[c].iColumn = aColIds[c];
|
|
}
|
|
|
|
hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,
|
|
cOutColumns,
|
|
aOutColumns,
|
|
0,
|
|
0,
|
|
&hAccessor);
|
|
LEAVE_IF( FAILED(hr) );
|
|
|
|
// Now go through the whole rowset and put those items that match our
|
|
// criteria (as determined by grfFlags) in the enumerator ptr array
|
|
|
|
ULONG cFetched = 0;
|
|
|
|
while ((0 != cFetched) ||
|
|
(DB_S_ENDOFROWSET != hr))
|
|
{
|
|
ULONG cThisTime = MAX_FETCHED_AT_ONCE;
|
|
HROW aHRows[MAX_FETCHED_AT_ONCE],*pHRows = aHRows;
|
|
|
|
hr = pRowset->GetNextRows(DB_INVALID_HCHAPTER, // no chapter
|
|
0, // no offset
|
|
cThisTime, // # requested
|
|
&cFetched, // # fetched
|
|
&pHRows); // put them here
|
|
|
|
if (0 != cFetched)
|
|
{
|
|
for (ULONG x = 0; x < cFetched; x++)
|
|
{
|
|
SRowBuf Row;
|
|
if (FAILED(hr = pRowset->GetData(aHRows[x],hAccessor,&Row)))
|
|
{
|
|
ASSERT( 0 && "pRowset->GetData failed" );
|
|
continue;
|
|
}
|
|
|
|
BOOL fFound = FALSE;
|
|
WIN32_FIND_DATA finddata;
|
|
|
|
//
|
|
// Fill out the WIN32_FIND_DATA structure from the data we got back in the row buffer
|
|
//
|
|
|
|
ZeroMemory(&finddata, sizeof(finddata));
|
|
|
|
finddata.dwFileAttributes = Row.dwFileAttributes;
|
|
|
|
// Note that ftLastAccess and ftCreate are not used by fstreex.c
|
|
|
|
finddata.ftLastWriteTime.dwLowDateTime = Row.ftLastWriteTime.dwLowDateTime;
|
|
finddata.ftLastWriteTime.dwHighDateTime = Row.ftLastWriteTime.dwHighDateTime;
|
|
|
|
finddata.nFileSizeHigh = (ULONG) (Row.llFileSize >> 32);
|
|
finddata.nFileSizeLow = (ULONG) (Row.llFileSize & 0xFFFFFFFF);
|
|
|
|
finddata.dwReserved0 = 0;
|
|
finddata.dwReserved1 = 0;
|
|
|
|
lstrcpynW(finddata.cFileName, Row.awchName, MAX_PATH);
|
|
lstrcpynW(finddata.cAlternateFileName, Row.awchShortName, ARRAYSIZE(Row.awchShortName));
|
|
|
|
//
|
|
// BUGBUG Overflow problems here
|
|
//
|
|
|
|
dwSize += finddata.nFileSizeLow;
|
|
|
|
//
|
|
// Object is a folder, but we aren't looking for folders, so skip it
|
|
//
|
|
|
|
if (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
if (0 == (grfFlags & SHCONTF_FOLDERS))
|
|
{
|
|
cHiddenFiles++;
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Object is a non-folder, but we are not enumerating for
|
|
// non-folders
|
|
//
|
|
|
|
if (0 == (grfFlags & SHCONTF_NONFOLDERS))
|
|
{
|
|
cHiddenFiles++;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (0 == (grfFlags & SHCONTF_INCLUDEHIDDEN))
|
|
{
|
|
//
|
|
// If object is hidden, but we aren't looking for hidden
|
|
// objects, skip it
|
|
//
|
|
|
|
if (finddata.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
|
|
{
|
|
cHiddenFiles++;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// If we are looking in the recent docs dir, but we can't
|
|
// find this item in the recent docs MRU, skip it
|
|
//
|
|
|
|
if (grfFlags & SHCONTF_RECENTDOCSDIR)
|
|
{
|
|
if (FALSE == FindLinkInRecentDocsMRU(finddata.cFileName))
|
|
{
|
|
cHiddenFiles++;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If this is a non-folder object, and is one of the types
|
|
// (based on its extension) that we are hiding, skip it
|
|
//
|
|
|
|
if (0 == (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
&& _SHFindExcludeExt(finddata.cFileName) >= 0)
|
|
{
|
|
cHiddenFiles++;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Object matches all of our criteria for one that should be
|
|
// displayed in this view, so we can stop looking
|
|
//
|
|
|
|
fFound = TRUE;
|
|
|
|
//
|
|
// We are done looking. If we found an object to be displayed, create
|
|
// an IDList and hand it back. Otherwise, we have looked at all of
|
|
// the objects in this folder, and we are done. We take that
|
|
// opportunity to update the hidden count and size summation in the
|
|
// folder itself.
|
|
//
|
|
|
|
if (fFound)
|
|
{
|
|
LPIDFOLDER pidf = CFSFolder_FillIDFolder(&finddata,
|
|
szFolder,
|
|
0L);
|
|
|
|
if (pidf)
|
|
{
|
|
hr = pEnumOLEDB->AddElement((LPITEMIDLIST)pidf);
|
|
if (FAILED(hr))
|
|
{
|
|
dprintf(TEXT("COFSFolder::SynchronousQuery -- pEnumOLEDB->AddElement (%lx)\n"), hr);
|
|
VERIFY(SUCCEEDED( pRowset->ReleaseRows(cFetched, aHRows, 0, 0) ));
|
|
LEAVE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dprintf(TEXT("COFSFolder::SynchronousQuery -- CFSFolder_FillIDFolder failed\n"));
|
|
VERIFY(SUCCEEDED( pRowset->ReleaseRows(cFetched, aHRows, 0, 0) ));
|
|
LEAVE;
|
|
}
|
|
}
|
|
}
|
|
|
|
VERIFY(SUCCEEDED( pRowset->ReleaseRows(cFetched, aHRows, 0, 0) ));
|
|
}
|
|
}
|
|
}
|
|
|
|
FINALLY
|
|
{
|
|
//
|
|
// Normal cleanup
|
|
//
|
|
|
|
if (pIColumnsInfo)
|
|
{
|
|
pIColumnsInfo->Release();
|
|
}
|
|
if (pIAccessor)
|
|
{
|
|
if (hAccessor)
|
|
{
|
|
VERIFY(SUCCEEDED( pIAccessor->ReleaseAccessor(hAccessor) ));
|
|
}
|
|
pIAccessor->Release();
|
|
}
|
|
if (pRowset)
|
|
{
|
|
pRowset->Release();
|
|
}
|
|
if (grfFlags & SHCONTF_RECENTDOCSDIR)
|
|
{
|
|
CloseRecentDocMRU();
|
|
}
|
|
if (pQuery)
|
|
{
|
|
pQuery->Release();
|
|
}
|
|
delete prst;
|
|
|
|
//
|
|
// Only update folders hidden count and size if the enum was successful
|
|
//
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_cHiddenFiles = cHiddenFiles;
|
|
m_dwSize = dwSize;
|
|
}
|
|
else
|
|
{
|
|
dprintf(TEXT("OLEDBSHL: Abnormal Exit from COFSFolder::SynchronousQuery, hr = %lx\n"), hr);
|
|
}
|
|
return hr;
|
|
}
|
|
}
|
|
|