WindowsXP-SP1/base/fs/hsm/cli/clifile.cpp
2020-09-30 16:53:49 +02:00

191 lines
7.1 KiB
C++

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
clifile.cpp
Abstract:
Implements CLI FILE sub-interface
Author:
Ran Kalach [rankala] 3-March-2000
Revision History:
--*/
#include "stdafx.h"
#include "rpdata.h"
HRESULT
FileRecall(
IN LPWSTR *FileSpecs,
IN DWORD NumberOfFileSpecs
)
/*++
Routine Description:
Recalls all the files that match the given specification (path + wildcards)
Arguments:
FileSpecs -
NumberOfFileSpecs -
Return Value:
S_OK - If all the files are recalled successfully.
--*/
{
HRESULT hr = S_OK;
HANDLE hSearchHandle = INVALID_HANDLE_VALUE;
HANDLE hFile = INVALID_HANDLE_VALUE;
BOOL bExistingFiles = FALSE;
WsbTraceIn(OLESTR("FileRecall"), OLESTR(""));
try {
// Verify that input parameters are valid
if (0 == NumberOfFileSpecs) {
WsbTraceAndPrint(CLI_MESSAGE_NO_FILES, NULL);
WsbThrow(E_INVALIDARG);
}
// Enumerate over the file specifications
for (ULONG i = 0; i < NumberOfFileSpecs; i++) {
CWsbStringPtr nameSpace;
WCHAR* pathEnd;
WIN32_FIND_DATA findData;
BOOL bMoreFiles = TRUE;
WsbAssert(NULL != FileSpecs[i], E_INVALIDARG);
// Enumerate over files in each specification
nameSpace = FileSpecs[i];
WsbAffirmHr(nameSpace.Prepend(OLESTR("\\\\?\\")));
pathEnd = wcsrchr(nameSpace, L'\\');
WsbAssert(pathEnd != NULL, E_INVALIDARG);
hSearchHandle = FindFirstFile((WCHAR *)nameSpace, &findData);
if (INVALID_HANDLE_VALUE != hSearchHandle) {
// Found at least one file that matches an input file specification
bExistingFiles = TRUE;
}
while ((INVALID_HANDLE_VALUE != hSearchHandle) && bMoreFiles) {
if ( findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ) {
// File may be managed by HSM:
CWsbStringPtr fileName;
BYTE ReparseBuffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
PREPARSE_DATA_BUFFER pReparseBuffer;
DWORD outSize;
BOOL bRecall = FALSE;
// Create full name based on the path and the find-data
*(pathEnd+1) = L'\0';
fileName = nameSpace;
*(pathEnd+1) = L'\\';
WsbAffirmHr(fileName.Append(findData.cFileName));
// Open the file
hFile = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_FLAG_OPEN_NO_RECALL | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
if (INVALID_HANDLE_VALUE == hFile) {
// Report on an error
DWORD dwErr = GetLastError();
hr = HRESULT_FROM_WIN32(dwErr);
WsbTraceAndPrint(CLI_MESSAGE_ERROR_FILE_RECALL, (WCHAR *)fileName, WsbHrAsString(hr), NULL);
WsbThrow(hr);
}
// Get reparse data and check if the file is offline (if not, just ignore it and continue)
if (0 == DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, NULL, 0,
ReparseBuffer, sizeof(ReparseBuffer), &outSize, NULL)) {
// Report on an error
DWORD dwErr = GetLastError();
hr = HRESULT_FROM_WIN32(dwErr);
WsbTraceAndPrint(CLI_MESSAGE_ERROR_FILE_RECALL, (WCHAR *)fileName, WsbHrAsString(hr), NULL);
WsbThrow(hr);
}
pReparseBuffer = (PREPARSE_DATA_BUFFER)ReparseBuffer;
if (IO_REPARSE_TAG_HSM == pReparseBuffer->ReparseTag) {
PRP_DATA pHsmData = (PRP_DATA) &pReparseBuffer->GenericReparseBuffer.DataBuffer[0];
if( RP_FILE_IS_TRUNCATED( pHsmData->data.bitFlags ) ) {
// File is managed by HSM and truncated
bRecall = TRUE;
}
}
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
// Recall the file if required
if (bRecall) {
// Open the file again for recall
hFile = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (INVALID_HANDLE_VALUE == hFile) {
// Report on an error
DWORD dwErr = GetLastError();
hr = HRESULT_FROM_WIN32(dwErr);
WsbTraceAndPrint(CLI_MESSAGE_ERROR_FILE_RECALL, (WCHAR *)fileName, WsbHrAsString(hr), NULL);
WsbThrow(hr);
}
// Recall the file
if (0 == DeviceIoControl(hFile, FSCTL_RECALL_FILE, NULL, 0,
NULL, 0, &outSize, NULL)) {
// Report on an error
// TEMPORARY: Should we abort or continue recalling other files?
DWORD dwErr = GetLastError();
hr = HRESULT_FROM_WIN32(dwErr);
WsbTraceAndPrint(CLI_MESSAGE_ERROR_FILE_RECALL, (WCHAR *)fileName, WsbHrAsString(hr), NULL);
WsbThrow(hr);
}
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
}
}
// Get next file
bMoreFiles = FindNextFile(hSearchHandle, &findData);
}
// Prepare for next file specification
nameSpace.Free();
if (INVALID_HANDLE_VALUE != hSearchHandle) {
FindClose(hSearchHandle);
hSearchHandle = INVALID_HANDLE_VALUE;
}
}
// Print warning message if no valid file was specified
if (FALSE == bExistingFiles) {
WsbTraceAndPrint(CLI_MESSAGE_NO_FILES, NULL);
}
} WsbCatch(hr);
// Ensure cleanup in case of an error
if (INVALID_HANDLE_VALUE != hSearchHandle) {
FindClose(hSearchHandle);
hSearchHandle = INVALID_HANDLE_VALUE;
}
if (INVALID_HANDLE_VALUE != hFile) {
CloseHandle(hFile);
hFile = INVALID_HANDLE_VALUE;
}
WsbTraceOut(OLESTR("FileRecall"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
return hr;
}