CreateProcessW с целью, переданной через стандартный ввод - не удается найти цель - PullRequest
0 голосов
/ 24 декабря 2018
#include <stdio.h>
#include <windows.h>

#pragma warning(disable : 4996)
int main(int argc, wchar_t** argv)
{
    DWORD bytes_read;
    WCHAR* buffer[4096];
    LPWSTR str;
    STARTUPINFO  start_info = { 0 };
    PROCESS_INFORMATION process_info = { 0 };

    ReadFile(GetStdHandle(STD_INPUT_HANDLE), buffer, 4096, &bytes_read, NULL);
    str = malloc(bytes_read);
    memcpy(str, buffer, bytes_read);

    // debug - stdout + file
    wprintf(L"\nTrying to run -> \"%LS\"", str);
    FILE *f = fopen("file.txt", "w");
    fwprintf(f, L"%LS", str);
    fclose(f);

    BOOL result = CreateProcessW(
        NULL,
        str,
        NULL,
        NULL,
        TRUE,
        CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS,
        NULL,
        NULL,
        &start_info,
        &process_info
    );

    if (!result) {
        DWORD err = GetLastError();
        WCHAR *errstr;

        FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
            NULL, err,
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            (LPWSTR)&errstr, 0, NULL
        );

        wprintf(L"\nError -> %ls", errstr);
        return 1;
    }

    return 0;
}

Запуск его приводит к следующему

C:\Users\Admin\source\repos\ConsoleApplication1\Debug                         
λ php -r "echo \"C:\\Windows\\System32\\PING.EXE\0\";"|ConsoleApplication1.exe

Trying to run -> "C:\Windows\System32\PING.EXE"                               
Error -> The system cannot find the file specified.  

Так что, похоже, он использует правильный ввод.Кроме того, в файле file.txt нет ничего подозрительного при просмотре в шестнадцатеричном редакторе

hex dump of a file

При жестком кодировании str, как следует, вместо использования stdin

wchar_t cmd[] = L"C:\\Windows\\System32\\PING.EXE";

Это работает.

Что мне нужно сделать, чтобы заставить CreateProcessW работать с вводом stdin?

1 Ответ

0 голосов
/ 24 декабря 2018
WCHAR* buffer[4096];

Это создаст массив строк символов.Вы просто хотите один широкий буфер символов.

Используйте для тестирования спецификатор формата L"%s":

wprintf(L"%s\n", buffer)

Если возможно, передайте текст Unicode в качестве командной строки, например

php -r "echo \"Test...\0\";"|app.exe Unicode

Текст Unicode можетсодержит наборы символов UTF16.

int main(void)
{
    wprintf(L"GetCommandLineW %s\n", GetCommandLineW());

    DWORD bytes_read = 0;
    char buffer[4096] = { 0 };
    ReadFile(GetStdHandle(STD_INPUT_HANDLE), buffer,
        sizeof(buffer), &bytes_read, NULL);

    int codepage = CP_UTF8;//or CP_ACP
    int wlen = MultiByteToWideChar(codepage, 0, buffer, -1, 0, 0);
    wchar_t *wstr = malloc(wlen * 2);
    MultiByteToWideChar(codepage, 0, buffer, -1, wstr, wlen);

    wprintf(L"pipe %s\n", wstr);

    free(wstr);
    return 0;
}
...