Leaked source code of windows server 2003
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.

394 lines
12 KiB

  1. /*++
  2. 1998 Seagate Software, Inc. All rights reserved.
  3. Module Name:
  4. RsClnFil.cpp
  5. Abstract:
  6. Implementation of CRsClnFile. This class represents a file on
  7. a local volume of a Remote Storage server, which is going to be
  8. cleaned. Cleaning means removing the file if it has been truncated
  9. and removing its reparse point. Each instance of CRsClnFile is created
  10. by CRsClnVolume.
  11. Author:
  12. Carl Hagerstrom [carlh] 20-Aug-1998
  13. Revision History:
  14. --*/
  15. #include <stdafx.h>
  16. /*++
  17. Implements:
  18. CRsClnFile Constructor
  19. Routine Description:
  20. Loads file information.
  21. Arguments:
  22. hVolume - handle of volume on which this file resides
  23. fileReference - file reference for this file. This is
  24. a numerical handle which can be used
  25. to uniquely identify and open a file.
  26. --*/
  27. CRsClnFile::CRsClnFile(
  28. IN CRsClnVolume* pVolume,
  29. IN LONGLONG FileReference
  30. ) :
  31. m_pVolume( pVolume )
  32. {
  33. TRACEFN( "CRsClnFile::CRsClnFile" );
  34. m_pReparseData = 0;
  35. m_pHsmData = 0;
  36. RsOptAffirmDw( GetFileInfo( FileReference ) );
  37. }
  38. /*++
  39. Implements:
  40. CRsClnFile Destructor
  41. --*/
  42. CRsClnFile::~CRsClnFile( )
  43. {
  44. TRACEFN( "CRsClnFile::~CRsClnFile" );
  45. }
  46. /*++
  47. Implements:
  48. CRsClnFile::RemoveReparsePointAndFile
  49. Routine Description:
  50. Removes the reparse point for this file and removes
  51. the file itself if it has been truncated.
  52. - Read the reparse point for this file.
  53. - Determine from reparse data whether the file has been truncated.
  54. - If truncated, close and remove it.
  55. - If not truncated, remove reparse point and close file.
  56. Arguments:
  57. stickyName - name of volume on which this file resides
  58. Return Value:
  59. S_OK - success
  60. E_* - any unexpected exceptions from lower level routines
  61. --*/
  62. HRESULT
  63. CRsClnFile::RemoveReparsePointAndFile(
  64. )
  65. {
  66. TRACEFNHR( "CRsClnFile::RemoveReparsePointAndFile" );
  67. DWORD actualSize;
  68. BOOL bStatus;
  69. HANDLE hFile = INVALID_HANDLE_VALUE;
  70. try {
  71. RsOptAffirmDw( ClearReadOnly( ) );
  72. if ( RP_FILE_IS_TRUNCATED( m_pHsmData->data.bitFlags ) ) {
  73. //
  74. // Clear the file attributes in case they are read only
  75. //
  76. RsOptAffirmStatus( DeleteFile( m_FullPath ) );
  77. } else {
  78. hFile = CreateFile( m_FullPath,
  79. FILE_READ_DATA | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES,
  80. FILE_SHARE_READ | FILE_SHARE_WRITE,
  81. 0,
  82. OPEN_EXISTING,
  83. FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
  84. 0 );
  85. RsOptAffirmHandle( hFile );
  86. //
  87. // Set the time flags so that when we close the handle the
  88. // time are not updated on the file and the FileAttributes
  89. // indicate the file is offline
  90. //
  91. IO_STATUS_BLOCK ioStatusBlock;
  92. FILE_BASIC_INFORMATION basicInfo;
  93. RsOptAffirmNtStatus( NtQueryInformationFile( hFile,
  94. &ioStatusBlock,
  95. (PVOID) &basicInfo,
  96. sizeof( basicInfo ),
  97. FileBasicInformation ) );
  98. basicInfo.CreationTime.QuadPart = -1;
  99. basicInfo.LastAccessTime.QuadPart = -1;
  100. basicInfo.LastWriteTime.QuadPart = -1;
  101. basicInfo.ChangeTime.QuadPart = -1;
  102. RsOptAffirmNtStatus( NtSetInformationFile( hFile,
  103. &ioStatusBlock,
  104. (PVOID)&basicInfo,
  105. sizeof( basicInfo ),
  106. FileBasicInformation ) );
  107. //
  108. // Nuke the reparse point
  109. //
  110. m_pReparseData->ReparseTag = IO_REPARSE_TAG_HSM;
  111. m_pReparseData->ReparseDataLength = 0;
  112. bStatus = DeviceIoControl( hFile,
  113. FSCTL_DELETE_REPARSE_POINT,
  114. (LPVOID) m_pReparseData,
  115. REPARSE_DATA_BUFFER_HEADER_SIZE,
  116. (LPVOID) 0,
  117. (DWORD) 0,
  118. &actualSize,
  119. (LPOVERLAPPED) 0 );
  120. RsOptAffirmStatus( bStatus );
  121. }
  122. } RsOptCatch( hrRet );
  123. if( INVALID_HANDLE_VALUE != hFile ) CloseHandle( hFile );
  124. if( ! RP_FILE_IS_TRUNCATED( m_pHsmData->data.bitFlags ) ) {
  125. //
  126. // Restore file attributes
  127. //
  128. RestoreAttributes( );
  129. }
  130. return( hrRet );
  131. }
  132. /*++
  133. Implements:
  134. CRsClnFile::GetFileInfo
  135. Routine Description:
  136. Obtain file information for file specified by volume and
  137. file reference.
  138. - Open file using volume handle and file reference.
  139. - Obtain the file name and the length of the file name.
  140. Since the length of the file name is unknown the first time
  141. NtQueryInformationFile is called, it might have to be called
  142. again once the correct buffer size can be determined.
  143. Arguments:
  144. hVolume - handle of volume on which this file resides
  145. fileReference - file reference for this file. This is
  146. a numerical handle which can be used
  147. to uniquely identify and open a file.
  148. Return Value:
  149. S_OK - Success
  150. E_* - Any unexpected exceptions from lower level routines
  151. --*/
  152. HRESULT
  153. CRsClnFile::GetFileInfo(
  154. IN LONGLONG fileReference
  155. )
  156. {
  157. TRACEFNHR( "CRsClnFile::GetFileInfo" );
  158. UNICODE_STRING objectName;
  159. OBJECT_ATTRIBUTES objectAttributes;
  160. NTSTATUS ntStatus;
  161. IO_STATUS_BLOCK ioStatusBlock;
  162. PFILE_NAME_INFORMATION pfni;
  163. HANDLE hFile = INVALID_HANDLE_VALUE;
  164. DWORD actualSize;
  165. ULONG fileNameLength;
  166. PVOID fileNameInfo = 0;
  167. m_pReparseData = (PREPARSE_DATA_BUFFER) m_ReparseData;
  168. m_pHsmData = (PRP_DATA)&( m_pReparseData->GenericReparseBuffer.DataBuffer[0] );
  169. try {
  170. RtlInitUnicodeString( &objectName, (WCHAR*)&fileReference );
  171. objectName.Length = 8;
  172. objectName.MaximumLength = 8;
  173. HANDLE hVolume = m_pVolume->GetHandle( );
  174. RsOptAffirmHandle( hVolume );
  175. InitializeObjectAttributes( &objectAttributes,
  176. &objectName,
  177. OBJ_CASE_INSENSITIVE,
  178. hVolume,
  179. (PVOID)0 );
  180. ULONG desiredAccess = FILE_READ_ATTRIBUTES;
  181. ULONG shareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;
  182. ULONG createOptions = FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_BY_FILE_ID | FILE_OPEN_REPARSE_POINT;
  183. ntStatus = NtCreateFile( &hFile,
  184. desiredAccess,
  185. &objectAttributes,
  186. &ioStatusBlock,
  187. (PLARGE_INTEGER)0,
  188. FILE_ATTRIBUTE_NORMAL,
  189. shareAccess,
  190. FILE_OPEN,
  191. createOptions,
  192. (PVOID)0,
  193. (ULONG)0 );
  194. RsOptAffirmNtStatus( ntStatus );
  195. RsOptAffirmNtStatus( NtQueryInformationFile( hFile,
  196. &ioStatusBlock,
  197. (PVOID) &m_BasicInfo,
  198. sizeof( m_BasicInfo ),
  199. FileBasicInformation ) );
  200. //
  201. // Get the file name
  202. //
  203. size_t bufSize = 256;
  204. fileNameInfo = malloc( bufSize );
  205. RsOptAffirmAlloc( fileNameInfo );
  206. ntStatus = NtQueryInformationFile( hFile,
  207. &ioStatusBlock,
  208. fileNameInfo,
  209. bufSize - sizeof(WCHAR),
  210. FileNameInformation );
  211. if( ntStatus == STATUS_BUFFER_OVERFLOW ) {
  212. pfni = (PFILE_NAME_INFORMATION)fileNameInfo;
  213. bufSize = sizeof(ULONG) + pfni->FileNameLength + sizeof(WCHAR);
  214. PVOID tmpFileNameInfo = realloc( fileNameInfo, bufSize );
  215. if( !tmpFileNameInfo ) {
  216. free( fileNameInfo );
  217. fileNameInfo = 0;
  218. } else {
  219. fileNameInfo = tmpFileNameInfo;
  220. }
  221. RsOptAffirmAlloc( fileNameInfo );
  222. RsOptAffirmNtStatus( NtQueryInformationFile( hFile,
  223. &ioStatusBlock,
  224. fileNameInfo,
  225. bufSize,
  226. FileNameInformation ) );
  227. } else {
  228. RsOptAffirmNtStatus( ntStatus );
  229. }
  230. pfni = (PFILE_NAME_INFORMATION) fileNameInfo;
  231. fileNameLength = pfni->FileNameLength / (ULONG)sizeof(WCHAR);
  232. pfni->FileName[ fileNameLength ] = L'\0';
  233. m_FileName = pfni->FileName;
  234. m_FullPath = m_pVolume->GetStickyName( ) + m_FileName;
  235. //
  236. // And grab the reparse point data
  237. //
  238. BOOL bStatus = DeviceIoControl( hFile,
  239. FSCTL_GET_REPARSE_POINT,
  240. (LPVOID) 0,
  241. (DWORD) 0,
  242. (LPVOID) m_ReparseData,
  243. (DWORD) sizeof(m_ReparseData),
  244. &actualSize,
  245. (LPOVERLAPPED) 0 );
  246. RsOptAffirmStatus( bStatus );
  247. } RsOptCatch( hrRet );
  248. if( INVALID_HANDLE_VALUE != hFile ) CloseHandle( hFile );
  249. if( fileNameInfo ) free( fileNameInfo );
  250. return( hrRet );
  251. }
  252. CString CRsClnFile::GetFileName( )
  253. {
  254. CString displayName;
  255. displayName = m_pVolume->GetBestName( );
  256. displayName += m_FileName.Mid( 1 ); // Gotta strip first backslash
  257. return( displayName );
  258. }
  259. HRESULT CRsClnFile::ClearReadOnly( )
  260. {
  261. TRACEFNHR( "CRsClnFile::ClearReadOnly" );
  262. try {
  263. RsOptAffirmStatus(
  264. SetFileAttributes( m_FullPath,
  265. ( m_BasicInfo.FileAttributes & ~FILE_ATTRIBUTE_READONLY ) | FILE_ATTRIBUTE_NORMAL ) );
  266. } RsOptCatch( hrRet );
  267. return( hrRet );
  268. }
  269. HRESULT CRsClnFile::RestoreAttributes( )
  270. {
  271. TRACEFNHR( "CRsClnFile::RestoreAttributes" );
  272. try {
  273. RsOptAffirmStatus(
  274. SetFileAttributes( m_FullPath,
  275. ( m_BasicInfo.FileAttributes & ~FILE_ATTRIBUTE_OFFLINE ) | FILE_ATTRIBUTE_NORMAL ) );
  276. } RsOptCatch( hrRet );
  277. return( hrRet );
  278. }