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