Error using CreateFileMapping - C - c

I am using the tutorial on this MSDN link to implement a way of transferring data from one process to another. Although I was advised in an earlier question to use the Pipe methods, due to certain constraints I have no choice but to use the CreateFileMapping method.
Now, i've succesfully managed to make two seperate window form projects within the same solution and by editing some properties both of the forms load at the same time.
Furthermore I have managed to implement the code given in the MSDN sample into the first (Producer) and second (Consumer) program without any compilation errors.
The problem I am having now is when I run the first program and try to create the handle to the mapped file, I am given an error saying it was unsuccesful and I do not understand why this is happening.
I have added both the Producer and Consumer code files to demonstrate what I am trying to do.
Producer:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
//File header definitions
#define IDM_FILE_ROLLDICE 1
#define IDM_FILE_QUIT 2
#define BUF_SIZE 256
TCHAR szName[]=TEXT("Global\\MyFileMappingObject");
TCHAR szMsg[]=TEXT("Message from first process!");
void AddMenus(HWND);
LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM);
////Standard windows stuff - omitted to save space.
//////////////////////
// WINDOWS FUNCTION //
//////////////////////
LRESULT CALLBACK WindowFunc(HWND hMainWindow, UINT message,
WPARAM wParam, LPARAM lParam)
{
WCHAR buffer[256];
LPCTSTR pBuf;
struct DiceData storage;
HANDLE hMapFile;
switch(message)
{
case WM_CREATE:
{
// Create Menus
AddMenus(hMainWindow);
}
break;
case WM_COMMAND:
// Intercept menu choices
switch(LOWORD(wParam))
{
case IDM_FILE_ROLLDICE:
{
//Roll dice and store results in variable
//storage = RollDice();
////Copy results to buffer
//swprintf(buffer,255,L"Dice 1: %d, Dice 2: %d",storage.dice1,storage.dice2);
////Show via message box
//MessageBox(hMainWindow,buffer,L"Dice Result",MB_OK);
hMapFile = CreateFileMapping(
(HANDLE)0xFFFFFFFF, // 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)
{
MessageBox(hMainWindow,L"Could not create file mapping object",L"Error",NULL);
return 1;
}
pBuf = (LPTSTR) MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
MessageBox(hMainWindow,L"Could not map view of file",L"Error",NULL);
CloseHandle(hMapFile);
return 1;
}
CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
_getch();
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
}
break;
case IDM_FILE_QUIT:
SendMessage(hMainWindow, WM_CLOSE, 0, 0);
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hMainWindow, message, wParam, lParam);
}
//
//Setup menus
//
Consumer:
#include <windows.h>
#include <stdio.h>
#include <conio.h>
//File header definitions
#define IDM_FILE_QUIT 1
#define IDM_FILE_POLL 2
#define BUF_SIZE 256
TCHAR szName[]=TEXT("Global\\MyFileMappingObject");
//Prototypes
void AddMenus(HWND);
LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM);
//More standard windows creation, again omitted.
//////////////////////
// WINDOWS FUNCTION //
//////////////////////
LRESULT CALLBACK WindowFunc(HWND hMainWindow, UINT message,
WPARAM wParam, LPARAM lParam)
{
HANDLE hMapFile;
LPCTSTR pBuf;
switch(message)
{
case WM_CREATE:
{
// Create Menus
AddMenus(hMainWindow);
break;
}
case WM_COMMAND:
{
// Intercept menu choices
switch(LOWORD(wParam))
{
case IDM_FILE_POLL:
{
hMapFile = OpenFileMapping(
FILE_MAP_ALL_ACCESS, // read/write access
FALSE, // do not inherit the name
szName); // name of mapping object
if (hMapFile == NULL)
{
MessageBox(hMainWindow,L"Could not open file mapping object",L"Error",NULL);
return 1;
}
pBuf = (LPTSTR) MapViewOfFile(hMapFile, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (pBuf == NULL)
{
MessageBox(hMainWindow,L"Could not map view of file",L"Error",NULL);
CloseHandle(hMapFile);
return 1;
}
MessageBox(NULL, pBuf, TEXT("Process2"), MB_OK);
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
break;
}
case IDM_FILE_QUIT:
SendMessage(hMainWindow, WM_CLOSE, 0, 0);
break;
}
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
}
return DefWindowProc(hMainWindow, message, wParam, lParam);
}
//
//Setup menus
//
It's by no means tidy and final but it's just a start, thanks for any help.
Edit: Error
Edit2: Output

Your code for the producer works for me. What version of Windows are you using? In newer versions (like Vista and 7) there are additional security restrictions placed on accessing shared memory. There is a note about this in the MSDN article you referenced above, saying that you must be an Administrator to create global shared memory objects in Windows Vista/7.
You should also make a call to GetLastError() to see which error code is actually returned from CreateFileMapping(), that may be helpful in determining the root cause of the problem.

Ensure the Global name is unique; this can be done with a tool named Process Explorer.
If not unique, this would typically fail with Error code 6 (The handle is invalid) upon calling CreateFileMappinng
Download Process Explorer from SysInternals
Run Process Explorer
Run your application up to a break point just prior to the CreateFileMapping() failure
Search for MyFileMappingObject using Find (Ctrl-F)
If anything comes up such as another FileMap, Mutex, etc.. consider a more unique name, and ensure your application is not the one creating it.
Note: Consider naming your FileMapping using a GUID (File -> Tools > Create GUID) within Visual Studio

Maybe we learned from the same material/examples in the past. I had the same problem after migrating from XP to Windows 7:
NULL Handle return value and GetLastError() = 5.
ERROR_ACCESS_DENIED
5 (0x5)
Access is denied.
System Error Codes (0-499): http://msdn.microsoft.com/en-us/library/ms681382.aspx
I used a lpName with backslashes like in the Microsoft example from http://msdn.microsoft.com/en-us/library/windows/desktop/aa366537.aspx that you posted above.
After changing the name of the file mapping object (lpName) from "Global\MyFileMappingObject" to "GlobalMyFileMappingObject", the CreateFileMapping function works again under Windows 7 with no other changes.
"The name can have a "Global\" or "Local\" prefix to explicitly create the object in the global or session namespace. The remainder of the name can contain any character except the backslash character ('\'). Creating a file mapping object in the global namespace from a session other than session zero requires the SeCreateGlobalPrivilege privilege. For more information, see Kernel Object Namespaces".
This is not just a name-change! If you need access to the global namespace, then you have to go the SeCreateGlobalPrivilege way.

Under Windows 7
I found:
OpenFileMapping(FILE_MAP_ALL_ACCESS, ...);
Causes issues with:
CreateFileMapping(
(HANDLE)0xFFFFFFFF, // use paging file
Try:
OpenFileMappingA(SECTION_MAP_WRITE | SECTION_MAP_READ,...);

Related

Close and Reopen PDF's in C

I am trying to write a function that when called, notes what pdf's are open in Acrobat, closes them, runs something else that will modify those files, and then reopens them.
Currently I am getting a bunch of HWND's and storing them in global variables accessed in close_pdfs(). This is shown below (I know I've been lazy and have magic numbers, just trying to get it working):
char windows[16][64]; // up to 16 windows with name length 64
int n_windows;
HWND tobedestroyed[16];
...
...
void close_pdfs() {
n_windows = 0;
EnumWindows(EnumWindowsProc, NULL);
for (int i = 0; i< n_windows; i++) {
printf("%s\n", windows[i]);
DestroyWindow(tobedestroyed[i]);
}
}
void reopen_pdfs() {
//this should iterate and reopen the closed pdf's
}
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam) {
char title[80];
GetWindowText(hwnd,title,sizeof(title));
if (!strcmp(&title[strlen(title)-4], ".pdf")) {
strcpy(windows[n_windows], title);
tobedestroyed[n_windows] = hwnd;
n_windows ++;
}
return TRUE;
}
These are called by:
close_pdfs();
system("modify_pdfs.exe");
reopen_pdfs();
Currently I can't get the pdf's to close, however I also think it is likely that there are better ways to tackle this problem.
Any help on how to complete this task as described in the first paragraph would be greatly appreciated.

DLL Export Function Called Twice

I have made a short DLL which will display a MessageBox when it is loaded by a process. However, the message box is displayed two times. So, it looks like the DLL Export Function is called twice. Could you please see if there is something that needs to be modified in my code so that the MessageBox is displayed only once?
#include <windows.h>
#include <stdio.h>
__declspec(dllexport) void sampledllmain()
{
MessageBox(NULL, "sample text","sample title", 0);
}
BOOL APIENTRY DllMain(HANDLE hHandle, DWORD dwReason, LPVOID Reserved)
{
switch(dwReason)
{
case DLL_PROCESS_ATTACH:
sampledllmain();
break;
}
return 1;
}
I load the DLL using rundll32 as shown below:
rundll32 "path to DLL",sampledllmain
As described by the information page about rundll32.exe :
It loads the specified DLL via LoadLibrary().
It obtains the address of the function via GetProcAddress().
It calls the function, passing the command line tail which is the .
In your case :
When LoadLibrary() is invoked it calls DllMain, in your case DllMain calls sampledllmain.
Obtains the address of sampledllmain
calls sampledllmain ( second time ).
to fix your issue:
add a second function dummy (for example )
use rundll32 "path to DLL",dummy on the command line
PS: On an additional note you could also debug your dll there are guides that describe how to do it
An example with MessageBox call in dllMain
#include <windows.h>
__declspec(dllexport) void sample(void)
{
MessageBox(NULL, "sample text test", "sample title test", 0);
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MessageBox(NULL, "attach", "DllMain", 0);
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
MessageBox(NULL, "detach", "DllMain", 0);
break;
}
return TRUE;
}
Run with rundll32.exe lib.dll,sample

Trouble calling a .DLL function from a Console Application

I really need your help because I'm having many problems integrating one .DLL function into my Console Application.This .DLL consists on getting 2 chars(Char a and Char b)(Input) and adding them to one char.For example:
Char A=H
Char B=I
Output=HI
But here's the problem.When I compile the console application and when I run it,it says that the function hasn't been detected.And here's my question..Why the hell doesn't it find the function even though in the .def file I've listed the LIBRARY and the only exported function?Please help me.
THIS IS THE .DLL SOURCE
#include "stdafx.h"
char concatenazione(char a,char b)
{
return a+b;
}
**THIS IS THE .DEF FILE OF THE .DLL**
LIBRARY Concatenazione
EXPORTS
concatenazione #1
**And this is the dllmain.cpp**
#include "stdafx.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
**This is the Console Application partial source(For now it just includes the functions import part)**
#include <iostream>
#include <windows.h>
#include <stdio.h>
typedef int (__cdecl *MYPROC)(LPWSTR);
int main( void )
{
HINSTANCE hinstLib;
MYPROC ProcAdd;
BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
// Get a handle to the DLL module.
hinstLib = LoadLibrary(TEXT("C:\\ConcatenazioneDiAyoub.dll"));
// If the handle is valid, try to get the function address.
if (hinstLib != NULL)
{
ProcAdd = (MYPROC) GetProcAddress(hinstLib, "concatenazione");
// If the function address is valid, call the function.
if (NULL != ProcAdd)
{
fRunTimeLinkSuccess = TRUE;
(ProcAdd) (L"Message sent to the DLL function\n");
}
// Free the DLL module.
fFreeResult = FreeLibrary(hinstLib);
}
// If unable to call the DLL function, use an alternative.
if (! fRunTimeLinkSuccess)
printf("Message printed from executable\n");
return 0;
}
**The Console Applications runs fine but the output is "Message printed from executable".This means that the function hasn't been detected.**
Ok, I looked at what you have above and wondered where in your code you import the dll. I'm kind of new at this myself, so I found this article on how to do it.
If I understand correctly, in your console application you need to have a line like (assuming the name of your dll is "your.dll":
[DllImport("your.Dll")]
by the way, welcome to Stack Overflow, I noticed it is your first day! CHEERS!

Gracefully closing a windowless app in WinAPI

I'm writing a little utility app to control the system master volume via hotkeys for my GF, whose laptop is for some reason deprived of such function keys. I whipped up the code pretty much instantly and I've got the main functionality working perfectly; however, since I'm not creating any windows (just a message loop handling the WM_HOTKEY message), I can't terminate the app in a more elegant manner than just gracelessly terminating the process (also, when the system is shutting down, it shows the "should I wait for the process to end or kill it now" window with some rubbish in the place where the window title usually is).
Is there any way of doing this which doesn't involve creating a fake window just for the sake of intercepting WM_CLOSE messages?
Here's the code (I left out the mixer control functions intentionally, they're irrelevant to the question):
int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nCmdShow) {
MSG msg;
int step;
MixerInfo_t mi;
HANDLE mutex;
mutex = CreateMutex(NULL, TRUE, "volhotkey");
if (mutex == NULL)
return 1;
if (GetLastError() == ERROR_ALREADY_EXISTS)
return 0;
RegisterHotKey(NULL, 1, MOD_ALT | MOD_CONTROL, VK_F5);
RegisterHotKey(NULL, 2, MOD_ALT | MOD_CONTROL, VK_F6);
RegisterHotKey(NULL, 3, MOD_ALT | MOD_CONTROL, VK_F7);
mi = GetMixerControls();
step = (mi.maxVolume - mi.minVolume) / 20;
while (GetMessage(&msg, NULL, 0, 0)) {
switch (msg.message) {
case WM_HOTKEY:
switch (msg.wParam) {
case 1:
AdjustVolume(&mi, -step);
break;
case 2:
AdjustVolume(&mi, step);
break;
case 3:
SetMute(&mi, !IsMuted(&mi));
break;
}
MessageBeep(MB_ICONASTERISK);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
break;
}
}
UnregisterHotKey(NULL, 1);
UnregisterHotKey(NULL, 2);
return msg.wParam;
}
Thanks in advance!
Oh, and for the record, WM_DESTROY is also never posted.
You could use the SetConsoleCtrlHandler() function to listen for the shutdown event.
SetConsoleCtrlHandler( ShutdownHandler, TRUE );
You handler would look something like this:
BOOL WINAPI ShutdownHandler( DWORD dwCtrlType )
{
if( dwCtrlType == CTRL_SHUTDOWN_EVENT || dwCtrlType == CTRL_LOGOFF_EVENT )
{
ExitProcess( 0 );
return TRUE; // just to keep the compiler happy
}
return FALSE;
}
Despite the name, SetConsoleCtrlHandler() works regardless of whether or not the application is a console application.
Have a look at the ExitProcess API call for shutting down a process gracefully. To detect a Windows shutdown, include WM_ENDSESSION in your message handling. If your application is more complex than what is posted, you may also want to review the ExitThread function.
You didn't create any window, not even a hidden one, so there's no way to get the loop to exit by sending a message to a window. Also the reason that WM_DESTROY never fires.
All that's left is PostThreadMessage() to post WM_QUIT. You'd have to be able to find the thread ID somehow. Using Shell_NotifyIcon() would be wise.
You could always show something in the system tray easily enough from which you could elegantly close it. And as your application grows, that may be desirable, because the user may eventually want to be able to configure or change the hotkeys, or temporarily turn them off it they interfere with another application etc.
Or have another hotkey which shows a small window with configuration options?

One time Hook DLL initialization

My program uses SetWindowsHookEx to set a global hook function in my DLL. However I want the DLL to work with a file so I need it a file to be opened once. I can't use DllMain's DLL_PROCESS_ATTACH because it's called multiple times. What is the best solution to my problem?
Use a static flag to tell whether you've initialized already or not.
void DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
static BOOL initialized = FALSE;
switch(dwReason) {
case DLL_PROCESS_ATTACH:
if(!initialized) {
// Perform initialization here...ex: open your file.
initialized = TRUE;
}
break;
case DLL_PROCESS_DETACH:
if(initialized) {
// Perform cleanup here...ex: close your file.
initialized = FALSE;
}
break;
};
}

Resources