static void OpenOrCreate(HWND hwnd) { static bool openAlreadyOpened = false; if (openAlreadyOpened) return; class Unique { public: Unique() { openAlreadyOpened = true; } ~Unique() { openAlreadyOpened = false; } } unique; std::tstring dir = GetExistingDirectory(hwnd, _T("Select a folder which contains or will contain encrypted data."), _T("Select Crypt Folder")); if (dir.empty()) return; // if directory is already configured add and try to mount boost::shared_ptr<EncFSConfig> config(new EncFSConfig); if (readConfig(slashTerminate(wchar_to_utf8_cstr(dir.c_str())), config) != Config_None) { char drive = SelectFreeDrive(hwnd); if (drive) { Drives::drive_t dr(Drives::Add(dir, drive)); if (dr) dr->Mount(hwnd); } return; } // TODO check directory is empty, warning if continue // "You are initializing a crypted directory with a no-empty directory. Is this expected?" OptionsData data; data.rootDir = dir; if (DialogBoxParam(hInst, (LPCTSTR) IDD_OPTIONS, hwnd, (DLGPROC) OptionsDlgProc, (LPARAM) &data) != IDOK) return; // add configuration and add new drive createConfig(slashTerminate(wchar_to_utf8_cstr(dir.c_str())), data.paranoia, false, wchar_to_utf8_cstr(data.password).c_str(), true); Drives::drive_t dr(Drives::Add(dir, data.drive)); if (dr) dr->Mount(hwnd); }
void Drive::Mount(HWND hwnd) { // check drive empty or require a new drive while (GetDriveType(mnt) != DRIVE_NO_ROOT_DIR) { char drive = SelectFreeDrive(hwnd); if (!drive) return; _stprintf(mnt, _T("%c:\\"), drive); Save(); } // check directory existence if (!isDirectory(wchar_to_utf8_cstr(dir.c_str()).c_str())) { if (YesNo(hwnd, _T("Directory does not exists. Remove from list?"))) Drives::Delete(shared_from_this()); return; } // TODO check configuration still exists ?? ... no can cause recursion problem // search if executable is present TCHAR executable[MAX_PATH]; if (!SearchPath(NULL, _T("encfs.exe"), NULL, LENGTH(executable), executable, NULL)) throw truntime_error(_T("Unable to find encfs.exe file")); // ask a password to mount TCHAR pass[128+2]; if (!GetPassword(hwnd, pass, LENGTH(pass)-2)) return; _tcscat(pass, _T("\r\n")); // mount using a sort of popen TCHAR cmd[2048]; _sntprintf(cmd, LENGTH(cmd), _T("\"%s\" -S \"%s\" %c:"), executable, dir.c_str(), mnt[0]); boost::shared_ptr<SubProcessInformations> proc(new SubProcessInformations); proc->creationFlags = CREATE_NEW_PROCESS_GROUP|CREATE_NO_WINDOW; if (!CreateSubProcess(cmd, proc.get())) { DWORD err = GetLastError(); memset(pass, 0, sizeof(pass)); _sntprintf(cmd, LENGTH(cmd), _T("Error: %s (%u)"), proc->errorPart, (unsigned) err); throw truntime_error(cmd); } subProcess = proc; // send the password std::string pwd = wchar_to_utf8_cstr(pass); DWORD written; WriteFile(proc->hIn, pwd.c_str(), pwd.length(), &written, NULL); CloseHandle(proc->hIn); // close input so sub process does not any more proc->hIn = NULL; memset(pass, 0, sizeof(pass)); memset((char*) pwd.c_str(), 0, pwd.length()); mounted = false; // wait for mount, read error and give feedback for (unsigned n = 0; n < 5*10; ++n) { // drive appeared if (GetDriveType(mnt) != DRIVE_NO_ROOT_DIR) { if (Drives::autoShow) Show(hwnd); break; } // process terminated DWORD readed; char output[2048]; switch (WaitForSingleObject(subProcess->hProcess, 200)) { case WAIT_OBJECT_0: case WAIT_ABANDONED: if (ReadFile(proc->hOut, output, sizeof(output)-1, &readed, NULL)) { output[readed] = 0; utf8_to_wchar_buf(output, cmd, LENGTH(cmd)); } else { _stprintf(cmd, _T("Unknown error mounting drive %c:"), mnt[0]); } subProcess.reset(); throw truntime_error(cmd); } } if (subProcess) mounted = true; Save(); // save for resume }