f2db40621ea569bf4932ecdf7b8ecee1968a0a16
[reactos.git] / rosapps / cmdutils / mode / mode.c
1 /*
2 * ReactOS mode console command
3 *
4 * mode.c
5 *
6 * Copyright (C) 2002 Robert Dickenson <robd@reactos.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include <windows.h>
24 #include <string.h>
25 #include <stdio.h>
26 #include <tchar.h>
27
28 #define MAX_PORTNAME_LEN 20
29 #define MAX_COMPORT_NUM 10
30 #define MAX_COMPARAM_LEN 20
31
32 #define NUM_ELEMENTS(a) (sizeof(a)/sizeof(a[0]))
33 #define ASSERT(a)
34
35 const TCHAR* const usage_strings[] = {
36 _T("Device Status: MODE [device] [/STATUS]"),
37 _T("Select code page: MODE CON[:] CP SELECT=yyy"),
38 _T("Code page status: MODE CON[:] CP [/STATUS]"),
39 _T("Display mode: MODE CON[:] [COLS=c] [LINES=n]"),
40 _T("Typematic rate: MODE CON[:] [RATE=r DELAY=d]"),
41 _T("Redirect printing: MODE LPTn[:]=COMm[:]"),
42 _T("Serial port: MODE COMm[:] [BAUD=b] [PARITY=p] [DATA=d] [STOP=s]\n") \
43 _T(" [to=on|off] [xon=on|off] [odsr=on|off]\n") \
44 _T(" [octs=on|off] [dtr=on|off|hs]\n") \
45 _T(" [rts=on|off|hs|tg] [idsr=on|off]"),
46 };
47
48 const TCHAR* const parity_strings[] = {
49 _T("None"), // default
50 _T("Odd"), // only symbol in this set to have a 'd' in it
51 _T("Even"), // ... 'v' in it
52 _T("Mark"), // ... 'm' in it
53 _T("Space") // ... 's' and/or a 'c' in it
54 };
55
56 const TCHAR* const control_strings[] = { _T("OFF"), _T("ON"), _T("HANDSHAKE"), _T("TOGGLE") };
57
58 const TCHAR* const stopbit_strings[] = { _T("1"), _T("1.5"), _T("2") };
59
60
61 int Usage()
62 {
63 int i;
64
65 _tprintf(_T("\nConfigures system devices.\n\n"));
66 for (i = 0; i < NUM_ELEMENTS(usage_strings); i++) {
67 _tprintf(_T("%s\n"), usage_strings[i]);
68 }
69 _tprintf(_T("\n"));
70 return 0;
71 }
72
73 int QueryDevices()
74 {
75 TCHAR buffer[10240];
76 int len;
77 TCHAR* ptr = buffer;
78
79 *ptr = '\0';
80 if (QueryDosDevice(NULL, buffer, NUM_ELEMENTS(buffer))) {
81 while (*ptr != '\0') {
82 len = _tcslen(ptr);
83 if (_tcsstr(ptr, _T("COM"))) {
84 _tprintf(_T(" Found serial device - %s\n"), ptr);
85 } else if (_tcsstr(ptr, _T("PRN"))) {
86 _tprintf(_T(" Found printer device - %s\n"), ptr);
87 } else if (_tcsstr(ptr, _T("LPT"))) {
88 _tprintf(_T(" Found parallel device - %s\n"), ptr);
89 } else {
90 _tprintf(_T(" Found other device - %s\n"), ptr);
91 }
92 ptr += (len+1);
93 }
94 } else {
95 _tprintf(_T(" ERROR: QueryDosDevice(...) failed.\n"));
96 }
97 return 1;
98 }
99
100 int ShowParallelStatus(int nPortNum)
101 {
102 TCHAR buffer[250];
103 TCHAR szPortName[MAX_PORTNAME_LEN];
104
105 _stprintf(szPortName, _T("LPT%d"), nPortNum);
106 _tprintf(_T("\nStatus for device LPT%d:\n"), nPortNum);
107 _tprintf(_T("-----------------------\n"));
108 if (QueryDosDevice(szPortName, buffer, NUM_ELEMENTS(buffer))) {
109 TCHAR* ptr = _tcsrchr(buffer, '\\');
110 if (ptr != NULL) {
111 if (0 == _tcscmp(szPortName, ++ptr)) {
112 _tprintf(_T(" Printer output is not being rerouted.\n"));
113 } else {
114 _tprintf(_T(" Printer output is being rerouted to serial port %s\n"), ptr);
115 }
116 return 0;
117 } else {
118 _tprintf(_T(" QueryDosDevice(%s) returned unrecogised form %s.\n"), szPortName, buffer);
119 }
120 } else {
121 _tprintf(_T(" ERROR: QueryDosDevice(%s) failed.\n"), szPortName);
122 }
123 return 1;
124 }
125
126 int ShowConsoleStatus()
127 {
128 DWORD dwKbdDelay;
129 DWORD dwKbdSpeed;
130 CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo;
131 HANDLE hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
132
133 _tprintf(_T("\nStatus for device CON:\n"));
134 _tprintf(_T("-----------------------\n"));
135 if (GetConsoleScreenBufferInfo(hConsoleOutput, &ConsoleScreenBufferInfo)) {
136 _tprintf(_T(" Lines: %d\n"), ConsoleScreenBufferInfo.dwSize.Y);
137 _tprintf(_T(" Columns: %d\n"), ConsoleScreenBufferInfo.dwSize.X);
138 }
139 if (SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &dwKbdDelay, 0)) {
140 _tprintf(_T(" Keyboard delay: %d\n"), dwKbdDelay);
141 }
142 if (SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &dwKbdSpeed, 0)) {
143 _tprintf(_T(" Keyboard rate: %d\n"), dwKbdSpeed);
144 }
145 _tprintf(_T(" Code page: %d\n"), GetConsoleOutputCP());
146 return 0;
147 }
148
149 static
150 BOOL SerialPortQuery(int nPortNum, LPDCB pDCB, LPCOMMTIMEOUTS pCommTimeouts, BOOL bWrite)
151 {
152 BOOL result;
153 HANDLE hPort;
154 TCHAR szPortName[MAX_PORTNAME_LEN];
155
156 ASSERT(pDCB);
157 ASSERT(pCommTimeouts);
158
159 _stprintf(szPortName, _T("COM%d"), nPortNum);
160 hPort = CreateFile(szPortName,
161 GENERIC_READ|GENERIC_WRITE,
162 0, // exclusive
163 NULL, // sec attr
164 OPEN_EXISTING,
165 0, // no attributes
166 NULL); // no template
167
168 if (hPort == (HANDLE)-1) {
169 _tprintf(_T("Illegal device name - %s\n"), szPortName);
170 _tprintf(_T("Last error = 0x%lx\n"), GetLastError());
171 return FALSE;
172 }
173 if (bWrite) {
174 result = SetCommState(hPort, pDCB);
175 } else {
176 result = GetCommState(hPort, pDCB);
177 }
178 if (!result) {
179 _tprintf(_T("Failed to %s the status for device COM%d:\n"), bWrite ? _T("set") : _T("get"), nPortNum);
180 CloseHandle(hPort);
181 return FALSE;
182 }
183 if (bWrite) {
184 result = SetCommTimeouts(hPort, pCommTimeouts);
185 } else {
186 result = GetCommTimeouts(hPort, pCommTimeouts);
187 }
188 if (!result) {
189 _tprintf(_T("Failed to %s Timeout status for device COM%d:\n"), bWrite ? _T("set") : _T("get"), nPortNum);
190 CloseHandle(hPort);
191 return FALSE;
192
193 }
194 CloseHandle(hPort);
195 return TRUE;
196 }
197
198 int ShowSerialStatus(int nPortNum)
199 {
200 HANDLE hPort;
201 DCB dcb;
202 COMMTIMEOUTS CommTimeouts;
203 TCHAR szPortName[MAX_PORTNAME_LEN];
204
205 if (!SerialPortQuery(nPortNum, &dcb, &CommTimeouts, FALSE)) {
206 return 1;
207 }
208 if (dcb.Parity > NUM_ELEMENTS(parity_strings)) {
209 _tprintf(_T("ERROR: Invalid value for Parity Bits %d:\n"), dcb.Parity);
210 dcb.Parity = 0;
211 }
212 if (dcb.StopBits > NUM_ELEMENTS(stopbit_strings)) {
213 _tprintf(_T("ERROR: Invalid value for Stop Bits %d:\n"), dcb.StopBits);
214 dcb.StopBits = 0;
215 }
216 _tprintf(_T("\nStatus for device COM%d:\n"), nPortNum);
217 _tprintf(_T("-----------------------\n"));
218 _tprintf(_T(" Baud: %d\n"), dcb.BaudRate);
219 _tprintf(_T(" Parity: %s\n"), parity_strings[dcb.Parity]);
220 _tprintf(_T(" Data Bits: %d\n"), dcb.ByteSize);
221 _tprintf(_T(" Stop Bits: %s\n"), stopbit_strings[dcb.StopBits]);
222 _tprintf(_T(" Timeout: %s\n"), CommTimeouts.ReadIntervalTimeout ? _T("ON") : _T("OFF"));
223 _tprintf(_T(" XON/XOFF: %s\n"), dcb.fOutX ? _T("ON") : _T("OFF"));
224 _tprintf(_T(" CTS handshaking: %s\n"), dcb.fOutxCtsFlow ? _T("ON") : _T("OFF"));
225 _tprintf(_T(" DSR handshaking: %s\n"), dcb.fOutxDsrFlow ? _T("ON") : _T("OFF"));
226 _tprintf(_T(" DSR sensitivity: %s\n"), dcb.fDsrSensitivity ? _T("ON") : _T("OFF"));
227 _tprintf(_T(" DTR circuit: %s\n"), control_strings[dcb.fDtrControl]);
228 _tprintf(_T(" RTS circuit: %s\n"), control_strings[dcb.fRtsControl]);
229 return 0;
230 }
231
232 int SetParallelState(int nPortNum)
233 {
234 TCHAR szPortName[MAX_PORTNAME_LEN];
235 TCHAR szTargetPath[MAX_PORTNAME_LEN];
236
237 _stprintf(szPortName, _T("LPT%d"), nPortNum);
238 _stprintf(szTargetPath, _T("COM%d"), nPortNum);
239 if (!DefineDosDevice(DDD_REMOVE_DEFINITION, szPortName, szTargetPath)) {
240 DWORD error = GetLastError();
241
242 _tprintf(_T("SetParallelState(%d) - DefineDosDevice(%s) failed: %x\n"), nPortNum, error);
243 }
244 return 0;
245 }
246
247 /*
248 \??\COM1
249 \Device\NamedPipe\Spooler\LPT1
250 BOOL DefineDosDevice(
251 DWORD dwFlags, // options
252 LPCTSTR lpDeviceName, // device name
253 LPCTSTR lpTargetPath // path string
254 );
255 DWORD QueryDosDevice(
256 LPCTSTR lpDeviceName, // MS-DOS device name string
257 LPTSTR lpTargetPath, // query results buffer
258 DWORD ucchMax // maximum size of buffer
259 );
260 */
261
262 int SetConsoleState()
263 {
264 /*
265 "Select code page: MODE CON[:] CP SELECT=yyy",
266 "Code page status: MODE CON[:] CP [/STATUS]",
267 "Display mode: MODE CON[:] [COLS=c] [LINES=n]",
268 "Typematic rate: MODE CON[:] [RATE=r DELAY=d]",
269 */
270 return 0;
271 }
272
273 static
274 int ExtractModeSerialParams(const TCHAR* param)
275 {
276 if ( _tcsstr(param, _T("OFF"))) {
277 return 0;
278 } else if (_tcsstr(param, _T("ON"))) {
279 return 1;
280 } else if (_tcsstr(param, _T("HS"))) {
281 return 2;
282 } else if (_tcsstr(param, _T("TG"))) {
283 return 3;
284 }
285 return -1;
286 }
287
288 int SetSerialState(int nPortNum, int args, TCHAR *argv[])
289 {
290 int arg;
291 int value;
292 DCB dcb;
293 COMMTIMEOUTS CommTimeouts;
294 TCHAR buf[MAX_COMPARAM_LEN+1];
295
296 if (SerialPortQuery(nPortNum, &dcb, &CommTimeouts, FALSE)) {
297 for (arg = 2; arg < args; arg++) {
298 if (_tcslen(argv[arg]) > MAX_COMPARAM_LEN) {
299 _tprintf(_T("Invalid parameter (too long) - %s\n"), argv[arg]);
300 return 1;
301 }
302 _tcscpy(buf, argv[arg]);
303 _tcslwr(buf);
304 if (_tcsstr(buf, _T("baud="))) {
305 _tscanf(buf+5, "%lu", &dcb.BaudRate);
306 } else if (_tcsstr(buf, _T("parity="))) {
307 if (_tcschr(buf, 'D')) {
308 dcb.Parity = 1;
309 } else if (_tcschr(buf, 'V')) {
310 dcb.Parity = 2;
311 } else if (_tcschr(buf, 'M')) {
312 dcb.Parity = 3;
313 } else if (_tcschr(buf, 'S')) {
314 dcb.Parity = 4;
315 } else {
316 dcb.Parity = 0;
317 }
318 } else if (_tcsstr(buf, _T("data="))) {
319 _tscanf(buf+5, "%lu", &dcb.ByteSize);
320 } else if (_tcsstr(buf, _T("stop="))) {
321 if (_tcschr(buf, '5')) {
322 dcb.StopBits = 1;
323 } else if (_tcschr(buf, '2')) {
324 dcb.StopBits = 2;
325 } else {
326 dcb.StopBits = 0;
327 }
328 } else if (_tcsstr(buf, _T("to="))) { // to=on|off
329 value = ExtractModeSerialParams(buf);
330 if (value != -1) {
331 } else {
332 goto invalid_serial_parameter;
333 }
334 } else if (_tcsstr(buf, _T("xon="))) { // xon=on|off
335 value = ExtractModeSerialParams(buf);
336 if (value != -1) {
337 dcb.fOutX = value;
338 dcb.fInX = value;
339 } else {
340 goto invalid_serial_parameter;
341 }
342 } else if (_tcsstr(buf, _T("odsr="))) { // odsr=on|off
343 value = ExtractModeSerialParams(buf);
344 if (value != -1) {
345 dcb.fOutxDsrFlow = value;
346 } else {
347 goto invalid_serial_parameter;
348 }
349 } else if (_tcsstr(buf, _T("octs="))) { // octs=on|off
350 value = ExtractModeSerialParams(buf);
351 if (value != -1) {
352 dcb.fOutxCtsFlow = value;
353 } else {
354 goto invalid_serial_parameter;
355 }
356 } else if (_tcsstr(buf, _T("dtr="))) { // dtr=on|off|hs
357 value = ExtractModeSerialParams(buf);
358 if (value != -1) {
359 dcb.fDtrControl = value;
360 } else {
361 goto invalid_serial_parameter;
362 }
363 } else if (_tcsstr(buf, _T("rts="))) { // rts=on|off|hs|tg
364 value = ExtractModeSerialParams(buf);
365 if (value != -1) {
366 dcb.fRtsControl = value;
367 } else {
368 goto invalid_serial_parameter;
369 }
370 } else if (_tcsstr(buf, _T("idsr="))) { // idsr=on|off
371 value = ExtractModeSerialParams(buf);
372 if (value != -1) {
373 dcb.fDsrSensitivity = value;
374 } else {
375 goto invalid_serial_parameter;
376 }
377 } else {
378 invalid_serial_parameter:;
379 _tprintf(_T("Invalid parameter - %s\n"), buf);
380 return 1;
381 }
382 }
383 SerialPortQuery(nPortNum, &dcb, &CommTimeouts, TRUE);
384 }
385 return 0;
386 }
387
388 int find_portnum(const TCHAR* cmdverb)
389 {
390 int portnum = -1;
391
392 if (cmdverb[3] >= '0' && cmdverb[3] <= '9') {
393 portnum = cmdverb[3] - '0';
394 if (cmdverb[4] >= '0' && cmdverb[4] <= '9') {
395 portnum *= 10;
396 portnum += cmdverb[4] - '0';
397 }
398 }
399 return portnum;
400 }
401
402 int main(int argc, TCHAR *argv[])
403 {
404 int nPortNum;
405 TCHAR param1[MAX_COMPARAM_LEN+1];
406 TCHAR param2[MAX_COMPARAM_LEN+1];
407
408 if (argc > 1) {
409 if (_tcslen(argv[1]) > MAX_COMPARAM_LEN) {
410 _tprintf(_T("Invalid parameter (too long) - %s\n"), argv[1]);
411 return 1;
412 }
413 _tcscpy(param1, argv[1]);
414 _tcslwr(param1);
415 if (argc > 2) {
416 if (_tcslen(argv[2]) > MAX_COMPARAM_LEN) {
417 _tprintf(_T("Invalid parameter (too long) - %s\n"), argv[2]);
418 return 1;
419 }
420 _tcscpy(param2, argv[2]);
421 _tcslwr(param2);
422 } else {
423 param2[0] = '\0';
424 }
425 if (_tcsstr(param1, _T("/?")) || _tcsstr(param1, _T("-?"))) {
426 return Usage();
427 } else if (_tcsstr(param1, _T("/status"))) {
428 goto show_status;
429 } else if (_tcsstr(param1, _T("lpt"))) {
430 nPortNum = find_portnum(param1);
431 if (nPortNum != -1)
432 return ShowParallelStatus(nPortNum);
433 } else if (_tcsstr(param1, _T("con"))) {
434 return ShowConsoleStatus();
435 } else if (_tcsstr(param1, _T("com"))) {
436 nPortNum = find_portnum(param1);
437 if (nPortNum != -1) {
438 if (param2[0] == '\0' || _tcsstr(param2, _T("/status"))) {
439 return ShowSerialStatus(nPortNum);
440 } else {
441 return SetSerialState(nPortNum, argc, argv);
442 }
443 }
444 }
445 _tprintf(_T("Invalid parameter - %s\n"), param1);
446 return 1;
447 } else {
448 show_status:;
449
450 QueryDevices();
451 /*
452 ShowParallelStatus(1);
453 for (nPortNum = 0; nPortNum < MAX_COMPORT_NUM; nPortNum++) {
454 ShowSerialStatus(nPortNum + 1);
455 }
456 ShowConsoleStatus();
457 */
458 }
459 return 0;
460 }