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.

1766 lines
51 KiB

  1. #define UNICODE 1
  2. #include <nt.h>
  3. #include <ntrtl.h>
  4. #include <nturtl.h>
  5. #include <ntdddisk.h>
  6. #include <ntddscsi.h>
  7. #include <initguid.h>
  8. #include <mountmgr.h>
  9. #include <ntddramd.h>
  10. #define _NTSCSI_USER_MODE_
  11. #include <scsi.h>
  12. #define PAGE_SIZE 4096
  13. #define ROUND_TO_PAGE_SIZE(_x) (((_x) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
  14. #include <windows.h>
  15. #include <devioctl.h>
  16. #include <setupapi.h>
  17. #include <cfgmgr32.h>
  18. #include <rpc.h>
  19. #include <stdio.h>
  20. #include <stddef.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <sdistructs.h>
  24. #define SECTOR_SIZE 0x200
  25. #define SECTORS_PER_TRACK 0x80
  26. #define TRACKS_PER_CYLINDER 0x10
  27. #define CYLINDER_SIZE (SECTOR_SIZE * SECTORS_PER_TRACK * TRACKS_PER_CYLINDER)
  28. #define arrayof(a) (sizeof(a)/sizeof(a[0]))
  29. typedef struct _RAMCTRL_HEADER {
  30. char Signature[8]; // "ramctrl"
  31. GUID DiskGuid;
  32. ULONG DiskOffset;
  33. ULONG DiskType;
  34. RAMDISK_CREATE_OPTIONS Options;
  35. } RAMCTRL_HEADER, *PRAMCTRL_HEADER;
  36. typedef union _RAMDISK_HEADER {
  37. RAMCTRL_HEADER Ramctrl;
  38. SDI_HEADER Sdi;
  39. } RAMDISK_HEADER, *PRAMDISK_HEADER;
  40. VOID
  41. PrintError(
  42. ULONG ErrorCode
  43. )
  44. {
  45. WCHAR errorBuffer[512];
  46. ULONG count;
  47. count = FormatMessage(
  48. FORMAT_MESSAGE_FROM_SYSTEM,
  49. NULL,
  50. ErrorCode,
  51. 0,
  52. errorBuffer,
  53. arrayof(errorBuffer),
  54. NULL
  55. );
  56. if ( count != 0 ) {
  57. printf( "%ws\n", errorBuffer );
  58. } else {
  59. printf( "Format message failed. Error: %d\n", GetLastError() );
  60. }
  61. return;
  62. } // PrintError
  63. VOID
  64. ListDisks (
  65. HANDLE ControlHandle
  66. )
  67. {
  68. BOOL ok;
  69. WCHAR actualDeviceName[MAX_PATH];
  70. WCHAR foundDeviceName[MAX_PATH];
  71. WCHAR dosDeviceName[MAX_PATH];
  72. WCHAR driveLetterString[3] = L"A:";
  73. BOOL foundRamDisk;
  74. BOOL foundDriveLetter;
  75. LPCGUID interfaceGuid;
  76. GUID foundGuid;
  77. PWSTR guidPtr;
  78. UNICODE_STRING guidString;
  79. GUID diskGuid;
  80. HDEVINFO devinfo;
  81. SP_DEVICE_INTERFACE_DATA interfaceData;
  82. BYTE detailBuffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + (MAX_PATH * sizeof(WCHAR))];
  83. PSP_DEVICE_INTERFACE_DETAIL_DATA interfaceDetailData;
  84. SP_DEVINFO_DATA devinfoData;
  85. DWORD i;
  86. RAMDISK_QUERY_INPUT queryInput;
  87. BYTE queryOutputBuffer[sizeof(RAMDISK_QUERY_OUTPUT) + (MAX_PATH * sizeof(WCHAR))];
  88. PRAMDISK_QUERY_OUTPUT queryOutput;
  89. DWORD returnedLength;
  90. interfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)detailBuffer;
  91. queryOutput = (PRAMDISK_QUERY_OUTPUT)queryOutputBuffer;
  92. interfaceGuid = &RamdiskDiskInterface;
  93. foundRamDisk = FALSE;
  94. do {
  95. devinfo = SetupDiGetClassDevs(
  96. interfaceGuid,
  97. NULL,
  98. NULL,
  99. DIGCF_PRESENT | DIGCF_DEVICEINTERFACE
  100. );
  101. if ( devinfo == NULL ) {
  102. printf( "ListDisks: SetupDiGetClassDevs failed: %d\n", GetLastError() );
  103. return;
  104. }
  105. ZeroMemory( &interfaceData, sizeof(interfaceData) );
  106. interfaceData.cbSize = sizeof(interfaceData);
  107. //
  108. // Enumerate the device interfaces of the class.
  109. //
  110. for (i = 0;
  111. SetupDiEnumDeviceInterfaces( devinfo, NULL, interfaceGuid, i, &interfaceData );
  112. i++ ) {
  113. interfaceDetailData->cbSize = sizeof(*interfaceDetailData);
  114. devinfoData.cbSize = sizeof(devinfoData);
  115. if ( !SetupDiGetDeviceInterfaceDetail(
  116. devinfo,
  117. &interfaceData,
  118. interfaceDetailData,
  119. sizeof(detailBuffer),
  120. NULL,
  121. &devinfoData
  122. ) ) {
  123. //printf( "ListDisks: SetupDiGetDeviceInterfaceDetail failed for item %d. (%d)\n", i, GetLastError() );
  124. wcscpy( interfaceDetailData->DevicePath, L"<couldn't retrieve name>" );
  125. }
  126. //printf( "Enumerated device %ws\n", interfaceDetailData->DevicePath );
  127. if ( !SetupDiGetDeviceRegistryProperty(
  128. devinfo,
  129. &devinfoData,
  130. SPDRP_BUSTYPEGUID,
  131. NULL,
  132. (PBYTE)&foundGuid,
  133. sizeof(foundGuid),
  134. NULL
  135. ) ) {
  136. DWORD error = GetLastError();
  137. //printf( "ListDisks: SetupDiGetDeviceRegistryProperty (bus GUID) failed for %ws: %d\n", interfaceDetailData->DevicePath, error );
  138. continue;
  139. }
  140. if ( memcmp( &foundGuid, &GUID_BUS_TYPE_RAMDISK, sizeof(GUID) ) != 0 ) {
  141. //printf( "ListDisks: skipping non-ramdisk device %ws\n", interfaceDetailData->DevicePath );
  142. continue;
  143. }
  144. if ( !SetupDiGetDeviceRegistryProperty(
  145. devinfo,
  146. &devinfoData,
  147. SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,
  148. NULL,
  149. (PBYTE)actualDeviceName,
  150. sizeof(actualDeviceName),
  151. NULL
  152. ) ) {
  153. DWORD error = GetLastError();
  154. printf( "ListDisks: SetupDiGetDeviceRegistryProperty (name) failed for %ws: %d\n", interfaceDetailData->DevicePath, error );
  155. continue;
  156. }
  157. foundRamDisk = TRUE;
  158. printf( "\n%ws\n", interfaceDetailData->DevicePath );
  159. printf( " Device name: %ws\n", actualDeviceName );
  160. guidPtr = wcschr( actualDeviceName, L'{' );
  161. swprintf( dosDeviceName, L"Ramdisk%ws", guidPtr );
  162. if ( QueryDosDeviceW(dosDeviceName, foundDeviceName, arrayof(foundDeviceName)) ) {
  163. printf( " DosDevice name %ws is assigned to this device\n", dosDeviceName );
  164. } else {
  165. printf( " No DosDevice name was assigned to this device\n" );
  166. }
  167. foundDriveLetter = FALSE;
  168. for ( driveLetterString[0] = 'A';
  169. driveLetterString[0] <= 'Z';
  170. driveLetterString[0]++ ) {
  171. if ( QueryDosDeviceW(driveLetterString, foundDeviceName, arrayof(foundDeviceName)) &&
  172. (_wcsicmp(actualDeviceName, foundDeviceName) == 0) ) {
  173. printf( " Drive letter %ws is assigned to this device\n", driveLetterString );
  174. foundDriveLetter = TRUE;
  175. break;
  176. }
  177. }
  178. if ( !foundDriveLetter ) {
  179. printf( " No letter was assigned to this device\n" );
  180. }
  181. guidString.Buffer = guidPtr;
  182. guidString.Length = (USHORT)(wcslen(guidPtr) * sizeof(WCHAR));
  183. guidString.MaximumLength = guidString.Length;
  184. RtlGUIDFromString( &guidString, &diskGuid );
  185. queryInput.Version = sizeof(RAMDISK_QUERY_INPUT);
  186. queryInput.DiskGuid = diskGuid;
  187. ok = DeviceIoControl(
  188. ControlHandle,
  189. FSCTL_QUERY_RAM_DISK,
  190. &queryInput,
  191. sizeof(queryInput),
  192. queryOutput,
  193. sizeof(queryOutputBuffer),
  194. &returnedLength,
  195. FALSE
  196. );
  197. if ( !ok ) {
  198. DWORD errorCode = GetLastError();
  199. printf( "Error querying RAM disk: %d\n", errorCode );
  200. PrintError( errorCode );
  201. } else {
  202. printf( " RAM disk information:\n" );
  203. if ( queryOutput->DiskType == RAMDISK_TYPE_BOOT_DISK ) {
  204. printf( " Type: boot disk\n" );
  205. printf( " Base page: 0x%x\n", queryOutput->BasePage );
  206. } else {
  207. printf( " Type: %s\n",
  208. queryOutput->DiskType == RAMDISK_TYPE_FILE_BACKED_VOLUME ? "volume" : "disk" );
  209. printf( " File: %ws\n", queryOutput->FileName );
  210. }
  211. printf( " Length: 0x%I64x\n", queryOutput->DiskLength );
  212. printf( " Offset: 0x%x\n", queryOutput->DiskOffset );
  213. if ( queryOutput->DiskType != RAMDISK_TYPE_BOOT_DISK ) {
  214. printf( " View count: 0x%x\n", queryOutput->ViewCount );
  215. printf( " View length: 0x%x\n", queryOutput->ViewLength );
  216. }
  217. printf( " Options: " );
  218. printf( "%s; ", queryOutput->Options.Fixed ? "fixed" : "removable" );
  219. printf( "%s; ", queryOutput->Options.Readonly ? "readonly" : "writeable" );
  220. printf( "%s; ", queryOutput->Options.NoDriveLetter ? "no drive letter" : "drive letter" );
  221. printf( "%s; ", queryOutput->Options.Hidden ? "hidden" : "visible" );
  222. printf( "%s\n", queryOutput->Options.NoDosDevice ? "no DosDevice" : "DosDevice" );
  223. }
  224. }
  225. SetupDiDestroyDeviceInfoList( devinfo );
  226. if ( interfaceGuid == &RamdiskDiskInterface ) {
  227. interfaceGuid = &MOUNTDEV_MOUNTED_DEVICE_GUID;
  228. } else {
  229. break;
  230. }
  231. } while ( TRUE );
  232. if ( !foundRamDisk ) {
  233. printf( "No RAM disks found\n" );
  234. }
  235. return;
  236. } // ListDisks
  237. VOID
  238. FindDisk (
  239. ULONG DiskType,
  240. PUNICODE_STRING DiskGuidString,
  241. BOOL WaitForDeletion
  242. )
  243. {
  244. WCHAR actualDeviceName[MAX_PATH];
  245. WCHAR foundDeviceName[MAX_PATH];
  246. WCHAR dosDeviceName[MAX_PATH];
  247. WCHAR driveLetterString[3] = L"A:";
  248. BOOL found;
  249. LPCGUID interfaceGuid;
  250. HDEVINFO devinfo;
  251. SP_DEVICE_INTERFACE_DATA interfaceData;
  252. BYTE detailBuffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + (MAX_PATH * sizeof(WCHAR))];
  253. PSP_DEVICE_INTERFACE_DETAIL_DATA interfaceDetailData;
  254. SP_DEVINFO_DATA devinfoData;
  255. DWORD i;
  256. interfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)detailBuffer;
  257. swprintf( actualDeviceName, L"\\Device\\Ramdisk%wZ", DiskGuidString );
  258. printf( "Waiting for device %ws to be %s...",
  259. actualDeviceName,
  260. WaitForDeletion ? "deleted" : "ready" );
  261. if ( DiskType == RAMDISK_TYPE_FILE_BACKED_DISK ) {
  262. interfaceGuid = &RamdiskDiskInterface;
  263. } else {
  264. interfaceGuid = &MOUNTDEV_MOUNTED_DEVICE_GUID;
  265. }
  266. found = FALSE;
  267. do {
  268. devinfo = SetupDiGetClassDevs(
  269. interfaceGuid,
  270. NULL,
  271. NULL,
  272. DIGCF_PRESENT | DIGCF_DEVICEINTERFACE
  273. );
  274. if ( devinfo == NULL ) {
  275. printf( "\nFindDisk: SetupDiGetClassDevs failed: %d\n", GetLastError() );
  276. return;
  277. }
  278. ZeroMemory( &interfaceData, sizeof(interfaceData) );
  279. interfaceData.cbSize = sizeof(interfaceData);
  280. //
  281. // Enumerate the device interfaces of the class.
  282. //
  283. for (i = 0;
  284. SetupDiEnumDeviceInterfaces( devinfo, NULL, interfaceGuid, i, &interfaceData );
  285. i++ ) {
  286. interfaceDetailData->cbSize = sizeof(*interfaceDetailData);
  287. devinfoData.cbSize = sizeof(devinfoData);
  288. if ( !SetupDiGetDeviceInterfaceDetail(
  289. devinfo,
  290. &interfaceData,
  291. interfaceDetailData,
  292. sizeof(detailBuffer),
  293. NULL,
  294. &devinfoData
  295. ) ) {
  296. //printf( "\nFindDisk: SetupDiGetDeviceInterfaceDetail failed for item %d. (%d)\n", i, GetLastError() );
  297. wcscpy( interfaceDetailData->DevicePath, L"<couldn't retrieve name>" );
  298. }
  299. //printf( "\nEnumerated device %ws\n", interfaceDetailData->DevicePath );
  300. if ( !SetupDiGetDeviceRegistryProperty(
  301. devinfo,
  302. &devinfoData,
  303. SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,
  304. NULL,
  305. (PBYTE)foundDeviceName,
  306. sizeof(foundDeviceName),
  307. NULL
  308. ) ) {
  309. DWORD error = GetLastError();
  310. //printf( "\nFindDisk: SetupDiGetDeviceRegistryProperty (name) failed for %ws: %d\n", interfaceDetailData->DevicePath, error );
  311. continue;
  312. }
  313. //printf( "\nTarget device %ws\n", foundDeviceName );
  314. if ( _wcsicmp( actualDeviceName, foundDeviceName ) != 0 ) {
  315. continue;
  316. }
  317. found = TRUE;
  318. break;
  319. }
  320. SetupDiDestroyDeviceInfoList( devinfo );
  321. if ( !found ) {
  322. if ( WaitForDeletion ) {
  323. printf( "\nRAM disk is now gone\n" );
  324. return;
  325. }
  326. //printf( "Enumeration failed to find target device; sleeping\n" );
  327. printf( "." );
  328. Sleep( 500 );
  329. } else {
  330. if ( !WaitForDeletion ) {
  331. printf( "\nRAM disk is now ready\n" );
  332. break;
  333. }
  334. //printf( "Enumeration found target device; sleeping\n" );
  335. printf( "." );
  336. Sleep( 500 );
  337. found = FALSE;
  338. }
  339. } while ( TRUE );
  340. if ( found ) {
  341. swprintf( dosDeviceName, L"Ramdisk%wZ", DiskGuidString );
  342. if ( QueryDosDeviceW(dosDeviceName, foundDeviceName, arrayof(foundDeviceName)) ) {
  343. printf( " DosDevice name %ws is assigned to this device\n", dosDeviceName );
  344. } else {
  345. printf( " No DosDevice name was assigned to this device\n" );
  346. }
  347. found = FALSE;
  348. for ( driveLetterString[0] = 'A';
  349. driveLetterString[0] <= 'Z';
  350. driveLetterString[0]++ ) {
  351. if ( QueryDosDeviceW(driveLetterString, foundDeviceName, arrayof(foundDeviceName)) &&
  352. (_wcsicmp(actualDeviceName, foundDeviceName) == 0) ) {
  353. printf( " Drive letter %ws is assigned to this device\n", driveLetterString );
  354. found = TRUE;
  355. break;
  356. }
  357. }
  358. if ( !found ) {
  359. printf( " No letter was assigned to this device\n" );
  360. }
  361. }
  362. return;
  363. } // FindDisk
  364. VOID
  365. FullFilePath (
  366. PWCHAR pwzPath
  367. )
  368. {
  369. WCHAR wzDevPath[512] = L"";
  370. WCHAR wzDosPath[512] = L"";
  371. PWCHAR pwzDosName = wzDosPath;
  372. DWORD dw;
  373. WCHAR c;
  374. dw = GetFullPathNameW(pwzPath, arrayof(wzDosPath), wzDosPath, NULL);
  375. if (0 != dw) {
  376. if (NULL != (pwzDosName = wcschr(wzDosPath, ':'))) {
  377. pwzDosName++;
  378. c = *pwzDosName;
  379. *pwzDosName = '\0';
  380. dw = QueryDosDeviceW(wzDosPath, wzDevPath, arrayof(wzDevPath));
  381. if (0 != dw) {
  382. *pwzDosName = c;
  383. swprintf(pwzPath, L"%ls%ls", wzDevPath, pwzDosName);
  384. }
  385. else {
  386. printf("QueryDosDeviceW(%ls) failed: %d\n", wzDosPath, GetLastError());
  387. PrintError(GetLastError());
  388. }
  389. }
  390. }
  391. }
  392. BOOLEAN
  393. IsDriveLetter (
  394. PWCHAR Name
  395. )
  396. {
  397. if ((((Name[0] >= L'A') && (Name[0] <= L'Z')) ||
  398. ((Name[0] >= L'a') && (Name[0] <= L'z'))) &&
  399. (Name[1] == L':') &&
  400. (Name[2] == 0)) {
  401. return TRUE;
  402. }
  403. return FALSE;
  404. }
  405. VOID
  406. DeleteRamdisk (
  407. IN HANDLE ControlHandle,
  408. IN PWSTR FileName
  409. )
  410. {
  411. BOOL ok;
  412. ULONG errorCode = 0;
  413. ULONG returnedLength = 0;
  414. UNICODE_STRING ustr;
  415. OBJECT_ATTRIBUTES obja;
  416. IO_STATUS_BLOCK iosb;
  417. NTSTATUS status;
  418. HANDLE imageFileHandle;
  419. HANDLE volumeHandle;
  420. RAMDISK_HEADER ramdiskHeader;
  421. UNICODE_STRING guidString;
  422. LARGE_INTEGER offset;
  423. LPCGUID diskGuid;
  424. ULONG diskType;
  425. RAMDISK_QUERY_INPUT queryInput;
  426. RAMDISK_MARK_FOR_DELETION_INPUT markInput;
  427. BYTE queryOutputBuffer[sizeof(RAMDISK_QUERY_OUTPUT) + (MAX_PATH * sizeof(WCHAR))];
  428. PRAMDISK_QUERY_OUTPUT queryOutput;
  429. CONFIGRET cr;
  430. DEVNODE devnode;
  431. WCHAR devinst[MAX_PATH];
  432. PNP_VETO_TYPE vetoType;
  433. WCHAR vetoName[MAX_PATH];
  434. WCHAR foundDeviceName[MAX_PATH];
  435. queryOutput = (PRAMDISK_QUERY_OUTPUT)queryOutputBuffer;
  436. if ( FileName[0] == L'{' ) {
  437. guidString.Buffer = FileName;
  438. guidString.Length = (USHORT)(wcslen(FileName) * sizeof(WCHAR));
  439. guidString.MaximumLength = guidString.Length;
  440. queryInput.Version = sizeof(RAMDISK_QUERY_INPUT);
  441. RtlGUIDFromString( &guidString, &queryInput.DiskGuid );
  442. ok = DeviceIoControl(
  443. ControlHandle,
  444. FSCTL_QUERY_RAM_DISK,
  445. &queryInput,
  446. sizeof(queryInput),
  447. queryOutput,
  448. sizeof(queryOutputBuffer),
  449. &returnedLength,
  450. FALSE
  451. );
  452. if ( !ok ) {
  453. DWORD errorCode = GetLastError();
  454. printf( "Error querying RAM disk: %d\n", errorCode );
  455. PrintError( errorCode );
  456. return;
  457. }
  458. diskGuid = &queryOutput->DiskGuid;
  459. diskType = queryOutput->DiskType;
  460. } else if (IsDriveLetter ( FileName ) ) {
  461. //
  462. // Treat FileName as a drive letter. See if this the supplied
  463. // drive letter corresponds to a ramdisk.
  464. //
  465. if ((QueryDosDeviceW(FileName, foundDeviceName, arrayof(foundDeviceName)) == 0) ||
  466. wcsncmp(foundDeviceName, L"\\Device\\Ramdisk", wcslen(L"\\Device\\Ramdisk"))) {
  467. DWORD errorCode = GetLastError();
  468. printf( "Drive letter \"%ws\" is not assigned to a RAM disk.\n",
  469. FileName);
  470. PrintError( errorCode );
  471. return;
  472. }
  473. guidString.Buffer = wcschr( foundDeviceName, L'{' );
  474. guidString.Length = (USHORT)(wcslen(guidString.Buffer) * sizeof(WCHAR));
  475. guidString.MaximumLength = guidString.Length;
  476. RtlGUIDFromString( &guidString, &queryInput.DiskGuid );
  477. ok = DeviceIoControl(
  478. ControlHandle,
  479. FSCTL_QUERY_RAM_DISK,
  480. &queryInput,
  481. sizeof(queryInput),
  482. queryOutput,
  483. sizeof(queryOutputBuffer),
  484. &returnedLength,
  485. FALSE
  486. );
  487. if ( !ok ) {
  488. DWORD errorCode = GetLastError();
  489. printf( "Error querying RAM disk: %d\n", errorCode );
  490. PrintError( errorCode );
  491. return;
  492. }
  493. diskGuid = &queryOutput->DiskGuid;
  494. diskType = queryOutput->DiskType;
  495. } else {
  496. RtlInitUnicodeString( &ustr, FileName );
  497. InitializeObjectAttributes( &obja, &ustr, OBJ_CASE_INSENSITIVE, NULL, NULL );
  498. status = NtOpenFile(
  499. &imageFileHandle,
  500. SYNCHRONIZE | FILE_READ_DATA | FILE_READ_ATTRIBUTES,
  501. &obja,
  502. &iosb,
  503. FILE_SHARE_READ,
  504. FILE_SYNCHRONOUS_IO_ALERT
  505. );
  506. if ( !NT_SUCCESS(status) ) {
  507. printf( "Can't open target file %ws: %x\n", FileName, status );
  508. errorCode = RtlNtStatusToDosError( status );
  509. PrintError( errorCode );
  510. return;
  511. }
  512. //
  513. // Read and verify the header.
  514. //
  515. offset.QuadPart = 0;
  516. status = NtReadFile(
  517. imageFileHandle,
  518. NULL,
  519. NULL,
  520. NULL,
  521. &iosb,
  522. &ramdiskHeader,
  523. sizeof(ramdiskHeader),
  524. &offset,
  525. NULL
  526. );
  527. if ( !NT_SUCCESS(status) ) {
  528. printf( "Can't read header from target file %ws: %x\n", FileName, status );
  529. errorCode = RtlNtStatusToDosError( status );
  530. PrintError( errorCode );
  531. return;
  532. }
  533. if ( strcmp( ramdiskHeader.Ramctrl.Signature, "ramctrl" ) == 0 ) {
  534. diskGuid = &ramdiskHeader.Ramctrl.DiskGuid;
  535. diskType = ramdiskHeader.Ramctrl.DiskType;
  536. } else if ( strncmp( ramdiskHeader.Sdi.Signature, SDI_SIGNATURE, strlen(SDI_SIGNATURE) ) == 0 ) {
  537. diskGuid = (LPCGUID)ramdiskHeader.Sdi.RuntimeGUID;
  538. diskType = RAMDISK_TYPE_FILE_BACKED_VOLUME;
  539. } else {
  540. printf( "Header in target file not recognized\n" );
  541. return;
  542. }
  543. NtClose( imageFileHandle );
  544. RtlStringFromGUID( diskGuid, &guidString );
  545. }
  546. printf("Attempting to delete \\Device\\Ramdisk%wZ\n", &guidString );
  547. swprintf( devinst, L"\\Device\\Ramdisk%ws", guidString.Buffer );
  548. RtlInitUnicodeString( &ustr, devinst );
  549. InitializeObjectAttributes( &obja, &ustr, OBJ_CASE_INSENSITIVE, NULL, NULL );
  550. status = NtOpenFile(
  551. &volumeHandle,
  552. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  553. &obja,
  554. &iosb,
  555. FILE_SHARE_READ | FILE_SHARE_WRITE,
  556. FILE_SYNCHRONOUS_IO_ALERT
  557. );
  558. if ( !NT_SUCCESS(status) ) {
  559. printf( "Can't open target device %ws: %x\n", devinst, status );
  560. errorCode = RtlNtStatusToDosError( status );
  561. PrintError( errorCode );
  562. return;
  563. }
  564. printf( "Syncing %ws ... ", devinst );
  565. if ( !FlushFileBuffers( volumeHandle ) ) {
  566. errorCode = GetLastError();
  567. // NOTE: [bassamt] FlushFileBuffers can fail with error code
  568. // ERROR_INVALID_FUNCTION if the volume is not formatted.
  569. // NOTE: [brimo] FlushFileBuffers can fail with error code
  570. // ERROR_WRITE_PROTECT if the volume is mounted read-only
  571. if ((errorCode != ERROR_INVALID_FUNCTION) && (errorCode != ERROR_WRITE_PROTECT)) {
  572. printf( "flush failed (%u)\n", errorCode );
  573. PrintError( errorCode );
  574. return;
  575. }
  576. }
  577. if ( !DeviceIoControl(
  578. volumeHandle,
  579. FSCTL_LOCK_VOLUME,
  580. NULL,
  581. 0,
  582. NULL,
  583. 0,
  584. &returnedLength,
  585. NULL
  586. ) ) {
  587. errorCode = GetLastError();
  588. printf( "lock volume failed (%u)\n", errorCode );
  589. PrintError( errorCode );
  590. return;
  591. }
  592. if ( !DeviceIoControl(
  593. volumeHandle,
  594. FSCTL_DISMOUNT_VOLUME,
  595. NULL,
  596. 0,
  597. NULL,
  598. 0,
  599. &returnedLength,
  600. NULL
  601. ) ) {
  602. errorCode = GetLastError();
  603. printf( "dismount volume failed (%u)\n", errorCode );
  604. PrintError( errorCode );
  605. return;
  606. }
  607. printf( "done\n" );
  608. NtClose( volumeHandle );
  609. markInput.Version = sizeof(RAMDISK_MARK_FOR_DELETION_INPUT);
  610. markInput.DiskGuid = *diskGuid;
  611. ok = DeviceIoControl(
  612. ControlHandle,
  613. FSCTL_MARK_RAM_DISK_FOR_DELETION,
  614. &markInput,
  615. sizeof(markInput),
  616. NULL,
  617. 0,
  618. &returnedLength,
  619. FALSE
  620. );
  621. if ( !ok ) {
  622. DWORD errorCode = GetLastError();
  623. printf( "Error marking RAM disk: %d\n", errorCode );
  624. PrintError( errorCode );
  625. return;
  626. }
  627. if ( diskType == RAMDISK_TYPE_FILE_BACKED_DISK ) {
  628. swprintf( devinst, L"Ramdisk\\Ramdisk\\%ws", guidString.Buffer );
  629. } else {
  630. swprintf( devinst, L"Ramdisk\\Ramvolume\\%ws", guidString.Buffer );
  631. }
  632. cr = CM_Locate_DevNode( &devnode, devinst, 0 );
  633. if ( cr != CR_SUCCESS ) {
  634. printf( "Unable to locate devnode: %d\n", cr );
  635. return;
  636. }
  637. cr = CM_Query_And_Remove_SubTree_Ex( devnode, &vetoType, vetoName, MAX_PATH, 0, NULL );
  638. if ( cr != CR_SUCCESS ) {
  639. printf( "Unable to remove devnode: %d\n", cr );
  640. if ( cr == CR_REMOVE_VETOED ) {
  641. printf( " veto type = 0x%x\n", vetoType );
  642. printf( " veto name = %ws\n", vetoName );
  643. }
  644. return;
  645. }
  646. FindDisk( diskType, &guidString, TRUE );
  647. printf( "RAM disk %wZ deleted\n", &guidString );
  648. return;
  649. } // DeleteRamdisk
  650. void
  651. AddBootFilesToSdi(
  652. PWCHAR SdiFile,
  653. PWCHAR StartromFile,
  654. PWCHAR OsloaderFile
  655. )
  656. {
  657. NTSTATUS status;
  658. UNICODE_STRING ustr;
  659. OBJECT_ATTRIBUTES obja;
  660. IO_STATUS_BLOCK iosb;
  661. HANDLE imageFileHandle;
  662. HANDLE startromHandle;
  663. HANDLE osloaderHandle;
  664. WCHAR dataFileName[512];
  665. FILE_STANDARD_INFORMATION fileInfo;
  666. FILE_ALLOCATION_INFORMATION allocInfo;
  667. SDI_HEADER sdiHeader;
  668. LARGE_INTEGER offset;
  669. ULONGLONG diskOffset;
  670. ULONGLONG diskLength;
  671. ULONGLONG startromOffset;
  672. ULONGLONG startromLength;
  673. ULONGLONG startromLengthAligned;
  674. ULONGLONG osloaderOffset;
  675. ULONGLONG osloaderLength;
  676. ULONGLONG osloaderLengthAligned;
  677. ULONGLONG finalFileLength;
  678. ULONG errorCode = 0;
  679. PUCHAR buffer;
  680. printf( "Adding boot files to SDI file %ws\n", SdiFile );
  681. RtlInitUnicodeString( &ustr, SdiFile );
  682. InitializeObjectAttributes( &obja, &ustr, OBJ_CASE_INSENSITIVE, NULL, NULL );
  683. status = NtOpenFile(
  684. &imageFileHandle,
  685. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA | FILE_READ_ATTRIBUTES,
  686. &obja,
  687. &iosb,
  688. 0,
  689. FILE_SYNCHRONOUS_IO_ALERT
  690. );
  691. if ( !NT_SUCCESS(status) ) {
  692. printf( "Can't open target file %ws: %x\n", SdiFile, status );
  693. errorCode = RtlNtStatusToDosError( status );
  694. PrintError( errorCode );
  695. return;
  696. }
  697. //
  698. // Read and verify the header.
  699. //
  700. offset.QuadPart = 0;
  701. status = NtReadFile(
  702. imageFileHandle,
  703. NULL,
  704. NULL,
  705. NULL,
  706. &iosb,
  707. &sdiHeader,
  708. sizeof(sdiHeader),
  709. &offset,
  710. NULL
  711. );
  712. if ( !NT_SUCCESS(status) ) {
  713. printf( "Can't read header from target file %ws: %x\n", SdiFile, status );
  714. errorCode = RtlNtStatusToDosError( status );
  715. PrintError( errorCode );
  716. return;
  717. }
  718. if ( strncmp( sdiHeader.Signature, SDI_SIGNATURE, strlen(SDI_SIGNATURE) ) != 0 ) {
  719. printf( "Header in target file not recognized\n" );
  720. return;
  721. }
  722. diskOffset = sdiHeader.ToC[0].llOffset.LowPart;
  723. diskLength = sdiHeader.ToC[0].llSize.QuadPart;
  724. startromOffset = ROUND_TO_PAGE_SIZE( diskOffset + diskLength );
  725. //
  726. // Get the length of startrom.com.
  727. //
  728. wcscpy( dataFileName, StartromFile );
  729. FullFilePath( dataFileName );
  730. RtlInitUnicodeString( &ustr, dataFileName );
  731. InitializeObjectAttributes( &obja, &ustr, OBJ_CASE_INSENSITIVE, NULL, NULL );
  732. status = NtOpenFile(
  733. &startromHandle,
  734. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA | FILE_READ_ATTRIBUTES,
  735. &obja,
  736. &iosb,
  737. 0,
  738. FILE_SYNCHRONOUS_IO_ALERT
  739. );
  740. if ( !NT_SUCCESS(status) ) {
  741. printf( "Can't open startrom file %ws: %x\n", dataFileName, status );
  742. errorCode = RtlNtStatusToDosError( status );
  743. PrintError( errorCode );
  744. return;
  745. }
  746. status = NtQueryInformationFile(
  747. startromHandle,
  748. &iosb,
  749. &fileInfo,
  750. sizeof(fileInfo),
  751. FileStandardInformation
  752. );
  753. if ( !NT_SUCCESS(status) ) {
  754. printf( "Can't query info for startrom file %ws: %x\n", dataFileName, status );
  755. errorCode = RtlNtStatusToDosError( status );
  756. PrintError( errorCode );
  757. return;
  758. }
  759. startromLength = fileInfo.EndOfFile.QuadPart;
  760. startromLengthAligned = ROUND_TO_PAGE_SIZE( startromLength );
  761. osloaderOffset = startromOffset + startromLengthAligned;
  762. //
  763. // Get the length of osloader.exe.
  764. //
  765. wcscpy( dataFileName, OsloaderFile );
  766. FullFilePath( dataFileName );
  767. RtlInitUnicodeString( &ustr, dataFileName );
  768. InitializeObjectAttributes( &obja, &ustr, OBJ_CASE_INSENSITIVE, NULL, NULL );
  769. status = NtOpenFile(
  770. &osloaderHandle,
  771. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA | FILE_READ_ATTRIBUTES,
  772. &obja,
  773. &iosb,
  774. 0,
  775. FILE_SYNCHRONOUS_IO_ALERT
  776. );
  777. if ( !NT_SUCCESS(status) ) {
  778. printf( "Can't open osloader file %ws: %x\n", dataFileName, status );
  779. errorCode = RtlNtStatusToDosError( status );
  780. PrintError( errorCode );
  781. return;
  782. }
  783. status = NtQueryInformationFile(
  784. osloaderHandle,
  785. &iosb,
  786. &fileInfo,
  787. sizeof(fileInfo),
  788. FileStandardInformation
  789. );
  790. if ( !NT_SUCCESS(status) ) {
  791. printf( "Can't query info for osloader file %ws: %x\n", dataFileName, status );
  792. errorCode = RtlNtStatusToDosError( status );
  793. PrintError( errorCode );
  794. return;
  795. }
  796. osloaderLength = fileInfo.EndOfFile.QuadPart;
  797. osloaderLengthAligned = ROUND_TO_PAGE_SIZE( startromLength );
  798. finalFileLength = osloaderOffset + osloaderLengthAligned;
  799. //
  800. // Truncate the file at the end of the disk image, then extend it back.
  801. //
  802. printf( " truncating SDI file at end of ramdisk image %I64d [0x%I64x]\n",
  803. startromOffset, startromOffset );
  804. allocInfo.AllocationSize.QuadPart = startromOffset;
  805. status = NtSetInformationFile(
  806. imageFileHandle,
  807. &iosb,
  808. &allocInfo,
  809. sizeof(allocInfo),
  810. FileAllocationInformation
  811. );
  812. if ( !NT_SUCCESS(status) ) {
  813. printf( "Can't set allocation size for image file %ws: %x\n", SdiFile, status );
  814. errorCode = RtlNtStatusToDosError( status );
  815. PrintError( errorCode );
  816. return;
  817. }
  818. allocInfo.AllocationSize.QuadPart = finalFileLength;
  819. status = NtSetInformationFile(
  820. imageFileHandle,
  821. &iosb,
  822. &allocInfo,
  823. sizeof(allocInfo),
  824. FileAllocationInformation
  825. );
  826. if ( !NT_SUCCESS(status) ) {
  827. printf( "Can't set allocation size for image file %ws: %x\n", SdiFile, status );
  828. errorCode = RtlNtStatusToDosError( status );
  829. PrintError( errorCode );
  830. return;
  831. }
  832. //
  833. // Copy startrom into the image file.
  834. //
  835. printf( " adding boot file %ws, length %I64d [0x%I64x]\n",
  836. StartromFile, startromLength, startromLength );
  837. buffer = malloc( (ULONG)startromLength );
  838. offset.QuadPart = 0;
  839. status = NtReadFile(
  840. startromHandle,
  841. NULL,
  842. NULL,
  843. NULL,
  844. &iosb,
  845. buffer,
  846. (ULONG)startromLength,
  847. &offset,
  848. NULL
  849. );
  850. if ( !NT_SUCCESS(status) ) {
  851. printf( "Can't read from startrom file %ws: %x\n", SdiFile, status );
  852. errorCode = RtlNtStatusToDosError( status );
  853. PrintError( errorCode );
  854. return;
  855. }
  856. offset.QuadPart = startromOffset;
  857. status = NtWriteFile(
  858. imageFileHandle,
  859. NULL,
  860. NULL,
  861. NULL,
  862. &iosb,
  863. buffer,
  864. (ULONG)startromLength,
  865. &offset,
  866. NULL
  867. );
  868. if ( !NT_SUCCESS(status) ) {
  869. printf( "Can't write startrom to image file %ws: %x\n", SdiFile, status );
  870. errorCode = RtlNtStatusToDosError( status );
  871. PrintError( errorCode );
  872. return;
  873. }
  874. free( buffer );
  875. //
  876. // Copy osloader into the image file.
  877. //
  878. printf( " adding load file %ws, length %I64d [0x%I64x]\n",
  879. OsloaderFile, osloaderLength, osloaderLength );
  880. buffer = malloc( (ULONG)osloaderLength );
  881. offset.QuadPart = 0;
  882. status = NtReadFile(
  883. osloaderHandle,
  884. NULL,
  885. NULL,
  886. NULL,
  887. &iosb,
  888. buffer,
  889. (ULONG)osloaderLength,
  890. &offset,
  891. NULL
  892. );
  893. if ( !NT_SUCCESS(status) ) {
  894. printf( "Can't read from osloader file %ws: %x\n", SdiFile, status );
  895. errorCode = RtlNtStatusToDosError( status );
  896. PrintError( errorCode );
  897. return;
  898. }
  899. offset.QuadPart = osloaderOffset;
  900. status = NtWriteFile(
  901. imageFileHandle,
  902. NULL,
  903. NULL,
  904. NULL,
  905. &iosb,
  906. buffer,
  907. (ULONG)osloaderLength,
  908. &offset,
  909. NULL
  910. );
  911. if ( !NT_SUCCESS(status) ) {
  912. printf( "Can't write osloader to image file %ws: %x\n", SdiFile, status );
  913. errorCode = RtlNtStatusToDosError( status );
  914. PrintError( errorCode );
  915. return;
  916. }
  917. free( buffer );
  918. //
  919. // Update the header.
  920. //
  921. printf( " updating header\n" );
  922. sdiHeader.liBootCodeOffset.QuadPart = startromOffset;
  923. sdiHeader.liBootCodeSize.QuadPart = startromLength;
  924. sdiHeader.ToC[1].dwType = SDI_BLOBTYPE_BOOT;
  925. sdiHeader.ToC[1].llOffset.QuadPart = startromOffset;
  926. sdiHeader.ToC[1].llSize.QuadPart = startromLength;
  927. sdiHeader.ToC[2].dwType = SDI_BLOBTYPE_LOAD;
  928. sdiHeader.ToC[2].llOffset.QuadPart = osloaderOffset;
  929. sdiHeader.ToC[2].llSize.QuadPart = osloaderLength;
  930. offset.QuadPart = 0;
  931. status = NtWriteFile(
  932. imageFileHandle,
  933. NULL,
  934. NULL,
  935. NULL,
  936. &iosb,
  937. &sdiHeader,
  938. sizeof(sdiHeader),
  939. &offset,
  940. NULL
  941. );
  942. if ( !NT_SUCCESS(status) ) {
  943. printf( "Can't write header to image file %ws: %x\n", SdiFile, status );
  944. errorCode = RtlNtStatusToDosError( status );
  945. PrintError( errorCode );
  946. return;
  947. }
  948. printf( " done\n" );
  949. NtClose( osloaderHandle );
  950. NtClose( startromHandle );
  951. NtClose( imageFileHandle );
  952. return;
  953. }
  954. int
  955. __cdecl
  956. wmain (
  957. ULONG argc,
  958. WCHAR *argv[])
  959. {
  960. BOOL ok;
  961. HANDLE controlHandle = NULL;
  962. PUCHAR dataBuffer = NULL;
  963. UCHAR buffer[2048];
  964. WCHAR string[25];
  965. ULONG length = 0;
  966. ULONG errorCode = 0;
  967. ULONG returned = 0;
  968. ULONG sizeInMb;
  969. ULONG diskType;
  970. WCHAR fileName[512];
  971. ULONG desiredSize;
  972. ULONG actualSize;
  973. ULONG controlSize;
  974. UNICODE_STRING ustr;
  975. OBJECT_ATTRIBUTES obja;
  976. IO_STATUS_BLOCK iosb;
  977. NTSTATUS status;
  978. PRAMDISK_CREATE_INPUT createInput;
  979. ULONG arg;
  980. BOOL fNeedHelp = FALSE;
  981. HANDLE imageFileHandle;
  982. LARGE_INTEGER allocation;
  983. BOOL fixed;
  984. BOOL readonly;
  985. BOOL delete = FALSE;
  986. ULONG diskNumber;
  987. BOOL noDriveLetter;
  988. BOOL hidden;
  989. BOOL noDosDevice;
  990. BOOL ignoreHeader;
  991. BOOL bootDisk;
  992. BOOL useSdi;
  993. ULONG diskOffset;
  994. RAMDISK_HEADER ramdiskHeader;
  995. UNICODE_STRING guidString;
  996. LARGE_INTEGER offset;
  997. PWCHAR startromFile = NULL;
  998. PWCHAR osloaderFile = NULL;
  999. sizeInMb = 64;
  1000. diskType = RAMDISK_TYPE_FILE_BACKED_VOLUME;
  1001. fileName[0] = 0;
  1002. fixed = TRUE;
  1003. readonly = FALSE;
  1004. noDriveLetter = FALSE;
  1005. hidden = FALSE;
  1006. noDosDevice = FALSE;
  1007. ignoreHeader = FALSE;
  1008. bootDisk = FALSE;
  1009. diskOffset = PAGE_SIZE;
  1010. useSdi = FALSE;
  1011. for ( arg = 1; arg < argc; arg++ ) {
  1012. // process options
  1013. if ( (argv[arg][0] == '-') || (argv[arg][0] == '/') ) {
  1014. PWCHAR argn = argv[arg]+1; // Argument name
  1015. PWCHAR argp = argn; // Argument parameter
  1016. while ( *argp && (*argp != ':') ) {
  1017. argp++;
  1018. }
  1019. if ( *argp == ':' ) {
  1020. *argp++ = '\0';
  1021. }
  1022. switch ( argn[0] ) {
  1023. case 's': // Size in MB
  1024. case 'S':
  1025. if ( _wcsicmp( argn, L"sdi" ) == 0 ) {
  1026. useSdi = TRUE;
  1027. } else {
  1028. sizeInMb = _wtoi(argp);
  1029. }
  1030. break;
  1031. case 'a':
  1032. if ( _wcsicmp( argn, L"addboot" ) == 0 ) {
  1033. if ( arg+2 < argc ) {
  1034. startromFile = argv[++arg];
  1035. osloaderFile = argv[++arg];
  1036. } else {
  1037. printf( "Missing startrom/osloader file name\n" );
  1038. fNeedHelp = TRUE;
  1039. arg = argc - 1;
  1040. }
  1041. } else {
  1042. printf( "Unknown argument: %s\n", argv[arg] );
  1043. fNeedHelp = TRUE;
  1044. arg = argc - 1;
  1045. }
  1046. case 'i': // ignore header
  1047. case 'I':
  1048. ignoreHeader = TRUE;
  1049. break;
  1050. case 'b': // use boot disk GUID
  1051. case 'B':
  1052. bootDisk = TRUE;
  1053. break;
  1054. case 'd': // disk offset
  1055. case 'D':
  1056. diskOffset = _wtol(argp);
  1057. break;
  1058. case 'o':
  1059. case 'O': // Readonly, or options
  1060. if ( *argp ) {
  1061. BOOL sense = TRUE;
  1062. do {
  1063. if ( *argp == '-' ) {
  1064. sense = FALSE;
  1065. argp++;
  1066. } else if ( *argp == '+' ) {
  1067. sense = TRUE;
  1068. argp++;
  1069. }
  1070. switch ( *argp ) {
  1071. case 'v':
  1072. case 'V':
  1073. diskType = sense ? RAMDISK_TYPE_FILE_BACKED_VOLUME :
  1074. RAMDISK_TYPE_FILE_BACKED_DISK;
  1075. break;
  1076. case 'r':
  1077. case 'R':
  1078. readonly = sense;
  1079. break;
  1080. case 'f':
  1081. case 'F':
  1082. fixed = sense;
  1083. break;
  1084. case 'l':
  1085. case 'L':
  1086. noDriveLetter = !sense;
  1087. break;
  1088. case 'h':
  1089. case 'H':
  1090. hidden = sense;
  1091. break;
  1092. case 'd':
  1093. case 'D':
  1094. noDosDevice = !sense;
  1095. break;
  1096. }
  1097. sense = TRUE;
  1098. argp++;
  1099. } while ( *argp );
  1100. } else {
  1101. readonly = TRUE;
  1102. }
  1103. break;
  1104. case 'x': // Delete device, not create
  1105. case 'X':
  1106. delete = TRUE;
  1107. break;
  1108. case 'h': // Help
  1109. case 'H':
  1110. case '?':
  1111. fNeedHelp = TRUE;
  1112. arg = argc - 1;
  1113. break;
  1114. default:
  1115. printf( "Unknown argument: %s\n", argv[arg] );
  1116. fNeedHelp = TRUE;
  1117. arg = argc - 1;
  1118. break;
  1119. }
  1120. } else {
  1121. wcscpy( fileName, argv[arg] );
  1122. }
  1123. }
  1124. if ( fNeedHelp ) {
  1125. printf(
  1126. "Usage (to create):\n"
  1127. " ramdiskctrl [options] win32_disk_file_name\n"
  1128. "or (to delete)\n"
  1129. " ramdiskctrl -x win32_disk_file_name | {guid} | drive_letter:\n"
  1130. "\n"
  1131. "Options:\n"
  1132. " -s:N Set size of disk image in MB (default: 64)\n"
  1133. " -i Ignore ramctrl header in existing ramdisk file.\n"
  1134. " -d:N Ramdisk offset from start of file. (default: 4096).\n"
  1135. " -o:options Options: (use - or + to set sense)\n"
  1136. " v Volume (vs. disk) (default: volume)\n"
  1137. " r Readonly (default: writeable)\n"
  1138. " f Fixed (default: removable)\n"
  1139. " l Assign drive letter (default: assign)\n"
  1140. " h Hidden (default: visible)\n"
  1141. " d Assign DosDevice name (default: assign)\n"
  1142. " -h or -? Display this help text.\n"
  1143. );
  1144. return 1;
  1145. }
  1146. if ( !delete ||
  1147. ((fileName[0] != L'{') &&
  1148. !IsDriveLetter(fileName))) {
  1149. FullFilePath( fileName );
  1150. }
  1151. if ( startromFile != NULL ) {
  1152. AddBootFilesToSdi( fileName, startromFile, osloaderFile );
  1153. return 0;
  1154. }
  1155. wcscpy( string, L"\\device\\ramdisk" );
  1156. RtlInitUnicodeString( &ustr, string );
  1157. InitializeObjectAttributes( &obja, &ustr, OBJ_CASE_INSENSITIVE, NULL, NULL );
  1158. //printf( "Opening %ws\n", string );
  1159. status = NtOpenFile(
  1160. &controlHandle,
  1161. GENERIC_READ | GENERIC_WRITE,
  1162. &obja,
  1163. &iosb,
  1164. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1165. FILE_OPEN
  1166. );
  1167. if ( !NT_SUCCESS(status) ) {
  1168. printf( "Error opening control device %ws. Error: %x\n", string, status );
  1169. errorCode = RtlNtStatusToDosError( status );
  1170. PrintError( errorCode );
  1171. return 1;
  1172. }
  1173. if ( delete ) {
  1174. //
  1175. // Delete the disk.
  1176. //
  1177. DeleteRamdisk( controlHandle, fileName );
  1178. return 0;
  1179. }
  1180. if ( fileName[0] == 0 ) {
  1181. //
  1182. // Just list the disks.
  1183. //
  1184. ListDisks( controlHandle );
  1185. return 0;
  1186. }
  1187. //
  1188. // If SDI, force the disk type to emulated volume, etc.
  1189. //
  1190. if ( useSdi ) {
  1191. diskType = RAMDISK_TYPE_FILE_BACKED_VOLUME;
  1192. bootDisk = FALSE;
  1193. fixed = TRUE;
  1194. readonly = FALSE;
  1195. noDriveLetter = FALSE;
  1196. hidden = FALSE;
  1197. noDosDevice = FALSE;
  1198. }
  1199. //
  1200. // Create the disk.
  1201. //
  1202. desiredSize = sizeInMb * 1024 * 1024;
  1203. actualSize = ((desiredSize + CYLINDER_SIZE - 1) / CYLINDER_SIZE) * CYLINDER_SIZE;
  1204. if ( actualSize != desiredSize ) {
  1205. printf( "Using rounded-up disk size of %d instead of %d\n", actualSize, desiredSize );
  1206. }
  1207. controlSize = sizeof(RAMDISK_CREATE_INPUT) + (wcslen(fileName) * sizeof(WCHAR));
  1208. createInput = malloc( controlSize );
  1209. if ( createInput == NULL ) {
  1210. printf( "Can't allocate %d bytes for RAMDISK_CREATE_INPUT struct\n", controlSize );
  1211. return 1;
  1212. }
  1213. RtlZeroMemory( createInput, controlSize );
  1214. createInput->Version = sizeof(RAMDISK_CREATE_INPUT);
  1215. wcscpy( createInput->FileName, fileName );
  1216. allocation.QuadPart = actualSize + diskOffset;
  1217. RtlInitUnicodeString( &ustr, fileName );
  1218. InitializeObjectAttributes( &obja, &ustr, OBJ_CASE_INSENSITIVE, NULL, NULL );
  1219. status = NtCreateFile(
  1220. &imageFileHandle,
  1221. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA | FILE_READ_ATTRIBUTES,
  1222. &obja,
  1223. &iosb,
  1224. &allocation,
  1225. 0,
  1226. 0,
  1227. FILE_OPEN_IF,
  1228. FILE_SYNCHRONOUS_IO_ALERT,
  1229. NULL,
  1230. 0
  1231. );
  1232. if ( !NT_SUCCESS(status) ) {
  1233. printf( "Can't create target file %ws: %x\n", fileName, status );
  1234. errorCode = RtlNtStatusToDosError( status );
  1235. PrintError( errorCode );
  1236. return 1;
  1237. }
  1238. if ( iosb.Information == FILE_CREATED || ignoreHeader ) {
  1239. if ( !bootDisk ) {
  1240. UuidCreate( &createInput->DiskGuid );
  1241. } else {
  1242. createInput->DiskGuid = RamdiskBootDiskGuid;
  1243. }
  1244. createInput->DiskOffset = diskOffset;
  1245. createInput->DiskLength = actualSize;
  1246. createInput->DiskType = diskType;
  1247. createInput->Options.Fixed = (BOOLEAN)fixed;
  1248. createInput->Options.Readonly = (BOOLEAN)readonly;
  1249. createInput->Options.NoDriveLetter = (BOOLEAN)noDriveLetter;
  1250. createInput->Options.Hidden = (BOOLEAN)hidden;
  1251. createInput->Options.NoDosDevice = (BOOLEAN)noDosDevice;
  1252. }
  1253. if ( iosb.Information == FILE_CREATED ) {
  1254. UCHAR byte = 0;
  1255. printf( "Created target file %ws\n", fileName );
  1256. //
  1257. // Extend the file to the desired length.
  1258. //
  1259. offset.QuadPart = actualSize + diskOffset - 1;
  1260. status = NtWriteFile(
  1261. imageFileHandle,
  1262. NULL,
  1263. NULL,
  1264. NULL,
  1265. &iosb,
  1266. &byte,
  1267. 1,
  1268. &offset,
  1269. NULL
  1270. );
  1271. if ( !NT_SUCCESS(status) ) {
  1272. printf( "Can't write to target file %ws: %x\n", fileName, status );
  1273. errorCode = RtlNtStatusToDosError( status );
  1274. PrintError( errorCode );
  1275. return 0;
  1276. }
  1277. //
  1278. // Write the header.
  1279. //
  1280. RtlZeroMemory( &ramdiskHeader, sizeof(ramdiskHeader) );
  1281. if ( !useSdi ) {
  1282. strcpy( ramdiskHeader.Ramctrl.Signature, "ramctrl" );
  1283. ramdiskHeader.Ramctrl.DiskGuid = createInput->DiskGuid;
  1284. ramdiskHeader.Ramctrl.DiskOffset = diskOffset;
  1285. ramdiskHeader.Ramctrl.DiskType = diskType;
  1286. ramdiskHeader.Ramctrl.Options = createInput->Options;
  1287. } else {
  1288. memcpy( ramdiskHeader.Sdi.Signature, SDI_SIGNATURE, strlen(SDI_SIGNATURE) );
  1289. ramdiskHeader.Sdi.dwMDBType = SDI_MDBTYPE_VOLATILE;
  1290. memcpy( ramdiskHeader.Sdi.RuntimeGUID, &createInput->DiskGuid, sizeof(GUID) );
  1291. ramdiskHeader.Sdi.dwPageAlignmentFactor = SDI_DEFAULTPAGEALIGNMENT;
  1292. ramdiskHeader.Sdi.ToC[0].dwType = SDI_BLOBTYPE_PART;
  1293. ramdiskHeader.Sdi.ToC[0].llOffset.QuadPart = diskOffset;
  1294. ramdiskHeader.Sdi.ToC[0].llSize.QuadPart = createInput->DiskLength;
  1295. }
  1296. offset.QuadPart = 0;
  1297. status = NtWriteFile(
  1298. imageFileHandle,
  1299. NULL,
  1300. NULL,
  1301. NULL,
  1302. &iosb,
  1303. &ramdiskHeader,
  1304. sizeof(ramdiskHeader),
  1305. &offset,
  1306. NULL
  1307. );
  1308. if ( !NT_SUCCESS(status) ) {
  1309. printf( "Can't write to target file %ws: %x\n", fileName, status );
  1310. errorCode = RtlNtStatusToDosError( status );
  1311. PrintError( errorCode );
  1312. return 0;
  1313. }
  1314. } else {
  1315. FILE_STANDARD_INFORMATION fileInfo;
  1316. printf( "Using existing target file %ws\n", fileName );
  1317. //
  1318. // Get the length of the existing file.
  1319. //
  1320. status = NtQueryInformationFile(
  1321. imageFileHandle,
  1322. &iosb,
  1323. &fileInfo,
  1324. sizeof(fileInfo),
  1325. FileStandardInformation
  1326. );
  1327. if ( !NT_SUCCESS(status) ) {
  1328. printf( "Can't query info for target file %ws: %x\n", fileName, status );
  1329. errorCode = RtlNtStatusToDosError( status );
  1330. PrintError( errorCode );
  1331. return 0;
  1332. }
  1333. //
  1334. // Read and verify the header.
  1335. //
  1336. if ( !ignoreHeader ) {
  1337. offset.QuadPart = 0;
  1338. status = NtReadFile(
  1339. imageFileHandle,
  1340. NULL,
  1341. NULL,
  1342. NULL,
  1343. &iosb,
  1344. &ramdiskHeader,
  1345. sizeof(ramdiskHeader),
  1346. &offset,
  1347. NULL
  1348. );
  1349. if ( !NT_SUCCESS(status) ) {
  1350. printf( "Can't read header from target file %ws: %x\n", fileName, status );
  1351. errorCode = RtlNtStatusToDosError( status );
  1352. PrintError( errorCode );
  1353. return 0;
  1354. }
  1355. if ( strcmp( ramdiskHeader.Ramctrl.Signature, "ramctrl" ) == 0 ) {
  1356. createInput->DiskGuid = ramdiskHeader.Ramctrl.DiskGuid;
  1357. createInput->DiskOffset = ramdiskHeader.Ramctrl.DiskOffset;
  1358. createInput->DiskLength = fileInfo.EndOfFile.QuadPart - createInput->DiskOffset;
  1359. diskType = createInput->DiskType = ramdiskHeader.Ramctrl.DiskType;
  1360. createInput->Options = ramdiskHeader.Ramctrl.Options;
  1361. } else if ( strncmp( ramdiskHeader.Sdi.Signature, SDI_SIGNATURE, strlen(SDI_SIGNATURE) ) == 0 ) {
  1362. memcpy( &createInput->DiskGuid, ramdiskHeader.Sdi.RuntimeGUID, sizeof(GUID) );
  1363. createInput->DiskOffset = ramdiskHeader.Sdi.ToC[0].llOffset.LowPart;
  1364. createInput->DiskLength = ramdiskHeader.Sdi.ToC[0].llSize.QuadPart;
  1365. diskType = createInput->DiskType = RAMDISK_TYPE_FILE_BACKED_VOLUME;
  1366. bootDisk = FALSE;
  1367. fixed = TRUE;
  1368. readonly = FALSE;
  1369. noDriveLetter = FALSE;
  1370. hidden = FALSE;
  1371. noDosDevice = FALSE;
  1372. createInput->Options.Fixed = (BOOLEAN)fixed;
  1373. createInput->Options.Readonly = (BOOLEAN)readonly;
  1374. createInput->Options.NoDriveLetter = (BOOLEAN)noDriveLetter;
  1375. createInput->Options.Hidden = (BOOLEAN)hidden;
  1376. createInput->Options.NoDosDevice = (BOOLEAN)noDosDevice;
  1377. } else {
  1378. printf( "Header in target file not recognized\n" );
  1379. return 0;
  1380. }
  1381. }
  1382. }
  1383. NtClose( imageFileHandle );
  1384. RtlStringFromGUID( &createInput->DiskGuid, &guidString );
  1385. printf( "Creating RAM disk:\n" );
  1386. printf( " File: %ws\n", createInput->FileName );
  1387. printf( " Type: %s\n",
  1388. createInput->DiskType == RAMDISK_TYPE_FILE_BACKED_VOLUME ? "volume" : "disk" );
  1389. printf( " Length: 0x%I64x\n", createInput->DiskLength );
  1390. printf( " Offset: 0x%x\n", createInput->DiskOffset );
  1391. printf( " GUID: %wZ\n", &guidString );
  1392. printf( " Options:" );
  1393. printf( "%s; ", createInput->Options.Fixed ? "fixed" : "removable" );
  1394. printf( "%s; ", createInput->Options.Readonly ? "readonly" : "writeable" );
  1395. printf( "%s; ", createInput->Options.NoDriveLetter ? "no drive letter" : "drive letter" );
  1396. printf( "%s; ", createInput->Options.Hidden ? "hidden" : "visible" );
  1397. printf( "%s\n", createInput->Options.NoDosDevice ? "no DosDevice" : "DosDevice" );
  1398. ok = DeviceIoControl(
  1399. controlHandle,
  1400. FSCTL_CREATE_RAM_DISK,
  1401. createInput,
  1402. controlSize,
  1403. NULL,
  1404. 0,
  1405. &returned,
  1406. FALSE
  1407. );
  1408. if ( !ok ) {
  1409. errorCode = GetLastError();
  1410. printf( "Error creating RAM disk: %d\n", errorCode );
  1411. PrintError( errorCode );
  1412. return 1;
  1413. }
  1414. printf( "RAM disk created\n" );
  1415. FindDisk( createInput->DiskType, &guidString, FALSE );
  1416. return 0;
  1417. } // wmain