1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | |
5 | /*============================================================= |
6 | ** |
7 | ** Source: MapViewOfFile.c |
8 | ** |
9 | ** |
10 | ** Purpose: Positive test the MapViewOfFile API. |
11 | ** Call MapViewOfFile with access FILE_MAP_READ. |
12 | ** |
13 | ** |
14 | **============================================================*/ |
15 | #include <palsuite.h> |
16 | #define MAPPINGSIZE 8192 |
17 | |
18 | // This test is special - it doesn't work when the file is created on a tmpfs, like the /tmp folder |
19 | // that is the default location for running PAL tests. The reason is that on such filesystem, |
20 | // it is not possible to create file with FILE_FLAG_NO_BUFFERING. |
21 | // So we explicitly use the /var/tmp that cannot be on tmpfs, since it it persistent over reboots. |
22 | |
23 | #ifndef __ANDROID__ |
24 | #define TEMP_DIRECTORY_PATH "/var/tmp/" |
25 | #else |
26 | // On Android, "/var/tmp/" doesn't exist; temporary files should go to /data/local/tmp/ |
27 | #define TEMP_DIRECTORY_PATH "/data/local/tmp/" |
28 | #endif |
29 | |
30 | int __cdecl main(int argc, char *argv[]) |
31 | { |
32 | |
33 | HANDLE hFile = INVALID_HANDLE_VALUE; |
34 | LPSTR buf = NULL; |
35 | CHAR ch[MAPPINGSIZE]; |
36 | CHAR lpFilePath[MAX_PATH]; |
37 | DWORD dwBytesWritten = 0; |
38 | DWORD dwInitialSize = 0; |
39 | DWORD dwFinalSize = 0; |
40 | BOOL bRetVal = FALSE; |
41 | |
42 | HANDLE hFileMapping = 0; |
43 | LPVOID lpMapViewAddress = NULL; |
44 | |
45 | /* Initialize the PAL environment. |
46 | */ |
47 | if( 0 != PAL_Initialize(argc, argv)) |
48 | { |
49 | return FAIL; |
50 | } |
51 | |
52 | GetTempFileName(TEMP_DIRECTORY_PATH, "tst" , 0, lpFilePath); |
53 | |
54 | /* Create a file handle with CreateFile. |
55 | */ |
56 | hFile = CreateFile( lpFilePath, |
57 | GENERIC_WRITE|GENERIC_READ, |
58 | FILE_SHARE_READ|FILE_SHARE_WRITE, |
59 | NULL, |
60 | OPEN_ALWAYS, |
61 | FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, |
62 | NULL); |
63 | |
64 | if (hFile == INVALID_HANDLE_VALUE) |
65 | { |
66 | Fail( "ERROR: %u :unable to create file \"%s\".\n" , |
67 | GetLastError(), lpFilePath); |
68 | } |
69 | |
70 | /* Get the initial size of file, for latter tests. |
71 | */ |
72 | dwInitialSize = GetFileSize (hFile, NULL); |
73 | if ( INVALID_FILE_SIZE == dwInitialSize ) |
74 | { |
75 | Fail("ERROR:%u: The created file \"%s\" has an invalid " |
76 | "file size.\n" ,GetLastError(),lpFilePath); |
77 | } |
78 | |
79 | /* |
80 | * An application must meet certain requirements when working |
81 | * with files opened with FILE_FLAG_NO_BUFFERING: |
82 | * File access must begin at byte offsets within the file that |
83 | * are integer multiples of the volume's sector size. To determine a |
84 | * volume's sector size, call the GetDiskFreeSpace function. |
85 | * |
86 | * File access must be for numbers of bytes that are integer |
87 | * multiples of the volume's sector size. For example, if the |
88 | * sector size is 512 bytes, an application can request reads and |
89 | * writes of 512, 1024, or 2048 bytes, but not of 335, 981, or 7171 bytes. |
90 | * |
91 | * Buffer addresses for read and write operations must be sector |
92 | * aligned (aligned on addresses in memory that are integer multiples |
93 | * of the volume's sector size). One way to sector align buffers is to use the |
94 | * VirtualAlloc function to allocate the buffers. This function allocates memory |
95 | * that is aligned on addresses that are integer multiples of the system's page size. |
96 | * Because both page and volume sector sizes are powers of 2, memory aligned by multiples |
97 | * of the system's page size is also aligned by multiples of the volume's sector size. |
98 | */ |
99 | buf = (LPSTR)VirtualAlloc( NULL, /* Let the system decide the location. */ |
100 | MAPPINGSIZE / 2, /* One page, the smallest you can request */ |
101 | MEM_COMMIT, /* Reserve and commit in one pass */ |
102 | PAGE_READWRITE ); /* Allow reading and writting. */ |
103 | |
104 | if ( NULL == buf ) |
105 | { |
106 | Trace( "VirtualAlloc failed! LastError=%d\n" , GetLastError() ); |
107 | CloseHandle( hFile ); |
108 | Fail("" ); |
109 | } |
110 | |
111 | |
112 | /* |
113 | * Write to the File handle. |
114 | * The reminder will be padded with zeros. |
115 | */ |
116 | strncpy( buf, |
117 | "thats not a test string....THIS is a test string" , |
118 | MAPPINGSIZE / 2 ); |
119 | |
120 | bRetVal = WriteFile(hFile, |
121 | buf, |
122 | MAPPINGSIZE / 2, |
123 | &dwBytesWritten, |
124 | NULL); |
125 | |
126 | if ( FALSE == bRetVal ) |
127 | { |
128 | Trace( "ERROR: %u :unable to write to file handle hFile=0x%lx\n" , |
129 | GetLastError(), hFile); |
130 | CloseHandle(hFile); |
131 | VirtualFree( buf, 0, MEM_RELEASE ); |
132 | Fail("" ); |
133 | } |
134 | |
135 | /* Create a unnamed file-mapping object with file handle FileHandle |
136 | * and with PAGE_READWRITE protection. |
137 | */ |
138 | hFileMapping = CreateFileMapping( hFile, |
139 | NULL, /*not inherited*/ |
140 | PAGE_READWRITE, /*read and wite*/ |
141 | 0, /*high-order of object size*/ |
142 | MAPPINGSIZE, /*low-orger of object size*/ |
143 | NULL); /*unnamed object*/ |
144 | |
145 | if( NULL == hFileMapping ) |
146 | { |
147 | Trace("ERROR:%u: Failed to create File Mapping.\n" , GetLastError()); |
148 | CloseHandle(hFile); |
149 | VirtualFree( buf, 0, MEM_RELEASE ); |
150 | Fail("" ); |
151 | } |
152 | |
153 | /* maps a view of a file into the address space of the calling process. |
154 | */ |
155 | lpMapViewAddress = MapViewOfFile( hFileMapping, |
156 | FILE_MAP_READ, /* access code */ |
157 | 0, /*high order offset*/ |
158 | 0, /*low order offset*/ |
159 | MAPPINGSIZE); /* number of bytes for map */ |
160 | |
161 | if( NULL == lpMapViewAddress ) |
162 | { |
163 | Trace( "ERROR:%u: Failed to call MapViewOfFile API to map" |
164 | " a view of file!\n" , GetLastError()); |
165 | CloseHandle(hFile); |
166 | CloseHandle(hFileMapping); |
167 | VirtualFree( buf, 0, MEM_RELEASE ); |
168 | Fail("" ); |
169 | } |
170 | |
171 | /* Verify that the size of the file has increased to |
172 | * accomidate the MapView. |
173 | */ |
174 | dwFinalSize = GetFileSize (hFile, NULL); |
175 | if ( (dwFinalSize <= dwInitialSize) && (dwFinalSize != MAPPINGSIZE)) |
176 | { |
177 | |
178 | CloseHandle(hFile); |
179 | CloseHandle(hFileMapping); |
180 | VirtualFree( buf, 0, MEM_RELEASE ); |
181 | UnmapViewOfFile(lpMapViewAddress); |
182 | |
183 | Fail( "ERROR: Size of the file was expected to " |
184 | "increase from \"%d\", to \"%d\".\n " , |
185 | dwInitialSize, |
186 | dwFinalSize); |
187 | } |
188 | |
189 | /* Copy the MapViewOfFile to buffer, so we can |
190 | * compare with value read from file directly. |
191 | */ |
192 | memcpy(ch, (LPCSTR)lpMapViewAddress, MAPPINGSIZE); |
193 | if (memcmp(ch, buf, strlen(buf)) != 0) |
194 | { |
195 | CloseHandle(hFile); |
196 | CloseHandle(hFileMapping); |
197 | UnmapViewOfFile(lpMapViewAddress) ; |
198 | VirtualFree( buf, 0, MEM_RELEASE ); |
199 | |
200 | Fail( "ERROR: MapViewOfFile not equal to file contents " |
201 | "retrieved \"%s\", expected \"%s\".\n" , |
202 | ch, |
203 | buf); |
204 | } |
205 | |
206 | /* Unmap the view of file. |
207 | */ |
208 | if( FALSE == UnmapViewOfFile(lpMapViewAddress) ) |
209 | { |
210 | Trace( "\nFailed to call UnmapViewOfFile API to unmap the " |
211 | "view of a file, error code=%u\n" , GetLastError()); |
212 | CloseHandle(hFile); |
213 | CloseHandle(hFileMapping); |
214 | VirtualFree( buf, 0, MEM_RELEASE ); |
215 | Fail("" ); |
216 | } |
217 | |
218 | /* Close handle to create file. |
219 | */ |
220 | if( FALSE == CloseHandle(hFile) ) |
221 | { |
222 | Trace( "ERROR:%u:Failed to call CloseHandle API to close a file handle." , |
223 | GetLastError()); |
224 | CloseHandle(hFileMapping); |
225 | VirtualFree( buf, 0, MEM_RELEASE ); |
226 | Fail("" ); |
227 | } |
228 | |
229 | if( FALSE == CloseHandle(hFileMapping) ) |
230 | { |
231 | Trace( "ERROR:%u:Failed to call CloseHandle API to close a " |
232 | "filemapping handle." ,GetLastError()); |
233 | VirtualFree( buf, 0, MEM_RELEASE ); |
234 | Fail("" ); |
235 | } |
236 | |
237 | VirtualFree( buf, 0, MEM_RELEASE ); |
238 | |
239 | DeleteFile(lpFilePath); |
240 | |
241 | PAL_Terminate(); |
242 | return PASS; |
243 | } |
244 | |
245 | |