[MKHIVE/USETUP]
[reactos.git] / reactos / base / shell / cmd / assoc.c
1 /*
2 * Assoc.C - assoc internal command.
3 *
4 *
5 * History:
6 *
7 * 14-Mar-2009 Lee C. Baker
8 * - initial implementation
9 *
10 * 15-Mar-2009 Lee C. Baker
11 * - Don't write to (or use) HKEY_CLASSES_ROOT directly
12 * - Externalize strings
13 *
14 * TODO:
15 * - PrintAllAssociations might could be optimized to not fetch all registry subkeys under 'Classes', just the ones that start with '.'
16 * - Make sure that non-administrator users can list associations, and get appropriate error messages when they don't have sufficient
17 * priveleges to perform an operation
18 */
19
20 #include <precomp.h>
21 #include <tchar.h>
22
23 #ifdef INCLUDE_CMD_ASSOC
24
25 static INT
26 PrintAssociation(LPTSTR extension)
27 {
28 DWORD return_val;
29 HKEY hKey = NULL, hInsideKey = NULL;
30
31 DWORD fileTypeLength = 0;
32 LPTSTR fileType = NULL;
33
34 return_val = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Classes"), 0, KEY_READ, &hKey);
35
36 if(return_val != ERROR_SUCCESS)
37 {
38 RegCloseKey(hKey);
39 return -1;
40 }
41
42 return_val = RegOpenKeyEx(hKey, extension, 0, KEY_READ, &hInsideKey);
43
44 if(return_val != ERROR_SUCCESS)
45 {
46 RegCloseKey(hKey);
47 RegCloseKey(hInsideKey);
48 return 0;
49 }
50
51 /* obtain string length */
52 return_val = RegQueryValueEx(hInsideKey, NULL, NULL, NULL, NULL, &fileTypeLength);
53
54 if(return_val == ERROR_FILE_NOT_FOUND) /* no default value, don't display */
55 {
56 RegCloseKey(hInsideKey);
57 RegCloseKey(hKey);
58 return 0;
59 }
60
61 if(return_val != ERROR_SUCCESS)
62 {
63 RegCloseKey(hInsideKey);
64 RegCloseKey(hKey);
65 return -2;
66 }
67
68 fileType = cmd_alloc(fileTypeLength * sizeof(TCHAR));
69
70 /* obtain actual file type */
71 return_val = RegQueryValueEx(hInsideKey, NULL, NULL, NULL, (LPBYTE) fileType, &fileTypeLength);
72
73 RegCloseKey(hInsideKey);
74 RegCloseKey(hKey);
75
76 if(return_val != ERROR_SUCCESS)
77 {
78 cmd_free(fileType);
79 return -2;
80 }
81
82 if(fileTypeLength != 0) /* if there is a default key, display relevant information */
83 {
84 ConOutPrintf(_T("%s=%s\r\n"), extension, fileType);
85 }
86
87 if(fileTypeLength)
88 cmd_free(fileType);
89
90 return 1;
91 }
92
93 static INT
94 PrintAllAssociations()
95 {
96 DWORD return_val = 0;
97 HKEY hKey = NULL;
98 DWORD numKeys = 0;
99
100 DWORD extLength = 0;
101 LPTSTR extName = NULL;
102 DWORD keyCtr = 0;
103
104 return_val = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Classes"), 0, KEY_READ, &hKey);
105
106 if(return_val != ERROR_SUCCESS)
107 {
108 RegCloseKey(hKey);
109 return -1;
110 }
111
112 return_val = RegQueryInfoKey(hKey, NULL, NULL, NULL, &numKeys, &extLength, NULL, NULL, NULL, NULL, NULL, NULL);
113
114 if(return_val != ERROR_SUCCESS)
115 {
116 RegCloseKey(hKey);
117 return -2;
118 }
119
120 extName = cmd_alloc(extLength * sizeof(TCHAR));
121
122 for(keyCtr = 0; keyCtr < numKeys; keyCtr++)
123 {
124 DWORD buffer_size = extLength;
125 return_val = RegEnumKeyEx(hKey, keyCtr, extName, &buffer_size, NULL, NULL, NULL, NULL);
126
127 if(return_val == ERROR_SUCCESS || return_val == ERROR_MORE_DATA)
128 {
129 if(*extName == _T('.'))
130 PrintAssociation(extName);
131 }
132 else
133 {
134 cmd_free(extName);
135 RegCloseKey(hKey);
136 return -1;
137 }
138 }
139
140 RegCloseKey(hKey);
141
142 if(extName)
143 cmd_free(extName);
144
145 return numKeys;
146 }
147
148 static INT
149 AddAssociation(LPTSTR extension, LPTSTR type)
150 {
151 DWORD return_val;
152 HKEY hKey = NULL, insideKey = NULL;
153
154 return_val = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Classes"), 0, KEY_ALL_ACCESS, &hKey);
155
156 if(return_val != ERROR_SUCCESS)
157 return -1;
158
159 return_val = RegCreateKeyEx(hKey, extension, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &insideKey, NULL);
160
161 if(return_val != ERROR_SUCCESS)
162 {
163 RegCloseKey(hKey);
164 return -1;
165 }
166
167 return_val = RegSetValueEx(insideKey, NULL, 0, REG_SZ, (LPBYTE)type, (_tcslen(type) + 1) * sizeof(TCHAR));
168
169 if(return_val != ERROR_SUCCESS)
170 {
171 RegCloseKey(insideKey);
172 RegCloseKey(hKey);
173 return -2;
174 }
175
176 RegCloseKey(insideKey);
177 RegCloseKey(hKey);
178 return 0;
179 }
180
181
182 static int
183 RemoveAssociation(LPTSTR extension)
184 {
185 DWORD return_val;
186 HKEY hKey;
187
188 return_val = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Classes"), 0, KEY_ALL_ACCESS, &hKey);
189
190 if(return_val != ERROR_SUCCESS)
191 return -1;
192
193 return_val = RegDeleteKey(hKey, extension);
194
195 if(return_val != ERROR_SUCCESS)
196 {
197 RegCloseKey(hKey);
198 return -2;
199 }
200
201 RegCloseKey(hKey);
202 return 0;
203 }
204
205
206
207 INT CommandAssoc (LPTSTR param)
208 {
209
210 LPTSTR lpEqualSign = NULL;
211
212 /* print help */
213 if (!_tcsncmp (param, _T("/?"), 2))
214 {
215 ConOutResPaging(TRUE,STRING_ASSOC_HELP);
216 return 0;
217 }
218
219 nErrorLevel = 0;
220
221 if(_tcslen(param) == 0)
222 PrintAllAssociations();
223 else
224 {
225 lpEqualSign = _tcschr(param, _T('='));
226 if(lpEqualSign != NULL)
227 {
228 LPTSTR fileType = lpEqualSign + 1;
229 LPTSTR extension = cmd_alloc((lpEqualSign - param + 1) * sizeof(TCHAR));
230
231 _tcsncpy(extension, param, lpEqualSign - param);
232 extension[lpEqualSign - param] = (TCHAR)0;
233
234 if(_tcslen(fileType) == 0)
235 /* if the equal sign is the last character
236 in the string, then delete the key */
237 {
238 RemoveAssociation(extension);
239 }
240 else
241 /* otherwise, add the key and print out the association*/
242 {
243 AddAssociation( extension, fileType);
244 PrintAssociation(extension);
245 }
246
247 cmd_free(extension);
248 }
249 else
250 {
251 /* no equal sign, print all associations */
252 INT retval = PrintAssociation(param);
253
254 if(retval == 0) /* if nothing printed out */
255 ConOutResPrintf(STRING_ASSOC_ERROR, param);
256 }
257 }
258
259 return 0;
260 }
261
262 #endif /* INCLUDE_CMD_ASSOC */