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.

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