From 8b4732e811fcca736c6e8a78b1d03c441d30ea2c Mon Sep 17 00:00:00 2001 From: David Kocik <kocikdav@gmail.com> Date: Tue, 26 Nov 2019 14:19:29 +0100 Subject: [PATCH] removable drive manager - Windows part --- src/slic3r/GUI/AppConfig.cpp | 5 + src/slic3r/GUI/RemovableDriveManager.cpp | 149 +++++++++++++++++++++++ src/slic3r/GUI/RemovableDriveManager.hpp | 41 +++++++ 3 files changed, 195 insertions(+) create mode 100644 src/slic3r/GUI/RemovableDriveManager.cpp create mode 100644 src/slic3r/GUI/RemovableDriveManager.hpp diff --git a/src/slic3r/GUI/AppConfig.cpp b/src/slic3r/GUI/AppConfig.cpp index d33d945ef..4f3272e26 100644 --- a/src/slic3r/GUI/AppConfig.cpp +++ b/src/slic3r/GUI/AppConfig.cpp @@ -21,6 +21,7 @@ #include <wx/string.h> #include "I18N.hpp" +#include "RemovableDriveManager.hpp" namespace Slic3r { @@ -357,6 +358,10 @@ void AppConfig::update_skein_dir(const std::string &dir) std::string AppConfig::get_last_output_dir(const std::string &alt) const { + if (GUI::RemovableDriveManager::getInstance().update()) + { + return GUI::RemovableDriveManager::getInstance().getLastDrivePath(); + } const auto it = m_storage.find(""); if (it != m_storage.end()) { const auto it2 = it->second.find("last_output_path"); diff --git a/src/slic3r/GUI/RemovableDriveManager.cpp b/src/slic3r/GUI/RemovableDriveManager.cpp new file mode 100644 index 000000000..44d4181d1 --- /dev/null +++ b/src/slic3r/GUI/RemovableDriveManager.cpp @@ -0,0 +1,149 @@ +#include "RemovableDriveManager.hpp" + +#include <windows.h> +#include <tchar.h> +#include <iostream> +#include <stdio.h> + +//#include <boost/log/trivial.hpp> +//#include "libslic3r/Utils.hpp" + +DEFINE_GUID(GUID_DEVINTERFACE_USB_DEVICE, + 0xA5DCBF10L, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED); + +namespace Slic3r { +namespace GUI { + +std::vector<DriveData> RemovableDriveManager::currentDrives; + +bool RemovableDriveManager::update() +{ + searchForDrives(currentDrives); + return !currentDrives.empty(); +} +void RemovableDriveManager::searchForDrives(std::vector<DriveData>& newDrives) +{ + newDrives.clear(); + newDrives.reserve(26); + DWORD drivesMask = GetLogicalDrives(); + for (size_t i = 0; i < 26; i++) + { + if(drivesMask & (1 << i)) + { + std::string path (1,(char)('A' + i)); + path+=":"; + UINT driveType = GetDriveTypeA(path.c_str()); + //std::cout << "found drive" << (char)('A' + i) << ": type:" <<driveType << "\n"; + if (driveType == DRIVE_REMOVABLE) + { + // get name of drive + std::wstring wpath = std::wstring(path.begin(), path.end()); + std::wstring volumeName; + volumeName.resize(1024); + std::wstring fileSystemName; + fileSystemName.resize(1024); + LPWSTR lpVolumeNameBuffer = new wchar_t; + BOOL error = GetVolumeInformationW(wpath.c_str(), &volumeName[0], sizeof(volumeName), NULL, NULL, NULL, &fileSystemName[0], sizeof(fileSystemName)); + if(error != 0) + { + if (volumeName == L"") + { + volumeName = L"REMOVABLE DRIVE"; + } + if (fileSystemName != L"") + { + ULARGE_INTEGER freeSpace; + GetDiskFreeSpaceExA(path.c_str(), &freeSpace, NULL, NULL); + //std::cout << std::string(volumeName.begin(), volumeName.end()) << " " << std::string(fileSystemName.begin(), fileSystemName.end()) << " " << freeSpace.QuadPart << "\n"; + if (freeSpace.QuadPart > 0) + { + newDrives.push_back(DriveData(volumeName, path)); + } + } + } + } + else if(driveType == 3)//disks and usb drives + { + } + } + } + +} + +void RemovableDriveManager::updateCurrentDrives(const std::vector<DriveData>& newDrives) +{ + currentDrives.clear(); + currentDrives.reserve(26); + for (auto it = newDrives.begin(); it != newDrives.end(); ++it) + { + currentDrives.push_back(*it); + } +} +void RemovableDriveManager::printDrivesToLog() +{ + //std::cout<<"current drives:"<< currentDrives.size() <<"\n"; + for (auto it = currentDrives.begin(); it != currentDrives.end(); ++it) + { + //BOOST_LOG_TRIVIAL(trace) << boost::format("found disk %1%:") % ('A' + i); + //std::cout << /*std::string((*it).name.begin(), (*it).name.end()) << "(" << */(*it).path << ":/, "; + } + //std::cout << "\n"; +} +bool RemovableDriveManager::isDriveMounted(std::string path) +{ + for (auto it = currentDrives.begin(); it != currentDrives.end(); ++it) + { + if ((*it).path == path) + { + return true; + } + } + return false; +} +void RemovableDriveManager::ejectDrive(std::string path) +{ + if (!update() || !isDriveMounted(path)) + return; + + path = "\\\\.\\"+path; + HANDLE handle = CreateFileA(path.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr); + if(handle == INVALID_HANDLE_VALUE) + { + std::cerr << "Ejecting " << path << " failed " << GetLastError() << " \n"; + return; + } + DWORD deviceControlRetVal(0); + BOOL error = DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, nullptr, 0,nullptr , 0, &deviceControlRetVal, nullptr); + CloseHandle(handle); + if(error != 0) + std::cout << "Ejected " << path << "\n"; + else + std::cerr << "Ejecting " << path << " failed "<< deviceControlRetVal << " " << GetLastError() <<" \n"; + + for (auto it = currentDrives.begin(); it != currentDrives.end(); ++it) + { + if ((*it).path == path) + { + currentDrives.erase(it); + break; + } + } +} +std::string RemovableDriveManager::getLastDrivePath() +{ + if (!currentDrives.empty()) + { + return currentDrives.back().path; + } + return ""; +} +void RemovableDriveManager::getAllDrives(std::vector<DriveData>& drives) +{ + drives.clear(); + drives.reserve(26); + for (auto it = currentDrives.begin(); it != currentDrives.end(); ++it) + { + drives.push_back(*it); + } +} +}} \ No newline at end of file diff --git a/src/slic3r/GUI/RemovableDriveManager.hpp b/src/slic3r/GUI/RemovableDriveManager.hpp new file mode 100644 index 000000000..cab58fee6 --- /dev/null +++ b/src/slic3r/GUI/RemovableDriveManager.hpp @@ -0,0 +1,41 @@ +#ifndef slic3r_GUI_RemovableDriveManager_hpp_ +#define slic3r_GUI_RemovableDriveManager_hpp_ + +#include <vector> +#include <string> + +namespace Slic3r { +namespace GUI { +struct DriveData +{ + std::wstring name; + std::string path; + DriveData(std::wstring n, std::string p):name(n),path(p){} +}; +class RemovableDriveManager +{ +public: + static RemovableDriveManager& getInstance() + { + static RemovableDriveManager instance; + return instance; + } + RemovableDriveManager(RemovableDriveManager const&) = delete; + void operator=(RemovableDriveManager const&) = delete; + + //update() searches for removable devices, returns false if empty. + static bool update(); + static bool isDriveMounted(std::string path); + static void ejectDrive(std::string path); + static std::string getLastDrivePath(); + static void getAllDrives(std::vector<DriveData>& drives); +private: + RemovableDriveManager(){} + static void searchForDrives(std::vector<DriveData>& newDrives); + static void printDrivesToLog(); + static void updateCurrentDrives(const std::vector<DriveData>& newDrives); + static std::vector<DriveData> currentDrives; + +}; +}} +#endif \ No newline at end of file