Reactos
1/*
2 * PROJECT: ReactOS api tests
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Tests for SHLoadIndirectString
5 * COPYRIGHT: Copyright 2020 Mark Jansen (mark.jansen@reactos.org)
6 */
7
8#include <apitest.h>
9#include <shlwapi.h>
10#include "resource.h"
11
12#include <pseh/pseh2.h>
13
14static void execute_test(LPCWSTR DllFile)
15{
16 WCHAR DllBuffer[MAX_PATH + 20];
17 WCHAR Buffer[MAX_PATH * 2] = {0};
18 HRESULT hr;
19 HANDLE hEvent;
20 DWORD dwRet;
21 HMODULE mod;
22
23 hEvent = CreateEventA(NULL, TRUE, FALSE, "Local\\shlwapi_apitest_evt");
24
25 // Show that it is not signaled
26 dwRet = WaitForSingleObject(hEvent, 1);
27 ok_hex(dwRet, WAIT_TIMEOUT);
28
29 // Ensure the module is not loaded yet...
30 mod = GetModuleHandleW(DllFile);
31 if (mod != NULL)
32 {
33 CloseHandle(hEvent);
34 skip("%S loaded, cannot continue\n", DllFile);
35 return;
36 }
37
38 wsprintfW(DllBuffer, L"@%s,-3", DllFile);
39
40 // Load a string from the dll
41 hr = SHLoadIndirectString(DllBuffer, Buffer, _countof(Buffer), NULL);
42 ok_hex(hr, S_OK);
43 if (SUCCEEDED(hr))
44 {
45 // Module should still not be loaded
46 mod = GetModuleHandleW(DllFile);
47 ok_ptr(mod, 0);
48
49 ok_wstr(Buffer, L"Test string one.");
50
51 // DllMain not called..
52 dwRet = WaitForSingleObject(hEvent, 1);
53 ok_hex(dwRet, WAIT_TIMEOUT);
54
55 // Show that calling DllMain will set the event
56 mod = LoadLibraryW(DllFile);
57 ok(mod != NULL, "Failed to load %S\n", DllFile);
58
59 if (mod)
60 {
61 dwRet = WaitForSingleObject(hEvent, 1);
62 ok_hex(dwRet, WAIT_OBJECT_0);
63 FreeLibrary(mod);
64 }
65 }
66 CloseHandle(hEvent);
67}
68
69
70BOOL extract_resource(const WCHAR* Filename, LPCWSTR ResourceName)
71{
72 BOOL Success;
73 DWORD dwWritten, Size;
74 HGLOBAL hGlobal;
75 LPVOID pData;
76 HANDLE Handle;
77 HRSRC hRsrc = FindResourceW(GetModuleHandleW(NULL), ResourceName, (LPCWSTR)10);
78 ok(!!hRsrc, "Unable to find %s\n", wine_dbgstr_w(ResourceName));
79 if (!hRsrc)
80 return FALSE;
81
82 hGlobal = LoadResource(GetModuleHandleW(NULL), hRsrc);
83 Size = SizeofResource(GetModuleHandleW(NULL), hRsrc);
84 pData = LockResource(hGlobal);
85
86 ok(Size && !!pData, "Unable to load %s\n", wine_dbgstr_w(ResourceName));
87 if (!Size || !pData)
88 return FALSE;
89
90 Handle = CreateFileW(Filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
91
92 if (Handle == INVALID_HANDLE_VALUE)
93 {
94 skip("Failed to create temp file %ls, error %lu\n", Filename, GetLastError());
95 return FALSE;
96 }
97 Success = WriteFile(Handle, pData, Size, &dwWritten, NULL);
98 ok(Success == TRUE, "WriteFile failed with %lu\n", GetLastError());
99 ok(dwWritten == Size, "WriteFile wrote %lu bytes instead of %lu\n", dwWritten, Size);
100 CloseHandle(Handle);
101 Success = Success && (dwWritten == Size);
102
103 UnlockResource(pData);
104 return Success;
105}
106
107START_TEST(SHLoadIndirectString)
108{
109 WCHAR workdir[MAX_PATH], dllpath[MAX_PATH];
110 BOOL ret;
111 UINT Length;
112
113 ret = GetTempPathW(_countof(workdir), workdir);
114 ok(ret, "GetTempPathW error: %lu\n", GetLastError());
115
116 Length = GetTempFileNameW(workdir, L"ntdll", 0, dllpath);
117 ok(Length != 0, "GetTempFileNameW failed with %lu\n", GetLastError());
118
119 if (extract_resource(dllpath, (LPCWSTR)101))
120 {
121 _SEH2_TRY
122 {
123 execute_test(dllpath);
124 }
125 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
126 {
127 ok(0, "Ldr didnt handle exception\n");
128 }
129 _SEH2_END;
130 }
131 else
132 {
133 ok(0, "Failed to extract resource\n");
134 }
135
136 DeleteFileW(dllpath);
137}