aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/CMakeLists.txt12
-rw-r--r--tests/test.c687
-rw-r--r--tests/testdll.c47
-rw-r--r--tests/testdll2.c59
-rw-r--r--tests/testdll3.c42
5 files changed, 847 insertions, 0 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644
index 0000000..64f85f7
--- /dev/null
+++ b/tests/CMakeLists.txt
@@ -0,0 +1,12 @@
1enable_testing()
2include_directories(../src)
3add_library(testdll SHARED testdll.c)
4set_target_properties(testdll PROPERTIES PREFIX "")
5add_library(testdll2 SHARED testdll2.c)
6set_target_properties(testdll2 PROPERTIES PREFIX "")
7target_link_libraries(testdll2 dl)
8add_library(testdll3 SHARED testdll3.c)
9set_target_properties(testdll3 PROPERTIES PREFIX "")
10add_executable(t_dlfcn test.c)
11target_link_libraries(t_dlfcn dl)
12add_test (NAME t_dlfcn COMMAND t_dlfcn)
diff --git a/tests/test.c b/tests/test.c
new file mode 100644
index 0000000..5d060d2
--- /dev/null
+++ b/tests/test.c
@@ -0,0 +1,687 @@
1/*
2 * dlfcn-win32
3 * Copyright (c) 2007-2009 Ramiro Polla
4 * Copyright (c) 2014 Tiancheng "Timothy" Gu
5 * Copyright (c) 2019 Pali Rohár <pali.rohar@gmail.com>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26#ifdef _DEBUG
27#define _CRTDBG_MAP_ALLOC
28#include <stdlib.h>
29#include <crtdbg.h>
30#endif
31#include <stdio.h>
32#include <string.h>
33#include <windows.h>
34#include <wchar.h>
35#include <io.h>
36#include <fcntl.h>
37#include <direct.h>
38#include "dlfcn.h"
39
40/* If these dlclose's fails, we don't care as the handles are going to be
41 closed eventually when the program ends. */
42#define CLOSE_LIB dlclose( library )
43#define CLOSE_GLOBAL dlclose( global )
44
45#define RETURN_ERROR printf("From line %d\n", __LINE__); return 1
46
47#define RUNFUNC do { \
48 ret = function (); \
49 if( ret != 0) { \
50 CLOSE_LIB; \
51 CLOSE_GLOBAL; \
52 RETURN_ERROR; \
53 } \
54 } while( 0 )
55
56/* This is what this test does:
57 * - Open library with RTLD_GLOBAL
58 * - Get global object
59 * - Get symbol from library through library object <- works
60 * - Run function if it worked
61 * - Get nonexistent symbol from library through library object <- fails
62 * - Get symbol from library through global object <- works
63 * - Run function if it worked
64 * - Get nonexistent symbol from library through global object <- fails
65 * - Close library
66 * - Open library with RTLD_LOCAL
67 * - Get symbol from library through library object <- works
68 * - Run function if it worked
69 * - Get nonexistent symbol from library through library object <- fails
70 * - Get local symbol from library through global object <- fails
71 * - Get nonexistent local symbol from library through global object <- fails
72 * - Open library again (without closing it first) with RTLD_GLOBAL
73 * - Get symbol from library through global object <- works
74 * - Get nonexistent symbol from library through global object <- fails
75 * - Close library
76 * - Close global object
77 *
78 * If one test fails, the program terminates itself.
79 */
80
81int main()
82{
83 void *global;
84 void *library2;
85 void *library;
86 char *error;
87 int (*function)( void );
88 int (*function2_from_library2)( void );
89 size_t (*fwrite_local) ( const void *, size_t, size_t, FILE * );
90 size_t (*fputs_default) ( const char *, FILE * );
91 int (*nonexistentfunction)( void );
92 int fd;
93 int ret;
94 HMODULE library3;
95 char toolongfile[32767];
96 DWORD code;
97 char nonlibraryfile[MAX_PATH];
98 char bytename[sizeof("testdll2.dll")+4];
99 WCHAR widename[sizeof("testdll2.dll")+1];
100 DWORD length;
101 HANDLE tempfile;
102 DWORD dummy;
103 UINT uMode;
104
105#ifdef _DEBUG
106 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
107 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
108 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
109 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);
110 _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
111 _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
112#endif
113
114 length = GetTempPathA( sizeof( nonlibraryfile ) - sizeof( "temp.dll" ), nonlibraryfile );
115 if( length == 0 || length > sizeof( nonlibraryfile ) - sizeof( "temp.dll" ) )
116 {
117 printf( "ERROR\tGetTempPath failed\n" );
118 RETURN_ERROR;
119 }
120
121 memcpy( nonlibraryfile + length, "temp.dll", sizeof( "temp.dll" ) );
122
123 tempfile = CreateFileA( (LPCSTR) nonlibraryfile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL );
124 if( tempfile == INVALID_HANDLE_VALUE )
125 {
126 printf( "ERROR\tCannot create temporary file %s: %lu\n", nonlibraryfile, (unsigned long)GetLastError( ) );
127 RETURN_ERROR;
128 }
129
130 WriteFile( tempfile, "test content", 12, &dummy, NULL );
131
132 CloseHandle( tempfile );
133
134 uMode = SetErrorMode( SEM_FAILCRITICALERRORS );
135 library3 = LoadLibraryA( nonlibraryfile );
136 code = GetLastError( );
137 SetErrorMode( uMode );
138 if( library3 )
139 {
140 printf( "ERROR\tNon-library file %s was opened via WINAPI\n", nonlibraryfile );
141 CloseHandle( library3 );
142 DeleteFileA( nonlibraryfile );
143 RETURN_ERROR;
144 }
145 else if( code != ERROR_BAD_EXE_FORMAT )
146 {
147 printf( "ERROR\tNon-library file %s was processed via WINAPI: %lu\n", nonlibraryfile, (unsigned long)code );
148 DeleteFileA( nonlibraryfile );
149 RETURN_ERROR;
150 }
151 else
152 printf( "SUCCESS\tCould not open non-library file %s via WINAPI: %lu\n", nonlibraryfile, (unsigned long)code );
153
154 library = dlopen( nonlibraryfile, RTLD_GLOBAL );
155 if( library )
156 {
157 printf( "ERROR\tNon-library file %s was opened via dlopen\n", nonlibraryfile );
158 dlclose( library );
159 DeleteFileA( nonlibraryfile );
160 RETURN_ERROR;
161 }
162 error = dlerror( );
163 if( !error )
164 {
165 printf( "ERROR\tNo error from dlopen for non-library file\n" );
166 DeleteFileA( nonlibraryfile );
167 RETURN_ERROR;
168 }
169 else
170 printf( "SUCCESS\tCould not open non-library file %s: %s\n", nonlibraryfile, error );
171
172 DeleteFileA( nonlibraryfile );
173
174 library = dlopen( "nonexistentfile.dll", RTLD_GLOBAL );
175 if( library )
176 {
177 printf( "ERROR\tNon-existent file nonexistentfile.dll was opened via dlopen\n" );
178 RETURN_ERROR;
179 }
180 error = dlerror( );
181 if( !error )
182 {
183 printf( "ERROR\tNo error from dlopen for non-existent file\n" );
184 RETURN_ERROR;
185 }
186 else
187 printf( "SUCCESS\tCould not open non-existent file nonexistentfile.dll: %s\n", error );
188
189 memset( toolongfile, 'X', sizeof( toolongfile ) - 5 );
190 memcpy( toolongfile + sizeof( toolongfile ) - 5, ".dll", 5 );
191
192 library = dlopen( toolongfile, RTLD_GLOBAL );
193 if( library )
194 {
195 printf( "ERROR\tFile with too long file name was opened via dlopen\n" );
196 RETURN_ERROR;
197 }
198 error = dlerror( );
199 if( !error )
200 {
201 printf( "ERROR\tNo error from dlopen for file with too long file name\n" );
202 RETURN_ERROR;
203 }
204 else
205 printf( "SUCCESS\tCould not open file with too long file name: %s\n", error );
206
207 uMode = SetErrorMode( SEM_FAILCRITICALERRORS );
208 library3 = LoadLibraryA( toolongfile );
209 code = GetLastError( );
210 SetErrorMode( uMode );
211 if( library3 )
212 {
213 printf( "ERROR\tFile with too long file name was opened via WINAPI\n" );
214 RETURN_ERROR;
215 }
216 else if( code != ERROR_FILENAME_EXCED_RANGE )
217 {
218 printf( "ERROR\tFile with too long file name was processed via WINAPI: %lu\n", (unsigned long)code );
219 RETURN_ERROR;
220 }
221 else
222 printf( "SUCCESS\tCould not open file with too long file name via WINAPI: %lu\n", (unsigned long)code );
223
224 fd = _open( "testdll2.dll", _O_RDONLY | _O_BINARY );
225 if( fd < 0 )
226 {
227 if( _chdir( "Debug" ) == 0 )
228 {
229 fd = _open( "testdll2.dll", _O_RDONLY | _O_BINARY );
230 if( fd < 0 )
231 _chdir( ".." );
232 }
233 }
234 if( fd < 0 )
235 {
236 if( _chdir( "Release" ) == 0 )
237 {
238 fd = _open( "testdll2.dll", _O_RDONLY | _O_BINARY );
239 if( fd < 0 )
240 _chdir( ".." );
241 }
242 }
243 if( fd < 0 )
244 {
245 printf( "ERROR\tCould not open library2 file: %s\n", strerror( errno ) );
246 RETURN_ERROR;
247 }
248 _close( fd );
249
250 library2 = dlopen( "testdll2.dll", RTLD_GLOBAL );
251 if( !library2 )
252 {
253 error = dlerror( );
254 printf( "ERROR\tCould not open library2 globally: %s\n", error ? error : "" );
255 RETURN_ERROR;
256 }
257 else
258 printf( "SUCCESS\tOpened library2 globally: %p\n", library2 );
259
260 widename[0] = 0xE1; /* wide non-ASCII character mappable to most ANSI codepages */
261 wcscpy( widename+1, L"testdll2.dll" );
262 if( !CopyFileW( L"testdll2.dll", widename, FALSE ))
263 {
264 printf( "ERROR\tCould not copy file testdll2.dll: %lu\n", (unsigned long)GetLastError( ) );
265 RETURN_ERROR;
266 }
267 else
268 printf( "SUCCESS\tCopied testdll2.dll to wide name %ls\n", widename );
269
270 ret = WideCharToMultiByte( CP_ACP, 0, widename, -1, bytename, sizeof( bytename ), NULL, NULL );
271 /* if we cannot convert widename to current codepage (used by _open() function), skip this test */
272 if( ret > 0 )
273 {
274 bytename[ret] = 0;
275
276 fd = _wopen( widename, _O_RDONLY | _O_BINARY );
277 if( fd < 0 )
278 {
279 printf( "ERROR\tCould not open copied wide library2 file %ls: %s\n", widename, strerror( errno ) );
280 DeleteFileW( widename );
281 RETURN_ERROR;
282 }
283 _close( fd );
284
285 fd = _open( bytename, _O_RDONLY | _O_BINARY );
286 if( fd < 0 )
287 {
288 printf( "ERROR\tCould not open copied wide library2 file %s: %s\n", bytename, strerror( errno ) );
289 DeleteFileW( widename );
290 RETURN_ERROR;
291 }
292 _close( fd );
293
294 dlclose( library2 );
295 library2 = dlopen( bytename, RTLD_GLOBAL );
296 if( !library2 )
297 {
298 error = dlerror( );
299 printf( "ERROR\tCould not open copied wide library2 file %s globally: %s\n", bytename, error ? error : "" );
300 DeleteFileW( widename );
301 RETURN_ERROR;
302 }
303 else
304 printf( "SUCCESS\tOpened copied wide library2 file %s globally: %p\n", bytename, library2 );
305
306 dlclose( library2 );
307 DeleteFileW( widename );
308
309 library2 = dlopen( "testdll2.dll", RTLD_GLOBAL );
310 if( !library2 )
311 {
312 error = dlerror( );
313 printf( "ERROR\tCould not open library2 globally: %s\n", error ? error : "" );
314 RETURN_ERROR;
315 }
316 else
317 printf( "SUCCESS\tOpened library2 globally: %p\n", library2 );
318 }
319
320 library = dlopen( "testdll.dll", RTLD_GLOBAL );
321 if( !library )
322 {
323 error = dlerror( );
324 printf( "ERROR\tCould not open library globally: %s\n", error ? error : "" );
325 RETURN_ERROR;
326 }
327 else
328 printf( "SUCCESS\tOpened library globally: %p\n", library );
329
330 global = dlopen( 0, RTLD_GLOBAL );
331 if( !global )
332 {
333 error = dlerror( );
334 printf( "ERROR\tCould not open global handle: %s\n", error ? error : "" );
335 CLOSE_LIB;
336 RETURN_ERROR;
337 }
338 else
339 printf( "SUCCESS\tGot global handle: %p\n", global );
340
341 *(void **) (&fwrite_local) = dlsym( global, "fwrite" );
342 if (!fwrite_local)
343 {
344 error = dlerror();
345 printf("ERROR\tCould not get symbol from global handle: %s\n",
346 error ? error : "");
347 CLOSE_LIB;
348 CLOSE_GLOBAL;
349 RETURN_ERROR;
350 }
351 else
352 printf( "SUCCESS\tGot symbol from global handle: %p\n", *(void **) (&fwrite_local) );
353 {
354 const char *hello_world = "Hello world from local fwrite!\n";
355 fwrite_local( hello_world, sizeof( char ), strlen( hello_world ), stderr );
356 fflush( stderr );
357 }
358
359 *(void **) (&fputs_default) = dlsym( RTLD_DEFAULT, "fputs" );
360 if (!fputs_default)
361 {
362 error = dlerror();
363 printf("ERROR\tCould not get symbol from default handle: %s\n",
364 error ? error : "");
365 CLOSE_LIB;
366 CLOSE_GLOBAL;
367 RETURN_ERROR;
368 }
369 else
370 printf( "SUCCESS\tGot symbol from default handle: %p\n", *(void **) (&fputs_default) );
371 {
372 const char *hello_world_fputs = "Hello world from default fputs!\n";
373 fputs_default( hello_world_fputs, stderr );
374 fflush( stderr );
375 }
376
377 *(void **) (&function) = dlsym( library, "function" );
378 if( !function )
379 {
380 error = dlerror( );
381 printf( "ERROR\tCould not get symbol from library handle: %s\n",
382 error ? error : "" );
383 CLOSE_LIB;
384 CLOSE_GLOBAL;
385 RETURN_ERROR;
386 }
387 else
388 printf( "SUCCESS\tGot symbol from library handle: %p\n", *(void **) (&function) );
389
390 RUNFUNC;
391
392 *(void **) (&function2_from_library2) = dlsym( library2, "function2" );
393 if( !function2_from_library2 )
394 {
395 error = dlerror( );
396 printf( "ERROR\tCould not get symbol from library2 handle: %s\n",
397 error ? error : "" );
398 CLOSE_LIB;
399 CLOSE_GLOBAL;
400 RETURN_ERROR;
401 }
402 else
403 printf( "SUCCESS\tGot symbol from library2 handle: %p\n", *(void **) (&function2_from_library2) );
404
405 ret = function2_from_library2 ();
406 if( ret != 2 )
407 {
408 CLOSE_LIB;
409 CLOSE_GLOBAL;
410 RETURN_ERROR;
411 }
412
413 *(void **) (&nonexistentfunction) = dlsym( library, "nonexistentfunction" );
414 if( nonexistentfunction )
415 {
416 error = dlerror( );
417 printf( "ERROR\tGot nonexistent symbol from library handle: %p\n", *(void **) (&nonexistentfunction) );
418 CLOSE_LIB;
419 CLOSE_GLOBAL;
420 RETURN_ERROR;
421 }
422 error = dlerror( );
423 if( !error )
424 {
425 printf( "ERROR\tNo error from dlsym for nonexistent symbol\n" );
426 RETURN_ERROR;
427 }
428 else
429 printf( "SUCCESS\tCould not get nonexistent symbol from library handle: %s\n", error );
430
431 *(void **) (&function) = dlsym( global, "function" );
432 if( !function )
433 {
434 error = dlerror( );
435 printf( "ERROR\tCould not get symbol from global handle: %s\n",
436 error ? error : "" );
437 CLOSE_LIB;
438 CLOSE_GLOBAL;
439 RETURN_ERROR;
440 }
441 else
442 printf( "SUCCESS\tGot symbol from global handle: %p\n", *(void **) (&function) );
443
444 RUNFUNC;
445
446 *(void **) (&nonexistentfunction) = dlsym( global, "nonexistentfunction" );
447 if( nonexistentfunction )
448 {
449 error = dlerror( );
450 printf( "ERROR\tGot nonexistent symbol from global handle: %p\n", *(void **) (&nonexistentfunction) );
451 CLOSE_LIB;
452 CLOSE_GLOBAL;
453 RETURN_ERROR;
454 }
455 error = dlerror( );
456 if( !error )
457 {
458 printf( "ERROR\tNo error from dlsym for nonexistent symbol\n" );
459 RETURN_ERROR;
460 }
461 else
462 printf( "SUCCESS\tCould not get nonexistent symbol from global handle: %s\n", error );
463
464 ret = dlclose( library );
465 if( ret )
466 {
467 error = dlerror( );
468 printf( "ERROR\tCould not close library: %s\n", error ? error : "" );
469 RETURN_ERROR;
470 }
471 else
472 printf( "SUCCESS\tClosed library.\n" );
473
474 ret = dlclose( library2 );
475 if( ret )
476 {
477 error = dlerror( );
478 printf( "ERROR\tCould not close library2: %s\n", error ? error : "" );
479 RETURN_ERROR;
480 }
481 else
482 printf( "SUCCESS\tClosed library2.\n" );
483
484 library = dlopen( "testdll.dll", RTLD_LOCAL );
485 if( !library )
486 {
487 error = dlerror( );
488 printf( "ERROR\tCould not open library locally: %s\n", error ? error : "" );
489 CLOSE_LIB;
490 CLOSE_GLOBAL;
491 RETURN_ERROR;
492 }
493 else
494 printf( "SUCCESS\tOpened library locally: %p\n", library );
495
496 *(void **) (&function) = dlsym( library, "function" );
497 if( !function )
498 {
499 error = dlerror( );
500 printf( "ERROR\tCould not get symbol from library handle: %s\n",
501 error ? error : "" );
502 CLOSE_LIB;
503 CLOSE_GLOBAL;
504 RETURN_ERROR;
505 }
506 else
507 printf( "SUCCESS\tGot symbol from library handle: %p\n", *(void **) (&function) );
508
509 RUNFUNC;
510
511 *(void **) (&nonexistentfunction) = dlsym( library, "nonexistentfunction" );
512 if( nonexistentfunction )
513 {
514 error = dlerror( );
515 printf( "ERROR\tGot nonexistent symbol from library handle: %p\n", *(void **) (&nonexistentfunction) );
516 CLOSE_LIB;
517 CLOSE_GLOBAL;
518 RETURN_ERROR;
519 }
520 error = dlerror( );
521 if( !error )
522 {
523 printf( "ERROR\tNo error from dlsym for nonexistent symbol\n" );
524 RETURN_ERROR;
525 }
526 else
527 printf( "SUCCESS\tCould not get nonexistent symbol from library handle: %s\n", error );
528
529 *(void **) (&function) = dlsym( global, "function" );
530 if( function )
531 {
532 error = dlerror( );
533 printf( "ERROR\tGot local symbol from global handle: %s @ %p\n",
534 error ? error : "", *(void **) (&function) );
535 CLOSE_LIB;
536 CLOSE_GLOBAL;
537 RETURN_ERROR;
538 }
539 else
540 printf( "SUCCESS\tDid not get local symbol from global handle.\n" );
541
542 *(void **) (&nonexistentfunction) = dlsym( global, "nonexistentfunction" );
543 if( nonexistentfunction )
544 {
545 error = dlerror( );
546 printf( "ERROR\tGot nonexistent local symbol from global handle: %p\n", *(void **) (&nonexistentfunction) );
547 CLOSE_LIB;
548 CLOSE_GLOBAL;
549 RETURN_ERROR;
550 }
551 error = dlerror( );
552 if( !error )
553 {
554 printf( "ERROR\tNo error from dlsym for nonexistent symbol\n" );
555 RETURN_ERROR;
556 }
557 else
558 printf( "SUCCESS\tDid not get nonexistent local symbol from global handle: %s\n", error );
559
560 library = dlopen( "testdll.dll", RTLD_GLOBAL );
561 if( !library )
562 {
563 error = dlerror( );
564 printf( "ERROR\tCould not open library globally without closing it first: %s\n", error ? error : "" );
565 CLOSE_LIB;
566 CLOSE_GLOBAL;
567 RETURN_ERROR;
568 }
569 else
570 printf( "SUCCESS\tOpened library globally without closing it first: %p\n", library );
571
572 *(void **) (&function) = dlsym( global, "function" );
573 if( !function )
574 {
575 error = dlerror( );
576 printf( "ERROR\tCould not get symbol from global handle: %s\n",
577 error ? error : "" );
578 CLOSE_LIB;
579 CLOSE_GLOBAL;
580 RETURN_ERROR;
581 }
582 else
583 printf( "SUCCESS\tGot symbol from global handle: %p\n", *(void **) (&function) );
584
585 RUNFUNC;
586
587 *(void **) (&nonexistentfunction) = dlsym( global, "nonexistentfunction" );
588 if( nonexistentfunction )
589 {
590 error = dlerror( );
591 printf( "ERROR\tGot nonexistent symbol from global handle: %p\n", *(void **) (&nonexistentfunction) );
592 CLOSE_LIB;
593 CLOSE_GLOBAL;
594 RETURN_ERROR;
595 }
596 error = dlerror( );
597 if( !error )
598 {
599 printf( "ERROR\tNo error from dlsym for nonexistent symbol\n" );
600 RETURN_ERROR;
601 }
602 else
603 {
604 printf( "SUCCESS\tCould not get nonexistent symbol from global handle: %s\n", error );
605
606 /* Test that the second call to dlerror() returns null as in the specs
607 See https://github.com/dlfcn-win32/dlfcn-win32/issues/34 */
608 error = dlerror( );
609 if( error == NULL )
610 {
611 printf( "SUCCESS\tSecond consecutive call to dlerror returned NULL\n");
612 }
613 else
614 {
615 printf( "ERROR\tSecond consecutive call to dlerror returned a non-NULL pointer: %p\n", error );
616 CLOSE_LIB;
617 CLOSE_GLOBAL;
618 RETURN_ERROR;
619 }
620 }
621
622 *(void **) (&function) = dlsym( global, "fwrite" );
623 if (!function)
624 {
625 error = dlerror();
626 printf("ERROR\tCould not get symbol from global handle: %s\n",
627 error ? error : "");
628 CLOSE_LIB;
629 CLOSE_GLOBAL;
630 RETURN_ERROR;
631 }
632 else
633 printf( "SUCCESS\tGot symbol from global handle: %p\n", *(void **) (&function) );
634
635
636 uMode = SetErrorMode( SEM_FAILCRITICALERRORS );
637 library3 = LoadLibraryA("testdll3.dll");
638 SetErrorMode( uMode );
639 if (!library3)
640 {
641 printf( "ERROR\tCould not open library3 via WINAPI\n" );
642 RETURN_ERROR;
643 }
644 else
645 printf( "SUCCESS\tOpened library3 via WINAPI: %p\n", (void *)library3 );
646
647 ret = dlclose( library );
648 if( ret )
649 {
650 error = dlerror( );
651 printf( "ERROR\tCould not close library: %s\n", error ? error : "" );
652 CLOSE_GLOBAL;
653 RETURN_ERROR;
654 }
655 else
656 printf( "SUCCESS\tClosed library.\n" );
657
658 *(void **) (&function) = dlsym( global, "function3" );
659 if (!function)
660 {
661 error = dlerror();
662 printf("ERROR\tCould not get symbol from global handle: %s\n",
663 error ? error : "");
664 CLOSE_LIB;
665 CLOSE_GLOBAL;
666 RETURN_ERROR;
667 }
668 else
669 printf( "SUCCESS\tGot symbol from global handle: %p\n", *(void **) (&function) );
670
671 RUNFUNC;
672
673 ret = dlclose( global );
674 if( ret )
675 {
676 error = dlerror( );
677 printf( "ERROR\tCould not close global handle: %s\n", error ? error : "" );
678 RETURN_ERROR;
679 }
680 else
681 printf( "SUCCESS\tClosed global handle.\n" );
682
683#ifdef _DEBUG
684 _CrtDumpMemoryLeaks();
685#endif
686 return 0;
687}
diff --git a/tests/testdll.c b/tests/testdll.c
new file mode 100644
index 0000000..5bb0f43
--- /dev/null
+++ b/tests/testdll.c
@@ -0,0 +1,47 @@
1/*
2 * dlfcn-win32
3 * Copyright (c) 2007 Ramiro Polla
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 * THE SOFTWARE.
22 */
23
24#ifdef _DEBUG
25#define _CRTDBG_MAP_ALLOC
26#include <stdlib.h>
27#include <crtdbg.h>
28#endif
29#include <stdio.h>
30
31#if defined(_WIN32)
32#define EXPORT __declspec(dllexport)
33#else
34#define EXPORT
35#endif
36
37EXPORT int function2( void )
38{
39 printf( "Hello, world! from original library\n" );
40 return 0;
41}
42
43EXPORT int function( void )
44{
45 printf( "Hello, world!\n" );
46 return 0;
47}
diff --git a/tests/testdll2.c b/tests/testdll2.c
new file mode 100644
index 0000000..1560738
--- /dev/null
+++ b/tests/testdll2.c
@@ -0,0 +1,59 @@
1/*
2 * dlfcn-win32
3 * Copyright (c) 2007 Ramiro Polla
4 * Copyright (c) 2019 Pali Rohár <pali.rohar@gmail.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#ifdef _DEBUG
26#define _CRTDBG_MAP_ALLOC
27#include <stdlib.h>
28#include <crtdbg.h>
29#endif
30#include <stdio.h>
31
32#include "dlfcn.h"
33
34#if defined(_WIN32)
35#define EXPORT __declspec(dllexport)
36#else
37#define EXPORT
38#endif
39
40EXPORT int function2( void )
41{
42 char *error;
43 int (*function2_orig)(void);
44 printf( "Hello, world! from wrapper library\n" );
45 *(void **) (&function2_orig) = dlsym( RTLD_NEXT, "function2" );
46 if (!function2_orig)
47 {
48 error = dlerror( );
49 printf( "ERROR\tCould not get symbol from RTLD_NEXT handle: %s\n",
50 error ? error : "" );
51 return 1;
52 }
53 if (function2_orig() != 0)
54 {
55 printf( "ERROR\tOriginal function from RTLD_NEXT handle did not return correct value\n" );
56 return 1;
57 }
58 return 2;
59}
diff --git a/tests/testdll3.c b/tests/testdll3.c
new file mode 100644
index 0000000..b6f4f5b
--- /dev/null
+++ b/tests/testdll3.c
@@ -0,0 +1,42 @@
1/*
2 * dlfcn-win32
3 * Copyright (c) 2007 Ramiro Polla
4 * Copyright (c) 2019 Pali Rohár <pali.rohar@gmail.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#ifdef _DEBUG
26#define _CRTDBG_MAP_ALLOC
27#include <stdlib.h>
28#include <crtdbg.h>
29#endif
30#include <stdio.h>
31
32#if defined(_WIN32)
33#define EXPORT __declspec(dllexport)
34#else
35#define EXPORT
36#endif
37
38EXPORT int function3( void )
39{
40 printf( "Hello, world!\n" );
41 return 0;
42}