2727#include < string>
2828#include < vector>
2929#include < CommCtrl.h>
30+ #include < Shlwapi.h>
3031
3132
3233HWND g_hwndCIDlg = nullptr , g_hwndCIHlpDlg = nullptr ;
@@ -272,6 +273,7 @@ INT_PTR CALLBACK ciDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
272273 }
273274
274275 // loop through each index in the buffer, and download as needed
276+ std::map<std::wstring, std::wstring> mapUacDelayed;
275277 for (auto selectedFileIndex: vBuf) {
276278 if (selectedFileIndex == LB_ERR) {
277279 ::MessageBox (NULL , L" Could not understand name selection; sorry" , L" Download Error" , MB_ICONERROR);
@@ -367,23 +369,8 @@ INT_PTR CALLBACK ciDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
367369 else {
368370 // check if it needs to be overwritten before elevating permissions
369371 if (pobjCI->ask_overwrite_if_exists (wsPath)) {
370- // download to a temp path, then use ShellExecute(runas) to move it from the temp path to the final destination
371- std::wstring wsAsk = L" Cannot write to " + wsPath;
372- wsAsk += L" \n I will try again with elevated UAC permission." ;
373- int ans = ::MessageBox (hwndDlg, wsAsk.c_str (), L" Need Directory Permission" , MB_OKCANCEL);
374- if (ans == IDOK) {
375- std::wstring tmpPath = pobjCI->getWritableTempDir () + L" \\ ~$TMPFILE.DOWNLOAD.PRYRT.xml" ;
376- pobjCI->downloadFileToDisk (wsURL, tmpPath);
377- std::wstring msg = L" Downloaded from\n " + tmpPath + L" \n and moved to\n " + wsPath;
378- std::wstring args = L" /C MOVE /Y \" " + tmpPath + L" \" \" " + wsPath + L" \" " ;
379- ShellExecute (hwndDlg, L" runas" , L" cmd.exe" , args.c_str (), NULL , SW_SHOWMINIMIZED);
380- // ::MessageBox(hwndDlg, msg.c_str(), L"Download and UAC move", MB_OK);
381- count++;
382- didDownload = true ;
383- }
384- else {
385- total--;
386- }
372+ mapUacDelayed[wsURL] = wsPath;
373+ total--;
387374 }
388375 else {
389376 total--;
@@ -392,6 +379,7 @@ INT_PTR CALLBACK ciDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
392379
393380 // update progress bar
394381 wchar_t wcDLPCT[256 ];
382+ if (total < 1 ) total = 1 ;
395383 swprintf_s (wcDLPCT, L" Downloading %d%%" , 100 * count / total);
396384 if (didDownload) {
397385 ::SendDlgItemMessage (hwndDlg, IDC_CI_PROGRESSBAR, PBM_SETPOS, 100 * count / total, 0 );
@@ -411,29 +399,16 @@ INT_PTR CALLBACK ciDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
411399 }
412400 else {
413401 if (pobjCI->ask_overwrite_if_exists (xPath)) {
414- // download to a temp path, then use ShellExecute(runas) to move it from the temp path to the final destination
415- std::wstring wsAsk = L" Cannot write to " + xPath;
416- wsAsk += L" \n I will try again with elevated UAC permission." ;
417- int ans = ::MessageBox (hwndDlg, wsAsk.c_str (), L" Need Directory Permission" , MB_OKCANCEL);
418- if (ans == IDOK) {
419- std::wstring tmpPath = pobjCI->getWritableTempDir () + L" \\ ~$TMPFILE.DOWNLOAD.PRYRT.xml" ;
420- pobjCI->downloadFileToDisk (xURL, tmpPath);
421- std::wstring msg = L" Downloaded from\n " + tmpPath + L" \n and moved to\n " + xPath;
422- std::wstring args = L" /C MOVE /Y \" " + tmpPath + L" \" \" " + xPath + L" \" " ;
423- ShellExecute (hwndDlg, L" runas" , L" cmd.exe" , args.c_str (), NULL , SW_SHOWMINIMIZED);
424- count++;
425- didDownload = true ;
426- }
427- else {
428- total--;
429- }
402+ mapUacDelayed[xURL] = xPath;
403+ total--;
430404 }
431405 else {
432406 total--;
433407 }
434408 }
435409 }
436410 // update progress bar
411+ if (total < 1 ) total = 1 ;
437412 swprintf_s (wcDLPCT, L" Downloading %d%%" , 100 * count / total);
438413 if (didDownload) {
439414 ::SendDlgItemMessage (hwndDlg, IDC_CI_PROGRESSBAR, PBM_SETPOS, 100 * count / total, 0 );
@@ -454,6 +429,43 @@ INT_PTR CALLBACK ciDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam
454429 }
455430 }
456431
432+ if (mapUacDelayed.size ()) {
433+ int total = static_cast <int >(mapUacDelayed.size ()) + 1 ; // want one extra "slot" for the MOVE command
434+ int count = 0 ;
435+ std::wstring wsAsk = L" Cannot write the following files:" ;
436+ for (const auto & pair : mapUacDelayed) {
437+ wsAsk += std::wstring (L" \n " ) + pair.second ;
438+ }
439+ wsAsk += L" \n\n I will download temporary files, and then try to copy them to the right location with elevated UAC permission. (The OS may prompt you for UAC.)" ;
440+ int ans = ::MessageBox (hwndDlg, wsAsk.c_str (), L" Need Directory Permission" , MB_OKCANCEL);
441+ if (ans == IDOK) {
442+ wchar_t wcDLPCT[256 ];
443+ swprintf_s (wcDLPCT, L" Downloading %d%%" , 100 * count / total);
444+ Edit_SetText (GetDlgItem (hwndDlg, IDC_CI_PROGRESSLBL), wcDLPCT);
445+
446+ std::wstring args = L" /C " ;
447+
448+ for (const auto & pair : mapUacDelayed) {
449+ ++count;
450+ std::wstring tmpPath = pobjCI->getWritableTempDir () + L" \\ ~$TMPFILE.DOWNLOAD.PRYRT." + std::to_wstring (count);
451+ pobjCI->downloadFileToDisk (pair.first , tmpPath);
452+ didDownload = true ;
453+ args += L" MOVE /Y \" " + tmpPath + L" \" \" " + pair.second + L" \" & " ;
454+
455+ ::SendDlgItemMessage (hwndDlg, IDC_CI_PROGRESSBAR, PBM_SETPOS, 100 * count / total, 0 );
456+ swprintf_s (wcDLPCT, L" Downloading %d%%" , 100 * count / total);
457+ Edit_SetText (GetDlgItem (hwndDlg, IDC_CI_PROGRESSLBL), wcDLPCT);
458+ }
459+
460+ // ::MessageBox(hwndDlg, (std::wstring(L"cmd.exe ") + args).c_str(), L"TODO: UAC Command", MB_OK);
461+ ShellExecute (hwndDlg, L" runas" , L" cmd.exe" , args.c_str (), NULL , SW_SHOWMINIMIZED);
462+
463+ ::SendDlgItemMessage (hwndDlg, IDC_CI_PROGRESSBAR, PBM_SETPOS, 100 , 0 );
464+ swprintf_s (wcDLPCT, L" Downloading %d%% [DONE]" , 100 );
465+ Edit_SetText (GetDlgItem (hwndDlg, IDC_CI_PROGRESSLBL), wcDLPCT);
466+ }
467+ }
468+
457469 return true ;
458470 }
459471 case IDC_CI_HELPBTN:
0 commit comments