1 /*
2  * Copyright (c) 1988-1997 Sam Leffler
3  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and
6  * its documentation for any purpose is hereby granted without fee, provided
7  * that (i) the above copyright notices and this permission notice appear in
8  * all copies of the software and related documentation, and (ii) the names of
9  * Sam Leffler and Silicon Graphics may not be used in any advertising or
10  * publicity relating to the software without the specific, prior written
11  * permission of Sam Leffler and Silicon Graphics.
12  *
13  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22  * OF THIS SOFTWARE.
23  */
24 
25 /*
26  * TIFF Library Win32-specific Routines.  Adapted from tif_unix.c 4/5/95 by
27  * Scott Wagner (wagner@itek.com), Itek Graphix, Rochester, NY USA
28  */
29 
30 /*
31   CreateFileA/CreateFileW return type 'HANDLE'.
32 
33   thandle_t is declared like
34 
35     DECLARE_HANDLE(thandle_t);
36 
37   in tiffio.h.
38 
39   Windows (from winnt.h) DECLARE_HANDLE logic looks like
40 
41   #ifdef STRICT
42     typedef void *HANDLE;
43   #define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
44   #else
45     typedef PVOID HANDLE;
46   #define DECLARE_HANDLE(name) typedef HANDLE name
47   #endif
48 
49   See http://bugzilla.maptools.org/show_bug.cgi?id=1941 for problems in WIN64
50   builds resulting from this.  Unfortunately, the proposed patch was lost.
51 
52 */
53 
54 #include "tiffiop.h"
55 
56 #include <windows.h>
57 
58 static tmsize_t
_tiffReadProc(thandle_t fd,void * buf,tmsize_t size)59 _tiffReadProc(thandle_t fd, void* buf, tmsize_t size)
60 {
61 	/* tmsize_t is 64bit on 64bit systems, but the WinAPI ReadFile takes
62 	 * 32bit sizes, so we loop through the data in suitable 32bit sized
63 	 * chunks */
64 	uint8* ma;
65 	uint64 mb;
66 	DWORD n;
67 	DWORD o;
68 	tmsize_t p;
69 	ma=(uint8*)buf;
70 	mb=size;
71 	p=0;
72 	while (mb>0)
73 	{
74 		n=0x80000000UL;
75 		if ((uint64)n>mb)
76 			n=(DWORD)mb;
77 		if (!ReadFile(fd,(LPVOID)ma,n,&o,NULL))
78 			return(0);
79 		ma+=o;
80 		mb-=o;
81 		p+=o;
82 		if (o!=n)
83 			break;
84 	}
85 	return(p);
86 }
87 
88 static tmsize_t
_tiffWriteProc(thandle_t fd,void * buf,tmsize_t size)89 _tiffWriteProc(thandle_t fd, void* buf, tmsize_t size)
90 {
91 	/* tmsize_t is 64bit on 64bit systems, but the WinAPI WriteFile takes
92 	 * 32bit sizes, so we loop through the data in suitable 32bit sized
93 	 * chunks */
94 	uint8* ma;
95 	uint64 mb;
96 	DWORD n;
97 	DWORD o;
98 	tmsize_t p;
99 	ma=(uint8*)buf;
100 	mb=size;
101 	p=0;
102 	while (mb>0)
103 	{
104 		n=0x80000000UL;
105 		if ((uint64)n>mb)
106 			n=(DWORD)mb;
107 		if (!WriteFile(fd,(LPVOID)ma,n,&o,NULL))
108 			return(0);
109 		ma+=o;
110 		mb-=o;
111 		p+=o;
112 		if (o!=n)
113 			break;
114 	}
115 	return(p);
116 }
117 
118 static uint64
_tiffSeekProc(thandle_t fd,uint64 off,int whence)119 _tiffSeekProc(thandle_t fd, uint64 off, int whence)
120 {
121 	LARGE_INTEGER offli;
122 	DWORD dwMoveMethod;
123 	offli.QuadPart = off;
124 	switch(whence)
125 	{
126 		case SEEK_SET:
127 			dwMoveMethod = FILE_BEGIN;
128 			break;
129 		case SEEK_CUR:
130 			dwMoveMethod = FILE_CURRENT;
131 			break;
132 		case SEEK_END:
133 			dwMoveMethod = FILE_END;
134 			break;
135 		default:
136 			dwMoveMethod = FILE_BEGIN;
137 			break;
138 	}
139 	offli.LowPart=SetFilePointer(fd,offli.LowPart,&offli.HighPart,dwMoveMethod);
140 	if ((offli.LowPart==INVALID_SET_FILE_POINTER)&&(GetLastError()!=NO_ERROR))
141 		offli.QuadPart=0;
142 	return(offli.QuadPart);
143 }
144 
145 static int
_tiffCloseProc(thandle_t fd)146 _tiffCloseProc(thandle_t fd)
147 {
148 	return (CloseHandle(fd) ? 0 : -1);
149 }
150 
151 static uint64
_tiffSizeProc(thandle_t fd)152 _tiffSizeProc(thandle_t fd)
153 {
154 	ULARGE_INTEGER m;
155 	m.LowPart=GetFileSize(fd,&m.HighPart);
156 	return(m.QuadPart);
157 }
158 
159 static int
_tiffDummyMapProc(thandle_t fd,void ** pbase,toff_t * psize)160 _tiffDummyMapProc(thandle_t fd, void** pbase, toff_t* psize)
161 {
162 	(void) fd;
163 	(void) pbase;
164 	(void) psize;
165 	return (0);
166 }
167 
168 /*
169  * From "Hermann Josef Hill" <lhill@rhein-zeitung.de>:
170  *
171  * Windows uses both a handle and a pointer for file mapping,
172  * but according to the SDK documentation and Richter's book
173  * "Advanced Windows Programming" it is safe to free the handle
174  * after obtaining the file mapping pointer
175  *
176  * This removes a nasty OS dependency and cures a problem
177  * with Visual C++ 5.0
178  */
179 static int
_tiffMapProc(thandle_t fd,void ** pbase,toff_t * psize)180 _tiffMapProc(thandle_t fd, void** pbase, toff_t* psize)
181 {
182 	uint64 size;
183 	tmsize_t sizem;
184 	HANDLE hMapFile;
185 
186 	size = _tiffSizeProc(fd);
187 	sizem = (tmsize_t)size;
188 	if ((uint64)sizem!=size)
189 		return (0);
190 
191 	/* By passing in 0 for the maximum file size, it specifies that we
192 	   create a file mapping object for the full file size. */
193 	hMapFile = CreateFileMapping(fd, NULL, PAGE_READONLY, 0, 0, NULL);
194 	if (hMapFile == NULL)
195 		return (0);
196 	*pbase = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
197 	CloseHandle(hMapFile);
198 	if (*pbase == NULL)
199 		return (0);
200 	*psize = size;
201 	return(1);
202 }
203 
204 static void
_tiffDummyUnmapProc(thandle_t fd,void * base,toff_t size)205 _tiffDummyUnmapProc(thandle_t fd, void* base, toff_t size)
206 {
207 	(void) fd;
208 	(void) base;
209 	(void) size;
210 }
211 
212 static void
_tiffUnmapProc(thandle_t fd,void * base,toff_t size)213 _tiffUnmapProc(thandle_t fd, void* base, toff_t size)
214 {
215 	(void) fd;
216 	(void) size;
217 	UnmapViewOfFile(base);
218 }
219 
220 /*
221  * Open a TIFF file descriptor for read/writing.
222  * Note that TIFFFdOpen and TIFFOpen recognise the character 'u' in the mode
223  * string, which forces the file to be opened unmapped.
224  */
225 TIFF*
TIFFFdOpen(int ifd,const char * name,const char * mode)226 TIFFFdOpen(int ifd, const char* name, const char* mode)
227 {
228 	TIFF* tif;
229 	int fSuppressMap;
230 	int m;
231 	fSuppressMap=0;
232 	for (m=0; mode[m]!=0; m++)
233 	{
234 		if (mode[m]=='u')
235 		{
236 			fSuppressMap=1;
237 			break;
238 		}
239 	}
240 	tif = TIFFClientOpen(name, mode, (thandle_t)ifd, /* FIXME: WIN64 cast to pointer warning */
241 			_tiffReadProc, _tiffWriteProc,
242 			_tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
243 			fSuppressMap ? _tiffDummyMapProc : _tiffMapProc,
244 			fSuppressMap ? _tiffDummyUnmapProc : _tiffUnmapProc);
245 	if (tif)
246 		tif->tif_fd = ifd;
247 	return (tif);
248 }
249 
250 #ifndef _WIN32_WCE
251 
252 /*
253  * Open a TIFF file for read/writing.
254  */
255 TIFF*
TIFFOpen(const char * name,const char * mode)256 TIFFOpen(const char* name, const char* mode)
257 {
258 	static const char module[] = "TIFFOpen";
259 	thandle_t fd;
260 	int m;
261 	DWORD dwMode;
262 	TIFF* tif;
263 
264 	m = _TIFFgetMode(mode, module);
265 
266 	switch(m) {
267 		case O_RDONLY:			dwMode = OPEN_EXISTING; break;
268 		case O_RDWR:			dwMode = OPEN_ALWAYS;   break;
269 		case O_RDWR|O_CREAT:		dwMode = OPEN_ALWAYS;   break;
270 		case O_RDWR|O_TRUNC:		dwMode = CREATE_ALWAYS; break;
271 		case O_RDWR|O_CREAT|O_TRUNC:	dwMode = CREATE_ALWAYS; break;
272 		default:			return ((TIFF*)0);
273 	}
274 
275 	fd = (thandle_t)CreateFileA(name,
276 		(m == O_RDONLY)?GENERIC_READ:(GENERIC_READ | GENERIC_WRITE),
277 		FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode,
278 		(m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL,
279 		NULL);
280 	if (fd == INVALID_HANDLE_VALUE) {
281 		TIFFErrorExt(0, module, "%s: Cannot open", name);
282 		return ((TIFF *)0);
283 	}
284 
285 	tif = TIFFFdOpen((int)fd, name, mode);   /* FIXME: WIN64 cast from pointer to int warning */
286 	if(!tif)
287 		CloseHandle(fd);
288 	return tif;
289 }
290 
291 /*
292  * Open a TIFF file with a Unicode filename, for read/writing.
293  */
294 TIFF*
TIFFOpenW(const wchar_t * name,const char * mode)295 TIFFOpenW(const wchar_t* name, const char* mode)
296 {
297 	static const char module[] = "TIFFOpenW";
298 	thandle_t fd;
299 	int m;
300 	DWORD dwMode;
301 	int mbsize;
302 	char *mbname;
303 	TIFF *tif;
304 
305 	m = _TIFFgetMode(mode, module);
306 
307 	switch(m) {
308 		case O_RDONLY:			dwMode = OPEN_EXISTING; break;
309 		case O_RDWR:			dwMode = OPEN_ALWAYS;   break;
310 		case O_RDWR|O_CREAT:		dwMode = OPEN_ALWAYS;   break;
311 		case O_RDWR|O_TRUNC:		dwMode = CREATE_ALWAYS; break;
312 		case O_RDWR|O_CREAT|O_TRUNC:	dwMode = CREATE_ALWAYS; break;
313 		default:			return ((TIFF*)0);
314 	}
315 
316 	fd = (thandle_t)CreateFileW(name,
317 		(m == O_RDONLY)?GENERIC_READ:(GENERIC_READ|GENERIC_WRITE),
318 		FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode,
319 		(m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL,
320 		NULL);
321 	if (fd == INVALID_HANDLE_VALUE) {
322 		TIFFErrorExt(0, module, "%S: Cannot open", name);
323 		return ((TIFF *)0);
324 	}
325 
326 	mbname = NULL;
327 	mbsize = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL);
328 	if (mbsize > 0) {
329 		mbname = (char *)_TIFFmalloc(mbsize);
330 		if (!mbname) {
331 			TIFFErrorExt(0, module,
332 			"Can't allocate space for filename conversion buffer");
333 			return ((TIFF*)0);
334 		}
335 
336 		WideCharToMultiByte(CP_ACP, 0, name, -1, mbname, mbsize,
337 				    NULL, NULL);
338 	}
339 
340 	tif = TIFFFdOpen((int)fd,    /* FIXME: WIN64 cast from pointer to int warning */
341 			 (mbname != NULL) ? mbname : "<unknown>", mode);
342 	if(!tif)
343 		CloseHandle(fd);
344 
345 	_TIFFfree(mbname);
346 
347 	return tif;
348 }
349 
350 #endif /* ndef _WIN32_WCE */
351 
352 void*
_TIFFmalloc(tmsize_t s)353 _TIFFmalloc(tmsize_t s)
354 {
355         if (s == 0)
356                 return ((void *) NULL);
357 
358 	return (malloc((size_t) s));
359 }
360 
_TIFFcalloc(tmsize_t nmemb,tmsize_t siz)361 void* _TIFFcalloc(tmsize_t nmemb, tmsize_t siz)
362 {
363     if( nmemb == 0 || siz == 0 )
364         return ((void *) NULL);
365 
366     return calloc((size_t) nmemb, (size_t)siz);
367 }
368 
369 void
_TIFFfree(void * p)370 _TIFFfree(void* p)
371 {
372 	free(p);
373 }
374 
375 void*
_TIFFrealloc(void * p,tmsize_t s)376 _TIFFrealloc(void* p, tmsize_t s)
377 {
378 	return (realloc(p, (size_t) s));
379 }
380 
381 void
_TIFFmemset(void * p,int v,tmsize_t c)382 _TIFFmemset(void* p, int v, tmsize_t c)
383 {
384 	memset(p, v, (size_t) c);
385 }
386 
387 void
_TIFFmemcpy(void * d,const void * s,tmsize_t c)388 _TIFFmemcpy(void* d, const void* s, tmsize_t c)
389 {
390 	memcpy(d, s, (size_t) c);
391 }
392 
393 int
_TIFFmemcmp(const void * p1,const void * p2,tmsize_t c)394 _TIFFmemcmp(const void* p1, const void* p2, tmsize_t c)
395 {
396 	return (memcmp(p1, p2, (size_t) c));
397 }
398 
399 #ifndef _WIN32_WCE
400 
401 #if (_MSC_VER < 1500)
402 #  define vsnprintf _vsnprintf
403 #endif
404 
405 static void
Win32WarningHandler(const char * module,const char * fmt,va_list ap)406 Win32WarningHandler(const char* module, const char* fmt, va_list ap)
407 {
408 	if (module != NULL)
409 		fprintf(stderr, "%s: ", module);
410 	fprintf(stderr, "Warning, ");
411 	vfprintf(stderr, fmt, ap);
412 	fprintf(stderr, ".\n");
413 }
414 TIFFErrorHandler _TIFFwarningHandler = Win32WarningHandler;
415 
416 static void
Win32ErrorHandler(const char * module,const char * fmt,va_list ap)417 Win32ErrorHandler(const char* module, const char* fmt, va_list ap)
418 {
419 	if (module != NULL)
420 		fprintf(stderr, "%s: ", module);
421 	vfprintf(stderr, fmt, ap);
422 	fprintf(stderr, ".\n");
423 }
424 TIFFErrorHandler _TIFFerrorHandler = Win32ErrorHandler;
425 
426 #endif /* ndef _WIN32_WCE */
427 
428 /* vim: set ts=8 sts=8 sw=8 noet: */
429 /*
430  * Local Variables:
431  * mode: c
432  * c-basic-offset: 8
433  * fill-column: 78
434  * End:
435  */
436