aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy Gu <timothygu99@gmail.com>2014-10-08 15:50:21 -0700
committerTimothy Gu <timothygu99@gmail.com>2015-03-15 17:15:14 -0700
commitdd4254a3d9d26cd436f984515570ec8cd211ee33 (patch)
treea83495b3a2497d16c9d36a8def435fc3bca9c61a
parent5ea707adea4146a64c38106a9bad11b01f74f0ef (diff)
downloaddlfcn-win32-dd4254a3d9d26cd436f984515570ec8cd211ee33.tar.gz
dlfcn-win32-dd4254a3d9d26cd436f984515570ec8cd211ee33.tar.bz2
dlfcn-win32-dd4254a3d9d26cd436f984515570ec8cd211ee33.zip
Add linked modules to a separate global list
Fixes #2.
-rw-r--r--CMakeLists.txt1
-rw-r--r--Makefile7
-rw-r--r--dlfcn.c142
-rw-r--r--test.c31
-rw-r--r--visual-studio/12/dl/dl.vcxproj4
-rw-r--r--visual-studio/12/dlfcn-win32.sln36
-rw-r--r--visual-studio/12/test/test.vcxproj8
7 files changed, 186 insertions, 43 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 972ffb4..1dbec48 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,6 +18,7 @@ if (BUILD_SHARED_LIBS)
18endif (BUILD_SHARED_LIBS) 18endif (BUILD_SHARED_LIBS)
19 19
20add_library(dl ${sources}) 20add_library(dl ${sources})
21target_link_libraries(dl psapi)
21 22
22install (TARGETS dl RUNTIME DESTINATION bin 23install (TARGETS dl RUNTIME DESTINATION bin
23 LIBRARY DESTINATION lib${LIB_SUFFIX} 24 LIBRARY DESTINATION lib${LIB_SUFFIX}
diff --git a/Makefile b/Makefile
index 0f32932..aec9ba8 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,8 @@
2# dlfcn-win32 Makefile 2# dlfcn-win32 Makefile
3# 3#
4include config.mak 4include config.mak
5CFLAGS=-Wall -O3 -fomit-frame-pointer 5CFLAGS = -Wall -O3 -fomit-frame-pointer
6LIBS += -lpsapi
6 7
7ifeq ($(BUILD_SHARED),yes) 8ifeq ($(BUILD_SHARED),yes)
8 TARGETS += libdl.dll 9 TARGETS += libdl.dll
@@ -33,7 +34,7 @@ libdl.a: $(LIB_OBJS)
33 $(RANLIB) libdl.a 34 $(RANLIB) libdl.a
34 35
35libdl.dll: $(LIB_OBJS) 36libdl.dll: $(LIB_OBJS)
36 $(CC) $(SHFLAGS) -shared -o $@ $^ 37 $(CC) $(SHFLAGS) -shared -o $@ $^ $(LIBS)
37 38
38libdl.lib: libdl.dll 39libdl.lib: libdl.dll
39 $(LIBCMD) /machine:i386 /def:libdl.def 40 $(LIBCMD) /machine:i386 /def:libdl.def
@@ -60,7 +61,7 @@ lib-install: $(LIBS)
60install: $(INSTALL) 61install: $(INSTALL)
61 62
62test.exe: test.o $(TARGETS) 63test.exe: test.o $(TARGETS)
63 $(CC) -o $@ $< -L. -ldl 64 $(CC) -o $@ $< -L. -ldl $(LIBS)
64 65
65testdll.dll: testdll.c 66testdll.dll: testdll.c
66 $(CC) -shared -o $@ $^ 67 $(CC) -shared -o $@ $^
diff --git a/dlfcn.c b/dlfcn.c
index add1f4f..324fafc 100644
--- a/dlfcn.c
+++ b/dlfcn.c
@@ -22,7 +22,9 @@
22#include <stdlib.h> 22#include <stdlib.h>
23#include <crtdbg.h> 23#include <crtdbg.h>
24#endif 24#endif
25#define PSAPI_VERSION 1
25#include <windows.h> 26#include <windows.h>
27#include <psapi.h>
26#include <stdio.h> 28#include <stdio.h>
27 29
28#define DLFCN_WIN32_EXPORTS 30#define DLFCN_WIN32_EXPORTS
@@ -40,23 +42,25 @@ typedef struct global_object {
40} global_object; 42} global_object;
41 43
42static global_object first_object; 44static global_object first_object;
45static global_object first_automatic_object;
46static int auto_ref_count = 0;
43 47
44/* These functions implement a double linked list for the global objects. */ 48/* These functions implement a double linked list for the global objects. */
45static global_object *global_search( HMODULE hModule ) 49static global_object *global_search( global_object *start, HMODULE hModule )
46{ 50{
47 global_object *pobject; 51 global_object *pobject;
48 52
49 if( hModule == NULL ) 53 if( hModule == NULL )
50 return NULL; 54 return NULL;
51 55
52 for( pobject = &first_object; pobject ; pobject = pobject->next ) 56 for( pobject = start; pobject; pobject = pobject->next )
53 if( pobject->hModule == hModule ) 57 if( pobject->hModule == hModule )
54 return pobject; 58 return pobject;
55 59
56 return NULL; 60 return NULL;
57} 61}
58 62
59static void global_add( HMODULE hModule ) 63static void global_add( global_object *start, HMODULE hModule )
60{ 64{
61 global_object *pobject; 65 global_object *pobject;
62 global_object *nobject; 66 global_object *nobject;
@@ -64,15 +68,22 @@ static void global_add( HMODULE hModule )
64 if( hModule == NULL ) 68 if( hModule == NULL )
65 return; 69 return;
66 70
67 pobject = global_search( hModule ); 71 pobject = global_search( start, hModule );
68 72
69 /* Do not add object again if it's already on the list */ 73 /* Do not add object again if it's already on the list */
70 if( pobject ) 74 if( pobject )
71 return; 75 return;
72 76
73 for( pobject = &first_object; pobject->next ; pobject = pobject->next ); 77 if( start == &first_automatic_object )
78 {
79 pobject = global_search( &first_object, hModule );
80 if( pobject )
81 return;
82 }
83
84 for( pobject = start; pobject->next; pobject = pobject->next );
74 85
75 nobject = malloc( sizeof(global_object) ); 86 nobject = malloc( sizeof( global_object ) );
76 87
77 /* Should this be enough to fail global_add, and therefore also fail 88 /* Should this be enough to fail global_add, and therefore also fail
78 * dlopen? 89 * dlopen?
@@ -86,14 +97,14 @@ static void global_add( HMODULE hModule )
86 nobject->hModule = hModule; 97 nobject->hModule = hModule;
87} 98}
88 99
89static void global_rem( HMODULE hModule ) 100static void global_rem( global_object *start, HMODULE hModule )
90{ 101{
91 global_object *pobject; 102 global_object *pobject;
92 103
93 if( hModule == NULL ) 104 if( hModule == NULL )
94 return; 105 return;
95 106
96 pobject = global_search( hModule ); 107 pobject = global_search( start, hModule );
97 108
98 if( !pobject ) 109 if( !pobject )
99 return; 110 return;
@@ -185,18 +196,40 @@ void *dlopen( const char *file, int mode )
185 196
186 if( file == 0 ) 197 if( file == 0 )
187 { 198 {
199 HMODULE hAddtnlMods[1024]; // Already loaded modules
200 HANDLE hCurrentProc = GetCurrentProcess( );
201 DWORD cbNeeded;
202
188 /* POSIX says that if the value of file is 0, a handle on a global 203 /* POSIX says that if the value of file is 0, a handle on a global
189 * symbol object must be provided. That object must be able to access 204 * symbol object must be provided. That object must be able to access
190 * all symbols from the original program file, and any objects loaded 205 * all symbols from the original program file, and any objects loaded
191 * with the RTLD_GLOBAL flag. 206 * with the RTLD_GLOBAL flag.
192 * The return value from GetModuleHandle( ) allows us to retrieve 207 * The return value from GetModuleHandle( ) allows us to retrieve
193 * symbols only from the original program file. For objects loaded with 208 * symbols only from the original program file. For objects loaded with
194 * the RTLD_GLOBAL flag, we create our own list later on. 209 * the RTLD_GLOBAL flag, we create our own list later on. For objects
210 * outside of the program file but already loaded (e.g. linked DLLs)
211 * they are added below.
195 */ 212 */
196 hModule = GetModuleHandle( NULL ); 213 hModule = GetModuleHandle( NULL );
197 214
198 if( !hModule ) 215 if( !hModule )
199 save_err_ptr_str( file ); 216 save_err_ptr_str( file );
217
218
219 /* GetModuleHandle( NULL ) only returns the current program file. So
220 * if we want to get ALL loaded module including those in linked DLLs,
221 * we have to use EnumProcessModules( ).
222 */
223 if( EnumProcessModules( hCurrentProc, hAddtnlMods,
224 sizeof( hAddtnlMods ), &cbNeeded ) != 0 )
225 {
226 DWORD i;
227 for( i = 0; i < cbNeeded / sizeof( HMODULE ); i++ )
228 {
229 global_add( &first_automatic_object, hAddtnlMods[i] );
230 }
231 }
232 auto_ref_count++;
200 } 233 }
201 else 234 else
202 { 235 {
@@ -233,7 +266,7 @@ void *dlopen( const char *file, int mode )
233 if( !hModule ) 266 if( !hModule )
234 save_err_str( lpFileName ); 267 save_err_str( lpFileName );
235 else if( (mode & RTLD_GLOBAL) ) 268 else if( (mode & RTLD_GLOBAL) )
236 global_add( hModule ); 269 global_add( &first_object, hModule );
237 } 270 }
238 271
239 /* Return to previous state of the error-mode bit flags. */ 272 /* Return to previous state of the error-mode bit flags. */
@@ -242,6 +275,21 @@ void *dlopen( const char *file, int mode )
242 return (void *) hModule; 275 return (void *) hModule;
243} 276}
244 277
278static void free_auto( )
279{
280 global_object *pobject = first_automatic_object.next;
281 if( pobject )
282 {
283 global_object *next;
284 for ( ; pobject; pobject = next )
285 {
286 next = pobject->next;
287 free( pobject );
288 }
289 first_automatic_object.next = NULL;
290 }
291}
292
245int dlclose( void *handle ) 293int dlclose( void *handle )
246{ 294{
247 HMODULE hModule = (HMODULE) handle; 295 HMODULE hModule = (HMODULE) handle;
@@ -255,7 +303,18 @@ int dlclose( void *handle )
255 * objects. 303 * objects.
256 */ 304 */
257 if( ret ) 305 if( ret )
258 global_rem( hModule ); 306 {
307 HMODULE cur = GetModuleHandle( NULL );
308 global_rem( &first_object, hModule );
309 if( hModule == cur )
310 {
311 auto_ref_count--;
312 if( auto_ref_count < 0 )
313 auto_ref_count = 0;
314 if( !auto_ref_count )
315 free_auto( );
316 }
317 }
259 else 318 else
260 save_err_ptr_str( handle ); 319 save_err_ptr_str( handle );
261 320
@@ -268,37 +327,47 @@ int dlclose( void *handle )
268void *dlsym( void *handle, const char *name ) 327void *dlsym( void *handle, const char *name )
269{ 328{
270 FARPROC symbol; 329 FARPROC symbol;
330 HMODULE hModule;
271 331
272 current_error = NULL; 332 current_error = NULL;
273 333
274 symbol = GetProcAddress( handle, name ); 334 symbol = GetProcAddress( handle, name );
275 335
276 if( symbol == NULL ) 336 if( symbol != NULL )
277 { 337 goto end;
278 HMODULE hModule;
279 338
280 /* If the handle for the original program file is passed, also search 339 /* If the handle for the original program file is passed, also search
281 * in all globally loaded objects. 340 * in all globally loaded objects.
282 */ 341 */
283 342
284 hModule = GetModuleHandle( NULL ); 343 hModule = GetModuleHandle( NULL );
285 344
286 if( hModule == handle ) 345 if( hModule == handle )
346 {
347 global_object *pobject;
348
349 for( pobject = &first_object; pobject; pobject = pobject->next )
287 { 350 {
288 global_object *pobject; 351 if( pobject->hModule )
352 {
353 symbol = GetProcAddress( pobject->hModule, name );
354 if( symbol != NULL )
355 goto end;
356 }
357 }
289 358
290 for( pobject = &first_object; pobject ; pobject = pobject->next ) 359 for( pobject = &first_automatic_object; pobject; pobject = pobject->next )
360 {
361 if( pobject->hModule )
291 { 362 {
292 if( pobject->hModule ) 363 symbol = GetProcAddress( pobject->hModule, name );
293 { 364 if( symbol != NULL )
294 symbol = GetProcAddress( pobject->hModule, name ); 365 goto end;
295 if( symbol != NULL )
296 break;
297 }
298 } 366 }
299 } 367 }
300 } 368 }
301 369
370end:
302 if( symbol == NULL ) 371 if( symbol == NULL )
303 save_err_str( name ); 372 save_err_str( name );
304 373
@@ -316,3 +385,22 @@ char *dlerror( void )
316 385
317 return error_pointer; 386 return error_pointer;
318} 387}
388
389#ifdef SHARED
390BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
391{
392 /*
393 * https://msdn.microsoft.com/en-us/library/windows/desktop/ms682583(v=vs.85).aspx
394 *
395 * When handling DLL_PROCESS_DETACH, a DLL should free resources such as heap
396 * memory only if the DLL is being unloaded dynamically (the lpReserved
397 * parameter is NULL).
398 */
399 if( fdwReason == DLL_PROCESS_DETACH && !lpvReserved )
400 {
401 auto_ref_count = 0;
402 free_auto( );
403 }
404 return TRUE;
405}
406#endif
diff --git a/test.c b/test.c
index d6280e4..878694e 100644
--- a/test.c
+++ b/test.c
@@ -31,7 +31,8 @@
31#define CLOSE_LIB dlclose( library ) 31#define CLOSE_LIB dlclose( library )
32#define CLOSE_GLOBAL dlclose( global ) 32#define CLOSE_GLOBAL dlclose( global )
33 33
34#define RETURN_ERROR return 1 34#define RETURN_ERROR printf("From line %d\n", __LINE__); return 1
35
35#define RUNFUNC do { \ 36#define RUNFUNC do { \
36 ret = function (); \ 37 ret = function (); \
37 if( ret != 0) { \ 38 if( ret != 0) { \
@@ -73,6 +74,7 @@ int main()
73 void *library; 74 void *library;
74 char *error; 75 char *error;
75 int (*function)( void ); 76 int (*function)( void );
77 int (*printf_local)( const char * );
76 int (*nonexistentfunction)( void ); 78 int (*nonexistentfunction)( void );
77 int ret; 79 int ret;
78 80
@@ -106,6 +108,20 @@ int main()
106 else 108 else
107 printf( "SUCCESS\tGot global handle: %p\n", global ); 109 printf( "SUCCESS\tGot global handle: %p\n", global );
108 110
111 printf_local = dlsym(global, "printf");
112 if (!printf_local)
113 {
114 error = dlerror();
115 printf("ERROR\tCould not get symbol from global handle: %s\n",
116 error ? error : "");
117 CLOSE_LIB;
118 CLOSE_GLOBAL;
119 RETURN_ERROR;
120 }
121 else
122 printf("SUCCESS\tGot symbol from global handle: %p\n", printf_local);
123 printf_local("Hello world from local printf!\n");
124
109 function = dlsym( library, "function" ); 125 function = dlsym( library, "function" );
110 if( !function ) 126 if( !function )
111 { 127 {
@@ -288,6 +304,19 @@ int main()
288 error ? error : "" ); 304 error ? error : "" );
289 } 305 }
290 306
307 function = dlsym(global, "printf");
308 if (!function)
309 {
310 error = dlerror();
311 printf("ERROR\tCould not get symbol from global handle: %s\n",
312 error ? error : "");
313 CLOSE_LIB;
314 CLOSE_GLOBAL;
315 RETURN_ERROR;
316 }
317 else
318 printf("SUCCESS\tGot symbol from global handle: %p\n", function);
319
291 ret = dlclose( library ); 320 ret = dlclose( library );
292 if( ret ) 321 if( ret )
293 { 322 {
diff --git a/visual-studio/12/dl/dl.vcxproj b/visual-studio/12/dl/dl.vcxproj
index cea69bd..45f87e7 100644
--- a/visual-studio/12/dl/dl.vcxproj
+++ b/visual-studio/12/dl/dl.vcxproj
@@ -129,6 +129,7 @@
129 </ClCompile> 129 </ClCompile>
130 <Link> 130 <Link>
131 <GenerateDebugInformation>true</GenerateDebugInformation> 131 <GenerateDebugInformation>true</GenerateDebugInformation>
132 <AdditionalDependencies>psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
132 </Link> 133 </Link>
133 </ItemDefinitionGroup> 134 </ItemDefinitionGroup>
134 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugStatic|Win32'"> 135 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugStatic|Win32'">
@@ -149,6 +150,7 @@
149 </ClCompile> 150 </ClCompile>
150 <Link> 151 <Link>
151 <GenerateDebugInformation>true</GenerateDebugInformation> 152 <GenerateDebugInformation>true</GenerateDebugInformation>
153 <AdditionalDependencies>psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
152 </Link> 154 </Link>
153 </ItemDefinitionGroup> 155 </ItemDefinitionGroup>
154 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugStatic|x64'"> 156 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugStatic|x64'">
@@ -174,6 +176,7 @@
174 <GenerateDebugInformation>true</GenerateDebugInformation> 176 <GenerateDebugInformation>true</GenerateDebugInformation>
175 <EnableCOMDATFolding>true</EnableCOMDATFolding> 177 <EnableCOMDATFolding>true</EnableCOMDATFolding>
176 <OptimizeReferences>true</OptimizeReferences> 178 <OptimizeReferences>true</OptimizeReferences>
179 <AdditionalDependencies>psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
177 </Link> 180 </Link>
178 </ItemDefinitionGroup> 181 </ItemDefinitionGroup>
179 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseStatic|Win32'"> 182 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseStatic|Win32'">
@@ -203,6 +206,7 @@
203 <GenerateDebugInformation>true</GenerateDebugInformation> 206 <GenerateDebugInformation>true</GenerateDebugInformation>
204 <EnableCOMDATFolding>true</EnableCOMDATFolding> 207 <EnableCOMDATFolding>true</EnableCOMDATFolding>
205 <OptimizeReferences>true</OptimizeReferences> 208 <OptimizeReferences>true</OptimizeReferences>
209 <AdditionalDependencies>psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
206 </Link> 210 </Link>
207 </ItemDefinitionGroup> 211 </ItemDefinitionGroup>
208 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseStatic|x64'"> 212 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseStatic|x64'">
diff --git a/visual-studio/12/dlfcn-win32.sln b/visual-studio/12/dlfcn-win32.sln
index d64cbdb..952a69c 100644
--- a/visual-studio/12/dlfcn-win32.sln
+++ b/visual-studio/12/dlfcn-win32.sln
@@ -30,62 +30,74 @@ Global
30 ReleaseStatic|x64 = ReleaseStatic|x64 30 ReleaseStatic|x64 = ReleaseStatic|x64
31 EndGlobalSection 31 EndGlobalSection
32 GlobalSection(ProjectConfigurationPlatforms) = postSolution 32 GlobalSection(ProjectConfigurationPlatforms) = postSolution
33 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Debug|ARM.ActiveCfg = Debug|Win32 33 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Debug|ARM.ActiveCfg = ReleaseStatic|x64
34 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Debug|ARM.Build.0 = ReleaseStatic|x64
34 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Debug|Win32.ActiveCfg = Debug|Win32 35 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Debug|Win32.ActiveCfg = Debug|Win32
35 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Debug|Win32.Build.0 = Debug|Win32 36 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Debug|Win32.Build.0 = Debug|Win32
36 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Debug|x64.ActiveCfg = Debug|x64 37 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Debug|x64.ActiveCfg = Debug|x64
37 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Debug|x64.Build.0 = Debug|x64 38 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Debug|x64.Build.0 = Debug|x64
38 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.DebugStatic|ARM.ActiveCfg = DebugStatic|Win32 39 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.DebugStatic|ARM.ActiveCfg = ReleaseStatic|x64
40 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.DebugStatic|ARM.Build.0 = ReleaseStatic|x64
39 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.DebugStatic|Win32.ActiveCfg = DebugStatic|Win32 41 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.DebugStatic|Win32.ActiveCfg = DebugStatic|Win32
40 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.DebugStatic|Win32.Build.0 = DebugStatic|Win32 42 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.DebugStatic|Win32.Build.0 = DebugStatic|Win32
41 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.DebugStatic|x64.ActiveCfg = DebugStatic|x64 43 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.DebugStatic|x64.ActiveCfg = DebugStatic|x64
42 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.DebugStatic|x64.Build.0 = DebugStatic|x64 44 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.DebugStatic|x64.Build.0 = DebugStatic|x64
43 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Release|ARM.ActiveCfg = Release|Win32 45 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Release|ARM.ActiveCfg = ReleaseStatic|x64
46 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Release|ARM.Build.0 = ReleaseStatic|x64
44 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Release|Win32.ActiveCfg = Release|Win32 47 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Release|Win32.ActiveCfg = Release|Win32
45 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Release|Win32.Build.0 = Release|Win32 48 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Release|Win32.Build.0 = Release|Win32
46 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Release|x64.ActiveCfg = Release|x64 49 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Release|x64.ActiveCfg = Release|x64
47 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Release|x64.Build.0 = Release|x64 50 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.Release|x64.Build.0 = Release|x64
48 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.ReleaseStatic|ARM.ActiveCfg = ReleaseStatic|Win32 51 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.ReleaseStatic|ARM.ActiveCfg = ReleaseStatic|x64
52 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.ReleaseStatic|ARM.Build.0 = ReleaseStatic|x64
49 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.ReleaseStatic|Win32.ActiveCfg = ReleaseStatic|Win32 53 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.ReleaseStatic|Win32.ActiveCfg = ReleaseStatic|Win32
50 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.ReleaseStatic|Win32.Build.0 = ReleaseStatic|Win32 54 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.ReleaseStatic|Win32.Build.0 = ReleaseStatic|Win32
51 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.ReleaseStatic|x64.ActiveCfg = ReleaseStatic|x64 55 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.ReleaseStatic|x64.ActiveCfg = ReleaseStatic|x64
52 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.ReleaseStatic|x64.Build.0 = ReleaseStatic|x64 56 {36E45DAF-D2EC-4660-B84F-3BC72664643E}.ReleaseStatic|x64.Build.0 = ReleaseStatic|x64
53 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Debug|ARM.ActiveCfg = Debug|Win32 57 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Debug|ARM.ActiveCfg = ReleaseStatic|x64
58 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Debug|ARM.Build.0 = ReleaseStatic|x64
54 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Debug|Win32.ActiveCfg = Debug|Win32 59 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Debug|Win32.ActiveCfg = Debug|Win32
55 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Debug|Win32.Build.0 = Debug|Win32 60 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Debug|Win32.Build.0 = Debug|Win32
56 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Debug|x64.ActiveCfg = Debug|x64 61 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Debug|x64.ActiveCfg = Debug|x64
57 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Debug|x64.Build.0 = Debug|x64 62 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Debug|x64.Build.0 = Debug|x64
58 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.DebugStatic|ARM.ActiveCfg = DebugStatic|Win32 63 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.DebugStatic|ARM.ActiveCfg = ReleaseStatic|x64
64 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.DebugStatic|ARM.Build.0 = ReleaseStatic|x64
59 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.DebugStatic|Win32.ActiveCfg = DebugStatic|Win32 65 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.DebugStatic|Win32.ActiveCfg = DebugStatic|Win32
60 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.DebugStatic|Win32.Build.0 = DebugStatic|Win32 66 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.DebugStatic|Win32.Build.0 = DebugStatic|Win32
61 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.DebugStatic|x64.ActiveCfg = DebugStatic|x64 67 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.DebugStatic|x64.ActiveCfg = DebugStatic|x64
62 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.DebugStatic|x64.Build.0 = DebugStatic|x64 68 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.DebugStatic|x64.Build.0 = DebugStatic|x64
63 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Release|ARM.ActiveCfg = Release|Win32 69 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Release|ARM.ActiveCfg = ReleaseStatic|x64
70 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Release|ARM.Build.0 = ReleaseStatic|x64
64 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Release|Win32.ActiveCfg = Release|Win32 71 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Release|Win32.ActiveCfg = Release|Win32
65 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Release|Win32.Build.0 = Release|Win32 72 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Release|Win32.Build.0 = Release|Win32
66 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Release|x64.ActiveCfg = Release|x64 73 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Release|x64.ActiveCfg = Release|x64
67 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Release|x64.Build.0 = Release|x64 74 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.Release|x64.Build.0 = Release|x64
68 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.ReleaseStatic|ARM.ActiveCfg = ReleaseStatic|Win32 75 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.ReleaseStatic|ARM.ActiveCfg = ReleaseStatic|x64
76 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.ReleaseStatic|ARM.Build.0 = ReleaseStatic|x64
69 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.ReleaseStatic|Win32.ActiveCfg = ReleaseStatic|Win32 77 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.ReleaseStatic|Win32.ActiveCfg = ReleaseStatic|Win32
70 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.ReleaseStatic|Win32.Build.0 = ReleaseStatic|Win32 78 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.ReleaseStatic|Win32.Build.0 = ReleaseStatic|Win32
71 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.ReleaseStatic|x64.ActiveCfg = ReleaseStatic|x64 79 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.ReleaseStatic|x64.ActiveCfg = ReleaseStatic|x64
72 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.ReleaseStatic|x64.Build.0 = ReleaseStatic|x64 80 {583AA2B8-B981-4DE9-A374-47EC9F817C5E}.ReleaseStatic|x64.Build.0 = ReleaseStatic|x64
73 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Debug|ARM.ActiveCfg = Debug|Win32 81 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Debug|ARM.ActiveCfg = ReleaseStatic|x64
82 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Debug|ARM.Build.0 = ReleaseStatic|x64
74 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Debug|Win32.ActiveCfg = Debug|Win32 83 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Debug|Win32.ActiveCfg = Debug|Win32
75 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Debug|Win32.Build.0 = Debug|Win32 84 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Debug|Win32.Build.0 = Debug|Win32
76 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Debug|x64.ActiveCfg = Debug|x64 85 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Debug|x64.ActiveCfg = Debug|x64
77 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Debug|x64.Build.0 = Debug|x64 86 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Debug|x64.Build.0 = Debug|x64
78 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.DebugStatic|ARM.ActiveCfg = DebugStatic|Win32 87 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.DebugStatic|ARM.ActiveCfg = ReleaseStatic|x64
88 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.DebugStatic|ARM.Build.0 = ReleaseStatic|x64
79 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.DebugStatic|Win32.ActiveCfg = DebugStatic|Win32 89 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.DebugStatic|Win32.ActiveCfg = DebugStatic|Win32
80 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.DebugStatic|Win32.Build.0 = DebugStatic|Win32 90 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.DebugStatic|Win32.Build.0 = DebugStatic|Win32
81 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.DebugStatic|x64.ActiveCfg = DebugStatic|x64 91 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.DebugStatic|x64.ActiveCfg = DebugStatic|x64
82 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.DebugStatic|x64.Build.0 = DebugStatic|x64 92 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.DebugStatic|x64.Build.0 = DebugStatic|x64
83 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Release|ARM.ActiveCfg = Release|Win32 93 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Release|ARM.ActiveCfg = ReleaseStatic|x64
94 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Release|ARM.Build.0 = ReleaseStatic|x64
84 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Release|Win32.ActiveCfg = Release|Win32 95 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Release|Win32.ActiveCfg = Release|Win32
85 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Release|Win32.Build.0 = Release|Win32 96 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Release|Win32.Build.0 = Release|Win32
86 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Release|x64.ActiveCfg = Release|x64 97 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Release|x64.ActiveCfg = Release|x64
87 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Release|x64.Build.0 = Release|x64 98 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.Release|x64.Build.0 = Release|x64
88 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.ReleaseStatic|ARM.ActiveCfg = ReleaseStatic|Win32 99 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.ReleaseStatic|ARM.ActiveCfg = ReleaseStatic|x64
100 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.ReleaseStatic|ARM.Build.0 = ReleaseStatic|x64
89 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.ReleaseStatic|Win32.ActiveCfg = ReleaseStatic|Win32 101 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.ReleaseStatic|Win32.ActiveCfg = ReleaseStatic|Win32
90 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.ReleaseStatic|Win32.Build.0 = ReleaseStatic|Win32 102 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.ReleaseStatic|Win32.Build.0 = ReleaseStatic|Win32
91 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.ReleaseStatic|x64.ActiveCfg = ReleaseStatic|x64 103 {2AEB7143-35F8-488A-9414-CA4B0B45D16E}.ReleaseStatic|x64.ActiveCfg = ReleaseStatic|x64
diff --git a/visual-studio/12/test/test.vcxproj b/visual-studio/12/test/test.vcxproj
index 8773e07..6866897 100644
--- a/visual-studio/12/test/test.vcxproj
+++ b/visual-studio/12/test/test.vcxproj
@@ -128,6 +128,7 @@
128 </ClCompile> 128 </ClCompile>
129 <Link> 129 <Link>
130 <GenerateDebugInformation>true</GenerateDebugInformation> 130 <GenerateDebugInformation>true</GenerateDebugInformation>
131 <AdditionalDependencies>psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
131 </Link> 132 </Link>
132 </ItemDefinitionGroup> 133 </ItemDefinitionGroup>
133 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugStatic|Win32'"> 134 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugStatic|Win32'">
@@ -138,6 +139,7 @@
138 </ClCompile> 139 </ClCompile>
139 <Link> 140 <Link>
140 <GenerateDebugInformation>true</GenerateDebugInformation> 141 <GenerateDebugInformation>true</GenerateDebugInformation>
142 <AdditionalDependencies>psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
141 </Link> 143 </Link>
142 </ItemDefinitionGroup> 144 </ItemDefinitionGroup>
143 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> 145 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@@ -148,6 +150,7 @@
148 </ClCompile> 150 </ClCompile>
149 <Link> 151 <Link>
150 <GenerateDebugInformation>true</GenerateDebugInformation> 152 <GenerateDebugInformation>true</GenerateDebugInformation>
153 <AdditionalDependencies>psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
151 </Link> 154 </Link>
152 </ItemDefinitionGroup> 155 </ItemDefinitionGroup>
153 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugStatic|x64'"> 156 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugStatic|x64'">
@@ -158,6 +161,7 @@
158 </ClCompile> 161 </ClCompile>
159 <Link> 162 <Link>
160 <GenerateDebugInformation>true</GenerateDebugInformation> 163 <GenerateDebugInformation>true</GenerateDebugInformation>
164 <AdditionalDependencies>psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
161 </Link> 165 </Link>
162 </ItemDefinitionGroup> 166 </ItemDefinitionGroup>
163 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 167 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -172,6 +176,7 @@
172 <GenerateDebugInformation>true</GenerateDebugInformation> 176 <GenerateDebugInformation>true</GenerateDebugInformation>
173 <EnableCOMDATFolding>true</EnableCOMDATFolding> 177 <EnableCOMDATFolding>true</EnableCOMDATFolding>
174 <OptimizeReferences>true</OptimizeReferences> 178 <OptimizeReferences>true</OptimizeReferences>
179 <AdditionalDependencies>psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
175 </Link> 180 </Link>
176 </ItemDefinitionGroup> 181 </ItemDefinitionGroup>
177 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseStatic|Win32'"> 182 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseStatic|Win32'">
@@ -186,6 +191,7 @@
186 <GenerateDebugInformation>true</GenerateDebugInformation> 191 <GenerateDebugInformation>true</GenerateDebugInformation>
187 <EnableCOMDATFolding>true</EnableCOMDATFolding> 192 <EnableCOMDATFolding>true</EnableCOMDATFolding>
188 <OptimizeReferences>true</OptimizeReferences> 193 <OptimizeReferences>true</OptimizeReferences>
194 <AdditionalDependencies>psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
189 </Link> 195 </Link>
190 </ItemDefinitionGroup> 196 </ItemDefinitionGroup>
191 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> 197 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -200,6 +206,7 @@
200 <GenerateDebugInformation>true</GenerateDebugInformation> 206 <GenerateDebugInformation>true</GenerateDebugInformation>
201 <EnableCOMDATFolding>true</EnableCOMDATFolding> 207 <EnableCOMDATFolding>true</EnableCOMDATFolding>
202 <OptimizeReferences>true</OptimizeReferences> 208 <OptimizeReferences>true</OptimizeReferences>
209 <AdditionalDependencies>psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
203 </Link> 210 </Link>
204 </ItemDefinitionGroup> 211 </ItemDefinitionGroup>
205 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseStatic|x64'"> 212 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseStatic|x64'">
@@ -214,6 +221,7 @@
214 <GenerateDebugInformation>true</GenerateDebugInformation> 221 <GenerateDebugInformation>true</GenerateDebugInformation>
215 <EnableCOMDATFolding>true</EnableCOMDATFolding> 222 <EnableCOMDATFolding>true</EnableCOMDATFolding>
216 <OptimizeReferences>true</OptimizeReferences> 223 <OptimizeReferences>true</OptimizeReferences>
224 <AdditionalDependencies>psapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
217 </Link> 225 </Link>
218 </ItemDefinitionGroup> 226 </ItemDefinitionGroup>
219 <ItemGroup> 227 <ItemGroup>