1 /*
2  * PROJECT:     ReactOS api tests
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     Test for CAtlFileMapping
5  * COPYRIGHT:   Copyright 2019 Mark Jansen (mark.jansen@reactos.org)
6  */
7 
8 #include <atlfile.h>
9 
10 #ifdef HAVE_APITEST
11     #include <apitest.h>
12 #else
13     #include <stdlib.h>
14     #include <stdio.h>
15     #include <stdarg.h>
16     #include <windows.h>
17     int g_tests_executed = 0;
18     int g_tests_failed = 0;
19     int g_tests_skipped = 0;
20     const char *g_file = NULL;
21     int g_line = 0;
22     void set_location(const char *file, int line)
23     {
24         g_file = file;
25         g_line = line;
26     }
27     void ok_func(int value, const char *fmt, ...)
28     {
29         va_list va;
30         va_start(va, fmt);
31         if (!value)
32         {
33             printf("%s (%d): ", g_file, g_line);
34             vprintf(fmt, va);
35             g_tests_failed++;
36         }
37         g_tests_executed++;
38         va_end(va);
39     }
40     void skip_func(const char *fmt, ...)
41     {
42         va_list va;
43         va_start(va, fmt);
44         printf("%s (%d): test skipped: ", g_file, g_line);
45         vprintf(fmt, va);
46         g_tests_skipped++;
47         va_end(va);
48     }
49     #undef ok
50     #define ok(value, ...) do { \
51         set_location(__FILE__, __LINE__); \
52         ok_func(value, __VA_ARGS__); \
53     } while (0)
54     #define ok_(x1,x2) set_location(x1,x2); ok_func
55     #define skip(...) do { \
56         set_location(__FILE__, __LINE__); \
57         skip_func(__VA_ARGS__); \
58     } while (0)
59     #define START_TEST(x)   int main()
60     char *wine_dbgstr_w(const wchar_t *wstr)
61     {
62         static char buf[512];
63         WideCharToMultiByte(CP_ACP, 0, wstr, -1, buf, _countof(buf), NULL, NULL);
64         return buf;
65     }
66 #endif
67 
68 struct TestData
69 {
70     int data[4];
71 };
72 
73 
74 static void test_SharedMem()
75 {
76     CAtlFileMapping<TestData> test1, test2;
77     CAtlFileMappingBase test3;
78     BOOL bAlreadyExisted;
79     HRESULT hr;
80 
81     ok(test1.GetData() == NULL, "Expected NULL, got %p\n", test1.GetData());
82     ok(test3.GetData() == NULL, "Expected NULL, got %p\n", test3.GetData());
83     ok(test1.GetHandle() == NULL, "Expected NULL, got %p\n", test1.GetHandle());
84     ok(test3.GetHandle() == NULL, "Expected NULL, got %p\n", test3.GetHandle());
85     ok(test1.GetMappingSize() == 0, "Expected 0, got %lu\n", test1.GetMappingSize());
86     ok(test3.GetMappingSize() == 0, "Expected 0, got %lu\n", test3.GetMappingSize());
87 
88     test1 = test1;
89     //test1 = test2;  // Asserts on orig.m_pData != NULL, same with CopyFrom
90     //test1 = test3;  // does not compile
91     hr = test1.Unmap();
92     ok(hr == S_OK, "Expected S_OK, got 0x%lx\n", hr);
93 
94     // Asserts on name == NULL
95     hr = test1.OpenMapping(_T("TEST_MAPPING"), 123, 0, FILE_MAP_ALL_ACCESS);
96     ok(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), "Expected HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), got 0x%lx\n", hr);
97     ok(test1.GetData() == NULL, "Expected NULL, got %p\n", test1.GetData());
98     ok(test1.GetHandle() == NULL, "Expected NULL, got %p\n", test1.GetHandle());
99     ok(test1.GetMappingSize() == 123, "Expected 123, got %lu\n", test1.GetMappingSize());
100 
101     hr = test1.Unmap();
102     ok(hr == S_OK, "Expected S_OK, got 0x%lx\n", hr);
103     ok(test1.GetData() == NULL, "Expected NULL, got %p\n", test1.GetData());
104     ok(test1.GetHandle() == NULL, "Expected NULL, got %p\n", test1.GetHandle());
105     ok(test1.GetMappingSize() == 123, "Expected 123, got %lu\n", test1.GetMappingSize());
106 
107     bAlreadyExisted = 123;
108     hr = test1.MapSharedMem(sizeof(TestData), _T("TEST_MAPPING"), &bAlreadyExisted, (LPSECURITY_ATTRIBUTES)0, PAGE_READWRITE, FILE_MAP_ALL_ACCESS);
109     ok(hr == S_OK, "Expected S_OK, got 0x%lx\n", hr);
110     ok(test1.GetData() != NULL, "Expected ptr, got %p\n", test1.GetData());
111     ok(test1.GetHandle() != NULL, "Expected handle, got %p\n", test1.GetHandle());
112     ok(test1.GetMappingSize() == sizeof(TestData), "Expected sizeof(TestData), got %lu\n", test1.GetMappingSize());
113     ok(bAlreadyExisted == FALSE, "Expected FALSE, got %u\n", bAlreadyExisted);
114 
115     if (test1.GetData())
116     {
117         memset(test1.GetData(), 0x35, sizeof(TestData));
118     }
119 
120     hr = test2.CopyFrom(test1);
121     ok(hr == S_OK, "Expected S_OK, got 0x%lx\n", hr);
122     ok(test2.GetData() != NULL, "Expected ptr, got %p\n", test2.GetData());
123     ok(test2.GetHandle() != NULL, "Expected handle, got %p\n", test2.GetHandle());
124     ok(test2.GetMappingSize() == sizeof(TestData), "Expected sizeof(TestData), got %lu\n", test2.GetMappingSize());
125 
126     // test1 is not closed:
127     ok(test1.GetData() != NULL, "Expected ptr, got %p\n", test1.GetData());
128     ok(test1.GetHandle() != NULL, "Expected handle, got %p\n", test1.GetHandle());
129     ok(test1.GetMappingSize() == sizeof(TestData), "Expected sizeof(TestData), got %lu\n", test1.GetMappingSize());
130 
131     // test2 does not equal test1
132     ok(test1.GetData() != test2.GetData(), "Expected different ptrs\n");
133     ok(test1.GetHandle() != test2.GetHandle(), "Expected different handles\n");
134 
135     TestData* t1 = test1;
136     TestData* t2 = test2;
137     if (t1 && t2)
138     {
139         ok(t1->data[0] == 0x35353535, "Expected 0x35353535, got 0x%x\n", t1->data[0]);
140         ok(t2->data[0] == 0x35353535, "Expected 0x35353535, got 0x%x\n", t2->data[0]);
141 
142         t1->data[0] = 0xbeefbeef;
143         ok(t1->data[0] == (int)0xbeefbeef, "Expected 0xbeefbeef, got 0x%x\n", t1->data[0]);
144         ok(t2->data[0] == (int)0xbeefbeef, "Expected 0xbeefbeef, got 0x%x\n", t2->data[0]);
145     }
146 
147     hr = test3.OpenMapping(_T("TEST_MAPPING"), sizeof(TestData), offsetof(TestData, data[1]));
148     ok(hr == HRESULT_FROM_WIN32(ERROR_MAPPED_ALIGNMENT), "Expected HRESULT_FROM_WIN32(ERROR_MAPPED_ALIGNMENT), got 0x%lx\n", hr);
149     ok(test3.GetData() == NULL, "Expected NULL, got %p\n", test3.GetData());
150     ok(test3.GetHandle() == NULL, "Expected NULL, got %p\n", test3.GetHandle());
151     ok(test3.GetMappingSize() == sizeof(TestData), "Expected sizeof(TestData), got %lu\n", test3.GetMappingSize());
152 
153     hr = test2.Unmap();
154     ok(hr == S_OK, "Expected S_OK, got 0x%lx\n", hr);
155     ok(test2.GetData() == NULL, "Expected NULL, got %p\n", test2.GetData());
156     ok(test2.GetHandle() == NULL, "Expected NULL, got %p\n", test2.GetHandle());
157     ok(test2.GetMappingSize() == sizeof(TestData), "Expected sizeof(TestData), got %lu\n", test2.GetMappingSize());
158 
159     bAlreadyExisted = 123;
160     // Wrong access flag
161     hr = test2.MapSharedMem(sizeof(TestData), _T("TEST_MAPPING"), &bAlreadyExisted, (LPSECURITY_ATTRIBUTES)0, PAGE_EXECUTE_READ, FILE_MAP_ALL_ACCESS);
162     ok(hr == E_ACCESSDENIED, "Expected E_ACCESSDENIED, got 0x%lx\n", hr);
163     ok(test2.GetData() == NULL, "Expected NULL, got %p\n", test2.GetData());
164     ok(test2.GetHandle() == NULL, "Expected NULL, got %p\n", test2.GetHandle());
165     ok(test2.GetMappingSize() == sizeof(TestData), "Expected sizeof(TestData), got %lu\n", test2.GetMappingSize());
166     ok(bAlreadyExisted == TRUE, "Expected TRUE, got %u\n", bAlreadyExisted);
167 
168     bAlreadyExisted = 123;
169     hr = test2.MapSharedMem(sizeof(TestData), _T("TEST_MAPPING"), &bAlreadyExisted, (LPSECURITY_ATTRIBUTES)0, PAGE_READWRITE, FILE_MAP_ALL_ACCESS);
170     ok(hr == S_OK, "Expected S_OK, got 0x%lx\n", hr);
171     ok(test2.GetData() != NULL, "Expected ptr, got %p\n", test2.GetData());
172     ok(test2.GetHandle() != NULL, "Expected handle, got %p\n", test2.GetHandle());
173     ok(test2.GetMappingSize() == sizeof(TestData), "Expected sizeof(TestData), got %lu\n", test2.GetMappingSize());
174     ok(bAlreadyExisted == TRUE, "Expected TRUE, got %u\n", bAlreadyExisted);
175 
176     // test2 does not equal test1
177     ok(test1.GetData() != test2.GetData(), "Expected different ptrs\n");
178     ok(test1.GetHandle() != test2.GetHandle(), "Expected different handles\n");
179 
180     t2 = test2;
181     if (t1 && t2)
182     {
183         ok(t1->data[0] == (int)0xbeefbeef, "Expected 0xbeefbeef, got 0x%x\n", t1->data[0]);
184         ok(t2->data[0] == (int)0xbeefbeef, "Expected 0xbeefbeef, got 0x%x\n", t2->data[0]);
185 
186         t1->data[0] = 0xdeaddead;
187         ok(t1->data[0] == (int)0xdeaddead, "Expected 0xdeaddead, got 0x%x\n", t1->data[0]);
188         ok(t2->data[0] == (int)0xdeaddead, "Expected 0xdeaddead, got 0x%x\n", t2->data[0]);
189     }
190 }
191 
192 static void test_FileMapping()
193 {
194     WCHAR Buf[MAX_PATH] = {0};
195     ULARGE_INTEGER FileSize;
196 
197     GetModuleFileNameW(NULL, Buf, _countof(Buf));
198 
199     CAtlFileMapping<IMAGE_DOS_HEADER> test1, test2;
200     HRESULT hr;
201 
202     {
203         CHandle hFile(CreateFileW(Buf, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL));
204         ok(hFile != INVALID_HANDLE_VALUE, "Could not open %S, aborting test\n", Buf);
205         if (hFile == INVALID_HANDLE_VALUE)
206             return;
207 
208         FileSize.LowPart = GetFileSize(hFile, &FileSize.HighPart);
209 
210         hr = test1.MapFile(hFile, 0, 0, PAGE_READONLY, FILE_MAP_READ);
211         ok(hr == S_OK, "Expected S_OK, got 0x%lx\n", hr);
212         ok(test1.GetData() != NULL, "Expected ptr, got %p\n", test1.GetData());
213         ok(test1.GetHandle() != NULL, "Expected handle, got %p\n", test1.GetHandle());
214         ok(test1.GetMappingSize() == FileSize.LowPart, "Expected %lu, got %lu\n", FileSize.LowPart, test1.GetMappingSize());
215 
216         hr = test2.MapFile(hFile, 0, 0x10000, PAGE_READONLY, FILE_MAP_READ);
217         ok(hr == S_OK, "Expected S_OK, got 0x%lx\n", hr);
218         ok(test2.GetData() != NULL, "Expected ptr, got %p\n", test2.GetData());
219         ok(test2.GetHandle() != NULL, "Expected handle, got %p\n", test2.GetHandle());
220         // Offset is subtracted
221         ok(test2.GetMappingSize() == FileSize.LowPart - 0x10000, "Expected %lu, got %lu\n", FileSize.LowPart-0x10000, test2.GetMappingSize());
222 
223         hr = test1.Unmap();
224         ok(hr == S_OK, "Expected S_OK, got 0x%lx\n", hr);
225         ok(test1.GetData() == NULL, "Expected NULL, got %p\n", test1.GetData());
226         ok(test1.GetHandle() == NULL, "Expected NULL, got %p\n", test1.GetHandle());
227         ok(test1.GetMappingSize() == FileSize.LowPart, "Expected %lu, got %lu\n", FileSize.LowPart, test1.GetMappingSize());
228 
229         hr = test1.MapFile(hFile, 0x1000);
230         ok(hr == S_OK, "Expected S_OK, got 0x%lx\n", hr);
231         ok(test1.GetData() != NULL, "Expected ptr, got %p\n", test1.GetData());
232         ok(test1.GetHandle() != NULL, "Expected handle, got %p\n", test1.GetHandle());
233         ok(test1.GetMappingSize() == 0x1000, "Expected 0x1000, got %lu\n", test1.GetMappingSize());
234     }
235 
236     // We can still access it after the file is closed
237     PIMAGE_DOS_HEADER dos = test1;
238     if (dos)
239     {
240         ok(dos->e_magic == IMAGE_DOS_SIGNATURE, "Expected IMAGE_DOS_SIGNATURE, got 0x%x\n", dos->e_magic);
241     }
242 }
243 
244 
245 START_TEST(CAtlFileMapping)
246 {
247     test_SharedMem();
248     test_FileMapping();
249 
250 #ifndef HAVE_APITEST
251     printf("CAtlFile: %i tests executed (0 marked as todo, %i failures), %i skipped.\n", g_tests_executed, g_tests_failed, g_tests_skipped);
252     return g_tests_failed;
253 #endif
254 }
255