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.

749 lines
15 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. /*++
  4. Copyright (c) 1990 Microsoft Corporation
  5. Module Name:
  6. det_vol.c
  7. Abstract:
  8. Disk/volume related detect operations for Win32 PDK Setup.
  9. This module has no external dependencies and is not statically linked
  10. to any part of Setup.
  11. Author:
  12. Ted Miller (tedm) June-August 1991
  13. --*/
  14. #define SPACE_FREE 1
  15. #define SPACE_TOTAL 2
  16. #define DRIVE_TYPE_REMOVABLE "RMV"
  17. #define DRIVE_TYPE_FIXED "FIX"
  18. #define DRIVE_TYPE_REMOTE "REM"
  19. #define DRIVE_TYPE_CDROM "CDR"
  20. #define DRIVE_TYPE_RAMDISK "RAM"
  21. #define DRIVE_TYPE_UNKNOWN "?"
  22. #define GET_TIME_CREATION 1
  23. #define GET_TIME_LASTACCESS 2
  24. #define GET_TIME_LASTWRITE 3
  25. CB GetTimeOfFile(RGSZ,USHORT,SZ,CB,DWORD);
  26. CB GetDrivesWorker(RGSZ,USHORT,SZ,CB,DWORD);
  27. DWORD AreDrivesACertainType(DWORD,BOOL *);
  28. VOID ConstructDiskList(BOOL *,LPSTR);
  29. CB GetSpaceWorker(SZ,CB,DWORD);
  30. //
  31. // Routine to get a drive type. Like GetDriveType() win32 api except
  32. // it attempts to differentiate between removable hard drives and floppies.
  33. // Removeable hard drives will returned as DRIVE_FIXED so we can use
  34. // DRIVE_REMOVABLE as a symonym for "floppy."
  35. //
  36. UINT
  37. MyGetDriveType(
  38. IN PSTR DriveName
  39. )
  40. {
  41. CHAR DriveNameNt[MAX_PATH];
  42. UINT rc;
  43. //
  44. // First, get the win32 drive type. If it tells us DRIVE_REMOVABLE,
  45. // then we need to see whether it's a floppy or hard disk. Otherwise
  46. // just believe the api.
  47. //
  48. if((rc = GetDriveType(DriveName)) == DRIVE_REMOVABLE) {
  49. if(DosPathToNtPathWorker(DriveName,DriveNameNt)) {
  50. CharLower(DriveNameNt);
  51. if(!strstr(DriveNameNt,"floppy")) {
  52. rc = DRIVE_FIXED;
  53. }
  54. }
  55. }
  56. return(rc);
  57. }
  58. //
  59. // Gets unused drives
  60. //
  61. CB
  62. GetUnusedDrives(
  63. IN RGSZ Args,
  64. IN USHORT cArgs,
  65. OUT SZ ReturnBuffer,
  66. IN CB cbReturnBuffer
  67. )
  68. {
  69. SZ sz;
  70. RGSZ rgsz;
  71. DWORD Disk;
  72. CHAR szRoot[4] = "?:\\";
  73. CHAR szDrive[3] = "?:";
  74. CB cbRet;
  75. Unused( Args );
  76. Unused( cArgs );
  77. Unused( cbReturnBuffer );
  78. rgsz = RgszAlloc(1);
  79. for( Disk = 26; Disk > 0; Disk-- ) {
  80. szRoot[0] = (CHAR)(Disk - 1) + (CHAR)'A';
  81. if ( MyGetDriveType( szRoot ) == 1 ) {
  82. szDrive[0] = szRoot[0];
  83. RgszAdd( &rgsz, SzDup( szDrive ) );
  84. }
  85. }
  86. sz = SzListValueFromRgsz( rgsz );
  87. lstrcpy( ReturnBuffer, sz );
  88. cbRet = lstrlen( sz );
  89. SFree( sz );
  90. RgszFree( rgsz );
  91. return( cbRet + 1 );
  92. }
  93. //
  94. // Gets the type of a drive
  95. //
  96. CB
  97. GetTypeOfDrive(
  98. IN RGSZ Args,
  99. IN USHORT cArgs,
  100. OUT SZ ReturnBuffer,
  101. IN CB cbReturnBuffer
  102. )
  103. {
  104. SZ szType;
  105. CHAR szRoot[ MAX_PATH];
  106. SZ sz;
  107. Unused( cbReturnBuffer );
  108. if ( (cArgs >= 1) && (*(Args[0]) != '\0') ) {
  109. lstrcpy( szRoot, Args[0] );
  110. sz = szRoot + strlen(szRoot) -1;
  111. if ( *sz != '\\' ) {
  112. strcat( szRoot, "\\" );
  113. }
  114. switch (MyGetDriveType( szRoot )) {
  115. case 0:
  116. case 1:
  117. return 0;
  118. case DRIVE_REMOVABLE:
  119. szType = DRIVE_TYPE_REMOVABLE;
  120. break;
  121. case DRIVE_FIXED:
  122. szType = DRIVE_TYPE_FIXED;
  123. break;
  124. case DRIVE_REMOTE:
  125. szType = DRIVE_TYPE_REMOTE;
  126. break;
  127. case DRIVE_CDROM:
  128. szType = DRIVE_TYPE_CDROM;
  129. break;
  130. case DRIVE_RAMDISK:
  131. szType = DRIVE_TYPE_RAMDISK;
  132. break;
  133. default:
  134. szType = DRIVE_TYPE_UNKNOWN;
  135. break;
  136. }
  137. } else {
  138. szType= DRIVE_TYPE_UNKNOWN;
  139. }
  140. lstrcpy( ReturnBuffer, szType );
  141. return lstrlen( ReturnBuffer )+1;
  142. }
  143. //
  144. // Determines the existence of a directory
  145. //
  146. CB
  147. DoesDirExist(
  148. IN RGSZ Args,
  149. IN USHORT cArgs,
  150. OUT SZ ReturnBuffer,
  151. IN CB cbReturnBuffer
  152. )
  153. {
  154. DWORD Attr;
  155. Unused( cbReturnBuffer );
  156. if ( cArgs == 0 ) {
  157. ReturnBuffer[0] = '\0';
  158. return 0;
  159. } else {
  160. Attr = GetFileAttributes( Args[0] );
  161. if ((Attr != -1) && ( Attr & FILE_ATTRIBUTE_DIRECTORY )) {
  162. lstrcpy( ReturnBuffer, "YES" );
  163. } else {
  164. lstrcpy( ReturnBuffer, "NO" );
  165. }
  166. }
  167. return lstrlen(ReturnBuffer)+1;
  168. }
  169. //
  170. // Determines the existence of a file
  171. //
  172. CB
  173. DoesFileExist(
  174. IN RGSZ Args,
  175. IN USHORT cArgs,
  176. OUT SZ ReturnBuffer,
  177. IN CB cbReturnBuffer
  178. )
  179. {
  180. DWORD Attr;
  181. Unused( cbReturnBuffer );
  182. if ( cArgs == 0 ) {
  183. ReturnBuffer[0] = '\0';
  184. return 0;
  185. } else {
  186. Attr = GetFileAttributes( Args[0] );
  187. if ((Attr != -1) && !( Attr & FILE_ATTRIBUTE_DIRECTORY )) {
  188. lstrcpy( ReturnBuffer, "YES" );
  189. } else {
  190. lstrcpy( ReturnBuffer, "NO" );
  191. }
  192. }
  193. return lstrlen(ReturnBuffer)+1;
  194. }
  195. //
  196. // Get file size
  197. //
  198. CB
  199. GetSizeOfFile(
  200. IN RGSZ Args,
  201. IN USHORT cArgs,
  202. OUT SZ ReturnBuffer,
  203. IN CB cbReturnBuffer
  204. )
  205. {
  206. HANDLE hff;
  207. WIN32_FIND_DATA ffd;
  208. DWORD Size = 0;
  209. #define ZERO_SIZE "0"
  210. Unused( cbReturnBuffer );
  211. ReturnBuffer[0] = '\0';
  212. if (cArgs > 0) {
  213. //
  214. // get find file information and get the size information out of
  215. // that
  216. //
  217. if ((hff = FindFirstFile(Args[0], &ffd)) != INVALID_HANDLE_VALUE) {
  218. Size = ffd.nFileSizeLow;
  219. _ltoa(Size, ReturnBuffer, 10);
  220. FindClose(hff);
  221. return lstrlen(ReturnBuffer)+1;
  222. }
  223. }
  224. //
  225. // If file not specified or file not found default return 0 size
  226. //
  227. lstrcpy( ReturnBuffer, ZERO_SIZE );
  228. return lstrlen(ReturnBuffer)+1;
  229. }
  230. //
  231. // Obtains creation time of a file
  232. //
  233. CB
  234. GetFileCreationTime(
  235. IN RGSZ Args,
  236. IN USHORT cArgs,
  237. OUT SZ ReturnBuffer,
  238. IN CB cbReturnBuffer
  239. )
  240. {
  241. return GetTimeOfFile( Args, cArgs, ReturnBuffer, cbReturnBuffer, GET_TIME_CREATION );
  242. }
  243. //
  244. // Obtains last access time of a file
  245. //
  246. CB
  247. GetFileLastAccessTime(
  248. IN RGSZ Args,
  249. IN USHORT cArgs,
  250. OUT SZ ReturnBuffer,
  251. IN CB cbReturnBuffer
  252. )
  253. {
  254. return GetTimeOfFile( Args, cArgs, ReturnBuffer, cbReturnBuffer, GET_TIME_LASTACCESS );
  255. }
  256. //
  257. // Obtains last write time of a file
  258. //
  259. CB
  260. GetFileLastWriteTime(
  261. IN RGSZ Args,
  262. IN USHORT cArgs,
  263. OUT SZ ReturnBuffer,
  264. IN CB cbReturnBuffer
  265. )
  266. {
  267. return GetTimeOfFile( Args, cArgs, ReturnBuffer, cbReturnBuffer, GET_TIME_LASTWRITE );
  268. }
  269. //
  270. // Obtains any time of a file
  271. //
  272. CB
  273. GetTimeOfFile(
  274. IN RGSZ Args,
  275. IN USHORT cArgs,
  276. OUT SZ ReturnBuffer,
  277. IN CB cbReturnBuffer,
  278. IN DWORD WhatTime
  279. )
  280. {
  281. HANDLE Handle;
  282. FILETIME TimeCreation;
  283. FILETIME TimeLastAccess;
  284. FILETIME TimeLastWrite;
  285. FILETIME WantedTime;
  286. Unused( cbReturnBuffer );
  287. ReturnBuffer[0] = '\0';
  288. if ( ( cArgs > 0) &&
  289. (WhatTime >= GET_TIME_CREATION) &&
  290. (WhatTime <= GET_TIME_LASTWRITE) ) {
  291. Handle = CreateFile( Args[0],
  292. GENERIC_READ,
  293. FILE_SHARE_READ | FILE_SHARE_WRITE,
  294. NULL,
  295. OPEN_EXISTING,
  296. 0,
  297. NULL );
  298. if ( Handle != INVALID_HANDLE_VALUE ) {
  299. if ( GetFileTime( Handle, &TimeCreation, &TimeLastAccess, &TimeLastWrite ) ) {
  300. switch( WhatTime ) {
  301. case GET_TIME_CREATION:
  302. WantedTime = TimeCreation;
  303. break;
  304. case GET_TIME_LASTACCESS:
  305. WantedTime = TimeLastAccess;
  306. break;
  307. case GET_TIME_LASTWRITE:
  308. WantedTime = TimeLastWrite;
  309. break;
  310. default:
  311. break;
  312. }
  313. }
  314. CloseHandle( Handle );
  315. wsprintf( ReturnBuffer, "{\"%lu\",\"%lu\"}", WantedTime.dwLowDateTime,
  316. WantedTime.dwHighDateTime );
  317. return lstrlen(ReturnBuffer)+1;
  318. }
  319. }
  320. return 0;
  321. }
  322. /*
  323. Return a list of floppy drive letters
  324. */
  325. CB
  326. GetFloppyDriveLetters(
  327. IN RGSZ Args,
  328. IN USHORT cArgs,
  329. OUT SZ ReturnBuffer,
  330. IN CB cbReturnBuffer
  331. )
  332. {
  333. return(GetDrivesWorker(Args,
  334. cArgs,
  335. ReturnBuffer,
  336. cbReturnBuffer,
  337. DRIVE_REMOVABLE
  338. )
  339. );
  340. }
  341. /*
  342. Return a list of hard drive letters
  343. */
  344. CB
  345. GetHardDriveLetters(
  346. IN RGSZ Args,
  347. IN USHORT cArgs,
  348. OUT SZ ReturnBuffer,
  349. IN CB cbReturnBuffer
  350. )
  351. {
  352. return(GetDrivesWorker(Args,
  353. cArgs,
  354. ReturnBuffer,
  355. cbReturnBuffer,
  356. DRIVE_FIXED
  357. )
  358. );
  359. }
  360. /*
  361. Return a list of filesystems on all hard drive volumes.
  362. */
  363. CB
  364. GetHardDriveFileSystems(
  365. IN RGSZ Args,
  366. IN USHORT cArgs,
  367. OUT SZ ReturnBuffer,
  368. IN CB cbReturnBuffer
  369. )
  370. {
  371. BOOL HardDisk[26];
  372. DWORD Disk;
  373. LPSTR InsertPoint = ReturnBuffer;
  374. char DiskName[4] = { 'x',':','\\','\0' };
  375. char FileSys[MAX_PATH];
  376. DWORD SizeSoFar;
  377. UINT ErrorMode;
  378. Unused(Args);
  379. Unused(cArgs);
  380. AreDrivesACertainType(DRIVE_FIXED,HardDisk);
  381. *InsertPoint++ = '{';
  382. SizeSoFar = 2;
  383. ErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX );
  384. for(Disk=0; Disk<26; Disk++) {
  385. if(HardDisk[Disk]) {
  386. DiskName[0] = (char)Disk + (char)'A';
  387. if(!GetVolumeInformation(DiskName,NULL,0,NULL,NULL,NULL,FileSys,sizeof(FileSys))) {
  388. *FileSys = '\0';
  389. } else if(!lstrcmpi(FileSys,"raw")) {
  390. *FileSys = '\0';
  391. }
  392. SizeSoFar += lstrlen(FileSys)+3; // 3 is for "",
  393. if(SizeSoFar > cbReturnBuffer) {
  394. SetErrorMode( ErrorMode );
  395. return(SizeSoFar);
  396. }
  397. *InsertPoint++ = '"';
  398. lstrcpy(InsertPoint,FileSys);
  399. InsertPoint = strchr(InsertPoint,0);
  400. *InsertPoint++ = '"';
  401. *InsertPoint++ = ',';
  402. }
  403. }
  404. if(*(InsertPoint-1) == ',') {
  405. *(InsertPoint-1) = '}'; // overwrite final comma
  406. } else {
  407. if(++SizeSoFar > cbReturnBuffer) {
  408. SetErrorMode( ErrorMode );
  409. return(SizeSoFar);
  410. }
  411. *InsertPoint++ = '}';
  412. }
  413. *InsertPoint = '\0';
  414. SetErrorMode( ErrorMode );
  415. return(lstrlen(ReturnBuffer)+1);
  416. }
  417. /*
  418. Return a list of ASCII representations of free space on all
  419. hard disk volumes
  420. */
  421. CB
  422. GetHardDriveFreeSpace(
  423. IN RGSZ Args,
  424. IN USHORT cArgs,
  425. OUT SZ ReturnBuffer,
  426. IN CB cbReturnBuffer
  427. )
  428. {
  429. CB Size;
  430. UINT ErrorMode;
  431. Unused(Args);
  432. Unused(cArgs);
  433. ErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX );
  434. Size = GetSpaceWorker(ReturnBuffer,cbReturnBuffer,SPACE_FREE);
  435. SetErrorMode( ErrorMode );
  436. return(Size);
  437. }
  438. /*
  439. Return a list of ASCII representations of total space on all
  440. hard disk volumes
  441. */
  442. CB
  443. GetHardDriveTotalSpace(
  444. IN RGSZ Args,
  445. IN USHORT cArgs,
  446. OUT SZ ReturnBuffer,
  447. IN CB cbReturnBuffer
  448. )
  449. {
  450. CB Size;
  451. UINT ErrorMode;
  452. Unused(Args);
  453. Unused(cArgs);
  454. ErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX );
  455. Size = GetSpaceWorker(ReturnBuffer,cbReturnBuffer,SPACE_TOTAL);
  456. SetErrorMode( ErrorMode );
  457. return(Size);
  458. }
  459. /******************************************************************
  460. Subroutines
  461. */
  462. CB
  463. GetDrivesWorker(
  464. IN RGSZ Args,
  465. IN USHORT cArgs,
  466. OUT SZ ReturnBuffer,
  467. IN CB cbReturnBuffer,
  468. IN DWORD TypeOfDrive
  469. )
  470. {
  471. char DriveName[4] = { 'x',':','\\','\0' };
  472. BOOL IsValid[26];
  473. DWORD NumMatches;
  474. DWORD SpaceRequired;
  475. Unused(Args);
  476. Unused(cArgs);
  477. NumMatches = AreDrivesACertainType(TypeOfDrive,IsValid);
  478. SpaceRequired = (NumMatches * 5) + 3 - 1;
  479. if(cbReturnBuffer < SpaceRequired) {
  480. return(SpaceRequired);
  481. } else {
  482. ConstructDiskList(IsValid,ReturnBuffer);
  483. return(lstrlen(ReturnBuffer)+1);
  484. }
  485. }
  486. DWORD
  487. AreDrivesACertainType(
  488. IN DWORD TypeWereLookingFor,
  489. IN BOOL *Results
  490. )
  491. {
  492. char DriveLetter;
  493. char DriveName[4] = { 'x',':','\\','\0' };
  494. DWORD NumMatches = 0;
  495. DWORD DriveNumber = 0;
  496. for(DriveLetter='A'; DriveLetter <= 'Z'; DriveLetter++)
  497. {
  498. DriveName[0] = DriveLetter;
  499. Results[DriveNumber] = (MyGetDriveType(DriveName) == TypeWereLookingFor);
  500. if(Results[DriveNumber]) {
  501. NumMatches++;
  502. }
  503. DriveNumber++;
  504. }
  505. return(NumMatches);
  506. }
  507. VOID
  508. ConstructDiskList(
  509. IN BOOL *ValidDisk,
  510. IN LPSTR TextOut
  511. )
  512. {
  513. DWORD DriveNumber;
  514. LPSTR InsertPoint = TextOut;
  515. *InsertPoint++ = '{';
  516. for(DriveNumber=0; DriveNumber<26; DriveNumber++) {
  517. if(ValidDisk[DriveNumber]) {
  518. *InsertPoint++ = '"';
  519. *InsertPoint++ = (char)DriveNumber + (char)'A';
  520. *InsertPoint++ = ':';
  521. *InsertPoint++ = '"';
  522. *InsertPoint++ = ',';
  523. }
  524. }
  525. if(*(InsertPoint-1) == ',') {
  526. *(InsertPoint-1) = '}'; // overwrite final comma
  527. } else {
  528. *InsertPoint++ = '}';
  529. }
  530. *InsertPoint = '\0';
  531. }
  532. CB
  533. GetSpaceWorker(
  534. OUT SZ ReturnBuffer,
  535. IN CB cbReturnBuffer,
  536. IN DWORD TypeOfSpace
  537. )
  538. {
  539. BOOL HardDisk[26];
  540. DWORD Disk;
  541. LPSTR InsertPoint = ReturnBuffer;
  542. char DiskName[4] = { 'x',':','\\','\0' };
  543. DWORD SizeSoFar;
  544. DWORD SectorsPerCluster,BytesPerSector,FreeClusters,TotalClusters;
  545. DWORD Space;
  546. char SpaceSTR[15];
  547. AreDrivesACertainType(DRIVE_FIXED,HardDisk);
  548. *InsertPoint++ = '{';
  549. SizeSoFar = 2;
  550. for(Disk=0; Disk<26; Disk++) {
  551. if(HardDisk[Disk]) {
  552. DiskName[0] = (char)Disk + (char)'A';
  553. if(GetDiskFreeSpace(DiskName,
  554. &SectorsPerCluster,
  555. &BytesPerSector,
  556. &FreeClusters,
  557. &TotalClusters))
  558. {
  559. Space = SectorsPerCluster * BytesPerSector
  560. * (TypeOfSpace == SPACE_FREE ? FreeClusters : TotalClusters)
  561. / (1024*1024); // converts # to megabytes
  562. } else {
  563. // assume unformatted
  564. Space = GetPartitionSize(DiskName);
  565. }
  566. wsprintf(SpaceSTR,"%lu",Space);
  567. SizeSoFar += lstrlen(SpaceSTR)+3; // 3 is for "",
  568. if(SizeSoFar > cbReturnBuffer) {
  569. return(SizeSoFar);
  570. }
  571. *InsertPoint++ = '"';
  572. lstrcpy(InsertPoint,SpaceSTR);
  573. InsertPoint = strchr(InsertPoint,0);
  574. *InsertPoint++ = '"';
  575. *InsertPoint++ = ',';
  576. }
  577. }
  578. if(*(InsertPoint-1) == ',') {
  579. *(InsertPoint-1) = '}'; // overwrite final comma
  580. } else {
  581. if(++SizeSoFar > cbReturnBuffer) {
  582. return(SizeSoFar);
  583. }
  584. *InsertPoint++ = '}';
  585. }
  586. *InsertPoint = '\0';
  587. return(lstrlen(ReturnBuffer)+1);
  588. }