BOOL EjectVolume( TCHAR cDriveLetter, BOOL reload ) { HANDLE hVolume; BOOL fRemoveSafely = FALSE; BOOL fAutoEject = FALSE; // Open the volume. hVolume = OpenVolume(cDriveLetter); if (hVolume == INVALID_HANDLE_VALUE) return FALSE; // Lock and dismount the volume. if (LockVolume(hVolume) && DismountVolume(hVolume)) { fRemoveSafely = TRUE; // Set prevent removal to false and eject the volume. if (PreventRemovalOfVolume(hVolume, FALSE) && AutoEjectVolume(hVolume,reload)) fAutoEject = TRUE; } // Close the volume so other processes can use the drive. if (!CloseVolume(hVolume)) return FALSE; /* if (fAutoEject) printf("Media in Drive %c has been ejected safely.\n", cDriveLetter); else { if (fRemoveSafely) printf("Media in Drive %c can be safely removed.\n", cDriveLetter); } */ return TRUE; }
/* Функция by Vadim Yegorov <*****@*****.**> Доработанная! Умеет "вставлять" диск :-) */ BOOL EjectVolume(wchar_t Letter,DWORD Flags) { BOOL Retry=TRUE; BOOL fAutoEject=FALSE; DWORD temp; BOOL ReadOnly=FALSE; UINT uDriveType; DWORD dwAccessFlags; BOOL fRemoveSafely = FALSE; BOOL foundError=FALSE; wchar_t szRootName[8]=L"\\\\.\\ :\\"; szRootName[4]=Letter; // OpenVolume uDriveType = FAR_GetDriveType(szRootName+4); szRootName[6]=0; switch (uDriveType) { case DRIVE_REMOVABLE: dwAccessFlags = GENERIC_READ | GENERIC_WRITE; break; default: if (IsDriveTypeCDROM(uDriveType)) { dwAccessFlags = GENERIC_READ; break; } return FALSE; } File Disk; bool Opened = Disk.Open(szRootName, dwAccessFlags, FILE_SHARE_READ|FILE_SHARE_WRITE, nullptr, OPEN_EXISTING); if(!Opened && GetLastError()==ERROR_ACCESS_DENIED) { Opened = Disk.Open(szRootName,GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, nullptr, OPEN_EXISTING); ReadOnly=FALSE; } if (Opened) { while (Retry) { if (Disk.IoControl(FSCTL_LOCK_VOLUME, nullptr, 0, nullptr, 0, &temp)) { foundError=FALSE; if (!ReadOnly) { Disk.FlushBuffers(); } #if 0 // TODO: ЭТОТ КУСОК НУЖНО РАСКОММЕНТИТЬ ВМЕСТЕ С ПОДЪЕМОМ ПРОЕКТА ПО USB /* ЭТО чудо нужно для того, чтобы, скажем, имея картридер на 3 карточки, дисмоунтить только 1 карточку, а не отключать все устройство! */ if (!(Flags&EJECT_LOAD_MEDIA)) { if (DismountVolume(DiskHandle)) fRemoveSafely = TRUE; else foundError=TRUE; } #endif if (!foundError) { PREVENT_MEDIA_REMOVAL PreventMediaRemoval={FALSE}; if (Disk.IoControl(IOCTL_STORAGE_MEDIA_REMOVAL, &PreventMediaRemoval, sizeof(PreventMediaRemoval), nullptr, 0, &temp)) { #if 1 // чистой воды шаманство... if (Flags&EJECT_READY) { fAutoEject=Disk.IoControl(IOCTL_STORAGE_CHECK_VERIFY, nullptr, 0, 0, 0, &temp); // ...если ошибка = "нет доступа", то это похоже на то, // что диск вставлен // Способ экспериментальный, потому афишировать не имеет смысла. if (!fAutoEject && GetLastError() == ERROR_ACCESS_DENIED) fAutoEject=TRUE; Retry=FALSE; } else #endif fAutoEject=Disk.IoControl((Flags&EJECT_LOAD_MEDIA)?IOCTL_STORAGE_LOAD_MEDIA:IOCTL_STORAGE_EJECT_MEDIA, nullptr, 0, nullptr, 0, &temp); } Retry=FALSE; } } else foundError=TRUE; if (foundError) { if (!(Flags&EJECT_NO_MESSAGE)) { string strMsgText; strMsgText.Format(MSG(MChangeCouldNotEjectMedia),Letter); if (Message(MSG_WARNING|MSG_ERRORTYPE,2,MSG(MError),strMsgText,MSG(MRetry),MSG(MCancel))) Retry=FALSE; } else Retry=FALSE; } else if (!(Flags&EJECT_LOAD_MEDIA) && fRemoveSafely) { //printf("Media in Drive %c can be safely removed.\n",cDriveLetter); //if(Flags&EJECT_NOTIFY_AFTERREMOVE) ; } } // END: while(Retry) Disk.IoControl(FSCTL_UNLOCK_VOLUME, nullptr, 0, nullptr, 0, &temp); Disk.Close(); } return fAutoEject||fRemoveSafely; //??? }
shared_ptr <VolumeInfo> CoreUnix::MountVolume (MountOptions &options) { CoalesceSlotNumberAndMountPoint (options); if (IsVolumeMounted (*options.Path)) throw VolumeAlreadyMounted (SRC_POS); Cipher::EnableHwSupport (!options.NoHardwareCrypto); shared_ptr <Volume> volume; while (true) { try { volume = OpenVolume ( options.Path, options.PreserveTimestamps, options.Password, options.Keyfiles, options.Protection, options.ProtectionPassword, options.ProtectionKeyfiles, options.SharedAccessAllowed, VolumeType::Unknown, options.UseBackupHeaders, options.PartitionInSystemEncryptionScope ); options.Password.reset(); } catch (SystemException &e) { if (options.Protection != VolumeProtection::ReadOnly && (e.GetErrorCode() == EROFS || e.GetErrorCode() == EACCES || e.GetErrorCode() == EPERM)) { // Read-only filesystem options.Protection = VolumeProtection::ReadOnly; continue; } throw; } break; } if (options.Path->IsDevice()) { if (volume->GetFile()->GetDeviceSectorSize() != volume->GetSectorSize()) throw ParameterIncorrect (SRC_POS); #if defined (TC_LINUX) if (volume->GetSectorSize() != TC_SECTOR_SIZE_LEGACY) { if (options.Protection == VolumeProtection::HiddenVolumeReadOnly) throw UnsupportedSectorSizeHiddenVolumeProtection(); if (options.NoKernelCrypto) throw UnsupportedSectorSizeNoKernelCrypto(); } #endif } // Find a free mount point for FUSE service MountedFilesystemList mountedFilesystems = GetMountedFilesystems (); string fuseMountPoint; for (int i = 1; true; i++) { stringstream path; path << GetTempDirectory() << "/" << GetFuseMountDirPrefix() << i; FilesystemPath fsPath (path.str()); bool inUse = false; foreach_ref (const MountedFilesystem &mf, mountedFilesystems) { if (mf.MountPoint == path.str()) { inUse = true; break; } } if (!inUse) { try { if (fsPath.IsDirectory()) fsPath.Delete(); throw_sys_sub_if (mkdir (path.str().c_str(), S_IRUSR | S_IXUSR) == -1, path.str()); fuseMountPoint = fsPath; break; } catch (...) { if (i > 255) throw TemporaryDirectoryFailure (SRC_POS, StringConverter::ToWide (path.str())); } } } try { FuseService::Mount (volume, options.SlotNumber, fuseMountPoint); } catch (...) { try { DirectoryPath (fuseMountPoint).Delete(); } catch (...) { } throw; } try { // Create a mount directory if a default path has been specified bool mountDirCreated = false; string mountPoint; if (!options.NoFilesystem && options.MountPoint) { mountPoint = *options.MountPoint; #ifndef TC_MACOSX if (mountPoint.find (GetDefaultMountPointPrefix()) == 0 && !options.MountPoint->IsDirectory()) { Directory::Create (*options.MountPoint); try { throw_sys_sub_if (chown (mountPoint.c_str(), GetRealUserId(), GetRealGroupId()) == -1, mountPoint); } catch (ParameterIncorrect&) { } mountDirCreated = true; } #endif } try { try { MountVolumeNative (volume, options, fuseMountPoint); } catch (NotApplicable&) { MountAuxVolumeImage (fuseMountPoint, options); } } catch (...) { if (mountDirCreated) remove (mountPoint.c_str()); throw; } } catch (...) { try { VolumeInfoList mountedVolumes = GetMountedVolumes (*options.Path); if (mountedVolumes.size() > 0) { shared_ptr <VolumeInfo> mountedVolume (mountedVolumes.front()); DismountVolume (mountedVolume); } } catch (...) { } throw; } VolumeInfoList mountedVolumes = GetMountedVolumes (*options.Path); if (mountedVolumes.size() != 1) throw ParameterIncorrect (SRC_POS); VolumeEventArgs eventArgs (mountedVolumes.front()); VolumeMountedEvent.Raise (eventArgs); return mountedVolumes.front(); }
DWORD _cdecl main( int argc, char *argv[], char *envp[] ) { char Drive[MAX_PATH]; HANDLE hDrive, hDiskImage; DISK_GEOMETRY Geometry; UINT i; char c, *p; LPSTR DriveName; BOOL fUsage = TRUE; BOOL fShowGeometry = FALSE; BOOL fDiskImage = FALSE; BOOL SourceIsDrive; LPSTR Source, Destination, DiskImage; if ( argc > 1 ) { fUsage = FALSE; while (--argc) { p = *++argv; if (*p == '/' || *p == '-') { while (c = *++p) switch (toupper( c )) { case '?': fUsage = TRUE; break; case 'C': fDiskImage = TRUE; argc--, argv++; Source = *argv; argc--, argv++; Destination = *argv; break; case 'G': fShowGeometry = TRUE; argc--, argv++; DriveName = *argv; break; default: printf("MFMT: Invalid switch - /%c\n", c ); fUsage = TRUE; break; } } } } if ( fUsage ) { printf("usage: MFMT switches \n" ); printf(" [-?] display this message\n" ); printf(" [-g drive] shows disk geometry\n" ); printf(" [-c source destination] produce diskimage\n" ); ExitProcess(1); } if ( fShowGeometry ) { sprintf(Drive,"\\\\.\\%s",DriveName); hDrive = CreateFile( Drive, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL ); if ( hDrive == INVALID_HANDLE_VALUE ) { printf("MFMT: Open %s failed %d\n",DriveName,GetLastError()); ExitProcess(1); } LockVolume(hDrive); if ( !GetDiskGeometry(hDrive,&Geometry) ) { printf("MFMT: GetDiskGeometry %s failed %d\n",DriveName,GetLastError()); ExitProcess(1); } PrintGeometry(DriveName,&Geometry); if ( !GetSupportedGeometrys(hDrive) ) { printf("MFMT: GetSupportedGeometrys %s failed %d\n",DriveName,GetLastError()); ExitProcess(1); } printf("\nDrive %s supports the following disk geometries\n",DriveName); for(i=0;i<SupportedGeometryCount;i++) { printf("\n"); PrintGeometry(NULL,&SupportedGeometry[i]); } printf("\n"); ExitProcess(0); } if ( fDiskImage ) { SourceIsDrive = FALSE; if ( Source[strlen(Source)-1] == ':' ) { SourceIsDrive = TRUE; sprintf(Drive,"\\\\.\\%s",Source); DiskImage = Destination; } if ( Destination[strlen(Destination)-1] == ':' ) { if ( SourceIsDrive ) { printf("MFMT: Source and Destination cannot both be drives\n"); ExitProcess(1); } SourceIsDrive = FALSE; sprintf(Drive,"\\\\.\\%s",Destination); DiskImage = Source; } else { if ( !SourceIsDrive ) { printf("MFMT: Either Source or Destination must be a drive\n"); ExitProcess(1); } } // // Open and Lock the drive // hDrive = CreateFile( Drive, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL ); if ( hDrive == INVALID_HANDLE_VALUE ) { printf("MFMT: Open %s failed %d\n",DriveName,GetLastError()); ExitProcess(1); } LockVolume(hDrive); if ( !GetDiskGeometry(hDrive,&Geometry) ) { printf("MFMT: GetDiskGeometry %s failed %d\n",DriveName,GetLastError()); ExitProcess(1); } if ( !GetSupportedGeometrys(hDrive) ) { printf("MFMT: GetSupportedGeometrys %s failed %d\n",DriveName,GetLastError()); ExitProcess(1); } // // Open the disk image file // hDiskImage = CreateFile( DiskImage, GENERIC_READ | GENERIC_WRITE, 0, NULL, SourceIsDrive ? CREATE_ALWAYS : OPEN_EXISTING, 0, NULL ); if ( hDiskImage == INVALID_HANDLE_VALUE ) { printf("MFMT: Open %s failed %d\n",DiskImage,GetLastError()); ExitProcess(1); } // // Now do the copy // { LPVOID IoBuffer; BOOL b; DWORD BytesRead, BytesWritten; DWORD FileSize; DWORD GeometrySize; // // If we are copying from floppy to file, just do the copy // Otherwise, we might have to format the floppy first // if ( SourceIsDrive ) { // // Device reads must be sector aligned. VirtualAlloc will // garuntee alignment // GeometrySize = Geometry.Cylinders.LowPart * Geometry.TracksPerCylinder * Geometry.SectorsPerTrack * Geometry.BytesPerSector; IoBuffer = VirtualAlloc(NULL,GeometrySize,MEM_COMMIT,PAGE_READWRITE); if ( !IoBuffer ) { printf("MFMT: Buffer Allocation Failed\n"); ExitProcess(1); } b = ReadFile(hDrive,IoBuffer, GeometrySize, &BytesRead, NULL); if (b && BytesRead){ b = WriteFile(hDiskImage,IoBuffer, BytesRead, &BytesWritten, NULL); if ( !b || ( BytesRead != BytesWritten ) ) { printf("MFMT: Fatal Write Error %d\n",GetLastError()); ExitProcess(1); } } else { printf("MFMT: Fatal Read Error %d\n",GetLastError()); ExitProcess(1); } } else { // // Check to see if the image will fit on the floppy. If it // will, then LowLevelFormat the floppy and press on // FileSize = GetFileSize(hDiskImage,NULL); b = FALSE; for(i=0;i<SupportedGeometryCount;i++) { GeometrySize = SupportedGeometry[i].Cylinders.LowPart * SupportedGeometry[i].TracksPerCylinder * SupportedGeometry[i].SectorsPerTrack * SupportedGeometry[i].BytesPerSector; if ( GeometrySize >= FileSize ) { IoBuffer = VirtualAlloc(NULL,GeometrySize,MEM_COMMIT,PAGE_READWRITE); if ( !IoBuffer ) { printf("MFMT: Buffer Allocation Failed\n"); ExitProcess(1); } // // Format the floppy // LowLevelFormat(hDrive,&SupportedGeometry[i]); b = ReadFile(hDiskImage,IoBuffer, GeometrySize, &BytesRead, NULL); if (b && BytesRead){ b = WriteFile(hDrive,IoBuffer, BytesRead, &BytesWritten, NULL); if ( !b || ( BytesRead != BytesWritten ) ) { printf("MFMT: Fatal Write Error %d\n",GetLastError()); ExitProcess(1); } } else { printf("MFMT: Fatal Read Error %d\n",GetLastError()); ExitProcess(1); } b = TRUE; break; } } if ( !b ) { printf("MFMT: FileSize %d is not supported on drive %s\n",FileSize,DriveName); ExitProcess(1); } } } // // Dismounting forces the filesystem to re-evaluate the media id // and geometry. This is the same as popping the floppy in and out // of the disk drive // DismountVolume(hDrive); UnlockVolume(hDrive); ExitProcess(0); } }