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.

1008 lines
24 KiB

  1. /* demgset.c - Drive related SVC hanlers.
  2. *
  3. * demSetDefaultDrive
  4. * demGetBootDrive
  5. * demGetDriveFreeSpace
  6. * demGetDrives
  7. * demGSetMediaID
  8. * demQueryDate
  9. * demQueryTime
  10. * demSetDate
  11. * demSetTime
  12. * demSetDTALocation
  13. * demGSetMediaID
  14. * demGetDPB
  15. * Modification History:
  16. *
  17. * Sudeepb 02-Apr-1991 Created
  18. *
  19. */
  20. #include "dem.h"
  21. #include "demmsg.h"
  22. #include <softpc.h>
  23. #include <mvdm.h>
  24. #include <winbase.h>
  25. #include "demdasd.h"
  26. #define BOOTDRIVE_PATH "Software\\Microsoft\\Windows\\CurrentVersion\\Setup"
  27. #define BOOTDRIVE_VALUE "BootDir"
  28. #define SUCCESS 0
  29. #define NODISK 1
  30. #define FAILURE 2
  31. BYTE demGetDpbI(BYTE Drive, DPB UNALIGNED *pDpb);
  32. UCHAR PhysicalDriveTypes[26]={0};
  33. extern PDOSSF pSFTHead;
  34. USHORT nDrives = 0;
  35. CHAR IsAPresent = TRUE;
  36. CHAR IsBPresent = TRUE;
  37. /* demSetDefaultDrive - Set the default drive
  38. *
  39. *
  40. * Entry -
  41. * Client (DS:SI) Current Directory on that drive
  42. * Client (dl) Zero based DriveNum
  43. *
  44. * Exit - SUCCESS
  45. * Client (CY) = 0
  46. * Current Drive Set
  47. *
  48. * FAILURE
  49. * Client (CY) = 1
  50. * Current Drive Not Set
  51. *
  52. * Notes:
  53. * The DOS keeps a current directory for each of the drives,
  54. * However winnt keeps only one current Drive, Directory per
  55. * process, and it is cmd.exe which associates a current
  56. * directory for each of the drive.
  57. */
  58. VOID demSetDefaultDrive (VOID)
  59. {
  60. LPSTR lpPath;
  61. lpPath = (LPSTR)GetVDMAddr (getDS(),getSI());
  62. // only in sp4
  63. #ifdef NOVELL_NETWARE_SETERRORMODE
  64. //
  65. // For removable drives check for media\volume info to avoid triggering
  66. // hard errors when no media is present. There exists win32 code
  67. // (e.g novell netware redir vdd) which is known to clobber our error
  68. // mode setting.
  69. //
  70. // 16-Jul-1997 Jonle
  71. //
  72. {
  73. UCHAR DriveType;
  74. CHAR DriveNum;
  75. DriveNum = (CHAR)getDL();
  76. DriveType = demGetPhysicalDriveType(DriveNum);
  77. if (DriveType == DRIVE_REMOVABLE || DriveType == DRIVE_CDROM) {
  78. VOLINFO VolInfo;
  79. //
  80. // if No Media in drive, the drive is still valid,
  81. // but the win32 curdir is still the old one.
  82. //
  83. if (!GetMediaId(DriveNum, &VolInfo)) {
  84. if (GetLastError() == ERROR_INVALID_DRIVE) {
  85. setCF(1);
  86. }
  87. else {
  88. setCF(0);
  89. }
  90. return;
  91. }
  92. }
  93. }
  94. #endif
  95. if (!SetCurrentDirectoryOem(lpPath) && GetLastError() == ERROR_INVALID_DRIVE) {
  96. //
  97. // Only return error if drive was invalid, the DOS doesn't check
  98. // for curdir when changing drives. Note that a number of old dos
  99. // apps will walk all of the drives, and do setdefaultdrive,
  100. // to determine the valid drives letters. The SetCurrentDirectoryOem
  101. // causes ntio to touch the drive and verify that the dir exists.
  102. // This is a significant performance problem for removable media
  103. // and network drives, but we have no choice since locking the
  104. // current dir for this drive is mandatory for winnt.
  105. //
  106. setCF(1);
  107. }
  108. else {
  109. setCF(0);
  110. }
  111. return;
  112. }
  113. /* demGetBootDrive - Get the boot drive
  114. *
  115. *
  116. * Entry - None
  117. *
  118. * Exit - CLIENT (AL) has 1 base boot drive (i.e. C=3)
  119. *
  120. * We try to read the registry value that indicates the real boot drive. This
  121. * should be the location of autoexec.bat, etc. If we can't find the key,
  122. * or if the value indicates some drive letter that is not a fixed drive,
  123. * then we use a fallback plan of just saying drive C.
  124. *
  125. */
  126. VOID demGetBootDrive (VOID)
  127. {
  128. #if defined(NEC_98) // NTBUG #98466
  129. CHAR szBootDir[MAX_PATH];
  130. BYTE Drive = 1; // default it to 'A:'
  131. UINT retCode;
  132. retCode = GetSystemDirectory(szBootDir,MAX_PATH);
  133. if (retCode == 0 || retCode > MAX_PATH){
  134. // error: can't get path
  135. goto DefaultBootDrive;
  136. }
  137. szBootDir[2] = '\\';
  138. szBootDir[3] = '\0';
  139. #else // !NEC_98
  140. HKEY hKey;
  141. DWORD retCode;
  142. DWORD dwType, cbData = MAX_PATH;
  143. CHAR szBootDir[MAX_PATH];
  144. BYTE Drive = 3; // default it to 'C:'
  145. retCode = RegOpenKeyEx (HKEY_LOCAL_MACHINE,
  146. BOOTDRIVE_PATH,
  147. 0,
  148. KEY_EXECUTE, // Requesting read access.
  149. &hKey);
  150. if (retCode) {
  151. // error: can't find section
  152. goto DefaultBootDrive;
  153. }
  154. retCode = RegQueryValueEx(hKey,
  155. BOOTDRIVE_VALUE,
  156. NULL,
  157. &dwType,
  158. szBootDir,
  159. &cbData);
  160. RegCloseKey(hKey);
  161. if (retCode) {
  162. // error: can't find key
  163. goto DefaultBootDrive;
  164. }
  165. #endif // NEC_98
  166. if (GetDriveType(szBootDir) != DRIVE_FIXED) {
  167. // error: drive is not a valid boot drive
  168. goto DefaultBootDrive;
  169. }
  170. Drive = (BYTE)(tolower(szBootDir[0])-'a')+1;
  171. DefaultBootDrive:
  172. setAL(Drive);
  173. return;
  174. }
  175. /* demGetDriveFreeSpace - Get free Space on the drive
  176. *
  177. *
  178. * Entry - Client (AL) Drive in question
  179. * 0 - A: etc.
  180. *
  181. * Exit -
  182. * SUCCESS
  183. * Client (CY) = 0
  184. * Client (AL) = FAT ID byte
  185. * Client (BX) = Number of free allocation units
  186. * Client (CX) = Sector size
  187. * Client (DX) = Total Number of allocation units on disk
  188. * Client (SI) = Sectors per allocation unit
  189. *
  190. * FAILURE
  191. * Client (CY) = 1
  192. * Client (AX) = Error code
  193. */
  194. VOID demGetDriveFreeSpace (VOID)
  195. {
  196. WORD SectorsPerCluster;
  197. WORD BytesPerSector;
  198. WORD FreeClusters;
  199. WORD TotalClusters;
  200. BYTE Drive;
  201. PBDS pbds;
  202. Drive = getAL();
  203. if (demGetDiskFreeSpace(Drive,
  204. &BytesPerSector,
  205. &SectorsPerCluster,
  206. &TotalClusters,
  207. &FreeClusters) == FALSE)
  208. {
  209. demClientError(INVALID_HANDLE_VALUE, (CHAR)(getAL() + 'A'));
  210. return;
  211. }
  212. if (pbds = demGetBDS(Drive)) {
  213. // if the device is a floppy, reload its bpb
  214. if (!(pbds->Flags & NON_REMOVABLE) && !demGetBPB(pbds))
  215. pbds->bpb.MediaID = 0xF8;
  216. setAL(pbds->bpb.MediaID);
  217. }
  218. else
  219. setAL(0);
  220. setBX(FreeClusters);
  221. setCX(BytesPerSector);
  222. setDX(TotalClusters);
  223. setSI(SectorsPerCluster);
  224. setCF(0);
  225. return;
  226. }
  227. //
  228. // retrieves drive type for physical drives
  229. // substd, redir drives are returned as unknown
  230. // uses same DriveType definitions as win32 GetDriveTypeW
  231. //
  232. UCHAR
  233. demGetPhysicalDriveType(
  234. UCHAR DriveNum)
  235. {
  236. return DriveNum < 26 ? PhysicalDriveTypes[DriveNum] : DRIVE_UNKNOWN;
  237. }
  238. //
  239. // worker function for DemGetDrives
  240. //
  241. UCHAR
  242. DosDeviceDriveTypeToPhysicalDriveType(
  243. UCHAR DeviceDriveType
  244. )
  245. {
  246. switch (DeviceDriveType) {
  247. case DOSDEVICE_DRIVE_REMOVABLE:
  248. return DRIVE_REMOVABLE;
  249. case DOSDEVICE_DRIVE_FIXED:
  250. return DRIVE_FIXED;
  251. case DOSDEVICE_DRIVE_CDROM:
  252. return DRIVE_CDROM;
  253. case DOSDEVICE_DRIVE_RAMDISK:
  254. return DRIVE_RAMDISK;
  255. }
  256. //case DOSDEVICE_DRIVE_REMOTE:
  257. //case DOSDEVICE_DRIVE_UNKNOWN:
  258. //default:
  259. return DRIVE_UNKNOWN;
  260. }
  261. /* demGetDrives - Get number of logical drives in the system
  262. * called by ntdos from msinit to get numio
  263. * initializes the physical drive list, which consists
  264. * of drive types for true physical drives. subst
  265. * and redir drives are classed as DRIVE_UNKNOWN.
  266. *
  267. * Entry - None
  268. *
  269. * Exit -
  270. * SUCCESS
  271. * Client (CY) = 0
  272. * Client (AL) = number of drives
  273. *
  274. * FAILURE
  275. * None
  276. */
  277. VOID demGetDrives (VOID)
  278. {
  279. NTSTATUS Status;
  280. UCHAR DriveNum;
  281. UCHAR DriveType;
  282. BOOL bCounting;
  283. PROCESS_DEVICEMAP_INFORMATION ProcessDeviceMapInfo;
  284. Status = NtQueryInformationProcess( NtCurrentProcess(),
  285. ProcessDeviceMap,
  286. &ProcessDeviceMapInfo.Query,
  287. sizeof(ProcessDeviceMapInfo.Query),
  288. NULL
  289. );
  290. if (!NT_SUCCESS(Status)) {
  291. RtlZeroMemory( &ProcessDeviceMapInfo, sizeof(ProcessDeviceMapInfo));
  292. }
  293. //
  294. // A and B are special cases.
  295. // if A doesn't exist means b also doesn't exist
  296. //
  297. PhysicalDriveTypes[0] = DosDeviceDriveTypeToPhysicalDriveType(
  298. ProcessDeviceMapInfo.Query.DriveType[0]
  299. );
  300. if (PhysicalDriveTypes[0] == DRIVE_UNKNOWN) {
  301. IsAPresent = FALSE;
  302. IsBPresent = FALSE;
  303. }
  304. PhysicalDriveTypes[1] = DosDeviceDriveTypeToPhysicalDriveType(
  305. ProcessDeviceMapInfo.Query.DriveType[1]
  306. );
  307. if (PhysicalDriveTypes[1] == DRIVE_UNKNOWN) {
  308. IsBPresent = FALSE;
  309. }
  310. DriveNum = 2;
  311. nDrives = 2;
  312. bCounting = TRUE;
  313. do {
  314. PhysicalDriveTypes[DriveNum] = DosDeviceDriveTypeToPhysicalDriveType(
  315. ProcessDeviceMapInfo.Query.DriveType[DriveNum]
  316. );
  317. if (bCounting) {
  318. if (PhysicalDriveTypes[DriveNum] == DRIVE_REMOVABLE ||
  319. PhysicalDriveTypes[DriveNum] == DRIVE_FIXED ||
  320. PhysicalDriveTypes[DriveNum] == DRIVE_CDROM ||
  321. PhysicalDriveTypes[DriveNum] == DRIVE_RAMDISK )
  322. {
  323. nDrives++;
  324. }
  325. else {
  326. bCounting = FALSE;
  327. }
  328. }
  329. } while (++DriveNum < 26);
  330. setAX(nDrives);
  331. setCF(0);
  332. return;
  333. }
  334. /* demQueryDate - Get The Date
  335. *
  336. *
  337. * Entry - None
  338. *
  339. * Exit -
  340. * SUCCESS
  341. * Client (DH) - month
  342. * Client (DL) - Day
  343. * Client (CX) - Year
  344. * Client (AL) - WeekDay
  345. *
  346. * FAILURE
  347. * Never
  348. */
  349. VOID demQueryDate (VOID)
  350. {
  351. SYSTEMTIME TimeDate;
  352. GetLocalTime(&TimeDate);
  353. setDH((UCHAR)TimeDate.wMonth);
  354. setDL((UCHAR)TimeDate.wDay);
  355. setCX(TimeDate.wYear);
  356. setAL((UCHAR)TimeDate.wDayOfWeek);
  357. return;
  358. }
  359. /* demQueryTime - Get The Time
  360. *
  361. *
  362. * Entry - None
  363. *
  364. * Exit -
  365. * SUCCESS
  366. * Client (CH) - hour
  367. * Client (CL) - minutes
  368. * Client (DH) - seconds
  369. * Client (DL) - hundredth of seconds
  370. *
  371. * FAILURE
  372. * Never
  373. */
  374. VOID demQueryTime (VOID)
  375. {
  376. SYSTEMTIME TimeDate;
  377. GetLocalTime(&TimeDate);
  378. setCH((UCHAR)TimeDate.wHour);
  379. setCL((UCHAR)TimeDate.wMinute);
  380. setDH((UCHAR)TimeDate.wSecond);
  381. setDL((UCHAR)(TimeDate.wMilliseconds/10));
  382. return;
  383. }
  384. /* demSetDate - Set The Date
  385. *
  386. *
  387. * Entry - Client (CX) - Year
  388. * Client (DH) - month
  389. * Client (DL) - Day
  390. *
  391. * Exit - SUCCESS
  392. * Client (AL) - 00
  393. *
  394. *
  395. * FAILURE
  396. * Client (AL) - ff
  397. */
  398. VOID demSetDate (VOID)
  399. {
  400. SYSTEMTIME TimeDate;
  401. GetLocalTime(&TimeDate);
  402. TimeDate.wYear = (WORD)getCX();
  403. TimeDate.wMonth = (WORD)getDH();
  404. TimeDate.wDay = (WORD)getDL();
  405. if(SetLocalTime(&TimeDate) || GetLastError() == ERROR_PRIVILEGE_NOT_HELD)
  406. setAL(0);
  407. else
  408. setAL(0xff);
  409. }
  410. /* demSetTime - Set The Time
  411. *
  412. *
  413. * Entry - Client (CH) - hour
  414. * Client (CL) - minutes
  415. * Client (DH) - seconds
  416. * Client (DL) - hundredth of seconds
  417. *
  418. * Exit - None
  419. *
  420. */
  421. VOID demSetTime (VOID)
  422. {
  423. SYSTEMTIME TimeDate;
  424. GetLocalTime(&TimeDate);
  425. TimeDate.wHour = (WORD)getCH();
  426. TimeDate.wMinute = (WORD)getCL();
  427. TimeDate.wSecond = (WORD)getDH();
  428. TimeDate.wMilliseconds = (WORD)getDL()*10;
  429. if (SetLocalTime(&TimeDate) || GetLastError() == ERROR_PRIVILEGE_NOT_HELD)
  430. setAL(0);
  431. else
  432. setAL(0xff);
  433. }
  434. /* demSetDTALocation - Set The address of variable where Disk Transfer Address
  435. * is stored in NTDOS.
  436. *
  437. *
  438. * Entry - Client (DS:AX) - DTA variable Address
  439. * Client (DS:DX) - CurrentPDB address
  440. *
  441. * Exit - None
  442. *
  443. */
  444. VOID demSetDTALocation (VOID)
  445. {
  446. PDOSWOWDATA pDosWowData;
  447. pulDTALocation = (PULONG) GetVDMAddr(getDS(),getAX());
  448. pusCurrentPDB = (PUSHORT) GetVDMAddr(getDS(),getDX());
  449. pExtendedError = (PDEMEXTERR) GetVDMAddr(getDS(),getCX());
  450. pDosWowData = (PDOSWOWDATA) GetVDMAddr(getDS(),getSI());
  451. pSFTHead = (PDOSSF) GetVDMAddr(getDS(),(WORD)pDosWowData->lpSftAddr);
  452. return;
  453. }
  454. /* demGSetMediaID - Get or set volume serial and volume label
  455. *
  456. * Entry - Client (BL) - Drive Number (0=A;1=B..etc)
  457. * Client (AL) - Get or Set (0=Get;1=Set)
  458. * Client (DS:DX) - Buffer to return information
  459. * (see VOLINFO in dosdef.h)
  460. *
  461. * Exit - SUCCESS
  462. * Client (CF) - 0
  463. *
  464. * FAILURE
  465. * Client (CF) - 1
  466. * Client (AX) - Error code
  467. *
  468. * NOTES:
  469. * Currently There is no way for us to set Volume info.
  470. */
  471. VOID demGSetMediaID (VOID)
  472. {
  473. CHAR Drive;
  474. PVOLINFO pVolInfo;
  475. // Set Volume info is not currently supported
  476. if(getAL() != 0){
  477. setCF(1);
  478. return;
  479. }
  480. pVolInfo = (PVOLINFO) GetVDMAddr (getDS(),getDX());
  481. Drive = (CHAR)getBL();
  482. if (!GetMediaId(Drive, pVolInfo)) {
  483. demClientError(INVALID_HANDLE_VALUE, (CHAR)(Drive + 'A'));
  484. return;
  485. }
  486. setCF(0);
  487. return;
  488. }
  489. //
  490. // GetMediaId
  491. //
  492. //
  493. BOOL
  494. GetMediaId(
  495. CHAR DriveNum,
  496. PVOLINFO pVolInfo
  497. )
  498. {
  499. CHAR RootPathName[] = "?:\\";
  500. CHAR achVolumeName[NT_VOLUME_NAME_SIZE];
  501. CHAR achFileSystemType[MAX_PATH];
  502. DWORD adwVolumeSerial[2],i;
  503. // Form Root path
  504. RootPathName[0] = DriveNum + 'A';
  505. // Call the supreme source of information
  506. if(!GetVolumeInformationOem( RootPathName,
  507. achVolumeName,
  508. NT_VOLUME_NAME_SIZE,
  509. adwVolumeSerial,
  510. NULL,
  511. NULL,
  512. achFileSystemType,
  513. MAX_PATH) )
  514. {
  515. return FALSE;
  516. }
  517. // Fill in user buffer. Remember to convert the null characters
  518. // to spaces in different strings.
  519. STOREDWORD(pVolInfo->ulSerialNumber,adwVolumeSerial[0]);
  520. strncpy(pVolInfo->VolumeID,achVolumeName,DOS_VOLUME_NAME_SIZE);
  521. for(i=0;i<DOS_VOLUME_NAME_SIZE;i++) {
  522. if (pVolInfo->VolumeID[i] == '\0')
  523. pVolInfo->VolumeID[i] = '\x020';
  524. }
  525. strncpy(pVolInfo->FileSystemType,achFileSystemType,FILESYS_NAME_SIZE);
  526. for(i=0;i<FILESYS_NAME_SIZE;i++) {
  527. if (pVolInfo->FileSystemType[i] == '\0')
  528. pVolInfo->VolumeID[i] = '\x020';
  529. }
  530. return TRUE;
  531. }
  532. /* demGetDPB - Get Devicr Parameter Block
  533. *
  534. * Entry - Client (AL) - Drive Number (0=A;1=B..etc)
  535. * Client (DS:DI) - Buffer to return information
  536. *
  537. * Exit - SUCCESS
  538. * Client (CF) - 0
  539. *
  540. * FAILURE
  541. * Client (CF) - 1
  542. * Client (AX) - Error code
  543. *
  544. */
  545. VOID demGetDPB(VOID)
  546. {
  547. BYTE Drive;
  548. DPB UNALIGNED *pDPB;
  549. BYTE Result;
  550. Drive = getAL();
  551. pDPB = (PDPB) GetVDMAddr(getDS(), getDI());
  552. Result = demGetDpbI(Drive, pDPB);
  553. if (Result == FAILURE) {
  554. demClientError(INVALID_HANDLE_VALUE,(CHAR)(Drive + 'A'));
  555. return;
  556. }
  557. else if (Result == NODISK){
  558. setCF(1);
  559. return;
  560. }
  561. setAX(0);
  562. setCF(0);
  563. }
  564. /* demGetDPBI - Worker for GetDPB and GetDPBList
  565. *
  566. * Entry -
  567. * Drive -- Drive Number (0=A;1=B..etc)
  568. * pDPB -- pointer to the location to store the dpb
  569. *
  570. * Exit - SUCCESS
  571. * returns success, fills in DPB
  572. * FAILURE
  573. * returns FAILURE or NODISK
  574. */
  575. BYTE demGetDpbI(BYTE Drive, DPB UNALIGNED *pDPB)
  576. {
  577. WORD SectorSize, ClusterSize, FreeClusters, TotalClusters;
  578. PBDS pbds;
  579. WORD DirsPerSector;
  580. if (demGetDiskFreeSpace(Drive,
  581. &SectorSize,
  582. &ClusterSize,
  583. &TotalClusters,
  584. &FreeClusters
  585. ))
  586. {
  587. pDPB->Next = (PDPB) 0xFFFFFFFF;
  588. pDPB->SectorSize = SectorSize;
  589. pDPB->FreeClusters = FreeClusters;
  590. pDPB->MaxCluster = TotalClusters + 1;
  591. pDPB->ClusterMask = ClusterSize - 1;
  592. pDPB->ClusterShift = 0;
  593. pDPB->DriveNum = pDPB->Unit = Drive;
  594. while ((ClusterSize & 1) == 0) {
  595. ClusterSize >>= 1;
  596. pDPB->ClusterShift++;
  597. }
  598. if (pbds = demGetBDS(Drive)) {
  599. // if the device is a floppy, reload its bpb
  600. if (!(pbds->Flags & NON_REMOVABLE) && !demGetBPB(pbds)) {
  601. return NODISK;
  602. }
  603. pDPB->MediaID = pbds->bpb.MediaID;
  604. pDPB->FATSector = pbds->bpb.ReservedSectors;
  605. pDPB->FATs = pbds->bpb.FATs;
  606. pDPB->RootDirs = pbds->bpb.RootDirs;
  607. pDPB->FATSize = pbds->bpb.FATSize;
  608. pDPB->DirSector = pbds->bpb.FATs * pbds->bpb.FATSize +
  609. pDPB->FATSector;
  610. DirsPerSector = pDPB->SectorSize >> DOS_DIR_ENTRY_LENGTH_SHIFT_COUNT;
  611. pDPB->FirstDataSector = pDPB->DirSector +
  612. ((pDPB->RootDirs + DirsPerSector - 1) /
  613. DirsPerSector);
  614. pDPB->DriveAddr = 0x123456;
  615. pDPB->FirstAccess = 10;
  616. }
  617. // if we don't know the drive, fake a DPB for it
  618. else {
  619. pDPB->MediaID = 0xF8;
  620. pDPB->FATSector = 1;
  621. pDPB->FATs = 2;
  622. pDPB->RootDirs = 63;
  623. pDPB->FATSize = 512;
  624. pDPB->DirSector = 1;
  625. pDPB->DriveAddr = 1212L * 64L * 1024L + 1212L;
  626. pDPB->FirstAccess = 10;
  627. }
  628. return SUCCESS;
  629. }
  630. else {
  631. return FAILURE;
  632. }
  633. }
  634. /* demGetComputerName - Get computer name
  635. *
  636. * Entry -
  637. * Client (DS:DX) - 16 byte buffer
  638. *
  639. * Exit - Always Succeeds
  640. * DS:DX is filled with the computer name (NULL terminated).
  641. */
  642. VOID demGetComputerName (VOID)
  643. {
  644. PCHAR pDOSBuffer;
  645. CHAR ComputerName[MAX_COMPUTERNAME_LENGTH+1];
  646. DWORD BufferSize = MAX_COMPUTERNAME_LENGTH+1;
  647. ULONG i;
  648. pDOSBuffer = (PCHAR) GetVDMAddr(getDS(), getDX());
  649. if (GetComputerNameOem(ComputerName, &BufferSize)){
  650. if (BufferSize <= 15){
  651. for (i = BufferSize ; i < 15 ; i++)
  652. ComputerName [i] = ' ';
  653. ComputerName[15] = '\0';
  654. strcpy (pDOSBuffer, ComputerName);
  655. }
  656. else{
  657. strncpy (pDOSBuffer, ComputerName, 15);
  658. pDOSBuffer [15] = '\0';
  659. }
  660. setCX(0x1ff);
  661. }
  662. else {
  663. *pDOSBuffer = '\0';
  664. setCH(0);
  665. }
  666. }
  667. #define APPS_SPACE_LIMIT 999990*1024 //999990kb to be on the safe side
  668. BOOL demGetDiskFreeSpace(
  669. BYTE Drive,
  670. WORD * BytesPerSector,
  671. WORD * SectorsPerCluster,
  672. WORD * TotalClusters,
  673. WORD * FreeClusters
  674. )
  675. {
  676. CHAR chRoot[]="?:\\";
  677. DWORD dwBytesPerSector;
  678. DWORD dwSectorsPerCluster;
  679. DWORD dwTotalClusters;
  680. DWORD dwFreeClusters;
  681. DWORD dwLostFreeSectors;
  682. DWORD dwLostTotalSectors;
  683. DWORD dwNewSectorPerCluster;
  684. ULONG ulTotal,ulTemp;
  685. // sudeepb 22-Jun-1993;
  686. // Please read this routine with an empty stomach.
  687. // The most common mistake all the apps do when calculating total
  688. // disk space or free space is to neglect overflow. Excel/Winword/Ppnt
  689. // and lots of other apps use "mul cx mul bx" never taking care
  690. // of first multiplication which can overflow. Hence this routine makes
  691. // sure that first multiplication will never overflow by fixing
  692. // appropriate values. Secondly, all these above apps use signed long
  693. // to deal with these free spaces. This puts a limit of 2Gb-1 on
  694. // the final outcome of the multiplication. If its above this the setup
  695. // fails. So here we have to make sure that total should never exceed
  696. // 0x7fffffff. Another bug in above setup program's that if you return
  697. // anything more than 999,999KB then they try to put "999,999KB+\0", but
  698. // unfortunately the buffer is only 10 bytes. Hence it corrupts something
  699. // with the last byte. In our case that is low byte of a segment which
  700. // it later tries to pop and GPF. This shrinks the maximum size that
  701. // we can return is 999,999KB.
  702. chRoot[0]=(CHAR)('A'+ Drive);
  703. if (GetDiskFreeSpaceOem(chRoot,
  704. &dwSectorsPerCluster,
  705. &dwBytesPerSector,
  706. &dwFreeClusters,
  707. &dwTotalClusters) == FALSE)
  708. return FALSE;
  709. /*
  710. * HPFS and NTFS can give num clusters over dos limit
  711. * For these cases increase SectorPerCluster and lower
  712. * cluster number accordingly. If the disk is very large
  713. * even this isn't enuf, so pass max sizes that dos can
  714. * handle.
  715. *
  716. * The following algorithm is accurate within 1 cluster
  717. * (final figure)
  718. *
  719. */
  720. dwLostFreeSectors = dwLostTotalSectors = 0;
  721. while (dwTotalClusters + dwLostTotalSectors/dwSectorsPerCluster > 0xFFFF)
  722. {
  723. if (dwSectorsPerCluster > 0x7FFF)
  724. {
  725. dwTotalClusters = 0xFFFF;
  726. if (dwFreeClusters > 0xFFFF)
  727. dwFreeClusters = 0xFFFF;
  728. break;
  729. }
  730. if (dwFreeClusters & 1) {
  731. dwLostFreeSectors += dwSectorsPerCluster;
  732. }
  733. if (dwTotalClusters & 1) {
  734. dwLostTotalSectors += dwSectorsPerCluster;
  735. }
  736. dwSectorsPerCluster <<= 1;
  737. dwFreeClusters >>= 1;
  738. dwTotalClusters >>= 1;
  739. }
  740. if (dwTotalClusters < 0xFFFF) {
  741. dwFreeClusters += dwLostFreeSectors/dwSectorsPerCluster;
  742. dwTotalClusters += dwLostTotalSectors/dwSectorsPerCluster;
  743. }
  744. if ((dwNewSectorPerCluster = (0xffff / dwBytesPerSector)) < dwSectorsPerCluster)
  745. dwSectorsPerCluster = dwNewSectorPerCluster;
  746. // finally check for 999,999kb
  747. ulTemp = (ULONG)((USHORT)dwSectorsPerCluster * (USHORT)dwBytesPerSector);
  748. // check that total space does'nt exceed 999,999kb
  749. ulTotal = ulTemp * (USHORT)dwTotalClusters;
  750. if (ulTotal > APPS_SPACE_LIMIT){
  751. if (ulTemp <= APPS_SPACE_LIMIT)
  752. dwTotalClusters = APPS_SPACE_LIMIT / ulTemp;
  753. else
  754. dwTotalClusters = 1;
  755. }
  756. ulTotal = ulTemp * (USHORT)dwFreeClusters;
  757. if (ulTotal > APPS_SPACE_LIMIT) {
  758. if (ulTemp <= APPS_SPACE_LIMIT)
  759. dwFreeClusters = APPS_SPACE_LIMIT / ulTemp;
  760. else
  761. dwFreeClusters = 1;
  762. }
  763. *BytesPerSector = (WORD) dwBytesPerSector;
  764. *SectorsPerCluster = (WORD) dwSectorsPerCluster;
  765. *TotalClusters = (WORD) dwTotalClusters;
  766. *FreeClusters = (WORD) dwFreeClusters;
  767. return TRUE;
  768. }
  769. /* demGetDPBList - Create the list of dpbs
  770. *
  771. * Entry -
  772. * Client(ES:BP) - points to destination for the dpb list
  773. * Exit - SUCCESS
  774. * Client (BP) - points to first byte past dpb list
  775. * FAILURE
  776. * Client (BP) unchanged
  777. *
  778. * Notes:
  779. * For performance reasons, only the drive and unit fields are
  780. * filled in. The only application I know of that depends on the
  781. * dpb list is go.exe (a shareware app installer). Even if we filled
  782. * in the other fields they would likely be incorrect when the app
  783. * looked at them, since ntdos.sys never updates the pdbs in the pdb
  784. * list
  785. */
  786. VOID demGetDPBList (VOID)
  787. {
  788. UCHAR DriveType;
  789. UCHAR DriveNum;
  790. DPB UNALIGNED *pDpb;
  791. USHORT usDpbOffset, usDpbSeg;
  792. usDpbOffset = getBP();
  793. usDpbSeg = getES();
  794. pDpb = (PDPB)GetVDMAddr(usDpbSeg, usDpbOffset);
  795. //
  796. // Iterate over all of the drive letters.
  797. //
  798. DriveNum = 0;
  799. do {
  800. DriveType = demGetPhysicalDriveType(DriveNum);
  801. //
  802. // Only include the local non cd rom drives ?? ramdisk ???
  803. //
  804. if ((DriveType == DRIVE_REMOVABLE) || (DriveType == DRIVE_FIXED)) {
  805. //
  806. // Fake the Dpb for the drive
  807. //
  808. pDpb->DriveNum = pDpb->Unit = DriveNum;
  809. //
  810. // Link it to the next dpb
  811. //
  812. usDpbOffset += sizeof(DPB);
  813. pDpb->Next = (PDPB)(((ULONG)usDpbSeg) << 16 | usDpbOffset);
  814. //
  815. // Advance to the next dpb
  816. //
  817. pDpb += 1;
  818. ASSERT(usDpbOffset < 0xFFFF);
  819. }
  820. } while (++DriveNum < 26);
  821. //
  822. // Terminate the list if necessary
  823. //
  824. if (usDpbOffset != getBP()) {
  825. pDpb -= 1;
  826. pDpb->Next = (PDPB)-1;
  827. }
  828. //
  829. // Return the new free space pointer
  830. //
  831. setBP(usDpbOffset);
  832. }