1 /* 2 * Copyright 2016-2017, 2021 Hugh McMaster 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #include "reg.h" 20 21 static BOOL op_delete_key = TRUE; 22 23 static void output_error(LONG rc) 24 { 25 if (rc == ERROR_FILE_NOT_FOUND) 26 { 27 if (op_delete_key) 28 output_message(STRING_KEY_NONEXIST); 29 else 30 output_message(STRING_VALUE_NONEXIST); 31 } 32 else 33 { 34 output_message(STRING_ACCESS_DENIED); 35 } 36 } 37 38 static int run_delete(HKEY root, WCHAR *path, REGSAM sam, WCHAR *key_name, WCHAR *value_name, 39 BOOL value_empty, BOOL value_all, BOOL force) 40 { 41 LONG rc; 42 HKEY hkey; 43 44 if (!force) 45 { 46 BOOL ret; 47 48 if (value_name || value_empty) 49 ret = ask_confirm(STRING_DELETE_VALUE, value_name); 50 else if (value_all) 51 ret = ask_confirm(STRING_DELETE_VALUEALL, key_name); 52 else 53 ret = ask_confirm(STRING_DELETE_SUBKEY, key_name); 54 55 if (!ret) 56 { 57 output_message(STRING_CANCELLED); 58 return 0; 59 } 60 } 61 62 if ((rc = RegOpenKeyExW(root, path, 0, KEY_READ|KEY_SET_VALUE|sam, &hkey))) 63 { 64 output_error(rc); 65 return 1; 66 } 67 68 /* Delete registry key if no /v* option is given */ 69 if (!value_name && !value_empty && !value_all) 70 { 71 if ((rc = RegDeleteTreeW(hkey, NULL))) 72 { 73 RegCloseKey(hkey); 74 output_error(rc); 75 return 1; 76 } 77 78 RegDeleteKeyW(hkey, L""); 79 RegCloseKey(hkey); 80 81 output_message(STRING_SUCCESS); 82 return 0; 83 } 84 85 op_delete_key = FALSE; 86 87 if (value_all) 88 { 89 DWORD max_value_len = 256, value_len; 90 WCHAR *value_name; 91 92 value_name = malloc(max_value_len * sizeof(WCHAR)); 93 94 while (1) 95 { 96 value_len = max_value_len; 97 rc = RegEnumValueW(hkey, 0, value_name, &value_len, NULL, NULL, NULL, NULL); 98 if (rc == ERROR_SUCCESS) 99 { 100 rc = RegDeleteValueW(hkey, value_name); 101 if (rc != ERROR_SUCCESS) 102 { 103 free(value_name); 104 RegCloseKey(hkey); 105 output_message(STRING_VALUEALL_FAILED, key_name); 106 output_error(rc); 107 return 1; 108 } 109 } 110 else if (rc == ERROR_MORE_DATA) 111 { 112 max_value_len *= 2; 113 value_name = realloc(value_name, max_value_len * sizeof(WCHAR)); 114 } 115 else break; 116 } 117 free(value_name); 118 } 119 else if (value_name || value_empty) 120 { 121 if ((rc = RegDeleteValueW(hkey, value_name))) 122 { 123 RegCloseKey(hkey); 124 output_error(rc); 125 return 1; 126 } 127 } 128 129 RegCloseKey(hkey); 130 output_message(STRING_SUCCESS); 131 return 0; 132 } 133 134 int reg_delete(int argc, WCHAR *argvW[]) 135 { 136 HKEY root; 137 WCHAR *path, *key_name, *value_name = NULL; 138 BOOL value_all = FALSE, value_empty = FALSE, force = FALSE; 139 REGSAM sam = 0; 140 int i; 141 142 if (!parse_registry_key(argvW[2], &root, &path)) 143 return 1; 144 145 for (i = 3; i < argc; i++) 146 { 147 WCHAR *str; 148 149 if (argvW[i][0] != '/' && argvW[i][0] != '-') 150 goto invalid; 151 152 str = &argvW[i][1]; 153 154 if (!lstrcmpiW(str, L"va")) 155 { 156 if (value_all) goto invalid; 157 value_all = TRUE; 158 continue; 159 } 160 else if (!lstrcmpiW(str, L"ve")) 161 { 162 if (value_empty) goto invalid; 163 value_empty = TRUE; 164 continue; 165 } 166 else if (!lstrcmpiW(str, L"reg:32")) 167 { 168 if (sam & KEY_WOW64_32KEY) goto invalid; 169 sam |= KEY_WOW64_32KEY; 170 continue; 171 } 172 else if (!lstrcmpiW(str, L"reg:64")) 173 { 174 if (sam & KEY_WOW64_64KEY) goto invalid; 175 sam |= KEY_WOW64_64KEY; 176 continue; 177 } 178 else if (!str[0] || str[1]) 179 goto invalid; 180 181 switch (towlower(*str)) 182 { 183 case 'v': 184 if (value_name || !(value_name = argvW[++i])) 185 goto invalid; 186 break; 187 case 'f': 188 if (force) goto invalid; 189 force = TRUE; 190 break; 191 default: 192 goto invalid; 193 } 194 } 195 196 if ((value_name && value_empty) || (value_name && value_all) || (value_empty && value_all)) 197 goto invalid; 198 199 if (sam == (KEY_WOW64_32KEY|KEY_WOW64_64KEY)) 200 goto invalid; 201 202 key_name = get_long_key(root, path); 203 204 return run_delete(root, path, sam, key_name, value_name, value_empty, value_all, force); 205 206 invalid: 207 output_message(STRING_INVALID_SYNTAX); 208 output_message(STRING_FUNC_HELP, _wcsupr(argvW[1])); 209 return 1; 210 } 211