Skip to content

Commit dc8f9b8

Browse files
committed
[SDK_APITEST] Revert "Fix initializing global variables" commit; improve the delayimp_apitest (reactos#8462)
CORE-10935 - This reverts commit 522e9f6. - Implement Mark's suggestion given in PR reactos#7784, reactos#7784 (review) Build three binary versions of the delayimp_apitest, named: delayimp_nohook_apitest, delayimp_globalhook_apitest, and delayimp_runtimehook_apitest, that respectively are: - "nohook": delayload is used, but neither of the hook/failurehook is defined; - "globalhook": delayload is used, and the hooks are assigned at global scope; - "runtimehook": delayload is used, and the hooks are assigned at runtime. - Since the delayimp apitests are self-contained, don't use the separate testlist.c file. It is temporarily unused, until other SDK-specific tests are added in this directory. ## Testing observations: GCC build (tested with KVM x86): binutils doesn't create specification-compliant `IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT` table for delay-loaded imports, and as a result, the tests show: ``` delayimp.cpp:472: Tests skipped: No IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT found, some advanced features might not work! ``` Additionally, both `SymGetOptions` and `MapAndLoad` tests are skipped "until CORE-6504 is fixed", as claimed. _**This doesn't happen for MSVC builds.**_
1 parent 67e331a commit dc8f9b8

3 files changed

Lines changed: 90 additions & 36 deletions

File tree

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,24 @@
11

2-
add_executable(sdk_apitest delayimp.cpp testlist.c)
3-
set_module_type(sdk_apitest win32cui)
4-
target_link_libraries(sdk_apitest ${PSEH_LIB})
5-
add_importlibs(sdk_apitest msvcrt kernel32 ntdll)
6-
add_delay_importlibs(sdk_apitest winmm version dbghelp shlwapi sfc_os imagehlp)
7-
add_rostests_file(TARGET sdk_apitest)
2+
#
3+
# Define three Delay-Import binary test programs:
4+
# - "nohook": delayload is used, but neither of the hook/failurehook is defined;
5+
# - "globalhook": delayload is used, and the hooks are assigned at global scope;
6+
# - "runtimehook": delayload is used, and the hooks are assigned at runtime.
7+
#
8+
list(APPEND DELAYIMP_TEST_NAME nohook globalhook runtimehook)
9+
list(APPEND DELAYIMP_TEST_INDEX 0 1 2)
10+
foreach(testname testid IN ZIP_LISTS DELAYIMP_TEST_NAME DELAYIMP_TEST_INDEX)
11+
add_executable(delayimp_${testname}_apitest delayimp.cpp)
12+
target_compile_definitions(delayimp_${testname}_apitest PRIVATE DELAYIMP_TEST=${testid})
13+
set_module_type(delayimp_${testname}_apitest win32cui)
14+
target_link_libraries(delayimp_${testname}_apitest ${PSEH_LIB})
15+
add_importlibs(delayimp_${testname}_apitest msvcrt kernel32)
16+
add_delay_importlibs(delayimp_${testname}_apitest winmm version dbghelp shlwapi sfc_os imagehlp)
17+
add_rostests_file(TARGET delayimp_${testname}_apitest)
18+
endforeach()
19+
20+
#add_executable(sdk_apitest testlist.c)
21+
#set_module_type(sdk_apitest win32cui)
22+
#target_link_libraries(sdk_apitest ${PSEH_LIB})
23+
#add_importlibs(sdk_apitest msvcrt kernel32 ntdll)
24+
#add_rostests_file(TARGET sdk_apitest)

modules/rostests/apitests/sdk/delayimp.cpp

Lines changed: 67 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
/*
2-
* PROJECT: ReactOS API tests
3-
* LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4-
* PURPOSE: Tests for delayload
5-
* PROGRAMMER: Mark Jansen
2+
* PROJECT: ReactOS API tests
3+
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4+
* PURPOSE: Tests for delayload
5+
* COPYRIGHT: Copyright 2023-2025 Mark Jansen <mark.jansen@reactos.org>
6+
* Copyright 2025 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
67
*/
78

9+
#define STANDALONE
810
#include <apitest.h>
911

10-
#include <apitest.h>
1112
#include <strsafe.h>
1213
#include <delayimp.h>
1314

15+
/* See CMakeLists.txt */
16+
#define DELAYIMP_NOHOOK 0
17+
#define DELAYIMP_GLOBALHOOK 1
18+
#define DELAYIMP_RUNTIMEHOOK 2
19+
1420
/* Some libraries to test against */
1521
#include <mmsystem.h>
1622
#include <winver.h>
@@ -47,7 +53,7 @@ const char* g_ExpectedDll = NULL;
4753
const char* g_ExpectedName = NULL;
4854
char g_Target[100] = { 0 };
4955

50-
char* target(PDelayLoadInfo pdli)
56+
static char* target(PDelayLoadInfo pdli)
5157
{
5258
if (g_Target[0] == '\0' && pdli)
5359
{
@@ -118,9 +124,14 @@ static void CheckDli_imp(unsigned dliNotify, PDelayLoadInfo pdli, BOOL ErrorHand
118124
static void CheckDliDone_imp()
119125
{
120126
if (!g_DliHookExpected) return;
121-
winetest_ok(LAST_DLI == g_DliHookExpected[g_DliHookIndex],
127+
#if (DELAYIMP_TEST == DELAYIMP_NOHOOK)
128+
unsigned lastDli = 0;
129+
#else
130+
unsigned lastDli = LAST_DLI;
131+
#endif
132+
winetest_ok(lastDli == g_DliHookExpected[g_DliHookIndex],
122133
"Expected g_DliHookExpected[g_DliHookIndex] to be %u, was: %u for %s\n",
123-
LAST_DLI, g_DliHookExpected[g_DliHookIndex], target(NULL));
134+
lastDli, g_DliHookExpected[g_DliHookIndex], target(NULL));
124135
g_DliHookExpected = NULL;
125136
g_Target[0] = '\0';
126137
}
@@ -172,7 +183,6 @@ FARPROC WINAPI DliHook(unsigned dliNotify, PDelayLoadInfo pdli)
172183
}
173184
}
174185

175-
176186
if (dliNotify == dliStartProcessing)
177187
{
178188
/* Test loadlib fail */
@@ -200,7 +210,6 @@ FARPROC WINAPI DliHook(unsigned dliNotify, PDelayLoadInfo pdli)
200210
g_VersionDll = LoadLibraryA("version.dll");
201211
return (FARPROC)1;
202212
}
203-
204213
}
205214
else if (dliNotify == dliNotePreGetProcAddress)
206215
{
@@ -220,7 +229,7 @@ FARPROC WINAPI DliHook(unsigned dliNotify, PDelayLoadInfo pdli)
220229
ok(pdli->dlp.szProcName != NULL, "Expected szProcName to be valid, was NULL for %s\n", target(pdli));
221230
else
222231
ok(pdli->dlp.dwOrdinal != 0, "Expected dwOrdinal to be valid, was NULL for %s\n", target(pdli));
223-
switch(dliNotify)
232+
switch (dliNotify)
224233
{
225234
case dliStartProcessing:
226235
ok(pdli->hmodCur == NULL, "Expected hmodCur to be NULL, was: %p for %s\n", pdli->hmodCur, target(pdli));
@@ -284,7 +293,7 @@ FARPROC WINAPI DliFailHook(unsigned dliNotify, PDelayLoadInfo pdli)
284293
ok(pdli->dlp.szProcName != NULL, "Expected szProcName to be valid, was NULL for %s\n", target(pdli));
285294
else
286295
ok(pdli->dlp.dwOrdinal != 0, "Expected dwOrdinal to be valid, was NULL for %s\n", target(pdli));
287-
switch(dliNotify)
296+
switch (dliNotify)
288297
{
289298
case dliFailLoadLib:
290299
ok(pdli->hmodCur == NULL, "Expected hmodCur to be NULL, was: %p for %s\n", pdli->hmodCur, target(pdli));
@@ -365,14 +374,14 @@ LONG ExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo, ULONG ExceptionCode)
365374
return EXCEPTION_EXECUTE_HANDLER;
366375
}
367376

368-
/* We register one hook the 'default' way and one manually,
369-
so that we can check that both fallback and registration work*/
370-
extern "C"
377+
#if (DELAYIMP_TEST == DELAYIMP_GLOBALHOOK)
378+
/* Register static hooks */
379+
ExternC
371380
{
372-
extern PfnDliHook __pfnDliNotifyHook2;
373-
//PfnDliHook __pfnDliFailureHook2 = DliFailHook;
381+
PfnDliHook __pfnDliNotifyHook2 = DliHook;
382+
PfnDliHook __pfnDliFailureHook2 = DliFailHook;
374383
}
375-
384+
#endif
376385

377386
bool g_UsePointers = false;
378387

@@ -399,17 +408,33 @@ unsigned g_imagehlp[] = { dliStartProcessing, dliNotePreLoadLibrary, dliFailLoad
399408

400409

401410
//#define DELAYLOAD_SUPPORTS_UNLOADING
402-
START_TEST(delayimp)
411+
#if (DELAYIMP_TEST == DELAYIMP_NOHOOK)
412+
START_TEST(delayimp_nohook)
413+
#elif (DELAYIMP_TEST == DELAYIMP_GLOBALHOOK)
414+
START_TEST(delayimp_globalhook)
415+
#else // (DELAYIMP_TEST == DELAYIMP_RUNTIMEHOOK)
416+
START_TEST(delayimp_runtimehook)
417+
#endif
403418
{
404-
__pfnDliNotifyHook2 = DliHook;
405-
/* Verify that both scenario's work */
419+
/* We register hooks either the 'default' (static) way or at runtime,
420+
* so that we can check that both fallback and registration work */
421+
#if (DELAYIMP_TEST == DELAYIMP_GLOBALHOOK)
406422
ok(__pfnDliNotifyHook2 == DliHook, "Expected __pfnDliNotifyHook2 to be DliHook(%p), but was: %p\n",
407-
DliHook, __pfnDliNotifyHook2);
423+
DliHook, __pfnDliNotifyHook2);
424+
ok(__pfnDliFailureHook2 == DliFailHook, "Expected __pfnDliFailureHook2 to be DliFailHook(%p), but was: %p\n",
425+
DliFailHook, __pfnDliFailureHook2);
426+
#elif (DELAYIMP_TEST == DELAYIMP_RUNTIMEHOOK)
427+
ok(__pfnDliNotifyHook2 == NULL, "Expected __pfnDliNotifyHook2 to be NULL, but was: %p\n",
428+
__pfnDliNotifyHook2);
408429
ok(__pfnDliFailureHook2 == NULL, "Expected __pfnDliFailureHook2 to be NULL, but was: %p\n",
409-
__pfnDliFailureHook2);
430+
__pfnDliFailureHook2);
410431

432+
/* Register hooks at runtime */
433+
__pfnDliNotifyHook2 = DliHook;
411434
__pfnDliFailureHook2 = DliFailHook;
412-
435+
#else // (DELAYIMP_TEST == DELAYIMP_NOHOOK)
436+
/* No hook is defined */
437+
#endif
413438

414439
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)GetModuleHandle(NULL);
415440

@@ -484,14 +509,25 @@ START_TEST(delayimp)
484509
_SEH2_END;
485510
ok(err == MMSYSERR_INVALHANDLE, "Expected err to be MMSYSERR_INVALHANDLE, was 0x%lx\n", err);
486511
CheckDliDone();
487-
ok(g_BreakFunctionName == false, "Expected the functionname to be changed\n");
512+
#if (DELAYIMP_TEST == DELAYIMP_NOHOOK)
513+
ok(g_BreakFunctionName == true, "Expected the function name to not be changed\n");
514+
#else
515+
ok(g_BreakFunctionName == false, "Expected the function name to be changed\n");
516+
#endif
488517

518+
BOOL ret;
519+
#if (DELAYIMP_TEST == DELAYIMP_NOHOOK)
520+
/* We cannot run this test with hooks disabled. The reason is that in this case,
521+
* sfc_os.dll may not export SfcIsKeyProtected() (e.g. on Windows <= 2003) and
522+
* without the delay-loading hooks, we wouldn't resolve SfcIsKeyProtected(). */
523+
#else
489524
/* Make the LoadLib fail, manually load the library in the Failure Hook,
490-
Respond to the dliNotePreGetProcAddress with an alternate function address */
525+
respond to the dliNotePreGetProcAddress with an alternate function address */
491526
SetExpectedDli(g_sfc_key);
492-
BOOL ret = SfcIsKeyProtected(NULL, NULL, NULL);
527+
ret = SfcIsKeyProtected(NULL, NULL, NULL);
493528
ok(ret == 12345, "Expected ret to be 12345, was %u\n", ret); /* The original function returns FALSE! */
494529
CheckDliDone();
530+
#endif // DELAYIMP_NOHOOK
495531

496532
/* Show that it works with the manually returned dll */
497533
SetExpectedDli(g_sfc_file);
@@ -511,6 +547,9 @@ START_TEST(delayimp)
511547
ok(ret == FALSE, "Expected ret to be FALSE, was %u\n", ret);
512548
CheckDliDone();
513549

550+
#if (DELAYIMP_TEST == DELAYIMP_NOHOOK)
551+
/* This test won't run with hooks disabled */
552+
#else
514553
if (HIWORD(SymGetOptions) == NULL)
515554
{
516555
skip("SymGetOptions until CORE-6504 is fixed\n");
@@ -525,6 +564,7 @@ START_TEST(delayimp)
525564
ok(opt == 123, "Expected opt to be 123, was %lu\n", opt); /* The original function returns ERROR_INVALID_HANDLE */
526565
CheckDliDone();
527566
}
567+
#endif // DELAYIMP_NOHOOK
528568

529569
/* Import by ordinal */
530570
g_ImportByName = false;

modules/rostests/apitests/sdk/testlist.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,7 @@
22
#define STANDALONE
33
#include <apitest.h>
44

5-
extern void func_delayimp(void);
6-
75
const struct test winetest_testlist[] =
86
{
9-
{ "delayimp", func_delayimp },
107
{ 0, 0 }
118
};

0 commit comments

Comments
 (0)