/**************************************************************** * multicopy.cpp * ------------- * Simple windows exe to copy a source to multiple destinations * by utilising the Windows Explorer API. * * Author: Oren Nachman * * License: Free to use - though a shoutout would be nice! ****************************************************************/ #include #include #include #include #include #include #include using namespace std; class ThreadCopyObject { private: SHFILEOPSTRUCTA fop; public: ThreadCopyObject(SHFILEOPSTRUCTA fop) { this->fop = fop; } static unsigned long doCopy(void* param) { SHFILEOPSTRUCTA fop =((ThreadCopyObject*)param)->fop; string msg; if(!SHFileOperation(&fop)) { //all is ok msg = "Copying to: "; msg += fop.pTo; msg += " Completed!"; } else { //some error msg = "Error copying to: "; msg += fop.pTo; } printStat (GetCurrentThreadId(), msg); return 0; } static void printStat(int id, string msg) { cout << "[" << id << "] : " << msg << endl; } }; int main(int argc, char* argv[]) { SHFILEOPSTRUCTA fop; char* src = (char*)malloc(sizeof(char) * (strlen(argv[1]) + 2)); //source string must end with \0\0 strcpy(src, argv[1]); src[strlen(argv[1])] = '\0'; src[strlen(argv[1]) + 1] = '\0'; //just to be safe //initialise common copy data fop.hwnd = NULL; fop.wFunc = FO_COPY; fop.fFlags = FOF_MULTIDESTFILES | FOF_NOCONFIRMMKDIR | FOF_NOCONFIRMATION; fop.pFrom = src; ThreadCopyObject** threads = (ThreadCopyObject**)malloc(sizeof(ThreadCopyObject*) * (argc - 2)); char** targets = (char**)malloc(sizeof(char*) * (argc - 2)); HANDLE* handles = (HANDLE*)malloc(sizeof(HANDLE) * (argc - 2)); for (int i = 2; i < argc; i++) { int idx = i - 2; //we can't use the same string for the target because the threads //will be accessing the same string concurrently (so each needs it's //own copy) targets[idx] = (char*)malloc(sizeof(char) * (strlen(argv[i]) + 2)); strcpy(targets[idx], argv[i]); //target string also needs to be padded out with \0\0 targets[idx][strlen(argv[i])] = '\0'; targets[idx][strlen(argv[i]) + 1] = '\0'; fop.pTo = targets[i - 2]; threads[idx] = new ThreadCopyObject(fop); handles[idx] = (HANDLE *)malloc(sizeof(HANDLE)); cout << "Spawning thread to copy to: " << targets[idx] << endl; handles[idx] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threads[i-2]->doCopy, threads[i-2], 0, NULL ); } WaitForMultipleObjects(argc - 2, handles, true, INFINITE); //free memory and close thread handles for (int i = 0; i < argc - 2; i++) { free(targets[i]); CloseHandle(handles[i]); } free(threads); free(handles); free(targets); free(src); }