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