114 Commits

Author SHA1 Message Date
Dmitry Nagibin a8da72d503 Added getting code base address API function to manage handles on other side 2021-01-11 20:27:05 +03:00
Dmitry Nagibin 59307f0a63 Merge remote-tracking branch 'github/secure_crt' 2021-01-10 17:51:01 +03:00
HotKeyIt 47a9ee83db Fix SectionAlignment
Some dlls do not use Native SectionAlignment, instead use SectionAlignment from PE.
2020-11-07 21:19:48 +01:00
Simon Rozman 08a59f2922 Fix loading of DLLs that export all functions by ordinal
See-also: https://github.com/fancycode/MemoryModule/pull/96
Signed-off-by: Simon Rozman <simon@rozman.si>
2020-11-07 21:19:48 +01:00
Simon Rozman 5e850c0b76 Implement IMAGE_REL_BASED_THUMB_MOV32 relocation
Signed-off-by: Simon Rozman <simon@rozman.si>
2020-11-07 21:19:48 +01:00
Simon Rozman 0a984057da Implement IMAGE_REL_BASED_LOW relocation
Signed-off-by: Simon Rozman <simon@rozman.si>
2020-11-07 21:19:48 +01:00
Simon Rozman fdf41455e9 Allow IMAGE_REL_BASED_DIR64 relocation on all platforms
Signed-off-by: Simon Rozman <simon@rozman.si>
2020-11-07 21:19:48 +01:00
Simon Rozman acd7da679a Fix DEBUG_OUTPUT
Signed-off-by: Simon Rozman <simon@rozman.si>
2020-11-07 21:02:14 +01:00
Simon Rozman fef80b544b Add ARM and ARM64 platforms
Signed-off-by: Simon Rozman <simon@rozman.si>
2020-11-07 20:58:15 +01:00
Joachim Bauch 5f83e41c3a Merge pull request #92 from fancycode/ci-xenial
CI: Upgrade to Ubuntu Xenial and use latest wine-stable
2019-02-24 15:35:09 +01:00
Joachim Bauch 316aa59c48 Get latest stable version of Wine when testing. 2019-02-24 15:28:59 +01:00
Joachim Bauch 9f37952407 Switch to Xenial for CI runs. 2019-02-24 15:07:24 +01:00
Joachim Bauch d1a0824733 Fix version for AppVeyor. 2019-02-24 13:49:51 +01:00
Joachim Bauch e4c1b3566c Merge pull request #84 from ianhbell/patch-1
Make .h file accessible to superprojects
2018-05-18 09:18:18 +02:00
Ian Bell a15e0769b0 Make .h file accessible to superprojects
As is, you need to add_subdirectory and also add the include, this kills two birds with one stone
2018-05-18 00:37:57 -06:00
Joachim Bauch e039372355 Merge pull request #81 from Scavanger/case-sensitive-function-names
Search for function names should be case sensitive (fixes #80).
2018-03-08 14:04:50 +01:00
Scavanger 060f0bd736 Search for function names should be case sensitive 2018-03-08 13:23:39 +01:00
Joachim Bauch 403a31e7bb Run with sudo enabled.
This fixes an issue where running wine fails on i386 with

/usr/bin/wine: error while loading shared libraries: libwine.so.1:
cannot create shared object descriptor: Operation not permitted
2018-02-14 21:58:51 +01:00
Joachim Bauch e7d53b53e0 Only install packages necessary for job. 2018-02-14 21:58:51 +01:00
Joachim Bauch 0acf4e7785 Fix typo. 2018-02-14 20:52:52 +01:00
Joachim Bauch 663ddca84b Update WINEPATH for Trusty. 2018-02-14 20:49:55 +01:00
Joachim Bauch 9ecfeb025d Remove all object files on clean. 2018-02-14 20:41:25 +01:00
Joachim Bauch 9e295953a8 Prevent memory of library from spanning over 4GB bounaries.
Based on code from #67 / #79, fixes #63.
2018-02-14 20:31:28 +01:00
Joachim Bauch 55577d939c Merge pull request #76 from fancycode/binsearch_export_names
Implement binary search for looking up exports by name.
2017-11-02 22:09:42 +01:00
Joachim Bauch ac78ea10e7 Add test that loads a dll with lots of exports. 2017-11-02 21:49:44 +01:00
Joachim Bauch 98b95eca4c Implement binary search for looking up exports by name.
Code based on #74 which contained code from py2exe.
2017-11-02 21:02:26 +01:00
Joachim Bauch 0884dccfa7 Update mingw -dev package for Trusty. 2017-11-02 20:15:22 +01:00
Joachim Bauch 00bc61e8c7 Merge pull request #70 from ForNeVeR/patch-1
readme: fix the doc file name
2017-07-17 08:46:59 +02:00
Friedrich von Never 2bbbc205d6 readme: fix the doc file name 2017-07-15 18:56:54 +07:00
Joachim Bauch 7d0c143f92 Need stdlib.h on MinGW. 2016-09-21 01:12:11 +02:00
Joachim Bauch 2ecf5b764b Use secure CRT functions for string copying. 2016-09-21 00:19:52 +02:00
Joachim Bauch 5c6b699b36 Merge pull request #51 from fancycode/cmake_testsuite
Also build and run testsuite on cmake CI tests.
2016-09-20 23:38:38 +02:00
Joachim Bauch 184113ca09 Also build and run testsuite on cmake CI tests. 2016-09-20 23:18:23 +02:00
Joachim Bauch f5c9db8b5c Simplfy some casting code, updated comments about 32/64 bit. 2016-09-20 22:36:55 +02:00
Joachim Bauch 6c4ab3589d Added testcase to load image above 32bit. 2016-09-20 22:18:42 +02:00
Joachim Bauch 8d609dc2a2 Use script to run wine. 2016-09-20 01:34:42 +02:00
Joachim Bauch 5ce3707c7d MSVC again - "static const" can not be used as array size. 2016-09-20 01:23:24 +02:00
Joachim Bauch d9dcc0eb8c Don't use "static const <type>", breaks on MSVC. 2016-09-20 01:17:12 +02:00
Joachim Bauch e2826eb956 Fix MSVC compiler error. 2016-09-20 01:15:26 +02:00
Joachim Bauch 49a82873f7 Use "size_t" instead of "long" for sizes. 2016-09-20 01:05:09 +02:00
Joachim Bauch 4074f1e6ab Simplify conditional compiled code a bit. 2016-09-20 01:00:39 +02:00
Joachim Bauch caf917707b Replace defines with static consts. 2016-09-20 00:54:28 +02:00
Joachim Bauch 221a470ad1 Merge pull request #50 from fancycode/fix_64bit_warnings
Fix various 64bit issues
2016-09-20 00:39:52 +02:00
Joachim Bauch 097403a8ad Added wrapper to run wine/wine64. 2016-09-20 00:23:29 +02:00
Joachim Bauch 6c2c3e2fee Fix more potential conversion issues on 64bit. 2016-09-20 00:23:29 +02:00
Joachim Bauch 03cd7c91d9 Fixed alignment of values/addresses on 64bit systems. 2016-09-20 00:23:29 +02:00
Joachim Bauch de5dbce770 Error on some type conversion warnings. 2016-09-20 00:23:29 +02:00
Joachim Bauch 89883558fe Merge pull request #48 from fancycode/appveyor-vc9
Also run CI against Visual Studio 2008.
2016-09-19 22:58:32 +02:00
Joachim Bauch b26476ff8d Also run CI against Visual Studio 9. 2016-09-19 22:43:29 +02:00
Joachim Bauch 1d19f9f750 Pass PLATFORM/UNICODE to cmake. 2016-09-19 22:43:01 +02:00
Joachim Bauch d19c62ed82 Fixed detection of x64 platform. 2016-09-19 22:27:02 +02:00
Joachim Bauch cfba548c66 Merge pull request #49 from fancycode/appveyor-script
Move AppVeyor test code to script.
2016-09-19 22:07:25 +02:00
Joachim Bauch af2c521cf2 Added .gitattributes file. 2016-09-19 21:55:22 +02:00
Joachim Bauch 164b21ac07 Move AppVeyor test code to script. 2016-09-19 21:55:22 +02:00
Joachim Bauch c4074afd3e Merge pull request #47 from sakurai-youhei/hotfix/issue-45-remove-stdint_h
Remove stdint.h for VC++9.0 (VS2008)
2016-09-12 18:02:14 +02:00
Youhei Sakurai c174ed1177 Remove stdint.h for VC++9.0 (VS2008) 2016-09-13 00:50:13 +09:00
Joachim Bauch 4b3d2a08d5 Merge pull request #33 from joankaradimov/custom-alloc-and-free
Pass alloc/free functions to MemoryLoadLibraryEx
2016-04-24 15:30:16 +02:00
Joan Karadimov a1fb42d4c5 Add some tests for the custom free and alloc functions 2016-02-14 00:40:30 +02:00
Joan Karadimov bc38a6b01d Extract a ReadLibrary function in DllLoader.cpp 2016-02-13 18:39:40 +02:00
Joan Karadimov d46b74d00d Pass alloc/free functions to MemoryLoadLibraryEx 2016-02-12 11:39:41 +02:00
Joachim Bauch d88817fbf7 Disable C4055 warning (data -> function pointer conversion). 2016-01-27 00:57:06 +01:00
Joachim Bauch d9a6bb9c8f Explicitly include "stdint.h" to make sure "uintptr_t" is defined (fixes #34). 2016-01-27 00:44:43 +01:00
Joachim Bauch 905ad75e82 Expose default callback functions.
This was suggested in #33.
2016-01-27 00:38:37 +01:00
Joachim Bauch 2e193f153a Also build on MSVC 2015. 2015-12-20 22:13:27 +01:00
Joachim Bauch cc562219af Fix C4055 on MSVC. 2015-12-20 22:07:30 +01:00
Joachim Bauch cddc54a671 Fixed syntax error on MSVC. 2015-12-20 21:51:29 +01:00
Joachim Bauch 5bda2104b9 Define "_CRT_SECURE_NO_WARNINGS" when compiling examples/tests. 2015-12-20 21:43:35 +01:00
Joachim Bauch 394fae8d51 Initialize variable (to make MSVC happy). 2015-12-20 21:39:47 +01:00
Joachim Bauch 15983313f4 Removed debug include. 2015-12-20 21:38:30 +01:00
Joachim Bauch 583e1b4a93 Fixed warning about unreferenced parameters. 2015-12-20 21:34:14 +01:00
Joachim Bauch bc04853584 Add some checks to prevent overruns on broken input. 2015-12-20 21:26:53 +01:00
Joachim Bauch 9df6e7dc93 Add more error checking of return values. 2015-12-20 21:26:53 +01:00
Joachim Bauch f02a8e6a38 Merge pull request #30 from kost/fix-deprecated-wcsnicmp
Use _wcsnicmp instead of wcsnicmp
2015-10-22 15:54:08 +02:00
Vlatko Kosturjak 71643ae62b Use _wcsnicmp instead of wcsnicmp
"These POSIX functions are deprecated. Use the ISO C++ conformant"
https://msdn.microsoft.com/en-us/library/ms235324.aspx
2015-10-18 11:13:24 +02:00
Joachim Bauch d19707369a Avoid (re-)allocations when searching for named resources.
Also add tests to load resources by name.
2015-08-23 00:22:42 +02:00
Joachim Bauch 8d5dbf39e8 Show AppVeyor status of master branch. 2015-08-23 00:02:04 +02:00
Joachim Bauch 62e357e515 Added information about build status. 2015-08-22 23:56:52 +02:00
Joachim Bauch b4bf2f7c4a Don't disable warnings about conversions. 2015-08-22 23:53:27 +02:00
Joachim Bauch 422f918c33 Declare variables at start of function. 2015-08-22 23:53:27 +02:00
Joachim Bauch a13ad18e11 Added AppVeyor CI integration. 2015-08-22 23:53:27 +02:00
Joachim Bauch 8c3d253325 Support building with cmake. 2015-08-22 01:00:13 +02:00
Joachim Bauch 70c4977019 Switch to container-based infrastructure. 2015-08-22 00:18:37 +02:00
Joachim Bauch 5a0c512885 Revert 78330cd2f1, package names don't match platform. 2015-08-22 00:02:25 +02:00
Joachim Bauch 78330cd2f1 Simplify package installation. 2015-08-21 23:59:29 +02:00
Joachim Bauch db9c2389f2 Fix compilation of tests with UNICODE defined. 2015-08-21 23:57:15 +02:00
Joachim Bauch 83899ac7f7 Use DWORD directly to avoid cast. 2015-08-21 22:26:50 +02:00
Joachim Bauch 6276f4426d Support imports by ordinal value.
Code based on pull-request #28.
2015-08-21 22:19:28 +02:00
Joachim Bauch e5d42852de Merge pull request #26 from CoolOppo/patch-1
Rename readme.txt to readme.rst
2015-04-07 09:47:41 +02:00
CoolOppo 48d3c5a7f6 Rename readme.txt to readme.rst
Makes GitHub actually render the file correctly 😒
2015-04-06 15:39:48 -04:00
Joachim Bauch 82b11d57db Call "VirtualFree" before setting error (fixes #23). 2015-03-13 16:56:02 +01:00
Joachim Bauch 0ce2454fc3 Merge pull request #24 from Fr0sT-Brutal/patch-1
Zero the memory allocated in the heap
2015-03-13 16:47:51 +01:00
Fr0sT-Brutal 89e02fcd9e Zero the memory allocated in the heap
Using HEAP_ZERO_MEMORY parameter of HeapAlloc function we can fill all the struct contents with zeros thus removing possible bugs with uninitialized members and slightly shortening/speeding up the code
2015-03-12 20:11:05 +03:00
Joachim Bauch dc173cad6d Disable alignment of 1000 bytes for now, failing in Travis. 2015-03-01 01:57:11 +01:00
Joachim Bauch d9dc0b0270 Setup additional environment flags for wine. 2015-03-01 01:16:33 +01:00
Joachim Bauch 31cbe89bfe Run tests before checking samples manually. 2015-03-01 01:08:48 +01:00
Joachim Bauch 2da44d00e9 Run more tests with sample DLLs. 2015-03-01 01:04:17 +01:00
Joachim Bauch 36574a5638 Handle case where resource to load is NULL. 2015-03-01 00:32:38 +01:00
Joachim Bauch 463447c1ed Reduced scope of variable. 2015-03-01 00:04:38 +01:00
Joachim Bauch d321abf8fa Added more error handling, changed boolean variables to "BOOL", bail our early from functions where possible. 2015-02-28 23:59:06 +01:00
Joachim Bauch aa6b93bab4 Support section alignments that are smaller than the memory page size (fixes #20/#21). 2015-02-28 23:01:44 +01:00
Joachim Bauch 927bd2a9f0 Link using "g++" to get reloc information. 2015-02-27 01:34:33 +01:00
Joachim Bauch dd5e818dfc Need to specify build matrix differently. 2015-02-27 00:56:39 +01:00
Joachim Bauch 4c08d8eb92 Also build UNICODE versions. 2015-02-27 00:55:13 +01:00
Joachim Bauch 625aa47035 Use "uintptr_t" instead of custom type. 2015-02-27 00:55:13 +01:00
Joachim Bauch dacdbaba9a Deny loading any other architecture than 64bit if compiled for 64bit. 2015-02-27 00:55:13 +01:00
Joachim Bauch 6212358a24 Use function from tchar.h instead of #ifdef. 2015-02-27 00:55:13 +01:00
Joachim Bauch 808c043faf Fixed indentation. 2015-02-27 00:55:13 +01:00
Joachim Bauch dcccd79158 Merge pull request #22 from dismantl/findresource-bugfix
small fix relating to searching memory-loaded modules for named resources
2015-02-27 00:23:06 +01:00
Joachim Bauch b889c72727 Bump year in copyright. 2015-02-27 00:22:03 +01:00
Joachim Bauch 3422b5791c Show build status. 2015-02-27 00:20:35 +01:00
Joachim Bauch 52b0379749 Added travis configuration. 2015-02-27 00:05:11 +01:00
Dan Staples 1d55f77753 small fix relating to searching IMAGE_RESOURCE_DIRECTORY_ENTRYs for named resources 2015-01-05 20:29:46 -05:00
Joachim Bauch 5a448ce93a Support loading (and running) EXE files (fixes #7). 2014-09-21 18:34:11 +02:00
Joachim Bauch 2d504b533e Check architecture of library to load. 2014-09-21 17:33:18 +02:00
29 changed files with 2103 additions and 331 deletions
+11
View File
@@ -0,0 +1,11 @@
* text=auto
# Native line endings.
*.c text
*.cpp text
*.h text
*.rc text
# Windows line endings.
*.bat text eol=crlf
*.eln text eol=crlf
+5
View File
@@ -1,3 +1,8 @@
*.o
*.obj
*.exe
tests/*.dll
tests/*.res
tests/SampleExports.cpp
tests/SampleExports.h
+95
View File
@@ -0,0 +1,95 @@
sudo: true
matrix:
include:
- env: PLATFORM=x86_64 UNICODE= CMAKE= WINE_PACKAGE=winehq-stable:amd64
addons:
apt:
packages:
- binutils-mingw-w64-x86-64
- mingw-w64-x86-64-dev
- g++-mingw-w64-x86-64
- gcc-mingw-w64-x86-64
- env: PLATFORM=i686 UNICODE= CMAKE= WINE_PACKAGE=winehq-stable:i386
addons:
apt:
packages:
- binutils-mingw-w64-i686
- mingw-w64-i686-dev
- g++-mingw-w64-i686
- gcc-mingw-w64-i686
- env: PLATFORM=x86_64 UNICODE=1 CMAKE= WINE_PACKAGE=winehq-stable:amd64
addons:
apt:
packages:
- binutils-mingw-w64-x86-64
- mingw-w64-x86-64-dev
- g++-mingw-w64-x86-64
- gcc-mingw-w64-x86-64
- env: PLATFORM=i686 UNICODE=1 CMAKE= WINE_PACKAGE=winehq-stable:i386
addons:
apt:
packages:
- binutils-mingw-w64-i686
- mingw-w64-i686-dev
- g++-mingw-w64-i686
- gcc-mingw-w64-i686
- env: PLATFORM=x86_64 UNICODE= CMAKE=1 WINE_PACKAGE=winehq-stable:amd64
addons:
apt:
packages:
- binutils-mingw-w64-x86-64
- mingw-w64-x86-64-dev
- g++-mingw-w64-x86-64
- gcc-mingw-w64-x86-64
- env: PLATFORM=i686 UNICODE= CMAKE=1 WINE_PACKAGE=winehq-stable:i386
addons:
apt:
packages:
- binutils-mingw-w64-i686
- cmake
- mingw-w64-i686-dev
- g++-mingw-w64-i686
- gcc-mingw-w64-i686
- env: PLATFORM=x86_64 UNICODE=1 CMAKE=1 WINE_PACKAGE=winehq-stable:amd64
addons:
apt:
packages:
- binutils-mingw-w64-x86-64
- cmake
- mingw-w64-x86-64-dev
- g++-mingw-w64-x86-64
- gcc-mingw-w64-x86-64
- env: PLATFORM=i686 UNICODE=1 CMAKE=1 WINE_PACKAGE=winehq-stable:i386
addons:
apt:
packages:
- binutils-mingw-w64-i686
- cmake
- mingw-w64-i686-dev
- g++-mingw-w64-i686
- gcc-mingw-w64-i686
language: cpp
dist: xenial
cache:
- apt
- ccache
before_script:
- curl https://dl.winehq.org/wine-builds/winehq.key | sudo apt-key add -
- echo "deb https://dl.winehq.org/wine-builds/ubuntu/ xenial main" | sudo tee /etc/apt/sources.list.d/winehq.list
- sudo apt-get -y update && sudo apt-get -y install --install-recommends $WINE_PACKAGE
- if [ ! -z "$CMAKE" ]; then cmake -DPLATFORM=$PLATFORM -DUNICODE=$UNICODE -DTESTSUITE=ON -H. -B.; fi
script:
- if [ -z "$CMAKE" ]; then make PLATFORM=$PLATFORM UNICODE=$UNICODE; fi
- if [ -z "$CMAKE" ]; then make test PLATFORM=$PLATFORM UNICODE=$UNICODE; fi
- if [ ! -z "$CMAKE" ]; then cmake --build .; fi
- cd example/DllLoader
- ../../tests/runwine.sh $PLATFORM ./DllLoader.exe
- ../../tests/runwine.sh $PLATFORM ./DllLoaderLoader.exe
- cd ../../tests
- ./runwine.sh $PLATFORM ./TestSuite.exe
+60
View File
@@ -0,0 +1,60 @@
project (MemoryModule)
cmake_minimum_required (VERSION 2.8.7)
set (PLATFORM "x86_64" CACHE STRING "Platform to compile for")
message (STATUS "Compile for ${PLATFORM} platform")
if (NOT MSVC)
set (CMAKE_SYSTEM_NAME Windows)
set (CMAKE_POSITION_INDEPENDENT_CODE False)
set (COMPILER_PREFIX "${PLATFORM}-w64-mingw32")
set (CMAKE_C_COMPILER "${COMPILER_PREFIX}-gcc")
set (CMAKE_CXX_COMPILER "${COMPILER_PREFIX}-g++")
set (CMAKE_RC_COMPILER "${COMPILER_PREFIX}-windres")
set (CMAKE_AR "${COMPILER_PREFIX}-ar")
set (CMAKE_RANLIB "${COMPILER_PREFIX}-ranlib")
set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
set (CMAKE_RC_COMPILE_OBJECT "${CMAKE_RC_COMPILER} -O coff -I${CMAKE_CURRENT_SOURCE_DIR} <SOURCE> <OBJECT>")
endif ()
if (NOT MSVC)
add_definitions ("-Wall")
else ()
# Show level 4 warnings.
add_definitions ("-W4")
endif ()
option(UNICODE "Compile with UNICODE support" OFF)
if (UNICODE)
message (STATUS "Compile with UNICODE support")
add_definitions ("-DUNICODE" "-D_UNICODE")
else ()
message (STATUS "Compile without UNICODE support")
endif ()
option(TESTSUITE "Compile with TESTSUITE support" OFF)
if (TESTSUITE)
message (STATUS "Compile with TESTSUITE support")
add_definitions ("-DTESTSUITE")
else ()
message (STATUS "Compile without TESTSUITE support")
endif ()
add_library (MemoryModule STATIC MemoryModule.c MemoryModule.h)
target_include_directories(MemoryModule PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
if (NOT MSVC)
set_target_properties ("MemoryModule" PROPERTIES PREFIX "")
endif ()
add_subdirectory (example)
add_subdirectory (tests)
enable_language (RC)
+5 -2
View File
@@ -1,4 +1,4 @@
SUBDIRS = example
SUBDIRS = example tests
.PHONY: subdirs $(SUBDIRS)
@@ -13,5 +13,8 @@ clean: $(CLEANDIRS)
$(CLEANDIRS):
$(MAKE) -C $(@:clean-%=%) clean
test:
$(MAKE) -C tests test
.PHONY: subdirs $(INSTALLDIRS)
.PHONY: clean
.PHONY: clean test
+797 -297
View File
File diff suppressed because it is too large Load Diff
+73 -8
View File
@@ -2,7 +2,7 @@
* Memory DLL loading code
* Version 0.0.4
*
* Copyright (c) 2004-2014 by Joachim Bauch / mail@joachim-bauch.de
* Copyright (c) 2004-2015 by Joachim Bauch / mail@joachim-bauch.de
* http://www.joachim-bauch.de
*
* The contents of this file are subject to the Mozilla Public License Version
@@ -19,7 +19,7 @@
*
* The Initial Developer of the Original Code is Joachim Bauch.
*
* Portions created by Joachim Bauch are Copyright (C) 2004-2014
* Portions created by Joachim Bauch are Copyright (C) 2004-2015
* Joachim Bauch. All Rights Reserved.
*
*/
@@ -39,39 +39,64 @@ typedef void *HCUSTOMMODULE;
extern "C" {
#endif
typedef LPVOID (*CustomAllocFunc)(LPVOID, SIZE_T, DWORD, DWORD, void*);
typedef BOOL (*CustomFreeFunc)(LPVOID, SIZE_T, DWORD, void*);
typedef HCUSTOMMODULE (*CustomLoadLibraryFunc)(LPCSTR, void *);
typedef FARPROC (*CustomGetProcAddressFunc)(HCUSTOMMODULE, LPCSTR, void *);
typedef void (*CustomFreeLibraryFunc)(HCUSTOMMODULE, void *);
/**
* Load DLL from memory location.
* Load EXE/DLL from memory location with the given size.
*
* All dependencies are resolved using default LoadLibrary/GetProcAddress
* calls through the Windows API.
*/
HMEMORYMODULE MemoryLoadLibrary(const void *);
HMEMORYMODULE MemoryLoadLibrary(const void *, size_t);
/**
* Load DLL from memory location using custom dependency resolvers.
* Load EXE/DLL from memory location with the given size using custom dependency
* resolvers.
*
* Dependencies will be resolved using passed callback methods.
*/
HMEMORYMODULE MemoryLoadLibraryEx(const void *,
HMEMORYMODULE MemoryLoadLibraryEx(const void *, size_t,
CustomAllocFunc,
CustomFreeFunc,
CustomLoadLibraryFunc,
CustomGetProcAddressFunc,
CustomFreeLibraryFunc,
void *);
/**
* Get address of exported method.
* Get address of exported method. Supports loading both by name and by
* ordinal value.
*/
FARPROC MemoryGetProcAddress(HMEMORYMODULE, LPCSTR);
/**
* Free previously loaded DLL.
* Get the code base address of loading module to store it above.
* On load dynamic library it used as a handle of library instance.
*/
LPVOID MemoryGetCodeAddress(HMEMORYMODULE);
/**
* Free previously loaded EXE/DLL.
*/
void MemoryFreeLibrary(HMEMORYMODULE);
/**
* Execute entry point (EXE only). The entry point can only be executed
* if the EXE has been loaded to the correct base address or it could
* be relocated (i.e. relocation information have not been stripped by
* the linker).
*
* Important: calling this function will not return, i.e. once the loaded
* EXE finished running, the process will terminate.
*
* Returns a negative value if the entry point could not be executed.
*/
int MemoryCallEntryPoint(HMEMORYMODULE);
/**
* Find the location of a resource with the specified type and name.
*/
@@ -102,6 +127,46 @@ int MemoryLoadString(HMEMORYMODULE, UINT, LPTSTR, int);
*/
int MemoryLoadStringEx(HMEMORYMODULE, UINT, LPTSTR, int, WORD);
/**
* Default implementation of CustomAllocFunc that calls VirtualAlloc
* internally to allocate memory for a library
*
* This is the default as used by MemoryLoadLibrary.
*/
LPVOID MemoryDefaultAlloc(LPVOID, SIZE_T, DWORD, DWORD, void *);
/**
* Default implementation of CustomFreeFunc that calls VirtualFree
* internally to free the memory used by a library
*
* This is the default as used by MemoryLoadLibrary.
*/
BOOL MemoryDefaultFree(LPVOID, SIZE_T, DWORD, void *);
/**
* Default implementation of CustomLoadLibraryFunc that calls LoadLibraryA
* internally to load an additional libary.
*
* This is the default as used by MemoryLoadLibrary.
*/
HCUSTOMMODULE MemoryDefaultLoadLibrary(LPCSTR, void *);
/**
* Default implementation of CustomGetProcAddressFunc that calls GetProcAddress
* internally to get the address of an exported function.
*
* This is the default as used by MemoryLoadLibrary.
*/
FARPROC MemoryDefaultGetProcAddress(HCUSTOMMODULE, LPCSTR, void *);
/**
* Default implementation of CustomFreeLibraryFunc that calls FreeLibrary
* internally to release an additional libary.
*
* This is the default as used by MemoryLoadLibrary.
*/
void MemoryDefaultFreeLibrary(HCUSTOMMODULE, void *);
#ifdef __cplusplus
}
#endif
+43
View File
@@ -0,0 +1,43 @@
# Status available at
# https://ci.appveyor.com/project/fancycode/memorymodule
version: 1.0.{build}
os:
- Visual Studio 2015
environment:
matrix:
- GENERATOR: "Visual Studio 9 2008"
UNICODE: ON
- GENERATOR: "Visual Studio 9 2008"
UNICODE: OFF
- GENERATOR: "Visual Studio 10 2010"
UNICODE: ON
- GENERATOR: "Visual Studio 10 2010"
UNICODE: OFF
- GENERATOR: "Visual Studio 11 2012"
UNICODE: ON
- GENERATOR: "Visual Studio 11 2012"
UNICODE: OFF
- GENERATOR: "Visual Studio 12 2013"
UNICODE: ON
- GENERATOR: "Visual Studio 12 2013"
UNICODE: OFF
- GENERATOR: "Visual Studio 14 2015"
UNICODE: ON
- GENERATOR: "Visual Studio 14 2015"
UNICODE: OFF
platform:
- x86
- x64
configuration:
- Debug
install:
- call scripts\run-appveyor.bat
build: off
test: off
deploy: off
+2 -2
View File
@@ -511,7 +511,7 @@ The interface is very similar to the standard methods for loading of libraries::
typedef void *HMEMORYMODULE;
HMEMORYMODULE MemoryLoadLibrary(const void *);
HMEMORYMODULE MemoryLoadLibrary(const void *, size_t);
FARPROC MemoryGetProcAddress(HMEMORYMODULE, const char *);
void MemoryFreeLibrary(HMEMORYMODULE);
@@ -543,4 +543,4 @@ Copyright
==========
The MemoryModule library and this tutorial are
Copyright (c) 2004-2014 by Joachim Bauch.
Copyright (c) 2004-2015 by Joachim Bauch.
+2
View File
@@ -0,0 +1,2 @@
add_subdirectory (DllLoader)
add_subdirectory (SampleDLL)
+26
View File
@@ -0,0 +1,26 @@
set (sources_dllloader
DllLoader.cpp
)
set (sources_dllloaderloader
DllLoaderLoader.cpp
)
if (NOT MSVC)
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-static")
set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "-static")
endif ()
add_executable (DllLoader ${sources_dllloader})
target_link_libraries ("DllLoader" "MemoryModule")
if (NOT MSVC)
set_target_properties ("DllLoader" PROPERTIES SUFFIX ".exe")
set_target_properties ("DllLoader" PROPERTIES LINK_FLAGS "-Wl,--image-base -Wl,0x20000000")
endif ()
add_executable (DllLoaderLoader ${sources_dllloaderloader})
target_link_libraries ("DllLoaderLoader" "MemoryModule")
if (NOT MSVC)
set_target_properties ("DllLoaderLoader" PROPERTIES SUFFIX ".exe")
set_target_properties ("DllLoaderLoader" PROPERTIES LINK_FLAGS "-Wl,--image-base -Wl,0x10000000")
endif ()
+252 -17
View File
@@ -1,5 +1,9 @@
#define WIN32_LEAN_AND_MEAN
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <assert.h>
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
@@ -42,10 +46,47 @@ void LoadFromFile(void)
FreeLibrary(handle);
}
void* ReadLibrary(size_t* pSize) {
size_t read;
void* result;
FILE* fp;
fp = _tfopen(DLL_FILE, _T("rb"));
if (fp == NULL)
{
_tprintf(_T("Can't open DLL file \"%s\"."), DLL_FILE);
return NULL;
}
fseek(fp, 0, SEEK_END);
*pSize = static_cast<size_t>(ftell(fp));
if (*pSize == 0)
{
fclose(fp);
return NULL;
}
result = (unsigned char *)malloc(*pSize);
if (result == NULL)
{
return NULL;
}
fseek(fp, 0, SEEK_SET);
read = fread(result, 1, *pSize, fp);
fclose(fp);
if (read != *pSize)
{
free(result);
return NULL;
}
return result;
}
void LoadFromMemory(void)
{
FILE *fp;
unsigned char *data=NULL;
void *data;
size_t size;
HMEMORYMODULE handle;
addNumberProc addNumber;
@@ -54,21 +95,13 @@ void LoadFromMemory(void)
LPVOID resourceData;
TCHAR buffer[100];
fp = _tfopen(DLL_FILE, _T("rb"));
if (fp == NULL)
data = ReadLibrary(&size);
if (data == NULL)
{
_tprintf(_T("Can't open DLL file \"%s\"."), DLL_FILE);
goto exit;
return;
}
fseek(fp, 0, SEEK_END);
size = ftell(fp);
data = (unsigned char *)malloc(size);
fseek(fp, 0, SEEK_SET);
fread(data, 1, size, fp);
fclose(fp);
handle = MemoryLoadLibrary(data);
handle = MemoryLoadLibrary(data, size);
if (handle == NULL)
{
_tprintf(_T("Can't load library from memory.\n"));
@@ -94,15 +127,217 @@ void LoadFromMemory(void)
MemoryFreeLibrary(handle);
exit:
if (data)
free(data);
free(data);
}
int main(int argc, char* argv[])
#define MAX_CALLS 20
struct CallList {
int current_alloc_call, current_free_call;
CustomAllocFunc alloc_calls[MAX_CALLS];
CustomFreeFunc free_calls[MAX_CALLS];
};
LPVOID MemoryFailingAlloc(LPVOID address, SIZE_T size, DWORD allocationType, DWORD protect, void* userdata)
{
UNREFERENCED_PARAMETER(address);
UNREFERENCED_PARAMETER(size);
UNREFERENCED_PARAMETER(allocationType);
UNREFERENCED_PARAMETER(protect);
UNREFERENCED_PARAMETER(userdata);
return NULL;
}
LPVOID MemoryMockAlloc(LPVOID address, SIZE_T size, DWORD allocationType, DWORD protect, void* userdata)
{
CallList* calls = (CallList*)userdata;
CustomAllocFunc current_func = calls->alloc_calls[calls->current_alloc_call++];
assert(current_func != NULL);
return current_func(address, size, allocationType, protect, NULL);
}
BOOL MemoryMockFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType, void* userdata)
{
CallList* calls = (CallList*)userdata;
CustomFreeFunc current_func = calls->free_calls[calls->current_free_call++];
assert(current_func != NULL);
return current_func(lpAddress, dwSize, dwFreeType, NULL);
}
void InitFuncs(void** funcs, va_list args) {
for (int i = 0; ; i++) {
assert(i < MAX_CALLS);
funcs[i] = va_arg(args, void*);
if (funcs[i] == NULL) break;
}
}
void InitAllocFuncs(CallList* calls, ...) {
va_list args;
va_start(args, calls);
InitFuncs((void**)calls->alloc_calls, args);
va_end(args);
calls->current_alloc_call = 0;
}
void InitFreeFuncs(CallList* calls, ...) {
va_list args;
va_start(args, calls);
InitFuncs((void**)calls->free_calls, args);
va_end(args);
calls->current_free_call = 0;
}
void InitFreeFunc(CallList* calls, CustomFreeFunc freeFunc) {
for (int i = 0; i < MAX_CALLS; i++) {
calls->free_calls[i] = freeFunc;
}
calls->current_free_call = 0;
}
void TestFailingAllocation(void *data, size_t size) {
CallList expected_calls;
HMEMORYMODULE handle;
InitAllocFuncs(&expected_calls, MemoryFailingAlloc, MemoryFailingAlloc, NULL);
InitFreeFuncs(&expected_calls, NULL);
handle = MemoryLoadLibraryEx(
data, size, MemoryMockAlloc, MemoryMockFree, MemoryDefaultLoadLibrary,
MemoryDefaultGetProcAddress, MemoryDefaultFreeLibrary, &expected_calls);
assert(handle == NULL);
assert(GetLastError() == ERROR_OUTOFMEMORY);
assert(expected_calls.current_free_call == 0);
MemoryFreeLibrary(handle);
assert(expected_calls.current_free_call == 0);
}
void TestCleanupAfterFailingAllocation(void *data, size_t size) {
CallList expected_calls;
HMEMORYMODULE handle;
int free_calls_after_loading;
InitAllocFuncs(&expected_calls,
MemoryDefaultAlloc,
MemoryDefaultAlloc,
MemoryDefaultAlloc,
MemoryDefaultAlloc,
MemoryFailingAlloc,
NULL);
InitFreeFuncs(&expected_calls, MemoryDefaultFree, NULL);
handle = MemoryLoadLibraryEx(
data, size, MemoryMockAlloc, MemoryMockFree, MemoryDefaultLoadLibrary,
MemoryDefaultGetProcAddress, MemoryDefaultFreeLibrary, &expected_calls);
free_calls_after_loading = expected_calls.current_free_call;
MemoryFreeLibrary(handle);
assert(expected_calls.current_free_call == free_calls_after_loading);
}
void TestFreeAfterDefaultAlloc(void *data, size_t size) {
CallList expected_calls;
HMEMORYMODULE handle;
int free_calls_after_loading;
// Note: free might get called internally multiple times
InitFreeFunc(&expected_calls, MemoryDefaultFree);
handle = MemoryLoadLibraryEx(
data, size, MemoryDefaultAlloc, MemoryMockFree, MemoryDefaultLoadLibrary,
MemoryDefaultGetProcAddress, MemoryDefaultFreeLibrary, &expected_calls);
assert(handle != NULL);
free_calls_after_loading = expected_calls.current_free_call;
MemoryFreeLibrary(handle);
assert(expected_calls.current_free_call == free_calls_after_loading + 1);
}
#ifdef _WIN64
LPVOID MemoryAllocHigh(LPVOID address, SIZE_T size, DWORD allocationType, DWORD protect, void* userdata)
{
int* counter = static_cast<int*>(userdata);
if (*counter == 0) {
// Make sure the image gets loaded to an address above 32bit.
uintptr_t offset = 0x10000000000;
address = (LPVOID) ((uintptr_t) address + offset);
}
(*counter)++;
return MemoryDefaultAlloc(address, size, allocationType, protect, NULL);
}
void TestAllocHighMemory(void *data, size_t size) {
HMEMORYMODULE handle;
int counter = 0;
addNumberProc addNumber;
HMEMORYRSRC resourceInfo;
DWORD resourceSize;
LPVOID resourceData;
TCHAR buffer[100];
handle = MemoryLoadLibraryEx(
data, size, MemoryAllocHigh, MemoryDefaultFree, MemoryDefaultLoadLibrary,
MemoryDefaultGetProcAddress, MemoryDefaultFreeLibrary, &counter);
assert(handle != NULL);
addNumber = (addNumberProc)MemoryGetProcAddress(handle, "addNumbers");
_tprintf(_T("From memory: %d\n"), addNumber(1, 2));
resourceInfo = MemoryFindResource(handle, MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
_tprintf(_T("MemoryFindResource returned 0x%p\n"), resourceInfo);
resourceSize = MemorySizeofResource(handle, resourceInfo);
resourceData = MemoryLoadResource(handle, resourceInfo);
_tprintf(_T("Memory resource data: %ld bytes at 0x%p\n"), resourceSize, resourceData);
MemoryLoadString(handle, 1, buffer, sizeof(buffer));
_tprintf(_T("String1: %s\n"), buffer);
MemoryLoadString(handle, 20, buffer, sizeof(buffer));
_tprintf(_T("String2: %s\n"), buffer);
MemoryFreeLibrary(handle);
}
#endif // _WIN64
void TestCustomAllocAndFree(void)
{
void *data;
size_t size;
data = ReadLibrary(&size);
if (data == NULL)
{
return;
}
_tprintf(_T("Test MemoryLoadLibraryEx after initially failing allocation function\n"));
TestFailingAllocation(data, size);
_tprintf(_T("Test cleanup after MemoryLoadLibraryEx with failing allocation function\n"));
TestCleanupAfterFailingAllocation(data, size);
_tprintf(_T("Test custom free function after MemoryLoadLibraryEx\n"));
TestFreeAfterDefaultAlloc(data, size);
#ifdef _WIN64
_tprintf(_T("Test allocating in high memory\n"));
TestAllocHighMemory(data, size);
#endif
free(data);
}
int main()
{
LoadFromFile();
printf("\n\n");
LoadFromMemory();
printf("\n\n");
TestCustomAllocAndFree();
return 0;
}
+64
View File
@@ -0,0 +1,64 @@
#define WIN32_LEAN_AND_MEAN
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <assert.h>
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <malloc.h>
#include "../../MemoryModule.h"
#define EXE_FILE TEXT("DllLoader.exe")
int RunFromMemory(void)
{
FILE *fp;
unsigned char *data=NULL;
long size;
size_t read;
HMEMORYMODULE handle;
int result = -1;
fp = _tfopen(EXE_FILE, _T("rb"));
if (fp == NULL)
{
_tprintf(_T("Can't open executable \"%s\"."), EXE_FILE);
goto exit;
}
fseek(fp, 0, SEEK_END);
size = ftell(fp);
assert(size >= 0);
data = (unsigned char *)malloc(size);
assert(data != NULL);
fseek(fp, 0, SEEK_SET);
read = fread(data, 1, size, fp);
assert(read == static_cast<size_t>(size));
fclose(fp);
handle = MemoryLoadLibrary(data, size);
if (handle == NULL)
{
_tprintf(_T("Can't load library from memory.\n"));
goto exit;
}
result = MemoryCallEntryPoint(handle);
if (result < 0) {
_tprintf(_T("Could not execute entry point: %d\n"), result);
}
MemoryFreeLibrary(handle);
exit:
free(data);
return result;
}
int main()
{
return RunFromMemory();
}
+8 -2
View File
@@ -22,9 +22,15 @@ CFLAGS += -DUNICODE -D_UNICODE
endif
OBJ = DllLoader.o ../../MemoryModule.o
OBJ_LOADER = DllLoaderLoader.o ../../MemoryModule.o
all: DllLoader.exe DllLoaderLoader.exe
DllLoader.exe: $(OBJ)
$(CC) $(LDFLAGS) -o DllLoader.exe $(OBJ)
$(CC) $(LDFLAGS) -Wl,--image-base -Wl,0x20000000 -o DllLoader.exe $(OBJ)
DllLoaderLoader.exe: $(OBJ_LOADER)
$(CC) $(LDFLAGS) -Wl,--image-base -Wl,0x10000000 -o DllLoaderLoader.exe $(OBJ_LOADER)
%.o: %.cpp
$(CXX) $(CFLAGS) -c $<
@@ -33,4 +39,4 @@ DllLoader.exe: $(OBJ)
$(CC) $(CFLAGS) -c $<
clean:
$(RM) -rf $(OBJ) DllLoader.exe
$(RM) -rf $(OBJ) $(OBJ_LOADER) DllLoader.exe DllLoaderLoader.exe
+12
View File
@@ -0,0 +1,12 @@
set (sources
SampleDLL.cpp
SampleDLL.h
SampleDLL.rc
)
add_definitions (-DSAMPLEDLL_EXPORTS)
add_library (SampleDLL MODULE ${sources})
if (NOT MSVC)
set_target_properties ("SampleDLL" PROPERTIES PREFIX "")
set_target_properties ("SampleDLL" PROPERTIES SUFFIX ".dll")
endif ()
+1 -1
View File
@@ -6,7 +6,7 @@ PLATFORM = i686
endif
CC = $(PLATFORM)-w64-mingw32-g++
CXX = $(PLATFORM)-w64-mingw32-g++
LINK = $(PLATFORM)-w64-mingw32-ld
LINK = $(PLATFORM)-w64-mingw32-g++
RC = $(PLATFORM)-w64-mingw32-windres
else
CC = g++
+1 -1
View File
@@ -10,7 +10,7 @@ BEGIN
VALUE "FileDescription", "SampleDLL"
VALUE "FileVersion", "1.0"
VALUE "InternalName", "SampleDLL"
VALUE "LegalCopyright", "Copyright (c) 2004-2014 Joachim Bauch"
VALUE "LegalCopyright", "Copyright (c) 2004-2015 Joachim Bauch"
VALUE "OriginalFilename", "SampleDLL.dll"
VALUE "ProductName", "MemoryModule"
VALUE "ProductVersion", "0.0.4"
+3 -1
View File
@@ -1,6 +1,8 @@
MemoryModule
============
[![Build Status](https://travis-ci.org/fancycode/MemoryModule.svg?branch=master)](https://travis-ci.org/fancycode/MemoryModule)[![Build status](https://ci.appveyor.com/api/projects/status/qcrfxbno0jbbl9cx/branch/master?svg=true)](https://ci.appveyor.com/project/fancycode/memorymodule)
The default windows API functions to load external libraries into a program
(`LoadLibrary`, `LoadLibraryEx`) only work with files on the filesystem. It's
therefore impossible to load a DLL from memory.
@@ -14,5 +16,5 @@ file gets deleted.
`MemoryModule` is a library that can be used to load a DLL completely from
memory - without storing on the disk first.
See `doc/readme.txt` for more informations about the format of a DLL file and
See `doc/readme.rst` for more informations about the format of a DLL file and
a tutorial how they can be loaded directly.
+48
View File
@@ -0,0 +1,48 @@
@echo off
setlocal
if /I "%PLATFORM%" == "x64" (
set CMAKE_GEN_SUFFIX= Win64
if /I "%GENERATOR%" == "Visual Studio 9 2008" (
echo Skipping %CONFIGURATION% build using %GENERATOR%%CMAKE_GEN_SUFFIX% on %PLATFORM%
exit 0
)
) else (
set CMAKE_GEN_SUFFIX=
)
echo.
echo Preparing %CONFIGURATION% build environment for %GENERATOR%%CMAKE_GEN_SUFFIX% ...
cmake "-G%GENERATOR%%CMAKE_GEN_SUFFIX%" -DPLATFORM=%PLATFORM% -DUNICODE=%UNICODE% -DTESTSUITE=ON -H. -Bbuild
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo Building ...
cmake --build build --config %CONFIGURATION%
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo Copying generated files ...
copy /y build\example\DllLoader\%CONFIGURATION%\DllLoader.exe build\example\DllLoader\ > NUL
copy /y build\example\DllLoader\%CONFIGURATION%\DllLoaderLoader.exe build\example\DllLoader\ > NUL
copy /y build\example\SampleDLL\%CONFIGURATION%\SampleDLL.dll build\example\SampleDLL\ > NUL
copy /y build\tests\%CONFIGURATION%\TestSuite.exe build\tests\ > NUL
cd build\example\DllLoader
echo.
echo Running DllLoader.exe ...
DllLoader.exe
if %errorlevel% neq 0 exit /b %errorlevel%
echo.
echo Running DllLoaderLoader.exe ...
DllLoaderLoader.exe
if %errorlevel% neq 0 exit /b %errorlevel%
cd ..\..\tests
echo.
echo Running TestSuite.exe ...
TestSuite.exe
if %errorlevel% neq 0 exit /b %errorlevel%
+14
View File
@@ -0,0 +1,14 @@
set (sources_testsuite
TestSuite.c
)
if (NOT MSVC)
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-static")
set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "-static")
endif ()
add_executable (TestSuite ${sources_testsuite})
target_link_libraries ("TestSuite" "MemoryModule")
if (NOT MSVC)
set_target_properties ("TestSuite" PROPERTIES SUFFIX ".exe")
endif ()
+304
View File
@@ -0,0 +1,304 @@
#define WIN32_LEAN_AND_MEAN
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <assert.h>
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <malloc.h>
#include "../MemoryModule.h"
typedef int (*addProc)(int);
typedef int (*addNumberProc)(int, int);
// Thanks to Tim Cooper (from http://stackoverflow.com/a/8584708)
const char *sstrstr(const char *haystack, const char *needle, size_t length) {
size_t needle_length = strlen(needle);
size_t i;
for (i = 0; i < length; i++) {
if (i + needle_length > length) {
return NULL;
}
if (strncmp(&haystack[i], needle, needle_length) == 0) {
return &haystack[i];
}
}
return NULL;
}
const wchar_t *swcsstr(const wchar_t *haystack, const wchar_t *needle, size_t length) {
size_t needle_length = wcslen(needle);
size_t i;
for (i = 0; i < length; i++) {
if (i + needle_length > length) {
return NULL;
}
if (wcsncmp(&haystack[i], needle, needle_length) == 0) {
return &haystack[i];
}
}
return NULL;
}
BOOL CheckResourceStrings(LPVOID data, DWORD size, const char *first, const wchar_t *second) {
const char *first_pos;
const wchar_t *second_pos;
const wchar_t *src;
if (data == NULL || size == 0) {
return FALSE;
}
first_pos = sstrstr((const char *) data, first, size);
if (first_pos == NULL) {
fprintf(stderr, "ERROR: data doesn't start with %s\n", first);
return FALSE;
}
src = (const wchar_t *) (((const char *) data) + strlen(first) + 1);
second_pos = swcsstr(src, second, (size - strlen(first) - 1) / sizeof(wchar_t));
if (second_pos == NULL) {
fwprintf(stderr, L"ERROR: data doesn't continue with %s\n", second);
return FALSE;
}
return TRUE;
}
BOOL LoadFromMemory(char *filename)
{
FILE *fp;
unsigned char *data=NULL;
long size;
size_t read;
HMEMORYMODULE handle = NULL;
addNumberProc addNumber;
addNumberProc addNumber2;
HMEMORYRSRC resourceInfo;
DWORD resourceSize;
LPVOID resourceData;
TCHAR buffer[100];
BOOL result = TRUE;
fp = fopen(filename, "rb");
if (fp == NULL)
{
printf("Can't open DLL file \"%s\".", filename);
result = FALSE;
goto exit;
}
fseek(fp, 0, SEEK_END);
size = ftell(fp);
assert(size > 0);
data = (unsigned char *)malloc(size);
assert(data != NULL);
fseek(fp, 0, SEEK_SET);
read = fread(data, 1, size, fp);
assert(read == static_cast<size_t>(size));
fclose(fp);
handle = MemoryLoadLibrary(data, size);
if (handle == NULL)
{
_tprintf(_T("Can't load library from memory.\n"));
result = FALSE;
goto exit;
}
addNumber = (addNumberProc)MemoryGetProcAddress(handle, NULL);
if (addNumber != NULL) {
_tprintf(_T("MemoryGetProcAddress(NULL) returned %p\n"), addNumber);
result = FALSE;
goto exit;
}
addNumber = (addNumberProc)MemoryGetProcAddress(handle, reinterpret_cast<LPCSTR>(0xff));
if (addNumber != NULL) {
_tprintf(_T("MemoryGetProcAddress(0xff) returned %p\n"), addNumber);
result = FALSE;
goto exit;
}
addNumber = (addNumberProc)MemoryGetProcAddress(handle, "addNumbers");
if (!addNumber) {
_tprintf(_T("MemoryGetProcAddress(\"addNumber\") returned NULL\n"));
result = FALSE;
goto exit;
}
_tprintf(_T("From memory: %d\n"), addNumber(1, 2));
// the DLL only exports one function, try to load by ordinal value
addNumber2 = (addNumberProc)MemoryGetProcAddress(handle, reinterpret_cast<LPCSTR>(0x01));
if (addNumber != addNumber2) {
_tprintf(_T("MemoryGetProcAddress(0x01) returned %p (expected %p)\n"), addNumber2, addNumber);
result = FALSE;
goto exit;
}
resourceInfo = MemoryFindResource(handle, MAKEINTRESOURCE(VS_VERSION_INFO), RT_VERSION);
_tprintf(_T("MemoryFindResource returned 0x%p\n"), resourceInfo);
if (resourceInfo != NULL) {
resourceSize = MemorySizeofResource(handle, resourceInfo);
resourceData = MemoryLoadResource(handle, resourceInfo);
_tprintf(_T("Memory resource data: %ld bytes at 0x%p\n"), resourceSize, resourceData);
MemoryLoadString(handle, 1, buffer, sizeof(buffer));
_tprintf(_T("String1: %s\n"), buffer);
MemoryLoadString(handle, 20, buffer, sizeof(buffer));
_tprintf(_T("String2: %s\n"), buffer);
} else {
result = FALSE;
}
resourceInfo = MemoryFindResource(handle, _T("stringres"), RT_RCDATA);
_tprintf(_T("MemoryFindResource returned 0x%p\n"), resourceInfo);
if (resourceInfo != NULL) {
resourceSize = MemorySizeofResource(handle, resourceInfo);
resourceData = MemoryLoadResource(handle, resourceInfo);
_tprintf(_T("Memory resource data: %ld bytes at 0x%p\n"), resourceSize, resourceData);
if (!CheckResourceStrings(resourceData, resourceSize, "This is a ANSI string", L"This is a UNICODE string")) {
result = FALSE;
}
} else {
result = FALSE;
}
resourceInfo = MemoryFindResource(handle, _T("stringres1"), RT_RCDATA);
_tprintf(_T("MemoryFindResource returned 0x%p\n"), resourceInfo);
if (resourceInfo != NULL) {
resourceSize = MemorySizeofResource(handle, resourceInfo);
resourceData = MemoryLoadResource(handle, resourceInfo);
_tprintf(_T("Memory resource data: %ld bytes at 0x%p\n"), resourceSize, resourceData);
if (!CheckResourceStrings(resourceData, resourceSize, "This is ANSI string 1", L"This is UNICODE string 1")) {
result = FALSE;
}
} else {
result = FALSE;
}
resourceInfo = MemoryFindResource(handle, _T("stringres2"), RT_RCDATA);
_tprintf(_T("MemoryFindResource returned 0x%p\n"), resourceInfo);
if (resourceInfo != NULL) {
resourceSize = MemorySizeofResource(handle, resourceInfo);
resourceData = MemoryLoadResource(handle, resourceInfo);
_tprintf(_T("Memory resource data: %ld bytes at 0x%p\n"), resourceSize, resourceData);
if (!CheckResourceStrings(resourceData, resourceSize, "This is ANSI string 2", L"This is UNICODE string 2")) {
result = FALSE;
}
} else {
result = FALSE;
}
resourceInfo = MemoryFindResource(handle, _T("stringres3"), RT_RCDATA);
_tprintf(_T("MemoryFindResource returned 0x%p\n"), resourceInfo);
if (resourceInfo != NULL) {
resourceSize = MemorySizeofResource(handle, resourceInfo);
resourceData = MemoryLoadResource(handle, resourceInfo);
_tprintf(_T("Memory resource data: %ld bytes at 0x%p\n"), resourceSize, resourceData);
if (!CheckResourceStrings(resourceData, resourceSize, "This is ANSI string 3", L"This is UNICODE string 3")) {
result = FALSE;
}
} else {
result = FALSE;
}
exit:
MemoryFreeLibrary(handle);
free(data);
return result;
}
BOOL LoadExportsFromMemory(char *filename)
{
FILE *fp;
unsigned char *data=NULL;
long size;
size_t read;
HMEMORYMODULE handle = NULL;
int i;
BOOL result = TRUE;
fp = fopen(filename, "rb");
if (fp == NULL)
{
printf("Can't open DLL file \"%s\".", filename);
result = FALSE;
goto exit;
}
fseek(fp, 0, SEEK_END);
size = ftell(fp);
assert(size > 0);
data = (unsigned char *)malloc(size);
assert(data != NULL);
fseek(fp, 0, SEEK_SET);
read = fread(data, 1, size, fp);
assert(read == static_cast<size_t>(size));
fclose(fp);
handle = MemoryLoadLibrary(data, size);
if (handle == NULL)
{
_tprintf(_T("Can't load library from memory.\n"));
result = FALSE;
goto exit;
}
for (i = 1; i <= 100; i++) {
char name[100];
sprintf(name, "add%d", i);
addProc addNumber = (addProc)MemoryGetProcAddress(handle, name);
if (!addNumber) {
_tprintf(_T("MemoryGetProcAddress(\"%s\") returned NULL\n"), name);
result = FALSE;
goto exit;
}
int result = addNumber(1);
if (result != 1 + i) {
_tprintf(_T("(\"%s\") returned %d, expected %d\n"), name, result, 1 + i);
result = FALSE;
goto exit;
}
_tprintf(_T("%s: %d\n"), name, result);
}
exit:
MemoryFreeLibrary(handle);
free(data);
return result;
}
int main(int argc, char* argv[])
{
if (argc < 2) {
fprintf(stderr, "USAGE: %s <filename.dll>\n", argv[0]);
return 1;
}
if (!strstr((const char *) argv[1], "exports")) {
if (!LoadFromMemory(argv[1])) {
return 2;
}
} else {
if (!LoadExportsFromMemory(argv[1])) {
return 2;
}
}
return 0;
}
+96
View File
@@ -0,0 +1,96 @@
UNAME := $(shell uname)
ifeq ($(UNAME), Linux)
ifndef PLATFORM
PLATFORM = i686
endif
CC = $(PLATFORM)-w64-mingw32-g++
CXX = $(PLATFORM)-w64-mingw32-g++
LD = $(PLATFORM)-w64-mingw32-ld
RC = $(PLATFORM)-w64-mingw32-windres
else
CC = g++
CXX = g++
LD = ld
RC = rc
endif
RM = rm
CFLAGS = -Wall -g -DTESTSUITE
LDFLAGS =
RCFLAGS = -O coff
ifdef UNICODE
CFLAGS += -DUNICODE -D_UNICODE
endif
CFLAGS_DLL = -DSAMPLEDLL_EXPORTS
CFLAGS_EXE =
LDFLAGS_DLL = -shared
LDFLAGS_EXE = -static
TEST_DLLS = \
test-align-128.dll \
test-align-256.dll \
test-align-512.dll \
test-align-768.dll \
test-align-1024.dll \
test-align-2048.dll \
test-align-3072.dll \
test-align-4096.dll \
test-align-100.dll \
test-align-200.dll \
test-align-300.dll \
test-align-400.dll \
test-align-500.dll \
test-align-600.dll \
test-align-800.dll \
test-align-900.dll \
test-relocate.dll \
test-exports.dll
LOADDLL_OBJ = LoadDll.o ../MemoryModule.o
TESTSUITE_OBJ = TestSuite.o ../MemoryModule.o
DLL_OBJ = SampleDLL.o SampleDLL.res
all: prepare_testsuite LoadDll.exe TestSuite.exe $(TEST_DLLS)
prepare_testsuite:
rm -f $(TESTSUITE_OBJ)
LoadDll.exe: $(LOADDLL_OBJ)
$(CC) $(LDFLAGS_EXE) $(LDFLAGS) -Wl,--image-base -Wl,0x20000000 -o LoadDll.exe $(LOADDLL_OBJ)
TestSuite.exe: $(TESTSUITE_OBJ)
$(CC) $(LDFLAGS_EXE) $(LDFLAGS) -o TestSuite.exe $(TESTSUITE_OBJ)
LoadDll.o: LoadDll.cpp
$(CXX) $(CFLAGS) $(CFLAGS_EXE) -c $<
test-align-%.dll: $(DLL_OBJ)
$(LD) $(LDFLAGS_DLL) $(LDFLAGS) --file-alignment $* --section-alignment $* -o $@ $(DLL_OBJ)
test-relocate.dll: $(DLL_OBJ)
$(CXX) $(LDFLAGS_DLL) $(LDFLAGS) -Wl,--image-base -Wl,0x20000000 -o $@ $(DLL_OBJ)
test-exports.dll: SampleExports.o
$(CXX) $(LDFLAGS_DLL) $(LDFLAGS) -o $@ SampleExports.o
SampleExports.cpp: generate-exports.sh
./generate-exports.sh
%.o: %.cpp
$(CXX) $(CFLAGS) $(CFLAGS_DLL) -c $<
%.o: %.cc
$(CC) $(CFLAGS) $(CFLAGS_DLL) -c $<
%.res: %.rc
$(RC) $(RCFLAGS) -o $*.res $<
clean:
$(RM) -rf LoadDll.exe $(TEST_DLLS) $(LOADDLL_OBJ) $(DLL_OBJ) $(TESTSUITE_OBJ) SampleExports.o
test: all
./runwine.sh $(PLATFORM) TestSuite.exe
./runtests.sh $(PLATFORM) "$(TEST_DLLS)"
+10
View File
@@ -0,0 +1,10 @@
#include "SampleDLL.h"
extern "C" {
SAMPLEDLL_API int addNumbers(int a, int b)
{
return a + b;
}
}
+11
View File
@@ -0,0 +1,11 @@
extern "C" {
#ifdef SAMPLEDLL_EXPORTS
#define SAMPLEDLL_API __declspec(dllexport)
#else
#define SAMPLEDLL_API __declspec(dllimport)
#endif
SAMPLEDLL_API int addNumbers(int a, int b);
}
+58
View File
@@ -0,0 +1,58 @@
1 VERSIONINFO
FILEVERSION 1,0,0,0
PRODUCTVERSION 1,0,0,0
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "CompanyName", "fancy.code"
VALUE "FileDescription", "SampleDLL"
VALUE "FileVersion", "1.0"
VALUE "InternalName", "SampleDLL"
VALUE "LegalCopyright", "Copyright (c) 2004-2015 Joachim Bauch"
VALUE "OriginalFilename", "SampleDLL.dll"
VALUE "ProductName", "MemoryModule"
VALUE "ProductVersion", "0.0.4"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1252
END
END
#define IDS_HELLO 1
#define IDS_WORLD 20
STRINGTABLE
{
IDS_HELLO, "Hello"
IDS_WORLD, "World!"
}
STRINGRES RCDATA
{
"This is a ANSI string\0",
L"This is a UNICODE string\0",
}
STRINGRES1 RCDATA
{
"This is ANSI string 1\0",
L"This is UNICODE string 1\0",
}
STRINGRES2 RCDATA
{
"This is ANSI string 2\0",
L"This is UNICODE string 2\0",
}
STRINGRES3 RCDATA
{
"This is ANSI string 3\0",
L"This is UNICODE string 3\0",
}
+19
View File
@@ -0,0 +1,19 @@
#define WIN32_LEAN_AND_MEAN
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <windows.h>
extern BOOL MemoryModuleTestsuite();
int main(int argc, char* argv[])
{
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
if (!MemoryModuleTestsuite()) {
return 1;
}
return 0;
}
+52
View File
@@ -0,0 +1,52 @@
#!/bin/sh
##
## Generate header file.
##
cat > SampleExports.h << EOF
extern "C" {
#ifdef SAMPLEDLL_EXPORTS
#define SAMPLEDLL_API __declspec(dllexport)
#else
#define SAMPLEDLL_API __declspec(dllimport)
#endif
EOF
for i in `seq 1 100`;
do
cat >> SampleExports.h << EOF
SAMPLEDLL_API int add$i(int a);
EOF
done
cat >> SampleExports.h << EOF
}
EOF
##
## Generate source file.
##
cat > SampleExports.cpp << EOF
#include "SampleExports.h"
extern "C" {
EOF
for i in `seq 1 100 | sort -R`;
do
cat >> SampleExports.cpp << EOF
SAMPLEDLL_API int add$i(int a)
{
return a + $i;
}
EOF
done
cat >> SampleExports.cpp << EOF
}
EOF
+16
View File
@@ -0,0 +1,16 @@
#!/bin/bash
PLATFORM=$1
read -a TEST_DLLS <<< $2
for filename in "${TEST_DLLS[@]}"
do
:
echo "Testing $filename"
./runwine.sh "${PLATFORM}" ./LoadDll.exe $filename
if [ "$?" != "0" ]; then
exit 1
fi
done
echo "${#TEST_DLLS[@]} tests completed successfully"
+15
View File
@@ -0,0 +1,15 @@
#!/bin/bash
set -eu
PLATFORM=$1
shift
if [ "${PLATFORM}" = "x86_64" ]; then
export WINEPREFIX=${HOME}/.wine64/
WINE=wine64
else
export WINEPREFIX=${HOME}/.wine/
WINE=wine
fi
export WINEPATH=/usr/lib/gcc/${PLATFORM}-w64-mingw32/4.8/:/usr/${PLATFORM}-w64-mingw32/lib
exec ${WINE} $@