1 /** 2 * コマンドに関連した処理 3 * 4 * Author: $(LINK2 https://twitter.com/dokutoku3, dokutoku) 5 * License: $(LINK2 https://creativecommons.org/publicdomain/zero/1.0/, CC0 1.0 Universal) 6 */ 7 module remove_shortcut_arrow.command; 8 9 10 version (Windows) { 11 private static import core.sys.windows.winbase; 12 private static import core.sys.windows.windef; 13 private static import core.sys.windows.winnt; 14 15 extern (Windows) 16 nothrow @nogc 17 core.sys.windows.windef.BOOL Wow64DisableWow64FsRedirection(core.sys.windows.winnt.PVOID*); 18 19 extern (Windows) 20 nothrow @nogc 21 core.sys.windows.windef.BOOL Wow64RevertWow64FsRedirection(core.sys.windows.winnt.PVOID); 22 } 23 24 private static import remove_shortcut_arrow.path; 25 26 /** 27 * PATHを除いたレジストリの追加コマンド。 28 */ 29 public enum REG_PRE_ADD_COMMAND = "reg.exe add \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Icons\" /f /v 29 /t REG_EXPAND_SZ /reg:64 /d \0"w; 30 31 /** 32 * レジストリから削除するコマンド 33 */ 34 public enum REG_DELETE_COMMAND = "reg.exe delete \"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Icons\" /f /v 29 /reg:64\0"w; 35 36 version (Windows) { 37 static assert(core.sys.windows.windef.MAX_PATH == 260); 38 } 39 40 public enum REG_ADD_COMMAND_BUFFER_LENGTH = .REG_PRE_ADD_COMMAND.length + ("\"\"".length * 2) + 260 + remove_shortcut_arrow.path.PATH_LIMIT; 41 public enum REG_DELETE_COMMAND_BUFFER_LENGTH = .REG_DELETE_COMMAND.length + "\"\"".length + 260; 42 43 /** 44 * 実行マシン上で有効な、ショートカット矢印を削除するためのコマンドをバッファにコピーする。 45 * 46 * Params: 47 * command_buffer = コマンドのバッファ 48 * buffer_size = コマンドのバッファサイズ 49 * ico_path = icoファイルの絶対パス 50 */ 51 version (Windows) 52 extern (C) 53 nothrow @nogc 54 public bool copy_remove_windows_shortcut_arrow_command(scope wchar* command_buffer, size_t buffer_size, const core.sys.windows.winnt.LPCWSTR ico_path) 55 56 do 57 { 58 if (command_buffer == null) { 59 return false; 60 } 61 62 if (buffer_size < .REG_ADD_COMMAND_BUFFER_LENGTH) { 63 if (buffer_size != 0) { 64 command_buffer[0] = '\0'; 65 } 66 67 return false; 68 } 69 70 if (ico_path == null) { 71 return false; 72 } 73 74 if (core.sys.windows.winbase.lstrlenW(ico_path) >= remove_shortcut_arrow.path.PATH_LIMIT) { 75 return false; 76 } 77 78 wchar[core.sys.windows.windef.MAX_PATH] system_directory = void; 79 80 command_buffer[0] = '"'; 81 command_buffer[1] = '\0'; 82 83 if (remove_shortcut_arrow.path.get_system32_path(system_directory) == 0) { 84 return false; 85 } 86 87 core.sys.windows.winbase.lstrcatW(command_buffer, &(system_directory[0])); 88 core.sys.windows.winbase.lstrcatW(command_buffer, &("\\System32\0"w[0])); 89 90 version (none) { 91 // reg:64オプションを削除しない場合(Vistaでは動作しない) 92 93 static assert(.REG_PRE_ADD_COMMAND[0 .. 8] == "reg.exe "w); 94 static assert(.REG_PRE_ADD_COMMAND[($ - " /d \0"w.length) .. $] == " /d \0"w); 95 enum TEMP = "\\reg.exe\" "w ~ .REG_PRE_ADD_COMMAND[8 .. ($ - " \0"w.length)] ~ " \"" ~ "\0"; 96 } else { 97 // reg:64オプションを削除する場合 98 99 static assert(.REG_PRE_ADD_COMMAND[0 .. 8] == "reg.exe "w); 100 static assert(.REG_PRE_ADD_COMMAND[($ - " /reg:64 /d \0"w.length) .. $] == " /reg:64 /d \0"w); 101 enum TEMP = "\\reg.exe\" "w ~ .REG_PRE_ADD_COMMAND[8 .. ($ - " /reg:64 /d \0"w.length)] ~ " /d \"" ~ "\0"; 102 } 103 104 core.sys.windows.winbase.lstrcatW(command_buffer, &(TEMP[0])); 105 core.sys.windows.winbase.lstrcatW(command_buffer, &(ico_path[0])); 106 int length = core.sys.windows.winbase.lstrlenW(command_buffer); 107 command_buffer[length] = '"'; 108 command_buffer[length + 1] = '\0'; 109 110 return true; 111 } 112 113 /** 114 * 実行マシン上で有効な、削除したショートカット矢印を元に戻すためのコマンドをバッファにコピーする。 115 * 116 * Params: 117 * command_buffer = コマンドのバッファ 118 * buffer_size = コマンドのバッファサイズ 119 */ 120 version (Windows) 121 extern (C) 122 nothrow @nogc 123 public bool copy_restore_windows_shortcut_arrow_command(scope wchar* command_buffer, size_t buffer_size) 124 125 do 126 { 127 if (command_buffer == null) { 128 return false; 129 } 130 131 if (buffer_size < .REG_DELETE_COMMAND_BUFFER_LENGTH) { 132 if (buffer_size != 0) { 133 command_buffer[0] = '\0'; 134 } 135 136 return false; 137 } 138 139 wchar[core.sys.windows.windef.MAX_PATH] system_directory = void; 140 141 command_buffer[0] = '"'; 142 command_buffer[1] = '\0'; 143 144 if (remove_shortcut_arrow.path.get_system32_path(system_directory) == 0) { 145 return false; 146 } 147 148 core.sys.windows.winbase.lstrcatW(command_buffer, &(system_directory[0])); 149 core.sys.windows.winbase.lstrcatW(command_buffer, &("\\System32\0"w[0])); 150 151 version (none) { 152 // reg:64オプションを削除しない場合(Vistaでは動作しない) 153 154 static assert(.REG_DELETE_COMMAND[0 .. 8] == "reg.exe "w); 155 static assert(.REG_DELETE_COMMAND[$ - 1] == '\0'); 156 enum TEMP = "\\reg.exe\" "w ~ .REG_DELETE_COMMAND[8 .. $]; 157 } else { 158 // reg:64オプションを削除する場合 159 160 static assert(.REG_DELETE_COMMAND[0 .. 8] == "reg.exe "w); 161 static assert(.REG_DELETE_COMMAND[($ - " /reg:64\0"w.length) .. $] == " /reg:64\0"w); 162 enum TEMP = "\\reg.exe\" "w ~ .REG_DELETE_COMMAND[8 .. ($ - " /reg:64\0"w.length)] ~ "\0"; 163 } 164 165 core.sys.windows.winbase.lstrcatW(command_buffer, &(TEMP[0])); 166 167 return true; 168 } 169 170 version (Windows) 171 nothrow @nogc 172 package bool exec_system32_command(core.sys.windows.winnt.LPWSTR command_buffer, bool disable_redirection = true) 173 174 do 175 { 176 core.sys.windows.winbase.STARTUPINFOW temp = 177 { 178 cb: core.sys.windows.winbase.STARTUPINFOW.sizeof, 179 }; 180 181 core.sys.windows.winbase.PROCESS_INFORMATION process_info; 182 core.sys.windows.winnt.PVOID old_value = core.sys.windows.windef.NULL; 183 core.sys.windows.windef.BOOL redirection_result = void; 184 185 if (disable_redirection) { 186 redirection_result = .Wow64DisableWow64FsRedirection(&old_value); 187 } 188 189 scope (exit) { 190 if (disable_redirection) { 191 if (redirection_result != core.sys.windows.windef.FALSE) { 192 .Wow64RevertWow64FsRedirection(old_value); 193 } 194 } 195 } 196 197 core.sys.windows.windef.BOOL result = core.sys.windows.winbase.CreateProcessW(null, command_buffer, null, null, core.sys.windows.windef.FALSE, core.sys.windows.winbase.CREATE_NO_WINDOW, null, null, &temp, &process_info); 198 199 if (result == core.sys.windows.windef.FALSE) { 200 return false; 201 } 202 203 scope (exit) { 204 core.sys.windows.winbase.CloseHandle(process_info.hProcess); 205 core.sys.windows.winbase.CloseHandle(process_info.hThread); 206 } 207 208 core.sys.windows.windef.DWORD exit_code = 1; 209 210 return (core.sys.windows.winbase.WaitForSingleObject(process_info.hProcess, core.sys.windows.winbase.INFINITE) != core.sys.windows.winbase.WAIT_FAILED) && (core.sys.windows.winbase.GetExitCodeProcess(process_info.hProcess, &exit_code) != core.sys.windows.windef.FALSE) && (exit_code == 0); 211 } 212 213 /** 214 * アイコンキャッシュをie4uinit.exeを利用してクリアする? 215 * 216 * ie4uinit.exeがあるかどうかやそのPATHなどはOSによって違うのでうまくいかないかもしれない 217 */ 218 version (Windows) 219 extern (C) 220 nothrow @nogc 221 public bool exec_clear_icon_cache() 222 223 do 224 { 225 wchar[core.sys.windows.windef.MAX_PATH] system_directory = void; 226 227 if (remove_shortcut_arrow.path.get_system32_path(system_directory) == 0) { 228 return false; 229 } 230 231 //Unicode版はバッファに入れなければならない 232 wchar[core.sys.windows.windef.MAX_PATH + "\"\"".length + " -ClearIconCache".length + "\0".length] command_buffer = void; 233 command_buffer[0] = '"'; 234 command_buffer[1] = '\0'; 235 core.sys.windows.winbase.lstrcatW(&(command_buffer[0]), &(system_directory[0])); 236 core.sys.windows.winbase.lstrcatW(&(command_buffer[0]), &("\\System32\0"w[0])); 237 core.sys.windows.winbase.lstrcatW(&(command_buffer[0]), &("\\ie4uinit.exe\" -ClearIconCache\0"w[0])); 238 239 int length = core.sys.windows.winbase.lstrlenW(&(command_buffer[0])); 240 assert(length > 0); 241 242 core.sys.windows.winnt.PVOID old_value = core.sys.windows.windef.NULL; 243 core.sys.windows.windef.BOOL redirection_result = void; 244 redirection_result = .Wow64DisableWow64FsRedirection(&old_value); 245 246 scope (exit) { 247 if (redirection_result != core.sys.windows.windef.FALSE) { 248 .Wow64RevertWow64FsRedirection(old_value); 249 } 250 } 251 252 bool result1 = .exec_system32_command(&(command_buffer[0]), false); 253 length -= "ClearIconCache".length; 254 255 command_buffer[length++] = 's'; 256 command_buffer[length++] = 'h'; 257 command_buffer[length++] = 'o'; 258 command_buffer[length++] = 'w'; 259 command_buffer[length] = '\0'; 260 261 return (result1) && (.exec_system32_command(&(command_buffer[0]), false)); 262 }