1 /* $Id: tif_win32.c,v 1.18 2006/02/07 11:03:29 dron 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 #include "tiffiop.h"
32 
33 static tsize_t
34 _tiffReadProc(thandle_t fd, tdata_t buf, tsize_t size)
35 {
36 	DWORD dwSizeRead;
37 	if (!ReadFile(fd, buf, size, &dwSizeRead, NULL))
38 		return(0);
39 	return ((tsize_t) dwSizeRead);
_tiffReadProc(thandle_t fd,tdata_t buf,tsize_t size)40 }
41 
42 static tsize_t
43 _tiffWriteProc(thandle_t fd, tdata_t buf, tsize_t size)
44 {
45 	DWORD dwSizeWritten;
46 	if (!WriteFile(fd, buf, size, &dwSizeWritten, NULL))
47 		return(0);
48 	return ((tsize_t) dwSizeWritten);
49 }
50 
51 static toff_t
_tiffSeekProc(thandle_t fd,toff_t off,int whence)52 _tiffSeekProc(thandle_t fd, toff_t off, int whence)
53 {
54 	DWORD dwMoveMethod, dwMoveHigh;
55 
56         /* we use this as a special code, so avoid accepting it */
57         if( off == 0xFFFFFFFF )
58             return 0xFFFFFFFF;
59 
60 	switch(whence)
61 	{
62 	case SEEK_SET:
63 		dwMoveMethod = FILE_BEGIN;
64 		break;
65 	case SEEK_CUR:
66 		dwMoveMethod = FILE_CURRENT;
67 		break;
68 	case SEEK_END:
69 		dwMoveMethod = FILE_END;
70 		break;
71 	default:
72 		dwMoveMethod = FILE_BEGIN;
73 		break;
74 	}
75         dwMoveHigh = 0;
76 	return ((toff_t)SetFilePointer(fd, (LONG) off, (PLONG)&dwMoveHigh,
77                                        dwMoveMethod));
78 }
_tiffUnmapProc(thandle_t fd,tdata_t base,toff_t size)79 
80 static int
81 _tiffCloseProc(thandle_t fd)
82 {
83 	return (CloseHandle(fd) ? 0 : -1);
84 }
85 
86 static toff_t
TIFFFdOpen(int fd,const char * name,const char * mode)87 _tiffSizeProc(thandle_t fd)
88 {
89 	return ((toff_t)GetFileSize(fd, NULL));
90 }
91 
92 #ifdef __BORLANDC__
93 #pragma argsused
94 #endif
95 static int
96 _tiffDummyMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
97 {
98 	return (0);
99 }
100 
101 /*
102  * From "Hermann Josef Hill" <lhill@rhein-zeitung.de>:
103  *
TIFFOpen(const char * name,const char * mode)104  * Windows uses both a handle and a pointer for file mapping,
105  * but according to the SDK documentation and Richter's book
106  * "Advanced Windows Programming" it is safe to free the handle
107  * after obtaining the file mapping pointer
108  *
109  * This removes a nasty OS dependency and cures a problem
110  * with Visual C++ 5.0
111  */
112 static int
113 _tiffMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
114 {
115 	toff_t size;
116 	HANDLE hMapFile;
117 
118 	if ((size = _tiffSizeProc(fd)) == 0xFFFFFFFF)
119 		return (0);
120 	hMapFile = CreateFileMapping(fd, NULL, PAGE_READONLY, 0, size, NULL);
121 	if (hMapFile == NULL)
122 		return (0);
123 	*pbase = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
124 	CloseHandle(hMapFile);
125 	if (*pbase == NULL)
126 		return (0);
127 	*psize = size;
128 	return(1);
129 }
130 
_TIFFmalloc(tsize_t s)131 #ifdef __BORLANDC__
132 #pragma argsused
133 #endif
134 static void
135 _tiffDummyUnmapProc(thandle_t fd, tdata_t base, toff_t size)
136 {
137 }
138 
139 static void
140 _tiffUnmapProc(thandle_t fd, tdata_t base, toff_t size)
141 {
142 	UnmapViewOfFile(base);
_TIFFrealloc(tdata_t p,tsize_t s)143 }
144 
145 /*
146  * Open a TIFF file descriptor for read/writing.
147  * Note that TIFFFdOpen and TIFFOpen recognise the character 'u' in the mode
148  * string, which forces the file to be opened unmapped.
149  */
150 TIFF*
151 TIFFFdOpen(int ifd, const char* name, const char* mode)
152 {
153 	TIFF* tif;
154 	BOOL fSuppressMap = (mode[1] == 'u' || (mode[1]!=0 && mode[2] == 'u'));
155 
156 	tif = TIFFClientOpen(name, mode, (thandle_t)ifd,
157 			_tiffReadProc, _tiffWriteProc,
158 			_tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
159 			fSuppressMap ? _tiffDummyMapProc : _tiffMapProc,
160 			fSuppressMap ? _tiffDummyUnmapProc : _tiffUnmapProc);
161 	if (tif)
162 		tif->tif_fd = ifd;
163 	return (tif);
164 }
165 
_TIFFmemcpy(tdata_t d,const tdata_t s,tsize_t c)166 /*
167  * Open a TIFF file for read/writing.
168  */
169 TIFF*
170 TIFFOpen(const char* name, const char* mode)
171 {
172 	static const char module[] = "TIFFOpen";
173 	thandle_t fd;
174 	int m;
175 	DWORD dwMode;
176 	TIFF* tif;
177 
178 	m = _TIFFgetMode(mode, module);
179 
180 	switch(m)
181 	{
182 	case O_RDONLY:
183 		dwMode = OPEN_EXISTING;
184 		break;
185 	case O_RDWR:
186 		dwMode = OPEN_ALWAYS;
187 		break;
188 	case O_RDWR|O_CREAT:
189 		dwMode = OPEN_ALWAYS;
190 		break;
191 	case O_RDWR|O_TRUNC:
192 		dwMode = CREATE_ALWAYS;
193 		break;
194 	case O_RDWR|O_CREAT|O_TRUNC:
195 		dwMode = CREATE_ALWAYS;
196 		break;
197 	default:
198 		return ((TIFF*)0);
199 	}
200 	fd = (thandle_t)CreateFileA(name,
201 		(m == O_RDONLY)?GENERIC_READ:(GENERIC_READ | GENERIC_WRITE),
202 		FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, dwMode,
203 		(m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL,
204 		NULL);
205 	if (fd == INVALID_HANDLE_VALUE) {
206 		TIFFErrorExt(0, module, "%s: Cannot open", name);
207 		return ((TIFF *)0);
208 	}
209 
210 	tif = TIFFFdOpen((int)fd, name, mode);
211 	if(!tif)
212 		CloseHandle(fd);
213 	return tif;
214 }
215 
win3ErrorHandler(const char * module,const char * fmt,va_list ap)216 /*
217  * Open a TIFF file with a Unicode filename, for read/writing.
218  */
219 TIFF*
220 TIFFOpenW(const wchar_t* name, const char* mode)
221 {
222 	static const char module[] = "TIFFOpenW";
223 	thandle_t fd;
224 	int m;
225 	DWORD dwMode;
226 	int mbsize;
227 	char *mbname;
228 	TIFF *tif;
229 
230 	m = _TIFFgetMode(mode, module);
231 
232 	switch(m) {
233 		case O_RDONLY:			dwMode = OPEN_EXISTING; break;
234 		case O_RDWR:			dwMode = OPEN_ALWAYS;   break;
235 		case O_RDWR|O_CREAT:		dwMode = OPEN_ALWAYS;   break;
236 		case O_RDWR|O_TRUNC:		dwMode = CREATE_ALWAYS; break;
237 		case O_RDWR|O_CREAT|O_TRUNC:	dwMode = CREATE_ALWAYS; break;
238 		default:			return ((TIFF*)0);
239 	}
240 
241 	fd = (thandle_t)CreateFileW(name,
242 		(m == O_RDONLY)?GENERIC_READ:(GENERIC_READ|GENERIC_WRITE),
243 		FILE_SHARE_READ, NULL, dwMode,
244 		(m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL,
245 		NULL);
246 	if (fd == INVALID_HANDLE_VALUE) {
247 		TIFFErrorExt(0, module, "%S: Cannot open", name);
248 		return ((TIFF *)0);
249 	}
250 
251 	mbname = NULL;
252 	mbsize = WideCharToMultiByte(CP_ACP, 0, name, -1, NULL, 0, NULL, NULL);
253 	if (mbsize > 0) {
254 		mbname = (char *)_TIFFmalloc(mbsize);
255 		if (!mbname) {
256 			TIFFErrorExt(0, module,
257 			"Can't allocate space for filename conversion buffer");
258 			return ((TIFF*)0);
259 		}
260 
261 		WideCharToMultiByte(CP_ACP, 0, name, -1, mbname, mbsize,
262 				    NULL, NULL);
263 	}
264 
265 	tif = TIFFFdOpen((int)fd,
266 			 (mbname != NULL) ? mbname : "<unknown>", mode);
267 	if(!tif)
268 		CloseHandle(fd);
269 
270 	_TIFFfree(mbname);
271 
272 	return tif;
273 }
274 
275 tdata_t
276 _TIFFmalloc(tsize_t s)
277 {
278 	return ((tdata_t)GlobalAlloc(GMEM_FIXED, s));
279 }
280 
281 void
282 _TIFFfree(tdata_t p)
283 {
284 	GlobalFree(p);
285 	return;
286 }
287 
288 tdata_t
289 _TIFFrealloc(tdata_t p, tsize_t s)
290 {
291         void* pvTmp;
292         tsize_t old;
293 
294         if(p == NULL)
295                 return ((tdata_t)GlobalAlloc(GMEM_FIXED, s));
296 
297         old = GlobalSize(p);
298 
299         if (old>=s) {
300                 if ((pvTmp = GlobalAlloc(GMEM_FIXED, s)) != NULL) {
301 	                CopyMemory(pvTmp, p, s);
302 	                GlobalFree(p);
303                 }
304         } else {
305                 if ((pvTmp = GlobalAlloc(GMEM_FIXED, s)) != NULL) {
306 	                CopyMemory(pvTmp, p, old);
307 	                GlobalFree(p);
308                 }
309         }
310         return ((tdata_t)pvTmp);
311 }
312 
313 void
314 _TIFFmemset(void* p, int v, tsize_t c)
315 {
316 	FillMemory(p, c, (BYTE)v);
317 }
318 
319 void
320 _TIFFmemcpy(void* d, const tdata_t s, tsize_t c)
321 {
322 	CopyMemory(d, s, c);
323 }
324 
325 int
326 _TIFFmemcmp(const tdata_t p1, const tdata_t p2, tsize_t c)
327 {
328 	register const BYTE *pb1 = (const BYTE *) p1;
329 	register const BYTE *pb2 = (const BYTE *) p2;
330 	register DWORD dwTmp = c;
331 	register int iTmp;
332 	for (iTmp = 0; dwTmp-- && !iTmp; iTmp = (int)*pb1++ - (int)*pb2++)
333 		;
334 	return (iTmp);
335 }
336 
337 static void
338 Win32WarningHandler(const char* module, const char* fmt, va_list ap)
339 {
340 #ifndef TIF_PLATFORM_CONSOLE
341 	LPTSTR szTitle;
342 	LPTSTR szTmp;
343 	LPCTSTR szTitleText = "%s Warning";
344 	LPCTSTR szDefaultModule = "LIBTIFF";
345 	LPCTSTR szTmpModule = (module == NULL) ? szDefaultModule : module;
346 	if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, (strlen(szTmpModule) +
347 		strlen(szTitleText) + strlen(fmt) + 128)*sizeof(char))) == NULL)
348 		return;
349 	sprintf(szTitle, szTitleText, szTmpModule);
350 	szTmp = szTitle + (strlen(szTitle)+2)*sizeof(char);
351 	vsprintf(szTmp, fmt, ap);
352 	MessageBoxA(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONINFORMATION);
353 	LocalFree(szTitle);
354 	return;
355 #else
356 	if (module != NULL)
357 		fprintf(stderr, "%s: ", module);
358 	fprintf(stderr, "Warning, ");
359 	vfprintf(stderr, fmt, ap);
360 	fprintf(stderr, ".\n");
361 #endif
362 }
363 TIFFErrorHandler _TIFFwarningHandler = Win32WarningHandler;
364 
365 static void
366 Win32ErrorHandler(const char* module, const char* fmt, va_list ap)
367 {
368 #ifndef TIF_PLATFORM_CONSOLE
369 	LPTSTR szTitle;
370 	LPTSTR szTmp;
371 	LPCTSTR szTitleText = "%s Error";
372 	LPCTSTR szDefaultModule = "LIBTIFF";
373 	LPCTSTR szTmpModule = (module == NULL) ? szDefaultModule : module;
374 	if ((szTitle = (LPTSTR)LocalAlloc(LMEM_FIXED, (strlen(szTmpModule) +
375 		strlen(szTitleText) + strlen(fmt) + 128)*sizeof(char))) == NULL)
376 		return;
377 	sprintf(szTitle, szTitleText, szTmpModule);
378 	szTmp = szTitle + (strlen(szTitle)+2)*sizeof(char);
379 	vsprintf(szTmp, fmt, ap);
380 	MessageBoxA(GetFocus(), szTmp, szTitle, MB_OK | MB_ICONEXCLAMATION);
381 	LocalFree(szTitle);
382 	return;
383 #else
384 	if (module != NULL)
385 		fprintf(stderr, "%s: ", module);
386 	vfprintf(stderr, fmt, ap);
387 	fprintf(stderr, ".\n");
388 #endif
389 }
390 TIFFErrorHandler _TIFFerrorHandler = Win32ErrorHandler;
391 
392 /* vim: set ts=8 sts=8 sw=8 noet: */
393