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.

389 lines
9.9 KiB

  1. // Copyright (c) 1996-1999 Microsoft Corporation
  2. //+-------------------------------------------------------------------------
  3. //
  4. // Microsoft Windows
  5. //
  6. // File: fileops.hxx
  7. //
  8. // Contents: Definitions for OBJID and file operations
  9. //
  10. // Classes:
  11. //
  12. // Functions:
  13. //
  14. //
  15. //
  16. // History: 18-Nov-96 BillMo Created.
  17. //
  18. // Notes:
  19. //
  20. // Codework:
  21. //
  22. //--------------------------------------------------------------------------
  23. unsigned
  24. ConvertToNtPath(const TCHAR *ptszVolumePath, WCHAR *pwszNtPath, ULONG cwcBuf);
  25. //+----------------------------------------------------------------------------
  26. //
  27. // CVolumeDeviceName
  28. //
  29. // This represents a "volume device name", as defined by the mount manager.
  30. // Volume device names are of the form (but without the trailing whack). E.g.:
  31. //
  32. // "\\?\Volume{856d50da-d07e-11d2-9e72-806d6172696f}"
  33. //
  34. //+----------------------------------------------------------------------------
  35. class CVolumeDeviceName
  36. {
  37. public:
  38. // Create a volume device name from a zero-relative
  39. // drive letter index.
  40. CVolumeDeviceName( LONG iVol )
  41. {
  42. _stprintf( _tszPath, TEXT("\\\\.\\%c:"), iVol+TEXT('A') );
  43. }
  44. // Return the volume name..
  45. operator const TCHAR*() const
  46. {
  47. return( _tszPath );
  48. }
  49. // Validate a zero-relative drive letter index.
  50. static BOOL IsValid( LONG iVol )
  51. {
  52. if( 0 <= iVol && NUM_VOLUMES > iVol )
  53. return( TRUE );
  54. else
  55. return( FALSE );
  56. }
  57. private:
  58. TCHAR _tszPath[ MAX_PATH ];
  59. };
  60. //
  61. // IsLocalObjectVolume
  62. //
  63. // Returns true of the volume supports object IDs (NTFS5).
  64. //
  65. BOOL IsLocalObjectVolume( const TCHAR *ptszVolumeName );
  66. inline BOOL
  67. IsLocalObjectVolume( LONG iVol )
  68. {
  69. if( !CVolumeDeviceName::IsValid(iVol) )
  70. return( STATUS_OBJECT_PATH_NOT_FOUND );
  71. TCHAR tszVolumeName[ MAX_PATH+1 ];
  72. _tcscpy( tszVolumeName, CVolumeDeviceName(iVol) );
  73. _tcscat( tszVolumeName, TEXT("\\") );
  74. return( IsLocalObjectVolume( tszVolumeName ));
  75. }
  76. //
  77. // IsSystemVolumeInformation
  78. //
  79. // Returns true if the path is somewhere under "\System Volume Information"
  80. //
  81. BOOL IsSystemVolumeInformation( const TCHAR *ptszPath );
  82. HRESULT
  83. MapLocalPathToUNC( RPC_BINDING_HANDLE IDL_handle,
  84. const TCHAR *ptszLocalPath,
  85. TCHAR *ptszUNC,
  86. ULONG cbMaxUnc );
  87. NTSTATUS
  88. OpenFileById( const TCHAR *ptszVolumeDeviceName,
  89. const CObjId &oid,
  90. ACCESS_MASK AccessMask,
  91. ULONG ShareAccess,
  92. ULONG AdditionalCreateOptions,
  93. HANDLE *ph);
  94. inline NTSTATUS
  95. OpenFileById( LONG iVol,
  96. const CObjId &oid,
  97. ACCESS_MASK AccessMask,
  98. ULONG ShareAccess,
  99. ULONG AdditionalCreateOptions,
  100. HANDLE *ph)
  101. {
  102. if( !CVolumeDeviceName::IsValid(iVol) )
  103. return( STATUS_OBJECT_PATH_NOT_FOUND );
  104. return( OpenFileById( CVolumeDeviceName(iVol), oid,
  105. AccessMask, ShareAccess, AdditionalCreateOptions, ph ));
  106. }
  107. NTSTATUS
  108. OpenVolume( const TCHAR *ptszVolumeDeviceName, HANDLE * ph );
  109. inline NTSTATUS
  110. OpenVolume( LONG iVol, HANDLE * phVolume )
  111. {
  112. if( !CVolumeDeviceName::IsValid(iVol) )
  113. return( STATUS_OBJECT_PATH_NOT_FOUND );
  114. return( OpenVolume( CVolumeDeviceName(iVol), phVolume ));
  115. }
  116. NTSTATUS
  117. CheckVolumeWriteProtection( const TCHAR *ptszVolumeDeviceName, BOOL *pfWriteProtected );
  118. #define CCH_MAX_VOLUME_NAME 50 // \\?\Volume{96765fc3-9c72-11d1-b93d-000000000000}\
  119. LONG
  120. MapVolumeDeviceNameToIndex( TCHAR *ptszVolumeDeviceName );
  121. NTSTATUS
  122. SetVolId( const TCHAR *ptszVolumeDeviceName, const CVolumeId &volid );
  123. inline NTSTATUS
  124. SetVolId( LONG iVol, const CVolumeId &volid )
  125. {
  126. if( !CVolumeDeviceName::IsValid(iVol) )
  127. return( STATUS_OBJECT_PATH_NOT_FOUND );
  128. return( SetVolId( CVolumeDeviceName(iVol), volid ));
  129. }
  130. NTSTATUS
  131. TrkCreateFile( const WCHAR *pwszCompleteDosPath,
  132. ACCESS_MASK AccessMask,
  133. ULONG Attributes,
  134. ULONG ShareAccess,
  135. ULONG CreationDisposition, // e.g. FILE_OPEN, FILE_OPEN_IF, etc
  136. ULONG CreateOptions, // e.g. FILE_WRITE_THROUGH, FILE_OPEN_FOR_BACKUP_INTENT
  137. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  138. HANDLE *ph);
  139. NTSTATUS
  140. FindLocalPath( IN const TCHAR *ptszVolumeDeviceName,
  141. IN const CObjId &objid,
  142. OUT CDomainRelativeObjId *pdroidBirth,
  143. OUT TCHAR *ptszLocalPath );
  144. inline NTSTATUS
  145. FindLocalPath( IN ULONG iVol,
  146. IN const CObjId &objid,
  147. OUT CDomainRelativeObjId *pdroidBirth,
  148. OUT TCHAR *ptszLocalPath )
  149. {
  150. if( !CVolumeDeviceName::IsValid(iVol) )
  151. return( STATUS_OBJECT_PATH_NOT_FOUND );
  152. return( FindLocalPath( CVolumeDeviceName(iVol), objid, pdroidBirth, ptszLocalPath ));
  153. }
  154. NTSTATUS
  155. GetDroids( HANDLE hFile,
  156. CDomainRelativeObjId *pdroidCurrent,
  157. CDomainRelativeObjId *pdroidBirth,
  158. RGO_ENUM rgoEnum );
  159. NTSTATUS
  160. GetDroids( const TCHAR *ptszFile,
  161. CDomainRelativeObjId *pdroidCurrent,
  162. CDomainRelativeObjId *pdroidBirth,
  163. RGO_ENUM rgoEnum );
  164. NTSTATUS
  165. SetObjId( const HANDLE hFile,
  166. CObjId objid,
  167. const CDomainRelativeObjId &droidBirth );
  168. NTSTATUS
  169. SetObjId( const TCHAR *ptszFile,
  170. CObjId objid,
  171. const CDomainRelativeObjId &droidBirth );
  172. NTSTATUS
  173. MakeObjIdReborn(HANDLE hFile);
  174. NTSTATUS
  175. MakeObjIdReborn(const TCHAR *ptszVolumeDeviceName, const CObjId &objid);
  176. inline NTSTATUS
  177. MakeObjIdReborn(LONG iVol, const CObjId &objid)
  178. {
  179. if( !CVolumeDeviceName::IsValid(iVol) )
  180. return( STATUS_OBJECT_PATH_NOT_FOUND );
  181. return( MakeObjIdReborn( CVolumeDeviceName(iVol), objid ));
  182. }
  183. NTSTATUS
  184. SetBirthId( HANDLE hFile,
  185. const CDomainRelativeObjId &droidBirth );
  186. NTSTATUS
  187. SetBirthId( const TCHAR *ptszFile,
  188. const CDomainRelativeObjId &droidBirth );
  189. NTSTATUS
  190. GetBirthId( IN HANDLE hFile, OUT CDomainRelativeObjId *pdroidBirth );
  191. // This routine is inline because it doesn't get used in the production code,
  192. // only in tests.
  193. inline NTSTATUS
  194. DelObjId(HANDLE hFile)
  195. {
  196. // -----------------
  197. // Delete the Object ID
  198. // -----------------
  199. // Send the FSCTL
  200. IO_STATUS_BLOCK IoStatus;
  201. return NtFsControlFile(
  202. hFile,
  203. NULL,
  204. NULL,
  205. NULL,
  206. &IoStatus,
  207. FSCTL_DELETE_OBJECT_ID,
  208. NULL, // in buffer
  209. 0, // in buffer size
  210. NULL, // Out buffer
  211. 0); // Out buffer size
  212. }
  213. // This routine is inline because it doesn't get used in the production code,
  214. // only in tests.
  215. inline NTSTATUS
  216. DelObjId(const TCHAR *ptszVolumeDeviceName, const CObjId &objid)
  217. {
  218. // --------------
  219. // Initialization
  220. // --------------
  221. NTSTATUS status = STATUS_SUCCESS;
  222. HANDLE hFile = NULL;
  223. // -------------
  224. // Open the file
  225. // -------------
  226. EnableRestorePrivilege();
  227. status = OpenFileById(ptszVolumeDeviceName,
  228. objid,
  229. SYNCHRONIZE | FILE_WRITE_ATTRIBUTES,
  230. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
  231. FILE_OPEN_FOR_BACKUP_INTENT, // for FSCTL_DELETE_OBJECT_ID
  232. &hFile);
  233. if( !NT_SUCCESS(status) )
  234. {
  235. hFile = NULL;
  236. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't del objid, failed open (%08x)"),
  237. status ));
  238. goto Exit;
  239. }
  240. status = DelObjId( hFile );
  241. if( !NT_SUCCESS(status) && STATUS_OBJECT_NAME_NOT_FOUND != status )
  242. {
  243. TrkLog(( TRKDBG_ERROR, TEXT("Couldn't delete file Object ID, failed delete (%08x)"),
  244. status ));
  245. goto Exit;
  246. }
  247. // ----
  248. // Exit
  249. // ----
  250. Exit:
  251. if( NULL != hFile )
  252. NtClose( hFile );
  253. return( status );
  254. }
  255. inline NTSTATUS
  256. DelObjId(LONG iVol, const CObjId &objid)
  257. {
  258. if( !CVolumeDeviceName::IsValid(iVol) )
  259. return( STATUS_OBJECT_PATH_NOT_FOUND );
  260. return( DelObjId( CVolumeDeviceName(iVol), objid ));
  261. }
  262. //+----------------------------------------------------------------------------
  263. //
  264. // InterlockedCloseHandle
  265. //
  266. // This routine provides a thread-safe way to close a handle for code
  267. // that isn't thread-safe. This is used by CloseVolumeHandles, since
  268. // that routine can't take a lock.
  269. //
  270. //+----------------------------------------------------------------------------
  271. inline void
  272. InterlockedCloseHandle( HANDLE *ph, void* EmptyValue = NULL, BOOL fCancelIo = FALSE )
  273. {
  274. HANDLE h1 = NULL;
  275. HANDLE h2 = NULL;
  276. // Get the current value.
  277. h1 = *ph;
  278. // If the handle hasn't changed between the previous line and the
  279. // following call, set it to null.
  280. h2 = InterlockedCompareExchangePointer( (void**)ph,
  281. (void*)EmptyValue,
  282. h1 );
  283. // If *ph was unchanged as of the previous
  284. // call, we've got a local copy of it now, and we can safely close it.
  285. if( h1 == h2
  286. &&
  287. EmptyValue != h1 )
  288. {
  289. // *ph is already NULL
  290. if( fCancelIo )
  291. {
  292. TrkLog(( TRKDBG_MISC, TEXT("Canceling handle x%x"), h1 ));
  293. CancelIo( h1 );
  294. }
  295. TrkLog(( TRKDBG_MISC, TEXT("Closing handle x%x"), h1 ));
  296. NtClose( h1 );
  297. }
  298. }