I have two win32 programs, and they communicate with one DLL via IPC. I use MSVC ++ so it makes sense that I use CreateFileMapping and MapViewOfFile. I already have some codes done, the problem is that when my second program starts and loads a DLL and starts to work with DLLs, everything is fine and IPC communication is going well. When the first program starts and loads a DLL and starts to work with DLLs and the second program starts and loads a DLL and starts to work with DLLs, second program stops communicating with DLL via IPC. The IPC communication is probably running but probably in wrong way. It obtains the size and capacity, but the content is junk. The content of the shared memory is vector of pointers! What am I doing wrong? Is there anything I need to know to get those work fine?
//The sender writer
MainWindow::~MainWindow()
{
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
}
void MainWindow::SetData(vector <SubWindow*> &iMainWin)
{
hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(vector <SubWindow*>), TEXT("MyMappedMem"));
if (hMapFile == NULL)
return;
vector <SubWindow*> *pBuf = reinterpret_cast<std::vector<SubWindow*>*> (MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(vector <SubWindow*>)));
if (pBuf == NULL)
{
CloseHandle(hMapFile);
return;
}
memcpy(pBuf, &iMainWin, sizeof(iMainWin));
return;
}
//The reciever reader
void DataWork()
{
do{
if (strcmp(pe32.szExeFile, "Win32Project.exe") == 0)
{
bProcessFound = true;
break;
}
} while (Process32Next(hProcessSnap, &pe32));
if (!bProcessFound)
{
MessageBox(NULL, TEXT("ERROR Process32Next Openning DLL"), TEXT("ERROR"), MB_OK);
return;
}
else
{
HANDLE hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, TEXT("MyMappedMem"));
if (hMapFile == NULL)
{
MessageBox(NULL, TEXT("ERROR OpenFileMapping DLL"), TEXT("ERROR"), MB_OK);
return;
}
vector<SubWindow*> *pBuf = reinterpret_cast<std::vector<SubWindow*>*> (MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(vector <SubWindow*>)));
if (pBuf == NULL)
{
MessageBox(NULL, TEXT("ERROR MapViewOfFile DLL"), TEXT("ERROR"), MB_OK);
CloseHandle(hMapFile);
return;
}
for (int i = 0; i < buf->size(); i++)
(*buf)[i]->value_access;
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
}
}
Pointers in the first program are useless in the second program, and vice versa. You cannot use a pointer from program A in program B because they have different virtual memory spaces.
Attempting to share a std::vector using shared memory is almost certainly wrong. The std::vector will allocate memory from the calling process, which will not be accessible via any other process. Furthermore, pointers pointing to local addresses will not be accessible any other process.
Additionally, you would need to coordinate access to the std::vector using a mutex, which you aren't doing.
In this situation, I can't see any reason why using a text file wouldn't be sufficient.
Related
I have 2 programs.
The first program will open the second one and will also create 2 Event objects that will be used for synchronization.
The second one (the one to be opened) will open those 2 Event objects.
Both of the programs will run a for loop to simulate writing and reading operations from memory.
Program one:
read = CreateEvent(NULL, false, false, "READ");
write = CreateEvent(NULL, false, false, "WRITE");
CreateProcess("PATH_TO_EXE", NULL, NULL, NULL, FALSE, NULL, 0, NULL, &startupInfo, &processInformation);
for (int i = 1; i <= 100; i++)
{
printf("Wrote data to memory\n");
SetEvent(write);
WaitForSingleObject(read, INFINITE);
}
Program two:
HANDLE read, write;
read = OpenEvent(EVENT_MODIFY_STATE, false, "READ");
write = OpenEvent(EVENT_MODIFY_STATE, false, "WRITE");
for (int i = 1; i <= 100; i++)
{
WaitForSingleObject(write, INFINITE);
printf("Read data from memory.\n");
SetEvent(read);
}
I would expect the output to be:
Wrote data to memory.
Read data from memory.
Wrote data to memory.
Read data from memory.
....
but the real output is something like:
Wrote data to memory.
Read data from memory.
Read data from memory.
Read data from memory.
Read data from memory.
Read data from memory.
Read data from memory.
Read data from memory.
Wrote data to memory.
Read data from memory.
Wrote data to memory.
Wrote data to memory.
Read data from memory.
...
And at some point it just hangs, which would mean a deadlock. But I'm not sure how is this possible. Any help?
for WaitForSingleObject - handle to the object (1-st parameter) must have the SYNCHRONIZE access right. otherwise api failed with ERROR_ACCESS_DENIED. but you call
write = OpenEvent(EVENT_MODIFY_STATE, false, "WRITE");
requested access not include SYNCHRONIZE which you need and include EVENT_MODIFY_STATE which you really not need in this code. so you need change code to
write = OpenEvent(SYNCHRONIZE, false, "WRITE");
also you not check result of any api call. if you do this - you just view that WaitForSingleObject(write, INFINITE); return WAIT_FAILED and GetLastError() == ERROR_ACCESS_DENIED.
also if you need ipc via this 2 events with child process - better create it unnamed and inherited, and pass it values via command line to child. if you want test only event work logic - more easy use separate thread instead new process. for this test code can look like:
ULONG WINAPI child(void* p)
{
if (HANDLE read = OpenEvent(EVENT_MODIFY_STATE, false, L"READ"))
{
if (HANDLE write = OpenEvent(SYNCHRONIZE, false, L"WRITE"))
{
ULONG i = (ULONG)(ULONG_PTR)p;
do
{
if (WaitForSingleObject(write, INFINITE) == WAIT_FAILED){
DbgPrint("2:%u\n", GetLastError());
break;
}
DbgPrint("Read data from memory.\n");
if (!SetEvent(read)){
DbgPrint("3:%u\n", GetLastError());
break;
}
} while (--i);
CloseHandle(write);
}
CloseHandle(read);
}
return 0;
}
void bfg()
{
if (HANDLE read = CreateEvent(NULL, false, false, L"READ"))
{
if (HANDLE write = CreateEvent(NULL, false, false, L"WRITE"))
{
ULONG i = 16;
if (HANDLE hThread = CreateThread(0, 0, child, (PVOID)(ULONG_PTR)i, 0, 0))
{
do
{
DbgPrint("Wrote data to memory\n");
if (!SetEvent(write) || WaitForSingleObject(read, INFINITE) == WAIT_FAILED){
DbgPrint("1:%u\n", GetLastError());
break;
}
} while (--i);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
CloseHandle(write);
}
CloseHandle(read);
}
}
interesting that early (before win 8.1) was EventPair object in windows, which was design for such task. but unknown reason it was removed
What I want to know is it possible to try an open a file (and when it fails because it's opened with another process with sharing off) to figure out which process is using said file?
The reason I am wanting to know this information is because I am making a little application that will "fix" malicious files.
For example, some malicious/adware etc set the file security descriptor so the user can't delete the file, etc. My application just resets the security descriptor allowing the user to regain control.
I have also seen a file open up its child process with for example (CreateFile) and have Shared Mode turned off so the file can't be touched, then the application would execute the childprocess from memory.
Yes, you can in general just use the openfiles command, after having enabled collection of this information via, it appears, openfiles /local on.
In Windows NT up to and including (it seems) Windows XP there was a similar Resource Kit command named oh, short for open handles.
An alternative to both is to use SysInternal's Process Explorer.
Note: In some cases openfiles will fail to list some handle. This happens for me when Windows refuses to unmount an USB disk, claiming that some process is using a file on that disk. No such process ever shows up.
I have developed a function to locate such process, kill it and delete the locked file.
bool ForceDeleteFile(LPWSTR FileName);
Here is the full source code:
bool KillFileProcess(LPWSTR FileName)
{
HANDLE hProcessSnap;
HANDLE hProcess;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass;
bool result = false;
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
//printError(TEXT("CreateToolhelp32Snapshot (of processes)"));
return(FALSE);
}
// Set the size of the structure before using it.
pe32.dwSize = sizeof(PROCESSENTRY32);
// Retrieve information about the first process,
// and exit if unsuccessful
if (!Process32First(hProcessSnap, &pe32))
{
//printError(TEXT("Process32First")); // show cause of failure
CloseHandle(hProcessSnap); // clean the snapshot object
return(FALSE);
}
// Now walk the snapshot of processes, and
// display information about each process in turn
do
{
// Retrieve the priority class.
dwPriorityClass = 0;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
if (hProcess == NULL)
{
//printError(TEXT("OpenProcess"));
}
else
{
dwPriorityClass = GetPriorityClass(hProcess);
if (!dwPriorityClass)
{
//printError(TEXT("GetPriorityClass"));
}
CloseHandle(hProcess);
if (HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe32.th32ProcessID))
{
WCHAR filename[MAX_PATH] = {};
if (GetModuleFileNameEx(hProcess, NULL, filename, MAX_PATH))
{
if (_wcsicmp((const wchar_t *)FileName, (const wchar_t *)filename) == NULL)
{
if (TerminateProcess(pe32.th32ProcessID, 0))
{
_tprintf(L"Found: Process full killed\nKILLED!\n");
result = true;
}
else
{
_tprintf(L"Found: Process full \nFailed to terminate\n");
DoRun(((CString)L"taskkill /F /IM " + (CString)pe32.szExeFile).GetBuffer());
result = false;
}
}
}
else
{
// handle error
}
CloseHandle(hProcess);
}
}
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
return(result);
}
bool ForceDeleteFile(LPWSTR FileName)
{
bool result = DeleteFile(FileName);
if (!result)
{
_tprintf(L"Can't delete file. using DeleteFile(). Trying to locate process and kill it\n");
result = KillFileProcess(FileName);
if (!result)
_tprintf(L"Couldn't find the process\n");
else
{
Sleep(1000);
result = DeleteFile(FileName);
if (result)
_tprintf(L"DeleteFile success");
else
_tprintf(L"DeleteFile ============== failed ===============");
}
}
return result;
}
BOOL TerminateProcess(DWORD dwProcessId, UINT uExitCode)
{
DWORD dwDesiredAccess = PROCESS_TERMINATE;
BOOL bInheritHandle = FALSE;
HANDLE hProcess = OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId);
if (hProcess == NULL)
return FALSE;
BOOL result = TerminateProcess(hProcess, uExitCode);
CloseHandle(hProcess);
return result;
}
First of all i appologize for my bad english because i'm not english :)
I wanted to use mailslots from vb.net. I'm quite noob about mailslots, not sure on how they works. Had some difficulties and ended to basic testing in simple c++ win32 code to firstly understand how it works without caring about vb managed/unmanaged stuff. I used vs 2010 in a virtual machine.
Here is the problem: i finally realized that my basic test program works fine on several computers but not on my developpement computer... I don't have any idea on what could be the cause and what i have to check.
Here is the code:
#include <stdio.h>
#include <Windows.h>
void main()
{
HANDLE hservslot;
HANDLE hclislot;
hservslot = CreateMailslot("\\\\.\\mailslot\\testingslot", 0, 0, NULL);
if (hservslot == INVALID_HANDLE_VALUE)
{
printf("CreateMailslot error : %d", GetLastError());
getchar();
return;
}
hclislot = CreateFile("\\\\*\\mailslot\\testingslot", GENERIC_WRITE, FILE_SHARE_READ, (LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL);
if (hclislot == INVALID_HANDLE_VALUE)
{
CloseHandle(hservslot);
printf("CreateFile error : %d", GetLastError());
getchar();
return;
}
BOOL fResult;
DWORD cbWritten;
BYTE buff[4] = {0,1,2,3};
fResult = WriteFile(hclislot, buff , 4, &cbWritten, (LPOVERLAPPED) NULL);
if (fResult)
{
printf("Slot written to successfully.\n");
}
else
{
printf("WriteFile failed with %d.\n", GetLastError());
}
getchar();
CloseHandle(hclislot);
CloseHandle(hservslot);
}
On my computer i get the "WriteFile failed with 53" (which means "The network path was not found." according to msdn doc). On some other computers, including the virtual one, i get "Slot written to successfully."
Any idea on wich direction i should search the "bug" to fix it ?
Thx.
Edit: By the way, all the pc, including vm, are on windows 7 pro 64 bits.
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.
I have a program writing/reading from a file, and I want to lock the file for other instances of my application. How can I do it (in c++ visual studio 2003)?
I tried using the _locking() but then also I myself cannot reach the file when trying to read/write (in the same instance).
I know there's an option of LockFile() but have no idea how to set it properly.
Please help me.
You can simply use the Win32 API CreateFile and then specify no sharing rights. This will ensure that no other processes can access the file.
The dwShareMode DWORD specifies the type of sharing you would like, for example GENERIC_READ. If you specify 0 then that means no sharing rights should be granted.
Example:
HANDLE hFile = CreateFile(_T("c:\\file.txt"), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
If you want to only lock a certain part of the file you can use LockFile or LockFileEx.
Example:
//Lock the first 1024 bytes
BOOL bLocked = LockFile(hFile, 0, 0, 1024, 0);
For locking on other platforms please see my post here.
You want LockFileEx() (exclusive file locking). Have a look at this discussion from Secure Programming Cookbook for C and C++.
After searching online for a while, I didn't find any good examples.
Here are two calls to CreateFile with the intent of locking the file for the life of a process... I use this along side the CLimitSingleInstance that uses CreateMutex for a global named mutex.
The first call to CreateFile attempts to open it, the second one creates it if necessary.
I have a little bit more thorough implementation. I implemented it in Qt, hence the qCritical() instead of std::cout and the QDir::tempPath() instead of getting that some other way.
class SingleInstance
{
protected:
DWORD m_dwLastError;
HANDLE m_hFile;
public:
SingleInstance(const char *strMutexName) { }
bool attemptToLockTempFile()
{
QString lockFile = QDir::tempPath() + "/My.exe.lock";
m_hFile = CreateFileA(lockFile.toLocal8Bit().data(), GENERIC_READ, 0,
NULL, OPEN_EXISTING, 0, NULL);
DWORD dwLastError = GetLastError();
if(m_hFile != NULL && m_hFile != INVALID_HANDLE_VALUE)
{
return true;
}
else
{
if(dwLastError == ERROR_FILE_NOT_FOUND )
{
m_hFile = CreateFileA(lockFile.toLocal8Bit().data(), GENERIC_READ,
0, NULL, CREATE_NEW, 0, NULL);
dwLastError = GetLastError();
if(m_hFile != NULL && m_hFile != INVALID_HANDLE_VALUE)
{
return true;
}
else if(dwLastError == ERROR_SHARING_VIOLATION)
{
qCritical() << "Sharing Violation on My.exe.lock";
}
else
{
qCritical() << "Error reading" << "My.exe.lock" << "-" << dwLastError;
}
}
else if(dwLastError == ERROR_SHARING_VIOLATION)
{
qCritical() << "Sharing Violation on My.exe.lock";
}
else
{
qCritical() << "Unable to obtain file lock -" << dwLastError;
}
return false;
}
}
~SingleInstance()
{
if ( m_hFile != NULL && m_hFile != INVALID_HANDLE_VALUE)
{
::CloseHandle(m_hFile); //Do as late as possible.
m_hFile = NULL;
}
}
}
Here is what you would have at the top of your main function:
SingleInstance g_SingleInstanceObj(globalId_QA);
// Makes sure that the program doesn't run if there is another
// instance already running
if (g_SingleInstanceObj.IsAnotherInstanceRunning())
{
return 0;
}