如何将wstring缓冲区发送到子进程的stdin

How to send wstring buffer to stdin of a child process?

本文关键字:子进程 stdin wstring 缓冲区      更新时间:2023-10-16

我在将WString写入子进程的STDIN时遇到问题。如果我只有acii字符串(例如:@WSX3edc),则代码运行良好,但如果它包含非ascii字符(例如:@WSX3eddß),则会失败。

子进程是7zr.exe(7Zip命令行版本)。我正在写入STDIN的输入是提取文件的密码。

// inject password
wPassword.append(password);
wPassword.append(L"n"); \For carriage return
...
DWORD dwBytesToWrite = wPassword.length()*sizeof(wchar_t);
DWORD dwBytesWritten = 0;
char szBuffer[1024] = "";
wcstombs(szBuffer, wPassword.c_str(),wcslen(wPassword.c_str())+1);
dwBytesToWrite = strlen(szBuffer);
if (!WriteFile(hInput, szBuffer, dwBytesToWrite, &dwBytesWritten, NULL)) {
std::cout<<"write file failed"<<GetLastError()<<std::endl;
goto Cleanup;
}

写入文件总是成功的,但由于密码注入机制的错误,文件提取不成功。

这个的Createprocess看起来像:(si对象使用前面的CreatePipe设置了STDIN和STDOUT流)

if(!CreateProcess((LPWSTR)cmd, (LPWSTR)cmdArgs, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS,
NULL, NULL, &si, &pi)) {
std::cout<<"7zr.exe process creation failed "<<GetLastError()<<std::endl;
goto Cleanup;
}

注意:7zr.exe适用于此特定密码,如果我们在命令行上运行并粘贴此密码。提取效果良好。

如果窄字符集没有相关的密码字符,则不能使用此方法。相反,查找7zr用于指定密码的选项。我没有一个名为7zr的可执行文件,但我有7z,命令7z | find /i "pass"运行得很好。


在其他新闻中:

  • 变量dwBytesToWrite用一个值初始化,但几行后被重新分配,而没有使用。

  • CCD_ 6在C++中一般是不好的。如果你想保证清理,可以使用析构函数(一种名为RAII的技术,请阅读它)。

  • 微软的匈牙利符号,前缀为szdw,通常是令人憎恶的。它曾经在20世纪80年代支持微软程序员工作台中的帮助系统。AFAIK该产品在过去30年左右都不存在。

  • (LPWSTR)cmd中的C转换很容易引入错误。在要强制转换常量的位置使用const_cast。那么更清楚的是,这种强制转换是不正确的:您需要一个可变的缓冲区。

  • 与其通过std::cout向标准输出流报告故障,不如考虑通过std::cerrstd::clog使用标准错误流。更好的是,不要在检测到故障的地方进行i/o,而是抛出一个异常,让调用代码来处理它。调用代码无法删除已经输出的输出。

wcslen(wide)返回其参数wide宽字符数(请参阅)。

wcstombs(narrow,wide,len)narrow写入的字节数不超过len字节(请参阅)。

现在,如果我们总是有一个宽字符=一个窄字符=一字节,那么有两种字符就没有多大意义了,是吗?

一旦你有一个宽字符翻译成多个窄字符,就存在未定义的行为。

由于你的szBuffer是固定大小的,你也可以写

wcstombs(szBuffer, wPassword.c_str(), sizeof(szBuffer));