#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <windows.h>
#include <string.h>
#include <winbase.h>


/*-----------------------------------------------------------------*/

void ErrorOut(char errstring[30])
/*
Purpose: Print out an meainful error code by means of
         GetLastError and printf

Inputs:  errstring - the action that failed, passed by the
                     calling proc.

Returns: none

Calls:   GetLastError
*/

{
DWORD Error;

Error= GetLastError();
printf("Error on %s = %d\n", errstring, Error);
}

/*-----------------------------------------------------------------*/

HANDLE CreateMapFile()
/*
Purpose: Create a Map file to map named share memory

Inputs:  none

Returns: MapFileHandle - a handle to the file
                         or NULL if failure

Calls:   CreateFile, ErrorOut
*/

{
char MapFileName[30]="MapFile.001";
HANDLE MapFileHandle;

MapFileHandle= CreateFile(MapFileName,
                          GENERIC_READ | GENERIC_WRITE,
                          FILE_SHARE_READ | FILE_SHARE_WRITE,
                          NULL,
                          CREATE_ALWAYS,
                          FILE_ATTRIBUTE_NORMAL /* | STANDARD_RIGHTS_REQUIRED |
                          FILE_MAP_WRITE | FILE_MAP_READ */,
                          NULL);

if (MapFileHandle == (HANDLE)-1)
  {
  ErrorOut("CreateFile");
  return(NULL);
  }
else
  return(MapFileHandle);

}

/*-----------------------------------------------------------------*/

HANDLE CreateMap(HANDLE *FileToBeMapped)
/*
Purpose: Create File Mapping object using the open file handle

Inputs:  *FileToBeMapped - pointer to the file handle

Returns: MapHandle - handle to the file mapping object
                     or NULL if failure

Calls:   CreateFileMapping, ErrorOut
*/

{
char MapName[30]="MapName1";
HANDLE MapHandle;

MapHandle= CreateFileMapping(*FileToBeMapped,
                             NULL,
                             PAGE_READWRITE,
                             0,
                             4096,
                             MapName);

if (MapHandle == NULL)
  {
  ErrorOut("CreateFileMapping");
  return(NULL);
  }
else
  return(MapHandle);

}
/*-----------------------------------------------------------------*/

LPVOID MapView(HANDLE *hMap)
/*
Purpose: Map the file mapping object into address space

Inputs:  *hMap - pointer to the mapping object

Returns: MappedPointer - pointer to the address space that the
                         object is mapped into
                         or NULL if failure

Calls:   MapViewOfFile, ErrorOut
*/

{
LPVOID MappedPointer;

MappedPointer= MapViewOfFile(*hMap,
                             FILE_MAP_WRITE | FILE_MAP_READ,
                             0,
                             0,
                             4096);
if (MappedPointer == NULL)
  {
  ErrorOut("MapViewOfFile");
  return(NULL);
  }
else
  return(MappedPointer);

}

/*-----------------------------------------------------------------*/

BOOL StartChildReader()
/*
Purpose: Start a Child Process to act on the shared memory

Inputs:  none

Returns: FALSE on failure, TRUE on success

Calls: CreateProcess, ErrorOut
*/
{
BOOL CreateSucc;
STARTUPINFO stinfo;
PROCESS_INFORMATION pinfo;

stinfo.cb= sizeof(STARTUPINFO);
stinfo.lpTitle= "SharedMemeoryClientReader";
stinfo.lpDesktop=NULL;
stinfo.dwX= 20;
stinfo.dwY= 20;
stinfo.dwXSize=80;
stinfo.dwYSize=25;
stinfo.dwFlags=0; // STARTF_SHELLOVERRIDE;
stinfo.wShowWindow=SW_SHOWDEFAULT;
stinfo.lpReserved=NULL;
stinfo.cbReserved2=0;
stinfo.lpReserved2=NULL;

CreateSucc= CreateProcess("nmmemcli.exe",        /* app name */
                          "nmmemcli.exe",    /* cmd line */
                          NULL,              /* proc sec. attr */
                          NULL,              /* thread sec. attr */
                          TRUE, 		           /* inherit handles */
                          0L,			             /* creation flags */
			                       NULL, 		           /* environment */
			                       NULL, 		           /* cur dir */
			                       &stinfo,		         /* startup info */
			                       &pinfo);		         /* process info */
if ((BOOL)CreateSucc == FALSE)
  {
  ErrorOut("CreateProcess");
  return(FALSE);
  }
else
  return(TRUE);

}
/*-----------------------------------------------------------------*/

void main(int argc, char *argv[])
/*
Purpose: 1. Open a file to map
         2. Create a mapping object for the file
         3. Map a view of the object
         4. set 2048 bytes of the memory to "z"'s
         5. start a child process to act on the share memory
         6. sleep while waiting for child to act

Inputs:  none

Returns: none

Calls:   CreateMapFile, CreateMap, MapView, strncpy, StartChildReader,
         Sleep
*/

{
HANDLE hMem1;
HANDLE MapFileHandle;
LPVOID pShrMem1;
BOOL   ChildSucc;
BOOL   usefile;

printf ("Server: Named Shared Memory\n\n");

if (argc < 2)
  {
  printf("\nusage: NMSHRMEM NEWFILE|PAGFILE\n");
  printf("where NEWFILE creates a seperate mapping file\n");
  printf("and PAGFILE uses the paging file\n");
  ExitProcess(0);
  }

if ( strnicmp(argv[1], "newfile", 8) == 0 )
  usefile= TRUE;
else
  if ( strnicmp(argv[1], "pagfile", 8) == 0 )
    usefile= FALSE;
  else
    {
    printf("bad parameters");
    ExitProcess(0);
    }

if (usefile)
  {
  printf("using a seperate mapping file\n");
  MapFileHandle= CreateMapFile();
  }
else
  {
  printf("using the system paging swapfile to map to\n");
  MapFileHandle= (HANDLE)0xFFFFFFFF;
  }

if (MapFileHandle == NULL)
  ExitProcess(0);

hMem1= CreateMap(&MapFileHandle);
if (hMem1 == NULL)
  ExitProcess(0);

pShrMem1= MapView(&hMem1);
if (pShrMem1 == NULL)
  ExitProcess(0);

strncpy(pShrMem1, "This is an example of Named Shared Memory", 50);

ChildSucc= StartChildReader();
if (ChildSucc = FALSE)
  ExitProcess(0);

Sleep(10000);

}
