├── resource.h ├── ResetPermission.rc ├── ResetPermission.ico ├── BIN ├── ResetPermission.zip ├── archive │ ├── 1.0.2.zip │ ├── 1.0.3.zip │ ├── 1.0.4.zip │ ├── 1.1.0.zip │ ├── 1.1.3.zip │ ├── 1.1.5.zip │ ├── 1.1.6.zip │ ├── 1.1.7.zip │ └── 1.2.0.zip └── README.txt ├── README.md ├── stdafx.cpp ├── targetver.h ├── .gitattributes ├── stdafx.h ├── ResetPermission.sln ├── ResetPermission.h ├── ResetPermission.vcxproj.filters ├── .gitignore ├── ResetPermission.vcxproj └── ResetPermission.cpp /resource.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lallousx86/ResetPermission/HEAD/resource.h -------------------------------------------------------------------------------- /ResetPermission.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lallousx86/ResetPermission/HEAD/ResetPermission.rc -------------------------------------------------------------------------------- /ResetPermission.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lallousx86/ResetPermission/HEAD/ResetPermission.ico -------------------------------------------------------------------------------- /BIN/ResetPermission.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lallousx86/ResetPermission/HEAD/BIN/ResetPermission.zip -------------------------------------------------------------------------------- /BIN/archive/1.0.2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lallousx86/ResetPermission/HEAD/BIN/archive/1.0.2.zip -------------------------------------------------------------------------------- /BIN/archive/1.0.3.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lallousx86/ResetPermission/HEAD/BIN/archive/1.0.3.zip -------------------------------------------------------------------------------- /BIN/archive/1.0.4.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lallousx86/ResetPermission/HEAD/BIN/archive/1.0.4.zip -------------------------------------------------------------------------------- /BIN/archive/1.1.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lallousx86/ResetPermission/HEAD/BIN/archive/1.1.0.zip -------------------------------------------------------------------------------- /BIN/archive/1.1.3.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lallousx86/ResetPermission/HEAD/BIN/archive/1.1.3.zip -------------------------------------------------------------------------------- /BIN/archive/1.1.5.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lallousx86/ResetPermission/HEAD/BIN/archive/1.1.5.zip -------------------------------------------------------------------------------- /BIN/archive/1.1.6.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lallousx86/ResetPermission/HEAD/BIN/archive/1.1.6.zip -------------------------------------------------------------------------------- /BIN/archive/1.1.7.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lallousx86/ResetPermission/HEAD/BIN/archive/1.1.7.zip -------------------------------------------------------------------------------- /BIN/archive/1.2.0.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lallousx86/ResetPermission/HEAD/BIN/archive/1.2.0.zip -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ResetPermission 2 | Reset NTFS permission graphical tool. 3 | 4 | Please check http://lallouslab.net/2013/08/26/resetting-ntfs-files-permission-in-windows-graphical-utility/ for more information. 5 | 6 | Check the book: "Batchography: The Art of Batch Files Programming" - http://lallouslab.net/2016/05/10/batchography/ 7 | -------------------------------------------------------------------------------- /stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // ResetPermission.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | // Exclude rarely-used stuff from Windows headers 16 | #define WIN32_LEAN_AND_MEAN 17 | #include 18 | 19 | // C RunTime Header Files 20 | #pragma warning(push) 21 | #pragma warning(disable: 4091) 22 | #include 23 | #pragma warning(pop) 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include "resource.h" 30 | 31 | //------------------------------------------------------------------------- 32 | #ifdef _UNICODE 33 | #define stringT std::wstring 34 | #else 35 | #define stringT std::string 36 | #endif 37 | 38 | #include "ResetPermission.h" 39 | -------------------------------------------------------------------------------- /ResetPermission.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ResetPermission", "ResetPermission.vcxproj", "{5AB9D7B8-1B38-4497-AB35-07D37C99AD26}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {5AB9D7B8-1B38-4497-AB35-07D37C99AD26}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {5AB9D7B8-1B38-4497-AB35-07D37C99AD26}.Debug|Win32.Build.0 = Debug|Win32 14 | {5AB9D7B8-1B38-4497-AB35-07D37C99AD26}.Release|Win32.ActiveCfg = Release|Win32 15 | {5AB9D7B8-1B38-4497-AB35-07D37C99AD26}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /ResetPermission.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define MAX_PATH2 (MAX_PATH * 2) 4 | //------------------------------------------------------------------------- 5 | class ResetPermissionDialog 6 | { 7 | HINSTANCE hInstance; 8 | HWND hDlg; 9 | TCHAR AppPath[MAX_PATH2]; 10 | size_t m_nbArgs; 11 | LPCTSTR *m_pArgs; 12 | 13 | bool bRecurse; 14 | bool bResetPerm; 15 | bool bRmHidSys; 16 | bool bTakeOwn; 17 | bool bDontFollowLinks; 18 | 19 | bool BrowseFolder( 20 | HWND hOwner, 21 | LPCTSTR szCaption, 22 | stringT &folderpath); 23 | static void QuotePath(stringT &Path); 24 | 25 | static INT_PTR CALLBACK AboutDlgProc( 26 | HWND hAboutDlg, 27 | UINT message, 28 | WPARAM wParam, 29 | LPARAM lParam); 30 | 31 | void SetCommandWindowText(LPCTSTR Str); 32 | 33 | void UpdateCommandText(); 34 | 35 | bool GetCommandWindowText(stringT &Cmd); 36 | 37 | LPCTSTR GenerateWorkBatchFileName(); 38 | 39 | bool ExecuteCommand(stringT &Cmd); 40 | bool ExecuteWindowCommand(bool bValidatePath); 41 | 42 | void ShowPopupMenu( 43 | int IdMenu, 44 | int IdBtnPos); 45 | 46 | void AddToExplorerContextMenu(bool bAdd); 47 | void BackRestorePermissions(bool bBackup); 48 | 49 | void UpdateCheckboxes(bool bGet); 50 | 51 | LPCTSTR GetArg(size_t idx); 52 | 53 | static INT_PTR CALLBACK s_MainDialogProc( 54 | HWND hWnd, 55 | UINT message, 56 | WPARAM wParam, 57 | LPARAM lParam); 58 | 59 | INT_PTR CALLBACK MainDialogProc( 60 | HWND hWnd, 61 | UINT message, 62 | WPARAM wParam, 63 | LPARAM lParam); 64 | 65 | bool BrowseFileName( 66 | bool bSave, 67 | LPCTSTR Caption, 68 | LPCTSTR Extension, 69 | LPCTSTR DefaultFile, 70 | stringT &out); 71 | 72 | public: 73 | ResetPermissionDialog(); 74 | ~ResetPermissionDialog(); 75 | 76 | static INT_PTR ShowDialog(HINSTANCE hInst); 77 | 78 | bool GetFolderText( 79 | stringT &Folder, 80 | bool bWarnRoot, 81 | bool bAddWildCard, 82 | bool bQuoteIfNeeded); 83 | 84 | void SetFolderText(LPCTSTR Value); 85 | void InitCommand(stringT &cmd); 86 | }; 87 | -------------------------------------------------------------------------------- /BIN/README.txt: -------------------------------------------------------------------------------- 1 | ResetPermission (c) Elias Bachaalany 2 | 3 | Copyright 4 | ========== 5 | This is a free utility. 6 | 7 | If you want to host this package somewhere else please include this copyright file. 8 | 9 | Check out the book: "Batchography: The Art of Batch Files Programming" -- http://lallouslab.net/2016/05/10/batchography/ 10 | 11 | History 12 | ========= 13 | 08/24/2013 - Initial version 14 | 08/30/2013 - Enclose the folder with quotes if it contains at least one space character 15 | 09/17/2013 - Added "Reset files permission" as a optional action 16 | - Added "Reset hidden and system files" 17 | 03/31/2014 - Fixed double backslash when folder is root 18 | 01/08/2014 - Added "Do not follow symbolic links" option 19 | 03/31/2015 - Allow editing of the generated command textbox 20 | - Added "More actions" to add Explorer shell context menu 21 | 11/03/2015 - Added /SKIPSL switch to takeown.exe 22 | 23 | 11/15/2015 - v1.1.3 24 | - Added HELP button to redirect to blog entry 25 | - Added warning when attempting to change permission of a root folder 26 | 27 | 02/13/2016 - v1.1.4 28 | - Minor code changes 29 | - Update the console window title when the commands execute 30 | 31 | 02/28/2016 - v1.1.5 32 | - Refactored code 33 | - Added the Advanced button 34 | - Added Backup/Restore permissions 35 | 36 | 06/14/2016 - v1.1.6 37 | - Made the dialog non-static 38 | - Refactored the code 39 | - bugfix: Add/Remove from the Explorer folder context menu did not work unless a folder was selected. 40 | 41 | 12/19/2016 - v1.1.7 42 | - Attempt to make ResetPermission AntiVirus false-positive free by using 43 | local app data folder instead of temp and by not deleting the temp batch script 44 | 45 | 04/30/2017 - v1.2.0 46 | - Browsing a folder will remember and focus on the previous folder 47 | - Support unicode path 48 | - Warn if the user is trying to reset permissions on a non-supported (or ACL-able) file system 49 | - Fix: command line parsing was erroneous 50 | - Fix: invoking the tool from the shell context menu was failing if the path contained space characters 51 | -------------------------------------------------------------------------------- /ResetPermission.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {572d99de-40b7-4322-93b2-a75b9d1b251c} 18 | 19 | 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | 35 | 36 | Source Files 37 | 38 | 39 | Source Files 40 | 41 | 42 | 43 | 44 | Resource Files 45 | 46 | 47 | 48 | 49 | Resource Files 50 | 51 | 52 | Resource Files 53 | 54 | 55 | 56 | 57 | Archived releases 58 | 59 | 60 | Archived releases 61 | 62 | 63 | Archived releases 64 | 65 | 66 | Archived releases 67 | 68 | 69 | Archived releases 70 | 71 | 72 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | *.opendb 217 | *.vc.db 218 | -------------------------------------------------------------------------------- /ResetPermission.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {5AB9D7B8-1B38-4497-AB35-07D37C99AD26} 15 | Win32Proj 16 | ResetPermission 17 | 8.1 18 | 19 | 20 | 21 | Application 22 | true 23 | v140_xp 24 | Unicode 25 | 26 | 27 | Application 28 | false 29 | v140_xp 30 | true 31 | Unicode 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | true 45 | 46 | 47 | false 48 | 49 | 50 | 51 | Use 52 | Level3 53 | Disabled 54 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) 55 | true 56 | 57 | 58 | Windows 59 | true 60 | 61 | 62 | 63 | 64 | Level3 65 | Use 66 | MaxSpeed 67 | true 68 | true 69 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) 70 | true 71 | MultiThreaded 72 | 73 | 74 | Windows 75 | false 76 | true 77 | true 78 | RequireAdministrator 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | Create 91 | Create 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /ResetPermission.cpp: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------- 2 | Reset files permission (c) Elias Bachaalany 3 | 4 | lallousz-x86@yahoo.com 5 | 6 | 7 | History 8 | --------- 9 | 10 | 08/24/2013 - Initial version 11 | 08/30/2013 - Enclose the folder with quotes if it contains at least one space character 12 | 09/17/2013 - Added "Reset files permission" as a optional action 13 | - Added "Reset hidden and system files" 14 | 03/31/2014 - Fixed double backslash when folder is root 15 | 01/08/2014 - Added "Do not follow symbolic links" option 16 | 03/31/2015 - Allow editing of the generated command textbox 17 | - Added "More actions" to add Explorer shell context menu 18 | 11/03/2015 - Added /SKIPSL switch to takeown.exe 19 | 20 | 11/15/2015 - v1.1.3 21 | - Added HELP button to redirect to blog entry 22 | - Added warning when attempting to change permission of a root folder 23 | 24 | 02/13/2016 - v1.1.4 25 | - Minor code changes 26 | - Update the console window title when the commands execute 27 | 28 | 02/28/2016 - v1.1.5 29 | - Refactored code 30 | - Added the Advanced button 31 | - Added Backup/Restore permissions 32 | 33 | 06/14/2016 - v1.1.6 34 | - Made the dialog non-static 35 | - Refactored the code 36 | - bugfix: Add/Remove from the Explorer folder context menu did not work unless a folder was selected. 37 | Fix: No folder selection is needed for that action. 38 | 39 | 12/19/2016 - v1.1.7 40 | - Attempt to make ResetPermission AntiVirus false-positive free by using 41 | local app data folder instead of temp and by not deleting the temp batch script 42 | 43 | 04/30/2017 - v1.2.0 44 | - Browsing a folder will remember and focus on the previous folder 45 | - Support unicode path 46 | - Warn if the user is trying to reset permissions on a non-supported (or ACL-able) file system 47 | - Fix: command line parsing was erroneous 48 | - Fix: invoking the tool from the shell context menu was failing if the path contained space characters 49 | 50 | -------------------------------------------------------------------------*/ 51 | 52 | #include "stdafx.h" 53 | 54 | //------------------------------------------------------------------------- 55 | static LPCTSTR STR_HELP_URL = _TEXT("http://lallouslab.net/2013/08/26/resetting-ntfs-files-permission-in-windows-graphical-utility/"); 56 | static LPCTSTR STR_SELECT_FOLDER = _TEXT("Please select a folder"); 57 | static LPCTSTR STR_ERROR = _TEXT("Error"); 58 | static LPCTSTR STR_CONFIRMATION = _TEXT("Confirmation"); 59 | static LPCTSTR STR_RESET_FN = _TEXT("resetperm.bat"); 60 | static LPCTSTR STR_HKCR_CTXMENU_BASE = _TEXT("\"HKCR\\Folder\\shell\\Reset Permission"); 61 | static LPCTSTR STR_HKCR_CTXMENU_CMD = _TEXT("\\command"); 62 | static stringT STR_CMD_PAUSE = _TEXT("pause\r\n"); 63 | static LPCTSTR STR_CMD_ICACLS = _TEXT("icacls "); 64 | static LPCTSTR STR_CMD_TAKEOWN = _TEXT("takeown"); 65 | static LPCTSTR STR_CMD_ATTRIB = _TEXT("attrib"); 66 | static LPCTSTR STR_FOLDER_LALLOUSLAB = _TEXT("\\lallouslab"); 67 | static LPCTSTR STR_CMD_REG = _TEXT("reg"); 68 | static stringT STR_NEWLINE = _TEXT("\r\n"); 69 | static stringT STR_NEWLINE2 = STR_NEWLINE + STR_NEWLINE; 70 | 71 | static LPCTSTR STR_WARNING = _TEXT("Warning!"); 72 | 73 | static LPCTSTR STR_FS_NOT_SUPPORTED_WARNING = 74 | _TEXT("The selected path does not support file permissions and thus using this tool might not have any effects!\n\n") 75 | _TEXT("Are you sure you want to continue?"); 76 | 77 | static LPCTSTR STR_ROOT_WARNING = 78 | _TEXT("You are about to change the permission of a root folder!\n") 79 | _TEXT("This is a **DANGEROUS** operation! It is better to choose a specific folder instead!\n\n") 80 | _TEXT("!! If you choose to proceed then you might render your system unstable !!\n\n") 81 | _TEXT("Are you sure you want to continue?"); 82 | 83 | static LPCTSTR STR_ADDREM_CTXMENU_CONFIRM = 84 | _TEXT("You are about to add or remove the ResetPermission tool to/from the Windows Explorer folder context menu!\n") 85 | _TEXT("\n") 86 | _TEXT("Are you sure you want to continue?"); 87 | 88 | static LPCTSTR STR_TITLE_BACKUP_PERMS = 89 | _TEXT("Pick the file you wish to backup the permissions into"); 90 | 91 | static LPCTSTR STR_TITLE_RESTORE_PERMS = 92 | _TEXT("Pick the permissions backup file you wish to restore from"); 93 | 94 | static LPCTSTR STR_CHECK_THE_BATCHOGRAPHY_BOOK = 95 | _TEXT("REM -- Check out the book: Batchography - The Art of Batch Files Programming\r\n") 96 | _TEXT("REM -- http://lallouslab.net/2016/05/10/batchography/\r\n") 97 | _TEXT("\r\n"); 98 | 99 | //------------------------------------------------------------------------- 100 | static bool IsSupportedFileSystem(LPCTSTR Path) 101 | { 102 | do 103 | { 104 | // Get the root path only 105 | TCHAR RootPath[4]; 106 | _tcsncpy_s(RootPath, Path, _countof(RootPath) - 1); 107 | if (_tcslen(RootPath) < 3) 108 | break; 109 | 110 | // Get the file system name 111 | TCHAR FileSysName[MAX_PATH + 1]; 112 | if (!GetVolumeInformation( 113 | RootPath, 114 | nullptr, 115 | 0, 116 | nullptr, 117 | nullptr, 118 | nullptr, 119 | FileSysName, 120 | _countof(FileSysName))) 121 | { 122 | break; 123 | } 124 | 125 | // Compare against supported file systems 126 | return _tcscmp(FileSysName, _TEXT("NTFS")) == 0; 127 | } while (false); 128 | 129 | // If we fail to determinte the FS type, then assume we support it and 130 | // let the user decide what to do 131 | return true; 132 | } 133 | 134 | //------------------------------------------------------------------------- 135 | // The premise behind this function is that if we can convert a UTF-16 136 | // string to both UTF-8 and ASCII and they are equal then no encoding is required 137 | static bool ConvertUtf16ToUtf8( 138 | const wchar_t *utf16_str, 139 | bool *bEncodingRequired, 140 | std::string *utf8_str) 141 | { 142 | size_t utf16_len = wcslen(utf16_str); 143 | 144 | int utf8_size = WideCharToMultiByte( 145 | CP_UTF8, 146 | 0, 147 | utf16_str, 148 | utf16_len, 149 | nullptr, 150 | 0, 151 | nullptr, 152 | nullptr); 153 | if (utf8_size == 0) 154 | return false; 155 | 156 | // If the UTF8 string's length is the same as the the UTF16 length 157 | // then it means we did not need extra bytes to encode some UTF8 characters 158 | // that are not part of the ASCII set 159 | bool bNeedEncoding = utf8_size != utf16_len; 160 | 161 | if (utf8_str != nullptr) 162 | { 163 | std::string buf_utf8; 164 | buf_utf8.resize(utf8_size); 165 | 166 | utf8_size = WideCharToMultiByte( 167 | CP_UTF8, 168 | 0, 169 | utf16_str, 170 | utf16_len, 171 | &buf_utf8[0], 172 | buf_utf8.size(), 173 | nullptr, 174 | nullptr); 175 | if (utf8_size == 0) 176 | return false; 177 | 178 | *utf8_str = buf_utf8; 179 | } 180 | if (bEncodingRequired != nullptr) 181 | *bEncodingRequired = bNeedEncoding; 182 | 183 | return true; 184 | } 185 | 186 | //------------------------------------------------------------------------- 187 | // BrowseFolder helper callback that sets the default path 188 | // https://www.arclab.com/en/kb/cppmfc/select-folder-shbrowseforfolder.html 189 | static INT CALLBACK BrowseFolderSetDefaultPathCallback( 190 | HWND hwnd, 191 | UINT uMsg, 192 | LPARAM lp, 193 | LPARAM pData) 194 | { 195 | if (uMsg == BFFM_INITIALIZED) 196 | SendMessage(hwnd, BFFM_SETSELECTION, TRUE, pData); 197 | 198 | return 0; 199 | } 200 | 201 | //------------------------------------------------------------------------- 202 | bool ResetPermissionDialog::BrowseFolder( 203 | HWND hOwner, 204 | LPCTSTR szCaption, 205 | stringT &folderpath) 206 | { 207 | BROWSEINFO bi; 208 | memset(&bi, 0, sizeof(bi)); 209 | 210 | bi.ulFlags = BIF_EDITBOX | BIF_VALIDATE | BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE; 211 | bi.hwndOwner = hOwner; 212 | bi.lpszTitle = szCaption; 213 | stringT CurFolder; 214 | if (GetFolderText(CurFolder, false, false, false)) 215 | { 216 | bi.lParam = (LPARAM)CurFolder.c_str(); 217 | bi.lpfn = BrowseFolderSetDefaultPathCallback; 218 | } 219 | LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi); 220 | 221 | if (pIDL == NULL) 222 | return false; 223 | 224 | TCHAR buffer[_MAX_PATH] = { 0 }; 225 | bool bOk = ::SHGetPathFromIDList(pIDL, buffer) != 0; 226 | 227 | if (bOk) 228 | folderpath = buffer; 229 | 230 | // free the item id list 231 | CoTaskMemFree(pIDL); 232 | 233 | return bOk; 234 | } 235 | 236 | //------------------------------------------------------------------------- 237 | void ResetPermissionDialog::QuotePath(stringT &Path) 238 | { 239 | if (Path.find(_T(' ')) != stringT::npos) 240 | Path = _TEXT("\"") + Path + _TEXT("\""); 241 | } 242 | 243 | //------------------------------------------------------------------------- 244 | bool ResetPermissionDialog::BrowseFileName( 245 | bool bSave, 246 | LPCTSTR Caption, 247 | LPCTSTR Extension, 248 | LPCTSTR DefaultFile, 249 | stringT &out) 250 | { 251 | TCHAR FileName[MAX_PATH2] = { 0 }; 252 | OPENFILENAME ofn = { 0 }; 253 | ofn.lStructSize = sizeof(ofn); 254 | ofn.lpstrDefExt = Extension; 255 | ofn.hwndOwner = hDlg; 256 | ofn.lpstrFile = FileName; 257 | ofn.nMaxFile = _countof(FileName); 258 | ofn.lpstrTitle = Caption; 259 | ofn.lpstrFilter = TEXT("All files\0*.*\0\0"); 260 | 261 | if (bSave) 262 | ofn.Flags = OFN_OVERWRITEPROMPT; 263 | else 264 | ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; 265 | 266 | bool bOk = (bSave ? GetSaveFileName : GetOpenFileName)(&ofn) == TRUE; 267 | 268 | if (bOk) 269 | out = ofn.lpstrFile; 270 | 271 | return bOk; 272 | } 273 | 274 | //------------------------------------------------------------------------- 275 | void ResetPermissionDialog::ShowPopupMenu( 276 | int IdMenu, 277 | int IdBtnPos) 278 | { 279 | HMENU hMenu = LoadMenu( 280 | hInstance, 281 | MAKEINTRESOURCE(IdMenu)); 282 | 283 | HWND hBtn = GetDlgItem(hDlg, IdBtnPos); 284 | HMENU hSubMenu = GetSubMenu(hMenu, 0); 285 | RECT rect; 286 | GetClientRect(hBtn, &rect); 287 | 288 | POINT pt = { rect.left, rect.top }; 289 | ClientToScreen(hBtn, &pt); 290 | 291 | TrackPopupMenu( 292 | hSubMenu, 293 | TPM_LEFTALIGN | TPM_LEFTBUTTON, 294 | pt.x, 295 | pt.y + 25, 296 | 0, 297 | hDlg, NULL); 298 | 299 | DestroyMenu(hMenu); 300 | } 301 | 302 | //------------------------------------------------------------------------- 303 | void ResetPermissionDialog::UpdateCheckboxes(bool bGet) 304 | { 305 | if (bGet) 306 | { 307 | bRecurse = SendDlgItemMessage( 308 | hDlg, 309 | IDCHK_RECURSE, 310 | BM_GETCHECK, 311 | 0, 312 | 0) == BST_CHECKED; 313 | 314 | bResetPerm = SendDlgItemMessage( 315 | hDlg, 316 | IDCHK_RESETPERM, 317 | BM_GETCHECK, 318 | 0, 319 | 0) == BST_CHECKED; 320 | 321 | bRmHidSys = SendDlgItemMessage( 322 | hDlg, 323 | IDCHK_RM_HS, 324 | BM_GETCHECK, 325 | 0, 326 | 0) == BST_CHECKED; 327 | 328 | bTakeOwn = SendDlgItemMessage( 329 | hDlg, 330 | IDCHK_TAKEOWN, 331 | BM_GETCHECK, 332 | 0, 333 | 0) == BST_CHECKED; 334 | 335 | bDontFollowLinks = SendDlgItemMessage( 336 | hDlg, 337 | IDCHK_DONTFOLLOWLINKS, 338 | BM_GETCHECK, 339 | 0, 340 | 0) == BST_CHECKED; 341 | } 342 | else 343 | { 344 | SendDlgItemMessage( 345 | hDlg, 346 | IDCHK_RECURSE, 347 | BM_SETCHECK, 348 | bRecurse ? BST_CHECKED : BST_UNCHECKED, 349 | 0); 350 | 351 | SendDlgItemMessage( 352 | hDlg, 353 | IDCHK_RESETPERM, 354 | BM_SETCHECK, 355 | bResetPerm ? BST_CHECKED : BST_UNCHECKED, 356 | 0); 357 | 358 | SendDlgItemMessage( 359 | hDlg, 360 | IDCHK_RM_HS, 361 | BM_SETCHECK, 362 | bRmHidSys ? BST_CHECKED : BST_UNCHECKED, 363 | 0); 364 | 365 | SendDlgItemMessage( 366 | hDlg, 367 | IDCHK_TAKEOWN, 368 | BM_SETCHECK, 369 | bTakeOwn ? BST_CHECKED : BST_UNCHECKED, 370 | 0); 371 | 372 | SendDlgItemMessage( 373 | hDlg, 374 | IDCHK_DONTFOLLOWLINKS, 375 | BM_SETCHECK, 376 | bDontFollowLinks ? BST_CHECKED : BST_UNCHECKED, 377 | 0); 378 | } 379 | } 380 | 381 | //------------------------------------------------------------------------- 382 | LPCTSTR ResetPermissionDialog::GetArg(size_t idx) 383 | { 384 | return idx >= m_nbArgs ? nullptr : m_pArgs[idx]; 385 | } 386 | 387 | //------------------------------------------------------------------------- 388 | bool ResetPermissionDialog::GetCommandWindowText(stringT &Cmd) 389 | { 390 | HWND hwndCtrl = GetDlgItem(hDlg, IDTXT_COMMAND); 391 | if (hwndCtrl == NULL) 392 | return false; 393 | 394 | int len = GetWindowTextLength(hwndCtrl); 395 | if (GetLastError() != NO_ERROR) 396 | return false; 397 | 398 | TCHAR *szCmd = new TCHAR[len + 1]; 399 | if (szCmd == NULL) 400 | return false; 401 | 402 | GetWindowText(hwndCtrl, szCmd, len); 403 | bool bOk = GetLastError() == NO_ERROR; 404 | 405 | Cmd = szCmd; 406 | delete[] szCmd; 407 | 408 | return bOk; 409 | } 410 | 411 | //------------------------------------------------------------------------- 412 | void ResetPermissionDialog::SetCommandWindowText(LPCTSTR Str) 413 | { 414 | SetDlgItemText(hDlg, IDTXT_COMMAND, Str); 415 | } 416 | 417 | //------------------------------------------------------------------------- 418 | bool ResetPermissionDialog::GetFolderText( 419 | stringT &Folder, 420 | bool bWarnRoot, 421 | bool bAddWildCard, 422 | bool bQuoteIfNeeded) 423 | { 424 | TCHAR Path[MAX_PATH * 4]; 425 | UINT len = GetDlgItemText( 426 | hDlg, 427 | IDTXT_FOLDER, 428 | Path, 429 | _countof(Path)); 430 | 431 | if (len == 0) 432 | return false; 433 | 434 | if (bWarnRoot) 435 | { 436 | // Warn if resetting root permissions 437 | if (_tcslen(Path) == 3 && Path[1] == _TCHAR(':') && Path[2] == _TCHAR('\\')) 438 | { 439 | if (MessageBox(hDlg, STR_ROOT_WARNING, STR_WARNING, MB_YESNO | MB_ICONWARNING) == IDNO) 440 | return false; 441 | } 442 | 443 | // Warn if tool is used on unsupported file system 444 | if (!IsSupportedFileSystem(Path)) 445 | { 446 | if (MessageBox(hDlg, STR_FS_NOT_SUPPORTED_WARNING, STR_WARNING, MB_YESNO | MB_ICONWARNING) == IDNO) 447 | return false; 448 | } 449 | } 450 | 451 | Folder = Path; 452 | 453 | // Add the wildcard mask 454 | if (bAddWildCard) 455 | { 456 | if (*Folder.rbegin() != TCHAR('\\')) 457 | Folder += _TEXT("\\"); 458 | 459 | Folder += _TEXT("*"); 460 | } 461 | 462 | // Quote the folder if needed 463 | if (bQuoteIfNeeded) 464 | QuotePath(Folder); 465 | 466 | return true; 467 | } 468 | 469 | //------------------------------------------------------------------------- 470 | void ResetPermissionDialog::SetFolderText(LPCTSTR Value) 471 | { 472 | SetDlgItemText(hDlg, IDTXT_FOLDER, Value); 473 | } 474 | 475 | //------------------------------------------------------------------------- 476 | void ResetPermissionDialog::InitCommand(stringT &cmd) 477 | { 478 | cmd += STR_CHECK_THE_BATCHOGRAPHY_BOOK; 479 | 480 | LPCTSTR TempScript = GenerateWorkBatchFileName(); 481 | if (TempScript != nullptr) 482 | { 483 | cmd += _TEXT("REM -- Temp script location: "); 484 | cmd += TempScript + STR_NEWLINE2; 485 | } 486 | } 487 | 488 | //------------------------------------------------------------------------- 489 | // Update the command text 490 | void ResetPermissionDialog::UpdateCommandText() 491 | { 492 | UpdateCheckboxes(true); 493 | 494 | stringT folder; 495 | if (GetFolderText(folder, false, true, true) == 0) 496 | return; 497 | 498 | stringT cmd; 499 | InitCommand(cmd); 500 | 501 | // Form takeown.exe command 502 | if (bTakeOwn) 503 | { 504 | // Update the command prompt's title 505 | cmd += _TEXT("TITLE taking ownership of folder: ") + folder + STR_NEWLINE; 506 | 507 | cmd += STR_CMD_TAKEOWN; 508 | if (bRecurse) 509 | cmd += _TEXT(" /r "); 510 | 511 | if (bDontFollowLinks) 512 | cmd += _TEXT(" /SKIPSL "); 513 | 514 | cmd += _TEXT(" /f ") + folder + STR_NEWLINE2; 515 | } 516 | 517 | // 518 | // Form icacls.exe command 519 | // 520 | if (bResetPerm) 521 | { 522 | // Update the command prompt's title 523 | cmd += _TEXT("TITLE Taking ownership of folder: ") + folder + STR_NEWLINE; 524 | 525 | cmd += STR_CMD_ICACLS + folder; 526 | if (bRecurse) 527 | cmd += _TEXT(" /T "); 528 | 529 | if (bDontFollowLinks) 530 | cmd += _TEXT(" /L "); 531 | 532 | cmd += _TEXT(" /Q /C /RESET") + STR_NEWLINE2; 533 | } 534 | 535 | // Form attribute.exe command 536 | if (bRmHidSys) 537 | { 538 | // Update the command prompt's title 539 | cmd += _TEXT("TITLE Changing files attributes in folder: ") + folder + STR_NEWLINE; 540 | 541 | cmd += STR_CMD_ATTRIB; 542 | if (bRecurse) 543 | cmd += _TEXT(" /s "); 544 | 545 | cmd += _TEXT(" -h -s ") + folder + STR_NEWLINE2; 546 | } 547 | 548 | // Always add a pause and a new line 549 | cmd += STR_CMD_PAUSE; 550 | cmd += STR_NEWLINE; 551 | 552 | // Update the 553 | SetCommandWindowText(cmd.c_str()); 554 | } 555 | 556 | //------------------------------------------------------------------------- 557 | LPCTSTR ResetPermissionDialog::GenerateWorkBatchFileName() 558 | { 559 | // Make temp file name 560 | static TCHAR CmdFileName[MAX_PATH2] = { 0 }; 561 | 562 | // Compute if it was not already computed 563 | if (CmdFileName[0] == _TCHAR('\0')) 564 | { 565 | // Attempt to use local user AppData folder 566 | if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, CmdFileName))) 567 | { 568 | _tcsncat_s(CmdFileName, STR_FOLDER_LALLOUSLAB, _countof(CmdFileName)); 569 | 570 | // Work directory note found? Create it! 571 | if ((GetFileAttributes(CmdFileName) == INVALID_FILE_ATTRIBUTES) 572 | && !CreateDirectory(CmdFileName, nullptr)) 573 | { 574 | // Failed to create the folder. Discard the local app folder and use temp folder 575 | CmdFileName[0] = _T('\0'); 576 | } 577 | } 578 | 579 | // Revert to temp folder if this fails 580 | if (CmdFileName[0] == _TCHAR('\0')) 581 | { 582 | // Get temp path via the API 583 | if (GetTempPath(_countof(CmdFileName), CmdFileName) == 0) 584 | { 585 | // Attempt to get it again via the environment variable 586 | if (GetEnvironmentVariable(_TEXT("TEMP"), CmdFileName, _countof(CmdFileName)) == 0) 587 | return nullptr; 588 | } 589 | } 590 | 591 | if (CmdFileName[_tcslen(CmdFileName) - 1] != TCHAR('\\')) 592 | _tcsncat_s(CmdFileName, _TEXT("\\"), _countof(CmdFileName)); 593 | 594 | _tcsncat_s(CmdFileName, STR_RESET_FN, _countof(CmdFileName)); 595 | } 596 | 597 | return CmdFileName; 598 | } 599 | 600 | //------------------------------------------------------------------------- 601 | void ResetPermissionDialog::AddToExplorerContextMenu(bool bAdd) 602 | { 603 | stringT cmd; 604 | InitCommand(cmd); 605 | 606 | cmd += STR_CMD_REG; 607 | 608 | if (bAdd) 609 | cmd += TEXT(" ADD "); 610 | else 611 | cmd += TEXT(" DELETE "); 612 | 613 | cmd += STR_HKCR_CTXMENU_BASE; 614 | 615 | if (bAdd) 616 | cmd += STR_HKCR_CTXMENU_CMD; 617 | 618 | cmd += TEXT("\" /f "); 619 | 620 | if (bAdd) 621 | { 622 | cmd += TEXT("/ve /t REG_SZ /d \"\\\""); 623 | cmd += AppPath; 624 | cmd += TEXT("\\\" \"\\\"%%1\"\\\"\""); 625 | } 626 | 627 | cmd += STR_NEWLINE; 628 | 629 | cmd += STR_CMD_PAUSE; 630 | 631 | // Confirm 632 | if (MessageBox(hDlg, STR_ADDREM_CTXMENU_CONFIRM, STR_CONFIRMATION, MB_YESNO | MB_ICONQUESTION) == IDNO) 633 | return; 634 | 635 | // Execute the command 636 | ExecuteCommand(cmd); 637 | } 638 | 639 | //------------------------------------------------------------------------- 640 | void ResetPermissionDialog::BackRestorePermissions(bool bBackup) 641 | { 642 | // Browse for permission backup file 643 | stringT PermsFile; 644 | if (!ResetPermissionDialog::BrowseFileName( 645 | bBackup, 646 | bBackup ? STR_TITLE_BACKUP_PERMS : STR_TITLE_RESTORE_PERMS, 647 | TEXT("permissions.txt"), 648 | TEXT("*.txt"), 649 | PermsFile)) 650 | { 651 | return; 652 | } 653 | 654 | QuotePath(PermsFile); 655 | 656 | // Get the folder location 657 | stringT folder; 658 | if (GetFolderText(folder, false, bBackup ? true : false, true) == 0) 659 | return; 660 | 661 | stringT cmd; 662 | InitCommand(cmd); 663 | 664 | // Update the command prompt's title 665 | if (bBackup) 666 | { 667 | cmd += _TEXT("TITLE Backing up permissions of folder: ") + folder + STR_NEWLINE; 668 | 669 | cmd += STR_CMD_ICACLS + folder + _TEXT(" /save ") + PermsFile; 670 | if (bRecurse) 671 | cmd += _TEXT(" /T "); 672 | } 673 | else 674 | { 675 | cmd += _TEXT("TITLE Restoring permissions of folder: ") + folder + STR_NEWLINE; 676 | 677 | cmd += STR_CMD_ICACLS + folder + _TEXT(" /restore ") + PermsFile; 678 | } 679 | 680 | cmd += STR_NEWLINE2 + STR_CMD_PAUSE; 681 | 682 | SetCommandWindowText(cmd.c_str()); 683 | } 684 | 685 | //------------------------------------------------------------------------- 686 | bool ResetPermissionDialog::ExecuteCommand(stringT &Cmd) 687 | { 688 | std::string Utf8Cmd; 689 | #ifdef _UNICODE 690 | std::string utf8_str; 691 | bool bEncodingRequired; 692 | if (!ConvertUtf16ToUtf8(Cmd.c_str(), &bEncodingRequired, &utf8_str)) 693 | { 694 | MessageBox( 695 | hDlg, 696 | _TEXT("Failed to convert input command to UTF-8"), 697 | TEXT("Error"), 698 | MB_OK | MB_ICONERROR); 699 | 700 | return false; 701 | } 702 | 703 | if (bEncodingRequired) 704 | { 705 | // 65001 = utf-8 # ref: https://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx 706 | Utf8Cmd = "CHCP 65001\r\n\r\n" + utf8_str; 707 | } 708 | else 709 | { 710 | Utf8Cmd = utf8_str; 711 | } 712 | #else 713 | Utf8Cmd = Cmd; 714 | #endif 715 | // Overwrite/create the previous temp Batch file 716 | LPCTSTR CmdFileName = GenerateWorkBatchFileName(); 717 | 718 | // Write the temp Batch file (as binary) 719 | FILE *fp; 720 | if (_tfopen_s(&fp, CmdFileName, _TEXT("wb")) != 0) 721 | { 722 | stringT err_msg = TEXT("Failed to write batch file to: "); 723 | err_msg += CmdFileName; 724 | 725 | MessageBox( 726 | hDlg, 727 | err_msg.c_str(), 728 | TEXT("Error"), 729 | MB_OK | MB_ICONERROR); 730 | 731 | return false; 732 | } 733 | 734 | fwrite(&Utf8Cmd[0], 1, Utf8Cmd.size(), fp); 735 | fclose(fp); 736 | 737 | // Execute the temp batch file 738 | return SUCCEEDED( 739 | ShellExecute( 740 | hDlg, 741 | _TEXT("open"), 742 | CmdFileName, 743 | NULL, 744 | NULL, 745 | SW_SHOW)); 746 | } 747 | 748 | //------------------------------------------------------------------------- 749 | // Execute the command typed in the command textbox 750 | bool ResetPermissionDialog::ExecuteWindowCommand(bool bValidateFolder) 751 | { 752 | // Warn if this is a root folder 753 | if (bValidateFolder) 754 | { 755 | stringT Path; 756 | if (!GetFolderText(Path, true, false, false)) 757 | return false; 758 | } 759 | 760 | // Get the window command 761 | stringT Cmd; 762 | if (!GetCommandWindowText(Cmd)) 763 | { 764 | MessageBox( 765 | hDlg, 766 | TEXT("Failed to get command text"), 767 | TEXT("Error"), 768 | MB_OK | MB_ICONERROR); 769 | return false; 770 | } 771 | 772 | // Execute the command 773 | if (!ExecuteCommand(Cmd)) 774 | { 775 | MessageBox( 776 | hDlg, 777 | TEXT("Failed to execute get command text"), 778 | TEXT("Error"), 779 | MB_OK | MB_ICONERROR); 780 | return false; 781 | } 782 | return true; 783 | } 784 | 785 | //------------------------------------------------------------------------- 786 | INT_PTR CALLBACK ResetPermissionDialog::AboutDlgProc( 787 | HWND hAboutDlg, 788 | UINT message, 789 | WPARAM wParam, 790 | LPARAM lParam) 791 | { 792 | if (message == WM_INITDIALOG) 793 | { 794 | return TRUE; 795 | } 796 | else if (message == WM_COMMAND && LOWORD(wParam) == IDOK) 797 | { 798 | EndDialog(hAboutDlg, 0); 799 | return TRUE; 800 | } 801 | return FALSE; 802 | } 803 | 804 | //------------------------------------------------------------------------- 805 | INT_PTR CALLBACK ResetPermissionDialog::s_MainDialogProc( 806 | HWND hWnd, 807 | UINT message, 808 | WPARAM wParam, 809 | LPARAM lParam) 810 | { 811 | ResetPermissionDialog *Dlg; 812 | 813 | // Dialog initialized? Let's setup / remember the instance pointer 814 | if (message == WM_INITDIALOG) 815 | { 816 | // Get the passed instance 817 | Dlg = (ResetPermissionDialog *)lParam; 818 | 819 | // Associate the dialog instance with the window's user data 820 | SetWindowLongPtr( 821 | hWnd, 822 | GWLP_USERDATA, 823 | LONG_PTR(Dlg)); 824 | } 825 | // Extract the dialog instance from the window's data 826 | else 827 | { 828 | Dlg = (ResetPermissionDialog *)GetWindowLongPtr(hWnd, GWLP_USERDATA); 829 | } 830 | 831 | // Dispatch the message to this specific dialog instance 832 | INT_PTR Ret = Dlg == nullptr ? FALSE : Dlg->MainDialogProc(hWnd, message, wParam, lParam); 833 | 834 | if (message == WM_DESTROY) 835 | { 836 | // Delete the dialog instance 837 | delete Dlg; 838 | } 839 | 840 | return Ret; 841 | } 842 | 843 | //------------------------------------------------------------------------- 844 | INT_PTR CALLBACK ResetPermissionDialog::MainDialogProc( 845 | HWND hWnd, 846 | UINT message, 847 | WPARAM wParam, 848 | LPARAM lParam) 849 | { 850 | switch (message) 851 | { 852 | case WM_INITDIALOG: 853 | { 854 | hDlg = hWnd; 855 | 856 | // Set the initial states/configuration 857 | bRecurse = true; 858 | bResetPerm = true; 859 | bRmHidSys = false; 860 | bTakeOwn = false; 861 | bDontFollowLinks = true; 862 | 863 | UpdateCheckboxes(false); 864 | 865 | HICON hIcon = LoadIcon( 866 | hInstance, 867 | MAKEINTRESOURCE(IDI_SMALL)); 868 | 869 | SendMessage( 870 | hDlg, 871 | WM_SETICON, 872 | ICON_BIG, 873 | (LPARAM)hIcon); 874 | 875 | LPCTSTR Arg = GetArg(1); 876 | 877 | #ifdef _DEBUG 878 | if (Arg == NULL) 879 | Arg = _TEXT("C:\\Temp\\perm"); 880 | 881 | // Enable editing for the folder text editbox in debug mode 882 | SendDlgItemMessage(hDlg, IDTXT_FOLDER, EM_SETREADONLY, FALSE, 0); 883 | #endif 884 | 885 | if (Arg != NULL) 886 | { 887 | SetFolderText(Arg); 888 | UpdateCommandText(); 889 | } 890 | 891 | return TRUE; 892 | } 893 | 894 | case WM_MENUCOMMAND: 895 | break; 896 | 897 | case WM_COMMAND: 898 | { 899 | UINT wmId = LOWORD(wParam); 900 | UINT wmEvent = HIWORD(wParam); 901 | #ifdef _DEBUG 902 | TCHAR b[1024]; 903 | _sntprintf_s( 904 | b, 905 | _countof(b), 906 | _TEXT("WM_COMMAND: wmParam=%08X lParam=%08X | ID=%04X Event=%04X\n"), 907 | wParam, 908 | lParam, 909 | wmId, 910 | wmEvent); 911 | OutputDebugString(b); 912 | 913 | // Reflect the folder text changes when the control is editable 914 | if (wmId == IDTXT_FOLDER && wmEvent == EN_CHANGE) 915 | UpdateCommandText(); 916 | #endif 917 | switch (wmId) 918 | { 919 | // 920 | // Handle checkboxes 921 | // 922 | case IDCHK_RECURSE: 923 | case IDCHK_DONTFOLLOWLINKS: 924 | case IDCHK_TAKEOWN: 925 | case IDCHK_RESETPERM: 926 | case IDCHK_RM_HS: 927 | { 928 | // Reforumulate the command text on each option change 929 | if (wmEvent == BN_CLICKED) 930 | { 931 | UpdateCommandText(); 932 | return TRUE; 933 | } 934 | break; 935 | } 936 | 937 | // 938 | // Handle context menu 939 | // 940 | case IDM_ADDTOEXPLORERFOLDERCONTEXTMENU: 941 | case IDM_REMOVEFROMEXPLORERFOLDERCONTEXTMENU: 942 | AddToExplorerContextMenu(wmId == IDM_ADDTOEXPLORERFOLDERCONTEXTMENU); 943 | break; 944 | 945 | case IDM_BACKUPPERMSCONTEXTMENU: 946 | case IDM_RESTOREPERMSCONTEXTMENU: 947 | BackRestorePermissions(wmId == IDM_BACKUPPERMSCONTEXTMENU); 948 | break; 949 | 950 | // 951 | // About box 952 | // 953 | case IDBTN_ABOUT: 954 | { 955 | DialogBox( 956 | hInstance, 957 | MAKEINTRESOURCE(IDD_ABOUTBOX), 958 | hDlg, 959 | AboutDlgProc); 960 | 961 | return TRUE; 962 | } 963 | 964 | // 965 | // Choose folder 966 | // 967 | case IDBTN_CHOOSE_FOLDER: 968 | { 969 | stringT Folder; 970 | if (BrowseFolder(hDlg, STR_SELECT_FOLDER, Folder)) 971 | { 972 | SetFolderText(Folder.c_str()); 973 | UpdateCommandText(); 974 | } 975 | return TRUE; 976 | } 977 | 978 | // 979 | // Trigger the "Advanced" menu 980 | // 981 | case IDBTN_ADVANCED: 982 | { 983 | ShowPopupMenu(IDR_ADVANCED_MENU, IDBTN_ADVANCED); 984 | return TRUE; 985 | } 986 | 987 | // 988 | // GO button 989 | // 990 | case IDOK: 991 | { 992 | // Validate the input folder and execute the command 993 | ExecuteWindowCommand(true); 994 | return TRUE; 995 | } 996 | 997 | // HELP button 998 | case IDBTN_HELP: 999 | { 1000 | ShellExecute( 1001 | hDlg, 1002 | _TEXT("open"), 1003 | STR_HELP_URL, 1004 | nullptr, 1005 | nullptr, 1006 | SW_SHOW); 1007 | 1008 | return TRUE; 1009 | } 1010 | } // switch(wmId) 1011 | break; 1012 | } // case WM_COMMAND 1013 | 1014 | // Close dialog 1015 | case WM_CLOSE: 1016 | EndDialog(hDlg, IDOK); 1017 | return TRUE; 1018 | } 1019 | return FALSE; 1020 | } 1021 | 1022 | //------------------------------------------------------------------------- 1023 | ResetPermissionDialog::ResetPermissionDialog() : m_pArgs(nullptr), m_nbArgs(0) 1024 | { 1025 | int nArgs; 1026 | LPWSTR *szArgList = CommandLineToArgvW(GetCommandLineW(), &nArgs); 1027 | if (szArgList != nullptr) 1028 | { 1029 | m_nbArgs = nArgs; 1030 | m_pArgs = new LPCTSTR[nArgs]; 1031 | for (auto i = 0; i < nArgs; ++i) 1032 | { 1033 | #ifdef _UNICODE 1034 | m_pArgs[i] = _wcsdup(szArgList[i]); 1035 | #else 1036 | std::string utf8; 1037 | if (!ConvertUtf16ToUtf8(szArgList[i], nullptr, &utf8)) 1038 | utf8 = ""; 1039 | m_pArgs[i] = _strdup(utf8.c_str()); 1040 | #endif 1041 | } 1042 | // Free argument list 1043 | LocalFree(szArgList); 1044 | } 1045 | } 1046 | 1047 | //------------------------------------------------------------------------- 1048 | ResetPermissionDialog::~ResetPermissionDialog() 1049 | { 1050 | for (size_t i = 0; i < m_nbArgs; ++i) 1051 | delete m_pArgs[i]; 1052 | 1053 | delete[] m_pArgs; 1054 | } 1055 | 1056 | //------------------------------------------------------------------------- 1057 | INT_PTR ResetPermissionDialog::ShowDialog(HINSTANCE hInst) 1058 | { 1059 | // Create new dialog instance 1060 | ResetPermissionDialog *Dlg = new ResetPermissionDialog(); 1061 | 1062 | // Get current program's full path 1063 | GetModuleFileName( 1064 | NULL, 1065 | Dlg->AppPath, 1066 | _countof(Dlg->AppPath)); 1067 | 1068 | Dlg->hInstance = hInst; 1069 | return DialogBoxParam( 1070 | hInst, 1071 | MAKEINTRESOURCE(IDD_RESETPERMS), 1072 | NULL, 1073 | s_MainDialogProc, 1074 | LPARAM(Dlg)); 1075 | } 1076 | 1077 | //------------------------------------------------------------------------- 1078 | int APIENTRY _tWinMain( 1079 | HINSTANCE hInstance, 1080 | HINSTANCE hPrevInstance, 1081 | LPTSTR lpCmdLine, 1082 | int nCmdShow) 1083 | { 1084 | ::OleInitialize(NULL); 1085 | return (int)ResetPermissionDialog::ShowDialog(hInstance); 1086 | } --------------------------------------------------------------------------------