#include "pch.h"
#include "misc.h"
#include "usrerr.h"

#include <strsafe.h>
#include <spdlog/spdlog.h>

void RemoveTailLineBreak(TCHAR *pInputStr, int strSize) {
    size_t length;
    if (pInputStr) {
        if (StringCbLength(pInputStr, strSize, &length) == S_OK && length > 0) {
            if (pInputStr[length - 2] == '\r' && pInputStr[length - 1] == '\n') {
                pInputStr[length - 2] = pInputStr[length - 1] = 0;
            } else if (pInputStr[length - 1] == '\n') {
                pInputStr[length - 1] = 0;
            }
        }
    }
}

int RunPipeCmd(TCHAR *pszCmd, TCHAR *pszResultBuffer, int dwResultBufferSize) {
    BOOL                bRet;
    HANDLE              hReadPipe  = nullptr;
    HANDLE              hWritePipe = nullptr;
    STARTUPINFO         si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES securityAttributes = {};

    memset(&si, 0, sizeof(STARTUPINFO));
    memset(&pi, 0, sizeof(PROCESS_INFORMATION));

    // 设定管道的安全属性
    securityAttributes.bInheritHandle       = TRUE;
    securityAttributes.nLength              = sizeof(securityAttributes);
    securityAttributes.lpSecurityDescriptor = nullptr;

    // 创建匿名管道
    bRet = ::CreatePipe(&hReadPipe, &hWritePipe, &securityAttributes, 0);
    if (FALSE == bRet) {
        SPDLOG_ERROR(TEXT("CreatePipe Error"));
        return -ERR_SYS_CALL;
    }

    // 设置新进程参数
    si.cb          = sizeof(si);
    si.hStdError   = hWritePipe;
    si.hStdOutput  = hWritePipe;
    si.wShowWindow = SW_HIDE;
    si.dwFlags     = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;

    // 创建新进程执行命令, 将执行结果写入匿名管道中
    bRet = ::CreateProcess(nullptr, (pszCmd), nullptr, nullptr, TRUE, 0, nullptr, nullptr, &si, &pi);
    if (FALSE == bRet) {
        SPDLOG_ERROR(TEXT("CreateProcess Error"));
    }

    // 等待命令执行结束
    ::WaitForSingleObject(pi.hThread, INFINITE);
    ::WaitForSingleObject(pi.hProcess, INFINITE);

    // 从匿名管道中读取结果到输出缓冲区
    ::RtlZeroMemory(pszResultBuffer, dwResultBufferSize);
    ::ReadFile(hReadPipe, pszResultBuffer, dwResultBufferSize, nullptr, nullptr);

    // 关闭句柄, 释放内存
    ::CloseHandle(pi.hThread);
    ::CloseHandle(pi.hProcess);
    ::CloseHandle(hWritePipe);
    ::CloseHandle(hReadPipe);

    RemoveTailLineBreak(pszResultBuffer, dwResultBufferSize);
    //pszResultBuffer[dwResultBufferSize - 1] = 0;
    return ERR_SUCCESS;
}