// DropDlg.cpp : Implementation of CDropDlg #include "stdafx.h" #include "DropDlg.h" ///////////////////////////////////////////////////////////////////////////// // CDropDlg const TCHAR* kLastBatch = _T("Batch"); CDropDlg::CDropDlg() : m_settings(HKEY_CURRENT_USER, _T("SOFTWARE\\WS\\Dropper\\")), CPersistPosWindow("Window") { m_isRunning = false; m_isCancelled = false; } void AddBatches(const string& wildcard, CComboBox& ctlBatch) { WIN32_FIND_DATA findData; HANDLE hFindFile = FindFirstFile(wildcard, &findData); if(hFindFile != INVALID_HANDLE_VALUE) { do { // Get first part of the file string name = findData.cFileName; name = name.substr(0, name.find_last_of('.')); ctlBatch.AddString(name); } while(FindNextFile(hFindFile, &findData)); } FindClose(hFindFile); } LRESULT CDropDlg::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { m_ctlLog = GetDlgItem(IDC_LOG); m_baseDir = GetModuleFolder(_Module.GetModuleInstance()); CleanFolder(m_baseDir); CComboBox ctlBatch = GetDlgItem(IDC_BATCH); AddBatches(m_baseDir + _T("*.cmd"), ctlBatch); AddBatches(m_baseDir + _T("*.bat"), ctlBatch); SetMin(IDC_MINSIZE); SetControlSizing(IDC_LOG, SD_HORZ | SD_VERT | SD_SIZING); SetControlSizing(IDC_RUN, SD_HORZ | SD_MOVING); SetControlSizing(IDC_BATCH, SD_HORZ | SD_SIZING); // Select last used batch ctlBatch.SelectString(-1, m_settings.GetString(kLastBatch)); SetRunMode(false); // Center it CenterWindow(); LoadPosition(m_settings); SetIcon((HICON)LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDI_MAIN), IMAGE_ICON, 32, 32, LR_SHARED), TRUE); SetIcon((HICON)LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDI_MAIN), IMAGE_ICON, 16, 16, LR_SHARED), FALSE); return 1; // Let the system set the focus } LRESULT CDropDlg::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { SavePosition(m_settings); return 1; } void CDropDlg::SetRunMode(bool isRunning) { m_isRunning = isRunning; if(isRunning) m_isCancelled = false; DragAcceptFiles(isRunning ? FALSE : TRUE); ::EnableWindow(GetDlgItem(IDC_BATCH), isRunning ? FALSE : TRUE); ::EnableWindow(GetDlgItem(IDC_RUN), TRUE); SetDlgItemText(IDC_RUN, isRunning ? _T("Cancel") : _T("Run")); } void CDropDlg::ReportError(HRESULT hr) { MessageBox(FormatHR(hr), _T("Dropper"), MB_ICONSTOP | MB_OK); } string CDropDlg::CleanFolder(const string& folderName) { if(folderName.at(folderName.length() - 1) != _T('\\')) return folderName + _T("\\"); return folderName; } bool CDropDlg::IsDots(const string& fileName) { return fileName == _T(".") || fileName == _T(".."); } LRESULT CDropDlg::OnDropFiles(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { HDROP hDrop = (HDROP)wParam; HRESULT hr = S_OK; string fileName; string batchName = GetCurBatch(); SetRunMode(true); SetDlgItemText(IDC_LOG, _T("")); UINT numFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); for(int i = 0; i < numFiles; i++) { if(DragQueryFile(hDrop, i, fileName.get_buffer(MAX_PATH), MAX_PATH)) { fileName.release_buffer(); hr = RunWithFile(batchName, fileName); if(FAILED(hr)) { ReportError(hr); break; } } } DragFinish(hDrop); SetRunMode(false); return 0; } LRESULT CDropDlg::OnClose(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { if(!m_isRunning) { string batchName; GetDlgItemText(IDC_BATCH, batchName.get_buffer(MAX_PATH), MAX_PATH); batchName.release_buffer(); m_settings.WriteString(kLastBatch, batchName); EndDialog(wID); } else { m_isCancelled = true; } return 0; } LRESULT CDropDlg::OnRun(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { if(m_isRunning) { // It's a cancel button now m_isCancelled = true; ::EnableWindow(GetDlgItem(IDC_RUN), FALSE); } else { // It's a run button SetRunMode(true); SetDlgItemText(IDC_LOG, _T("")); HRESULT hr = RunWithFile(GetCurBatch(), _T("")); if(FAILED(hr)) ReportError(hr); SetRunMode(false); } return 0; } string CDropDlg::GetCurBatch() { string sBatch; GetDlgItemText(IDC_BATCH, sBatch.get_buffer(MAX_PATH), MAX_PATH); sBatch.release_buffer(); return sBatch; } HRESULT CDropDlg::RunWithFolder(const string& batch, const string& folderName) { string wildcard = folderName + _T("*.*"); WIN32_FIND_DATA findData; HRESULT hr = S_OK; HANDLE hFindFile = FindFirstFile(wildcard, &findData); if(hFindFile != INVALID_HANDLE_VALUE) { do { if(!IsDots(findData.cFileName)) { string fileName = folderName + findData.cFileName; hr = RunWithFile(batch, fileName); if(FAILED(hr)) return hr; } if(m_isCancelled) { ::SetLastError(ERROR_SUCCESS); break; } } while(FindNextFile(hFindFile, &findData)); } if(GetLastError() != 0 && GetLastError() != ERROR_NO_MORE_FILES) return HRESULT_FROM_WIN32(::GetLastError()); return S_OK; } HRESULT CDropDlg::RunWithFile(const string& batch, const string& path) { if(path.size() > 0) { DWORD fileAttrib = GetFileAttributes(path); if(fileAttrib & FILE_ATTRIBUTE_DIRECTORY) { return RunWithFolder(batch, CleanFolder(path)); } } string cmdLine = _T("\"") + m_baseDir + batch + _T(".bat\""); HRESULT hr = S_OK; if(path.size() > 0) { cmdLine += _T(" \"") + path + _T("\""); size_t pos = path.find_last_of(_T("\\/")); string file, dir; if(pos != string::npos) { pos++; file = path.substr(pos); dir = path.substr(0, pos); } else { file = path; } SetEnvironmentVariable(_T("DROPPED_FILE"), file); SetEnvironmentVariable(_T("DROPPED_DIR"), dir); SetEnvironmentVariable(_T("DROPPED_PATH"), path); } if(!CreateProcessOutput(NULL, (LPTSTR)(LPCTSTR)cmdLine, NULL, NULL, TRUE, 0, NULL, m_baseDir, OutputString, (LPVOID)this)) { hr = HRESULT_FROM_WIN32(::GetLastError()); } // Do an extra line OutputString(_T("\r\n"), (LPVOID)this); return S_OK; } BOOL CDropDlg::OutputString(LPCTSTR data, LPVOID param) { CDropDlg* pDlg = (CDropDlg*)param; pDlg->m_ctlLog.AppendText(data); // TODO: Provide some way to cancel return TRUE; }