home *** CD-ROM | disk | FTP | other *** search
/ Windows NT Super Tune-Up Kit / PIE-WindowsNTSuperTuneUpKit-1997.iso / DISK_UTL / MOUNT / UNMOUNT.C < prev    next >
C/C++ Source or Header  |  1995-02-25  |  8KB  |  270 lines

  1. // UNMOUNT - Unmounts a drive, so that it can be removed
  2. // Version 1.00
  3. // Copyright (c) 1995, Christoph H. HochstΣtter
  4.  
  5. #include <windows.h>
  6. #include <string.h>
  7. #include <stdio.h>
  8. #include <winioctl.h>
  9. #include <stdarg.h>
  10. #include <io.h>
  11. #include <conio.h>
  12. #include "mnt.h"
  13.  
  14. HANDLE filenum;
  15. UINT DriveType;
  16. char quiet = FALSE;
  17. char rootname[MaxRootName];
  18. char keyin[MaxKeyIn];
  19. char filename[MaxDeviceName];
  20. char RealDeviceName[MaxDeviceItem];
  21. char ValidDevice = FALSE;
  22.  
  23.  
  24. import char __fastcall ValidDrive(char *);
  25. import void __fastcall index(char *, char *[], register unsigned short *);
  26. import int __fastcall sort(char *[],const unsigned short);
  27.  
  28. __inline void __fastcall chmalloc(void **chpointer, int bytes)
  29. {
  30.     if (!(*chpointer=malloc(bytes))) {
  31.         fputs("Not enough memory.\n",stderr);
  32.         ExitProcess(94);
  33.     }
  34. }
  35.  
  36. void __fastcall MyQueryDosDevice(const LPCTSTR s1,const LPTSTR s2,const DWORD i)
  37. {
  38.     if (!QueryDosDevice(s1,s2,i)) {
  39.         fputs("QueryDosDevice failed.\n",stderr);
  40.         ExitProcess(95);
  41.     }
  42. }
  43.  
  44. void __fastcall qputs(const char *string)
  45. {
  46.     if (!quiet) puts(string);
  47. }
  48.  
  49. __inline void __fastcall qfputs(const char *string, FILE *file)
  50. {
  51.     if (!quiet) fputs(string,file);
  52. }
  53.  
  54. void __fastcall qprintf(const char *string, ...)
  55. {
  56. va_list marker;
  57.     va_start(marker,string);
  58.     if (!quiet) vprintf(string,marker);
  59. }
  60.  
  61. void __fastcall Exception(void)
  62. {
  63. unsigned int rc;
  64.  
  65.         rc=GetLastError();
  66.         if (!rc) return;
  67.         fprintf(stderr,"\n\n");
  68.         switch (rc) {
  69.                 case 2:
  70.                         fprintf(stderr,"The device %s does not exist.\n",keyin);
  71.                         break;
  72.                 case 5:
  73.                         fprintf(stderr,"Another process has opened %s exclusively or %s is no root.\n",keyin,keyin);
  74.                         break;
  75.                 default:
  76.                         fprintf(stderr,"An error has occured. Errornumber %d\n",rc);
  77.         }
  78.         ExitProcess(rc);
  79. }
  80.  
  81.  
  82. void __fastcall Usage(void)
  83. {
  84.         fputs("Usage: unmount [-abdelq] <drive:> to unmount a volume.\n\n",stderr);
  85.         fputs("-a: Always delete drive letter. (Default: For non-removable disks only)\n",stderr);
  86.         fputs("-b: Delete drive letter before locking.\n",stderr);
  87.         fputs("-d: Never delete drive letter.\n",stderr);
  88.         fputs("-e: Don't eject media after unmounting.\n",stderr);
  89.         fputs("-l: Try locking the disk continously.\n",stderr);
  90.         fputs("-q: Quiet operation.\n",stderr);
  91.         ExitProcess(87);
  92. }
  93.  
  94. void __fastcall DeleteDefinition(void)
  95. {
  96.     qprintf("Deleting \\DosDevices\\%s (Ensures no new files can be opened)\n",keyin);
  97.     if (!DefineDosDevice(DDD_REMOVE_DEFINITION,keyin,NULL))
  98.         Exception();
  99. }
  100.  
  101. __inline void __fastcall PhysicalCheck(const char drive[])
  102. {
  103. char *DeviceBuffer;
  104. unsigned short MaxDevicelist;
  105. char *Devicelist[MaxDosDevices];
  106. char CurrentDevice[MaxDeviceItem];
  107. char *part1;
  108. char *part2;
  109. unsigned short i;
  110.  
  111.     if (QueryDosDevice(drive,RealDeviceName,MaxDeviceItem)) {
  112.         if ((part1=strrchr(RealDeviceName,'\\')) == NULL) return;
  113.         ValidDevice=TRUE;
  114.         chmalloc(&DeviceBuffer,MaxDeviceBuffer);
  115.         MyQueryDosDevice(NULL,DeviceBuffer,MaxDeviceBuffer);
  116.         index(DeviceBuffer,Devicelist,&MaxDevicelist);
  117.         MaxDevicelist=sort(Devicelist,MaxDevicelist);
  118.         for (i=0;i<=MaxDevicelist;i++) {
  119.             MyQueryDosDevice(Devicelist[i],CurrentDevice,MaxDeviceItem);
  120.             part2=strrchr(CurrentDevice,'\\');
  121.             if (stricmp(Devicelist[i],drive)\
  122.             &&(!stricmp(CurrentDevice,RealDeviceName)\
  123.             ||((part2 != NULL )\
  124.             &&!memicmp("\\partition",part2,10)\
  125.             &&!memicmp(CurrentDevice,RealDeviceName,max(part2-CurrentDevice,part1-RealDeviceName))))) {
  126.                 printf("%s same physical disk as %s.\n",Devicelist[i],drive);
  127.             }
  128.         }
  129.         free(DeviceBuffer);
  130.     }
  131. }
  132.  
  133. int main(int argc, char *argv[], char *envp[])
  134. {
  135. DWORD dummy = 0;
  136. DISK_GEOMETRY Info;
  137. BOOL DontRetryLock = TRUE;
  138. BOOL DontEject = FALSE;
  139. BOOL DontDeleteDefinition = FALSE;
  140. BOOL DeleteAlways = FALSE;
  141. BOOL DeleteBeforeLock = FALSE;
  142. int i,j;
  143.  
  144.         if ((argc < 2) || (!ValidDrive(argv[--argc]))) Usage();
  145.  
  146.         for (i=1;i<argc;i++) {
  147.             for (j=0;argv[i][j]!=0;j++) {
  148.             switch (argv[i][j] | 0x20) {
  149.                 case '-':
  150.                 case '/':
  151.                     break;
  152.                 case 'l':
  153.                     DontRetryLock = FALSE;
  154.                     break;
  155.                 case 'e':
  156.                     DontEject = TRUE;
  157.                     break;
  158.                 case 'b':
  159.                     DeleteBeforeLock = TRUE;
  160.                     break;
  161.                 case 'd':
  162.                     DontDeleteDefinition = TRUE;
  163.                     break;
  164.                 case 'q':
  165.                     quiet = TRUE;
  166.                     break;
  167.                 case 'a':
  168.                     DeleteAlways = TRUE;
  169.                     break;
  170.                 default:
  171.                     Usage();
  172.                     break;
  173.                 }
  174.             }
  175.         }
  176.  
  177.         lstrcpy(filename,"\\\\.\\");
  178.         lstrcat(filename,argv[argc]);
  179.         lstrcpy(rootname,argv[argc]);
  180.         lstrcat(rootname,"\\");
  181.         lstrcpy(keyin,argv[argc]);
  182.  
  183.         PhysicalCheck(keyin);
  184.  
  185.         qprintf("Testing %s -- ",keyin);
  186.         DriveType=GetDriveType(rootname);
  187.         switch (DriveType) {
  188.                 case 0:
  189.                     fputs("This drive does not exist\n",stderr);
  190.                     ExitProcess(99);
  191.                 case 1:
  192.                     fputs("non-exisiting drive, empty drive or unformatted.\n",stderr);
  193.                     ExitProcess(98);
  194.                 case DRIVE_REMOVABLE:
  195.                     qputs("This is a removable drive.");
  196.                     break;
  197.                 case DRIVE_FIXED:
  198.                     qputs("This is a fixed disk drive.");
  199.                     break;
  200.                 case DRIVE_REMOTE:
  201.                     fprintf(stderr,"This is a network drive. Try NET USE %s /DEL\n",keyin);
  202.                     ExitProcess(97);
  203.                 case DRIVE_CDROM:
  204.                     qputs("This is a CDROM-Drive. (Actually unmounting not required)");
  205.                     break;
  206.                 case DRIVE_RAMDISK:
  207.                     fputs("This is a RAMDISK.\n",stderr);
  208.                     ExitProcess(96);
  209.                 default:
  210.                      qputs("Unknown Drive Type. Assuming removable.");
  211.         }
  212.  
  213.         if (!ValidDrive) {
  214.             qfputs("Unable to determine Windows NT Device.\n",stderr);
  215.             }
  216.         else {
  217.             qprintf("Windows NT Device Name is %s.\n",RealDeviceName);
  218.             }
  219.         qprintf("Opening %s\n",keyin);
  220.         filenum=CreateFile(filename,GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,0);
  221.         Exception();
  222.  
  223.         if (DeviceIoControl(filenum,IOCTL_DISK_GET_DRIVE_GEOMETRY,NULL,0,&Info,sizeof(Info),&dummy,NULL))
  224.             qprintf("Drive has %ld Cyls, %lu surfaces, %lu sectors/track and %lu bytes/sector\n",Info.Cylinders.LowPart,Info.TracksPerCylinder,Info.SectorsPerTrack,Info.BytesPerSector);
  225.  
  226.         if (DeleteBeforeLock && (DeleteAlways || ((DriveType == DRIVE_FIXED) && (!DontDeleteDefinition))))
  227.             DeleteDefinition();
  228.  
  229.         qprintf("Locking %s (Ensures that all files are closed)\n",keyin);
  230.         for (i=0;!DeviceIoControl(filenum,FSCTL_LOCK_VOLUME,NULL,0,NULL,0,&dummy,NULL);) {
  231.             if (DontRetryLock) {
  232.                 fputs("Locking failed. There still open files.\n",stderr);
  233.                 ExitProcess(95);
  234.             }
  235.             putchar('.');
  236.             i=1;
  237.             Sleep(500);
  238.         }
  239.         if (i==1) putchar(10);
  240.  
  241.         if (!DeleteBeforeLock && (DeleteAlways || ((DriveType == DRIVE_FIXED) && (!DontDeleteDefinition))))
  242.             DeleteDefinition();
  243.  
  244.         qprintf("Dismounting %s\n",keyin);
  245.         if    (!DeviceIoControl(filenum,FSCTL_DISMOUNT_VOLUME,NULL,0,NULL,0,&dummy,NULL))
  246.             Exception();
  247.  
  248.         if (!DontEject) {
  249.             qprintf("Ejecting %s -- ",keyin);
  250.             if (!DeviceIoControl(filenum,IOCTL_DISK_EJECT_MEDIA,NULL,0,NULL,0,&dummy,NULL)) {
  251.                    if (GetLastError() == 1) {
  252.                        printf("%s does not support ejecting\n",keyin) ;
  253.                     printf("Please remove the media manually. Then press any key\n");
  254.                     getch();
  255.                 }
  256.                    else
  257.                        Exception();
  258.             }
  259.             else
  260.                    qprintf("successful\n");
  261.         }
  262.  
  263.         qprintf("Unlocking %s\n",keyin);
  264.         if (!DeviceIoControl(filenum,FSCTL_UNLOCK_VOLUME,NULL,0,NULL,0,&dummy,NULL))
  265.             Exception();
  266.  
  267.         CloseHandle(filenum);
  268.         return 0;
  269. }
  270.