Minor changes for ATAPI Srb Functions
[reactos.git] / base / applications / 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 <windef.h>
24 #include <winbase.h>
25 #include <winuser.h>
26 #include <wincon.h>
27 #include <stdio.h>
28
29 #define MAX_PORTNAME_LEN 20
30 #define MAX_COMPORT_NUM 10
31 #define MAX_COMPARAM_LEN 20
32
33 #define ASSERT(a)
34
35 const WCHAR* const usage_strings[] =
36 {
37 L"Device Status: MODE [device] [/STATUS]",
38 L"Select code page: MODE CON[:] CP SELECT=yyy",
39 L"Code page status: MODE CON[:] CP [/STATUS]",
40 L"Display mode: MODE CON[:] [COLS=c] [LINES=n]",
41 L"Typematic rate: MODE CON[:] [RATE=r DELAY=d]",
42 L"Redirect printing: MODE LPTn[:]=COMm[:]",
43 L"Serial port: MODE COMm[:] [BAUD=b] [PARITY=p] [DATA=d] [STOP=s]\n" \
44 L" [to=on|off] [xon=on|off] [odsr=on|off]\n" \
45 L" [octs=on|off] [dtr=on|off|hs]\n" \
46 L" [rts=on|off|hs|tg] [idsr=on|off]",
47 };
48
49 const WCHAR* const parity_strings[] =
50 {
51 L"None", // default
52 L"Odd", // only symbol in this set to have a 'd' in it
53 L"Even", // ... 'v' in it
54 L"Mark", // ... 'm' in it
55 L"Space" // ... 's' and/or a 'c' in it
56 };
57
58 const WCHAR* const control_strings[] = { L"OFF", L"ON", L"HANDSHAKE", L"TOGGLE" };
59
60 const WCHAR* const stopbit_strings[] = { L"1", L"1.5", L"2" };
61
62
63 int Usage()
64 {
65 int i;
66
67 wprintf(L"\nConfigures system devices.\n\n");
68 for (i = 0; i < ARRAYSIZE(usage_strings); i++)
69 {
70 wprintf(L"%s\n", usage_strings[i]);
71 }
72 wprintf(L"\n");
73 return 0;
74 }
75
76 int QueryDevices()
77 {
78 WCHAR buffer[20240];
79 int len;
80 WCHAR* ptr = buffer;
81
82 *ptr = L'\0';
83 if (QueryDosDeviceW(NULL, buffer, ARRAYSIZE(buffer)))
84 {
85 while (*ptr != L'\0')
86 {
87 len = wcslen(ptr);
88 if (wcsstr(ptr, L"COM"))
89 {
90 wprintf(L" Found serial device - %s\n", ptr);
91 }
92 else if (wcsstr(ptr, L"PRN"))
93 {
94 wprintf(L" Found printer device - %s\n", ptr);
95 }
96 else if (wcsstr(ptr, L"LPT"))
97 {
98 wprintf(L" Found parallel device - %s\n", ptr);
99 }
100 else
101 {
102 // wprintf(L" Found other device - %s\n", ptr);
103 }
104 ptr += (len+1);
105 }
106 }
107 else
108 {
109 wprintf(L" ERROR: QueryDosDeviceW(...) failed: 0x%lx\n", GetLastError());
110 }
111 return 1;
112 }
113
114 int ShowParallelStatus(int nPortNum)
115 {
116 WCHAR buffer[250];
117 WCHAR szPortName[MAX_PORTNAME_LEN];
118
119 swprintf(szPortName, L"LPT%d", nPortNum);
120 wprintf(L"\nStatus for device LPT%d:\n", nPortNum);
121 wprintf(L"-----------------------\n");
122 if (QueryDosDeviceW(szPortName, buffer, ARRAYSIZE(buffer)))
123 {
124 WCHAR* ptr = wcsrchr(buffer, L'\\');
125 if (ptr != NULL)
126 {
127 if (0 == wcscmp(szPortName, ++ptr))
128 {
129 wprintf(L" Printer output is not being rerouted.\n");
130 }
131 else
132 {
133 wprintf(L" Printer output is being rerouted to serial port %s\n", ptr);
134 }
135 return 0;
136 }
137 else
138 {
139 wprintf(L" QueryDosDeviceW(%s) returned unrecognised form %s.\n", szPortName, buffer);
140 }
141 }
142 else
143 {
144 wprintf(L" ERROR: QueryDosDeviceW(%s) failed: 0x%lx\n", szPortName, GetLastError());
145 }
146 return 1;
147 }
148
149 int ShowConsoleStatus()
150 {
151 DWORD dwKbdDelay;
152 DWORD dwKbdSpeed;
153 CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo;
154 HANDLE hConsoleOutput = GetStdHandle(STD_OUTPUT_HANDLE);
155
156 wprintf(L"\nStatus for device CON:\n");
157 wprintf(L"-----------------------\n");
158 if (GetConsoleScreenBufferInfo(hConsoleOutput, &ConsoleScreenBufferInfo))
159 {
160 wprintf(L" Lines: %d\n", ConsoleScreenBufferInfo.dwSize.Y);
161 wprintf(L" Columns: %d\n", ConsoleScreenBufferInfo.dwSize.X);
162 }
163 if (SystemParametersInfo(SPI_GETKEYBOARDDELAY, 0, &dwKbdDelay, 0))
164 {
165 wprintf(L" Keyboard delay: %ld\n", dwKbdDelay);
166 }
167 if (SystemParametersInfo(SPI_GETKEYBOARDSPEED, 0, &dwKbdSpeed, 0))
168 {
169 wprintf(L" Keyboard rate: %ld\n", dwKbdSpeed);
170 }
171 wprintf(L" Code page: %d\n", GetConsoleOutputCP());
172 return 0;
173 }
174
175 static
176 BOOL SerialPortQuery(int nPortNum, LPDCB pDCB, LPCOMMTIMEOUTS pCommTimeouts, BOOL bWrite)
177 {
178 BOOL result;
179 HANDLE hPort;
180 WCHAR szPortName[MAX_PORTNAME_LEN];
181
182 ASSERT(pDCB);
183 ASSERT(pCommTimeouts);
184
185 swprintf(szPortName, L"COM%d", nPortNum);
186 hPort = CreateFileW(szPortName,
187 GENERIC_READ | GENERIC_WRITE,
188 0, // exclusive
189 NULL, // sec attr
190 OPEN_EXISTING,
191 0, // no attributes
192 NULL); // no template
193
194 if (hPort == INVALID_HANDLE_VALUE)
195 {
196 wprintf(L"Illegal device name - %s\n", szPortName);
197 wprintf(L"Last error = 0x%lx\n", GetLastError());
198 return FALSE;
199 }
200
201 result = bWrite ? SetCommState(hPort, pDCB)
202 : GetCommState(hPort, pDCB);
203 if (!result)
204 {
205 wprintf(L"Failed to %s the status for device COM%d:\n", bWrite ? L"set" : L"get", nPortNum);
206 CloseHandle(hPort);
207 return FALSE;
208 }
209
210 result = bWrite ? SetCommTimeouts(hPort, pCommTimeouts)
211 : GetCommTimeouts(hPort, pCommTimeouts);
212 if (!result)
213 {
214 wprintf(L"Failed to %s Timeout status for device COM%d:\n", bWrite ? L"set" : L"get", nPortNum);
215 CloseHandle(hPort);
216 return FALSE;
217 }
218 CloseHandle(hPort);
219 return TRUE;
220 }
221
222 int ShowSerialStatus(int nPortNum)
223 {
224 DCB dcb;
225 COMMTIMEOUTS CommTimeouts;
226
227 if (!SerialPortQuery(nPortNum, &dcb, &CommTimeouts, FALSE))
228 {
229 return 1;
230 }
231 if (dcb.Parity >= ARRAYSIZE(parity_strings))
232 {
233 wprintf(L"ERROR: Invalid value for Parity Bits %d:\n", dcb.Parity);
234 dcb.Parity = 0;
235 }
236 if (dcb.StopBits >= ARRAYSIZE(stopbit_strings))
237 {
238 wprintf(L"ERROR: Invalid value for Stop Bits %d:\n", dcb.StopBits);
239 dcb.StopBits = 0;
240 }
241 wprintf(L"\nStatus for device COM%d:\n", nPortNum);
242 wprintf(L"-----------------------\n");
243 wprintf(L" Baud: %ld\n", dcb.BaudRate);
244 wprintf(L" Parity: %s\n", parity_strings[dcb.Parity]);
245 wprintf(L" Data Bits: %d\n", dcb.ByteSize);
246 wprintf(L" Stop Bits: %s\n", stopbit_strings[dcb.StopBits]);
247 wprintf(L" Timeout: %s\n", CommTimeouts.ReadIntervalTimeout ? L"ON" : L"OFF");
248 wprintf(L" XON/XOFF: %s\n", dcb.fOutX ? L"ON" : L"OFF");
249 wprintf(L" CTS handshaking: %s\n", dcb.fOutxCtsFlow ? L"ON" : L"OFF");
250 wprintf(L" DSR handshaking: %s\n", dcb.fOutxDsrFlow ? L"ON" : L"OFF");
251 wprintf(L" DSR sensitivity: %s\n", dcb.fDsrSensitivity ? L"ON" : L"OFF");
252 wprintf(L" DTR circuit: %s\n", control_strings[dcb.fDtrControl]);
253 wprintf(L" RTS circuit: %s\n", control_strings[dcb.fRtsControl]);
254 return 0;
255 }
256
257 int SetParallelState(int nPortNum)
258 {
259 WCHAR szPortName[MAX_PORTNAME_LEN];
260 WCHAR szTargetPath[MAX_PORTNAME_LEN];
261
262 swprintf(szPortName, L"LPT%d", nPortNum);
263 swprintf(szTargetPath, L"COM%d", nPortNum);
264 if (!DefineDosDeviceW(DDD_REMOVE_DEFINITION, szPortName, szTargetPath))
265 {
266 wprintf(L"SetParallelState(%d) - DefineDosDevice(%s) failed: 0x%lx\n", nPortNum, szPortName, GetLastError());
267 }
268 return 0;
269 }
270
271 /*
272 \??\COM1
273 \Device\NamedPipe\Spooler\LPT1
274 BOOL DefineDosDevice(
275 DWORD dwFlags, // options
276 LPCTSTR lpDeviceName, // device name
277 LPCTSTR lpTargetPath // path string
278 );
279 DWORD QueryDosDevice(
280 LPCTSTR lpDeviceName, // MS-DOS device name string
281 LPTSTR lpTargetPath, // query results buffer
282 DWORD ucchMax // maximum size of buffer
283 );
284 */
285
286 int SetConsoleState()
287 {
288 /*
289 "Select code page: MODE CON[:] CP SELECT=yyy",
290 "Code page status: MODE CON[:] CP [/STATUS]",
291 "Display mode: MODE CON[:] [COLS=c] [LINES=n]",
292 "Typematic rate: MODE CON[:] [RATE=r DELAY=d]",
293 */
294 return 0;
295 }
296
297 static
298 int ExtractModeSerialParams(const WCHAR* param)
299 {
300 if (wcsstr(param, L"OFF"))
301 return 0;
302 else if (wcsstr(param, L"ON"))
303 return 1;
304 else if (wcsstr(param, L"HS"))
305 return 2;
306 else if (wcsstr(param, L"TG"))
307 return 3;
308
309 return -1;
310 }
311
312 int SetSerialState(int nPortNum, int args, WCHAR *argv[])
313 {
314 int arg;
315 int value;
316 DCB dcb;
317 COMMTIMEOUTS CommTimeouts;
318 WCHAR buf[MAX_COMPARAM_LEN+1];
319
320 if (SerialPortQuery(nPortNum, &dcb, &CommTimeouts, FALSE))
321 {
322 for (arg = 2; arg < args; arg++)
323 {
324 if (wcslen(argv[arg]) > MAX_COMPARAM_LEN)
325 {
326 wprintf(L"Invalid parameter (too long) - %s\n", argv[arg]);
327 return 1;
328 }
329 wcscpy(buf, argv[arg]);
330 _wcslwr(buf);
331 if (wcsstr(buf, L"baud="))
332 {
333 wscanf(buf+5, L"%lu", &dcb.BaudRate);
334 }
335 else if (wcsstr(buf, L"parity="))
336 {
337 if (wcschr(buf, L'D'))
338 dcb.Parity = 1;
339 else if (wcschr(buf, L'V'))
340 dcb.Parity = 2;
341 else if (wcschr(buf, L'M'))
342 dcb.Parity = 3;
343 else if (wcschr(buf, L'S'))
344 dcb.Parity = 4;
345 else
346 dcb.Parity = 0;
347 }
348 else if (wcsstr(buf, L"data="))
349 {
350 wscanf(buf+5, L"%lu", &dcb.ByteSize);
351 }
352 else if (wcsstr(buf, L"stop="))
353 {
354 if (wcschr(buf, L'5'))
355 dcb.StopBits = 1;
356 else if (wcschr(buf, L'2'))
357 dcb.StopBits = 2;
358 else
359 dcb.StopBits = 0;
360 }
361 else if (wcsstr(buf, L"to=")) // to=on|off
362 {
363 value = ExtractModeSerialParams(buf);
364 if (value != -1)
365 {
366 }
367 else
368 {
369 goto invalid_serial_parameter;
370 }
371 }
372 else if (wcsstr(buf, L"xon=")) // xon=on|off
373 {
374 value = ExtractModeSerialParams(buf);
375 if (value != -1)
376 {
377 dcb.fOutX = value;
378 dcb.fInX = value;
379 }
380 else
381 {
382 goto invalid_serial_parameter;
383 }
384 }
385 else if (wcsstr(buf, L"odsr=")) // odsr=on|off
386 {
387 value = ExtractModeSerialParams(buf);
388 if (value != -1)
389 {
390 dcb.fOutxDsrFlow = value;
391 }
392 else
393 {
394 goto invalid_serial_parameter;
395 }
396 }
397 else if (wcsstr(buf, L"octs=")) // octs=on|off
398 {
399 value = ExtractModeSerialParams(buf);
400 if (value != -1)
401 {
402 dcb.fOutxCtsFlow = value;
403 }
404 else
405 {
406 goto invalid_serial_parameter;
407 }
408 }
409 else if (wcsstr(buf, L"dtr=")) // dtr=on|off|hs
410 {
411 value = ExtractModeSerialParams(buf);
412 if (value != -1)
413 {
414 dcb.fDtrControl = value;
415 }
416 else
417 {
418 goto invalid_serial_parameter;
419 }
420 }
421 else if (wcsstr(buf, L"rts=")) // rts=on|off|hs|tg
422 {
423 value = ExtractModeSerialParams(buf);
424 if (value != -1)
425 {
426 dcb.fRtsControl = value;
427 }
428 else
429 {
430 goto invalid_serial_parameter;
431 }
432 }
433 else if (wcsstr(buf, L"idsr=")) // idsr=on|off
434 {
435 value = ExtractModeSerialParams(buf);
436 if (value != -1)
437 {
438 dcb.fDsrSensitivity = value;
439 }
440 else
441 {
442 goto invalid_serial_parameter;
443 }
444 }
445 else
446 {
447 invalid_serial_parameter:;
448 wprintf(L"Invalid parameter - %s\n", buf);
449 return 1;
450 }
451 }
452 SerialPortQuery(nPortNum, &dcb, &CommTimeouts, TRUE);
453 }
454 return 0;
455 }
456
457 int find_portnum(const WCHAR* cmdverb)
458 {
459 int portnum = -1;
460
461 if (cmdverb[3] >= L'0' && cmdverb[3] <= L'9')
462 {
463 portnum = cmdverb[3] - L'0';
464 if (cmdverb[4] >= L'0' && cmdverb[4] <= L'9')
465 {
466 portnum *= 10;
467 portnum += cmdverb[4] - L'0';
468 }
469 }
470 return portnum;
471 }
472
473 int wmain(int argc, WCHAR* argv[])
474 {
475 int nPortNum;
476 WCHAR param1[MAX_COMPARAM_LEN+1];
477 WCHAR param2[MAX_COMPARAM_LEN+1];
478
479 if (argc > 1)
480 {
481 if (wcslen(argv[1]) > MAX_COMPARAM_LEN)
482 {
483 wprintf(L"Invalid parameter (too long) - %s\n", argv[1]);
484 return 1;
485 }
486 wcscpy(param1, argv[1]);
487 _wcslwr(param1);
488 if (argc > 2)
489 {
490 if (wcslen(argv[2]) > MAX_COMPARAM_LEN)
491 {
492 wprintf(L"Invalid parameter (too long) - %s\n", argv[2]);
493 return 1;
494 }
495 wcscpy(param2, argv[2]);
496 _wcslwr(param2);
497 }
498 else
499 {
500 param2[0] = L'\0';
501 }
502 if (wcsstr(param1, L"/?") || wcsstr(param1, L"-?"))
503 {
504 return Usage();
505 }
506 else if (wcsstr(param1, L"/status"))
507 {
508 goto show_status;
509 }
510 else if (wcsstr(param1, L"lpt"))
511 {
512 nPortNum = find_portnum(param1);
513 if (nPortNum != -1)
514 return ShowParallelStatus(nPortNum);
515 }
516 else if (wcsstr(param1, L"con"))
517 {
518 return ShowConsoleStatus();
519 }
520 else if (wcsstr(param1, L"com"))
521 {
522 nPortNum = find_portnum(param1);
523 if (nPortNum != -1)
524 {
525 if (param2[0] == L'\0' || wcsstr(param2, L"/status"))
526 {
527 return ShowSerialStatus(nPortNum);
528 }
529 else
530 {
531 return SetSerialState(nPortNum, argc, argv);
532 }
533 }
534 }
535 wprintf(L"Invalid parameter - %s\n", param1);
536 return 1;
537 }
538 else
539 {
540 show_status:;
541
542 QueryDevices();
543 /*
544 ShowParallelStatus(1);
545 for (nPortNum = 0; nPortNum < MAX_COMPORT_NUM; nPortNum++)
546 {
547 ShowSerialStatus(nPortNum + 1);
548 }
549 ShowConsoleStatus();
550 */
551 }
552 return 0;
553 }