--- a +++ b/SharedMemoryWinCpp/MyShmExample.cpp @@ -0,0 +1,237 @@ +// MyShmExample.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" +#include <Windows.h> +#include <Windowsx.h> +#include <stdio.h> +#include <conio.h> +#include <stdlib.h> + +#if 0 +//Beispiel wie man mit eingeschalteter UAC für den lokalen Prozess die erforderlichen Rechte anfordern kann. +static void* BuildSDForAccessToAllAuthenticatedUsers(SECURITY_DESCRIPTOR* pSD) +{ +#if defined (_WIN32_WCE) + return NULL; +#else + DWORD dwAclLength; + PSID pAuthenticatedUsersSID = NULL; + PACL pDACL = NULL; + BOOL bResult = FALSE; + PACCESS_ALLOWED_ACE pACE = NULL; + SID_IDENTIFIER_AUTHORITY siaNT = SECURITY_NT_AUTHORITY; + + SECURITY_INFORMATION si = DACL_SECURITY_INFORMATION; + + // initialize the security descriptor + if (InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) + { + // obtain a sid for the Authenticated Users Group + if (AllocateAndInitializeSid(&siaNT, 1, SECURITY_AUTHENTICATED_USER_RID, 0, 0, + 0, 0, 0, 0, 0, &pAuthenticatedUsersSID)) + { + // NOTE: + // + // The Authenticated Users group includes all user accounts that + // have been successfully authenticated by the system. If access + // must be restricted to a specific user or group other than + // Authenticated Users, the SID can be constructed using the + // LookupAccountSid() API based on a user or group name. + + // calculate the DACL length + dwAclLength = sizeof(ACL) + // add space for Authenticated Users group ACE + + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + + GetLengthSid(pAuthenticatedUsersSID); + + // allocate memory for the DACL + pDACL = (PACL) malloc(dwAclLength); + if (pDACL) + { + // initialize the DACL + if (InitializeAcl(pDACL, dwAclLength, ACL_REVISION)) + { + // add the Authenticated Users group ACE to the DACL with + // GENERIC_READ, GENERIC_WRITE, and GENERIC_EXECUTE access + if (AddAccessAllowedAce(pDACL, ACL_REVISION, + GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | SECTION_ALL_ACCESS, + pAuthenticatedUsersSID)) + { + if (SetSecurityDescriptorDacl(pSD, TRUE, pDACL, FALSE)) + bResult = TRUE; + } + } + } + } + } + + if (!bResult) + { + if (pAuthenticatedUsersSID) + FreeSid(pAuthenticatedUsersSID); + + if (pDACL) + { + free(pDACL); + pDACL = NULL; + } + } + return pDACL; +#endif +} +#endif + +#include <WtsApi32.h> +/* help functions for shared memory on windows vista */ +typedef struct _COPIED_WTS_SESSION_INFO { + DWORD SessionId; + LPSTR pWinStationName; /* A-function, so we have a char-string */ + DWORD dummy; /* originally an enum */ +} COPIED_WTS_SESSION_INFO, *PCOPIED_WTS_SESSION_INFO; + +BOOL LocalSysCreateNamedShm(char* szName, unsigned long ulSize, HANDLE* phShmHandle, void** ppUserSpace) +{ + HANDLE hProcess; + unsigned long lMinimumWorkingSetSize; + unsigned long lMaximumWorkingSetSize; + // the global... is needed for the following case: + // - runtime is running as a system service (the default for the plcwinnt) + // - runtime wants to communicate with a process that does not run under the system accout + // -> Will fail because of the different namespaces, at least in Windows Vista! + // Problem occurred in the Targetvisu that is started from the service unter Vista + + char szNameBuffer[MAX_PATH]; + char szGlobalPrefix[] = "Global\\"; + char szSessionPrefix[] = "Session\\"; + + strcpy(szNameBuffer, szGlobalPrefix); + strcat(szNameBuffer, szName); + + // prefer the global entry and afterwards check for the local name + *phShmHandle = OpenFileMapping(FILE_MAP_WRITE, TRUE, szNameBuffer); + if (*phShmHandle == 0) + *phShmHandle = OpenFileMapping(FILE_MAP_WRITE, TRUE, szName); + + // check if a shared memory exists in any active user session + if (*phShmHandle == 0) + { + /* walk over all sessions to check if the shared memory is opened somewhere */ + COPIED_WTS_SESSION_INFO* pResult; + DWORD dwCount; + DWORD i; + + WTSEnumerateSessions(0 /* current machine */, 0, 1, (WTS_SESSION_INFO**)&pResult, &dwCount); + + for (i = 0; i < dwCount; ++i) + { + char szTemp[15]; + strcpy(szNameBuffer, szSessionPrefix); + strcat(szNameBuffer, _itoa((int) pResult[i].SessionId, szTemp, 10)); + strcat(szNameBuffer, "\\"); + strcat(szNameBuffer, szName); + + *phShmHandle = OpenFileMapping(FILE_MAP_WRITE, TRUE, szNameBuffer); + if (*phShmHandle != 0) + break; + } + + WTSFreeMemory(pResult); + } + + if (*phShmHandle == 0) + { +#if 0 + //See examlpe above how to obtain a security descriptor. + SECURITY_ATTRIBUTES sa; + SECURITY_ATTRIBUTES* psa = NULL; + if (s_pSecurityDescriptorData) + { + sa.nLength = sizeof(sa); + sa.bInheritHandle = FALSE; + sa.lpSecurityDescriptor = &s_SecurityDescriptor; + psa = &sa; + } +#endif + + //*phShmHandle = CreateFileMapping((HANDLE)0xffffffff, psa, PAGE_READWRITE, 0, ulSize, szName); + *phShmHandle = CreateFileMapping((HANDLE)0xffffffff, NULL, PAGE_READWRITE, 0, ulSize, szName); + } + + if (*phShmHandle == 0) + { + return FALSE; + } + *ppUserSpace = MapViewOfFile((HANDLE)*phShmHandle, FILE_MAP_WRITE, 0, 0, 0); + if (*ppUserSpace == NULL) + { + return FALSE; + } + + hProcess = GetCurrentProcess(); + GetProcessWorkingSetSize(hProcess, (PSIZE_T)&lMinimumWorkingSetSize, (PSIZE_T)&lMaximumWorkingSetSize); + if (lMinimumWorkingSetSize <= ulSize) + { + lMinimumWorkingSetSize = ulSize + 0x10000UL; + if(lMaximumWorkingSetSize <= lMinimumWorkingSetSize) + { + lMaximumWorkingSetSize = lMinimumWorkingSetSize + 0x1000000UL; + } + if (!SetProcessWorkingSetSize(hProcess, lMinimumWorkingSetSize, lMaximumWorkingSetSize)) + { + DWORD dwError = GetLastError(); + /* return 0; When this call produces an error, everything still seems to work, but returning 0 will lead to a crash of Targetvisu.*/ + } + } + /* Lock memory mapped file */ + if (!VirtualLock((LPVOID)*ppUserSpace, ulSize)) + { + DWORD dwError = GetLastError(); + /* TOCHECK: Don't know why locking does not work for SHM larger than 1MB */ + /*return 0;*/ + } + + return TRUE; +} + + + +struct DataExchangeStruct +{ + INT32 i1; + INT32 i2; +}; +int main(int argc, char* argv[]) +{ + HANDLE hShmRead, hShmWrite; + DataExchangeStruct* pDESRead = NULL; + DataExchangeStruct* pDESWrite = NULL; + + printf("Opening Shared Memory _CODESYS_SharedMemoryTest_Write (means a memory mapped file)...\n"); + LocalSysCreateNamedShm("_CODESYS_SharedMemoryTest_Write",sizeof(DataExchangeStruct),&hShmRead,(void**)&pDESRead); + printf("ShmPointer: 0x%X, handle: 0x%X \n",pDESRead,pDESRead); + + printf("Opening Shared Memory _CODESYS_SharedMemoryTest_Read (means a memory mapped file)...\n"); + LocalSysCreateNamedShm("_CODESYS_SharedMemoryTest_Read",sizeof(DataExchangeStruct),&hShmWrite,(void**)&pDESWrite); + printf("ShmPointer: 0x%X, handle: 0x%X \n",pDESWrite,hShmWrite); + + if(pDESRead == NULL) + { + printf("Could not Created SHM!\r\n"); + return 1; + } + + while(!_kbhit()) + { + printf("Read: i1:%d, i2:%d Write: i1:%d, i2:%d \r", pDESRead->i1, pDESRead->i2, pDESWrite->i1, pDESWrite->i2); + pDESWrite->i1++; + if(pDESWrite->i1 > 1000) + pDESWrite->i1 = 0; + pDESWrite->i2--; + if(pDESWrite->i2 < -1000) + pDESWrite->i2 = 0; + Sleep(200); + } + return 0; +} +