1

I am trying to capture output from cmd.exe when running commands. I am trying to capture Unicode output to support other languages. My code works right now for getting unicode back from built in commands to cmd.exe. Such as Dir. But if I try to run external commands such as "net user" or "ipconfig" it does not output unicode.

I did reading and found out it is due to my pipes being file pipes. Ipconfig.exe determines if it is printing to the console or not. If it is printing to console, it uses WriteFileW and outputs unicode. Else it just prints ANSI and I get ???????? for anything Unicode.

#include <winsock.h>
#include <Windows.h>
#include <stdio.h>

void ExecCmd() {
    HANDLE hPipeRead;
    HANDLE hPipeWrite;
    SECURITY_ATTRIBUTES saAttr = { sizeof(SECURITY_ATTRIBUTES) };
    STARTUPINFO si = { sizeof(STARTUPINFO) };
    PROCESS_INFORMATION pi = { 0 };
    BOOL fSuccess;
    BOOL bProcessEnded = FALSE;
    size_t total = 0;

    saAttr.bInheritHandle = TRUE;
    saAttr.lpSecurityDescriptor = NULL;

    if (!CreatePipe(&hPipeRead, &hPipeWrite, &saAttr, 0)) {
        return;
    }

    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    si.hStdOutput = hPipeWrite;
    si.hStdError = hPipeWrite;
    si.wShowWindow = SW_HIDE; 

    WCHAR k[] = L"cmd.exe /u /c net user";
    fSuccess = CreateProcessW(NULL, k, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
    if (!fSuccess) {
        CloseHandle(hPipeWrite);
        CloseHandle(hPipeRead);
        return;
    }


    for (; !bProcessEnded;) {
        bProcessEnded = WaitForSingleObject(pi.hProcess, 50) == WAIT_OBJECT_0;

        while (TRUE) {
            DWORD dwRead = 0;
            DWORD dwAvail = 0;
            WCHAR *buffer = NULL;

            if (!PeekNamedPipe(hPipeRead, NULL, NULL, NULL, &dwAvail, NULL)) {
                break;
            }

            if (!dwAvail) {
                break;
            }

            buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (dwAvail + 2));
            if (buffer == NULL) {
                break;
            }

            if (!ReadFile(hPipeRead, buffer, dwAvail, &dwRead, NULL) || !dwRead) {
                break;
            }

            total += dwRead;

        }

    }
    CloseHandle(hPipeWrite);
    CloseHandle(hPipeRead);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    return;

} 

int main() {
    ExecCmd();
    return 0;
}

My question is how can I change the way my pipes are getting information back from external commands like ipconfig so that it will support unicode.

Doritos
  • 403
  • 3
  • 16
  • 1
    Is "console pipe" really the right terminology here? I would think you need to actually allocate a new console. I don't know the answer for Windows, but in the Unix world, you would say you need a new *terminal* (or, more likely, *pseudoterminal* or pty). – Daniel Pryden Feb 22 '19 at 15:37
  • 2
    Possibly relevant: https://blogs.msdn.microsoft.com/commandline/2018/08/02/windows-command-line-introducing-the-windows-pseudo-console-conpty/ – Daniel Pryden Feb 22 '19 at 15:39
  • Possibly relevant: https://stackoverflow.com/questions/49454596/cmd-exe-input-output-pipe-redirection-in-unicode – DodgyCodeException Feb 22 '19 at 17:44

0 Answers0