csWString joinFileNames(const csWStringList& files) { size_t size = 0; for(csWStringList::const_iterator it = files.begin(); it != files.end(); it++) { if( it->size() > 0 ) { size += 3 + it->size(); // '"' + <filename> + '"' + ' ' } } if( size < 1 ) { return csWString(); } wchar_t *data = new wchar_t[size]; if( data == 0 ) { return csWString(); } size_t pos(0); for(csWStringList::const_iterator it = files.begin(); it != files.end(); it++) { if( it->size() > 0 ) { data[pos++] = L'"'; csStringNCpy(&data[pos], it->c_str(), it->size()); pos += it->size(); data[pos++] = L'"'; data[pos++] = L' '; } } data[size-1] = L'\0'; // Overwrite last ' ' with '\0' csWString joined(data); delete[] data; return joined; }
csWString quoteFileName(const csWString& filename) { if( filename.empty() ) { return csWString(); } return csWString(L"\""+filename+L"\""); }
bool executeCommand(const UINT cmd, const csWStringList& files) { const csWString parallel = regReadParallel(); const DWORD parallelCount = regReadParallelCount(); const bool hasParallel = !parallel.empty() && parallelCount > 1; const DWORD flags = regReadFlags(); const bool isBatch = testFlags(flags, CMD_FLAG_BATCH); const bool isParallel = testFlags(flags, CMD_FLAG_PARALLEL) && hasParallel; const bool isUnc = testFlags(flags, CMD_FLAG_UNC) && cmd != Cmd_List; const bool isUnix = testFlags(flags, CMD_FLAG_UNIX); const csWString scriptPath = regReadScriptsPath(); const csWStringList scripts = regReadScripts(); if( cmd == Cmd_List || cmd == Cmd_ListWithPath || cmd == Cmd_ListWithPathTabular ) { int size = 0; for(csWStringList::const_iterator it = files.begin(); it != files.end(); it++) { wchar_t *uncName = 0; if( isUnc && (uncName = resolveUNC(it->c_str())) != 0 ) { size += lenFN(csWString(uncName), cmd); delete[] uncName; } else { size += lenFN(*it, cmd); } } wchar_t *text = new wchar_t[size+1]; if( text == 0 ) { return false; } int pos = 0; for(csWStringList::const_iterator it = files.begin(); it != files.end(); it++) { wchar_t *uncName = 0; if( isUnc && (uncName = resolveUNC(it->c_str())) != 0 ) { catFN(text, pos, csWString(uncName), cmd); delete[] uncName; } else { catFN(text, pos, *it, cmd); } } text[size] = L'\0'; if( files.size() == 1 ) { // Overwrite trailing <CR><LF> text[size-1] = text[size-2] = L'\0'; } if( isUnix ) { replace(text, size, L'\\', L'/'); } setClipboardText(text); delete[] text; return true; } else if( cmd == Cmd_CreateSymbolicLink ) { csWString symLink; IFileSaveDialog *saveDialog = NULL; HRESULT hr = CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_INPROC_SERVER, IID_IFileSaveDialog, (LPVOID*)&saveDialog); if( hr == S_OK ) { saveDialog->SetTitle(L"Create symbolic link"); const int index = files.front().lastIndexOf(L'\\'); if( index >= 0 ) { const csWString path = files.front().mid(0, index); const csWString name = files.front().mid(index+1); PIDLIST_ABSOLUTE pidl = NULL; SHParseDisplayName(path.c_str(), NULL, &pidl, 0, NULL); if( pidl != NULL ) { IShellItem *item = NULL; SHCreateItemFromIDList(pidl, IID_IShellItem, (LPVOID*)&item); if( item != NULL ) { saveDialog->SetFolder(item); item->Release(); } CoTaskMemFree(pidl); } saveDialog->SetFileName(name.c_str()); } const COMDLG_FILTERSPEC filterSpec = { L"All files", L"*.*" }; saveDialog->SetFileTypes(1, &filterSpec); const FILEOPENDIALOGOPTIONS opts = FOS_OVERWRITEPROMPT | FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_CREATEPROMPT | FOS_NOREADONLYRETURN | FOS_NODEREFERENCELINKS | FOS_DONTADDTORECENT; saveDialog->SetOptions(opts); if( saveDialog->Show(NULL) == S_OK ) { IShellItem *item = NULL; if( saveDialog->GetResult(&item) == S_OK ) { wchar_t *filename = NULL; if( item->GetDisplayName(SIGDN_FILESYSPATH, &filename) == S_OK ) { symLink = filename; CoTaskMemFree(filename); } item->Release(); } } saveDialog->Release(); } if( !symLink.empty() ) { if( csFileExists(symLink.c_str()) ) { MessageBoxW(NULL, L"Symbolic link target already exists!", L"Error", MB_OK | MB_ICONERROR); return false; } const DWORD linkFlags = csIsDirectory(files.front().c_str()) ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0; if( CreateSymbolicLinkW(symLink.c_str(), files.front().c_str(), linkFlags) == 0 ) { const DWORD lastError = GetLastError(); csWString msg(L"ERROR(0x"); msg += csWString::number(lastError, 16); msg += L"): "; msg += formatError(lastError); MessageBoxW(NULL, msg.c_str(), L"Error", MB_OK | MB_ICONERROR); return false; } } return true; } else if( cmd == Cmd_CheckBatchProcessing ) { regWriteFlags(flags ^ CMD_FLAG_BATCH); return true; } else if( cmd == Cmd_CheckParallelExecution ) { regWriteFlags(flags ^ CMD_FLAG_PARALLEL); return true; } else if( cmd == Cmd_CheckResolveUncPaths ) { regWriteFlags(flags ^ CMD_FLAG_UNC); return true; } else if( cmd == Cmd_CheckUnixPathSeparators ) { regWriteFlags(flags ^ CMD_FLAG_UNIX); return true; } else if( Cmd_ExecuteScripts <= cmd && cmd < Cmd_ExecuteScripts+scripts.size() ) { csWString script(scriptPath + L"\\"); UINT i = 0; for(csWStringList::const_iterator it = scripts.begin(); it != scripts.end(); it++) { if( i == cmd-Cmd_ExecuteScripts ) { script += *it; break; } i++; } if( isParallel ) { csWStringList args(files); args.push_front(script); args.push_front(csWString::number(parallelCount)); ShellExecuteW(NULL, L"open", parallel.c_str(), joinFileNames(args).c_str(), NULL, SW_SHOWNORMAL); } else { // DO NOT use parallelizer if( isBatch ) { const csWString args = joinFileNames(files); ShellExecuteW(NULL, L"open", script.c_str(), args.c_str(), NULL, SW_SHOWNORMAL); } else { // NO batch processing for(csWStringList::const_iterator it = files.begin(); it != files.end(); it++) { ShellExecuteW(NULL, L"open", script.c_str(), quoteFileName(*it).c_str(), NULL, SW_SHOWNORMAL); } } } return true; } return false; }