1 //
2 // Copyright(C) 1993-1996 Id Software, Inc.
3 // Copyright(C) 2005-2014 Simon Howard
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // DESCRIPTION:
16 //	WAD I/O functions.
17 //
18 
19 #include "config.h"
20 
21 #ifdef _WIN32
22 
23 #include <stdio.h>
24 
25 #define WIN32_LEAN_AND_MEAN
26 #include <windows.h>
27 
28 #include "i_system.h"
29 #include "m_misc.h"
30 #include "w_file.h"
31 #include "z_zone.h"
32 
33 // This constant doesn't exist in VC6:
34 
35 #ifndef INVALID_SET_FILE_POINTER
36 #define INVALID_SET_FILE_POINTER 0xffffffff
37 #endif
38 
39 typedef struct
40 {
41     wad_file_t wad;
42     HANDLE handle;
43     HANDLE handle_map;
44 } win32_wad_file_t;
45 
46 extern wad_file_class_t win32_wad_file;
47 
MapFile(win32_wad_file_t * wad,const char * filename)48 static void MapFile(win32_wad_file_t *wad, const char *filename)
49 {
50     wad->handle_map = CreateFileMapping(wad->handle,
51                                         NULL,
52                                         PAGE_WRITECOPY,
53                                         0,
54                                         0,
55                                         NULL);
56 
57     if (wad->handle_map == NULL)
58     {
59         fprintf(stderr, "W_Win32_OpenFile: Unable to CreateFileMapping() "
60                         "for %s\n", filename);
61         return;
62     }
63 
64     wad->wad.mapped = MapViewOfFile(wad->handle_map,
65                                     FILE_MAP_COPY,
66                                     0, 0, 0);
67 
68     if (wad->wad.mapped == NULL)
69     {
70         fprintf(stderr, "W_Win32_OpenFile: Unable to MapViewOfFile() for %s\n",
71                         filename);
72     }
73 }
74 
GetFileLength(HANDLE handle)75 unsigned int GetFileLength(HANDLE handle)
76 {
77     DWORD result;
78 
79     result = SetFilePointer(handle, 0, NULL, FILE_END);
80 
81     if (result == INVALID_SET_FILE_POINTER)
82     {
83         I_Error("W_Win32_OpenFile: Failed to read file length");
84     }
85 
86     return result;
87 }
88 
W_Win32_OpenFile(const char * path)89 static wad_file_t *W_Win32_OpenFile(const char *path)
90 {
91     win32_wad_file_t *result;
92     wchar_t wpath[MAX_PATH + 1];
93     HANDLE handle;
94 
95     // Open the file:
96 
97     MultiByteToWideChar(CP_OEMCP, 0,
98                         path, strlen(path) + 1,
99                         wpath, sizeof(wpath));
100 
101     handle = CreateFileW(wpath,
102                          GENERIC_READ,
103                          FILE_SHARE_READ,
104                          NULL,
105                          OPEN_EXISTING,
106                          FILE_ATTRIBUTE_NORMAL,
107                          NULL);
108 
109     if (handle == INVALID_HANDLE_VALUE)
110     {
111         return NULL;
112     }
113 
114     // Create a new win32_wad_file_t to hold the file handle.
115 
116     result = Z_Malloc(sizeof(win32_wad_file_t), PU_STATIC, 0);
117     result->wad.file_class = &win32_wad_file;
118     result->wad.length = GetFileLength(handle);
119     result->wad.path = M_StringDuplicate(path);
120     result->handle = handle;
121 
122     // Try to map the file into memory with mmap:
123 
124     MapFile(result, path);
125 
126     return &result->wad;
127 }
128 
W_Win32_CloseFile(wad_file_t * wad)129 static void W_Win32_CloseFile(wad_file_t *wad)
130 {
131     win32_wad_file_t *win32_wad;
132 
133     win32_wad = (win32_wad_file_t *) wad;
134 
135     // If mapped, unmap it.
136 
137     if (win32_wad->wad.mapped != NULL)
138     {
139         UnmapViewOfFile(win32_wad->wad.mapped);
140     }
141 
142     if (win32_wad->handle_map != NULL)
143     {
144         CloseHandle(win32_wad->handle_map);
145     }
146 
147     // Close the file
148 
149     if (win32_wad->handle != NULL)
150     {
151         CloseHandle(win32_wad->handle);
152     }
153 
154     Z_Free(win32_wad);
155 }
156 
157 // Read data from the specified position in the file into the
158 // provided buffer.  Returns the number of bytes read.
159 
W_Win32_Read(wad_file_t * wad,unsigned int offset,void * buffer,size_t buffer_len)160 size_t W_Win32_Read(wad_file_t *wad, unsigned int offset,
161                    void *buffer, size_t buffer_len)
162 {
163     win32_wad_file_t *win32_wad;
164     DWORD bytes_read;
165     DWORD result;
166 
167     win32_wad = (win32_wad_file_t *) wad;
168 
169     // Jump to the specified position in the file.
170 
171     result = SetFilePointer(win32_wad->handle, offset, NULL, FILE_BEGIN);
172 
173     if (result == INVALID_SET_FILE_POINTER)
174     {
175         I_Error("W_Win32_Read: Failed to set file pointer to %i",
176                 offset);
177     }
178 
179     // Read into the buffer.
180 
181     if (!ReadFile(win32_wad->handle, buffer, buffer_len, &bytes_read, NULL))
182     {
183         I_Error("W_Win32_Read: Error reading from file");
184     }
185 
186     return bytes_read;
187 }
188 
189 
190 wad_file_class_t win32_wad_file =
191 {
192     W_Win32_OpenFile,
193     W_Win32_CloseFile,
194     W_Win32_Read,
195 };
196 
197 
198 #endif /* #ifdef _WIN32 */
199 
200