如何访问父对象的句柄?
Posted
技术标签:
【中文标题】如何访问父对象的句柄?【英文标题】:How to get access to parent's object handles? 【发布时间】:2020-04-03 23:11:02 【问题描述】:我有 ParentProcess.exe,其中包含以下代码。它创建一个文件并用一个简单的字符 1 填充它,然后它创建一个名为 ChildProcess.exe 的新进程。此 ChildProcess 使用 bIheritance 标志 true 创建。我希望它能够访问父对象的对象。
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
int main(int argc, const char* argv[])
SECURITY_ATTRIBUTES process_sa;
process_sa.nLength = sizeof(process_sa);
process_sa.bInheritHandle = TRUE;
process_sa.lpSecurityDescriptor = 0;
SECURITY_ATTRIBUTES thread_sa;
thread_sa.nLength = sizeof(thread_sa);
thread_sa.bInheritHandle = TRUE;
thread_sa.lpSecurityDescriptor = NULL;
HANDLE hFileCreated = CreateFile("e:\\Sample.txt", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, &process_sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (hFileCreated == INVALID_HANDLE_VALUE)
printf("File doesn't created.");
return 1;
char c = '1';
DWORD w;
WriteFile(hFileCreated, &c, 1, &w, 0);
STARTUPINFO sinfo;
ZeroMemory(&sinfo, sizeof(sinfo));
sinfo.cb = sizeof(sinfo);
PROCESS_INFORMATION pinfo;
ZeroMemory(&pinfo, sizeof(pinfo));
if (CreateProcess(0, "ChildProcess.exe", &process_sa, &thread_sa, TRUE, 0, 0, 0, &sinfo, &pinfo))
printf("done.");
else
printf("failed.");
CloseHandle(pinfo.hThread);
CloseHandle(pinfo.hProcess);
return 0;
ChildProcess.exe 有以下代码,我希望它可以访问由父进程创建的文件的句柄,但是当它运行时它显示 0XFFFFFFFF 的地址。哪里有问题。 ChildProcess 代码:
#include <Windows.h>
#include <process.h>
#include <stdio.h>
#include <tchar.h>
int _tmain(int argc, _TCHAR* argv[])
HANDLE hFileCreatedInheritance = INVALID_HANDLE_VALUE;
_stscanf_s(L"e:\\Sample.txt", _T("%p"), &hFileCreatedInheritance);
printf("The handle of the file is %p.\n", hFileCreatedInheritance);
return 0;
【问题讨论】:
阅读 CreateFile 的文档,特别注意 dwShareMode。它指的是如果在原始进程打开文件时第二个进程尝试打开文件会发生什么。 @thurizas 仅在两个进程都调用CreateFile
时适用,在这种情况下并非如此。
嗯...这就是重点。 CreateFile
不处理跨进程共享句柄。要访问该文件,OP 必须在子进程和父进程中调用 CreateFile
。我不确定CreateProcess
的参数是否允许共享文件句柄。 (我很确定fork
确实如此)。
【参考方案1】:
在父进程中:
在将句柄插入文本文件之前将其转换为字符串:
DWORD w;
std::stringstream streamAdr;
streamAdr << hFileCreated;
std::string strAddr = streamAdr.str();
WriteFile(hFileCreated, strAddr.c_str(), strAddr.size(), &w, 0);
在子进程中:
string sLine;
ifstream infile("G:\\Sample.txt");
if (infile.good())
getline(infile, sLine); // Get first line containing handle of file
infile.close();
unsigned int i = stoi(sLine.c_str(), 0, 16); // Convert hexadecimal string
hFileCreatedInheritance = (HANDLE) i; // cast to a HANDLE
printf("The handle of the file is %p.\n", hFileCreatedInheritance);
结果:
问题: 你想达到什么目的?
【讨论】:
您正在使用ostream::operator<<(void*)
将hFileCreated
的值写入文件,那么您为什么不使用istream::operator>>(void*&)
将其读入hFileCreatedInheritance
?你不需要使用getline()
和stoi()
@rem:如果孩子和父母有不同的位数,那将失败。当然,这个答案中提供的解决方案也没有解决这种情况。事实上,更糟糕的是,如果子进程是 64 位进程,它会失败,而如果子进程是 32 位(或 64 位)进程,则会表现出未定义的行为。
@RemyLebeau 确实,你的替代方案更简单
@IInspectable "如果孩子和父母有不同的位数,那将失败" - no, it won't: "64 位版本的 Windows 使用 32 位句柄互操作性。在 32 位和 64 位应用程序之间共享句柄时,只有低 32 位是有效的,因此截断句柄(从 64 位传递到 32 位时)或符号扩展是安全的句柄(从 32 位传递到 64 位时)。可以共享的句柄包括...文件句柄。"
@rem:不管HANDLE
中有多少有效位,void*
对于 32 位和 64 位构建都有不同的大小。写入 32 位 void*
并尝试读取 64 位 void*
不是有意义的操作。当然,您可以在不同位数的进程之间转移HANDLE
s,但您不能按照您的建议或这个答案进行。以上是关于如何访问父对象的句柄?的主要内容,如果未能解决你的问题,请参考以下文章