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.

542 lines
20 KiB

  1. /*++
  2. Copyright (c) 1989-1997 Microsoft Corporation
  3. Module Name:
  4. rentest.c
  5. Abstract:
  6. This module contains tests for stream rename support
  7. --*/
  8. extern "C" {
  9. #include <nt.h>
  10. #include <ntioapi.h>
  11. #include <ntrtl.h>
  12. #include <nturtl.h>
  13. }
  14. #include <windows.h>
  15. #include <stdio.h>
  16. #define DEFAULT_DATA_STREAM "::$DATA"
  17. //
  18. // Simple wrapper for NtCreateFile
  19. //
  20. NTSTATUS
  21. OpenObject (
  22. WCHAR const *pwszFile,
  23. HANDLE RelatedObject,
  24. ULONG CreateOptions,
  25. ULONG DesiredAccess,
  26. ULONG ShareAccess,
  27. ULONG CreateDisposition,
  28. HANDLE *ph)
  29. {
  30. NTSTATUS Status;
  31. OBJECT_ATTRIBUTES oa;
  32. UNICODE_STRING str;
  33. IO_STATUS_BLOCK isb;
  34. if (RelatedObject == NULL) {
  35. RtlDosPathNameToNtPathName_U(pwszFile, &str, NULL, NULL);
  36. } else {
  37. RtlInitUnicodeString(&str, pwszFile);
  38. }
  39. InitializeObjectAttributes(
  40. &oa,
  41. &str,
  42. OBJ_CASE_INSENSITIVE,
  43. RelatedObject,
  44. NULL);
  45. Status = NtCreateFile(
  46. ph,
  47. DesiredAccess | SYNCHRONIZE,
  48. &oa,
  49. &isb,
  50. NULL, // pallocationsize (none!)
  51. FILE_ATTRIBUTE_NORMAL,
  52. ShareAccess,
  53. CreateDisposition,
  54. CreateOptions,
  55. NULL, // EA buffer (none!)
  56. 0);
  57. RtlFreeHeap(RtlProcessHeap(), 0, str.Buffer);
  58. return(Status);
  59. }
  60. void
  61. SzToWsz (
  62. OUT WCHAR *Unicode,
  63. IN char *Ansi
  64. )
  65. {
  66. while (*Unicode++ = *Ansi++)
  67. ;
  68. }
  69. typedef enum {
  70. NoTarget,
  71. EmptyTarget,
  72. NonZeroTarget
  73. } TARGET_STATUS;
  74. typedef enum {
  75. EmptySource,
  76. SmallSource,
  77. BigSource
  78. } SOURCE_STATUS;
  79. void
  80. StickDataIn (
  81. HANDLE Handle,
  82. char *SomeData,
  83. SOURCE_STATUS SourceStatus
  84. )
  85. {
  86. if (SourceStatus == EmptySource) {
  87. } else if (SourceStatus == SmallSource) {
  88. IO_STATUS_BLOCK Iosb;
  89. NTSTATUS Status =
  90. NtWriteFile( Handle, NULL, NULL, NULL, &Iosb, SomeData, strlen( SomeData ), NULL, NULL );
  91. if (!NT_SUCCESS( Status )) {
  92. printf( "Unable to stick data in - %x\n", Status );
  93. }
  94. NtFlushBuffersFile( Handle, &Iosb );
  95. } else if (SourceStatus == BigSource) {
  96. IO_STATUS_BLOCK Iosb;
  97. LARGE_INTEGER Offset;
  98. Offset.QuadPart = 1024 * 1024;
  99. NTSTATUS Status =
  100. NtWriteFile( Handle, NULL, NULL, NULL, &Iosb, SomeData, strlen( SomeData ), &Offset, NULL );
  101. if (!NT_SUCCESS( Status )) {
  102. printf( "Unable to stick data in - %x\n", Status );
  103. }
  104. NtFlushBuffersFile( Handle, &Iosb );
  105. }
  106. }
  107. void
  108. CheckData (
  109. HANDLE Handle,
  110. char *Data,
  111. SOURCE_STATUS SourceStatus,
  112. int Line
  113. )
  114. {
  115. if (SourceStatus == EmptySource) {
  116. //
  117. // Verify that the source is zero bytes long
  118. //
  119. } else if (SourceStatus == SmallSource) {
  120. IO_STATUS_BLOCK Iosb;
  121. char *FileData = new char[ strlen( Data )];
  122. NTSTATUS Status =
  123. NtReadFile( Handle, NULL, NULL, NULL, &Iosb, FileData, strlen( Data ), NULL, NULL );
  124. if (!NT_SUCCESS( Status )) {
  125. printf( "line %d Unable to read data - %x\n", Line, Status );
  126. }
  127. if (memcmp( Data, FileData, strlen( Data ))) {
  128. printf( "line %d small data is different\n", Line );
  129. printf( "File: '%.*s' Test: '%s'\n", strlen( Data ), FileData, Data );
  130. }
  131. delete [] FileData;
  132. } else if (SourceStatus == BigSource) {
  133. IO_STATUS_BLOCK Iosb;
  134. char *FileData = new char[ strlen( Data )];
  135. LARGE_INTEGER Offset;
  136. Offset.QuadPart = 1024 * 1024;
  137. NTSTATUS Status =
  138. NtReadFile( Handle, NULL, NULL, NULL, &Iosb, FileData, strlen( Data ), &Offset, NULL );
  139. if (!NT_SUCCESS( Status )) {
  140. printf( "line %d Unable to read data in - %x\n", Line, Status );
  141. }
  142. if (memcmp( Data, FileData, strlen( Data ))) {
  143. printf( "line %d large data is different\n", Line );
  144. printf( "File: '%.*s' Test: '%s'\n", strlen( Data ), FileData, Data );
  145. }
  146. delete [] FileData;
  147. }
  148. }
  149. #define TESTONE \
  150. printf( "TestOne( %s, %s, %x, %x, %x, Line %d ): ", \
  151. SourceStream, TargetStream, \
  152. TargetStatus, ReplaceIfExists, ExpectedStatus, \
  153. Line )
  154. #define CLOSE(h) { \
  155. NTSTATUS TmpStatus = NtClose(h); \
  156. h = INVALID_HANDLE_VALUE; \
  157. if (!NT_SUCCESS( TmpStatus )) { \
  158. TESTONE; printf( "Couldn't close handle @ %d\n", __LINE__ ); \
  159. } \
  160. }
  161. //
  162. // Open a handle relative to the parent of the Source stream.
  163. //
  164. void
  165. TestOne (
  166. char *FileName,
  167. char *SourceStream,
  168. SOURCE_STATUS SourceStatus,
  169. char *TargetStream,
  170. TARGET_STATUS TargetStatus,
  171. BOOLEAN ReplaceIfExists,
  172. NTSTATUS ExpectedStatus,
  173. int Line
  174. )
  175. {
  176. NTSTATUS Status;
  177. WCHAR UnicodeFullSourceStreamName[MAX_PATH];
  178. WCHAR UnicodeFullTargetStreamName[MAX_PATH];
  179. WCHAR UnicodeTargetStreamName[MAX_PATH];
  180. HANDLE SourceHandle;
  181. HANDLE TargetHandle;
  182. //
  183. // Convert names to unicode and form complete source name
  184. //
  185. SzToWsz( UnicodeFullSourceStreamName, FileName );
  186. SzToWsz( UnicodeFullSourceStreamName + wcslen( UnicodeFullSourceStreamName ), SourceStream );
  187. SzToWsz( UnicodeTargetStreamName, TargetStream );
  188. SzToWsz( UnicodeFullTargetStreamName, FileName );
  189. SzToWsz( UnicodeFullTargetStreamName + wcslen( UnicodeFullTargetStreamName ), TargetStream );
  190. //
  191. // Create/open source stream
  192. //
  193. Status = OpenObject( UnicodeFullSourceStreamName,
  194. NULL,
  195. FILE_SYNCHRONOUS_IO_NONALERT,
  196. FILE_READ_DATA | FILE_WRITE_DATA | DELETE,
  197. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
  198. FILE_OPEN_IF,
  199. &SourceHandle );
  200. if (!NT_SUCCESS( Status )) {
  201. TESTONE; printf( "unable to open source stream - %x\n", Status );
  202. }
  203. //
  204. // Stick data into source
  205. //
  206. StickDataIn( SourceHandle, SourceStream, SourceStatus );
  207. //
  208. // If target is not supposed to exist
  209. //
  210. if (TargetStatus == NoTarget) {
  211. //
  212. // Create/Open target stream with delete-on-close
  213. //
  214. Status = OpenObject( UnicodeFullTargetStreamName,
  215. NULL,
  216. FILE_SYNCHRONOUS_IO_NONALERT | FILE_DELETE_ON_CLOSE,
  217. FILE_READ_DATA | FILE_WRITE_DATA | DELETE,
  218. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
  219. FILE_OPEN_IF,
  220. &TargetHandle );
  221. //
  222. // Close target stream (do the delete)
  223. //
  224. if (NT_SUCCESS( Status )) {
  225. CLOSE( TargetHandle );
  226. } else {
  227. TESTONE; printf( "Unable to set NoTarget on %s - %x\n", TargetStream, Status );
  228. }
  229. } else {
  230. //
  231. // Create/open target stream
  232. //
  233. Status = OpenObject( UnicodeFullTargetStreamName,
  234. NULL,
  235. FILE_SYNCHRONOUS_IO_NONALERT,
  236. FILE_READ_DATA | FILE_WRITE_DATA,
  237. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
  238. FILE_OPEN_IF,
  239. &TargetHandle );
  240. if (!NT_SUCCESS( Status )) {
  241. TESTONE; printf( "unable to open target for sizing %x\n", Status );
  242. }
  243. FILE_END_OF_FILE_INFORMATION EndOfFile;
  244. EndOfFile.EndOfFile.QuadPart = 0i64;
  245. IO_STATUS_BLOCK Iosb;
  246. Status = NtSetInformationFile( TargetHandle,
  247. &Iosb,
  248. &EndOfFile,
  249. sizeof( EndOfFile ),
  250. FileEndOfFileInformation );
  251. //
  252. // If target has data in it
  253. //
  254. if (TargetStatus == NonZeroTarget) {
  255. //
  256. // Stick data into target
  257. //
  258. StickDataIn( TargetHandle, TargetStream, SmallSource );
  259. }
  260. //
  261. // Close target
  262. //
  263. CLOSE( TargetHandle );
  264. }
  265. //
  266. // Set up FileRenameInformation
  267. //
  268. char buffer[sizeof( FILE_RENAME_INFORMATION ) + MAX_PATH * sizeof( WCHAR )];
  269. PFILE_RENAME_INFORMATION FileRenameInformationBlock = (PFILE_RENAME_INFORMATION) buffer;
  270. FileRenameInformationBlock->ReplaceIfExists = ReplaceIfExists;
  271. FileRenameInformationBlock->RootDirectory = NULL;
  272. FileRenameInformationBlock->FileNameLength = strlen( TargetStream ) * sizeof( WCHAR );
  273. SzToWsz( FileRenameInformationBlock->FileName, TargetStream );
  274. //
  275. // Attempt to rename
  276. //
  277. IO_STATUS_BLOCK Iosb;
  278. Status = NtSetInformationFile( SourceHandle,
  279. &Iosb,
  280. FileRenameInformationBlock,
  281. sizeof( buffer ),
  282. FileRenameInformation );
  283. //
  284. // Check output status codes
  285. //
  286. if (Status != ExpectedStatus) {
  287. TESTONE; printf( "status was %x\n", Status );
  288. }
  289. //
  290. // Close Source stream
  291. //
  292. CLOSE( SourceHandle );
  293. //
  294. // If we succeeded in tehe rename
  295. //
  296. if (NT_SUCCESS( Status )) {
  297. //
  298. // Verify that the source stream no longer exists
  299. //
  300. Status = OpenObject( UnicodeFullSourceStreamName,
  301. NULL,
  302. FILE_SYNCHRONOUS_IO_NONALERT,
  303. FILE_READ_DATA | FILE_WRITE_DATA,
  304. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
  305. FILE_OPEN,
  306. &SourceHandle );
  307. //
  308. // Verify that the source does/doesn't exist as appropriate
  309. //
  310. if (NT_SUCCESS( Status )) {
  311. if (!strcmp( SourceStream, DEFAULT_DATA_STREAM )) {
  312. // Default data stream still exists. No problem
  313. } else {
  314. TESTONE; printf( "source stream still exists\n" );
  315. }
  316. CLOSE( SourceHandle );
  317. } else if (!strcmp( SourceStream, DEFAULT_DATA_STREAM )) {
  318. TESTONE; printf( "failed to open default data stream - %x\n", Status );
  319. } else {
  320. // failed to open previous source stream. No problem
  321. }
  322. //
  323. // Reopen the target stream (formerly source stream)
  324. //
  325. Status = OpenObject( UnicodeFullTargetStreamName,
  326. NULL,
  327. FILE_SYNCHRONOUS_IO_NONALERT,
  328. FILE_READ_DATA | FILE_WRITE_DATA,
  329. FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
  330. FILE_OPEN,
  331. &TargetHandle );
  332. if (!NT_SUCCESS( Status )) {
  333. TESTONE; printf( "unable to open target for verification %x\n", Status );
  334. }
  335. //
  336. // Verify the contents
  337. //
  338. CheckData( TargetHandle, SourceStream, SourceStatus, Line );
  339. CLOSE( TargetHandle );
  340. }
  341. }
  342. void
  343. RenameTest (
  344. char *FileName
  345. )
  346. {
  347. // Test:
  348. // ::$Data to :New Succeed
  349. // ::$Data to :NonZero Fail always
  350. // ::$Data to :Empty Succeed if ReplaceIfExists
  351. // :Test to ::$Data <empty> Succeed if ReplaceIfExists
  352. // :Test to ::$Data <nonzero> Fail always
  353. //
  354. // XXX:Test to YYY:Test Fail always
  355. //
  356. // ::$Data to :New Succeed
  357. TestOne( FileName, DEFAULT_DATA_STREAM, EmptySource, ":New", NoTarget, FALSE, STATUS_SUCCESS, __LINE__ );
  358. TestOne( FileName, DEFAULT_DATA_STREAM, EmptySource, ":New", NoTarget, TRUE, STATUS_SUCCESS, __LINE__ );
  359. TestOne( FileName, DEFAULT_DATA_STREAM, SmallSource, ":New", NoTarget, FALSE, STATUS_SUCCESS, __LINE__ );
  360. TestOne( FileName, DEFAULT_DATA_STREAM, SmallSource, ":New", NoTarget, TRUE, STATUS_SUCCESS, __LINE__ );
  361. TestOne( FileName, DEFAULT_DATA_STREAM, BigSource, ":New", NoTarget, FALSE, STATUS_SUCCESS, __LINE__ );
  362. TestOne( FileName, DEFAULT_DATA_STREAM, BigSource, ":New", NoTarget, TRUE, STATUS_SUCCESS, __LINE__ );
  363. // ::$Data to :NonZero Fail always
  364. TestOne( FileName, DEFAULT_DATA_STREAM, EmptySource, ":NonZero", NonZeroTarget, FALSE, STATUS_OBJECT_NAME_COLLISION, __LINE__ );
  365. TestOne( FileName, DEFAULT_DATA_STREAM, EmptySource, ":NonZero", NonZeroTarget, TRUE, STATUS_INVALID_PARAMETER, __LINE__ );
  366. TestOne( FileName, DEFAULT_DATA_STREAM, SmallSource, ":NonZero", NonZeroTarget, FALSE, STATUS_OBJECT_NAME_COLLISION, __LINE__ );
  367. TestOne( FileName, DEFAULT_DATA_STREAM, SmallSource, ":NonZero", NonZeroTarget, TRUE, STATUS_INVALID_PARAMETER, __LINE__ );
  368. TestOne( FileName, DEFAULT_DATA_STREAM, BigSource, ":NonZero", NonZeroTarget, FALSE, STATUS_OBJECT_NAME_COLLISION, __LINE__ );
  369. TestOne( FileName, DEFAULT_DATA_STREAM, BigSource, ":NonZero", NonZeroTarget, TRUE, STATUS_INVALID_PARAMETER, __LINE__ );
  370. // ::$Data to :Empty Succeed if ReplaceIfExists
  371. TestOne( FileName, DEFAULT_DATA_STREAM, EmptySource, ":Empty", EmptyTarget, FALSE, STATUS_OBJECT_NAME_COLLISION, __LINE__ );
  372. TestOne( FileName, DEFAULT_DATA_STREAM, EmptySource, ":Empty", EmptyTarget, TRUE, STATUS_SUCCESS, __LINE__ );
  373. TestOne( FileName, DEFAULT_DATA_STREAM, SmallSource, ":Empty", EmptyTarget, FALSE, STATUS_OBJECT_NAME_COLLISION, __LINE__ );
  374. TestOne( FileName, DEFAULT_DATA_STREAM, SmallSource, ":Empty", EmptyTarget, TRUE, STATUS_SUCCESS, __LINE__ );
  375. TestOne( FileName, DEFAULT_DATA_STREAM, BigSource, ":Empty", EmptyTarget, FALSE, STATUS_OBJECT_NAME_COLLISION, __LINE__ );
  376. TestOne( FileName, DEFAULT_DATA_STREAM, BigSource, ":Empty", EmptyTarget, TRUE, STATUS_SUCCESS, __LINE__ );
  377. // :Test to ::$Data <empty> Succeed if ReplaceIfExists
  378. TestOne( FileName, ":Test", EmptySource, DEFAULT_DATA_STREAM, EmptyTarget, FALSE, STATUS_OBJECT_NAME_COLLISION, __LINE__ );
  379. TestOne( FileName, ":Test", EmptySource, DEFAULT_DATA_STREAM, EmptyTarget, TRUE, STATUS_SUCCESS, __LINE__ );
  380. TestOne( FileName, ":Test", SmallSource, DEFAULT_DATA_STREAM, EmptyTarget, FALSE, STATUS_OBJECT_NAME_COLLISION, __LINE__ );
  381. TestOne( FileName, ":Test", SmallSource, DEFAULT_DATA_STREAM, EmptyTarget, TRUE, STATUS_SUCCESS, __LINE__ );
  382. TestOne( FileName, ":Test", BigSource, DEFAULT_DATA_STREAM, EmptyTarget, FALSE, STATUS_OBJECT_NAME_COLLISION, __LINE__ );
  383. TestOne( FileName, ":Test", BigSource, DEFAULT_DATA_STREAM, EmptyTarget, TRUE, STATUS_SUCCESS, __LINE__ );
  384. // :Test to ::$Data <nonzero> Fail always
  385. TestOne( FileName, ":Test", EmptySource, DEFAULT_DATA_STREAM, NonZeroTarget, FALSE, STATUS_OBJECT_NAME_COLLISION, __LINE__ );
  386. TestOne( FileName, ":Test", EmptySource, DEFAULT_DATA_STREAM, NonZeroTarget, TRUE, STATUS_INVALID_PARAMETER, __LINE__ );
  387. TestOne( FileName, ":Test", SmallSource, DEFAULT_DATA_STREAM, NonZeroTarget, FALSE, STATUS_OBJECT_NAME_COLLISION, __LINE__ );
  388. TestOne( FileName, ":Test", SmallSource, DEFAULT_DATA_STREAM, NonZeroTarget, TRUE, STATUS_INVALID_PARAMETER, __LINE__ );
  389. TestOne( FileName, ":Test", BigSource, DEFAULT_DATA_STREAM, NonZeroTarget, FALSE, STATUS_OBJECT_NAME_COLLISION, __LINE__ );
  390. TestOne( FileName, ":Test", BigSource, DEFAULT_DATA_STREAM, NonZeroTarget, TRUE, STATUS_INVALID_PARAMETER, __LINE__ );
  391. // :Test to :New Succeed
  392. TestOne( FileName, ":Test", EmptySource, ":New", NoTarget, FALSE, STATUS_SUCCESS, __LINE__ );
  393. TestOne( FileName, ":Test", EmptySource, ":New", NoTarget, TRUE, STATUS_SUCCESS, __LINE__ );
  394. TestOne( FileName, ":Test", SmallSource, ":New", NoTarget, FALSE, STATUS_SUCCESS, __LINE__ );
  395. TestOne( FileName, ":Test", SmallSource, ":New", NoTarget, TRUE, STATUS_SUCCESS, __LINE__ );
  396. TestOne( FileName, ":Test", BigSource, ":New", NoTarget, FALSE, STATUS_SUCCESS, __LINE__ );
  397. TestOne( FileName, ":Test", BigSource, ":New", NoTarget, TRUE, STATUS_SUCCESS, __LINE__ );
  398. // :Test to :NonZero Fail always
  399. TestOne( FileName, ":Test", EmptySource, ":New", NonZeroTarget, FALSE, STATUS_OBJECT_NAME_COLLISION, __LINE__ );
  400. TestOne( FileName, ":Test", EmptySource, ":New", NonZeroTarget, TRUE, STATUS_INVALID_PARAMETER, __LINE__ );
  401. TestOne( FileName, ":Test", SmallSource, ":New", NonZeroTarget, FALSE, STATUS_OBJECT_NAME_COLLISION, __LINE__ );
  402. TestOne( FileName, ":Test", SmallSource, ":New", NonZeroTarget, TRUE, STATUS_INVALID_PARAMETER, __LINE__ );
  403. TestOne( FileName, ":Test", BigSource, ":New", NonZeroTarget, FALSE, STATUS_OBJECT_NAME_COLLISION, __LINE__ );
  404. TestOne( FileName, ":Test", BigSource, ":New", NonZeroTarget, TRUE, STATUS_INVALID_PARAMETER, __LINE__ );
  405. // :Test to :Empty Succeed if ReplaceIfExists
  406. TestOne( FileName, ":Test", EmptySource, ":New", EmptyTarget, FALSE, STATUS_OBJECT_NAME_COLLISION, __LINE__ );
  407. TestOne( FileName, ":Test", EmptySource, ":New", EmptyTarget, TRUE, STATUS_SUCCESS, __LINE__ );
  408. TestOne( FileName, ":Test", SmallSource, ":New", EmptyTarget, FALSE, STATUS_OBJECT_NAME_COLLISION, __LINE__ );
  409. TestOne( FileName, ":Test", SmallSource, ":New", EmptyTarget, TRUE, STATUS_SUCCESS, __LINE__ );
  410. TestOne( FileName, ":Test", BigSource, ":New", EmptyTarget, FALSE, STATUS_OBJECT_NAME_COLLISION, __LINE__ );
  411. TestOne( FileName, ":Test", BigSource, ":New", EmptyTarget, TRUE, STATUS_SUCCESS, __LINE__ );
  412. }
  413. int __cdecl
  414. main (
  415. int argc,
  416. char **argv)
  417. {
  418. DbgPrint( "--------------------------------------------\n" );
  419. while (--argc != 0) {
  420. RenameTest( *++argv );
  421. }
  422. DbgPrint( "--------------------------------------------\n" );
  423. return 0;
  424. }