Source code of Windows XP (NT5)
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.

190 lines
6.9 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. clifile.cpp
  5. Abstract:
  6. Implements CLI FILE sub-interface
  7. Author:
  8. Ran Kalach [rankala] 3-March-2000
  9. Revision History:
  10. --*/
  11. #include "stdafx.h"
  12. #include "rpdata.h"
  13. HRESULT
  14. FileRecall(
  15. IN LPWSTR *FileSpecs,
  16. IN DWORD NumberOfFileSpecs
  17. )
  18. /*++
  19. Routine Description:
  20. Recalls all the files that match the given specification (path + wildcards)
  21. Arguments:
  22. FileSpecs -
  23. NumberOfFileSpecs -
  24. Return Value:
  25. S_OK - If all the files are recalled successfully.
  26. --*/
  27. {
  28. HRESULT hr = S_OK;
  29. HANDLE hSearchHandle = INVALID_HANDLE_VALUE;
  30. HANDLE hFile = INVALID_HANDLE_VALUE;
  31. BOOL bExistingFiles = FALSE;
  32. WsbTraceIn(OLESTR("FileRecall"), OLESTR(""));
  33. try {
  34. // Verify that input parameters are valid
  35. if (0 == NumberOfFileSpecs) {
  36. WsbTraceAndPrint(CLI_MESSAGE_NO_FILES, NULL);
  37. WsbThrow(E_INVALIDARG);
  38. }
  39. // Enumerate over the file specifications
  40. for (ULONG i = 0; i < NumberOfFileSpecs; i++) {
  41. CWsbStringPtr nameSpace;
  42. WCHAR* pathEnd;
  43. WIN32_FIND_DATA findData;
  44. BOOL bMoreFiles = TRUE;
  45. WsbAssert(NULL != FileSpecs[i], E_INVALIDARG);
  46. // Enumerate over files in each specification
  47. nameSpace = FileSpecs[i];
  48. WsbAffirmHr(nameSpace.Prepend(OLESTR("\\\\?\\")));
  49. pathEnd = wcsrchr(nameSpace, L'\\');
  50. WsbAssert(pathEnd != NULL, E_INVALIDARG);
  51. hSearchHandle = FindFirstFile((WCHAR *)nameSpace, &findData);
  52. if (INVALID_HANDLE_VALUE != hSearchHandle) {
  53. // Found at least one file that matches an input file specification
  54. bExistingFiles = TRUE;
  55. }
  56. while ((INVALID_HANDLE_VALUE != hSearchHandle) && bMoreFiles) {
  57. if ( findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ) {
  58. // File may be managed by HSM:
  59. CWsbStringPtr fileName;
  60. BYTE ReparseBuffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
  61. PREPARSE_DATA_BUFFER pReparseBuffer;
  62. DWORD outSize;
  63. BOOL bRecall = FALSE;
  64. // Create full name based on the path and the find-data
  65. *(pathEnd+1) = L'\0';
  66. fileName = nameSpace;
  67. *(pathEnd+1) = L'\\';
  68. WsbAffirmHr(fileName.Append(findData.cFileName));
  69. // Open the file
  70. hFile = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL,
  71. OPEN_EXISTING, FILE_FLAG_OPEN_NO_RECALL | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
  72. if (INVALID_HANDLE_VALUE == hFile) {
  73. // Report on an error
  74. DWORD dwErr = GetLastError();
  75. hr = HRESULT_FROM_WIN32(dwErr);
  76. WsbTraceAndPrint(CLI_MESSAGE_ERROR_FILE_RECALL, (WCHAR *)fileName, WsbHrAsString(hr), NULL);
  77. WsbThrow(hr);
  78. }
  79. // Get reparse data and check if the file is offline (if not, just ignore it and continue)
  80. if (0 == DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, NULL, 0,
  81. ReparseBuffer, sizeof(ReparseBuffer), &outSize, NULL)) {
  82. // Report on an error
  83. DWORD dwErr = GetLastError();
  84. hr = HRESULT_FROM_WIN32(dwErr);
  85. WsbTraceAndPrint(CLI_MESSAGE_ERROR_FILE_RECALL, (WCHAR *)fileName, WsbHrAsString(hr), NULL);
  86. WsbThrow(hr);
  87. }
  88. pReparseBuffer = (PREPARSE_DATA_BUFFER)ReparseBuffer;
  89. if (IO_REPARSE_TAG_HSM == pReparseBuffer->ReparseTag) {
  90. PRP_DATA pHsmData = (PRP_DATA) &pReparseBuffer->GenericReparseBuffer.DataBuffer[0];
  91. if( RP_FILE_IS_TRUNCATED( pHsmData->data.bitFlags ) ) {
  92. // File is managed by HSM and truncated
  93. bRecall = TRUE;
  94. }
  95. }
  96. CloseHandle(hFile);
  97. hFile = INVALID_HANDLE_VALUE;
  98. // Recall the file if required
  99. if (bRecall) {
  100. // Open the file again for recall
  101. hFile = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL,
  102. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  103. if (INVALID_HANDLE_VALUE == hFile) {
  104. // Report on an error
  105. DWORD dwErr = GetLastError();
  106. hr = HRESULT_FROM_WIN32(dwErr);
  107. WsbTraceAndPrint(CLI_MESSAGE_ERROR_FILE_RECALL, (WCHAR *)fileName, WsbHrAsString(hr), NULL);
  108. WsbThrow(hr);
  109. }
  110. // Recall the file
  111. if (0 == DeviceIoControl(hFile, FSCTL_RECALL_FILE, NULL, 0,
  112. NULL, 0, &outSize, NULL)) {
  113. // Report on an error
  114. // TEMPORARY: Should we abort or continue recalling other files?
  115. DWORD dwErr = GetLastError();
  116. hr = HRESULT_FROM_WIN32(dwErr);
  117. WsbTraceAndPrint(CLI_MESSAGE_ERROR_FILE_RECALL, (WCHAR *)fileName, WsbHrAsString(hr), NULL);
  118. WsbThrow(hr);
  119. }
  120. CloseHandle(hFile);
  121. hFile = INVALID_HANDLE_VALUE;
  122. }
  123. }
  124. // Get next file
  125. bMoreFiles = FindNextFile(hSearchHandle, &findData);
  126. }
  127. // Prepare for next file specification
  128. nameSpace.Free();
  129. if (INVALID_HANDLE_VALUE != hSearchHandle) {
  130. FindClose(hSearchHandle);
  131. hSearchHandle = INVALID_HANDLE_VALUE;
  132. }
  133. }
  134. // Print warning message if no valid file was specified
  135. if (FALSE == bExistingFiles) {
  136. WsbTraceAndPrint(CLI_MESSAGE_NO_FILES, NULL);
  137. }
  138. } WsbCatch(hr);
  139. // Ensure cleanup in case of an error
  140. if (INVALID_HANDLE_VALUE != hSearchHandle) {
  141. FindClose(hSearchHandle);
  142. hSearchHandle = INVALID_HANDLE_VALUE;
  143. }
  144. if (INVALID_HANDLE_VALUE != hFile) {
  145. CloseHandle(hFile);
  146. hFile = INVALID_HANDLE_VALUE;
  147. }
  148. WsbTraceOut(OLESTR("FileRecall"), OLESTR("hr = <%ls>"), WsbHrAsString(hr));
  149. return hr;
  150. }