aboutsummaryrefslogtreecommitdiff
path: root/src/libs/dutil/WixToolset.DUtil/conutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/conutil.cpp')
-rw-r--r--src/libs/dutil/WixToolset.DUtil/conutil.cpp673
1 files changed, 673 insertions, 0 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/conutil.cpp b/src/libs/dutil/WixToolset.DUtil/conutil.cpp
new file mode 100644
index 00000000..33e1b59a
--- /dev/null
+++ b/src/libs/dutil/WixToolset.DUtil/conutil.cpp
@@ -0,0 +1,673 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3#include "precomp.h"
4
5
6// Exit macros
7#define ConExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_CONUTIL, x, s, __VA_ARGS__)
8#define ConExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_CONUTIL, x, s, __VA_ARGS__)
9#define ConExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_CONUTIL, x, s, __VA_ARGS__)
10#define ConExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_CONUTIL, x, s, __VA_ARGS__)
11#define ConExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_CONUTIL, x, s, __VA_ARGS__)
12#define ConExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_CONUTIL, x, s, __VA_ARGS__)
13#define ConExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_CONUTIL, p, x, e, s, __VA_ARGS__)
14#define ConExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_CONUTIL, p, x, s, __VA_ARGS__)
15#define ConExitOnNullDebugTrace(p, x, e, s, ...) ExitOnNullDebugTraceSource(DUTIL_SOURCE_CONUTIL, p, x, e, s, __VA_ARGS__)
16#define ConExitOnInvalidHandleWithLastError(p, x, s, ...) ExitOnInvalidHandleWithLastErrorSource(DUTIL_SOURCE_CONUTIL, p, x, s, __VA_ARGS__)
17#define ConExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_CONUTIL, e, x, s, __VA_ARGS__)
18#define ConExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_CONUTIL, g, x, s, __VA_ARGS__)
19
20
21static HANDLE vhStdIn = INVALID_HANDLE_VALUE;
22static HANDLE vhStdOut = INVALID_HANDLE_VALUE;
23static BOOL vfConsoleIn = FALSE;
24static BOOL vfConsoleOut = FALSE;
25static CONSOLE_SCREEN_BUFFER_INFO vcsbiInfo;
26
27
28extern "C" HRESULT DAPI ConsoleInitialize()
29{
30 Assert(INVALID_HANDLE_VALUE == vhStdOut);
31 HRESULT hr = S_OK;
32 UINT er;
33
34 vhStdIn = ::GetStdHandle(STD_INPUT_HANDLE);
35 if (INVALID_HANDLE_VALUE == vhStdIn)
36 {
37 ConExitOnLastError(hr, "failed to open stdin");
38 }
39
40 vhStdOut = ::GetStdHandle(STD_OUTPUT_HANDLE);
41 if (INVALID_HANDLE_VALUE == vhStdOut)
42 {
43 ConExitOnLastError(hr, "failed to open stdout");
44 }
45
46 // check if we have a std in on the console
47 if (::GetConsoleScreenBufferInfo(vhStdIn, &vcsbiInfo))
48 {
49 vfConsoleIn = TRUE;
50 }
51 else
52 {
53 er = ::GetLastError();
54 if (ERROR_INVALID_HANDLE == er)
55 {
56 vfConsoleIn= FALSE;
57 hr = S_OK;
58 }
59 else
60 {
61 ConExitOnWin32Error(er, hr, "failed to get input console screen buffer info");
62 }
63 }
64
65 if (::GetConsoleScreenBufferInfo(vhStdOut, &vcsbiInfo))
66 {
67 vfConsoleOut = TRUE;
68 }
69 else // no console
70 {
71 memset(&vcsbiInfo, 0, sizeof(vcsbiInfo));
72 er = ::GetLastError();
73 if (ERROR_INVALID_HANDLE == er)
74 {
75 vfConsoleOut = FALSE;
76 hr = S_OK;
77 }
78 else
79 {
80 ConExitOnWin32Error(er, hr, "failed to get output console screen buffer info");
81 }
82 }
83
84LExit:
85 if (FAILED(hr))
86 {
87 if (INVALID_HANDLE_VALUE != vhStdOut)
88 {
89 ::CloseHandle(vhStdOut);
90 }
91
92 if (INVALID_HANDLE_VALUE != vhStdIn && vhStdOut != vhStdIn)
93 {
94 ::CloseHandle(vhStdIn);
95 }
96
97 vhStdOut = INVALID_HANDLE_VALUE;
98 vhStdIn = INVALID_HANDLE_VALUE;
99 }
100
101 return hr;
102}
103
104
105extern "C" void DAPI ConsoleUninitialize()
106{
107 BOOL fOutEqualsIn = vhStdOut == vhStdIn;
108
109 memset(&vcsbiInfo, 0, sizeof(vcsbiInfo));
110
111 if (INVALID_HANDLE_VALUE != vhStdOut)
112 {
113 ::CloseHandle(vhStdOut);
114 }
115
116 if (INVALID_HANDLE_VALUE != vhStdIn && !fOutEqualsIn)
117 {
118 ::CloseHandle(vhStdIn);
119 }
120
121 vhStdOut = INVALID_HANDLE_VALUE;
122 vhStdIn = INVALID_HANDLE_VALUE;
123}
124
125
126extern "C" void DAPI ConsoleGreen()
127{
128 AssertSz(INVALID_HANDLE_VALUE != vhStdOut, "ConsoleInitialize() has not been called");
129 if (vfConsoleOut)
130 {
131 ::SetConsoleTextAttribute(vhStdOut, FOREGROUND_GREEN | FOREGROUND_INTENSITY);
132 }
133}
134
135
136extern "C" void DAPI ConsoleRed()
137{
138 AssertSz(INVALID_HANDLE_VALUE != vhStdOut, "ConsoleInitialize() has not been called");
139 if (vfConsoleOut)
140 {
141 ::SetConsoleTextAttribute(vhStdOut, FOREGROUND_RED | FOREGROUND_INTENSITY);
142 }
143}
144
145
146extern "C" void DAPI ConsoleYellow()
147{
148 AssertSz(INVALID_HANDLE_VALUE != vhStdOut, "ConsoleInitialize() has not been called");
149 if (vfConsoleOut)
150 {
151 ::SetConsoleTextAttribute(vhStdOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY);
152 }
153}
154
155
156extern "C" void DAPI ConsoleNormal()
157{
158 AssertSz(INVALID_HANDLE_VALUE != vhStdOut, "ConsoleInitialize() has not been called");
159 if (vfConsoleOut)
160 {
161 ::SetConsoleTextAttribute(vhStdOut, vcsbiInfo.wAttributes);
162 }
163}
164
165
166/********************************************************************
167 ConsoleWrite - full color printfA without libc
168
169 NOTE: use FormatMessage formatting ("%1" or "%1!d!") not plain printf formatting ("%ls" or "%d")
170 assumes already in normal color and resets the screen to normal color
171********************************************************************/
172extern "C" HRESULT DAPI ConsoleWrite(
173 CONSOLE_COLOR cc,
174 __in_z __format_string LPCSTR szFormat,
175 ...
176 )
177{
178 AssertSz(INVALID_HANDLE_VALUE != vhStdOut, "ConsoleInitialize() has not been called");
179 HRESULT hr = S_OK;
180 LPSTR pszOutput = NULL;
181 DWORD cchOutput = 0;
182 DWORD cbWrote = 0;
183 DWORD cbTotal = 0;
184
185 // set the color
186 switch (cc)
187 {
188 case CONSOLE_COLOR_NORMAL: break; // do nothing
189 case CONSOLE_COLOR_RED: ConsoleRed(); break;
190 case CONSOLE_COLOR_YELLOW: ConsoleYellow(); break;
191 case CONSOLE_COLOR_GREEN: ConsoleGreen(); break;
192 }
193
194 va_list args;
195 va_start(args, szFormat);
196 hr = StrAnsiAllocFormattedArgs(&pszOutput, szFormat, args);
197 va_end(args);
198 ConExitOnFailure(hr, "failed to format message: \"%s\"", szFormat);
199
200 cchOutput = lstrlenA(pszOutput);
201 while (cbTotal < (sizeof(*pszOutput) * cchOutput))
202 {
203 if (!::WriteFile(vhStdOut, reinterpret_cast<BYTE*>(pszOutput) + cbTotal, cchOutput * sizeof(*pszOutput) - cbTotal, &cbWrote, NULL))
204 {
205 ConExitOnLastError(hr, "failed to write output to console: %s", pszOutput);
206 }
207
208 cbTotal += cbWrote;
209 }
210
211 // reset the color to normal
212 if (CONSOLE_COLOR_NORMAL != cc)
213 {
214 ConsoleNormal();
215 }
216
217LExit:
218 ReleaseStr(pszOutput);
219 return hr;
220}
221
222
223/********************************************************************
224 ConsoleWriteLine - full color printfA plus newline without libc
225
226 NOTE: use FormatMessage formatting ("%1" or "%1!d!") not plain printf formatting ("%ls" or "%d")
227 assumes already in normal color and resets the screen to normal color
228********************************************************************/
229extern "C" HRESULT DAPI ConsoleWriteLine(
230 CONSOLE_COLOR cc,
231 __in_z __format_string LPCSTR szFormat,
232 ...
233 )
234{
235 AssertSz(INVALID_HANDLE_VALUE != vhStdOut, "ConsoleInitialize() has not been called");
236 HRESULT hr = S_OK;
237 LPSTR pszOutput = NULL;
238 DWORD cchOutput = 0;
239 DWORD cbWrote = 0;
240 DWORD cbTotal = 0;
241 LPCSTR szNewLine = "\r\n";
242
243 // set the color
244 switch (cc)
245 {
246 case CONSOLE_COLOR_NORMAL: break; // do nothing
247 case CONSOLE_COLOR_RED: ConsoleRed(); break;
248 case CONSOLE_COLOR_YELLOW: ConsoleYellow(); break;
249 case CONSOLE_COLOR_GREEN: ConsoleGreen(); break;
250 }
251
252 va_list args;
253 va_start(args, szFormat);
254 hr = StrAnsiAllocFormattedArgs(&pszOutput, szFormat, args);
255 va_end(args);
256 ConExitOnFailure(hr, "failed to format message: \"%s\"", szFormat);
257
258 //
259 // write the string
260 //
261 cchOutput = lstrlenA(pszOutput);
262 while (cbTotal < (sizeof(*pszOutput) * cchOutput))
263 {
264 if (!::WriteFile(vhStdOut, reinterpret_cast<BYTE*>(pszOutput) + cbTotal, cchOutput * sizeof(*pszOutput) - cbTotal, &cbWrote, NULL))
265 ConExitOnLastError(hr, "failed to write output to console: %s", pszOutput);
266
267 cbTotal += cbWrote;
268 }
269
270 //
271 // write the newline
272 //
273 if (!::WriteFile(vhStdOut, reinterpret_cast<const BYTE*>(szNewLine), 2, &cbWrote, NULL))
274 {
275 ConExitOnLastError(hr, "failed to write newline to console");
276 }
277
278 // reset the color to normal
279 if (CONSOLE_COLOR_NORMAL != cc)
280 {
281 ConsoleNormal();
282 }
283
284LExit:
285 ReleaseStr(pszOutput);
286 return hr;
287}
288
289
290/********************************************************************
291 ConsoleWriteError - display an error to the screen
292
293 NOTE: use FormatMessage formatting ("%1" or "%1!d!") not plain printf formatting ("%s" or "%d")
294********************************************************************/
295HRESULT ConsoleWriteError(
296 HRESULT hrError,
297 CONSOLE_COLOR cc,
298 __in_z __format_string LPCSTR szFormat,
299 ...
300 )
301{
302 HRESULT hr = S_OK;
303 LPSTR pszMessage = NULL;
304
305 va_list args;
306 va_start(args, szFormat);
307 hr = StrAnsiAllocFormattedArgs(&pszMessage, szFormat, args);
308 va_end(args);
309 ConExitOnFailure(hr, "failed to format error message: \"%s\"", szFormat);
310
311 if (FAILED(hrError))
312 {
313 hr = ConsoleWriteLine(cc, "Error 0x%x: %s", hrError, pszMessage);
314 }
315 else
316 {
317 hr = ConsoleWriteLine(cc, "Error: %s", pszMessage);
318 }
319
320LExit:
321 ReleaseStr(pszMessage);
322 return hr;
323}
324
325
326/********************************************************************
327 ConsoleReadW - get console input without libc
328
329 NOTE: only supports reading ANSI characters
330********************************************************************/
331extern "C" HRESULT DAPI ConsoleReadW(
332 __deref_out_z LPWSTR* ppwzBuffer
333 )
334{
335 AssertSz(INVALID_HANDLE_VALUE != vhStdIn, "ConsoleInitialize() has not been called");
336 Assert(ppwzBuffer);
337
338 HRESULT hr = S_OK;
339 LPSTR psz = NULL;
340 DWORD cch = 0;
341 DWORD cchRead = 0;
342 DWORD cchTotalRead = 0;
343
344 cch = 64;
345 hr = StrAnsiAlloc(&psz, cch);
346 ConExitOnFailure(hr, "failed to allocate memory to read from console");
347
348 // loop until we read the \r\n from the console
349 for (;;)
350 {
351 // read one character at a time, since that seems to be the only way to make this work
352 if (!::ReadFile(vhStdIn, psz + cchTotalRead, 1, &cchRead, NULL))
353 ConExitOnLastError(hr, "failed to read string from console");
354
355 cchTotalRead += cchRead;
356 if (1 < cchTotalRead && '\r' == psz[cchTotalRead - 2] || '\n' == psz[cchTotalRead - 1])
357 {
358 psz[cchTotalRead - 2] = '\0'; // chop off the \r\n
359 break;
360 }
361 else if (0 == cchRead) // nothing more was read
362 {
363 psz[cchTotalRead] = '\0'; // null termintate and bail
364 break;
365 }
366
367 if (cchTotalRead == cch)
368 {
369 cch *= 2; // double everytime we run out of space
370 hr = StrAnsiAlloc(&psz, cch);
371 ConExitOnFailure(hr, "failed to allocate memory to read from console");
372 }
373 }
374
375 hr = StrAllocStringAnsi(ppwzBuffer, psz, 0, CP_ACP);
376
377LExit:
378 ReleaseStr(psz);
379 return hr;
380}
381
382
383/********************************************************************
384 ConsoleReadNonBlockingW - Read from the console without blocking
385 Won't work for redirected files (exe < txtfile), but will work for stdin redirected to
386 an anonymous or named pipe
387
388 if (fReadLine), stop reading immediately when \r\n is found
389*********************************************************************/
390extern "C" HRESULT DAPI ConsoleReadNonBlockingW(
391 __deref_out_ecount_opt(*pcchSize) LPWSTR* ppwzBuffer,
392 __out DWORD* pcchSize,
393 BOOL fReadLine
394 )
395{
396 Assert(INVALID_HANDLE_VALUE != vhStdIn && pcchSize);
397 HRESULT hr = S_OK;
398
399 LPSTR psz = NULL;
400
401 ConExitOnNull(ppwzBuffer, hr, E_INVALIDARG, "Failed to read from console because buffer was not provided");
402
403 DWORD dwRead;
404 DWORD dwNumInput;
405
406 DWORD cchTotal = 0;
407 DWORD cch = 8;
408
409 DWORD cchRead = 0;
410 DWORD cchTotalRead = 0;
411
412 DWORD dwIndex = 0;
413 DWORD er;
414
415 INPUT_RECORD ir;
416 WCHAR chIn;
417
418 *ppwzBuffer = NULL;
419 *pcchSize = 0;
420
421 // If we really have a handle to stdin, and not the end of a pipe
422 if (!PeekNamedPipe(vhStdIn, NULL, 0, NULL, &dwRead, NULL))
423 {
424 er = ::GetLastError();
425 if (ERROR_INVALID_HANDLE != er)
426 {
427 ExitFunction1(hr = HRESULT_FROM_WIN32(er));
428 }
429
430 if (!GetNumberOfConsoleInputEvents(vhStdIn, &dwRead))
431 {
432 ConExitOnLastError(hr, "failed to peek at console input");
433 }
434
435 if (0 == dwRead)
436 {
437 ExitFunction1(hr = S_FALSE);
438 }
439
440 for (/* dwRead from num of input events */; dwRead > 0; dwRead--)
441 {
442 if (!ReadConsoleInputW(vhStdIn, &ir, 1, &dwNumInput))
443 {
444 ConExitOnLastError(hr, "Failed to read input from console");
445 }
446
447 // If what we have is a KEY_EVENT, and that event signifies keyUp, we're interested
448 if (KEY_EVENT == ir.EventType && FALSE == ir.Event.KeyEvent.bKeyDown)
449 {
450 chIn = ir.Event.KeyEvent.uChar.UnicodeChar;
451
452 if (0 == cchTotal)
453 {
454 cchTotal = cch;
455 cch *= 2;
456 StrAlloc(ppwzBuffer, cch);
457 }
458
459 (*ppwzBuffer)[dwIndex] = chIn;
460
461 if (fReadLine && (L'\r' == (*ppwzBuffer)[dwIndex - 1] && L'\n' == (*ppwzBuffer)[dwIndex]))
462 {
463 *ppwzBuffer[dwIndex - 1] = L'\0';
464 dwIndex -= 1;
465 break;
466 }
467
468 ++dwIndex;
469 cchTotal--;
470 }
471 }
472
473 *pcchSize = dwIndex;
474 }
475 else
476 {
477 // otherwise, the peek worked, and we have the end of a pipe
478 if (0 == dwRead)
479 ExitFunction1(hr = S_FALSE);
480
481 cch = 8;
482 hr = StrAnsiAlloc(&psz, cch);
483 ConExitOnFailure(hr, "failed to allocate memory to read from console");
484
485 for (/*dwRead from PeekNamedPipe*/; dwRead > 0; dwRead--)
486 {
487 // read one character at a time, since that seems to be the only way to make this work
488 if (!::ReadFile(vhStdIn, psz + cchTotalRead, 1, &cchRead, NULL))
489 {
490 ConExitOnLastError(hr, "failed to read string from console");
491 }
492
493 cchTotalRead += cchRead;
494 if (fReadLine && '\r' == psz[cchTotalRead - 1] && '\n' == psz[cchTotalRead])
495 {
496 psz[cchTotalRead - 1] = '\0'; // chop off the \r\n
497 cchTotalRead -= 1;
498 break;
499 }
500 else if (0 == cchRead) // nothing more was read
501 {
502 psz[cchTotalRead] = '\0'; // null termintate and bail
503 break;
504 }
505
506 if (cchTotalRead == cch)
507 {
508 cch *= 2; // double everytime we run out of space
509 hr = StrAnsiAlloc(&psz, cch);
510 ConExitOnFailure(hr, "failed to allocate memory to read from console");
511 }
512 }
513
514 *pcchSize = cchTotalRead;
515 hr = StrAllocStringAnsi(ppwzBuffer, psz, cchTotalRead, CP_ACP);
516 }
517
518LExit:
519 ReleaseStr(psz);
520
521 return hr;
522}
523
524
525/********************************************************************
526 ConsoleReadStringA - get console input without libc
527
528*********************************************************************/
529extern "C" HRESULT DAPI ConsoleReadStringA(
530 __deref_inout_ecount_part(cchCharBuffer,*pcchNumCharReturn) LPSTR* ppszCharBuffer,
531 CONST DWORD cchCharBuffer,
532 __out DWORD* pcchNumCharReturn
533 )
534{
535 AssertSz(INVALID_HANDLE_VALUE != vhStdIn, "ConsoleInitialize() has not been called");
536 HRESULT hr = S_OK;
537 if (ppszCharBuffer && (pcchNumCharReturn || cchCharBuffer < 2))
538 {
539 DWORD iRead = 1;
540 DWORD iReadCharTotal = 0;
541 if (ppszCharBuffer && *ppszCharBuffer == NULL)
542 {
543 do
544 {
545 hr = StrAnsiAlloc(ppszCharBuffer, cchCharBuffer * iRead);
546 ConExitOnFailure(hr, "failed to allocate memory for ConsoleReadStringW");
547 // ReadConsoleW will not return until <Return>, the last two chars are 13 and 10.
548 if (!::ReadConsoleA(vhStdIn, *ppszCharBuffer + iReadCharTotal, cchCharBuffer, pcchNumCharReturn, NULL) || *pcchNumCharReturn == 0)
549 {
550 ConExitOnLastError(hr, "failed to read string from console");
551 }
552 iReadCharTotal += *pcchNumCharReturn;
553 iRead += 1;
554 }
555 while((*ppszCharBuffer)[iReadCharTotal - 1] != 10 || (*ppszCharBuffer)[iReadCharTotal - 2] != 13);
556 *pcchNumCharReturn = iReadCharTotal;
557 }
558 else
559 {
560 if (!::ReadConsoleA(vhStdIn, *ppszCharBuffer, cchCharBuffer, pcchNumCharReturn, NULL) ||
561 *pcchNumCharReturn > cchCharBuffer || *pcchNumCharReturn == 0)
562 {
563 ConExitOnLastError(hr, "failed to read string from console");
564 }
565 if ((*ppszCharBuffer)[*pcchNumCharReturn - 1] != 10 ||
566 (*ppszCharBuffer)[*pcchNumCharReturn - 2] != 13)
567 {
568 // need read more
569 hr = ERROR_MORE_DATA;
570 }
571 }
572 }
573 else
574 {
575 hr = E_INVALIDARG;
576 }
577
578LExit:
579 return hr;
580}
581
582/********************************************************************
583 ConsoleReadStringW - get console input without libc
584
585*********************************************************************/
586extern "C" HRESULT DAPI ConsoleReadStringW(
587 __deref_inout_ecount_part(cchCharBuffer,*pcchNumCharReturn) LPWSTR* ppwzCharBuffer,
588 const DWORD cchCharBuffer,
589 __out DWORD* pcchNumCharReturn
590 )
591{
592 AssertSz(INVALID_HANDLE_VALUE != vhStdIn, "ConsoleInitialize() has not been called");
593 HRESULT hr = S_OK;
594 if (ppwzCharBuffer && (pcchNumCharReturn || cchCharBuffer < 2))
595 {
596 DWORD iRead = 1;
597 DWORD iReadCharTotal = 0;
598 if (*ppwzCharBuffer == NULL)
599 {
600 do
601 {
602 hr = StrAlloc(ppwzCharBuffer, cchCharBuffer * iRead);
603 ConExitOnFailure(hr, "failed to allocate memory for ConsoleReadStringW");
604 // ReadConsoleW will not return until <Return>, the last two chars are 13 and 10.
605 if (!::ReadConsoleW(vhStdIn, *ppwzCharBuffer + iReadCharTotal, cchCharBuffer, pcchNumCharReturn, NULL) || *pcchNumCharReturn == 0)
606 {
607 ConExitOnLastError(hr, "failed to read string from console");
608 }
609 iReadCharTotal += *pcchNumCharReturn;
610 iRead += 1;
611 }
612 while((*ppwzCharBuffer)[iReadCharTotal - 1] != 10 || (*ppwzCharBuffer)[iReadCharTotal - 2] != 13);
613 *pcchNumCharReturn = iReadCharTotal;
614 }
615 else
616 {
617 if (!::ReadConsoleW(vhStdIn, *ppwzCharBuffer, cchCharBuffer, pcchNumCharReturn, NULL) ||
618 *pcchNumCharReturn > cchCharBuffer || *pcchNumCharReturn == 0)
619 {
620 ConExitOnLastError(hr, "failed to read string from console");
621 }
622 if ((*ppwzCharBuffer)[*pcchNumCharReturn - 1] != 10 ||
623 (*ppwzCharBuffer)[*pcchNumCharReturn - 2] != 13)
624 {
625 // need read more
626 hr = ERROR_MORE_DATA;
627 }
628 }
629 }
630 else
631 {
632 hr = E_INVALIDARG;
633 }
634
635LExit:
636 return hr;
637}
638
639/********************************************************************
640 ConsoleSetReadHidden - set console input no echo
641
642*********************************************************************/
643extern "C" HRESULT DAPI ConsoleSetReadHidden(void)
644{
645 AssertSz(INVALID_HANDLE_VALUE != vhStdIn, "ConsoleInitialize() has not been called");
646 HRESULT hr = S_OK;
647 ::FlushConsoleInputBuffer(vhStdIn);
648 if (!::SetConsoleMode(vhStdIn, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT))
649 {
650 ConExitOnLastError(hr, "failed to set console input mode to be hidden");
651 }
652
653LExit:
654 return hr;
655}
656
657/********************************************************************
658 ConsoleSetReadNormal - reset to echo
659
660*********************************************************************/
661extern "C" HRESULT DAPI ConsoleSetReadNormal(void)
662{
663 AssertSz(INVALID_HANDLE_VALUE != vhStdIn, "ConsoleInitialize() has not been called");
664 HRESULT hr = S_OK;
665 if (!::SetConsoleMode(vhStdIn, ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_MOUSE_INPUT))
666 {
667 ConExitOnLastError(hr, "failed to set console input mode to be normal");
668 }
669
670LExit:
671 return hr;
672}
673