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.

1792 lines
50 KiB

  1. /*++
  2. Copyright (c) 1993-1994 Microsoft Corporation
  3. Module Name:
  4. fmifs.c
  5. Abstract:
  6. This module contains the set of routines that work with the fmifs.dll
  7. Author:
  8. Bob Rinne (bobri) 11/15/93
  9. Environment:
  10. User process.
  11. Notes:
  12. Revision History:
  13. --*/
  14. #include "fdisk.h"
  15. #include "shellapi.h"
  16. #include "fmifs.h"
  17. #include <string.h>
  18. #include <stdio.h>
  19. //
  20. // defines unique to this module
  21. //
  22. #define FS_CANCELUPDATE (WM_USER + 0)
  23. #define FS_FINISHED (WM_USER + 1)
  24. BOOLEAN
  25. FmIfsCallback(
  26. IN FMIFS_PACKET_TYPE PacketType,
  27. IN DWORD PacketLength,
  28. IN PVOID PacketData
  29. );
  30. //
  31. // Externals needed for IFS Dll support (format and label)
  32. //
  33. HINSTANCE IfsDllHandle = NULL;
  34. PFMIFS_FORMAT_ROUTINE FormatRoutine = NULL;
  35. PFMIFS_SETLABEL_ROUTINE LabelRoutine = NULL;
  36. #ifdef DOUBLE_SPACE_SUPPORT_INCLUDED
  37. PFMIFS_DOUBLESPACE_CREATE_ROUTINE DblSpaceCreateRoutine = NULL;
  38. PFMIFS_DOUBLESPACE_MOUNT_ROUTINE DblSpaceMountRoutine = NULL;
  39. PFMIFS_DOUBLESPACE_DELETE_ROUTINE DblSpaceDeleteRoutine = NULL;
  40. PFMIFS_DOUBLESPACE_DISMOUNT_ROUTINE DblSpaceDismountRoutine = NULL;
  41. PFMIFS_DOUBLESPACE_QUERY_INFO_ROUTINE DblSpaceQueryInfoRoutine = NULL;
  42. BOOLEAN DoubleSpaceSupported = TRUE;
  43. #endif
  44. // HACK HACK - clean this up if it works.
  45. #define SELECTED_REGION(i) (SelectedDS[i]->RegionArray[SelectedRG[i]])
  46. #define MaxMembersInFtSet 32
  47. extern DWORD SelectionCount;
  48. extern PDISKSTATE SelectedDS[MaxMembersInFtSet];
  49. extern ULONG SelectedRG[MaxMembersInFtSet];
  50. VOID
  51. setUnicode(
  52. char *astring,
  53. WCHAR *wstring
  54. )
  55. /*++
  56. Routine Description:
  57. Convert an ansii string to Unicode. Internal routine to fmifs module.
  58. Arguments:
  59. astring - ansii string to convert to Unicode
  60. wstring - resulting string location
  61. Return Value:
  62. None
  63. --*/
  64. {
  65. int len = lstrlen(astring)+1;
  66. MultiByteToWideChar( CP_ACP, 0, astring, len, wstring, len );
  67. }
  68. BOOL
  69. LoadIfsDll(
  70. VOID
  71. )
  72. /*++
  73. Routine Description:
  74. This routine will determine if the IFS Dll needs to be loaded. If
  75. so, it will load it and locate the format and label routines in the
  76. dll.
  77. Arguments:
  78. None
  79. Return Value:
  80. TRUE if Dll is loaded and the routines needed have been found
  81. FALSE if something fails
  82. --*/
  83. {
  84. if (FormatRoutine) {
  85. // Library is already loaded and the routines needed
  86. // have been located.
  87. return TRUE;
  88. }
  89. IfsDllHandle = LoadLibrary(TEXT("fmifs.dll"));
  90. if (IfsDllHandle == (HANDLE)NULL) {
  91. // FMIFS not available.
  92. return FALSE;
  93. }
  94. // Library is loaded. Locate the two routines needed by
  95. // Disk Administrator.
  96. FormatRoutine = (PVOID)GetProcAddress(IfsDllHandle, "Format");
  97. LabelRoutine = (PVOID)GetProcAddress(IfsDllHandle, "SetLabel");
  98. if (!FormatRoutine || !LabelRoutine) {
  99. // something didn't get found so shut down all accesses
  100. // to the library by insuring FormatRoutine is NULL
  101. FreeLibrary(IfsDllHandle);
  102. FormatRoutine = NULL;
  103. return FALSE;
  104. }
  105. #ifdef DOUBLE_SPACE_SUPPORT_INCLUDED
  106. DblSpaceMountRoutine = (PVOID)GetProcAddress(IfsDllHandle, "DoubleSpaceMount");
  107. DblSpaceDismountRoutine = (PVOID)GetProcAddress(IfsDllHandle, "DoubleSpaceDismount");
  108. DblSpaceCreateRoutine = (PVOID)GetProcAddress(IfsDllHandle, "DoubleSpaceCreate");
  109. DblSpaceDeleteRoutine = (PVOID)GetProcAddress(IfsDllHandle, "DoubleSpaceDelete");
  110. DblSpaceQueryInfoRoutine = (PVOID)GetProcAddress(IfsDllHandle, "FmifsQueryDriveInformation");
  111. if (!DblSpaceMountRoutine || !DblSpaceDismountRoutine || !DblSpaceQueryInfoRoutine) {
  112. // didn't get all of the DoubleSpace support routines
  113. // Allow format and label, just don't do DoubleSpace
  114. DoubleSpaceSupported = FALSE;
  115. }
  116. if (DblSpaceCreateRoutine && DblSpaceDeleteRoutine) {
  117. // Everything is there for read/write double space support.
  118. // This will change certain dialogs to allow creation and
  119. // deletion of double space volumes.
  120. IsFullDoubleSpace = TRUE;
  121. }
  122. #endif
  123. return TRUE;
  124. }
  125. VOID
  126. UnloadIfsDll(
  127. VOID
  128. )
  129. /*++
  130. Routine Description:
  131. This routine will free the FmIfs DLL if it was loaded.
  132. Arguments:
  133. None
  134. Return Value:
  135. None
  136. --*/
  137. {
  138. if (FormatRoutine) {
  139. FreeLibrary(IfsDllHandle);
  140. FormatRoutine = NULL;
  141. IfsDllHandle = NULL;
  142. LabelRoutine = NULL;
  143. #ifdef DOUBLE_SPACE_SUPPORT_INCLUDED
  144. DblSpaceDismountRoutine = NULL;
  145. DblSpaceMountRoutine = NULL;
  146. DblSpaceCreateRoutine = NULL;
  147. DblSpaceDeleteRoutine = NULL;
  148. #endif
  149. }
  150. }
  151. PFORMAT_PARAMS ParamsForCallBack = NULL;
  152. BOOLEAN
  153. FmIfsCallback(
  154. IN FMIFS_PACKET_TYPE PacketType,
  155. IN DWORD PacketLength,
  156. IN PVOID PacketData
  157. )
  158. /*++
  159. Routine Description:
  160. This routine gets callbacks from fmifs.dll regarding
  161. progress and status of the ongoing format or doublespace
  162. create. It runs in the same thread as the format or create,
  163. which is a separate thread from the "cancel" button. If
  164. the user hits "cancel", this routine notices on the next
  165. callback and cancels the format or double space create.
  166. Arguments:
  167. [PacketType] -- an fmifs packet type
  168. [PacketLength] -- length of the packet data
  169. [PacketData] -- data associated with the packet
  170. Return Value:
  171. TRUE if the fmifs activity should continue, FALSE if the
  172. activity should halt immediately. Thus, we return FALSE if
  173. the user has hit "cancel" and we wish fmifs to clean up and
  174. return from the Format() entrypoint call.
  175. --*/
  176. {
  177. PFORMAT_PARAMS formatParams = ParamsForCallBack;
  178. HWND hDlg = formatParams->DialogHwnd;
  179. // Quit if told to do so..
  180. if (formatParams->Cancel) {
  181. formatParams->Result = MSG_FORMAT_CANCELLED;
  182. return FALSE;
  183. }
  184. switch (PacketType) {
  185. case FmIfsPercentCompleted:
  186. PostMessage(hDlg,
  187. FS_CANCELUPDATE,
  188. ((PFMIFS_PERCENT_COMPLETE_INFORMATION)PacketData)->PercentCompleted,
  189. 0);
  190. break;
  191. case FmIfsFormatReport:
  192. formatParams->TotalSpace = ((PFMIFS_FORMAT_REPORT_INFORMATION)PacketData)->KiloBytesTotalDiskSpace;
  193. formatParams->SpaceAvailable = ((PFMIFS_FORMAT_REPORT_INFORMATION)PacketData)->KiloBytesAvailable;
  194. break;
  195. case FmIfsIncompatibleFileSystem:
  196. formatParams->Result = MSG_INCOMPATIBLE_FILE_SYSTEM;
  197. break;
  198. case FmIfsInsertDisk:
  199. break;
  200. case FmIfsFormattingDestination:
  201. break;
  202. case FmIfsIncompatibleMedia:
  203. formatParams->Result = MSG_INCOMPATIBLE_MEDIA;
  204. break;
  205. case FmIfsAccessDenied:
  206. formatParams->Result = MSG_FORMAT_ACCESS_DENIED;
  207. break;
  208. case FmIfsMediaWriteProtected:
  209. formatParams->Result = MSG_WRITE_PROTECTED;
  210. break;
  211. case FmIfsCantLock:
  212. formatParams->Result = MSG_FORMAT_CANT_LOCK;
  213. break;
  214. case FmIfsBadLabel:
  215. formatParams->Result = MSG_BAD_LABEL;
  216. break;
  217. case FmIfsCantQuickFormat:
  218. formatParams->Result = MSG_CANT_QUICK_FORMAT;
  219. break;
  220. case FmIfsIoError:
  221. formatParams->Result = MSG_IO_ERROR;
  222. break;
  223. case FmIfsFinished:
  224. PostMessage(hDlg,
  225. FS_FINISHED,
  226. 0,
  227. 0);
  228. return FALSE;
  229. break;
  230. #ifdef DOUBLE_SPACE_SUPPORT_INCLUDED
  231. case FmIfsDblspaceCreateFailed:
  232. formatParams->Result = MSG_CANT_CREATE_DBLSPACE;
  233. break;
  234. case FmIfsDblspaceMountFailed:
  235. formatParams->Result = MSG_CANT_MOUNT_DBLSPACE;
  236. break;
  237. case FmIfsDblspaceDriveLetterFailed:
  238. formatParams->Result = MSG_DBLSPACE_LETTER_FAILED;
  239. break;
  240. case FmIfsDblspaceCreated:
  241. // Save the name of the double space file.
  242. if (formatParams->DblspaceFileName = (PWSTR) Malloc(PacketLength)) {
  243. memcpy(formatParams->DblspaceFileName, PacketData, PacketLength);
  244. }
  245. break;
  246. case FmIfsDblspaceMounted:
  247. break;
  248. #endif
  249. default:
  250. break;
  251. }
  252. return (formatParams->Result) ? FALSE : TRUE;
  253. }
  254. #ifdef DOUBLE_SPACE_SUPPORT_INCLUDED
  255. ULONG MountDismountResult;
  256. #define MOUNT_DISMOUNT_SUCCESS 0
  257. BOOLEAN
  258. FmIfsMountDismountCallback(
  259. IN FMIFS_PACKET_TYPE PacketType,
  260. IN DWORD PacketLength,
  261. IN PVOID PacketData
  262. )
  263. /*++
  264. Routine Description:
  265. This routine gets callbacks from fmifs.dll regarding
  266. progress and status of the ongoing format or doublespace
  267. Arguments:
  268. [PacketType] -- an fmifs packet type
  269. [PacketLength] -- length of the packet data
  270. [PacketData] -- data associated with the packet
  271. Return Value:
  272. TRUE if the fmifs activity should continue, FALSE if the
  273. activity should halt immediately. Thus, we return FALSE if
  274. the user has hit "cancel" and we wish fmifs to clean up and
  275. return from the Format() entrypoint call.
  276. --*/
  277. {
  278. switch (PacketType) {
  279. case FmIfsDblspaceMounted:
  280. MountDismountResult = MOUNT_DISMOUNT_SUCCESS;
  281. break;
  282. }
  283. return TRUE;
  284. }
  285. #endif
  286. VOID
  287. FormatVolume(
  288. IN PVOID ThreadParameter
  289. )
  290. /*++
  291. Routine Description:
  292. This routine converts the strings in the formatParams structure
  293. and calls the fmifs routines to perform the format.
  294. It assumes it is called by a separate thread and will exit the
  295. thread on completion of the format.
  296. Arguments:
  297. ThreadParameter - a pointer to the FORMAT_PARAMS structure
  298. Return Value:
  299. None
  300. --*/
  301. {
  302. PFORMAT_PARAMS formatParams = (PFORMAT_PARAMS) ThreadParameter;
  303. PPERSISTENT_REGION_DATA regionData;
  304. DWORD index;
  305. WCHAR unicodeLabel[100],
  306. unicodeFsType[20],
  307. driveLetter[4];
  308. // The fmifs interface doesn't allow for a context parameter
  309. // therefore the formatparams must be passed through an external.
  310. ParamsForCallBack = formatParams;
  311. // set up a unicode drive letter.
  312. regionData = (PPERSISTENT_REGION_DATA) formatParams->RegionData;
  313. driveLetter[1] = L':';
  314. driveLetter[2] = 0;
  315. driveLetter[0] = (WCHAR) regionData->DriveLetter;
  316. // convert label to unicode
  317. setUnicode(formatParams->Label,
  318. unicodeLabel);
  319. // convert filesystem type to unicode
  320. for (index = 0;
  321. unicodeFsType[index] = (WCHAR)(formatParams->FileSystem[index]);
  322. index++) {
  323. // operation done in for loop
  324. }
  325. (*FormatRoutine)(driveLetter,
  326. FmMediaUnknown,
  327. unicodeFsType,
  328. unicodeLabel,
  329. (BOOLEAN)formatParams->QuickFormat,
  330. &FmIfsCallback);
  331. // Set the synchronization event to inform the windisk thread
  332. // that this is complete and all handles have been closed.
  333. formatParams->ThreadIsDone = 1;
  334. ExitThread(0L);
  335. }
  336. #ifdef DOUBLE_SPACE_SUPPORT_INCLUDED
  337. VOID
  338. FmIfsCreateDblspace(
  339. IN PVOID ThreadParameter
  340. )
  341. /*++
  342. Routine Description:
  343. This routine converts the strings in the formatParams structure
  344. and calls the fmifs routines to perform the double space create.
  345. It assumes it is called by a separate thread and will exit the
  346. thread on completion of the create.
  347. Arguments:
  348. ThreadParameter - a pointer to the FORMAT_PARAMS structure
  349. Return Value:
  350. None
  351. --*/
  352. {
  353. PFORMAT_PARAMS formatParams = (PFORMAT_PARAMS) ThreadParameter;
  354. PPERSISTENT_REGION_DATA regionData;
  355. DWORD index;
  356. UCHAR letter;
  357. WCHAR unicodeLabel[100],
  358. newDriveLetter[4],
  359. driveLetter[4];
  360. // The fmifs interface doesn't allow for a context parameter
  361. // therefore the formatparams must be passed through an external.
  362. ParamsForCallBack = formatParams;
  363. // set up a unicode drive letter.
  364. regionData = (PPERSISTENT_REGION_DATA) formatParams->RegionData;
  365. driveLetter[1] = L':';
  366. driveLetter[2] = 0;
  367. driveLetter[0] = (WCHAR) regionData->DriveLetter;
  368. // set up the new letter
  369. newDriveLetter[1] = L':';
  370. newDriveLetter[2] = 0;
  371. // Choose the first available. This should come from the dialog
  372. // newDriveLetter[0] = (WCHAR) formatParams->NewLetter;
  373. for (letter='C'; letter <= 'Z'; letter++) {
  374. if (DriveLetterIsAvailable((CHAR)letter)) {
  375. newDriveLetter[0] = (WCHAR) letter;
  376. break;
  377. }
  378. }
  379. // convert label to unicode
  380. setUnicode(formatParams->Label,
  381. unicodeLabel);
  382. (*DblSpaceCreateRoutine)(driveLetter,
  383. formatParams->SpaceAvailable * 1024 * 1024,
  384. unicodeLabel,
  385. newDriveLetter,
  386. &FmIfsCallback);
  387. ExitThread(0L);
  388. }
  389. BOOL
  390. FmIfsDismountDblspace(
  391. IN CHAR DriveLetter
  392. )
  393. /*++
  394. Routine Description:
  395. Convert the name provided into unicode and call the
  396. FmIfs support routine.
  397. Arguments:
  398. DriveLetter - the drive letter to dismount.
  399. Return Value:
  400. TRUE - it worked.
  401. --*/
  402. {
  403. WCHAR unicodeLetter[4];
  404. ULONG index;
  405. unicodeLetter[0] = (WCHAR) DriveLetter;
  406. unicodeLetter[1] = (WCHAR) ':';
  407. unicodeLetter[2] = 0;
  408. // The only way to communicate with the fmifs callback
  409. // is through global externals.
  410. MountDismountResult = MSG_CANT_DISMOUNT_DBLSPACE;
  411. (*DblSpaceDismountRoutine)(unicodeLetter, &FmIfsMountDismountCallback);
  412. return MountDismountResult;
  413. }
  414. BOOL
  415. FmIfsMountDblspace(
  416. IN PCHAR FileName,
  417. IN CHAR HostDrive,
  418. IN CHAR NewDrive
  419. )
  420. /*++
  421. Routine Description:
  422. Convert the arguments into unicode characters and
  423. call the FmIfs support routine to mount the double
  424. space volume.
  425. Arguments:
  426. FileName - ASCII file name (i.e. dblspace.xxx)
  427. HostDrive - Drive drive letter containing double space volume
  428. NewDrive - Drive letter to be assigned to the volume
  429. Return Value:
  430. TRUE it worked.
  431. --*/
  432. {
  433. WCHAR wideFileName[40];
  434. WCHAR wideHostDrive[4];
  435. WCHAR wideNewDrive[4];
  436. ULONG index;
  437. // convert the double space file name.
  438. for (index = 0; wideFileName[index] = (WCHAR) FileName[index]; index++) {
  439. // all work done in for expression
  440. }
  441. // convert the drive names.
  442. wideNewDrive[1] = wideHostDrive[1] = (WCHAR) ':';
  443. wideNewDrive[2] = wideHostDrive[2] = 0;
  444. wideNewDrive[0] = (WCHAR) NewDrive;
  445. wideHostDrive[0] = (WCHAR) HostDrive;
  446. // The only way to communicate with the fmifs callback
  447. // is through global externals.
  448. MountDismountResult = MSG_CANT_MOUNT_DBLSPACE;
  449. (*DblSpaceMountRoutine)(wideHostDrive,
  450. wideFileName,
  451. wideNewDrive,
  452. &FmIfsMountDismountCallback);
  453. return MountDismountResult;
  454. }
  455. BOOLEAN
  456. FmIfsQueryInformation(
  457. IN PWSTR DosDriveName,
  458. OUT PBOOLEAN IsRemovable,
  459. OUT PBOOLEAN IsFloppy,
  460. OUT PBOOLEAN IsCompressed,
  461. OUT PBOOLEAN Error,
  462. OUT PWSTR NtDriveName,
  463. IN ULONG MaxNtDriveNameLength,
  464. OUT PWSTR CvfFileName,
  465. IN ULONG MaxCvfFileNameLength,
  466. OUT PWSTR HostDriveName,
  467. IN ULONG MaxHostDriveNameLength
  468. )
  469. /*++
  470. Routine Description:
  471. Call through the pointer to the routine in the fmifs dll.
  472. Arguments:
  473. Same as the Fmifs routine in the DLL.
  474. Return Value:
  475. --*/
  476. {
  477. if (!DblSpaceQueryInfoRoutine) {
  478. return FALSE;
  479. }
  480. return (*DblSpaceQueryInfoRoutine)(DosDriveName,
  481. IsRemovable,
  482. IsFloppy,
  483. IsCompressed,
  484. Error,
  485. NtDriveName,
  486. MaxNtDriveNameLength,
  487. CvfFileName,
  488. MaxCvfFileNameLength,
  489. HostDriveName,
  490. MaxHostDriveNameLength);
  491. }
  492. #endif
  493. BOOL
  494. CancelDlgProc(
  495. IN HWND hDlg,
  496. IN UINT uMsg,
  497. IN WPARAM wParam,
  498. IN LPARAM lParam
  499. )
  500. /*++
  501. Routine Description:
  502. Dialog procedure for the modeless progress & cancel dialog
  503. Two main purposes here:
  504. 1. if the user chooses CANCEL we set bCancel to TRUE
  505. which will end the PeekMessage background processing loop
  506. 2. handle the private FS_CANCELUPDATE message and draw
  507. a "gas gauge" indication of how far the background job
  508. has progressed
  509. Arguments:
  510. standard Windows dialog procedure
  511. Return Values:
  512. standard Windows dialog procedure
  513. --*/
  514. {
  515. static DWORD percentDrawn;
  516. static RECT rectGG; // GasGauge rectangle
  517. static BOOL captionIsLoaded;
  518. static PFORMAT_PARAMS formatParams;
  519. TCHAR title[100],
  520. templateString[100];
  521. switch (uMsg) {
  522. case WM_INITDIALOG: {
  523. PPERSISTENT_REGION_DATA regionData;
  524. HANDLE threadHandle;
  525. DWORD threadId;
  526. HWND hwndGauge = GetDlgItem(hDlg, IDC_GASGAUGE);
  527. // set up the dialog handle in the parameter block so the
  528. // call back routine can communicate with this routine
  529. // and initialize static variables.
  530. formatParams = (PFORMAT_PARAMS) lParam;
  531. formatParams->DialogHwnd = hDlg;
  532. regionData = (PPERSISTENT_REGION_DATA) formatParams->RegionData;
  533. percentDrawn = 0;
  534. captionIsLoaded = FALSE;
  535. // Set the caption string.
  536. LoadString(hModule, IDS_FORMAT_TITLE, templateString, sizeof(templateString)/sizeof(TCHAR));
  537. wsprintf(title,
  538. templateString,
  539. regionData->DriveLetter);
  540. SetWindowText(hDlg, title);
  541. #ifdef DOUBLE_SPACE_SUPPORT_INCLUDED
  542. if (formatParams->DoubleSpace) {
  543. // start the double space create thread
  544. threadHandle = CreateThread(NULL,
  545. 0,
  546. (LPTHREAD_START_ROUTINE) FmIfsCreateDblspace,
  547. (LPVOID) formatParams,
  548. (DWORD) 0,
  549. (LPDWORD) &threadId);
  550. } else {
  551. #endif
  552. // start the format thread
  553. threadHandle = CreateThread(NULL,
  554. 0,
  555. (LPTHREAD_START_ROUTINE) FormatVolume,
  556. (LPVOID) formatParams,
  557. (DWORD) 0,
  558. (LPDWORD) &threadId);
  559. #ifdef DOUBLE_SPACE_SUPPORT_INCLUDED
  560. }
  561. #endif
  562. if (!threadHandle) {
  563. // can't do it now.
  564. formatParams->Result = MSG_COULDNT_CREATE_THREAD;
  565. EndDialog(hDlg, FALSE);
  566. return TRUE;
  567. }
  568. // no need to keep the handle around.
  569. CloseHandle(threadHandle);
  570. // Get the coordinates of the gas gauge static control rectangle,
  571. // and convert them to dialog client area coordinates
  572. GetClientRect(hwndGauge, &rectGG);
  573. ClientToScreen(hwndGauge, (LPPOINT)&rectGG.left);
  574. ClientToScreen(hwndGauge, (LPPOINT)&rectGG.right);
  575. ScreenToClient(hDlg, (LPPOINT)&rectGG.left);
  576. ScreenToClient(hDlg, (LPPOINT)&rectGG.right);
  577. return TRUE;
  578. }
  579. case WM_COMMAND:
  580. switch (wParam) {
  581. case IDCANCEL:
  582. formatParams->Result = MSG_FORMAT_CANCELLED;
  583. formatParams->Cancel = TRUE;
  584. EndDialog(hDlg, FALSE);
  585. }
  586. return TRUE;
  587. case WM_PAINT: {
  588. INT width = rectGG.right - rectGG.left;
  589. INT height = rectGG.bottom - rectGG.top;
  590. INT nDivideRects;
  591. HDC hDC;
  592. PAINTSTRUCT ps;
  593. TCHAR buffer[100];
  594. SIZE size;
  595. INT xText,
  596. yText,
  597. byteCount;
  598. RECT rectDone,
  599. rectLeftToDo;
  600. // The gas gauge is drawn by drawing a text string stating
  601. // what percentage of the job is done into the middle of
  602. // the gas gauge rectangle, and by separating that rectangle
  603. // into two parts: rectDone (the left part, filled in blue)
  604. // and rectLeftToDo(the right part, filled in white).
  605. // nDivideRects is the x coordinate that divides these two rects.
  606. //
  607. // The text in the blue rectangle is drawn white, and vice versa
  608. // This is easy to do with ExtTextOut()!
  609. hDC = BeginPaint(hDlg, &ps);
  610. // If formatting quick, set this display
  611. if (!captionIsLoaded) {
  612. UINT resourceId = IDS_PERCENTCOMPLETE;
  613. if (formatParams->QuickFormat) {
  614. resourceId = IDS_QUICK_FORMAT;
  615. }
  616. #ifdef DOUBLE_SPACE_SUPPORT_INCLUDED
  617. if (formatParams->DoubleSpace) {
  618. resourceId = IDS_CREATING_DBLSPACE;
  619. }
  620. #endif
  621. LoadString(hModule,
  622. resourceId,
  623. buffer,
  624. sizeof(buffer)/sizeof(TCHAR));
  625. if (!formatParams->QuickFormat) {
  626. SetDlgItemText(hDlg, IDC_TEXT, buffer);
  627. }
  628. captionIsLoaded = TRUE;
  629. }
  630. if (formatParams->QuickFormat) {
  631. nDivideRects = 0;
  632. byteCount = lstrlen(buffer);
  633. } else {
  634. byteCount = wsprintf(buffer, TEXT("%3d%%"), percentDrawn);
  635. nDivideRects = (width * percentDrawn) / 100;
  636. }
  637. GetTextExtentPoint(hDC, buffer, lstrlen(buffer), &size);
  638. xText = rectGG.left + (width - size.cx) / 2;
  639. yText = rectGG.top + (height - size.cy) / 2;
  640. // Paint in the "done so far" rectangle of the gas
  641. // gauge with blue background and white text
  642. SetRect(&rectDone,
  643. rectGG.left,
  644. rectGG.top,
  645. rectGG.left + nDivideRects,
  646. rectGG.bottom);
  647. SetTextColor(hDC, RGB(255, 255, 255));
  648. SetBkColor(hDC, RGB(0, 0, 255));
  649. ExtTextOut(hDC,
  650. xText,
  651. yText,
  652. ETO_CLIPPED | ETO_OPAQUE,
  653. &rectDone,
  654. buffer,
  655. byteCount/sizeof(TCHAR),
  656. NULL);
  657. // Paint in the "still left to do" rectangle of the gas
  658. // gauge with white background and blue text
  659. SetRect(&rectLeftToDo,
  660. rectGG.left + nDivideRects,
  661. rectGG.top,
  662. rectGG.right,
  663. rectGG.bottom);
  664. SetTextColor(hDC, RGB(0, 0, 255));
  665. SetBkColor(hDC, RGB(255, 255, 255));
  666. ExtTextOut(hDC,
  667. xText,
  668. yText,
  669. ETO_CLIPPED | ETO_OPAQUE,
  670. &rectLeftToDo,
  671. buffer,
  672. byteCount/sizeof(TCHAR),
  673. NULL);
  674. EndPaint(hDlg, &ps);
  675. return TRUE;
  676. }
  677. case FS_CANCELUPDATE:
  678. // wParam = % completed
  679. percentDrawn = (INT)wParam;
  680. InvalidateRect(hDlg, &rectGG, TRUE);
  681. UpdateWindow(hDlg);
  682. return TRUE;
  683. case FS_FINISHED:
  684. EndDialog(hDlg, TRUE);
  685. return TRUE;
  686. default:
  687. return FALSE;
  688. }
  689. }
  690. INT
  691. LabelDlgProc(
  692. IN HWND hDlg,
  693. IN UINT wMsg,
  694. IN WPARAM wParam,
  695. IN LONG lParam)
  696. /*++
  697. Routine Description:
  698. This routine manages the label dialog.
  699. Upon completion of the dialog it will end the dialog with a result of
  700. TRUE to indicate that all is set up for the label operation. FALSE if
  701. the label operation has been cancelled by the user.
  702. Arguments:
  703. Standard Windows dialog procedure.
  704. Return Value:
  705. Standard Windows dialog procedure.
  706. --*/
  707. {
  708. static PLABEL_PARAMS labelParams;
  709. static PREGION_DESCRIPTOR regionDescriptor;
  710. static PPERSISTENT_REGION_DATA regionData;
  711. char text[100];
  712. TCHAR uniText[100];
  713. int labelSize;
  714. TCHAR title[100],
  715. templateString[100];
  716. switch (wMsg) {
  717. case WM_INITDIALOG:
  718. labelParams = (PLABEL_PARAMS) lParam;
  719. regionDescriptor = labelParams->RegionDescriptor;
  720. regionData = PERSISTENT_DATA(regionDescriptor);
  721. // Set the caption string.
  722. //
  723. LoadString(hModule, IDS_LABEL_TITLE, templateString, sizeof(templateString)/sizeof(TCHAR));
  724. wsprintf(title,
  725. templateString,
  726. regionData->DriveLetter);
  727. SetWindowText(hDlg, title);
  728. // Convert the volume label into the proper type for windows.
  729. wsprintf(text, "%ws", regionData->VolumeLabel);
  730. UnicodeHack(text, uniText);
  731. SetDlgItemText(hDlg, IDC_NAME, uniText);
  732. return TRUE;
  733. case WM_COMMAND:
  734. switch (wParam) {
  735. case FD_IDHELP:
  736. DialogHelp(HC_DM_DLG_LABEL);
  737. break;
  738. case IDCANCEL:
  739. EndDialog(hDlg, FALSE);
  740. break;
  741. case IDOK:
  742. labelSize = GetDlgItemText(hDlg, IDC_NAME, text, 100);
  743. UnicodeHack(text, labelParams->NewLabel);
  744. EndDialog(hDlg, TRUE);
  745. break;
  746. }
  747. break;
  748. }
  749. return FALSE;
  750. }
  751. #define NUM_FSTYPES 2
  752. #define MAX_FSTYPENAME_SIZE 6
  753. // HPFS is not supported -- therefore commented out.
  754. TCHAR *FsTypes[NUM_FSTYPES + 1] = { "NTFS",
  755. /* "HPFS", */
  756. "FAT" };
  757. WCHAR *UnicodeFsTypes[NUM_FSTYPES] = { L"NTFS",
  758. /* L"HPFS", */
  759. L"FAT" };
  760. INT
  761. FormatDlgProc(
  762. IN HWND hDlg,
  763. IN UINT wMsg,
  764. IN WPARAM wParam,
  765. IN LONG lParam)
  766. /*++
  767. Routine Description:
  768. This routine manages the format dialog. Upon completion it ends the
  769. dialog with a result value of TRUE to indicate that the format operation
  770. is to take place. FALSE is the result if the user cancels out of the
  771. dialog.
  772. Arguments:
  773. Standard Windows dialog procedure.
  774. Return Value:
  775. Standard Windows dialog procedure.
  776. --*/
  777. {
  778. static HWND hwndCombo;
  779. static PFORMAT_PARAMS formatParams;
  780. static PREGION_DESCRIPTOR regionDescriptor;
  781. static PPERSISTENT_REGION_DATA regionData;
  782. char text[40];
  783. TCHAR uniText[40];
  784. INT i;
  785. DWORD selection;
  786. BOOL quickFormat = FALSE;
  787. HWND hwndButton;
  788. TCHAR title[100],
  789. templateString[100];
  790. UNREFERENCED_PARAMETER(lParam);
  791. switch (wMsg) {
  792. case WM_INITDIALOG: {
  793. PWSTR typeName = NULL,
  794. volumeLabel = NULL;
  795. WCHAR driveLetter = L' ';
  796. // since the format params are static reset the quick format boolean.
  797. formatParams = (PFORMAT_PARAMS) lParam;
  798. formatParams->QuickFormat = FALSE;
  799. // get format params, set static values and
  800. // get information about the volume
  801. hwndCombo = GetDlgItem(hDlg, IDC_FSTYPE);
  802. regionDescriptor = formatParams->RegionDescriptor;
  803. DetermineRegionInfo(regionDescriptor,
  804. &typeName,
  805. &volumeLabel,
  806. &driveLetter);
  807. regionData = PERSISTENT_DATA(regionDescriptor);
  808. // Set the caption string.
  809. LoadString(hModule, IDS_FORMAT_TITLE, templateString, sizeof(templateString)/sizeof(TCHAR));
  810. wsprintf(title,
  811. templateString,
  812. regionData->DriveLetter);
  813. SetWindowText(hDlg, title);
  814. // Convert the volume label into the proper type for windows
  815. // and set default values.
  816. wsprintf(text, "%ws", regionData->VolumeLabel);
  817. UnicodeHack(text, uniText);
  818. SetDlgItemText(hDlg, IDC_NAME, uniText);
  819. CheckDlgButton(hDlg, IDC_VERIFY, quickFormat);
  820. SendDlgItemMessage(hDlg, IDOK, EM_SETSEL, 0, -1);
  821. // If this volume is a mirror or stripe with parity,
  822. // disable Quick Format.
  823. if (regionData->FtObject != NULL &&
  824. (regionData->FtObject->Set->Type == Mirror ||
  825. regionData->FtObject->Set->Type == StripeWithParity)) {
  826. hwndButton = GetDlgItem(hDlg, IDC_VERIFY);
  827. if (hwndButton != NULL) {
  828. EnableWindow(hwndButton, FALSE);
  829. }
  830. }
  831. selection = 0;
  832. if (IsDiskRemovable[regionDescriptor->Disk]) {
  833. // If removable, start from the bottom of the list so FAT is first.
  834. // Load the available File system types.
  835. for (i = NUM_FSTYPES - 1; i >= 0; i--) {
  836. // Fill the drop down list.
  837. SendMessage(hwndCombo, CB_ADDSTRING, 0, (LONG)FsTypes[i]);
  838. }
  839. } else {
  840. // Load the available File system types.
  841. for (i = 0; i < NUM_FSTYPES; i++) {
  842. // While filling in the drop down, determine which FS
  843. // this volume is already formated for and make it the
  844. // default (if not found, NTFS is the default).
  845. if (wcscmp(typeName, UnicodeFsTypes[i]) == 0) {
  846. selection = i;
  847. }
  848. // set the FS type into the dialog.
  849. SendMessage(hwndCombo, CB_ADDSTRING, 0, (LONG)FsTypes[i]);
  850. }
  851. }
  852. SendMessage(hwndCombo, CB_SETCURSEL, selection, 0);
  853. return TRUE;
  854. break;
  855. }
  856. case WM_COMMAND:
  857. switch (wParam) {
  858. case FD_IDHELP:
  859. DialogHelp(HC_DM_DLG_FORMAT);
  860. break;
  861. case IDCANCEL:
  862. EndDialog(hDlg, FALSE);
  863. break;
  864. case IDOK: {
  865. int labelSize;
  866. // pull the parameters from the dialog
  867. // and return with success.
  868. selection = SendMessage(hwndCombo, CB_GETCURSEL, 0, 0);
  869. SendMessage(hwndCombo,
  870. CB_GETLBTEXT,
  871. selection,
  872. (LONG)formatParams->FileSystem);
  873. labelSize = GetDlgItemText(hDlg,
  874. IDC_NAME,
  875. (LPTSTR) formatParams->Label,
  876. 100);
  877. if (IsDlgButtonChecked(hDlg, IDC_VERIFY)) {
  878. formatParams->QuickFormat = TRUE;
  879. }
  880. EndDialog(hDlg, TRUE);
  881. break;
  882. }
  883. default:
  884. return FALSE;
  885. }
  886. default:
  887. break;
  888. }
  889. return FALSE;
  890. }
  891. VOID
  892. FormatPartition(
  893. PREGION_DESCRIPTOR RegionDescriptor
  894. )
  895. /*++
  896. Routine Description:
  897. Insure the IFS Dll is loaded and start the dialog for format
  898. of a volume.
  899. Arguments:
  900. RegionDescriptor - The region to format.
  901. Return Value:
  902. None
  903. --*/
  904. {
  905. static FORMAT_PARAMS formatParams; // this is passed to other threads
  906. // it cannot be located on the stack
  907. PPERSISTENT_REGION_DATA regionData;
  908. int doFormat;
  909. ULONG diskSize;
  910. PWSTR tempName,
  911. tempLabel,
  912. typeName;
  913. TCHAR label[100],
  914. fileSystem[10],
  915. message[300],
  916. msgProto[300],
  917. title[200];
  918. // Make sure format of this partition is allowed. It is not allowed
  919. // if it is the boot partition (or sys partition on x86).
  920. if ((DeletionIsAllowed(RegionDescriptor)) != NO_ERROR) {
  921. ErrorDialog(MSG_CANT_FORMAT_WINNT);
  922. return;
  923. }
  924. // must have a drive letter
  925. regionData = PERSISTENT_DATA(RegionDescriptor);
  926. if (!regionData->DriveLetter) {
  927. ErrorDialog(MSG_CANT_FORMAT_NO_LETTER);
  928. return;
  929. }
  930. // can only do this is the dll is loaded.
  931. if (!LoadIfsDll()) {
  932. // could not load the dll
  933. ErrorDialog(MSG_CANT_LOAD_FMIFS);
  934. return;
  935. }
  936. // set up the parameters and get the information from the user.
  937. formatParams.RegionDescriptor = RegionDescriptor;
  938. formatParams.Result = 0;
  939. formatParams.RegionData = regionData;
  940. formatParams.Label = (PUCHAR) label;
  941. formatParams.FileSystem = (PUCHAR) fileSystem;
  942. formatParams.QuickFormat = formatParams.Cancel =
  943. formatParams.DoubleSpace = FALSE;
  944. formatParams.TotalSpace = formatParams.SpaceAvailable = 0;
  945. doFormat = DialogBoxParam(hModule,
  946. MAKEINTRESOURCE(IDD_PARTITIONFORMAT),
  947. hwndFrame,
  948. (DLGPROC) FormatDlgProc,
  949. (ULONG) &formatParams);
  950. if (doFormat) {
  951. // do an are you sure message.
  952. doFormat = ConfirmationDialog(MSG_CONFIRM_FORMAT,
  953. MB_ICONQUESTION | MB_YESNO);
  954. if (doFormat == IDYES) {
  955. if (IsDiskRemovable[RegionDescriptor->Disk]) {
  956. PWSTR typeName,
  957. volumeLabel;
  958. BOOLEAN volumeChanged = FALSE;
  959. if (!RegionDescriptor->PartitionNumber) {
  960. // TODO: something has changed where the code gets to this
  961. // point with an incorrect partition number - This happens
  962. // when a partition is deleted and added to removable media.
  963. // For removable media the partition number is always 1.
  964. RegionDescriptor->PartitionNumber = 1;
  965. }
  966. if (GetVolumeTypeAndSize(RegionDescriptor->Disk,
  967. RegionDescriptor->PartitionNumber,
  968. &volumeLabel,
  969. &typeName,
  970. &diskSize) == OK_STATUS) {
  971. // Verify that this is still the same device.
  972. if (typeName) {
  973. if (!lstrcmpiW(typeName, L"raw")) {
  974. Free(typeName);
  975. typeName = Malloc((wcslen(wszUnknown) * sizeof(WCHAR)) + sizeof(WCHAR));
  976. lstrcpyW(typeName, wszUnknown);
  977. }
  978. } else {
  979. typeName = Malloc((wcslen(wszUnknown) * sizeof(WCHAR)) + sizeof(WCHAR));
  980. lstrcpyW(typeName, wszUnknown);
  981. }
  982. if (regionData) {
  983. if (regionData->VolumeLabel) {
  984. if (wcscmp(regionData->VolumeLabel, volumeLabel)) {
  985. volumeChanged = TRUE;
  986. }
  987. }
  988. if (regionData->TypeName) {
  989. // It is possible the region has no type
  990. // or is of type "Unformatted".
  991. // This says it is ok to format.
  992. if (*regionData->TypeName) {
  993. if (wcscmp(regionData->TypeName, wszUnformatted)) {
  994. // It has a type and it isn't
  995. // unformatted - see if it is
  996. // the same as before.
  997. if (wcscmp(regionData->TypeName, typeName)) {
  998. volumeChanged = TRUE;
  999. }
  1000. }
  1001. }
  1002. }
  1003. }
  1004. if (Disks[RegionDescriptor->Disk]->DiskSizeMB != (diskSize/1024)) {
  1005. volumeChanged = TRUE;
  1006. }
  1007. if (volumeChanged) {
  1008. ErrorDialog(MSG_VOLUME_CHANGED);
  1009. // since the user was told the volume changed,
  1010. // update the display.
  1011. SetCursor(hcurWait);
  1012. if (GetVolumeTypeAndSize(RegionDescriptor->Disk,
  1013. RegionDescriptor->PartitionNumber,
  1014. &tempLabel,
  1015. &tempName,
  1016. &diskSize) == OK_STATUS) {
  1017. Free(typeName);
  1018. typeName = tempName;
  1019. Free(volumeLabel);
  1020. volumeLabel = tempLabel;
  1021. }
  1022. if (regionData->VolumeLabel) {
  1023. Free(regionData->VolumeLabel);
  1024. }
  1025. regionData->VolumeLabel = volumeLabel;
  1026. if (regionData->TypeName) {
  1027. Free(regionData->TypeName);
  1028. }
  1029. regionData->TypeName = typeName;
  1030. SetCursor(hcurNormal);
  1031. TotalRedrawAndRepaint();
  1032. return;
  1033. } else {
  1034. if (volumeLabel) {
  1035. Free(volumeLabel);
  1036. }
  1037. if (typeName) {
  1038. Free(typeName);
  1039. }
  1040. }
  1041. }
  1042. }
  1043. // Insure the partition is not to big if the requested format
  1044. // is FAT.
  1045. if (!strcmpi(formatParams.FileSystem, "FAT")) {
  1046. if (GetVolumeSizeMB(RegionDescriptor->Disk,
  1047. RegionDescriptor->PartitionNumber,
  1048. &diskSize)) {
  1049. if (diskSize > (4*1024)) {
  1050. ErrorDialog(MSG_TOO_BIG_FOR_FAT);
  1051. TotalRedrawAndRepaint();
  1052. return;
  1053. }
  1054. } else {
  1055. // Just try the format anyway.
  1056. }
  1057. }
  1058. // Initialize synchronization event to know when the
  1059. // format thread is really complete.
  1060. formatParams.ThreadIsDone = 0;
  1061. // user still wants to format.
  1062. DialogBoxParam(hModule,
  1063. MAKEINTRESOURCE(IDD_FORMATCANCEL),
  1064. hwndFrame,
  1065. (DLGPROC) CancelDlgProc,
  1066. (ULONG) &formatParams);
  1067. if (formatParams.Result) {
  1068. // the format failed.
  1069. ErrorDialog(formatParams.Result);
  1070. } else {
  1071. LoadString(hModule,
  1072. IDS_FORMATCOMPLETE,
  1073. title,
  1074. sizeof(title)/sizeof(TCHAR));
  1075. LoadString(hModule,
  1076. IDS_FORMATSTATS,
  1077. msgProto,
  1078. sizeof(msgProto)/sizeof(TCHAR));
  1079. wsprintf(message,
  1080. msgProto,
  1081. formatParams.TotalSpace,
  1082. formatParams.SpaceAvailable);
  1083. MessageBox(GetActiveWindow(),
  1084. message,
  1085. title,
  1086. MB_ICONINFORMATION | MB_OK);
  1087. }
  1088. // Synchronize with the format thread just in case
  1089. // the user did a cancel and the format thread is
  1090. // still buzy verifying 50MB or some such thing.
  1091. // Rather than use an event this is a polling loop.
  1092. SetCursor(hcurWait);
  1093. while (!formatParams.ThreadIsDone) {
  1094. Sleep(1000);
  1095. }
  1096. SetCursor(hcurNormal);
  1097. // If the format was successful, update the volume
  1098. // information in the data structures.
  1099. if (!formatParams.Result) {
  1100. // get the new label and FsType regardless of success of the
  1101. // format (i.e. user cancel may have occurred, so this stuff
  1102. // is not what it used to be even if the format failed.
  1103. {
  1104. // force mount by filesystem. This is done with the
  1105. // extra \ on the end of the path. This must be done
  1106. // in order to get the FS type. Otherwise the filesystem
  1107. // recognisor may allow the open without actually getting
  1108. // the file system involved.
  1109. char ntDeviceName[100];
  1110. STATUS_CODE sc;
  1111. HANDLE_T handle;
  1112. sprintf(ntDeviceName, "\\DosDevices\\%c:\\", regionData->DriveLetter);
  1113. sc = LowOpenNtName(ntDeviceName, &handle);
  1114. if (sc == OK_STATUS) {
  1115. LowCloseDisk(handle);
  1116. }
  1117. }
  1118. typeName = NULL;
  1119. GetTypeName(RegionDescriptor->Disk, RegionDescriptor->PartitionNumber, &typeName);
  1120. if (!typeName) {
  1121. // Failed to get the type after a cancel. This means
  1122. // GetTypeName() could not open the volume for some reason.
  1123. // This has been seen on Alpha's and x86 with large
  1124. // hardware raid devices. Exiting and starting
  1125. // over will get an FS type. For now, don't change the
  1126. // data structures.
  1127. TotalRedrawAndRepaint();
  1128. return;
  1129. }
  1130. tempLabel = NULL;
  1131. if (GetVolumeLabel(RegionDescriptor->Disk, RegionDescriptor->PartitionNumber, &tempLabel) == NO_ERROR) {
  1132. if (tempLabel) {
  1133. Free(regionData->VolumeLabel);
  1134. regionData->VolumeLabel = Malloc((lstrlenW(tempLabel) + 1) * sizeof(WCHAR));
  1135. lstrcpyW(regionData->VolumeLabel, tempLabel);
  1136. }
  1137. } else {
  1138. *regionData->VolumeLabel = 0;
  1139. }
  1140. // update the type name.
  1141. if (regionData->TypeName) {
  1142. Free(regionData->TypeName);
  1143. regionData->TypeName = typeName;
  1144. }
  1145. // update the file system type information for all
  1146. // components of this region (i.e. fix up FT structures if
  1147. // it is an FT item). This is done via knowledge about multiple
  1148. // selections as opposed to walking through the FtObject list.
  1149. if (SelectionCount > 1) {
  1150. PPERSISTENT_REGION_DATA passedRegionData;
  1151. ULONG index;
  1152. // Need to update all involved.
  1153. passedRegionData = regionData;
  1154. for (index = 0; index < SelectionCount; index++) {
  1155. RegionDescriptor = &SELECTED_REGION(index);
  1156. regionData = PERSISTENT_DATA(RegionDescriptor);
  1157. if (regionData == passedRegionData) {
  1158. continue;
  1159. }
  1160. if (regionData->VolumeLabel) {
  1161. Free(regionData->VolumeLabel);
  1162. regionData->VolumeLabel = NULL;
  1163. }
  1164. if (tempLabel) {
  1165. regionData->VolumeLabel = Malloc((lstrlenW(tempLabel) + 1) * sizeof(WCHAR));
  1166. lstrcpyW(regionData->VolumeLabel, tempLabel);
  1167. }
  1168. if (regionData->TypeName) {
  1169. Free(regionData->TypeName);
  1170. }
  1171. regionData->TypeName = Malloc((lstrlenW(passedRegionData->TypeName) + 1) * sizeof(WCHAR));
  1172. lstrcpyW(regionData->TypeName, passedRegionData->TypeName);
  1173. }
  1174. }
  1175. if (tempLabel) {
  1176. Free(tempLabel);
  1177. }
  1178. }
  1179. // force screen update.
  1180. TotalRedrawAndRepaint();
  1181. }
  1182. }
  1183. }
  1184. VOID
  1185. LabelPartition(
  1186. PREGION_DESCRIPTOR RegionDescriptor
  1187. )
  1188. /*++
  1189. Routine Description:
  1190. Insure the IFS Dll is loaded and start the dialog for label
  1191. of a volume.
  1192. Arguments:
  1193. RegionDescriptor - the region for the label.
  1194. Return Value:
  1195. None
  1196. --*/
  1197. {
  1198. int doLabel;
  1199. DWORD ec;
  1200. TCHAR label[100];
  1201. WCHAR unicodeLabel[100];
  1202. LABEL_PARAMS labelParams;
  1203. WCHAR driveLetter[4];
  1204. PWSTR tmpLabel;
  1205. PPERSISTENT_REGION_DATA regionData;
  1206. if (!LoadIfsDll()) {
  1207. // could not load the Dll
  1208. ErrorDialog(MSG_CANT_LOAD_FMIFS);
  1209. return;
  1210. }
  1211. labelParams.RegionDescriptor = RegionDescriptor;
  1212. labelParams.NewLabel = (LPTSTR)label;
  1213. doLabel = DialogBoxParam(hModule,
  1214. MAKEINTRESOURCE(IDD_PARTITIONLABEL),
  1215. hwndFrame,
  1216. (DLGPROC) LabelDlgProc,
  1217. (ULONG) &labelParams);
  1218. if (doLabel) {
  1219. regionData = PERSISTENT_DATA(RegionDescriptor);
  1220. if (IsDiskRemovable[RegionDescriptor->Disk]) {
  1221. PWSTR typeName,
  1222. volumeLabel;
  1223. ULONG diskSize;
  1224. BOOLEAN volumeChanged = FALSE;
  1225. if (GetVolumeTypeAndSize(RegionDescriptor->Disk,
  1226. RegionDescriptor->PartitionNumber,
  1227. &volumeLabel,
  1228. &typeName,
  1229. &diskSize) == OK_STATUS) {
  1230. // Verify that this is still the same device.
  1231. if (regionData) {
  1232. if (regionData->VolumeLabel) {
  1233. if (wcscmp(regionData->VolumeLabel, volumeLabel)) {
  1234. volumeChanged = TRUE;
  1235. }
  1236. }
  1237. if (regionData->TypeName) {
  1238. if (wcscmp(regionData->TypeName, typeName)) {
  1239. volumeChanged = TRUE;
  1240. }
  1241. }
  1242. }
  1243. if (Disks[RegionDescriptor->Disk]->DiskSizeMB != (diskSize/1024)) {
  1244. volumeChanged = TRUE;
  1245. }
  1246. if (volumeChanged) {
  1247. PWSTR tempName,
  1248. tempLabel;
  1249. ErrorDialog(MSG_VOLUME_CHANGED);
  1250. // since the user was told the volume changed,
  1251. // update the display.
  1252. SetCursor(hcurWait);
  1253. if (GetVolumeTypeAndSize(RegionDescriptor->Disk,
  1254. RegionDescriptor->PartitionNumber,
  1255. &tempLabel,
  1256. &tempName,
  1257. &diskSize) == OK_STATUS) {
  1258. Free(typeName);
  1259. typeName = tempName;
  1260. Free(volumeLabel);
  1261. volumeLabel = tempLabel;
  1262. }
  1263. if (regionData->VolumeLabel) {
  1264. Free(regionData->VolumeLabel);
  1265. }
  1266. regionData->VolumeLabel = volumeLabel;
  1267. if (regionData->TypeName) {
  1268. Free(regionData->TypeName);
  1269. }
  1270. regionData->TypeName = typeName;
  1271. SetCursor(hcurNormal);
  1272. TotalRedrawAndRepaint();
  1273. return;
  1274. } else {
  1275. Free(volumeLabel);
  1276. Free(typeName);
  1277. }
  1278. }
  1279. }
  1280. driveLetter[1] = L':';
  1281. driveLetter[2] = 0;
  1282. driveLetter[0] = (WCHAR)regionData->DriveLetter;
  1283. // convert to unicode - use variable doLabel as an index.
  1284. setUnicode(label,
  1285. unicodeLabel);
  1286. // perform the label.
  1287. SetCursor(hcurWait);
  1288. (*LabelRoutine)(driveLetter, unicodeLabel);
  1289. ec = GetLastError();
  1290. if (ec != NO_ERROR) {
  1291. SetCursor(hcurNormal);
  1292. ErrorDialog(ec);
  1293. SetCursor(hcurWait);
  1294. }
  1295. // get the new label to be certain it took and update
  1296. // the internal structures.
  1297. if (GetVolumeLabel(RegionDescriptor->Disk, RegionDescriptor->PartitionNumber, &tmpLabel) == NO_ERROR) {
  1298. Free(regionData->VolumeLabel);
  1299. regionData->VolumeLabel = Malloc((lstrlenW(tmpLabel) + 1) * sizeof(WCHAR));
  1300. lstrcpyW(regionData->VolumeLabel, tmpLabel);
  1301. } else {
  1302. *regionData->VolumeLabel = 0;
  1303. }
  1304. // update the label for all
  1305. // components of this region (i.e. fix up FT structures if
  1306. // it is an FT item). This is done via knowledge about multiple
  1307. // selections as opposed to walking through the FtObject list.
  1308. if (SelectionCount > 1) {
  1309. PPERSISTENT_REGION_DATA passedRegionData;
  1310. ULONG index;
  1311. // Need to update all involved.
  1312. passedRegionData = regionData;
  1313. for (index = 0; index < SelectionCount; index++) {
  1314. RegionDescriptor = &SELECTED_REGION(index);
  1315. regionData = PERSISTENT_DATA(RegionDescriptor);
  1316. if (regionData == passedRegionData) {
  1317. continue;
  1318. }
  1319. if (regionData->VolumeLabel) {
  1320. Free(regionData->VolumeLabel);
  1321. regionData->VolumeLabel = NULL;
  1322. }
  1323. if (tmpLabel) {
  1324. regionData->VolumeLabel = Malloc((lstrlenW(tmpLabel) + 1) * sizeof(WCHAR));
  1325. lstrcpyW(regionData->VolumeLabel, tmpLabel);
  1326. } else {
  1327. *regionData->VolumeLabel = 0;
  1328. }
  1329. }
  1330. }
  1331. if (tmpLabel) {
  1332. Free(tmpLabel);
  1333. }
  1334. SetCursor(hcurNormal);
  1335. // force screen update.
  1336. TotalRedrawAndRepaint();
  1337. }
  1338. }