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
30int __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