0

我正在尝试使用 WinApi 来 CreateFileMapping、MapViewOfFile 和 CopyMemory。它没有向我显示错误,并且缓冲区正在与我的 PID 一起提交

int write_pid_to_memory(const char *t_pid)
{
    _tprintf(TEXT("[write_pid_to_memory] t_pid: (%s).\n"), t_pid);

    HANDLE h_map_file;
    LPCTSTR p_buf;

    h_map_file = CreateFileMapping(
        INVALID_HANDLE_VALUE, // use paging file
        NULL,                 // default security
        PAGE_READWRITE,       // read/write access
        0,                    // maximum object size (high-order DWORD)
        BUF_SIZE,             // maximum object size (low-order DWORD)
        t_name);              // name of mapping object

    if (h_map_file == NULL)
    {
        _tprintf(TEXT("[write_pid_to_memory] Could not create file mapping object (%d).\n"),
                 GetLastError());
        return 1;
    }
    p_buf = (LPTSTR)MapViewOfFile(
        h_map_file,          // handle to map object
        FILE_MAP_ALL_ACCESS, // read/write permission
        0,
        0,
        BUF_SIZE);

    if (p_buf == NULL)
    {
        _tprintf(TEXT("[write_pid_to_memory] Could not map view of file (%d).\n"),
                 GetLastError());

        CloseHandle(h_map_file);

        return 1;
    }

    std::cout << "[write_pid_to_memory] strlen(t_pid) * sizeof(char) " << strlen(t_pid) * sizeof(char) << std::endl;

    CopyMemory((PVOID)p_buf, t_pid, (strlen(t_pid) * sizeof(char)));

    _getch();

    std::cout << "p_buf " << p_buf << std::endl;

    UnmapViewOfFile(p_buf);

    CloseHandle(h_map_file);

    return 0;
}

...但是从内存中读取

int access_pid_from_memory()
{

    HANDLE h_map_file;
    LPCTSTR p_buf;

    h_map_file = OpenFileMapping(
        FILE_MAP_ALL_ACCESS, // read/write access
        FALSE,               // do not inherit the name
        t_name);             // name of mapping object

    if (h_map_file == NULL)
    {
        _tprintf(TEXT("[access_pid_from_memory] Could not open file mapping object (%d).\n"),
                 GetLastError());
        return 1;
    }

    p_buf = (LPTSTR)MapViewOfFile(
        h_map_file,          // handle to map object
        FILE_MAP_ALL_ACCESS, // read/write permission
        0,
        0,
        BUF_SIZE);

    if (p_buf == NULL)
    {
        _tprintf(TEXT("[access_pid_from_memory] Could not map view of file (%d).\n"),
                 GetLastError());

        CloseHandle(h_map_file);

        return 1;
    }

    MessageBox(NULL, p_buf, TEXT("[access_pid_from_memory] Process2"), MB_OK);

    UnmapViewOfFile(p_buf);

    CloseHandle(h_map_file);

    return 0;
}

尝试打开映射时出现系统错误 (2)。

My PID: 19516
[access_pid_from_memory] Could not open file mapping object (2).
[write_pid_to_memory] t_pid: (19516).
[write_pid_to_memory] strlen(t_pid) * sizeof(char) 5
p_buf 19516
Envariamental variable = NEW
Env var value length = 3
Env var value compare resault = 0
Mutex created sucesfully

这些函数的代码来自 https://docs.microsoft.com/en-us/windows/win32/memory/creating-named-shared-memory 我唯一改变的是

CopyMemory((PVOID)p_buf, t_pid, (strlen(t_pid) * sizeof(char)));

代替

CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));

其中 t_pid 只是一个 const char *,因为我厌倦了 Windows TCHAR 类型,而且我不知道如何将 DWORD ProcessID 转换为 TCHAR 以将其传递给 memcopy。

好吧,我不知道为什么我无法打开映射。Windows 可能超出了我的范围,我不知道如何

TCHAR t_name[] = TEXT("Global\\MyFileMappingObject");

应该被系统识别以找到我想从中读取消息的内存。

整个程序应该只锁定一个进程的执行,如果有一个名为“SO2”的系统变量值为“NEW”,新进程应该停止执行前一个进程并继续为自己锁定程序。
锁定机制是使用互斥锁并找到以前的进程 ID,我希望将当前进程 ID 保存在内存中,以便下一个进程读取它的形式,当 sys var 为“新”时关闭它。
没什么疯狂的。我在一天之内就在 Linux 中完成了所有这些工作,但 Windows 正在扼杀我。

请帮忙

如果有人感兴趣,主要是:

#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <windows.h>
#include <string>

#include <conio.h>
#include <tchar.h>

#define BUFFER_SIZE 2048
#define ENV_KEY "SO2"
#define ENV_VAL "NEW"

#define BUF_SIZE 256

TCHAR t_name[] = TEXT("Global\\MyFileMappingObject");
HANDLE h_mutex;

int write_pid_to_memory(const char *dw_pid);
int access_pid_from_memory();

int main(int argc, char **argv)
{

    DWORD dw_pid = GetCurrentProcessId();

    std::stringstream stream;
    stream << dw_pid;
    const char *t_pid = stream.str().c_str();

    // int legnth = s_pid.length()
    // const char *t_pid = (char*)malloc( * sizeof(char));

    // const char t_pid = (char)malloc(strlen(dw_pid) * sizeof(char));

    std::cout << "My PID: " << dw_pid << std::endl;

    access_pid_from_memory();
    write_pid_to_memory(t_pid);

    std::string env_val(ENV_VAL);
    char c_buffer[BUFFER_SIZE];
    LPCSTR lp_name = ENV_KEY;
    LPSTR lp_buffer = c_buffer;
    DWORD dw_size = BUFFER_SIZE;
    DWORD get_env_var;

    //Write to memory your pid for other process to access it and close you

    get_env_var = GetEnvironmentVariable(
        lp_name,
        lp_buffer,
        dw_size);

    if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
    {
        std::cout << "Couldn't find envariamental variable \"SO2\"." << std::endl;
    }

    if (BUFFER_SIZE == get_env_var)
    {
        std::cout << "Buffer for function [GetEnvironmentVariable] is too small. Function failed." << std::endl;
    }

    std::cout << "Envariamental variable = " << lp_buffer << std::endl;
    std::string str_buffer(lp_buffer);
    std::cout << "Env var value length = " << str_buffer.length() << std::endl;
    std::cout << "Env var value compare resault = " << str_buffer.compare(env_val) << std::endl;

    HANDLE h_mutex = NULL;

    LPCSTR str = ENV_KEY;

    h_mutex = OpenMutex(
        MUTEX_ALL_ACCESS,
        TRUE,
        str);

    if (NULL != h_mutex)
    {
        if (str_buffer.compare(env_val) == 0)
        {
            //Realease mutex3
            ReleaseMutex(h_mutex);
            //Close previous process
        }
        else
        {

            throw std::runtime_error("Instance of a program is already running");
        }
    }

    h_mutex = CreateMutex(
        NULL,
        FALSE,
        str);

    if (h_mutex == NULL)
    {
        std::cout << "Failed to create mutex: error - " << GetLastError() << std::endl;
        return 1;
    }

    std::cout << "Mutex created sucesfully" << std::endl;

    DWORD dw_wait_res;

    dw_wait_res = WaitForSingleObject(
        h_mutex,   // handle to mutex
        INFINITE); // no time-out interval

    for (;;)
    {
        Sleep(100);
    }

    CloseHandle(h_mutex);
    system("PAUSE");
    return 0;
}
4

1 回答 1

2

您的记录清楚地显示[access_pid_from_memory]发生在之前 [write_pid_to_memory]

我们可以在您的main()函数中清楚地看到它access_pid_from_memory()首先调用(尝试打开内存映射然后关闭它),然后调用write_pid_to_memory()(创建内存映射然后关闭它)。由于没有引用映射的活动句柄,它一write_pid_to_memory()退出就会被销毁。

因此,您正在无序地进行操作,这就是OpenFileMapping()失败的原因。access_pid_from_memory()尝试打开映射时,映射实际上并不存在。

您需要改为执行以下操作:

  • 在一个过程中,首先创建映射,然后将其保持打开状态

  • 然后,在另一个进程中,打开映射,而它在前一个进程中仍处于打开状态

  • 然后,根据需要使用映射内存。

  • 然后,关闭两个进程中的映射。

您的代码也存在其他问题:

  • 将进程 ID 转换为字符串只是为了共享它。DWORD您可以改为将 ID 作为二进制文件共享。

  • access_pid_from_memory()实际上并没有从映射中读取任何内容(如果它能够完全打开它)。

  • main()正在分配t_pid指向悬空的内存。调用stream.str()产生一个临时 std::string的,一旦c_str()退出就会被销毁。

  • 我什至不知道你试图用你的环境变量和互斥锁做什么,以及这与共享内存有什么关系。出于本文的目的,您应该删除该代码,直到您的共享内存正常工作。

于 2022-02-17T00:02:21.527 回答