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