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.

1710 lines
45 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. dblspace.c
  5. Abstract:
  6. This module contains the set of routines that deal with double space
  7. dialogs and support.
  8. Author:
  9. Bob Rinne (bobri) 11/15/93
  10. Environment:
  11. User process.
  12. Notes:
  13. Revision History:
  14. --*/
  15. #include "fdisk.h"
  16. #include "fmifs.h"
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <wchar.h>
  20. #include <string.h>
  21. #ifdef DOUBLE_SPACE_SUPPORT_INCLUDED
  22. PREGION_DESCRIPTOR RegionForDblSpaceVolume;
  23. ULONG DblSpaceThresholdSizes[] = { 10, 40, 100, (ULONG) -1 };
  24. #define NUMBER_PARSEFORMAT_ITEMS 4
  25. char *DblSpaceIniFileName = "%c:\\dblspace.ini";
  26. char *DblSpaceWildCardFileName = "%c:\\dblspace.*";
  27. char *DblSpaceParseFormat = "%s %s %d %d";
  28. // All double space structures are chained into the base chain
  29. // this allows for ease in initialization to determine which are
  30. // mounted. This chain is only used for initialization.
  31. PDBLSPACE_DESCRIPTOR DblChainBase = NULL;
  32. PDBLSPACE_DESCRIPTOR DblChainLast = NULL;
  33. extern BOOLEAN DoubleSpaceSupported;
  34. #define DblSpaceMountDrive(REGDESC, DBLSPACE) \
  35. DblSpaceChangeState(REGDESC, DBLSPACE, TRUE)
  36. #define DblSpaceDismountDrive(REGDESC, DBLSPACE) \
  37. DblSpaceChangeState(REGDESC, DBLSPACE, FALSE)
  38. VOID
  39. DblSpaceUpdateIniFile(
  40. IN PREGION_DESCRIPTOR RegionDescriptor
  41. )
  42. /*++
  43. Routine Description:
  44. This routine is left around in case this code must update DOS
  45. based .ini files. Currently it does nothing.
  46. Arguments:
  47. The region with the double space volumes.
  48. Return Value
  49. None
  50. --*/
  51. {
  52. }
  53. ULONG
  54. DblSpaceChangeState(
  55. IN PREGION_DESCRIPTOR RegionDescriptor,
  56. IN PDBLSPACE_DESCRIPTOR DblSpacePtr,
  57. IN BOOL Mount
  58. )
  59. /*++
  60. Routine Description:
  61. Based on the value of Mount, either mount the volume or
  62. dismount the Double Space volume
  63. Arguments:
  64. RegionDescriptor - The region containing the double space volume
  65. DriveLetter - The drive letter of the double space volume involved.
  66. Mount - TRUE == perform a mount function
  67. FALSE == dismount the volume
  68. Return Value:
  69. None
  70. --*/
  71. {
  72. PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
  73. WCHAR dblSpaceUniqueName[32];
  74. ULONG index;
  75. ULONG result = 0;
  76. SetCursor(hcurWait);
  77. if (Mount) {
  78. // Call fmifs mount routine.
  79. result = FmIfsMountDblspace(DblSpacePtr->FileName,
  80. regionData->DriveLetter,
  81. DblSpacePtr->NewDriveLetter);
  82. } else {
  83. // Call fmifs dismount routine.
  84. result = FmIfsDismountDblspace(DblSpacePtr->DriveLetter);
  85. }
  86. if (!result) {
  87. DblSpacePtr->Mounted = Mount;
  88. if (Mount) {
  89. DblSpacePtr->DriveLetter = DblSpacePtr->NewDriveLetter;
  90. MarkDriveLetterUsed(DblSpacePtr->DriveLetter);
  91. } else {
  92. TCHAR name[4];
  93. // remove the drive letter.
  94. name[0] = (TCHAR)DblSpacePtr->DriveLetter;
  95. name[1] = (TCHAR)':';
  96. name[2] = 0;
  97. DefineDosDevice(DDD_REMOVE_DEFINITION, (LPCTSTR) name, (LPCTSTR) NULL);
  98. // Now update the internal structures.
  99. MarkDriveLetterFree(DblSpacePtr->DriveLetter);
  100. DblSpacePtr->DriveLetter = ' ';
  101. }
  102. if (!IsDiskRemovable[RegionDescriptor->Disk]) {
  103. dblSpaceUniqueName[0] = (WCHAR) regionData->DriveLetter;
  104. dblSpaceUniqueName[1] = (WCHAR) ':';
  105. dblSpaceUniqueName[2] = (WCHAR) '\\';
  106. index = 0;
  107. while (dblSpaceUniqueName[index + 3] = DblSpacePtr->FileName[index]) {
  108. index++;
  109. }
  110. result = DiskRegistryAssignDblSpaceLetter(dblSpaceUniqueName,
  111. (WCHAR) DblSpacePtr->DriveLetter);
  112. }
  113. }
  114. SetCursor(hcurNormal);
  115. return result;
  116. }
  117. PDBLSPACE_DESCRIPTOR
  118. DblSpaceCreateInternalStructure(
  119. IN CHAR DriveLetter,
  120. IN ULONG Size,
  121. IN PCHAR Name,
  122. IN BOOLEAN ChainIt
  123. )
  124. /*++
  125. Routine Description:
  126. This routine constructs the internal data structure that represents a
  127. double space volume.
  128. Arguments:
  129. DriveLetter - drive letter for new internal structure
  130. Size - size of the actual volume
  131. Name - name of the containing double space file (i.e. dblspace.xxx)
  132. Return Value:
  133. Pointer to the new structure if created.
  134. NULL if it couldn't be created.
  135. --*/
  136. {
  137. PDBLSPACE_DESCRIPTOR dblSpace;
  138. dblSpace = malloc(sizeof(DBLSPACE_DESCRIPTOR));
  139. if (dblSpace) {
  140. if (DriveLetter != ' ') {
  141. MarkDriveLetterUsed(DriveLetter);
  142. }
  143. dblSpace->DriveLetter = DriveLetter;
  144. dblSpace->DriveLetterEOS = 0;
  145. dblSpace->NewDriveLetter = 0;
  146. dblSpace->NewDriveLetterEOS = 0;
  147. dblSpace->ChangeDriveLetter = FALSE;
  148. dblSpace->Next = dblSpace->DblChainNext = NULL;
  149. dblSpace->Mounted = FALSE;
  150. dblSpace->ChangeMountState = FALSE;
  151. dblSpace->AllocatedSize = Size;
  152. dblSpace->FileName = malloc(strlen(Name) + 4);
  153. if (dblSpace->FileName) {
  154. // Copy the name.
  155. strcpy(dblSpace->FileName, Name);
  156. if (ChainIt) {
  157. if (DblChainBase) {
  158. DblChainLast->DblChainNext = dblSpace;
  159. } else {
  160. DblChainBase = dblSpace;
  161. }
  162. DblChainLast = dblSpace;
  163. }
  164. } else {
  165. // no memory - free what is allocated and give up.
  166. free(dblSpace);
  167. dblSpace = NULL;
  168. }
  169. }
  170. return dblSpace;
  171. }
  172. #define MAX_IFS_NAME_LENGTH 200
  173. VOID
  174. DblSpaceDetermineMounted(
  175. VOID
  176. )
  177. /*++
  178. Routine Description:
  179. This routine walks through all of the system drive letters to see
  180. if any are mounted double space volumes. If a mounted double space
  181. volume is located it updates the state of that volume in the internal
  182. data structures for the double space volumes.
  183. Arguments:
  184. None
  185. Return Value:
  186. None
  187. --*/
  188. {
  189. PDBLSPACE_DESCRIPTOR dblSpace;
  190. ULONG index;
  191. WCHAR driveLetter[4],
  192. ntDriveName[MAX_IFS_NAME_LENGTH],
  193. cvfName[MAX_IFS_NAME_LENGTH],
  194. hostDriveName[MAX_IFS_NAME_LENGTH],
  195. compareName[MAX_IFS_NAME_LENGTH];
  196. UINT errorMode;
  197. BOOLEAN removable,
  198. floppy,
  199. compressed,
  200. error;
  201. driveLetter[1] = (WCHAR) ':';
  202. driveLetter[2] = 0;
  203. errorMode = SetErrorMode(SEM_FAILCRITICALERRORS);
  204. for (driveLetter[0] = (WCHAR) 'C'; driveLetter[0] < (WCHAR) 'Z'; driveLetter[0]++) {
  205. if (DriveLetterIsAvailable((CHAR)driveLetter[0])) {
  206. // No sense calling this stuff for something that doesn't exist
  207. continue;
  208. }
  209. compressed = FALSE;
  210. if (FmIfsQueryInformation(&driveLetter[0],
  211. &removable,
  212. &floppy,
  213. &compressed,
  214. &error,
  215. &ntDriveName[0],
  216. MAX_IFS_NAME_LENGTH,
  217. &cvfName[0],
  218. MAX_IFS_NAME_LENGTH,
  219. &hostDriveName[0],
  220. MAX_IFS_NAME_LENGTH)) {
  221. // call worked, see if it is a double space volume
  222. if (compressed) {
  223. // now need to find this volume in the chain and
  224. // update it mounted state.
  225. for (dblSpace = DblChainBase;
  226. dblSpace;
  227. dblSpace = dblSpace->DblChainNext) {
  228. for (index = 0;
  229. compareName[index] = (WCHAR) dblSpace->FileName[index];
  230. index++) {
  231. // Everything in for loop
  232. }
  233. if (!wcscmp(compareName, cvfName)) {
  234. // found a match.
  235. dblSpace->Mounted = TRUE;
  236. dblSpace->DriveLetter = (UCHAR) driveLetter[0];
  237. }
  238. }
  239. }
  240. }
  241. }
  242. SetErrorMode(errorMode);
  243. }
  244. VOID
  245. DblSpaceInitialize(
  246. VOID
  247. )
  248. /*++
  249. Routine Description:
  250. This routine goes through the disk table and searches for FAT format
  251. partitions. When one is found, it checks for the presense of DoubleSpace
  252. volumes and initializes the DoubleSpace support structures inside
  253. Disk Administrator.
  254. Arguments:
  255. None
  256. Return Value:
  257. None
  258. --*/
  259. {
  260. PDISKSTATE diskState;
  261. PREGION_DESCRIPTOR regionDesc;
  262. PPERSISTENT_REGION_DATA regionData;
  263. PDBLSPACE_DESCRIPTOR dblSpace,
  264. prevDblSpace;
  265. FILE *dblSpaceIniFile,
  266. *dblSpaceFile;
  267. CHAR driveLetter[10];
  268. CHAR fileName[50];
  269. ULONG size,
  270. mounted;
  271. int items;
  272. unsigned diskIndex,
  273. regionIndex;
  274. for (diskIndex = 0; diskIndex < DiskCount; diskIndex++) {
  275. diskState = Disks[diskIndex];
  276. regionDesc = diskState->RegionArray;
  277. for (regionIndex = 0; regionIndex < diskState->RegionCount; regionIndex++) {
  278. regionData = PERSISTENT_DATA(&regionDesc[regionIndex]);
  279. // region may be free or something that isn't recognized by NT
  280. if (!regionData) {
  281. continue;
  282. }
  283. // region may not be formatted yet.
  284. if (!regionData->TypeName) {
  285. continue;
  286. }
  287. // Double space volumes are only allowed on FAT non-FT partitions.
  288. if (regionData->FtObject) {
  289. continue;
  290. }
  291. if (wcscmp(regionData->TypeName, L"FAT") == 0) {
  292. WIN32_FIND_DATA findInformation;
  293. HANDLE findHandle;
  294. // it is possible to have a double space volume here.
  295. // Search the root directory of the driver for files with
  296. // the name "dblspace.xxx". These are potentially dblspace
  297. // volumes.
  298. prevDblSpace = NULL;
  299. sprintf(fileName, DblSpaceWildCardFileName, regionData->DriveLetter);
  300. findHandle = FindFirstFile(fileName, &findInformation);
  301. while (findHandle != INVALID_HANDLE_VALUE) {
  302. char *cp;
  303. int i;
  304. int save;
  305. // There is at least one dblspace volume. Insure that
  306. // the name is of the proper form.
  307. save = TRUE;
  308. cp = &findInformation.cFileName[0];
  309. while (*cp) {
  310. if (*cp == '.') {
  311. break;
  312. }
  313. cp++;
  314. }
  315. if (*cp != '.') {
  316. // not a proper dblspace volume name.
  317. save = FALSE;
  318. } else {
  319. cp++;
  320. for (i = 0; i < 3; i++, cp++) {
  321. if ((*cp < '0') || (*cp > '9')) {
  322. break;
  323. }
  324. }
  325. if (i != 3) {
  326. // not a proper dblspace volume name.
  327. save = FALSE;
  328. }
  329. }
  330. if (save) {
  331. // save the information and search for more.
  332. dblSpace =
  333. DblSpaceCreateInternalStructure(' ',
  334. ((findInformation.nFileSizeHigh << 16) |
  335. (findInformation.nFileSizeLow)
  336. / (1024 * 1024)),
  337. &findInformation.cFileName[0],
  338. TRUE);
  339. if (dblSpace) {
  340. // Assume volume is not mounted.
  341. dblSpace->Mounted = FALSE;
  342. dblSpace->ChangeMountState = FALSE;
  343. // Chain in this description.
  344. if (prevDblSpace) {
  345. prevDblSpace->Next = dblSpace;
  346. } else {
  347. regionData->DblSpace = dblSpace;
  348. }
  349. // Keep the pointer to this one for the chain.
  350. prevDblSpace = dblSpace;
  351. } else {
  352. // no memory
  353. break;
  354. }
  355. }
  356. if (!FindNextFile(findHandle, &findInformation)) {
  357. // Technically this should double check and call
  358. // GetLastError to see that it is ERROR_NO_MORE_FILES
  359. // but this code doesn't do that.
  360. FindClose(findHandle);
  361. // Get out of the search loop.
  362. findHandle = INVALID_HANDLE_VALUE;
  363. }
  364. }
  365. }
  366. }
  367. }
  368. // Now that all volumes have been located determine which volumes
  369. // are mounted by chasing down the drive letters.
  370. LoadIfsDll();
  371. DblSpaceDetermineMounted();
  372. }
  373. PDBLSPACE_DESCRIPTOR
  374. DblSpaceGetNextVolume(
  375. IN PREGION_DESCRIPTOR RegionDescriptor,
  376. IN PDBLSPACE_DESCRIPTOR DblSpace
  377. )
  378. /*++
  379. Routine Description:
  380. This routine will check the RegionDescriptor to walk the DoubleSpace volume chain
  381. located from the persistent data.
  382. Arguments:
  383. RegionDescriptor - pointer to the region on the disk that is to be searched for
  384. a DoubleSpace volume.
  385. DblSpace - pointer to the last DoubleSpace volume located on the region.
  386. Return Value:
  387. pointer to the next DoubleSpace volume if found
  388. NULL if no volume found.
  389. --*/
  390. {
  391. PPERSISTENT_REGION_DATA regionData;
  392. // If a previous DoubleSpace location was past, simply walk the chain to the next.
  393. if (DblSpace) {
  394. return DblSpace->Next;
  395. }
  396. // no previous DoubleSpace location, just get the first one and return it.
  397. // Could get a NULL RegionDescriptor. If so, return NULL.
  398. if (RegionDescriptor) {
  399. regionData = PERSISTENT_DATA(RegionDescriptor);
  400. if (!regionData) {
  401. return NULL;
  402. }
  403. } else {
  404. return NULL;
  405. }
  406. return regionData->DblSpace;
  407. }
  408. VOID
  409. DblSpaceLinkNewVolume(
  410. IN PREGION_DESCRIPTOR RegionDescriptor,
  411. IN PDBLSPACE_DESCRIPTOR DblSpace
  412. )
  413. /*++
  414. Routine Description:
  415. Chain the new double space volume on the list of double space volumes
  416. for the region.
  417. Arguments:
  418. RegionDescriptor - the region the double space volume has been added to.
  419. DblSpace - the new volume internal data structure.
  420. Return Value:
  421. None
  422. --*/
  423. {
  424. PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
  425. PDBLSPACE_DESCRIPTOR prevDblSpace;
  426. // if this is the first one, chain it first
  427. if (!regionData->DblSpace) {
  428. regionData->DblSpace = DblSpace;
  429. return;
  430. }
  431. for (prevDblSpace = regionData->DblSpace;
  432. prevDblSpace->Next;
  433. prevDblSpace = prevDblSpace->Next) {
  434. // all the work is in the for
  435. }
  436. // found the last one. Add the new one to the chain
  437. prevDblSpace->Next = DblSpace;
  438. }
  439. BOOL
  440. DblSpaceVolumeExists(
  441. IN PREGION_DESCRIPTOR RegionDescriptor
  442. )
  443. /*++
  444. Routine Description:
  445. Indicate to the caller if the input region contains a DoubleSpace volume.
  446. Arguments:
  447. RegionDescriptor - a pointer to the region in question.
  448. Return Value:
  449. TRUE if this region contains DoubleSpace volume(s).
  450. FALSE if not
  451. --*/
  452. {
  453. PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
  454. if (regionData) {
  455. return(regionData->DblSpace ? TRUE : FALSE);
  456. }
  457. return FALSE;
  458. }
  459. BOOL
  460. DblSpaceDismountedVolumeExists(
  461. IN PREGION_DESCRIPTOR RegionDescriptor
  462. )
  463. /*++
  464. Routine Description:
  465. Indicate to the caller if the input region contains a DoubleSpace volume
  466. that is not mounted.
  467. Arguments:
  468. RegionDescriptor - a pointer to the region in question.
  469. Return Value:
  470. TRUE if this region contains DoubleSpace volume(s).
  471. FALSE if not
  472. --*/
  473. {
  474. PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
  475. PDBLSPACE_DESCRIPTOR dblSpace;
  476. if (regionData) {
  477. if (dblSpace = regionData->DblSpace) {
  478. while (dblSpace) {
  479. if (!dblSpace->Mounted) {
  480. return TRUE;
  481. }
  482. dblSpace = dblSpace->Next;
  483. }
  484. }
  485. }
  486. return FALSE;
  487. }
  488. PDBLSPACE_DESCRIPTOR
  489. DblSpaceFindVolume(
  490. IN PREGION_DESCRIPTOR RegionDescriptor,
  491. IN PCHAR Name
  492. )
  493. /*++
  494. Routine Description:
  495. Given a region and a name, locate the double space data structure.
  496. Arguments:
  497. RegionDescriptor - the region to search
  498. Name - the filename wanted.
  499. Return Value:
  500. A pointer to a double space descriptor if found.
  501. NULL if not found.
  502. --*/
  503. {
  504. PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
  505. PDBLSPACE_DESCRIPTOR dblSpace = NULL;
  506. PCHAR string[50];
  507. if (regionData) {
  508. for (dblSpace = regionData->DblSpace; dblSpace; dblSpace = dblSpace->Next) {
  509. if (strcmp(Name, dblSpace->FileName) == 0) {
  510. // found the desired double space volume
  511. break;
  512. }
  513. }
  514. }
  515. return dblSpace;
  516. }
  517. BOOL
  518. DblSpaceDetermineUniqueFileName(
  519. IN PREGION_DESCRIPTOR RegionDescriptor,
  520. IN PUCHAR FileName
  521. )
  522. /*++
  523. Routine Description:
  524. This routine will search the actual partition to determine what
  525. valid double space file name to use (i.e. dblspace.xxx where xxx
  526. is a unique number).
  527. Arguments:
  528. RegionDescriptor - the region to search and determine what double space
  529. file names are in use.
  530. FileName - a pointer to a character buffer for the name.
  531. Return Value:
  532. None
  533. --*/
  534. {
  535. DWORD uniqueNumber = 0;
  536. PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
  537. PDBLSPACE_DESCRIPTOR dblSpace;
  538. do {
  539. sprintf(FileName, "dblspace.%03d", uniqueNumber++);
  540. if (uniqueNumber > 999) {
  541. return FALSE;
  542. }
  543. } while (DblSpaceFindVolume(RegionDescriptor, FileName));
  544. return TRUE;
  545. }
  546. VOID
  547. DblSpaceRemoveVolume(
  548. IN PREGION_DESCRIPTOR RegionDescriptor,
  549. IN UCHAR DriveLetter
  550. )
  551. /*++
  552. Routine Description:
  553. Find the drive letter provided and unlink it from the chain.
  554. Currently this also removes the volume for the scaffolding file.
  555. Arguments:
  556. RegionDescriptor - region containing the double space volume.
  557. DriveLetter - the drive letter to remove.
  558. Return Value:
  559. None
  560. --*/
  561. {
  562. PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(RegionDescriptor);
  563. PDBLSPACE_DESCRIPTOR dblSpace,
  564. prevDblSpace = NULL;
  565. // Clean up the internal structures.
  566. if (regionData) {
  567. for (dblSpace = regionData->DblSpace; dblSpace; dblSpace = dblSpace->Next) {
  568. if (dblSpace->DriveLetter == DriveLetter) {
  569. // This is the one to delete
  570. if (prevDblSpace) {
  571. prevDblSpace->Next = dblSpace->Next;
  572. } else {
  573. regionData->DblSpace = dblSpace->Next;
  574. }
  575. free(dblSpace);
  576. break;
  577. }
  578. prevDblSpace = dblSpace;
  579. }
  580. }
  581. }
  582. BOOL CALLBACK
  583. CreateDblSpaceDlgProc(
  584. IN HWND hDlg,
  585. IN UINT wMsg,
  586. IN WPARAM wParam,
  587. IN LPARAM lParam
  588. )
  589. /*++
  590. Routine Description:
  591. This routine manages the dialog for the creation of a new double
  592. space volume.
  593. Arguments:
  594. hDlg - the dialog box handle.
  595. wMsg - the message.
  596. wParam - the windows parameter.
  597. lParam - depends on message type.
  598. Return Value:
  599. TRUE is returned back through windows if the create is successful
  600. FALSE otherwise
  601. --*/
  602. {
  603. PREGION_DESCRIPTOR regionDescriptor = &SingleSel->RegionArray[SingleSelIndex];
  604. PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(regionDescriptor);
  605. PDBLSPACE_DESCRIPTOR dblSpace;
  606. static FORMAT_PARAMS formatParams; // this is passed to other threads
  607. // it cannot be located on the stack
  608. static HWND hwndCombo;
  609. static DWORD sizeMB = 0,
  610. maxSizeMB = 600,
  611. minSizeMB = 10;
  612. TCHAR outputString[50],
  613. driveLetterString[4], // big enough for "x:" string.
  614. sizeString[20], // must be big enough for an 8.3 name
  615. letter;
  616. FILE *dblspaceIniFile;
  617. DWORD compressedSize,
  618. selection;
  619. BOOL validNumber;
  620. CHAR fileName[50];
  621. switch (wMsg) {
  622. case WM_INITDIALOG:
  623. // limit the size of string that may be entered for the label
  624. hwndCombo = GetDlgItem(hDlg, IDC_NAME);
  625. SendMessage(hwndCombo, EM_LIMITTEXT, 11, 0);
  626. // set up to watch all characters that go thru the size dialog
  627. // to allow only decimal numbers.
  628. hwndCombo = GetDlgItem(hDlg, IDC_DBLSPACE_SIZE);
  629. OldSizeDlgProc = SetWindowLong(hwndCombo,
  630. GWL_WNDPROC,
  631. (LONG)&SizeDlgProc);
  632. // Add each available drive letter to the list of available
  633. // drive letters and set the default letter to the first available.
  634. hwndCombo = GetDlgItem(hDlg, IDC_DRIVELET_COMBOBOX);
  635. driveLetterString[1] = TEXT(':');
  636. driveLetterString[2] = 0;
  637. for (letter='C'; letter <= 'Z'; letter++) {
  638. if (DriveLetterIsAvailable((CHAR)letter)) {
  639. *driveLetterString = letter;
  640. SendMessage(hwndCombo, CB_ADDSTRING, 0, (LONG)driveLetterString);
  641. }
  642. }
  643. SendMessage(hwndCombo,CB_SETCURSEL,0,0);
  644. // Setup the min/max values and the size box.
  645. wsprintf(outputString, TEXT("%u"), 0);
  646. SetDlgItemText(hDlg, IDC_DBLSPACE_SIZE, outputString);
  647. wsprintf(outputString, TEXT("%u"), minSizeMB);
  648. SetDlgItemText(hDlg, IDC_MINMAX_MIN, outputString);
  649. wsprintf(outputString, TEXT("%u"), maxSizeMB);
  650. SetDlgItemText(hDlg, IDC_MINMAX_MAX, outputString);
  651. CenterDialog(hDlg);
  652. return TRUE;
  653. case WM_VSCROLL:
  654. {
  655. switch (LOWORD(wParam)) {
  656. case SB_LINEDOWN:
  657. case SB_LINEUP:
  658. // user is pressing one of the scroll buttons.
  659. sizeMB = GetDlgItemInt(hDlg, IDC_DBLSPACE_SIZE, &validNumber, FALSE);
  660. if (sizeMB < minSizeMB) {
  661. sizeMB = minSizeMB + 1;
  662. }
  663. if (sizeMB > maxSizeMB) {
  664. sizeMB = maxSizeMB - 1;
  665. }
  666. if (((sizeMB > minSizeMB) && (LOWORD(wParam) == SB_LINEDOWN))
  667. || ((sizeMB < maxSizeMB) && (LOWORD(wParam) == SB_LINEUP ))) {
  668. if (sizeMB > maxSizeMB) {
  669. sizeMB = maxSizeMB;
  670. } else if (LOWORD(wParam) == SB_LINEUP) {
  671. sizeMB++;
  672. } else {
  673. sizeMB--;
  674. }
  675. SetDlgItemInt(hDlg, IDC_DBLSPACE_SIZE, sizeMB, FALSE);
  676. SendDlgItemMessage(hDlg, IDC_DBLSPACE_SIZE, EM_SETSEL, 0, -1);
  677. #if 0
  678. compressedSize = sizeMB * 2;
  679. wsprintf(outputString, TEXT("%u"), compressedSize);
  680. SetDlgItemText(hDlg, IDC_DBLSPACE_COMPRESSED, outputString);
  681. #endif
  682. } else {
  683. Beep(500,100);
  684. }
  685. }
  686. break;
  687. }
  688. case WM_COMMAND:
  689. switch (wParam) {
  690. case FD_IDHELP:
  691. break;
  692. case IDCANCEL:
  693. EndDialog(hDlg, FALSE);
  694. break;
  695. case IDOK:
  696. // can only do this if the fmifs dll supports double space.
  697. if (!DoubleSpaceSupported) {
  698. // could not load the dll
  699. ErrorDialog(MSG_CANT_LOAD_FMIFS);
  700. EndDialog(hDlg, FALSE);
  701. break;
  702. }
  703. // Get the current size for this volume.
  704. sizeMB = GetDlgItemInt(hDlg, IDC_DBLSPACE_SIZE, &validNumber, FALSE);
  705. if (!validNumber || !sizeMB || (sizeMB > maxSizeMB) || (sizeMB < minSizeMB)) {
  706. ErrorDialog(MSG_INVALID_SIZE);
  707. EndDialog(hDlg, FALSE);
  708. break;
  709. }
  710. // Get the currently selected item in the listbox for drive letter
  711. selection = SendMessage(hwndCombo, CB_GETCURSEL, 0, 0);
  712. SendMessage(hwndCombo, CB_GETLBTEXT, selection, (LONG)driveLetterString);
  713. formatParams.RegionDescriptor = regionDescriptor;
  714. formatParams.RegionData = regionData;
  715. formatParams.FileSystem = NULL;
  716. formatParams.DblspaceFileName = NULL;
  717. formatParams.QuickFormat = formatParams.Cancel = FALSE;
  718. formatParams.DoubleSpace = TRUE;
  719. formatParams.TotalSpace = 0;
  720. formatParams.SpaceAvailable = sizeMB;
  721. formatParams.NewLetter = driveLetterString[0];
  722. // get the label
  723. formatParams.Label = (PUCHAR) malloc(100);
  724. GetDlgItemText(hDlg, IDC_NAME, (LPTSTR)formatParams.Label, 100);
  725. DialogBoxParam(hModule,
  726. MAKEINTRESOURCE(IDD_DBLSPACE_CANCEL),
  727. hwndFrame,
  728. CancelDlgProc,
  729. (ULONG) &formatParams);
  730. if (formatParams.Result) {
  731. // the format failed.
  732. ErrorDialog(formatParams.Result);
  733. EndDialog(hDlg, FALSE);
  734. } else {
  735. ULONG index;
  736. TCHAR message[300],
  737. msgProto[300],
  738. title[200];
  739. // save the name
  740. if (formatParams.DblspaceFileName) {
  741. for (index = 0;
  742. message[index] = (TCHAR) formatParams.DblspaceFileName[index];
  743. index++) {
  744. }
  745. } else {
  746. sprintf(message, "DIDNTWORK");
  747. }
  748. free(formatParams.DblspaceFileName);
  749. dblSpace = DblSpaceCreateInternalStructure(*driveLetterString,
  750. sizeMB,
  751. message,
  752. FALSE);
  753. if (dblSpace) {
  754. DblSpaceLinkNewVolume(regionDescriptor, dblSpace);
  755. MarkDriveLetterUsed(dblSpace->DriveLetter);
  756. dblSpace->Mounted = TRUE;
  757. }
  758. LoadString(hModule,
  759. IDS_DBLSPACECOMPLETE,
  760. title,
  761. sizeof(title)/sizeof(TCHAR));
  762. LoadString(hModule,
  763. IDS_FORMATSTATS,
  764. msgProto,
  765. sizeof(msgProto)/sizeof(TCHAR));
  766. wsprintf(message,
  767. msgProto,
  768. formatParams.TotalSpace,
  769. formatParams.SpaceAvailable);
  770. MessageBox(GetActiveWindow(),
  771. message,
  772. title,
  773. MB_ICONINFORMATION | MB_OK);
  774. EndDialog(hDlg, TRUE);
  775. }
  776. break;
  777. default:
  778. if (HIWORD(wParam) == EN_CHANGE) {
  779. // The size value has changed. Update the compressed
  780. // size value displayed to the user.
  781. sizeMB = GetDlgItemInt(hDlg, IDC_DBLSPACE_SIZE, &validNumber, FALSE);
  782. if (!validNumber) {
  783. sizeMB = 0;
  784. }
  785. }
  786. break;
  787. }
  788. break;
  789. case WM_DESTROY:
  790. // restore original subclass to window.
  791. hwndCombo = GetDlgItem(hDlg, IDC_DBLSPACE_SIZE);
  792. SetWindowLong(hwndCombo, GWL_WNDPROC, (LONG) OldSizeDlgProc);
  793. break;
  794. case WM_PAINT:
  795. // This may be dead code that really isn't needed.
  796. sizeMB = GetDlgItemInt(hDlg, IDC_DBLSPACE_SIZE, &validNumber, FALSE);
  797. if (!validNumber || !sizeMB || (sizeMB > maxSizeMB) || (sizeMB < minSizeMB)) {
  798. return FALSE;
  799. }
  800. SetDlgItemInt(hDlg, IDC_DBLSPACE_SIZE, sizeMB, FALSE);
  801. SendDlgItemMessage(hDlg, IDC_DBLSPACE_SIZE, EM_SETSEL, 0, -1);
  802. break;
  803. }
  804. return FALSE;
  805. }
  806. VOID
  807. DblSpaceDelete(
  808. IN PDBLSPACE_DESCRIPTOR DblSpace
  809. )
  810. /*++
  811. Routine Description:
  812. Start the dialog box for the deletion of a double space volume.
  813. Arguments:
  814. Param - not currently used.
  815. Return Value:
  816. None
  817. --*/
  818. {
  819. PREGION_DESCRIPTOR regionDescriptor = &SingleSel->RegionArray[SingleSelIndex];
  820. PPERSISTENT_REGION_DATA regionData = PERSISTENT_DATA(regionDescriptor);
  821. if (ConfirmationDialog(MSG_CONFIRM_DBLSPACE_DELETE, MB_ICONQUESTION | MB_YESNOCANCEL) == IDYES) {
  822. // Delete the drive from view
  823. DblSpaceRemoveVolume(regionDescriptor, DblSpace->DriveLetter);
  824. DblSpaceUpdateIniFile(regionDescriptor);
  825. DrawDiskBar(SingleSel);
  826. ForceLBRedraw();
  827. }
  828. }
  829. BOOLEAN
  830. DblSpaceCreate(
  831. IN HWND Dialog,
  832. IN PVOID Param
  833. )
  834. /*++
  835. Routine Description:
  836. Start the dialog box for the creation of a double space volume.
  837. Arguments:
  838. Param - not currently used.
  839. Return Value:
  840. None
  841. --*/
  842. {
  843. BOOLEAN result = 0;
  844. result = DialogBoxParam(hModule,
  845. MAKEINTRESOURCE(IDD_DBLSPACE_CREATE),
  846. Dialog,
  847. CreateDblSpaceDlgProc,
  848. (ULONG) NULL);
  849. if (result) {
  850. DrawDiskBar(SingleSel);
  851. ForceLBRedraw();
  852. }
  853. return result;
  854. }
  855. BOOL CALLBACK
  856. DblSpaceMountDlgProc(
  857. IN HWND hDlg,
  858. IN UINT wMsg,
  859. IN WPARAM wParam,
  860. IN LPARAM lParam
  861. )
  862. /*++
  863. Routine Description:
  864. Handle the dialog for double space.
  865. Arguments:
  866. Standard Windows dialog procedure.
  867. Return Value:
  868. TRUE if something was deleted.
  869. FALSE otherwise.
  870. --*/
  871. {
  872. static PDBLSPACE_DESCRIPTOR dblSpace;
  873. HWND hwndCombo;
  874. DWORD selection;
  875. CHAR driveLetter;
  876. TCHAR driveLetterString[20];
  877. switch (wMsg) {
  878. case WM_INITDIALOG:
  879. dblSpace = (PDBLSPACE_DESCRIPTOR) lParam;
  880. // Update the drive letter selections.
  881. hwndCombo = GetDlgItem(hDlg, IDC_DRIVELET_COMBOBOX);
  882. // Add all other available letters. Keep track of current
  883. // letters offset to set the cursor correctly
  884. driveLetterString[1] = TEXT(':');
  885. driveLetterString[2] = 0;
  886. for (driveLetter = 'C'; driveLetter <= 'Z'; driveLetter++) {
  887. if (DriveLetterIsAvailable((CHAR)driveLetter) ||
  888. (driveLetter == dblSpace->DriveLetter)) {
  889. *driveLetterString = driveLetter;
  890. SendMessage(hwndCombo, CB_ADDSTRING, 0, (LONG)driveLetterString);
  891. }
  892. }
  893. // set the current selection to the appropriate index
  894. SendMessage(hwndCombo, CB_SETCURSEL, 0, 0);
  895. return TRUE;
  896. case WM_COMMAND:
  897. switch (wParam) {
  898. case FD_IDHELP:
  899. DialogHelp(HC_DM_DLG_DOUBLESPACE_MOUNT);
  900. break;
  901. case IDCANCEL:
  902. EndDialog(hDlg, FALSE);
  903. break;
  904. case IDOK:
  905. // User has selected the drive letter and wants the mount to occur.
  906. hwndCombo = GetDlgItem(hDlg, IDC_DRIVELET_COMBOBOX);
  907. selection = SendMessage(hwndCombo, CB_GETCURSEL, 0, 0);
  908. SendMessage(hwndCombo,
  909. CB_GETLBTEXT,
  910. selection,
  911. (LONG)driveLetterString);
  912. dblSpace->NewDriveLetter = (UCHAR) driveLetterString[0];
  913. EndDialog(hDlg, TRUE);
  914. break;
  915. }
  916. }
  917. return FALSE;
  918. }
  919. VOID
  920. DblSpaceSetDialogState(
  921. IN HWND hDlg,
  922. IN PDBLSPACE_DESCRIPTOR DblSpace
  923. )
  924. /*++
  925. Routine Description:
  926. Given a double space volume this routine will update the buttons
  927. in the dialog box to reflect they meaning.
  928. Arguments:
  929. hDlg - dialog handle
  930. DblSpace - The double space volume selection for determining dialog state.
  931. Return Value
  932. None
  933. --*/
  934. {
  935. TCHAR outputString[200];
  936. if (DblSpace->Mounted) {
  937. LoadString(hModule,
  938. IDS_DBLSPACE_MOUNTED,
  939. outputString,
  940. sizeof(outputString)/sizeof(TCHAR));
  941. SetDlgItemText(hDlg, IDC_MOUNT_STATE, outputString);
  942. LoadString(hModule,
  943. IDS_DISMOUNT,
  944. outputString,
  945. sizeof(outputString)/sizeof(TCHAR));
  946. SetDlgItemText(hDlg, ID_MOUNT_OR_DISMOUNT, outputString);
  947. outputString[1] = TEXT(':');
  948. outputString[2] = 0;
  949. outputString[0] = DblSpace->DriveLetter;
  950. SetDlgItemText(hDlg, IDC_DBLSPACE_LETTER, outputString);
  951. } else {
  952. LoadString(hModule,
  953. IDS_DBLSPACE_DISMOUNTED,
  954. outputString,
  955. sizeof(outputString)/sizeof(TCHAR));
  956. SetDlgItemText(hDlg, IDC_MOUNT_STATE, outputString);
  957. LoadString(hModule,
  958. IDS_MOUNT,
  959. outputString,
  960. sizeof(outputString)/sizeof(TCHAR));
  961. SetDlgItemText(hDlg, ID_MOUNT_OR_DISMOUNT, outputString);
  962. outputString[1] = TEXT(' ');
  963. outputString[2] = 0;
  964. outputString[0] = TEXT(' ');
  965. SetDlgItemText(hDlg, IDC_DBLSPACE_LETTER, outputString);
  966. }
  967. }
  968. BOOL CALLBACK
  969. DblSpaceDlgProc(
  970. IN HWND hDlg,
  971. IN UINT wMsg,
  972. IN WPARAM wParam,
  973. IN LPARAM lParam
  974. )
  975. /*++
  976. Routine Description:
  977. Handle the dialog for double space.
  978. Arguments:
  979. Return Value:
  980. TRUE if something was deleted.
  981. FALSE otherwise.
  982. --*/
  983. {
  984. static HWND hwndCombo,
  985. mountButtonHwnd,
  986. deleteButtonHwnd;
  987. static PREGION_DESCRIPTOR regionDescriptor;
  988. static PPERSISTENT_REGION_DATA regionData;
  989. static PDBLSPACE_DESCRIPTOR firstDblSpace;
  990. CHAR driveLetter;
  991. PDBLSPACE_DESCRIPTOR dblSpace;
  992. TCHAR outputString[200];
  993. DWORD selection;
  994. BOOLEAN result;
  995. ULONG errorMessage;
  996. DRAWITEMSTRUCT drawItem;
  997. switch (wMsg) {
  998. case WM_INITDIALOG:
  999. regionDescriptor = &SingleSel->RegionArray[SingleSelIndex];
  1000. regionData = PERSISTENT_DATA(regionDescriptor);
  1001. hwndCombo = GetDlgItem(hDlg, IDC_DBLSPACE_VOLUME);
  1002. mountButtonHwnd = GetDlgItem(hDlg, ID_MOUNT_OR_DISMOUNT);
  1003. deleteButtonHwnd = GetDlgItem(hDlg, IDDELETE);
  1004. // place all double space file names in the selection
  1005. // box and remember the first name.
  1006. firstDblSpace = dblSpace = DblSpaceGetNextVolume(regionDescriptor, NULL);
  1007. for (; dblSpace;
  1008. dblSpace = DblSpaceGetNextVolume(regionDescriptor, dblSpace)) {
  1009. wsprintf(outputString, TEXT("%s"), dblSpace->FileName);
  1010. SendMessage(hwndCombo, CB_ADDSTRING, 0, (LONG)outputString);
  1011. }
  1012. SendMessage(hwndCombo, CB_SETCURSEL, 0, 0);
  1013. // add the drive letter
  1014. if (firstDblSpace) {
  1015. // update the allocated size.
  1016. wsprintf(outputString, TEXT("%u"), firstDblSpace->AllocatedSize);
  1017. SetDlgItemText(hDlg, IDC_DBLSPACE_ALLOCATED, outputString);
  1018. // update mount state
  1019. DblSpaceSetDialogState(hDlg, firstDblSpace);
  1020. EnableWindow(mountButtonHwnd, TRUE);
  1021. EnableWindow(deleteButtonHwnd, TRUE);
  1022. } else {
  1023. // update the Mount/Dismount button to say mount and grey it
  1024. LoadString(hModule,
  1025. IDS_MOUNT,
  1026. outputString,
  1027. sizeof(outputString)/sizeof(TCHAR));
  1028. SetDlgItemText(hDlg, ID_MOUNT_OR_DISMOUNT, outputString);
  1029. EnableWindow(mountButtonHwnd, FALSE);
  1030. EnableWindow(deleteButtonHwnd, FALSE);
  1031. }
  1032. return TRUE;
  1033. case WM_COMMAND:
  1034. switch (wParam) {
  1035. case FD_IDHELP:
  1036. DialogHelp(HC_DM_DLG_DOUBLESPACE);
  1037. break;
  1038. case IDCANCEL:
  1039. // Run the dblspace change and forget about any changes.
  1040. for (dblSpace = firstDblSpace;
  1041. dblSpace;
  1042. dblSpace = DblSpaceGetNextVolume(regionDescriptor, dblSpace)) {
  1043. dblSpace->ChangeMountState = FALSE;
  1044. dblSpace->NewDriveLetter = 0;
  1045. }
  1046. EndDialog(hDlg, FALSE);
  1047. break;
  1048. case IDOK:
  1049. EndDialog(hDlg, TRUE);
  1050. break;
  1051. case IDADD:
  1052. DblSpaceCreate(hDlg, NULL);
  1053. break;
  1054. case IDDELETE:
  1055. hwndCombo = GetDlgItem(hDlg, IDC_DBLSPACE_VOLUME);
  1056. selection = SendMessage(hwndCombo, CB_GETCURSEL, 0, 0);
  1057. SendMessage(hwndCombo,
  1058. CB_GETLBTEXT,
  1059. selection,
  1060. (LONG)outputString);
  1061. // relate the name to a double space volume
  1062. dblSpace = DblSpaceFindVolume(regionDescriptor, (PCHAR)outputString);
  1063. if (!dblSpace) {
  1064. break;
  1065. }
  1066. DblSpaceDelete(dblSpace);
  1067. break;
  1068. case ID_MOUNT_OR_DISMOUNT:
  1069. // The state of something in the dialog changed.
  1070. // Determine which double space volume is involved.
  1071. hwndCombo = GetDlgItem(hDlg, IDC_DBLSPACE_VOLUME);
  1072. selection = SendMessage(hwndCombo, CB_GETCURSEL, 0, 0);
  1073. SendMessage(hwndCombo,
  1074. CB_GETLBTEXT,
  1075. selection,
  1076. (LONG)outputString);
  1077. // relate the name to a double space volume
  1078. dblSpace = DblSpaceFindVolume(regionDescriptor, (PCHAR)outputString);
  1079. if (!dblSpace) {
  1080. break;
  1081. }
  1082. if (dblSpace->Mounted) {
  1083. // dismount the volume
  1084. errorMessage = DblSpaceDismountDrive(regionDescriptor,
  1085. dblSpace);
  1086. if (errorMessage) {
  1087. ErrorDialog(errorMessage);
  1088. } else {
  1089. // Update the dialog
  1090. DblSpaceSetDialogState(hDlg, dblSpace);
  1091. DblSpaceUpdateIniFile(regionDescriptor);
  1092. }
  1093. } else {
  1094. // mount the volume unless the user cancels out
  1095. result = DialogBoxParam(hModule,
  1096. MAKEINTRESOURCE(IDD_DBLSPACE_DRIVELET),
  1097. hwndFrame,
  1098. DblSpaceMountDlgProc,
  1099. (ULONG) dblSpace);
  1100. if (result) {
  1101. errorMessage = DblSpaceMountDrive(regionDescriptor, dblSpace);
  1102. if (errorMessage) {
  1103. ErrorDialog(errorMessage);
  1104. } else {
  1105. // Update the dialog
  1106. DblSpaceSetDialogState(hDlg, dblSpace);
  1107. DblSpaceUpdateIniFile(regionDescriptor);
  1108. }
  1109. }
  1110. }
  1111. DrawDiskBar(SingleSel);
  1112. ForceLBRedraw();
  1113. break;
  1114. default:
  1115. // The state of something in the dialog changed.
  1116. // Determine which double space volume is involved.
  1117. hwndCombo = GetDlgItem(hDlg, IDC_DBLSPACE_VOLUME);
  1118. selection = SendMessage(hwndCombo, CB_GETCURSEL, 0, 0);
  1119. SendMessage(hwndCombo,
  1120. CB_GETLBTEXT,
  1121. selection,
  1122. (LONG)outputString);
  1123. // relate the name to a double space volume
  1124. dblSpace = DblSpaceFindVolume(regionDescriptor, (PCHAR)outputString);
  1125. if (!dblSpace) {
  1126. // update the Mount/Dismount button to say mount and grey it
  1127. LoadString(hModule,
  1128. IDS_MOUNT,
  1129. outputString,
  1130. sizeof(outputString)/sizeof(TCHAR));
  1131. SetDlgItemText(hDlg, ID_MOUNT_OR_DISMOUNT, outputString);
  1132. EnableWindow(mountButtonHwnd, FALSE);
  1133. EnableWindow(deleteButtonHwnd, FALSE);
  1134. break;
  1135. } else {
  1136. EnableWindow(mountButtonHwnd, TRUE);
  1137. EnableWindow(deleteButtonHwnd, TRUE);
  1138. }
  1139. if (HIWORD(wParam) == LBN_SELCHANGE) {
  1140. // update the allocated/compressed size items
  1141. wsprintf(outputString, TEXT("%u"), dblSpace->AllocatedSize);
  1142. SetDlgItemText(hDlg, IDC_DBLSPACE_ALLOCATED, outputString);
  1143. #if 0
  1144. wsprintf(outputString, TEXT("%u"), dblSpace->AllocatedSize * 2);
  1145. SetDlgItemText(hDlg, IDC_DBLSPACE_COMPRESSED, outputString);
  1146. wsprintf(outputString, TEXT("%u.%u"), 2, 0);
  1147. SetDlgItemText(hDlg, IDC_DBLSPACE_RATIO, outputString);
  1148. #endif
  1149. // update mount state
  1150. DblSpaceSetDialogState(hDlg, dblSpace);
  1151. }
  1152. break;
  1153. }
  1154. break;
  1155. }
  1156. return FALSE;
  1157. }
  1158. VOID
  1159. DblSpace(
  1160. IN HWND Dialog,
  1161. IN PVOID Param
  1162. )
  1163. /*++
  1164. Routine Description:
  1165. Start the dialog box for double space.
  1166. Arguments:
  1167. Param - not currently used.
  1168. Return Value:
  1169. None
  1170. --*/
  1171. {
  1172. BOOLEAN result;
  1173. if (IsFullDoubleSpace) {
  1174. result = DialogBoxParam(hModule,
  1175. MAKEINTRESOURCE(IDD_DBLSPACE_FULL),
  1176. Dialog,
  1177. DblSpaceDlgProc,
  1178. (ULONG) NULL);
  1179. } else {
  1180. result = DialogBoxParam(hModule,
  1181. MAKEINTRESOURCE(IDD_DBLSPACE),
  1182. Dialog,
  1183. DblSpaceDlgProc,
  1184. (ULONG) NULL);
  1185. }
  1186. if (result) {
  1187. DrawDiskBar(SingleSel);
  1188. ForceLBRedraw();
  1189. }
  1190. }
  1191. #else
  1192. // STUBS for easy removal of DoubleSpace support.
  1193. BOOL
  1194. DblSpaceVolumeExists(
  1195. IN PREGION_DESCRIPTOR RegionDescriptor
  1196. )
  1197. {
  1198. return FALSE;
  1199. }
  1200. BOOL
  1201. DblSpaceDismountedVolumeExists(
  1202. IN PREGION_DESCRIPTOR RegionDescriptor
  1203. )
  1204. {
  1205. return FALSE;
  1206. }
  1207. BOOLEAN
  1208. DblSpaceCreate(
  1209. IN HWND Dialog,
  1210. IN PVOID Param
  1211. )
  1212. {
  1213. return FALSE;
  1214. }
  1215. VOID
  1216. DblSpaceDelete(
  1217. IN PVOID Param
  1218. )
  1219. {
  1220. }
  1221. VOID
  1222. DblSpaceMount(
  1223. IN PVOID Param
  1224. )
  1225. {
  1226. }
  1227. VOID
  1228. DblSpaceDismount(
  1229. IN PVOID Param
  1230. )
  1231. {
  1232. }
  1233. VOID
  1234. DblSpaceInitialize(
  1235. VOID
  1236. )
  1237. {
  1238. }
  1239. VOID
  1240. DblSpace(
  1241. IN HWND Dialog,
  1242. IN PVOID Param
  1243. )
  1244. {
  1245. }
  1246. PDBLSPACE_DESCRIPTOR
  1247. DblSpaceGetNextVolume(
  1248. IN PREGION_DESCRIPTOR RegionDescriptor,
  1249. IN PDBLSPACE_DESCRIPTOR DblSpace
  1250. )
  1251. {
  1252. return NULL;
  1253. }
  1254. #endif