|
|
/*++
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; }
|