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.

1472 lines
44 KiB

  1. /*++
  2. Copyright (c) 1993 Microsoft Corporation
  3. Module Name:
  4. spdblspc.c
  5. Abstract:
  6. Code that detects compressed drives on a system that contains
  7. dblspace.ini in the root of c:.
  8. Author:
  9. Jaime Sasson (jaimes) 01-October-1993
  10. Revision History:
  11. --*/
  12. #include "spprecmp.h"
  13. #pragma hdrstop
  14. //
  15. // This variable is needed since it contains a buffer that can
  16. // be used in kernel mode. The buffer is used by NtFsControlFile,
  17. // since the Zw API is not exported
  18. //
  19. extern PSETUP_COMMUNICATION CommunicationParams;
  20. #define KWD_ACT L"ActivateDrive"
  21. #define KWD_FIRST L"FirstDrive"
  22. #define KWD_LAST L"LastDrive"
  23. #define KWD_MAXREM L"MaxRemovableDrives"
  24. #define KWD_MAXFILE L"MaxFileFragments"
  25. #define KWD_AUTOMOUNT L"Automount"
  26. #define KWD_DOUBLEGUARD L"Doubleguard"
  27. #define KWD_ROMSERVER L"Romserver"
  28. #define KWD_SWITCHES L"Switches"
  29. #define CVF_SEQ_MAX 255
  30. #define MINFILEFRAGMENTS 50
  31. #define MAXFILEFRAGMENTS 10000
  32. #define DBLSPACE_INI_FILE L"\\dblspace.ini"
  33. #define CVF_NAME_PATTERN L"DBLSPACE.%03d"
  34. typedef struct _ACTIVATE_DRIVE {
  35. struct _ACTIVATE_DRIVE* Next;
  36. struct _ACTIVATE_DRIVE* Previous;
  37. WCHAR MountDrive;
  38. WCHAR HostDrive;
  39. USHORT SeqNumber;
  40. } ACTIVATE_DRIVE, *PACTIVATE_DRIVE;
  41. typedef struct _DBLSPACE_INI_INFO {
  42. USHORT MaxRemovableDrives;
  43. WCHAR FirstDrive;
  44. WCHAR LastDrive;
  45. USHORT MaxFileFragments;
  46. WCHAR DoubleGuard[2];
  47. WCHAR RomServer[2];
  48. PACTIVATE_DRIVE CompressedDriveList;
  49. WCHAR AutoMount[30];
  50. WCHAR Switches[4];
  51. } DBLSPACE_INI_INFO, *PDBLSPACE_INI_INFO;
  52. BOOLEAN DblspaceModified = FALSE;
  53. DBLSPACE_INI_INFO DblspaceInfo = { 0, // MaxRemovableDrives
  54. 0, // FirstDrive
  55. 0, // LastDrive
  56. 0, // MaxFileFragments
  57. { (WCHAR)'\0' }, // DoubleGuard
  58. { (WCHAR)'\0' }, // RomServer
  59. NULL, // CompressedDriveList
  60. { (WCHAR)'\0' }, // AutoMount[0]
  61. { (WCHAR)'\0' } // Switches[0]
  62. };
  63. LONG
  64. CompareDrive(
  65. IN PACTIVATE_DRIVE Drive1,
  66. IN PACTIVATE_DRIVE Drive2
  67. )
  68. /*++
  69. Routine Description:
  70. Compares two structures of type ACTIVATE_DRIVE.
  71. This routine is used to sort the list of compressed drives
  72. in the global variable DblspaceInfo.
  73. Drive1 < Drive2 if
  74. Drive1->HostDrive < Drive2->HostDrive or
  75. Drive1->HostDrive == Drive2->HostDrive and
  76. Drive1->SeqNumber < Drive2->SeqNumber
  77. Drive1 == Drive2 if
  78. Drive1->HostDrive == Drive2->HostDrive and
  79. Drive1->SeqNumber == Drive2->SeqNumber
  80. Drive1 > Drive2 if
  81. Drive1->HostDrive > Drive2->HostDrive or
  82. Drive1->HostDrive == Drive2->HostDrive and
  83. Drive1->SeqNumber > Drive2->SeqNumber
  84. Arguments:
  85. Drive1, Drive2 - Pointer to ACTIVATE_STRUCTUREs to be compared.
  86. Return Value:
  87. LONG - Returns: -1 if Drive1 < Drive2
  88. 0 if Drive1 == Drive2
  89. 1 if Drive1 > Drive2
  90. --*/
  91. {
  92. if( ( Drive1->HostDrive < Drive2->HostDrive ) ||
  93. ( ( Drive1->HostDrive == Drive2->HostDrive ) &&
  94. ( Drive1->SeqNumber < Drive2->SeqNumber ) )
  95. ) {
  96. return( -1 );
  97. } else if ( ( Drive1->HostDrive > Drive2->HostDrive ) ||
  98. ( ( Drive1->HostDrive == Drive2->HostDrive ) &&
  99. ( Drive1->SeqNumber > Drive2->SeqNumber ) )
  100. ) {
  101. return( 1 );
  102. }
  103. return( 0 );
  104. }
  105. BOOLEAN
  106. AddCompressedDrive(
  107. IN WCHAR MountDrive,
  108. IN WCHAR HostDrive,
  109. IN USHORT SeqNumber
  110. )
  111. /*++
  112. Routine Description:
  113. Add an ACTIVATE_DRIVE structure to the list of compressed drives
  114. kept in DblspaceInfo.
  115. Arguments:
  116. MountDrive - Indicates the drive letter of the compressed drive.
  117. HostDrive - Indicates the drive letter of the host drive (drive that
  118. contains the file dblspace.nnn) for the compressed drive.
  119. SeqNumber - Sequence number for the CVF file associated to the compressed
  120. drive.
  121. Return Value:
  122. BOOLEAN - Returns TRUE if the information was successfully added
  123. to the list of compressed drives.
  124. --*/
  125. {
  126. PACTIVATE_DRIVE NewElement;
  127. PACTIVATE_DRIVE Pointer;
  128. NewElement = SpMemAlloc( sizeof( ACTIVATE_DRIVE ) );
  129. if( NewElement == NULL ) {
  130. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to allocate memory!\n" ) );
  131. return( FALSE );
  132. }
  133. NewElement->MountDrive = MountDrive;
  134. NewElement->HostDrive = HostDrive;
  135. NewElement->SeqNumber = SeqNumber;
  136. NewElement->Next = NULL;
  137. NewElement->Previous = NULL;
  138. if( ( Pointer = DblspaceInfo.CompressedDriveList ) == NULL ) {
  139. DblspaceInfo.CompressedDriveList = NewElement;
  140. } else {
  141. for( ; Pointer; Pointer = Pointer->Next ) {
  142. if( CompareDrive( NewElement, Pointer ) <= 0 ) {
  143. //
  144. // Insert element
  145. //
  146. NewElement->Previous = Pointer->Previous;
  147. if( NewElement->Previous != NULL ) {
  148. NewElement->Previous->Next = NewElement;
  149. } else {
  150. DblspaceInfo.CompressedDriveList = NewElement;
  151. }
  152. NewElement->Next = Pointer;
  153. Pointer->Previous = NewElement;
  154. break;
  155. } else {
  156. if( Pointer->Next == NULL ) {
  157. //
  158. // Insert element if element is greater than the last
  159. // element in the list
  160. //
  161. Pointer->Next = NewElement;
  162. NewElement->Previous = Pointer;
  163. break;
  164. }
  165. }
  166. }
  167. }
  168. DblspaceModified = TRUE;
  169. return( TRUE );
  170. }
  171. BOOLEAN
  172. RemoveCompressedDrive(
  173. IN WCHAR Drive
  174. )
  175. /*++
  176. Routine Description:
  177. Remove a the entry from the list of compressed drives that describes
  178. a particular compressed drive.
  179. Arguments:
  180. Drive - Drive letter that describes a compressed drive.
  181. Return Value:
  182. BOOLEAN - Returns TRUE if the compressed drive was successfuly removed
  183. from the list of compressed drives. Returns FALSE
  184. if the drive was not found in the data base.
  185. --*/
  186. {
  187. PACTIVATE_DRIVE Pointer;
  188. BOOLEAN Status;
  189. Status = FALSE;
  190. Pointer = DblspaceInfo.CompressedDriveList;
  191. for( ; Pointer; Pointer = Pointer->Next ) {
  192. if( Pointer->MountDrive == Drive ) {
  193. if( Pointer->Previous != NULL ) {
  194. Pointer->Previous->Next = Pointer->Next;
  195. }
  196. if( Pointer->Next != NULL ) {
  197. Pointer->Next->Previous = Pointer->Previous;
  198. }
  199. if( Pointer == DblspaceInfo.CompressedDriveList ) {
  200. DblspaceInfo.CompressedDriveList = Pointer->Next;
  201. }
  202. SpMemFree( Pointer );
  203. Status = TRUE;
  204. DblspaceModified = TRUE;
  205. break;
  206. }
  207. }
  208. return( Status );
  209. }
  210. VOID
  211. DumpDblspaceInfo()
  212. /*++
  213. Routine Description:
  214. Dump the information stored in the global variable DblspaceInfo
  215. into the debugger.
  216. Arguments:
  217. None.
  218. Return Value:
  219. None.
  220. --*/
  221. {
  222. PACTIVATE_DRIVE Pointer;
  223. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "MaxRemovableDrives=%d\n",
  224. DblspaceInfo.MaxRemovableDrives ));
  225. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "FirstDrive=%c\n",
  226. ( CHAR )DblspaceInfo.FirstDrive ));
  227. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "LastDrive=%c\n",
  228. ( CHAR )DblspaceInfo.LastDrive ));
  229. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "MaxFileFragments=%d\n",
  230. DblspaceInfo.MaxFileFragments ));
  231. for( Pointer = DblspaceInfo.CompressedDriveList;
  232. Pointer;
  233. Pointer = Pointer->Next ) {
  234. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "ActivateDrive=%c,%c%d\n",
  235. ( CHAR )Pointer->MountDrive,
  236. ( CHAR )Pointer->HostDrive,
  237. Pointer->SeqNumber ));
  238. }
  239. }
  240. VOID
  241. DumpCompressedDrives(
  242. IN PDISK_REGION HostRegion
  243. )
  244. /*++
  245. Routine Description:
  246. Dump the compressed drive list associated to a particular host drive,
  247. into the debugger
  248. Arguments:
  249. None.
  250. Return Value:
  251. None.
  252. --*/
  253. {
  254. PDISK_REGION CurrentDrive;
  255. if( ( HostRegion->Filesystem == FilesystemFat ) &&
  256. ( HostRegion->NextCompressed != NULL ) ) {
  257. for( CurrentDrive = HostRegion;
  258. CurrentDrive;
  259. CurrentDrive = CurrentDrive->NextCompressed ) {
  260. if( CurrentDrive->Filesystem == FilesystemFat ) {
  261. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "HostDrive = %wc\n", CurrentDrive->HostDrive) );
  262. } else {
  263. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "CompressedDrive = %wc, HostDrive = %wc, CVF = %wc:DBLSPACE.%03d\n", CurrentDrive->MountDrive, CurrentDrive->HostRegion->HostDrive, CurrentDrive->HostDrive, CurrentDrive->SeqNumber ) );
  264. }
  265. }
  266. }
  267. }
  268. VOID
  269. DumpAllCompressedDrives()
  270. /*++
  271. Routine Description:
  272. Traverse all the structures that represent partitions and dump
  273. all compressed drives into the debugger.
  274. Arguments:
  275. None.
  276. Return Value:
  277. None.
  278. --*/
  279. {
  280. ULONG DiskNumber;
  281. PPARTITIONED_DISK pDisk;
  282. PDISK_REGION pRegion;
  283. unsigned pass;
  284. for( DiskNumber = 0; DiskNumber < HardDiskCount; DiskNumber++ ) {
  285. pDisk = &PartitionedDisks[DiskNumber];
  286. for(pass=0; pass<2; pass++) {
  287. pRegion = pass ? pDisk->ExtendedDiskRegions : pDisk->PrimaryDiskRegions;
  288. for( ; pRegion; pRegion=pRegion->Next) {
  289. DumpCompressedDrives( pRegion );
  290. }
  291. }
  292. }
  293. }
  294. BOOLEAN
  295. SpLoadDblspaceIni()
  296. /*++
  297. Routine Description:
  298. Read and parse dblspace.ini, if one is found.
  299. Arguments:
  300. None.
  301. Return Value:
  302. BOOLEAN - Returns TRUE if dblspace.ini was read successfully.
  303. Returns FALSE otherwise.
  304. --*/
  305. {
  306. PDISK_REGION CColonRegion;
  307. WCHAR NtPath[ 512 ];
  308. NTSTATUS Status;
  309. PVOID Handle;
  310. ULONG ErrorLine;
  311. ULONG LineNumber;
  312. PWCHAR Key;
  313. PWCHAR Value1;
  314. PWCHAR Value2;
  315. PWCHAR Value3;
  316. UINT ValueSize;
  317. ULONG CvfNumber;
  318. ULONG MaxNumber;
  319. PWCHAR AuxPointer;
  320. // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Entering SpLoadDblspaceIni\n"));
  321. //
  322. // See if there is a valid C: already. If not, then silently fail.
  323. //
  324. #ifndef _X86_
  325. return( FALSE );
  326. #else
  327. CColonRegion = SpPtValidSystemPartition();
  328. if(!CColonRegion) {
  329. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: no C:, no dblspace.ini!\n"));
  330. return(FALSE);
  331. }
  332. // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Called SpPtValidSystemPartition\n"));
  333. #endif
  334. //
  335. // Check the filesystem. If not FAT, then silently fail.
  336. //
  337. if(CColonRegion->Filesystem != FilesystemFat) {
  338. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: C: is not FAT, dblspace.ini!\n"));
  339. return(FALSE);
  340. }
  341. SpNtNameFromRegion(
  342. CColonRegion,
  343. NtPath,
  344. sizeof(NtPath),
  345. PartitionOrdinalCurrent
  346. );
  347. wcscat( NtPath, DBLSPACE_INI_FILE );
  348. // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Called SpNtNameFromRegion\n"));
  349. Status = SpLoadSetupTextFile( NtPath,
  350. NULL,
  351. 0,
  352. &Handle,
  353. &ErrorLine,
  354. TRUE,
  355. FALSE
  356. );
  357. if( !NT_SUCCESS( Status ) ) {
  358. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: unable to read dblspace.ini!\n"));
  359. return( FALSE );
  360. }
  361. // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Called SpLoadSetupTextFile\n"));
  362. //
  363. // Read and interpret each line in dblspace.ini
  364. //
  365. // DblspaceInfo.ActivateDriveCount = 0;
  366. LineNumber = 0;
  367. while( ( Key = SpGetKeyName( Handle,
  368. DBLSPACE_SECTION,
  369. LineNumber ) ) != NULL ) {
  370. // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Called SpGetKeyName\n"));
  371. if( _wcsicmp( Key, KWD_ACT ) == 0 ) {
  372. //
  373. // Found an ActivateDrive= key
  374. //
  375. //
  376. // Read mount drive letter
  377. //
  378. Value1 = SpGetSectionLineIndex( Handle,
  379. DBLSPACE_SECTION,
  380. LineNumber,
  381. 0 );
  382. if( Value1 == NULL ) {
  383. //
  384. // Unable to read mount drive letter
  385. //
  386. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: unable to read Mount Drive letter from dblspace.ini!\n"));
  387. continue;
  388. }
  389. //
  390. // Validate Mount Drive letter
  391. //
  392. if( ( wcslen( Value1 ) != 1 ) ||
  393. ( !SpIsAlpha( *Value1 ) ) ) {
  394. //
  395. // Mount Drive letter is not valid
  396. //
  397. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Mount Drive letter in dblspace.ini is not legal!\n"));
  398. continue;
  399. }
  400. //
  401. // Read host drive letter
  402. //
  403. Value2 = SpGetSectionLineIndex( Handle,
  404. DBLSPACE_SECTION,
  405. LineNumber,
  406. 1 );
  407. if( Value2 == NULL ) {
  408. //
  409. // Unable to read host drive letter
  410. //
  411. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: unable to read Host Drive letter from dblspace.ini!\n"));
  412. continue;
  413. }
  414. //
  415. // Validate Host Drive letter
  416. //
  417. ValueSize = wcslen( Value2 );
  418. if( ( ( ValueSize < 2 ) || ( ValueSize > 4 ) ) ||
  419. ( !SpIsAlpha( *Value2 ) ) ) {
  420. //
  421. // Mount Drive letter is not valid
  422. //
  423. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Mount Drive letter in dblspace.ini is not legal!\n"));
  424. continue;
  425. }
  426. //
  427. // Validate CVF string
  428. //
  429. Value3 = Value2 + 1;
  430. ValueSize--;
  431. while( ValueSize != 0 ) {
  432. if( !SpIsDigit( *Value3 ) ) {
  433. //
  434. // CVF number is not valid
  435. //
  436. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: unable to read CVF number from dblspace.ini!\n"));
  437. continue;
  438. }
  439. ValueSize--;
  440. Value3++;
  441. }
  442. //
  443. // Validate CVF number
  444. //
  445. CvfNumber = (ULONG)SpStringToLong( Value2 + 1, &AuxPointer, 10 );
  446. if( CvfNumber > CVF_SEQ_MAX ) {
  447. //
  448. // CVF number is out of range
  449. //
  450. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: found an invalid CVF number in dblspace.ini!\n"));
  451. continue;
  452. }
  453. //
  454. // Save the values read in DblspaceInfo
  455. //
  456. if( !AddCompressedDrive( SpToUpper( *Value1 ),
  457. SpToUpper( *Value2 ),
  458. ( USHORT )CvfNumber ) ) {
  459. //
  460. // CVF number is out of range
  461. //
  462. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: Unable to initialize DblspaceInfo: out of memory!\n"));
  463. continue;
  464. }
  465. } else if( ( _wcsicmp( Key, KWD_FIRST ) == 0 ) ||
  466. ( _wcsicmp( Key, KWD_LAST ) == 0 ) ) {
  467. //
  468. // Read first drive
  469. //
  470. Value1 = SpGetSectionLineIndex( Handle,
  471. DBLSPACE_SECTION,
  472. LineNumber,
  473. 0 );
  474. if( Value1 == NULL ) {
  475. //
  476. // Unable to read drive letter
  477. //
  478. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: unable to read FirstDrive or LastDrive from dblspace.ini!\n"));
  479. continue;
  480. }
  481. //
  482. // Validate the drive letter
  483. //
  484. if( ( wcslen( Value1 ) != 1 ) ||
  485. ( !SpIsAlpha( *Value1 ) ) ) {
  486. //
  487. // Drive letter is not valid
  488. //
  489. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: FirstDrive or LastDrive in dblspace.ini is not legal!\n"));
  490. continue;
  491. }
  492. if( _wcsicmp( Key, KWD_FIRST ) == 0 ) {
  493. DblspaceInfo.FirstDrive = SpToUpper( *Value1 );
  494. } else {
  495. DblspaceInfo.LastDrive = SpToUpper( *Value1 );
  496. }
  497. } else if( ( _wcsicmp( Key, KWD_MAXFILE ) == 0 ) ||
  498. ( _wcsicmp( Key, KWD_MAXREM ) == 0 ) ) {
  499. //
  500. // Read MaxFileFragment or MaxRemovableDrives
  501. //
  502. Value1 = SpGetSectionLineIndex( Handle,
  503. DBLSPACE_SECTION,
  504. LineNumber,
  505. 0 );
  506. if( Value1 == NULL ) {
  507. //
  508. // Unable to read MaxFileFragments or MaxRemovableDrives
  509. //
  510. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: unable to read MaxFileFragments or MaxRemovableDrives from dblspace.ini!\n"));
  511. continue;
  512. }
  513. //
  514. // Validate MaxFileFragments or MaxRemovableDrives
  515. //
  516. Value2 = Value1;
  517. ValueSize = wcslen( Value2 );
  518. while( ValueSize != 0 ) {
  519. ValueSize--;
  520. if( !SpIsDigit( *Value2 ) ) {
  521. //
  522. // Number is not valid
  523. //
  524. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: value of MaxFileFragments or MaxRemovableDrives in dblspace.ini is not valid!\n"));
  525. ValueSize = 0;
  526. }
  527. Value2++;
  528. }
  529. //
  530. // Validate number
  531. //
  532. MaxNumber = (ULONG)SpStringToLong( Value1, &AuxPointer, 10 );
  533. //
  534. // Validate and initialize MaxFileFragments or MaxRemovableDrives
  535. //
  536. if( _wcsicmp( Key, KWD_MAXFILE ) == 0 ) {
  537. if( MaxNumber < MINFILEFRAGMENTS ) {
  538. MaxNumber = MINFILEFRAGMENTS;
  539. } else if( MaxNumber > MAXFILEFRAGMENTS ) {
  540. MaxNumber = MAXFILEFRAGMENTS;
  541. }
  542. DblspaceInfo.MaxFileFragments = ( USHORT )MaxNumber;
  543. } else {
  544. DblspaceInfo.MaxRemovableDrives = ( MaxNumber == 0 )?
  545. 1 : ( USHORT )MaxNumber;
  546. }
  547. } else if( ( _wcsicmp( Key, KWD_DOUBLEGUARD ) == 0 ) ||
  548. ( _wcsicmp( Key, KWD_ROMSERVER ) == 0 ) ||
  549. ( _wcsicmp( Key, KWD_SWITCHES ) == 0 ) ||
  550. ( _wcsicmp( Key, KWD_AUTOMOUNT ) == 0 ) ) {
  551. //
  552. // Read Doubleguard, Romerver, Switches, or Automount
  553. //
  554. Value1 = SpGetSectionLineIndex( Handle,
  555. DBLSPACE_SECTION,
  556. LineNumber,
  557. 0 );
  558. if( Value1 == NULL ) {
  559. //
  560. // Unable to read Doubleguard, Romerver, Switches, or Automount
  561. //
  562. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: unable to read Doubleguard, Romerver, Switches, or Automount from dblspace.ini!\n"));
  563. continue;
  564. }
  565. if( _wcsicmp( Key, KWD_DOUBLEGUARD ) == 0 ) {
  566. wcsncpy( DblspaceInfo.DoubleGuard,
  567. Value1,
  568. sizeof( DblspaceInfo.DoubleGuard ) / sizeof( WCHAR ) );
  569. } else if( _wcsicmp( Key, KWD_ROMSERVER ) == 0 ) {
  570. wcsncpy( DblspaceInfo.RomServer,
  571. Value1,
  572. sizeof( DblspaceInfo.RomServer ) / sizeof( WCHAR ) );
  573. } else if( _wcsicmp( Key, KWD_SWITCHES ) == 0 ) {
  574. wcsncpy( DblspaceInfo.Switches,
  575. Value1,
  576. sizeof( DblspaceInfo.Switches ) / sizeof( WCHAR ) );
  577. } else {
  578. wcsncpy( DblspaceInfo.AutoMount,
  579. Value1,
  580. sizeof( DblspaceInfo.AutoMount ) / sizeof( WCHAR ) );
  581. }
  582. } else {
  583. //
  584. // Invalid key in dblspace.ini
  585. //
  586. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_WARNING_LEVEL, "SETUP: dblspace.ini contains invalid key!\n"));
  587. continue;
  588. }
  589. LineNumber++;
  590. }
  591. SpFreeTextFile( Handle );
  592. //
  593. // Clear DblspaceModified flag, so that dblspace.ini won't get updated when
  594. // SpUpdateDoubleSpaceIni() is called, and no compressed drive was added or
  595. // deleted.
  596. //
  597. DblspaceModified = FALSE;
  598. // DumpDblspaceInfo();
  599. // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Exiting SpLoadDblspaceIni\n"));
  600. return( TRUE );
  601. }
  602. BOOLEAN
  603. IsHostDrive(
  604. IN WCHAR Drive,
  605. OUT PACTIVATE_DRIVE* Pointer
  606. )
  607. /*++
  608. Routine Description:
  609. Find out whether a particular drive is the host for a compressed drive.
  610. Arguments:
  611. Drive -
  612. Pointer - Variable that will contain the pointer for an entry in the
  613. list of compressed drives, that describes the compressed
  614. drive with the lowest sequence number, whose host drive
  615. is the drive received as parameter.
  616. Return Value:
  617. BOOLEAN - Returns TRUE if the drive passed as argument is a host drive.
  618. Returns FALSE otherwise.
  619. --*/
  620. {
  621. PACTIVATE_DRIVE p;
  622. BOOLEAN Status;
  623. Status = FALSE;
  624. for( p = DblspaceInfo.CompressedDriveList;
  625. ( p && ( p->HostDrive != Drive ) );
  626. p = p->Next );
  627. if( p ) {
  628. *Pointer = p;
  629. Status = TRUE;
  630. }
  631. return( Status );
  632. }
  633. NTSTATUS
  634. MountDoubleSpaceDrive(
  635. IN PDISK_REGION HostRegion,
  636. IN PACTIVATE_DRIVE CompressedDriveInfo
  637. )
  638. /*++
  639. Routine Description:
  640. Mount a double space drive.
  641. Arguments:
  642. HostRegion - Pointer to the structure that describes a FAT partition, that
  643. will be the host for the compressed drive.
  644. CompressedDriveInfo - Pointer to a structure that contains the information
  645. about the compressed drive to be mounted.
  646. Return Value:
  647. NTSTATUS - Returns an NT status code indicating whether or not the drive
  648. was mounted.
  649. --*/
  650. {
  651. #ifdef FULL_DOUBLE_SPACE_SUPPORT
  652. NTSTATUS Status;
  653. WCHAR HostName[512];
  654. UNICODE_STRING UnicodeDasdName;
  655. OBJECT_ATTRIBUTES ObjectAttributes;
  656. IO_STATUS_BLOCK IoStatusBlock;
  657. PIO_STATUS_BLOCK KernelModeIoStatusBlock;
  658. HANDLE Handle;
  659. PFILE_MOUNT_DBLS_BUFFER KernelModeMountFsctlBuffer;
  660. SpNtNameFromRegion(
  661. HostRegion,
  662. HostName,
  663. sizeof(HostName),
  664. PartitionOrdinalCurrent
  665. );
  666. RtlInitUnicodeString( &UnicodeDasdName, HostName );
  667. InitializeObjectAttributes( &ObjectAttributes,
  668. &UnicodeDasdName,
  669. OBJ_CASE_INSENSITIVE,
  670. NULL,
  671. NULL );
  672. Status = ZwCreateFile( &Handle,
  673. GENERIC_READ,
  674. &ObjectAttributes,
  675. &IoStatusBlock,
  676. NULL,
  677. 0,
  678. FILE_SHARE_READ | FILE_SHARE_WRITE,
  679. OPEN_EXISTING,
  680. FILE_SYNCHRONOUS_IO_NONALERT,
  681. NULL,
  682. 0 );
  683. if( !NT_SUCCESS( Status ) ) {
  684. KdPrintEx( DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, ("SETUP: NtCreateFile failed, Status = %x\n", Status ) );
  685. return( Status );
  686. }
  687. //
  688. // Note that since we use the NtFsControlFile API instead of the
  689. // Zw API (this one is not exported), we need a buffer for IoStatusBlock
  690. // and for MountBuffer, that can be used in kernel mode.
  691. // We use the the region of memory pointed by CommunicationParams for this
  692. // purpose.
  693. //
  694. KernelModeIoStatusBlock = ( PIO_STATUS_BLOCK )( &(CommunicationParams->Buffer[0]) );
  695. *KernelModeIoStatusBlock = IoStatusBlock;
  696. KernelModeMountFsctlBuffer = ( PFILE_MOUNT_DBLS_BUFFER )( &(CommunicationParams->Buffer[128]) );
  697. KernelModeMountFsctlBuffer->CvfNameLength =
  698. sizeof(WCHAR) * swprintf( KernelModeMountFsctlBuffer->CvfName,
  699. CVF_NAME_PATTERN,
  700. CompressedDriveInfo->SeqNumber );
  701. Status = NtFsControlFile( Handle,
  702. NULL,
  703. NULL,
  704. NULL,
  705. KernelModeIoStatusBlock,
  706. FSCTL_MOUNT_DBLS_VOLUME,
  707. KernelModeMountFsctlBuffer,
  708. sizeof( FILE_MOUNT_DBLS_BUFFER ) + 12*sizeof( WCHAR ),
  709. NULL,
  710. 0 );
  711. if( !NT_SUCCESS( Status ) ) {
  712. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to mount %ls. NtFsControlFile returned Status = %x\n",
  713. KernelModeMountFsctlBuffer->CvfName, Status ) );
  714. }
  715. ZwClose( Handle );
  716. return( Status );
  717. #else //FULL_DOUBLE_SPACE_SUPPORT
  718. return( STATUS_SUCCESS );
  719. #endif
  720. }
  721. VOID
  722. MountCompressedDrives(
  723. IN PDISK_REGION HostRegion
  724. )
  725. /*++
  726. Routine Description:
  727. Mount all compressed drives detected on a partition.
  728. Arguments:
  729. HostRegion - Pointer to the structure that describes a FAT partition.
  730. Return Value:
  731. None.
  732. --*/
  733. {
  734. PDISK_REGION CompressedList;
  735. PDISK_REGION CurrentDrive;
  736. PDISK_REGION TmpPointer;
  737. WCHAR HostDrive;
  738. PACTIVATE_DRIVE Pointer;
  739. CompressedList = NULL;
  740. CurrentDrive = NULL;
  741. if( ( HostRegion != NULL ) &&
  742. ( HostRegion->Filesystem == FilesystemFat ) &&
  743. IsHostDrive( HostRegion->DriveLetter, &Pointer )
  744. ) {
  745. HostDrive = HostRegion->DriveLetter;
  746. for( ;
  747. ( Pointer && ( HostDrive == Pointer->HostDrive ));
  748. Pointer = Pointer->Next ) {
  749. //
  750. // Mount the drive
  751. //
  752. if( NT_SUCCESS( MountDoubleSpaceDrive( HostRegion, Pointer) ) ) {
  753. //
  754. // Drive was mounted successfully
  755. //
  756. TmpPointer =
  757. SpPtAllocateDiskRegionStructure( HostRegion->DiskNumber,
  758. HostRegion->StartSector,
  759. HostRegion->SectorCount,
  760. HostRegion->PartitionedSpace,
  761. HostRegion->MbrInfo,
  762. HostRegion->TablePosition );
  763. ASSERT( TmpPointer );
  764. if( TmpPointer == NULL ) {
  765. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to allocate memory\n" ) );
  766. //
  767. // Unmount drive
  768. //
  769. continue;
  770. }
  771. TmpPointer->NextCompressed = NULL;
  772. TmpPointer->HostRegion = HostRegion;
  773. TmpPointer->Filesystem = FilesystemDoubleSpace;
  774. TmpPointer->SeqNumber = Pointer->SeqNumber;
  775. if( TmpPointer->SeqNumber == 0 ) {
  776. TmpPointer->MountDrive = Pointer->HostDrive;
  777. TmpPointer->HostDrive = Pointer->MountDrive;
  778. HostRegion->HostDrive = TmpPointer->HostDrive;
  779. } else {
  780. TmpPointer->MountDrive = Pointer->MountDrive;
  781. if( HostRegion->HostDrive == 0 ) {
  782. HostRegion->HostDrive = Pointer->HostDrive;
  783. }
  784. TmpPointer->HostDrive = HostRegion->HostDrive;
  785. }
  786. swprintf( TmpPointer->TypeName,
  787. CVF_NAME_PATTERN,
  788. TmpPointer->SeqNumber );
  789. if( CompressedList == NULL ) {
  790. TmpPointer->PreviousCompressed = NULL;
  791. CompressedList = TmpPointer;
  792. } else {
  793. TmpPointer->PreviousCompressed = CurrentDrive;
  794. CurrentDrive->NextCompressed = TmpPointer;
  795. }
  796. CurrentDrive = TmpPointer;
  797. }
  798. }
  799. }
  800. HostRegion->NextCompressed = CompressedList;
  801. }
  802. VOID
  803. SpInitializeCompressedDrives()
  804. /*++
  805. Routine Description:
  806. Traverse the structure that describes all the disks in the system,
  807. and mount all compressed drives previously identified.
  808. Arguments:
  809. None.
  810. Return Value:
  811. None.
  812. --*/
  813. {
  814. ULONG DiskNumber;
  815. PPARTITIONED_DISK pDisk;
  816. PDISK_REGION pRegion;
  817. unsigned pass;
  818. for( DiskNumber = 0; DiskNumber < HardDiskCount; DiskNumber++ ) {
  819. pDisk = &PartitionedDisks[DiskNumber];
  820. for(pass=0; pass<2; pass++) {
  821. pRegion = pass ? pDisk->ExtendedDiskRegions : pDisk->PrimaryDiskRegions;
  822. for( ; pRegion; pRegion=pRegion->Next) {
  823. MountCompressedDrives( pRegion );
  824. }
  825. }
  826. }
  827. // DumpAllCompressedDrives();
  828. }
  829. VOID
  830. SpDisposeCompressedDrives(
  831. PDISK_REGION CompressedDrive
  832. )
  833. /*++
  834. Routine Description:
  835. Delete the list of compressed drives found in a structure
  836. associated with a partition in the disk.
  837. This function is called when the user deletes a host partition
  838. that contains compressed drives.
  839. The list of compressed drives kept in the global variable DblspaceInfo
  840. is updated so that it reflects the changes made by the user.
  841. Arguments:
  842. CompressedDrive - Pointer to the first element of a compressed drive list.
  843. Return Value:
  844. None.
  845. --*/
  846. {
  847. ASSERT( CompressedDrive->Filesystem == FilesystemDoubleSpace );
  848. if( CompressedDrive->NextCompressed != NULL ) {
  849. SpDisposeCompressedDrives( CompressedDrive->NextCompressed );
  850. }
  851. if( CompressedDrive->SeqNumber != 0 ) {
  852. RemoveCompressedDrive( CompressedDrive->MountDrive );
  853. } else {
  854. RemoveCompressedDrive( CompressedDrive->HostDrive );
  855. }
  856. SpMemFree( CompressedDrive );
  857. }
  858. BOOLEAN
  859. SpUpdateDoubleSpaceIni()
  860. /*++
  861. Routine Description:
  862. Update dblspace.ini to reflect all changes made by the user, with respect
  863. to compressed drives deleted or created.
  864. Arguments:
  865. None.
  866. Return Value:
  867. BOOLEAN - Returns TRUE if dblspace.ini was successfully updated.
  868. Returns FALSE otherwise.
  869. --*/
  870. {
  871. PDISK_REGION CColonRegion;
  872. WCHAR NtPath[ 512 ];
  873. UNICODE_STRING FileName;
  874. NTSTATUS Status;
  875. HANDLE Handle;
  876. OBJECT_ATTRIBUTES ObjectAttributes;
  877. IO_STATUS_BLOCK IoStatusBlock;
  878. CHAR Buffer[ 512 ];
  879. PACTIVATE_DRIVE Pointer;
  880. // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Entering SpUpdateDblspaceIni\n"));
  881. //
  882. // If no compressed drive was created or deleted, then do not
  883. // touch dblspace.ini
  884. //
  885. if( !DblspaceModified ) {
  886. return( TRUE );
  887. }
  888. //
  889. // See if there is a valid C: already. If not, then silently fail.
  890. //
  891. #ifndef _X86_
  892. return( FALSE );
  893. #else
  894. CColonRegion = SpPtValidSystemPartition();
  895. if(!CColonRegion) {
  896. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: no C:, no dblspace.ini!\n"));
  897. return(FALSE);
  898. }
  899. // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Called SpPtValidSystemPartition\n"));
  900. #endif
  901. //
  902. // Check the filesystem. If not FAT, then silently fail.
  903. //
  904. if(CColonRegion->Filesystem != FilesystemFat) {
  905. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: C: is not FAT, no dblspace.ini!\n"));
  906. return(FALSE);
  907. }
  908. SpNtNameFromRegion(
  909. CColonRegion,
  910. NtPath,
  911. sizeof(NtPath),
  912. PartitionOrdinalCurrent
  913. );
  914. wcscat( NtPath, DBLSPACE_INI_FILE );
  915. Status = SpDeleteFile( NtPath, NULL, NULL );
  916. if( !NT_SUCCESS( Status ) &&
  917. ( Status != STATUS_OBJECT_NAME_NOT_FOUND ) ) {
  918. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Unable to delete dblspace.ini, Status = %x\n",Status ) );
  919. return( FALSE );
  920. }
  921. //
  922. // If the user deleted all compressed drives, then don't create a new
  923. // dblspace.ini
  924. //
  925. // if( DblspaceInfo.CompressedDriveList == NULL ) {
  926. // return( TRUE );
  927. // }
  928. //
  929. // Create and write a new dblspace.ini
  930. //
  931. RtlInitUnicodeString( &FileName, NtPath );
  932. InitializeObjectAttributes( &ObjectAttributes,
  933. &FileName,
  934. OBJ_CASE_INSENSITIVE,
  935. NULL,
  936. NULL );
  937. Status = ZwCreateFile( &Handle,
  938. FILE_GENERIC_READ | FILE_GENERIC_WRITE,
  939. &ObjectAttributes,
  940. &IoStatusBlock,
  941. NULL,
  942. FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM,
  943. 0,
  944. FILE_OVERWRITE_IF,
  945. FILE_SYNCHRONOUS_IO_NONALERT,
  946. NULL,
  947. 0 );
  948. if( !NT_SUCCESS( Status ) ) {
  949. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to create dblspace.ini, Status = %x\n", Status ) );
  950. return( FALSE );
  951. }
  952. sprintf( Buffer,
  953. "%ls=%d\r\n",
  954. KWD_MAXREM,
  955. DblspaceInfo.MaxRemovableDrives
  956. );
  957. Status = ZwWriteFile( Handle,
  958. NULL,
  959. NULL,
  960. NULL,
  961. &IoStatusBlock,
  962. Buffer,
  963. strlen( Buffer ),
  964. NULL,
  965. NULL );
  966. if( !NT_SUCCESS( Status ) ) {
  967. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to write MaxRemovableDrives to dblspace.ini, Status = %x\n", Status ));
  968. ZwClose( Handle );
  969. return( FALSE );
  970. }
  971. if( DblspaceInfo.FirstDrive != ( WCHAR )'\0' ) {
  972. sprintf( Buffer,
  973. "%ls=%c\r\n",
  974. KWD_FIRST,
  975. DblspaceInfo.FirstDrive
  976. );
  977. Status = ZwWriteFile( Handle,
  978. NULL,
  979. NULL,
  980. NULL,
  981. &IoStatusBlock,
  982. Buffer,
  983. strlen( Buffer ),
  984. NULL,
  985. NULL );
  986. if( !NT_SUCCESS( Status ) ) {
  987. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to write FirstDrive to dblspace.ini, Status = %x\n", Status ));
  988. ZwClose( Handle );
  989. return( FALSE );
  990. }
  991. }
  992. if( DblspaceInfo.LastDrive != ( WCHAR )'\0' ) {
  993. sprintf( Buffer,
  994. "%ls=%c\r\n",
  995. KWD_LAST,
  996. DblspaceInfo.LastDrive
  997. );
  998. Status = ZwWriteFile( Handle,
  999. NULL,
  1000. NULL,
  1001. NULL,
  1002. &IoStatusBlock,
  1003. Buffer,
  1004. strlen( Buffer ),
  1005. NULL,
  1006. NULL );
  1007. if( !NT_SUCCESS( Status ) ) {
  1008. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to write LastDrive to dblspace.ini, Status = %x\n", Status ));
  1009. ZwClose( Handle );
  1010. return( FALSE );
  1011. }
  1012. }
  1013. sprintf( Buffer,
  1014. "%ls=%d\r\n",
  1015. KWD_MAXFILE,
  1016. DblspaceInfo.MaxFileFragments
  1017. );
  1018. Status = ZwWriteFile( Handle,
  1019. NULL,
  1020. NULL,
  1021. NULL,
  1022. &IoStatusBlock,
  1023. Buffer,
  1024. strlen( Buffer ),
  1025. NULL,
  1026. NULL );
  1027. if( !NT_SUCCESS( Status ) ) {
  1028. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to write LastDrive to dblspace.ini, Status = %x\n", Status ));
  1029. ZwClose( Handle );
  1030. return( FALSE );
  1031. }
  1032. if( wcslen( DblspaceInfo.DoubleGuard ) != 0 ) {
  1033. sprintf( Buffer,
  1034. "%ls=%ls\r\n",
  1035. KWD_AUTOMOUNT,
  1036. DblspaceInfo.AutoMount
  1037. );
  1038. Status = ZwWriteFile( Handle,
  1039. NULL,
  1040. NULL,
  1041. NULL,
  1042. &IoStatusBlock,
  1043. Buffer,
  1044. strlen( Buffer ),
  1045. NULL,
  1046. NULL );
  1047. if( !NT_SUCCESS( Status ) ) {
  1048. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to write Automount to dblspace.ini, Status = %x\n", Status ));
  1049. ZwClose( Handle );
  1050. return( FALSE );
  1051. }
  1052. }
  1053. if( wcslen( DblspaceInfo.RomServer ) != 0 ) {
  1054. sprintf( Buffer,
  1055. "%ls=%ls\r\n",
  1056. KWD_ROMSERVER,
  1057. DblspaceInfo.RomServer
  1058. );
  1059. Status = ZwWriteFile( Handle,
  1060. NULL,
  1061. NULL,
  1062. NULL,
  1063. &IoStatusBlock,
  1064. Buffer,
  1065. strlen( Buffer ),
  1066. NULL,
  1067. NULL );
  1068. if( !NT_SUCCESS( Status ) ) {
  1069. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to write Romserver to dblspace.ini, Status = %x\n", Status ));
  1070. ZwClose( Handle );
  1071. return( FALSE );
  1072. }
  1073. }
  1074. if( wcslen( DblspaceInfo.Switches ) != 0 ) {
  1075. sprintf( Buffer,
  1076. "%ls=%ls\r\n",
  1077. KWD_SWITCHES,
  1078. DblspaceInfo.Switches
  1079. );
  1080. Status = ZwWriteFile( Handle,
  1081. NULL,
  1082. NULL,
  1083. NULL,
  1084. &IoStatusBlock,
  1085. Buffer,
  1086. strlen( Buffer ),
  1087. NULL,
  1088. NULL );
  1089. if( !NT_SUCCESS( Status ) ) {
  1090. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to write Switches to dblspace.ini, Status = %x\n", Status ));
  1091. ZwClose( Handle );
  1092. return( FALSE );
  1093. }
  1094. }
  1095. if( wcslen( DblspaceInfo.DoubleGuard ) != 0 ) {
  1096. sprintf( Buffer,
  1097. "%ls=%ls\r\n",
  1098. KWD_DOUBLEGUARD,
  1099. DblspaceInfo.DoubleGuard
  1100. );
  1101. Status = ZwWriteFile( Handle,
  1102. NULL,
  1103. NULL,
  1104. NULL,
  1105. &IoStatusBlock,
  1106. Buffer,
  1107. strlen( Buffer ),
  1108. NULL,
  1109. NULL );
  1110. if( !NT_SUCCESS( Status ) ) {
  1111. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to write Doubleguard to dblspace.ini, Status = %x\n", Status ));
  1112. ZwClose( Handle );
  1113. return( FALSE );
  1114. }
  1115. }
  1116. for( Pointer = DblspaceInfo.CompressedDriveList;
  1117. Pointer;
  1118. Pointer = Pointer->Next ) {
  1119. sprintf( Buffer,
  1120. "%ls=%c,%c%d\r\n",
  1121. KWD_ACT,
  1122. Pointer->MountDrive,
  1123. Pointer->HostDrive,
  1124. Pointer->SeqNumber
  1125. );
  1126. Status = ZwWriteFile( Handle,
  1127. NULL,
  1128. NULL,
  1129. NULL,
  1130. &IoStatusBlock,
  1131. Buffer,
  1132. strlen( Buffer ),
  1133. NULL,
  1134. NULL );
  1135. if( !NT_SUCCESS( Status ) ) {
  1136. KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_ERROR_LEVEL, "SETUP: Unable to write to dblspace.ini, Status = %x\n", Status ));
  1137. ZwClose( Handle );
  1138. return( FALSE );
  1139. }
  1140. }
  1141. ZwClose( Handle );
  1142. // KdPrintEx((DPFLTR_SETUP_ID, DPFLTR_INFO_LEVEL, "SETUP: Exiting SpUpdateDblspaceIni\n"));
  1143. return( TRUE );
  1144. }
  1145. ULONG
  1146. SpGetNumberOfCompressedDrives(
  1147. IN PDISK_REGION Partition
  1148. )
  1149. /*++
  1150. Routine Description:
  1151. Determine the number of compressed volumes on a particular partition.
  1152. Arguments:
  1153. Partition - Pointer to the structure that describes a partition.
  1154. Return Value:
  1155. ULONG - Returns the number of compressed drives found on the partition.
  1156. --*/
  1157. {
  1158. ULONG Count;
  1159. PDISK_REGION Pointer;
  1160. Count = 0;
  1161. if( ( Partition != NULL ) &&
  1162. ( Partition->Filesystem == FilesystemFat )
  1163. ) {
  1164. for( Pointer = Partition->NextCompressed;
  1165. Pointer;
  1166. Pointer = Pointer->NextCompressed ) {
  1167. Count++;
  1168. }
  1169. }
  1170. return( Count );
  1171. }