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