summaryrefslogtreecommitdiff
path: root/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory
diff options
context:
space:
mode:
Diffstat (limited to 'src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory')
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/CMakeLists.txt6
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/ReadProcessMemory_neg.c127
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/CMakeLists.txt19
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/ReadProcessMemory.c126
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/testinfo.dat12
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/CMakeLists.txt36
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/commonconsts.h48
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/helper.c249
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/test2.c258
-rw-r--r--src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/testinfo.dat18
12 files changed, 930 insertions, 0 deletions
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/CMakeLists.txt
new file mode 100644
index 0000000000..d2ae61f923
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/CMakeLists.txt
@@ -0,0 +1,6 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+add_subdirectory(ReadProcessMemory_neg1)
+add_subdirectory(test1)
+add_subdirectory(test2)
+
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/CMakeLists.txt
new file mode 100644
index 0000000000..400c9219f6
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ ReadProcessMemory_neg.c
+)
+
+add_executable(paltest_readprocessmemory_readprocessmemory_neg1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_readprocessmemory_readprocessmemory_neg1 coreclrpal)
+
+target_link_libraries(paltest_readprocessmemory_readprocessmemory_neg1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/ReadProcessMemory_neg.c b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/ReadProcessMemory_neg.c
new file mode 100644
index 0000000000..aecd5ad576
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/ReadProcessMemory_neg.c
@@ -0,0 +1,127 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: ReadProcessMemory_neg.c
+**
+** Purpose: Negative test the ReadProcessMemory API.
+** Call ReadProcessMemory to read unreadabel memory area
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+#define REGIONSIZE 1024
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ BOOL bResult;
+ HANDLE ProcessHandle;
+ DWORD ProcessID;
+ LPVOID lpProcessAddress = NULL;
+ char ProcessBuffer[REGIONSIZE];
+ ULONG_PTR size = 0;
+
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /*retrieve the current process ID*/
+ ProcessID = GetCurrentProcessId();
+
+ /*retrieve the current process handle*/
+ ProcessHandle = OpenProcess(
+ PROCESS_ALL_ACCESS,
+ FALSE, /*not inherited*/
+ ProcessID);
+
+ if(NULL == ProcessHandle)
+ {
+ Fail("\nFailed to call OpenProcess API to retrieve "
+ "current process handle error code=%u\n",
+ GetLastError());
+ }
+
+
+
+ /*allocate the virtual memory*/
+ lpProcessAddress = VirtualAlloc(
+ NULL, /*system determine where to allocate the region*/
+ REGIONSIZE, /*specify the size*/
+ MEM_RESERVE, /*allocation type*/
+ PAGE_READONLY); /*access protection*/
+
+ if(NULL == lpProcessAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API to allocate "
+ "virtual memory, error code=%u\n", GetLastError());
+ }
+
+ /*zero the memory*/
+ memset(ProcessBuffer, 0, REGIONSIZE);
+ /*try to retrieve the unreadable memory area*/
+ bResult = ReadProcessMemory(
+ ProcessHandle, /*current process handle*/
+ lpProcessAddress, /*base of memory area*/
+ (LPVOID)ProcessBuffer,
+ REGIONSIZE, /*buffer length in bytes*/
+ &size);
+
+
+ /*check the return value*/
+ if(0 != bResult)
+ {
+ Trace("\nFailed to call ReadProcessMemory API for a negative test, "
+ "Try to read an unreadable memory area will cause fail "
+ "but it successes\n");
+
+ err = CloseHandle(ProcessHandle);
+ if(0 == err)
+ {
+ Trace("\nFailed to call CloseHandle API, error code=%u\n",
+ GetLastError());
+ }
+
+ /*decommit the specified region*/
+ err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Trace("\nFailed to call VirtualFree API, error code=%u\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ err = CloseHandle(ProcessHandle);
+ if(0 == err)
+ {
+ Trace("\nFailed to call CloseHandle API, error code = %u\n",
+ GetLastError());
+
+ err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Trace("\nFailed to call VirtualFree API, error code=%u\n",
+ GetLastError());
+ }
+
+ Fail("");
+ }
+ /*decommit the specified region*/
+ err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API, error code=%u\n",
+ GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/testinfo.dat
new file mode 100644
index 0000000000..08c8f3291d
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/ReadProcessMemory_neg1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = ReadProcessMemory
+Name = Negative test ReadProcessMemory API to read unreadable memory area
+TYPE = DEFAULT
+EXE1 = readprocessmemory_neg
+Description
+=Test the ReadProcessMemory to read unreadable memory area
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/CMakeLists.txt
new file mode 100644
index 0000000000..8c21f01562
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/CMakeLists.txt
@@ -0,0 +1,19 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(SOURCES
+ ReadProcessMemory.c
+)
+
+add_executable(paltest_readprocessmemory_test1
+ ${SOURCES}
+)
+
+add_dependencies(paltest_readprocessmemory_test1 coreclrpal)
+
+target_link_libraries(paltest_readprocessmemory_test1
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/ReadProcessMemory.c b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/ReadProcessMemory.c
new file mode 100644
index 0000000000..c9475f13f1
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/ReadProcessMemory.c
@@ -0,0 +1,126 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: ReadProcessMemory.c
+**
+** Purpose: Positive test the ReadProcessMemory API.
+** Call ReadProcessMemory to read memory contents
+** inside current process.
+**
+**
+**============================================================*/
+#include <palsuite.h>
+
+#define REGIONSIZE 1024
+
+int __cdecl main(int argc, char *argv[])
+{
+ int err;
+ BOOL bResult;
+ HANDLE ProcessHandle;
+ DWORD ProcessID;
+ LPVOID lpProcessAddress = NULL;
+ char ProcessBuffer[REGIONSIZE];
+ ULONG_PTR size = 0;
+
+
+ /*Initialize the PAL environment*/
+ err = PAL_Initialize(argc, argv);
+ if(0 != err)
+ {
+ return FAIL;
+ }
+
+ /*retrieve the current process ID*/
+ ProcessID = GetCurrentProcessId();
+
+ /*retrieve the current process handle*/
+ ProcessHandle = OpenProcess(
+ PROCESS_VM_READ,/*access flag*/
+ FALSE, /*not inherited*/
+ ProcessID);
+
+ if(NULL == ProcessHandle)
+ {
+ Fail("\nFailed to call OpenProcess API to retrieve "
+ "current process handle error code=%u\n",
+ GetLastError());
+ }
+
+ /*allocate the virtual memory*/
+ lpProcessAddress = VirtualAlloc(
+ NULL, /*system determine where to allocate the region*/
+ REGIONSIZE, /*specify the size*/
+ MEM_COMMIT, /*allocation type*/
+ PAGE_READONLY); /*access protection*/
+
+ if(NULL == lpProcessAddress)
+ {
+ Fail("\nFailed to call VirtualAlloc API to allocate "
+ "virtual memory, error code=%u!\n", GetLastError());
+ }
+
+ /*zero the memory*/
+ memset(ProcessBuffer, 0, REGIONSIZE);
+
+ /*retrieve the memory contents*/
+ bResult = ReadProcessMemory(
+ ProcessHandle, /*current process handle*/
+ lpProcessAddress, /*base of memory area*/
+ (LPVOID)ProcessBuffer,
+ REGIONSIZE, /*buffer length in bytes*/
+ &size);
+
+ if(!bResult || REGIONSIZE != size)
+ {
+ Trace("\nFailed to call ReadProcessMemory API "
+ "to retrieve the memory contents, error code=%u\n",
+ GetLastError());
+
+ err = CloseHandle(ProcessHandle);
+ if(0 == err)
+ {
+ Trace("\nFailed to call CloseHandle API, error code=%u\n",
+ GetLastError());
+ }
+
+ /*decommit the specified region*/
+ err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Trace("\nFailed to call VirtualFree API, error code=%u\n",
+ GetLastError());
+ }
+ Fail("");
+ }
+
+ err = CloseHandle(ProcessHandle);
+ if(0 == err)
+ {
+ Trace("\nFailed to call CloseHandle API, error code = %u\n",
+ GetLastError());
+
+ err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Trace("\nFailed to call VirtualFree API, error code=%u\n",
+ GetLastError());
+ }
+
+ Fail("");
+ }
+
+ /*decommit the specified region*/
+ err = VirtualFree(lpProcessAddress, REGIONSIZE, MEM_DECOMMIT);
+ if(0 == err)
+ {
+ Fail("\nFailed to call VirtualFree API, error code=%u\n",
+ GetLastError());
+ }
+
+ PAL_Terminate();
+ return PASS;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/testinfo.dat
new file mode 100644
index 0000000000..c56920d206
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test1/testinfo.dat
@@ -0,0 +1,12 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Filemapping_memmgt
+Function = ReadProcessMemory
+Name = Positive test for ReadProcessMemory API to read memory contents
+TYPE = DEFAULT
+EXE1 = readprocessmemory
+Description
+=Test the ReadProcessMemory to read the memory contents
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/CMakeLists.txt b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/CMakeLists.txt
new file mode 100644
index 0000000000..9e0de95a0a
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/CMakeLists.txt
@@ -0,0 +1,36 @@
+cmake_minimum_required(VERSION 2.8.12.2)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(TESTSOURCES
+ test2.c
+)
+
+add_executable(paltest_readprocessmemory_test2
+ ${TESTSOURCES}
+)
+
+add_dependencies(paltest_readprocessmemory_test2 coreclrpal)
+
+target_link_libraries(paltest_readprocessmemory_test2
+ pthread
+ m
+ coreclrpal
+)
+
+
+set(HELPERSOURCES
+ helper.c
+)
+
+add_executable(paltest_readprocessmemory_test2_helper
+ ${HELPERSOURCES}
+)
+
+add_dependencies(paltest_readprocessmemory_test2_helper coreclrpal)
+
+target_link_libraries(paltest_readprocessmemory_test2_helper
+ pthread
+ m
+ coreclrpal
+)
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/commonconsts.h b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/commonconsts.h
new file mode 100644
index 0000000000..433d820f0f
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/commonconsts.h
@@ -0,0 +1,48 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: commonconsts.h
+**
+**
+**============================================================*/
+
+#ifndef _COMMONCONSTS_H_
+#define _COMMONCONSTS_H_
+
+#include <pal.h>
+#define REGIONSIZE 1024
+
+const int TIMEOUT = 40000;
+
+const WCHAR szcToHelperEvName[] = { 'T', 'o', '\0' };
+const WCHAR szcFromHelperEvName[] = { 'F', 'r', 'o', 'm', '\0' };
+
+const char initialValue = '-';
+const char nextValue = '|';
+const char guardValue = '*';
+const char *commsFileName = "AddrNLen.dat";
+
+
+/* PEDANTIC and PEDANTIC0 is a helper macro that just grumps about any
+ * zero return codes in a generic way. with little typing */
+#define PEDANTIC(function, parameters) \
+{ \
+ if (! (function parameters) ) \
+ { \
+ Trace("%s: NonFatal failure of %s%s for reasons %u and %u\n", \
+ __FILE__, #function, #parameters, GetLastError(), errno); \
+ } \
+}
+#define PEDANTIC1(function, parameters) \
+{ \
+ if ( (function parameters) ) \
+ { \
+ Trace("%s: NonFatal failure of %s%s for reasons %u and %u\n", \
+ __FILE__, #function, #parameters, GetLastError(), errno); \
+ } \
+}
+
+#endif
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/helper.c b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/helper.c
new file mode 100644
index 0000000000..59e882fc1f
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/helper.c
@@ -0,0 +1,249 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: helper.c
+**
+** Purpose: This helper process sets up a several blocks of memory,
+** then uses a file to tell its parent process where that memory is
+** So it can do a WriteProcessMemory on it. When the parent process is done
+** we check here that it was written properly.
+**
+**
+**============================================================*/
+
+#include "commonconsts.h"
+
+#include <palsuite.h>
+
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+#define LLFORMAT "%I64u"
+#else
+#define LLFORMAT "%u"
+#endif
+
+struct allhandles_t
+{
+ HANDLE hEvToHelper;
+ HANDLE hEvFromHelper;
+ char *valuesFileName;
+};
+
+
+/* function: wpmDoIt
+ *
+ * This is a general WriteProcessMemory testing function that sets up
+ * the RAM pointed to and tells the companion process on the other end
+ * of the handles in 'Comms' to attempt to alter 'lenDest' bytes at
+ * '*pDest'.
+ *
+ * '*pBuffer'[0..'lenBuffer'] is expected to be a guard region
+ * surrounding the '*pDest'[0..'lenDest'] region so that this function
+ * can verify that only the proper bytes were altered.
+ */
+
+int wpmDoIt(struct allhandles_t Comms,
+ char * pBuffer, unsigned int lenBuffer,
+ char * pDest, unsigned int lenDest,
+ const char* storageDescription)
+{
+ char *pCurr;
+ FILE *commsFile;
+ DWORD dwRet;
+
+ if (pBuffer > pDest || lenDest > lenBuffer)
+ {
+ Trace("WriteProcessMemory::DoIt() test implementation: "
+ "(pBuffer > pDest || lenDest > lenBuffer)\n");
+ return FALSE;
+ }
+
+ /* set up the storage */
+ memset(pBuffer, guardValue, lenBuffer);
+ memset(pDest, initialValue, lenDest);
+
+ /* tell the parent what RAM to adjust */
+ if(!(commsFile = fopen(Comms.valuesFileName, "w")))
+ {
+ Trace("WriteProcessMemory: fopen of '%S' failed (%u). \n",
+ Comms.valuesFileName, GetLastError());
+ return FALSE;
+ }
+ if (!fprintf(commsFile, LLFORMAT " " LLFORMAT " '%s'\n",
+ pDest, lenDest, storageDescription))
+ {
+ Trace("WriteProcessMemory: fprintf to '%S' failed (%u). \n",
+ Comms.valuesFileName, GetLastError());
+ return FALSE;
+ }
+ PEDANTIC1(fclose, (commsFile));
+
+ /* Tell the parent the data is ready for it to adjust */
+ PEDANTIC(ResetEvent, (Comms.hEvToHelper));
+ PEDANTIC(SetEvent, (Comms.hEvFromHelper));
+
+ dwRet = WaitForSingleObject(Comms.hEvToHelper, TIMEOUT); /* parent is done */
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Trace("helper WaitForSingleObjectTest: WaitForSingleObject "
+ "failed (%u)\n", GetLastError());
+ return FALSE;
+ }
+
+ /* check the stuff that SHOULD have changed */
+ for (pCurr = pDest; pCurr < (pDest + lenDest); pCurr++)
+ {
+ if ( *pCurr != nextValue)
+ {
+ Trace("When testing '%s': alteration test failed "
+ "at " LLFORMAT " offset " LLFORMAT " Found '%c' instead of '%c'\n.",
+ storageDescription, pDest, pCurr - pDest, *pCurr, nextValue);
+ Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer);
+ return FALSE;
+ }
+ }
+ /* check the stuff that should NOT have changed */
+ for (pCurr = pBuffer; pCurr < pDest; pCurr++ )
+ {
+ if ( *pCurr != guardValue)
+ {
+ Trace("When testing '%s': leading guard zone test failed "
+ "at " LLFORMAT " offset " LLFORMAT ". Found '%c' instead of '%c'\n.",
+ storageDescription, pDest, pCurr - pBuffer, *pCurr, guardValue);
+ Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer);
+ return FALSE;
+ }
+ }
+ for (pCurr = pDest + lenDest; pCurr < (pBuffer + lenBuffer); pCurr++ )
+ {
+ if ( *pCurr != guardValue)
+ {
+ Trace("When testing '%s': trailing guard zone test failed "
+ "at " LLFORMAT " offset " LLFORMAT ". Found '%c' instead of '%c'\n.",
+ storageDescription, pDest + lenDest, pCurr - pBuffer, *pCurr, guardValue);
+ Trace(" 'Altered' string: '%.*s'\n",lenBuffer, pBuffer);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ BOOL success = TRUE; /* assume success */
+ struct allhandles_t Comms = {0,0,0} ;
+
+ /* variables to track storage to alter */
+ char *pTarget = NULL;
+ unsigned int sizeTarget;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* hook up with the events created by the parent */
+ Comms.hEvToHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcToHelperEvName);
+ if (!Comms.hEvToHelper)
+ {
+ Fail("WriteProcessMemory: OpenEvent of '%S' failed (%u). "
+ "(the event should already exist!)\n",
+ szcToHelperEvName, GetLastError());
+ }
+ Comms.hEvFromHelper = OpenEventW(EVENT_ALL_ACCESS, 0, szcFromHelperEvName);
+ if (!Comms.hEvToHelper)
+ {
+ Trace("WriteProcessMemory: OpenEvent of '%S' failed (%u). "
+ "(the event should already exist!)\n",
+ szcFromHelperEvName, GetLastError());
+ success = FALSE;
+ goto EXIT;
+ }
+ Comms.valuesFileName = argv[1];
+
+ {
+ char autoAllocatedOnStack[51];
+
+ /* Get the parent process to write to the local stack */
+ success &= wpmDoIt(Comms, autoAllocatedOnStack,
+ sizeof(autoAllocatedOnStack),
+ autoAllocatedOnStack + sizeof(int),
+ sizeof(autoAllocatedOnStack) - 2 * sizeof(int),
+ "const size array on stack with int sized guards");
+ }
+
+ /* Get the parent process to write to stuff on the heap */
+ sizeTarget = 2 * sizeof(int) + 23 ; /* 23 is just a random prime > 16 */
+ if (!(pTarget = malloc(sizeTarget)))
+ {
+ Trace("WriteProcessMemory helper: unable to allocate '%s'->%d bytes of memory"
+ "(%u).\n",
+ argv[3], sizeTarget, GetLastError());
+ success = FALSE;
+ goto EXIT;
+
+ }
+ success &= wpmDoIt(Comms, pTarget, sizeTarget,
+ pTarget + sizeof(int),
+ sizeTarget - 2 * sizeof(int),
+ "array on heap with int sized guards");
+
+ /* just to be nice try something 16 - 2 * sizeof(int) bytes long */
+ {
+ char autoAllocatedOnStack[16];
+
+ /* Get the parent process to write to the local stack */
+ success &= wpmDoIt(Comms, autoAllocatedOnStack,
+ sizeof(autoAllocatedOnStack),
+ autoAllocatedOnStack + sizeof(int),
+ sizeof(autoAllocatedOnStack) - 2 * sizeof(int),
+ "another 16 byte array on stack with int sized guards inside");
+ }
+
+ /* NOTE: Don't try 0 bytes long. Win32 WriteProcessMemory claims
+ * it writes 8 bytes in that case! */
+
+ /* and 1 byte long... */
+ {
+ char autoAllocatedOnStack[1+ 2 * sizeof(int)];
+
+ /* Get the parent process to write to the local stack */
+ success &= wpmDoIt(Comms, autoAllocatedOnStack,
+ sizeof(autoAllocatedOnStack),
+ autoAllocatedOnStack + sizeof(int),
+ 1,
+ "no bytes with int sized guards outside on stack");
+ }
+
+
+EXIT:
+ /* Tell the parent that we are done */
+ if (!DeleteFile(Comms.valuesFileName))
+ {
+ Trace("helper: DeleteFile failed so parent (test1) is unlikely "
+ "to exit cleanly\n");
+ }
+ PEDANTIC(ResetEvent, (Comms.hEvToHelper));
+ if (!SetEvent(Comms.hEvFromHelper))
+ {
+ Trace("helper: SetEvent failed so parent (test1) is unlikely "
+ "to exit cleanly\n");
+ }
+
+ free(pTarget);
+ PEDANTIC(CloseHandle, (Comms.hEvToHelper));
+ PEDANTIC(CloseHandle, (Comms.hEvFromHelper));
+
+ if (!success)
+ {
+ Fail("");
+ }
+
+ PAL_Terminate();
+
+ return success ? PASS : FAIL;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/test2.c b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/test2.c
new file mode 100644
index 0000000000..eda40599ce
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/test2.c
@@ -0,0 +1,258 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+/*=============================================================
+**
+** Source: test2.c
+**
+** Purpose: Create a child process and some events for communications with it.
+** When the child gets back to us with a memory location and a length,
+** Call WriteProcessMemory on this location and check to see that it
+** writes successfully. Then call ReadProcessMemory to check if the
+** contents read are same as those written
+**
+**
+**============================================================*/
+
+#define UNICODE
+
+#include "commonconsts.h"
+
+#include <palsuite.h>
+
+#if defined(BIT64) && defined(PLATFORM_UNIX)
+#define LLFORMAT "%I64u"
+#else
+#define LLFORMAT "%u"
+#endif
+
+int __cdecl main(int argc, char *argv[])
+{
+
+ PROCESS_INFORMATION pi;
+ STARTUPINFO si;
+ HANDLE hEvToHelper;
+ HANDLE hEvFromHelper;
+ DWORD dwExitCode;
+
+ DWORD dwRet;
+ char cmdComposeBuf[MAX_PATH];
+ PWCHAR uniString;
+
+ if(0 != (PAL_Initialize(argc, argv)))
+ {
+ return FAIL;
+ }
+
+ /* Create the signals we need for cross process communication */
+ hEvToHelper = CreateEvent(NULL, TRUE, FALSE, szcToHelperEvName);
+ if (!hEvToHelper)
+ {
+ Fail("WriteProcessMemory: CreateEvent of '%S' failed. "
+ "GetLastError() returned %d.\n", szcToHelperEvName,
+ GetLastError());
+ }
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ Fail("WriteProcessMemory: CreateEvent of '%S' failed. "
+ "(already exists!)\n", szcToHelperEvName);
+ }
+ hEvFromHelper = CreateEvent(NULL, TRUE, FALSE, szcFromHelperEvName);
+ if (!hEvToHelper)
+ {
+ Fail("WriteProcessMemory: CreateEvent of '%S' failed. "
+ "GetLastError() returned %d.\n", szcFromHelperEvName,
+ GetLastError());
+ }
+ if (GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ Fail("WriteProcessMemory: CreateEvent of '%S' failed. "
+ "(already exists!)\n", szcFromHelperEvName);
+ }
+ ResetEvent(hEvFromHelper);
+ ResetEvent(hEvToHelper);
+
+ if (!sprintf(cmdComposeBuf, "helper %s", commsFileName))
+ {
+ Fail("Could not convert command line\n");
+ }
+ uniString = convert(cmdComposeBuf);
+
+ ZeroMemory( &si, sizeof(si) );
+ si.cb = sizeof(si);
+ ZeroMemory( &pi, sizeof(pi) );
+
+ /* Create a new process. This is the process that will ask for
+ * memory munging */
+ if(!CreateProcess( NULL, uniString, NULL, NULL,
+ FALSE, 0, NULL, NULL, &si, &pi))
+ {
+ Trace("ERROR: CreateProcess failed to load executable '%S'. "
+ "GetLastError() returned %u.\n",
+ uniString, GetLastError());
+ free(uniString);
+ Fail("");
+ }
+ free(uniString);
+
+
+ while(1)
+ {
+ FILE *commsFile;
+ char* pSrcMemory;
+ char* pDestMemory;
+ SIZE_T Count;
+ SIZE_T wpmCount;
+ char incomingCMDBuffer[MAX_PATH + 1];
+
+ int err;
+ HANDLE readProcessHandle;
+ DWORD readProcessID;
+ char readProcessBuffer[REGIONSIZE]; // size 1024
+ BOOL bResult;
+ size_t size = 0;
+
+ readProcessID = pi.dwProcessId;
+
+ /* wait until the helper tells us that it has given us
+ * something to do */
+ dwRet = WaitForSingleObject(hEvFromHelper, TIMEOUT);
+ if (dwRet != WAIT_OBJECT_0)
+ {
+ Trace("test1 WaitForSingleObjectTest: WaitForSingleObject "
+ "failed (%u)\n", GetLastError());
+ break; /* no more work incoming */
+ }
+
+ /* get the parameters to test WriteProcessMemory with */
+ if (!(commsFile = fopen(commsFileName, "r")))
+ {
+ /* no file means there is no more work */
+ break;
+ }
+ if ( NULL == fgets(incomingCMDBuffer, MAX_PATH, commsFile))
+ {
+ Fail ("unable to read from communication file %s "
+ "for reasons %u & %u\n",
+ errno, GetLastError());
+ }
+ PEDANTIC1(fclose,(commsFile));
+ sscanf(incomingCMDBuffer, LLFORMAT " " LLFORMAT, &pDestMemory, &Count);
+ if (argc > 1)
+ {
+ Trace("Preparing to write to " LLFORMAT " bytes @ " LLFORMAT "('%s')\n",
+ Count, pDestMemory, incomingCMDBuffer);
+ }
+
+ /* compose some data to write to the client process */
+ if (!(pSrcMemory = malloc(Count)))
+ {
+ Trace("could not dynamically allocate memory to copy from "
+ "for reasons %u & %u\n",
+ errno, GetLastError());
+ goto doneIteration;
+ }
+ memset(pSrcMemory, nextValue, Count);
+ Trace("Preparing to write to " LLFORMAT " bytes @ " LLFORMAT " ('%s')[%u]\n",
+ Count, pDestMemory, incomingCMDBuffer, pSrcMemory);
+
+ /* do the work */
+ dwRet = WriteProcessMemory(pi.hProcess,
+ pDestMemory,
+ pSrcMemory,
+ Count,
+ &wpmCount);
+
+ if (!dwRet)
+ {
+ Trace("%s: Problem: on a write to "LLFORMAT " bytes @ " LLFORMAT " ('%s')\n",
+ argv[0], Count, pDestMemory, incomingCMDBuffer);
+ Trace("test1 WriteProcessMemory returned a (!=0) (GLE=%u)\n",
+ GetLastError());
+ }
+ if(Count != wpmCount)
+ {
+ Trace("%s: Problem: on a write to " LLFORMAT " bytes @ " LLFORMAT " ('%s')\n",
+ argv[0], Count, pDestMemory, incomingCMDBuffer);
+ Trace("The number of bytes written should have been "
+ LLFORMAT ", but was reported as " LLFORMAT " \n", Count, wpmCount);
+ }
+
+ readProcessHandle = OpenProcess(
+ PROCESS_VM_READ,
+ FALSE,
+ readProcessID);
+
+ if(NULL == readProcessHandle)
+ {
+ Fail("\nFailed to call OpenProcess API to retrieve "
+ "current process handle error code=%u\n",
+ GetLastError());
+ }
+
+ /*zero the memory*/
+ memset(readProcessBuffer, 0, size);
+
+ /*retrieve the memory contents*/
+ bResult = ReadProcessMemory(
+ readProcessHandle, /*current process handle*/
+ pDestMemory, /*base of memory area*/
+ (LPVOID)readProcessBuffer,
+ Count, /*buffer length in bytes*/
+ &size);
+
+
+ if( !bResult || (Count != size) )
+ {
+ Trace("\nFailed to call ReadProcessMemory API "
+ "to retrieve the memory contents, error code=%u; Bresult[%u] Count[" LLFORMAT "], Size[%d]\n",
+ GetLastError(), bResult, Count, size);
+
+ err = CloseHandle(readProcessHandle);
+
+ if(0 == err)
+ {
+ Trace("\nFailed to call CloseHandle API, error code=%u\n",
+ GetLastError());
+ }
+ dwExitCode = FAIL;
+ }
+
+ if( !memcmp (pDestMemory, readProcessBuffer, Count ) )
+ {
+ Trace("Difference in memory contents, expected [%s], but received [%s]\n", pDestMemory, readProcessBuffer);
+ dwExitCode = FAIL;
+ }
+
+ Trace("ReadProcessBuffer contains [%s]\n", readProcessBuffer);
+ err = CloseHandle(readProcessHandle);
+
+ free(pSrcMemory);
+
+ doneIteration:
+ PEDANTIC(ResetEvent, (hEvFromHelper));
+ PEDANTIC(SetEvent, (hEvToHelper));
+ }
+
+ /* wait for the child process to complete */
+ WaitForSingleObject ( pi.hProcess, TIMEOUT );
+ /* this may return a failure code on a success path */
+
+ /* check the exit code from the process */
+ if( ! GetExitCodeProcess( pi.hProcess, &dwExitCode ) )
+ {
+ Trace( "GetExitCodeProcess call failed with error code %u\n",
+ GetLastError() );
+ dwExitCode = FAIL;
+ }
+
+
+ PEDANTIC(CloseHandle, (hEvToHelper));
+ PEDANTIC(CloseHandle, (hEvFromHelper));
+ PEDANTIC(CloseHandle, (pi.hThread));
+ PEDANTIC(CloseHandle, (pi.hProcess));
+
+ PAL_TerminateEx(dwExitCode);
+ return dwExitCode;
+}
diff --git a/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/testinfo.dat b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/testinfo.dat
new file mode 100644
index 0000000000..58a9935a08
--- /dev/null
+++ b/src/pal/tests/palsuite/filemapping_memmgt/ReadProcessMemory/test2/testinfo.dat
@@ -0,0 +1,18 @@
+# Licensed to the .NET Foundation under one or more agreements.
+# The .NET Foundation licenses this file to you under the MIT license.
+# See the LICENSE file in the project root for more information.
+
+Version = 1.0
+Section = Debug
+Function = ReadProcessMemory
+Name = Check that writing/reading text to/from process memory succeeds.
+TYPE = DEFAULT
+EXE1 = test2
+EXE2 = helper
+Description
+= Create a child process and attempt to write to its memory
+= at the places and lengths it specifies via a data file.
+= the child verifies that all the specified memory was altered
+= with no overruns. Parent then tries to read memory from child
+= and does memory compare to ensure it read memory contents
+= correctly