how to create a share memory pool in windows - c++

I want to make a share memory pool for all the other process to share the data, but after I read about the CreateFileMapping API document, I was confused about that it will need to specify the size of the share memory. I actually want it to be dynamic allocate and free which looks more like a service. Is there some way to do the share memory dynamic using createFileMapping or not?

Creating Named Shared Memory.
First Process
The first process creates the file mapping object by calling the CreateFileMapping function with INVALID_HANDLE_VALUE and a name for the object. By using the PAGE_READWRITE flag, the process has read/write permission to the memory through any file views that are created.
Then the process uses the file mapping object handle that CreateFileMapping returns in a call to MapViewOfFile to create a view of the file in the process address space. The MapViewOfFile function returns a pointer to the file view, pBuf. The process then uses the CopyMemory function to write a string to the view that can be accessed by other processes.
Process 1 code:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#define BUF_SIZE 256
TCHAR szName[]=TEXT("Global\\MyFileMappingObject");
TCHAR szMsg[]=TEXT("Message from first process.");
int _tmain()
{
HANDLE hMapFile;
LPCTSTR pBuf;
hMapFile = 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)
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not create file mapping object (%d).\n"),
GetLastError());
return 1;
}
pBuf = (LPTSTR) MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return 1;
}
CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
_getch();
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
return 0;
}
Second Process
A second process can access the string written to the shared memory by the first process by calling the OpenFileMapping function specifying the same name for the mapping object as the first process. Then it can use the MapViewOfFile function to obtain a pointer to the file view, pBuf. The process can display this string as it would any other string. In this example, the message box displayed contains the message "Message from first process" that was written by the first process.
Process 2 code:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#pragma comment(lib, "user32.lib")
#define BUF_SIZE 256
TCHAR szName[]=TEXT("Global\\MyFileMappingObject");
int _tmain()
{
HANDLE hMapFile;
LPCTSTR pBuf;
hMapFile = OpenFileMapping(
FILE_MAP_ALL_ACCESS, // read/write access
FALSE, // do not inherit the name
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not open file mapping object (%d).\n"),
GetLastError());
return 1;
}
pBuf = (LPTSTR) MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return 1;
}
MessageBox(NULL, pBuf, TEXT("Process2"), MB_OK);
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
return 0;
}
Source : http://msdn.microsoft.com/en-us/library/windows/desktop/aa366551(v=vs.85).aspx

Related

memory mapp file write C++ read in mql4

hi guys i want read a memory mapped file created by C++ program , i use the MSDN example for create in C++ the memory mapped file , i want read the string in my metatrader 4 i write this code
#property copyright "Copyright © 2005, MetaQuotes Software Corp."
#property link "http://www.metaquotes.net/"
#property indicator_separate_window
#property indicator_minimum 0
#property indicator_buffers 1
#property indicator_color1 Blue
#define FILE_MAP_READ 4
#define BUF_SIZE 256
extern string szName = "MyFileMappingObject";
//extern string szName = "Global\\dllmemfilemap";
int handle = 0;
string Data;
#import "kernel32.dll"
int OpenFileMappingA(int dwDesiredAccess, bool bInheritHandle, string lpName);
string MapViewOfFile(int hFileMappingObject, int dwDesiredAccess, int dwFileOffsetHigh, int dwFileOffsetLow, int dwNumberOfBytestoMap);
int CloseHandle( int handle);
int UnmapViewOfFile(string lpBaseAddress);
#import
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int start()
{
handle = OpenFileMappingA(FILE_MAP_READ, FALSE, szName);
if(handle == 0)
{
Alert("Could not open file mapping object", GetLastError());
}
else
{
Data = MapViewOfFile(handle, FILE_MAP_READ, 0, 0, BUF_SIZE);
Alert(Data);
UnmapViewOfFile(Data);
CloseHandle(handle);
}
return (0);
}
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
return(0);
}
but not open the OpenFileMappingA, return always 0 , anyone have some idea ? thankz at all
You need to call CreateFileMapping before trying to OpenFileMapping.
See example here :
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#define BUF_SIZE 256
TCHAR szName[]=TEXT("Global\\MyFileMappingObject");
TCHAR szMsg[]=TEXT("Message from first process.");
int _tmain()
{
HANDLE hMapFile;
LPCTSTR pBuf;
hMapFile = 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)
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not create file mapping object (%d).\n"),
GetLastError());
return 1;
}
pBuf = (LPTSTR) MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return 1;
}
CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
_getch();
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
return 0;
}
strings are unicode in MQL, or similarly 2-bytes wchat_t in C++.
Here is a sample :
#include <cstdlib>
#include <cstring>
#include <string>
char* pBufMQL;
std::wstring ss = L"Sample string";
CopyMemory((PVOID)pBufMQL, ss.c_str(), ss.size() * sizeof(wchar_t));
in MQL:
handle = OpenFileMappingW( FILE_MAP_ALL_ACCESS, FALSE, szName);
if(handle == 0)
{
Alert("Could not open file mapping object", GetLastError());
}
string Data = MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE);
Print("Done, size: ", StringLen(Data), "-", Data);
p.s. 1: I'm currently struggling with writing from MQL to the buffer and string in MQL are a copy of pBuf(from C++), converted to string.
And I need to modify buffer from MQL.
p.s. 2: p.s. 1 solved, Here is a working example : https://www.mql5.com/en/articles/364#3

Passing DWORD* to mapped file

This example http://msdn.microsoft.com/en-us/library/windows/desktop/aa366551(v=vs.85).aspx passes a TCHAR, but how can I make it pass a DWORD? I tried below but I get cannot convert parameter 1 from 'DWORD *' to 'const wchar_t *'.
DWORD* pid=new DWORD[20];
HANDLE hMapFile;
DWORD pBuf;
TCHAR szName[]=TEXT("Global\\mapFile");
//il creez
hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, // use paging file
NULL, // default security
PAGE_READWRITE, // read/write access
0, // maximum object size (high-order DWORD)
256, // maximum object size (low-order DWORD)
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not create file mapping object (%d).\n"),
GetLastError());
return 1;
}
pBuf = (DWORD) MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
256);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return 1;
}
CopyMemory((LPVOID)pBuf, pid, (_tcslen(pid) * sizeof(TCHAR)));
Mapviewoffile returns LPVOID.
Next way it will work:
DWORD* pBuf = (DWORD*) MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
256);
if (pBuf == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(hMapFile);
return 1;
}
CopyMemory((LPVOID)pBuf, pid, (20* sizeof(DWORD)));

CreateFileMapping() returns null

I am trying to follow this tutorial on MSDN: Creating Named Shared Memory.
Unfortunately, I get NULL from CreateFileMapping(). The file shmfile.txt exists on my file system, so I thought no problems should occur, the mapping would be created, and the file would take its role as my shared memory object.
What am I doing wrong?
This is my code:
...
#define BUF_SIZE 256
TCHAR szName[]=TEXT("C:\\Users\\joe\\shmfolder\\shmfile.txt");
int main(){
HANDLE hMapFile; // filehandle
LPCTSTR pBuf;
hMapFile = 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)
szName); // name of mapping object
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not create file mapping object (%d).\n"), GetLastError());
return 1;
}
...
}
Right now, you're telling CreateFileMapping to create the mapping in the page file, then use the name of your existing file as the name of the file mapping.
The name you give for a file mapping object can have local\ or global\ as a prefix, but can't contain any other back-slashes.
If you want to map your pre-existing file as a shared memory region, you'd do something on this general order:
TCHAR szName[]=TEXT("C:\\Users\\joe\\shmfolder\\shmfile.txt");
TCHAR szMapName[]=TEXT("SharedFile");
HANDLE file = CreateFile(szName, ...);
HANDLE mapping = CreateFileMapping(file, ..., szMapName);

Debug content of shared memory

I got two processes. In process A, application Alpha is prepared for using shared memory. In process B, my windows console application with a main method accesses this shared memory. It works, I can connect to the memory. Unfortunately if I store the memory content in a variable (here pBuf) and inspect the variable via MsVisualStudioDebugger, there is only one letter in the buffer - what went wrong? How am I able to look in the memory/file to get a clue, what objects are stored in the memory? Thanks in advance.
Here is the code of my console app:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#pragma comment(lib, "user32.lib")
using namespace std;
#define BUF_SIZE 256
TCHAR szName[] = TEXT("SIMITSHM"); // Name des SHMs;
int main(void){
std::cout << "*** start SharedMemory ***\n";
HANDLE hMapFile;
LPCTSTR pBuf;
hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, szName);
if (hMapFile == NULL){
MessageBox(NULL, TEXT("Could not open file mapping object"), TEXT("FEHLER"), MB_OK);
return 1;
}
pBuf = (LPTSTR) MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE);
if (pBuf == NULL){
MessageBox(NULL, TEXT("Could not map view of file"), TEXT("FEHLER"), MB_OK);
CloseHandle(hMapFile);
return 1;
}
MessageBox(NULL, pBuf, TEXT("SIMIT-SHM"), MB_OK); // content of memory
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
std::cout << "*** close app by typing a number. ***\n";
int a = 0;
cin >> a;
return 0;
}
UPDATE: after doing more research on this issue, I guess the problem is the casting of the return value of MapViewOfFile()-function.
UPDATE-2: Thanks Hans! I was able to look the pBuf content as a hexdump, see:
UPDATE-3: Thanks Hans! Due to your advice I was able to use fwrite() to put the shared-memory-content in a file on my local machine. Moreover I am able to see some familiar names, i.e. names like EingangMotor1 which I configured in application-Alpha and it seems this content was stored in shared memory. Now I hope to play around with application-Alpha, recognize the related changes in shared-memory and afterwards hopefully I will be able to change the values of the shared memory variable values, so application-Alpha will change its behaviour on the fly.
UPDATE-4: current code - thanks in advance for feedback, which lines needs to be improved.
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#include <strsafe.h>
#include <fstream>
#include <sstream>
#include <vector>
#pragma comment(lib, "user32.lib")
using namespace std;
#define BUF_SIZE 256
TCHAR szName[] = TEXT("SIMITSHM"); // Name des SHMs;
int main(void){
std::cout << "*** Start SharedMemory ***\n";
HANDLE hMapFile;
FILE * pBuf;
hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, szName);
if (hMapFile == NULL){
MessageBox(NULL, TEXT("Could not open file mapping object"), TEXT("ERROR"), MB_OK);
return 1;
}
// MapViewOfFile return a pointer to void, so you need to cast it to a suitable structure
pBuf = (FILE*) MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, BUF_SIZE);
if (pBuf == NULL){
MessageBox(NULL, TEXT("Could not map view of file"), TEXT("ERROR"), MB_OK);
CloseHandle(hMapFile);
return 1;
}
// write file
FILE * pFile;
pFile = fopen ("shm-main-simit-content-fwrite.txt","w");
fwrite(pBuf, 50, 20, pFile);
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
std::cout << "*** close app by typing a number. ***\n";
int a = 0;
cin >> a;
return 0;
}
Yes, you certainly have a type mismatch. That file is very unlikely to contain a properly zero-terminated C string. Using the TCHAR macros adds to the randomness, there is no point in using them anymore. The last non-Unicode version of Windows died 10 years ago.
Answering the question: use Debug + Windows + Memory + Memory 1 and put "pBuf" in the Address box. You'll see a raw hex dump of the shared memory content.

Win CE: Creating Named Shared Memory

I try to create Named Shared Memory on win CE 6.0 but probably the process does not save the data.
I wrote two processes. The 1st writes the text to the shared memory and the 2nd reads. The 2nd show empty message window.
1st process:
#include "stdafx.h"
#include <stdlib.h>
#define BUFFSIZE 256
TCHAR szName[]=TEXT("MyFileMappingObject");
TCHAR szText[]=TEXT("Process write");
int _tmain(int argc, TCHAR *argv[], TCHAR *envp[])
{
HANDLE hMutex;
HANDLE hMapFile;
LPCTSTR pBuff;
BOOL fFirstApp = TRUE;
int rc;
// Create mutex used to share memory-mapped structure.
hMutex = CreateMutex (NULL, TRUE, TEXT ("MyFileMOWRT"));
rc = GetLastError();
if (rc == ERROR_ALREADY_EXISTS)
fFirstApp = FALSE;
else if (rc)
{
_tprintf(TEXT("rc1 (%d).\n"), GetLastError());
return 0;
}
// Wait here for ownership to ensure that the initialization is done.
// This is necessary since CreateMutex doesn’t wait.
rc = WaitForSingleObject(hMutex, 2000);
if (rc != WAIT_OBJECT_0)
{
_tprintf(TEXT("rc2 wait (%d).\n"), GetLastError());
return 0;
}
// Create a file-mapping object.
hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
BUFFSIZE, szName);
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not create file mapping object (%d).\n"), GetLastError());
return 1;
}
else
printf("File mapping object was created\n");
// Map into memory the file-mapping object.
pBuff = (LPTSTR)MapViewOfFile(hMapFile, FILE_MAP_WRITE, 0, 0, BUFFSIZE);
if (pBuff == NULL)
{
_tprintf(TEXT("Could not map view of file (%d).\n"), GetLastError());
CloseHandle(hMapFile);
return 1;
}
else
printf("Map view of file\n");
CopyMemory((PVOID)pBuff, szText, (_tcslen(szText) * sizeof(TCHAR)));
UnmapViewOfFile(pBuff);
// Release the mutex. We need to release the mutex twice
// if we owned it when we entered the wait above. ReleaseMutex(hMutex);
ReleaseMutex(hMutex);
if (fFirstApp)
ReleaseMutex(hMutex);
CloseHandle(hMapFile);
CloseHandle(hMutex);
return 0;
}
2nd process:
#include "stdafx.h"
#include <stdlib.h>
#define BUFFSIZE 256
TCHAR szName[]=TEXT("MyFileMappingObject");
int _tmain(int argc, TCHAR *argv[], TCHAR *envp[])
{
HANDLE hMutex;
HANDLE hMapFile;
LPCTSTR pBuf;
BOOL fFirstApp = TRUE;
int rc;
// Create mutex used to share memory-mapped structure.
hMutex = CreateMutex (NULL, TRUE, TEXT ("MyFileMOWRT"));
rc = GetLastError();
if (rc == ERROR_ALREADY_EXISTS)
fFirstApp = FALSE;
else if (rc)
{
_tprintf(TEXT("rc1 (%d).\n"), GetLastError());
return 0;
}
// Wait here for ownership to ensure that the initialization is done.
// This is necessary since CreateMutex doesn’t wait.
rc = WaitForSingleObject(hMutex, 2000);
if (rc != WAIT_OBJECT_0)
{
_tprintf(TEXT("rc2 wait (%d).\n"), GetLastError());
return 0;
}
// Create a file-mapping object.
hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
BUFFSIZE, szName);
if (hMapFile == NULL)
{
_tprintf(TEXT("Could not create file mapping object (%d).\n"), GetLastError());
return 1;
}
else
printf("File mapping object was created\n");
pBuf = (LPTSTR) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
if (pBuf)
{
MessageBox(NULL, pBuf, TEXT("Process2"), MB_OK);
}
else
{
_tprintf(TEXT("Could not map view of file (%d).\n"), GetLastError());
CloseHandle(hMapFile);
return 1;
}
UnmapViewOfFile(pBuf);
// Release the mutex. We need to release the mutex twice
// if we owned it when we entered the wait above. ReleaseMutex(hMutex);
ReleaseMutex(hMutex);
if (fFirstApp)
ReleaseMutex(hMutex);
CloseHandle(hMapFile);
CloseHandle(hMutex);
return 0;
}
Program which runs processes:
#include "stdafx.h"
#include <stdlib.h>
int _tmain(int argc, TCHAR *argv[], TCHAR *envp[])
{
CreateProcess(TEXT("\\Windows\\Mutex_proces.exe"), NULL, 0,0,0,0,0,0,0,0);
CreateProcess(TEXT("\\Windows\\Mutex_proces_rd.exe"), NULL, 0,0,0,0,0,0,0,0);
return 0;
}
After you get pointer to shared memory from MapViewOfFile, your code in both processes should setup synchronized pattern for reading/writing from/to this memory so:
Process 1 - P1
creates named file mapping
gets pointer to memory
writes to memory
create named mutex,
signalize to P2 (using mutex) that it has written memory, and P2 can read it. .
P1 should wait till P2 reads shared memory, it can simply wait on mutex from point 4.
Process 2 - P2
Creates named mutex, but if it does not exists then either returns with error, or waits till P1 creates this mutex.
Create named filemapping and get pointer to its memory
Handle to mutex (from 1.) is aquired, P2 now waits until P1 signals (use WaitForSingleObject)
When signal arrives then you can read memory, after reading release mutex so that P1 can proceed with processing from point 6.