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