Sync with trunk r63647.
[reactos.git] / base / system / subst / subst.c
1 /* PROJECT: ReactOS Kernel
2 * LICENSE: GPL - See COPYING in the top level directory
3 * FILE: base/system/subst/subst.c
4 * PURPOSE: Associates a path with a drive letter
5 * PROGRAMMERS: Sam Arun Raj
6 */
7
8 /* INCLUDES *****************************************************************/
9
10 #define WIN32_NO_STATUS
11 #include <stdarg.h>
12 #include <windef.h>
13 #include <winbase.h>
14 #include <winuser.h>
15 #include <stdlib.h>
16 #include <tchar.h>
17
18 #define NDEBUG
19 #include <debug.h>
20
21 #include "resource.h"
22
23 /* FUNCTIONS ****************************************************************/
24
25 void PrintError(DWORD ErrCode)
26 {
27 TCHAR szFmtString[RC_STRING_MAX_SIZE] = {0};
28 TCHAR *buffer = (TCHAR*) calloc(2048,
29 sizeof(TCHAR));
30 TCHAR *msg = NULL;
31
32 if (buffer)
33 {
34 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
35 NULL,
36 ErrCode,
37 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
38 (TCHAR*)&msg,
39 0,
40 NULL);
41 LoadString(GetModuleHandle(NULL),
42 IDS_FAILED_WITH_ERRORCODE,
43 szFmtString,
44 sizeof(szFmtString) / sizeof(szFmtString[0]));
45 _sntprintf(buffer,
46 2048,
47 szFmtString,
48 ErrCode,
49 msg);
50 _tprintf(_T("%s"),
51 buffer);
52 if (msg)
53 LocalFree(msg);
54 free(buffer);
55 }
56 }
57
58 void DisplaySubstUsage(void)
59 {
60 TCHAR szHelp[RC_STRING_MAX_SIZE] = {0};
61
62 LoadString(GetModuleHandle(NULL),
63 IDS_USAGE,
64 szHelp,
65 sizeof(szHelp) / sizeof(szHelp[0]));
66 _tprintf(_T("%s"), szHelp);
67 }
68
69 BOOLEAN IsSubstedDrive(TCHAR *Drive)
70 {
71 BOOLEAN Result = FALSE;
72 LPTSTR lpTargetPath = NULL;
73 DWORD CharCount, dwSize;
74
75 if (_tcslen(Drive) > 2)
76 return FALSE;
77
78 dwSize = sizeof(TCHAR) * MAX_PATH;
79 lpTargetPath = (LPTSTR) malloc(sizeof(TCHAR) * MAX_PATH);
80 if ( lpTargetPath)
81 {
82 CharCount = QueryDosDevice(Drive,
83 lpTargetPath,
84 dwSize / sizeof(TCHAR));
85 while (! CharCount &&
86 GetLastError() == ERROR_INSUFFICIENT_BUFFER)
87 {
88 free(lpTargetPath);
89 dwSize *= 2;
90 lpTargetPath = (LPTSTR) malloc(dwSize);
91 if (lpTargetPath)
92 {
93 CharCount = QueryDosDevice(Drive,
94 lpTargetPath,
95 dwSize / sizeof(TCHAR));
96 }
97 }
98
99 if (CharCount)
100 {
101 if ( _tcsncmp(lpTargetPath, _T("\\??\\"), 4) == 0 &&
102 ( (lpTargetPath[4] >= _T('A') &&
103 lpTargetPath[4] <= _T('Z')) ||
104 (lpTargetPath[4] >= _T('a') &&
105 lpTargetPath[4] <= _T('z')) ) )
106 {
107 Result = TRUE;
108 }
109 }
110 free(lpTargetPath);
111 }
112 return Result;
113 }
114
115 void DumpSubstedDrives(void)
116 {
117 TCHAR Drive[3] = _T("A:");
118 LPTSTR lpTargetPath = NULL;
119 DWORD CharCount, dwSize;
120 INT i = 0;
121
122 dwSize = sizeof(TCHAR) * MAX_PATH;
123 lpTargetPath = (LPTSTR) malloc(sizeof(TCHAR) * MAX_PATH);
124 if (! lpTargetPath)
125 return;
126
127 while (i < 26)
128 {
129 Drive[0] = _T('A') + i;
130 CharCount = QueryDosDevice(Drive,
131 lpTargetPath,
132 dwSize / sizeof(TCHAR));
133 while (! CharCount &&
134 GetLastError() == ERROR_INSUFFICIENT_BUFFER)
135 {
136 free(lpTargetPath);
137 dwSize *= 2;
138 lpTargetPath = (LPTSTR) malloc(dwSize);
139 if (lpTargetPath)
140 {
141 CharCount = QueryDosDevice(Drive,
142 lpTargetPath,
143 dwSize / sizeof(TCHAR));
144 }
145 }
146
147 if (! CharCount)
148 {
149 i++;
150 continue;
151 }
152 else
153 {
154 if ( _tcsncmp(lpTargetPath, _T("\\??\\"), 4) == 0 &&
155 ( (lpTargetPath[4] >= _T('A') &&
156 lpTargetPath[4] <= _T('Z')) ||
157 (lpTargetPath[4] >= _T('a') &&
158 lpTargetPath[4] <= _T('z')) ) )
159 {
160 _tprintf(_T("%s\\: => %s\n"),
161 Drive,
162 lpTargetPath + 4);
163 }
164 }
165 i++;
166 }
167 free(lpTargetPath);
168 }
169
170 int DeleteSubst(TCHAR* Drive)
171 {
172 BOOL Result;
173 TCHAR szFmtString[RC_STRING_MAX_SIZE] = {0};
174
175 LoadString(GetModuleHandle(NULL),
176 IDS_INVALID_PARAMETER2,
177 szFmtString,
178 sizeof(szFmtString) / sizeof(szFmtString[0]));
179
180 if (_tcslen(Drive) > 2)
181 {
182 _tprintf(szFmtString,
183 Drive);
184 return 1;
185 }
186
187 if (! IsSubstedDrive(Drive))
188 {
189 _tprintf(szFmtString,
190 Drive);
191 return 1;
192 }
193
194 Result = DefineDosDevice(DDD_REMOVE_DEFINITION,
195 Drive,
196 NULL);
197 if (! Result)
198 {
199 PrintError(GetLastError());
200 return 1;
201 }
202 return 0;
203 }
204
205 int AddSubst(TCHAR* Drive, TCHAR *Path)
206 {
207 BOOL Result;
208 TCHAR szFmtString[RC_STRING_MAX_SIZE] = {0};
209
210 LoadString(GetModuleHandle(NULL),
211 IDS_INVALID_PARAMETER2,
212 szFmtString,
213 sizeof(szFmtString) / sizeof(szFmtString[0]));
214 if (_tcslen(Drive) != 2)
215 {
216 _tprintf(szFmtString,
217 Drive);
218 return 1;
219 }
220
221 if (Drive[1] != _T(':'))
222 {
223 _tprintf(szFmtString,
224 Drive);
225 return 1;
226 }
227
228 if (IsSubstedDrive(Drive))
229 {
230 LoadString(GetModuleHandle(NULL),
231 IDS_DRIVE_ALREADY_SUBSTED,
232 szFmtString,
233 sizeof(szFmtString) / sizeof(szFmtString[0]));
234 _tprintf(szFmtString);
235 return 1;
236 }
237
238 Result = DefineDosDevice(0,
239 Drive,
240 Path);
241 if (! Result)
242 {
243 PrintError(GetLastError());
244 return 1;
245 }
246 return 0;
247 }
248
249 int _tmain(int argc, TCHAR* argv[])
250 {
251 INT i;
252 TCHAR szFmtString[RC_STRING_MAX_SIZE] = {0};
253
254 for (i = 0; i < argc; i++)
255 {
256 if (!_tcsicmp(argv[i], _T("/?")))
257 {
258 DisplaySubstUsage();
259 return 0;
260 }
261 }
262
263 if (argc < 3)
264 {
265 if (argc >= 2)
266 {
267 LoadString(GetModuleHandle(NULL),
268 IDS_INVALID_PARAMETER,
269 szFmtString,
270 sizeof(szFmtString) / sizeof(szFmtString[0]));
271 _tprintf(szFmtString,
272 argv[1]);
273 return 1;
274 }
275 DumpSubstedDrives();
276 return 0;
277 }
278
279 if (argc > 3)
280 {
281 LoadString(GetModuleHandle(NULL),
282 IDS_INCORRECT_PARAMETER_COUNT,
283 szFmtString,
284 sizeof(szFmtString) / sizeof(szFmtString[0]));
285 _tprintf(szFmtString,
286 argv[3]);
287 return 1;
288 }
289
290 if (! _tcsicmp(argv[1], _T("/D")))
291 return DeleteSubst(argv[2]);
292 if (! _tcsicmp(argv[2], _T("/D")))
293 return DeleteSubst(argv[1]);
294 return AddSubst(argv[1], argv[2]);
295 }
296
297 /* EOF */