0

I'm trying to use WinApi to CreateFileMapping, MapViewOfFile and CopyMemory. It's not showhing me errors and buffor is being filed with my 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;
}

... but then there is reading from memmory

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;
}

where I get System Error (2) while trying to open Mapping.

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

Code of those functions is from https://learn.microsoft.com/en-us/windows/win32/memory/creating-named-shared-memory and only thing I've changed is

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

Instead of

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

Where t_pid is just a const char *, becouse I was tired of Windows TCHAR types and I had no clue how to convert DWORD ProcessID to TCHAR to pass it to memcopy.

Well, I'm clueless why I'm unable to open Mapping. Windows is probably beyond me and I have no idea how

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

is supposed to be recognised by system to find memory from which I want to read a message.

Whole programm is supposed to lock execution for only one process and if there is a System variable named "SO2" of value "NEW", new process should stop execution of previous process and continoue locking program for himself.
Locking mechanism is with mutex and to find previous porcess ID, I wanted my current process ID to be saved in memory, for next process to read it form, to close it when sys var will be "NEW".
Nothing crazy. All of this in Linux I've done in one day, but Windows is killing me.

Please help

There is main if someone would be intrested:

#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;
}
  • the openfilemapping is supposed to be in one program and the createfilemapping in a different one. The create is called first then open is called by the other process. Even if all one process you have to call create first – pm100 Feb 16 '22 at 23:17
  • @pm100 Well, I'm running two instances of a programm, so there are two programms. First I need to read the PID and then I decide if I want to continue with execution – Bartłomiej Błaszczyk Feb 16 '22 at 23:19
  • error code say to you that not exist section with this name, whhen you try open it – RbMm Feb 16 '22 at 23:22
  • @pm100 and I know I have to create first but I'm expected to run the same code in diffrent processes, so first, I need to check if there is already memmory with PID and if not, I need to create one. I was changing the order in which both function are called but effect was the same – Bartłomiej Błaszczyk Feb 16 '22 at 23:25
  • @RbMm Yes, I know that but there is no reason for code to not find this Shared Named Memory. At least I can't see the reason – Bartłomiej Błaszczyk Feb 16 '22 at 23:27
  • can be 3 reasons - you use different names, you yet not create section, you already close section – RbMm Feb 16 '22 at 23:27
  • @RbMm 1. Name is from global variable. 2. There is no errors when creating section and buffer is being filed with content to store. 3. I was trying to not UnmapViewOfFile and was using create function before opening it (still, I'm creating two processes with the same code, so it shouldn't matter) Idk how but windows just doesn't like me – Bartłomiej Błaszczyk Feb 16 '22 at 23:34
  • again - how about variant - you close section before try open it in another process ? – RbMm Feb 16 '22 at 23:41
  • @RbMm Aparently yes, I've commented out UnmapViewOfFile in read function, and it worked – Bartłomiej Błaszczyk Feb 16 '22 at 23:52
  • no, not `UnmapViewOfFile` but `CloseHandle(h_map_file);` – RbMm Feb 16 '22 at 23:53
  • @RbMm It's only a handle. Each function creates it's own handle and is done with it at the end when it stoped reading or writing. What is freeing space in memory is Unmap function. I need to time this right in program – Bartłomiej Błaszczyk Feb 16 '22 at 23:57
  • when last handle on named object is closed and object have not permanent flag - name of object is destroyed. when you close section ( CloseHandle(h_map_file); ) - it have no more name – RbMm Feb 16 '22 at 23:59
  • @RbMm You're right. Thanks – Bartłomiej Błaszczyk Feb 17 '22 at 00:42

1 Answers1

2

Your logging clearly shows [access_pid_from_memory] occurs before [write_pid_to_memory].

And we can clearly see in your main() function that it calls access_pid_from_memory() first (which attempts to open the memory map and then closes it), and then afterwards calls write_pid_to_memory() (which creates the memory map and then closes it). Since there is no active handle referring to the mapping, it gets destroyed as soon as write_pid_to_memory() exits.

So, you are doing operations out of order, which is why OpenFileMapping() is failing. At no point does the mapping actually exist when access_pid_from_memory() is trying to open it.

You need to do the following instead:

  • in one process, create the mapping first, and leave it open.

  • THEN, in another process, open the mapping while it is still open in the previous process.

  • THEN, use the mapped memory as needed.

  • THEN, close the mapping in both processes.

There are other issues with your code, too:

  • converting the process ID to a string just to share it. You can share the ID as a binary DWORD instead.

  • access_pid_from_memory() doesn't actually read anything from the mapping (if it were able to open it at all).

  • main() is assigning t_pid to point at dangling memory. The call to stream.str() produces a temporary std::string that is destroyed as soon as c_str() exits.

  • I don't even know what you are attempting to do with your environment variable and mutex, and what that has to do with sharing memory. For purposes of this post, you should remove that code until you have your shared memory working properly.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Thank you for your insides. I'm explaining reason for the main feature of program before showing main() in my post. I started writing program with locking mechanism and tried to adapt Microsoft example to my case. Whole thing isn't finished yet, that's why function reading memory doesn't have buffer to write to. It's something I'm working on right now. What I need is to sort out my handle to mapping usage; I didn't know about object destruction when there is no handle left - Thank you for the help. – Bartłomiej Błaszczyk Feb 17 '22 at 23:09
  • @BartłomiejBłaszczyk "*Thank you for your insides*" - I think you mean **insights**. You don't want my *insides* ;-) – Remy Lebeau Feb 18 '22 at 00:37
  • - converting the process ID to a string just to share it. You can share the ID as a binary DWORD instead.
    How would you do that?
    – Bartłomiej Błaszczyk Feb 21 '22 at 21:33
  • @BartłomiejBłaszczyk Simply allocate the shared memory to `sizeof(DWORD)` number of bytes, get a `DWORD*` pointer to the memory, and then assign the original process ID `DWORD` to that memory. – Remy Lebeau Feb 21 '22 at 21:49