From 010dc75a7127435a51a8ca42484eee15b13a881e Mon Sep 17 00:00:00 2001 From: kichik Date: Fri, 6 Aug 2004 17:03:07 +0000 Subject: [PATCH] converted RMDir back from SHFileOperation to the good old manual method - RMDir can now be used with both /r and /REBOOTOK - RMDir /r no longer leaves lots of files behind if one file removal failed - The plug-ins directory is now always deleted, if not immediately, then after reboot - RMDir /r prints a detailed log of its actions git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@3597 212acab6-be3b-0410-9dea-997c60f758d6 --- Docs/src/basic.but | 4 +- Source/exehead/Main.c | 2 +- Source/exehead/exec.c | 47 ++------------ Source/exehead/fileform.h | 5 ++ Source/exehead/util.c | 126 ++++++++++++++++++++++++++++++-------- Source/exehead/util.h | 2 +- Source/script.cpp | 40 ++++++++---- Source/tokens.cpp | 2 +- 8 files changed, 141 insertions(+), 87 deletions(-) diff --git a/Docs/src/basic.but b/Docs/src/basic.but index 39f788ee..a890a848 100644 --- a/Docs/src/basic.but +++ b/Docs/src/basic.but @@ -66,9 +66,9 @@ See \R{file}{File} for more information about the parameters. \S2{rmdir} RMDir -\c [/r|/REBOOTOK] directory_name +\c [/r] [/REBOOTOK] directory_name -Remove the specified directory (which should be a full path). Without /r, the directory will only be removed if it is completely empty. If /r is specified, the directory will be removed recursively, so all directories and files in the specified directory will be removed. If /REBOOTOK is specified, and the directory cannot be overwritten, then the directory will be deleted when the system reboots -- if the directory will be removed on a reboot, the reboot flag will be set. The error flag is set if the directory cannot be removed. +Remove the specified directory (which should be a full path). Without /r, the directory will only be removed if it is completely empty. If /r is specified, the directory will be removed recursively, so all directories and files in the specified directory will be removed. If /REBOOTOK is specified, any file or directory which could not have been removed during the process will be removed on reboot -- if any file or directory will be removed on a reboot, the reboot flag will be set. The error flag is set if any file or directory cannot be removed. \S2{setoutpath} SetOutPath diff --git a/Source/exehead/Main.c b/Source/exehead/Main.c index 966ea2fc..12a67fd0 100644 --- a/Source/exehead/Main.c +++ b/Source/exehead/Main.c @@ -278,6 +278,6 @@ void NSISCALL CleanUp() #endif #ifdef NSIS_CONFIG_PLUGIN_SUPPORT // Clean up after plug-ins - doRMDir(state_plugins_dir, 1); + myDelete(state_plugins_dir, DEL_DIR | DEL_RECURSE | DEL_REBOOT); #endif // NSIS_CONFIG_PLUGIN_SUPPORT } diff --git a/Source/exehead/exec.c b/Source/exehead/exec.c index 4920fbbd..6db2c25b 100644 --- a/Source/exehead/exec.c +++ b/Source/exehead/exec.c @@ -487,46 +487,9 @@ static int NSISCALL ExecuteEntry(entry *entry_) #ifdef NSIS_SUPPORT_DELETE case EW_DELETEFILE: { - HANDLE h; - WIN32_FIND_DATA fd; - char *buf1=GetStringFromParm(0x10); - mystrcpy(buf0,buf1); + char *buf0=GetStringFromParm(0x00); log_printf2("Delete: \"%s\"",buf0); - trimslashtoend(buf0); - h=FindFirstFile(buf1,&fd); - if (h != INVALID_HANDLE_VALUE) - { - do - { - if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) - { - wsprintf(buf1,"%s\\%s",buf0,fd.cFileName); - if (fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) - SetFileAttributes(buf1,fd.dwFileAttributes^FILE_ATTRIBUTE_READONLY); - if (DeleteFile(buf1)) - { - log_printf2("Delete: DeleteFile(\"%s\")",buf1); - update_status_text_buf1(LANG_DELETEFILE); - } - else - { -#ifdef NSIS_SUPPORT_MOVEONREBOOT - if (parm1) - { - log_printf2("Delete: DeleteFile on Reboot(\"%s\")",buf1); - update_status_text_buf1(LANG_DELETEONREBOOT); - MoveFileOnReboot(buf1,NULL); - } - else -#endif - { - exec_error++; - } - } - } - } while (FindNextFile(h,&fd)); - FindClose(h); - } + myDelete(buf0,parm1); } break; #endif//NSIS_SUPPORT_DELETE @@ -558,9 +521,7 @@ static int NSISCALL ExecuteEntry(entry *entry_) char *buf1=GetStringFromParm(-0x10); log_printf2("RMDir: \"%s\"",buf1); - doRMDir(buf1,parm1); - if (file_exists(buf1) && parm1!=2) exec_error++; - else update_status_text_buf1(LANG_REMOVEDIR); + myDelete(buf1,parm1); } break; #endif//NSIS_SUPPORT_RMDIR @@ -1178,7 +1139,7 @@ static int NSISCALL ExecuteEntry(entry *entry_) { char *buf3=GetStringFromParm(0x33); res = RegDeleteValue(hKey,buf3); - log_printf4("DeleteRegValue: %d\\%s\\%s",rootkey,buf2,buf3); + log_printf4("DeleteRegValue: %d\\%s\\%s",parm1,buf2,buf3); RegCloseKey(hKey); } } diff --git a/Source/exehead/fileform.h b/Source/exehead/fileform.h index fef87017..f09c35de 100644 --- a/Source/exehead/fileform.h +++ b/Source/exehead/fileform.h @@ -432,6 +432,11 @@ typedef struct { int flags; } ctlcolors; +// constants for myDelete (util.c) +#define DEL_DIR 1 +#define DEL_RECURSE 2 +#define DEL_REBOOT 4 + // $0..$9, $INSTDIR, etc are encoded as ASCII bytes starting from this value. // Added by ramon 3 jun 2003 #define NS_SKIP_CODE 252 diff --git a/Source/exehead/util.c b/Source/exehead/util.c index e95af818..77402098 100644 --- a/Source/exehead/util.c +++ b/Source/exehead/util.c @@ -94,36 +94,110 @@ void * NSISCALL my_GlobalAlloc(DWORD dwBytes) { return (void *)GlobalAlloc(GPTR, dwBytes); } -#ifdef NSIS_SUPPORT_RMDIR -void NSISCALL doRMDir(char *buf, int flags) // 1 - recurse, 2 - rebootok +void NSISCALL myDelete(char *buf, int flags) { - if (is_valid_instpath(buf)) - { - if (flags&1) { - SHFILEOPSTRUCT op; + static char lbuf[NSIS_MAX_STRLEN]; - op.hwnd=g_hwnd; - op.wFunc=FO_DELETE; - buf[mystrlen(buf)+1]=0; - op.pFrom=buf; - op.pTo=0; + HANDLE h; + WIN32_FIND_DATA fd; + char *fn; - op.fFlags=FOF_NOERRORUI|FOF_SILENT|FOF_NOCONFIRMATION; - - SHFileOperation(&op); - } -#ifdef NSIS_SUPPORT_MOVEONREBOOT - else if (!RemoveDirectory(buf) && flags&2) { - log_printf2("Remove folder on reboot: %s",buf); - MoveFileOnReboot(buf,0); - } -#else - else RemoveDirectory(buf); -#endif - } - log_printf2("RMDir: RemoveDirectory(\"%s\")",buf); -} +#ifdef NSIS_SUPPORT_RMDIR + if (!(flags & DEL_DIR) || (is_valid_instpath(buf) && (flags & DEL_RECURSE))) #endif//NSIS_SUPPORT_RMDIR + { + mystrcpy(lbuf,buf); +#ifdef NSIS_SUPPORT_RMDIR + if (flags & DEL_DIR) + lstrcat(lbuf,"\\*.*"); + else +#endif//NSIS_SUPPORT_RMDIR + trimslashtoend(buf); + + lstrcat(buf,"\\"); + + fn=buf+mystrlen(buf); + + h = FindFirstFile(lbuf,&fd); + if (h != INVALID_HANDLE_VALUE) + { + do + { +#ifdef NSIS_SUPPORT_RMDIR + if (fd.cFileName[0] != '.' || + (fd.cFileName[1] != '.' && fd.cFileName[1])) +#endif//NSIS_SUPPORT_RMDIR + { + mystrcpy(fn,fd.cFileName); + if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { +#ifdef NSIS_SUPPORT_RMDIR + if ((flags & DEL_DIR | DEL_RECURSE) == (DEL_DIR | DEL_RECURSE)) + { + myDelete(buf,flags); + } +#endif//NSIS_SUPPORT_RMDIR + } + else + { + log_printf2("Delete: DeleteFile(\"%s\")",buf); + SetFileAttributes(buf,fd.dwFileAttributes&(~FILE_ATTRIBUTE_READONLY)); + if (!DeleteFile(buf)) + { +#ifdef NSIS_SUPPORT_MOVEONREBOOT + if (flags & DEL_REBOOT) + { + log_printf2("Delete: DeleteFile on Reboot(\"%s\")",buf); + update_status_text(LANG_DELETEONREBOOT,buf); + MoveFileOnReboot(buf,NULL); + } + else +#endif//NSIS_SUPPORT_MOVEONREBOOT + { + log_printf2("Delete: DeleteFile failed(\"%s\")",buf); + g_exec_flags.exec_error++; + } + } + else + update_status_text(LANG_DELETEFILE,buf); + } + } + } while (FindNextFile(h,&fd)); + FindClose(h); + } + +#ifdef NSIS_SUPPORT_RMDIR + if (flags & DEL_DIR) + fn[-1]=0; +#endif//NSIS_SUPPORT_RMDIR + } + +#ifdef NSIS_SUPPORT_RMDIR + if (flags & DEL_DIR) + { + addtrailingslash(buf); + log_printf2("RMDir: RemoveDirectory(\"%s\")",buf); + if (!RemoveDirectory(buf)) + { +#ifdef NSIS_SUPPORT_MOVEONREBOOT + if (flags & DEL_REBOOT) + { + log_printf2("RMDir: RemoveDirectory on Reboot(\"%s\")",buf); + update_status_text(LANG_DELETEONREBOOT,buf); + MoveFileOnReboot(buf,NULL); + } + else +#endif//NSIS_SUPPORT_MOVEONREBOOT + { + log_printf2("RMDir: RemoveDirectory failed(\"%s\")",buf); + g_exec_flags.exec_error++; + } + } + else + update_status_text(LANG_REMOVEDIR,buf); + } +#endif//NSIS_SUPPORT_RMDIR +} char *NSISCALL addtrailingslash(char *str) { diff --git a/Source/exehead/util.h b/Source/exehead/util.h index 0ec9980b..f6e42af3 100644 --- a/Source/exehead/util.h +++ b/Source/exehead/util.h @@ -54,7 +54,7 @@ HANDLE NSISCALL myCreateProcess(char *cmd, char *dir); int NSISCALL my_MessageBox(const char *text, UINT type); void * NSISCALL my_GlobalAlloc(DWORD dwBytes); -void NSISCALL doRMDir(char *buf, int recurse); +void NSISCALL myDelete(char *buf, int flags); HANDLE NSISCALL myOpenFile(const char *fn, DWORD da, DWORD cd); int NSISCALL validpathspec(char *ubuf); diff --git a/Source/script.cpp b/Source/script.cpp index cf16fdc4..f72294c8 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -3929,7 +3929,7 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) if (!stricmp(line.gettoken_str(a),"/REBOOTOK")) { a++; - ent.offsets[1]=1; + ent.offsets[1]=DEL_REBOOT; #ifndef NSIS_SUPPORT_MOVEONREBOOT ERROR_MSG("Error: /REBOOTOK specified, NSIS_SUPPORT_MOVEONREBOOT not defined\n"); PRINTHELP() @@ -3958,23 +3958,37 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) { int a=1; ent.which=EW_RMDIR; - if (!stricmp(line.gettoken_str(1),"/r")) + ent.offsets[1]=DEL_DIR; + while (line.gettoken_str(a)[0]=='/') { - if (line.getnumtokens() < 3) PRINTHELP() - a++; - ent.offsets[1]=1; + if (!stricmp(line.gettoken_str(a),"/r")) + { + if (a == 3) PRINTHELP(); + a++; + ent.offsets[1]|=DEL_RECURSE; + } + else if (!stricmp(line.gettoken_str(a),"/REBOOTOK")) + { + if (a == 3) PRINTHELP(); + a++; + ent.offsets[1]|=DEL_REBOOT; + } + else PRINTHELP(); } - else if (!stricmp(line.gettoken_str(1),"/REBOOTOK")) - { - if (line.getnumtokens() < 3) PRINTHELP() - a++; - ent.offsets[1]=2; - } - else if (line.gettoken_str(1)[0]=='/') PRINTHELP() + if (a < line.getnumtokens() - 1) PRINTHELP(); ent.offsets[0]=add_string(line.gettoken_str(a)); - SCRIPT_MSG("RMDir: %s%s\"%s\"\n",a==1?"":line.gettoken_str(1),ent.offsets[1]?" ":"",line.gettoken_str(a)); + SCRIPT_MSG("RMDir: "); + if (a>1) + SCRIPT_MSG("%s ",line.gettoken_str(1)); + if (a>2) + SCRIPT_MSG("%s ",line.gettoken_str(2)); + SCRIPT_MSG("\"%s\"\n",line.gettoken_str(a)); DefineInnerLangString(NLF_REMOVE_DIR); + DefineInnerLangString(NLF_DEL_FILE); +#ifdef NSIS_SUPPORT_MOVEONREBOOT + DefineInnerLangString(NLF_DEL_ON_REBOOT); +#endif } return add_entry(&ent); #else//!NSIS_SUPPORT_RMDIR diff --git a/Source/tokens.cpp b/Source/tokens.cpp index 7e9cfa4c..02ea07f7 100644 --- a/Source/tokens.cpp +++ b/Source/tokens.cpp @@ -146,7 +146,7 @@ static tokenType tokenlist[TOK__LAST] = {TOK_REGDLL,"RegDLL",1,1,"dll_path_on_target.dll [entrypoint_symbol]",TP_CODE}, {TOK_RENAME,"Rename",2,1,"[/REBOOTOK] source_file destination_file",TP_CODE}, {TOK_RET,"Return",0,0,"",TP_CODE}, -{TOK_RMDIR,"RMDir",1,1,"[/r|/REBOOTOK] directory_name",TP_CODE}, +{TOK_RMDIR,"RMDir",1,2,"[/r] [/REBOOTOK] directory_name",TP_CODE}, {TOK_SECTION,"Section",0,3,"[/0] [-][un.][section_name] [section index output]",TP_GLOBAL}, {TOK_SECTIONEND,"SectionEnd",0,0,"",TP_SEC}, {TOK_SECTIONIN,"SectionIn",1,-1,"InstTypeIdx [InstTypeIdx [...]]",TP_SEC},