1 /*
2   Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.
3 
4   See the accompanying file LICENSE, version 2009-Jan-02 or later
5   (the contents of which are also included in unzip.h) for terms of use.
6   If, for some reason, all these files are missing, the Info-ZIP license
7   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
8 */
9 /*---------------------------------------------------------------------------
10 
11   api.c
12 
13   This module supplies an UnZip engine for use directly from C/C++
14   programs.  The functions are:
15 
16     ZCONST UzpVer *UzpVersion(void);
17     unsigned UzpVersion2(UzpVer2 *version)
18     int UzpMain(int argc, char *argv[]);
19     int UzpAltMain(int argc, char *argv[], UzpInit *init);
20     int UzpValidate(char *archive, int AllCodes);
21     void UzpFreeMemBuffer(UzpBuffer *retstr);
22     int UzpUnzipToMemory(char *zip, char *file, UzpOpts *optflgs,
23                          UzpCB *UsrFuncts, UzpBuffer *retstr);
24 
25   non-WINDLL only (a special WINDLL variant is defined in windll/windll.c):
26     int UzpGrep(char *archive, char *file, char *pattern, int cmd, int SkipBin,
27                 UzpCB *UsrFuncts);
28 
29   OS/2 only (for now):
30     int UzpFileTree(char *name, cbList(callBack), char *cpInclude[],
31           char *cpExclude[]);
32 
33   You must define `DLL' in order to include the API extensions.
34 
35   ---------------------------------------------------------------------------*/
36 
37 
38 #ifdef OS2
39 #  define  INCL_DOSMEMMGR
40 #  include <os2.h>
41 #endif
42 
43 #define UNZIP_INTERNAL
44 #include "unzip.h"
45 #ifdef WINDLL
46 #  ifdef POCKET_UNZIP
47 #    include "wince/intrface.h"
48 #  else
49 #    include "windll/windll.h"
50 #  endif
51 #endif
52 #include "unzvers.h"
53 #include <setjmp.h>
54 
55 #ifdef DLL      /* This source file supplies DLL-only interface code. */
56 
57 #ifndef POCKET_UNZIP    /* WinCE pUnZip defines this elsewhere. */
58 jmp_buf dll_error_return;
59 #endif
60 
61 /*---------------------------------------------------------------------------
62     Documented API entry points
63   ---------------------------------------------------------------------------*/
64 
65 
UzpVersion()66 ZCONST UzpVer * UZ_EXP UzpVersion()     /* returns pointer to const struct */
67 {
68     static ZCONST UzpVer version = {    /* doesn't change between calls */
69         /* structure size */
70         UZPVER_LEN,
71         /* version flags */
72 #ifdef BETA
73 # ifdef ZLIB_VERSION
74         3,
75 # else
76         1,
77 # endif
78 #else
79 # ifdef ZLIB_VERSION
80         2,
81 # else
82         0,
83 # endif
84 #endif
85         /* betalevel and date strings */
86         UZ_BETALEVEL, UZ_VERSION_DATE,
87         /* zlib_version string */
88 #ifdef ZLIB_VERSION
89         ZLIB_VERSION,
90 #else
91         NULL,
92 #endif
93         /*== someday each of these may have a separate patchlevel: ==*/
94         /* unzip version */
95         {UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, 0},
96         /* zipinfo version */
97         {ZI_MAJORVER, ZI_MINORVER, UZ_PATCHLEVEL, 0},
98         /* os2dll version (retained for backward compatibility) */
99         {UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, 0},
100         /* windll version (retained for backward compatibility)*/
101         {UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, 0},
102 #ifdef OS2DLL
103         /* os2dll API minimum compatible version*/
104         {UZ_OS2API_COMP_MAJOR, UZ_OS2API_COMP_MINOR, UZ_OS2API_COMP_REVIS, 0}
105 #else /* !OS2DLL */
106 #ifdef WINDLL
107         /* windll API minimum compatible version*/
108         {UZ_WINAPI_COMP_MAJOR, UZ_WINAPI_COMP_MINOR, UZ_WINAPI_COMP_REVIS, 0}
109 #else /* !WINDLL */
110         /* generic DLL API minimum compatible version*/
111         {UZ_GENAPI_COMP_MAJOR, UZ_GENAPI_COMP_MINOR, UZ_GENAPI_COMP_REVIS, 0}
112 #endif /* ?WINDLL */
113 #endif /* ?OS2DLL */
114     };
115 
116     return &version;
117 }
118 
UzpVersion2(UzpVer2 * version)119 unsigned UZ_EXP UzpVersion2(UzpVer2 *version)
120 {
121 
122     if (version->structlen != sizeof(UzpVer2))
123         return sizeof(UzpVer2);
124 
125 #ifdef BETA
126     version->flag = 1;
127 #else
128     version->flag = 0;
129 #endif
130     strcpy(version->betalevel, UZ_BETALEVEL);
131     strcpy(version->date, UZ_VERSION_DATE);
132 
133 #ifdef ZLIB_VERSION
134     /* Although ZLIB_VERSION is a compile-time constant, we implement an
135        "overrun-safe" copy because its actual value is not under our control.
136      */
137     strncpy(version->zlib_version, ZLIB_VERSION,
138             sizeof(version->zlib_version) - 1);
139     version->zlib_version[sizeof(version->zlib_version) - 1] = '\0';
140     version->flag |= 2;
141 #else
142     version->zlib_version[0] = '\0';
143 #endif
144 
145     /* someday each of these may have a separate patchlevel: */
146     version->unzip.major = UZ_MAJORVER;
147     version->unzip.minor = UZ_MINORVER;
148     version->unzip.patchlevel = UZ_PATCHLEVEL;
149 
150     version->zipinfo.major = ZI_MAJORVER;
151     version->zipinfo.minor = ZI_MINORVER;
152     version->zipinfo.patchlevel = UZ_PATCHLEVEL;
153 
154     /* these are retained for backward compatibility only: */
155     version->os2dll.major = UZ_MAJORVER;
156     version->os2dll.minor = UZ_MINORVER;
157     version->os2dll.patchlevel = UZ_PATCHLEVEL;
158 
159     version->windll.major = UZ_MAJORVER;
160     version->windll.minor = UZ_MINORVER;
161     version->windll.patchlevel = UZ_PATCHLEVEL;
162 
163 #ifdef OS2DLL
164     /* os2dll API minimum compatible version*/
165     version->dllapimin.major = UZ_OS2API_COMP_MAJOR;
166     version->dllapimin.minor = UZ_OS2API_COMP_MINOR;
167     version->dllapimin.patchlevel = UZ_OS2API_COMP_REVIS;
168 #else /* !OS2DLL */
169 #ifdef WINDLL
170     /* windll API minimum compatible version*/
171     version->dllapimin.major = UZ_WINAPI_COMP_MAJOR;
172     version->dllapimin.minor = UZ_WINAPI_COMP_MINOR;
173     version->dllapimin.patchlevel = UZ_WINAPI_COMP_REVIS;
174 #else /* !WINDLL */
175     /* generic DLL API minimum compatible version*/
176     version->dllapimin.major = UZ_GENAPI_COMP_MAJOR;
177     version->dllapimin.minor = UZ_GENAPI_COMP_MINOR;
178     version->dllapimin.patchlevel = UZ_GENAPI_COMP_REVIS;
179 #endif /* ?WINDLL */
180 #endif /* ?OS2DLL */
181     return 0;
182 }
183 
184 
185 
186 
187 
188 #ifndef SFX
189 #ifndef WINDLL
190 
UzpAltMain(int argc,char * argv[],UzpInit * init)191 int UZ_EXP UzpAltMain(int argc, char *argv[], UzpInit *init)
192 {
193     int r, (*dummyfn)();
194 
195 
196     CONSTRUCTGLOBALS();
197 
198     if (init->structlen >= (sizeof(ulg) + sizeof(dummyfn)) && init->msgfn)
199         G.message = init->msgfn;
200 
201     if (init->structlen >= (sizeof(ulg) + 2*sizeof(dummyfn)) && init->inputfn)
202         G.input = init->inputfn;
203 
204     if (init->structlen >= (sizeof(ulg) + 3*sizeof(dummyfn)) && init->pausefn)
205         G.mpause = init->pausefn;
206 
207     if (init->structlen >= (sizeof(ulg) + 4*sizeof(dummyfn)) && init->userfn)
208         (*init->userfn)();    /* allow void* arg? */
209 
210     r = unzip(__G__ argc, argv);
211     DESTROYGLOBALS();
212     RETURN(r);
213 }
214 
215 #endif /* !WINDLL */
216 
217 
218 
219 
220 #ifndef __16BIT__
221 
UzpFreeMemBuffer(UzpBuffer * retstr)222 void UZ_EXP UzpFreeMemBuffer(UzpBuffer *retstr)
223 {
224     if (retstr != NULL && retstr->strptr != NULL) {
225         free(retstr->strptr);
226         retstr->strptr = NULL;
227         retstr->strlength = 0;
228     }
229 }
230 
231 
232 
233 
234 #ifndef WINDLL
235 
236 static int UzpDLL_Init OF((zvoid *pG, UzpCB *UsrFuncts));
237 
UzpDLL_Init(pG,UsrFuncts)238 static int UzpDLL_Init(pG, UsrFuncts)
239 zvoid *pG;
240 UzpCB *UsrFuncts;
241 {
242     int (*dummyfn)();
243 
244     if (UsrFuncts->structlen >= (sizeof(ulg) + sizeof(dummyfn)) &&
245         UsrFuncts->msgfn)
246         ((Uz_Globs *)pG)->message = UsrFuncts->msgfn;
247     else
248         return FALSE;
249 
250     if (UsrFuncts->structlen >= (sizeof(ulg) + 2*sizeof(dummyfn)) &&
251         UsrFuncts->inputfn)
252         ((Uz_Globs *)pG)->input = UsrFuncts->inputfn;
253 
254     if (UsrFuncts->structlen >= (sizeof(ulg) + 3*sizeof(dummyfn)) &&
255         UsrFuncts->pausefn)
256         ((Uz_Globs *)pG)->mpause = UsrFuncts->pausefn;
257 
258     if (UsrFuncts->structlen >= (sizeof(ulg) + 4*sizeof(dummyfn)) &&
259         UsrFuncts->passwdfn)
260         ((Uz_Globs *)pG)->decr_passwd = UsrFuncts->passwdfn;
261 
262     if (UsrFuncts->structlen >= (sizeof(ulg) + 5*sizeof(dummyfn)) &&
263         UsrFuncts->statrepfn)
264         ((Uz_Globs *)pG)->statreportcb = UsrFuncts->statrepfn;
265 
266     return TRUE;
267 }
268 
269 
UzpUnzipToMemory(char * zip,char * file,UzpOpts * optflgs,UzpCB * UsrFuncts,UzpBuffer * retstr)270 int UZ_EXP UzpUnzipToMemory(char *zip, char *file, UzpOpts *optflgs,
271     UzpCB *UsrFuncts, UzpBuffer *retstr)
272 {
273     int r;
274 #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
275     char *intern_zip, *intern_file;
276 #endif
277 
278     CONSTRUCTGLOBALS();
279 #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
280     intern_zip = (char *)malloc(strlen(zip)+1);
281     if (intern_zip == NULL) {
282        DESTROYGLOBALS();
283        return PK_MEM;
284     }
285     intern_file = (char *)malloc(strlen(file)+1);
286     if (intern_file == NULL) {
287        DESTROYGLOBALS();
288        free(intern_zip);
289        return PK_MEM;
290     }
291     ISO_TO_INTERN(zip, intern_zip);
292     ISO_TO_INTERN(file, intern_file);
293 #   define zip intern_zip
294 #   define file intern_file
295 #endif
296     /* Copy those options that are meaningful for UzpUnzipToMemory, instead of
297      * a simple "memcpy(G.UzO, optflgs, sizeof(UzpOpts));"
298      */
299     uO.pwdarg = optflgs->pwdarg;
300     uO.aflag = optflgs->aflag;
301     uO.C_flag = optflgs->C_flag;
302     uO.qflag = optflgs->qflag;  /* currently,  overridden in unzipToMemory */
303 
304     if (!UzpDLL_Init((zvoid *)&G, UsrFuncts)) {
305        DESTROYGLOBALS();
306        return PK_BADERR;
307     }
308     G.redirect_data = 1;
309 
310     r = (unzipToMemory(__G__ zip, file, retstr) <= PK_WARN);
311 
312     DESTROYGLOBALS();
313 #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
314 #  undef file
315 #  undef zip
316     free(intern_file);
317     free(intern_zip);
318 #endif
319     if (!r && retstr->strlength) {
320        free(retstr->strptr);
321        retstr->strptr = NULL;
322     }
323     return r;
324 }
325 #endif /* !WINDLL */
326 #endif /* !__16BIT__ */
327 
328 
329 
330 
331 
332 #ifdef OS2DLL
333 
UzpFileTree(char * name,cbList (callBack),char * cpInclude[],char * cpExclude[])334 int UZ_EXP UzpFileTree(char *name, cbList(callBack), char *cpInclude[],
335                 char *cpExclude[])
336 {
337     int r;
338 
339     CONSTRUCTGLOBALS();
340     uO.qflag = 2;
341     uO.vflag = 1;
342     uO.C_flag = 1;
343     G.wildzipfn = name;
344     G.process_all_files = TRUE;
345     if (cpInclude) {
346         char **ptr = cpInclude;
347 
348         while (*ptr != NULL) ptr++;
349         G.filespecs = ptr - cpInclude;
350         G.pfnames = cpInclude, G.process_all_files = FALSE;
351     }
352     if (cpExclude) {
353         char **ptr = cpExclude;
354 
355         while (*ptr != NULL) ptr++;
356         G.xfilespecs = ptr - cpExclude;
357         G.pxnames = cpExclude, G.process_all_files = FALSE;
358     }
359 
360     G.processExternally = callBack;
361     r = process_zipfiles(__G)==0;
362     DESTROYGLOBALS();
363     return r;
364 }
365 
366 #endif /* OS2DLL */
367 #endif /* !SFX */
368 
369 
370 
371 
372 /*---------------------------------------------------------------------------
373     Helper functions
374   ---------------------------------------------------------------------------*/
375 
376 
setFileNotFound(__G)377 void setFileNotFound(__G)
378     __GDEF
379 {
380     G.filenotfound++;
381 }
382 
383 
384 #ifndef SFX
385 
unzipToMemory(__GPRO__ char * zip,char * file,UzpBuffer * retstr)386 int unzipToMemory(__GPRO__ char *zip, char *file, UzpBuffer *retstr)
387 {
388     int r;
389     char *incname[2];
390 
391     if ((zip == NULL) || (strlen(zip) > ((WSIZE>>2) - 160)))
392         return PK_PARAM;
393     if ((file == NULL) || (strlen(file) > ((WSIZE>>2) - 160)))
394         return PK_PARAM;
395 
396     G.process_all_files = FALSE;
397     G.extract_flag = TRUE;
398     uO.qflag = 2;
399     G.wildzipfn = zip;
400 
401     G.pfnames = incname;
402     incname[0] = file;
403     incname[1] = NULL;
404     G.filespecs = 1;
405 
406     r = process_zipfiles(__G);
407     if (retstr) {
408         retstr->strptr = (char *)G.redirect_buffer;
409         retstr->strlength = G.redirect_size;
410     }
411     return r;                   /* returns `PK_???' error values */
412 }
413 
414 #endif /* !SFX */
415 
416 /*
417     With the advent of 64 bit support, for now I am assuming that
418     if the size of the file is greater than an unsigned long, there
419     will simply not be enough memory to handle it, and am returning
420     FALSE.
421 */
redirect_outfile(__G)422 int redirect_outfile(__G)
423      __GDEF
424 {
425 #ifdef ZIP64_SUPPORT
426     __int64 check_conversion;
427 #endif
428 
429     if (G.redirect_size != 0 || G.redirect_buffer != NULL)
430         return FALSE;
431 
432 #ifndef NO_SLIDE_REDIR
433     G.redirect_slide = !G.pInfo->textmode;
434 #endif
435 #if (lenEOL != 1)
436     if (G.pInfo->textmode) {
437         G.redirect_size = (ulg)(G.lrec.ucsize * lenEOL);
438         if (G.redirect_size < G.lrec.ucsize)
439             G.redirect_size = (ulg)((G.lrec.ucsize > (ulg)-2L) ?
440                                     G.lrec.ucsize : -2L);
441 #ifdef ZIP64_SUPPORT
442         check_conversion = G.lrec.ucsize * lenEOL;
443 #endif
444     } else
445 #endif
446     {
447         G.redirect_size = (ulg)G.lrec.ucsize;
448 #ifdef ZIP64_SUPPORT
449         check_conversion = (__int64)G.lrec.ucsize;
450 #endif
451     }
452 
453 #ifdef ZIP64_SUPPORT
454     if ((__int64)G.redirect_size != check_conversion)
455         return FALSE;
456 #endif
457 
458 #ifdef __16BIT__
459     if ((ulg)((extent)G.redirect_size) != G.redirect_size)
460         return FALSE;
461 #endif
462 #ifdef OS2
463     DosAllocMem((void **)&G.redirect_buffer, G.redirect_size+1,
464       PAG_READ|PAG_WRITE|PAG_COMMIT);
465     G.redirect_pointer = G.redirect_buffer;
466 #else
467     G.redirect_pointer =
468       G.redirect_buffer = malloc((extent)(G.redirect_size+1));
469 #endif
470     if (!G.redirect_buffer)
471         return FALSE;
472     G.redirect_pointer[G.redirect_size] = '\0';
473     return TRUE;
474 }
475 
476 
477 
writeToMemory(__GPRO__ ZCONST uch * rawbuf,extent size)478 int writeToMemory(__GPRO__ ZCONST uch *rawbuf, extent size)
479 {
480     int errflg = FALSE;
481 
482     if ((uch *)rawbuf != G.redirect_pointer) {
483         extent redir_avail = (G.redirect_buffer + G.redirect_size) -
484                              G.redirect_pointer;
485 
486         /* Check for output buffer overflow */
487         if (size > redir_avail) {
488            /* limit transfer data to available space, set error return flag */
489            size = redir_avail;
490            errflg = TRUE;
491         }
492         memcpy(G.redirect_pointer, rawbuf, size);
493     }
494     G.redirect_pointer += size;
495     return errflg;
496 }
497 
498 
499 
500 
close_redirect(__G)501 int close_redirect(__G)
502      __GDEF
503 {
504     if (G.pInfo->textmode) {
505         *G.redirect_pointer = '\0';
506         G.redirect_size = (ulg)(G.redirect_pointer - G.redirect_buffer);
507         if ((G.redirect_buffer =
508              realloc(G.redirect_buffer, G.redirect_size + 1)) == NULL) {
509             G.redirect_size = 0;
510             return EOF;
511         }
512     }
513     return 0;
514 }
515 
516 
517 
518 
519 #ifndef SFX
520 #ifndef __16BIT__
521 #ifndef WINDLL
522 
523 /* Purpose: Determine if file in archive contains the string szSearch
524 
525    Parameters: archive  = archive name
526                file     = file contained in the archive. This cannot be
527                           a wildcard to be meaningful
528                pattern  = string to search for
529                cmd      = 0 - case-insensitive search
530                           1 - case-sensitve search
531                           2 - case-insensitive, whole words only
532                           3 - case-sensitive, whole words only
533                SkipBin  = if true, skip any files that have control
534                           characters other than CR, LF, or tab in the first
535                           100 characters.
536 
537    Returns:    TRUE if a match is found
538                FALSE if no match is found
539                -1 on error
540 
541    Comments: This does not pretend to be as useful as the standard
542              Unix grep, which returns the strings associated with a
543              particular pattern, nor does it search past the first
544              matching occurrence of the pattern.
545  */
546 
UzpGrep(char * archive,char * file,char * pattern,int cmd,int SkipBin,UzpCB * UsrFuncts)547 int UZ_EXP UzpGrep(char *archive, char *file, char *pattern, int cmd,
548                    int SkipBin, UzpCB *UsrFuncts)
549 {
550     int retcode = FALSE, compare;
551     ulg i, j, patternLen, buflen;
552     char * sz, *p;
553     UzpOpts flgopts;
554     UzpBuffer retstr;
555 
556     memzero(&flgopts, sizeof(UzpOpts));         /* no special options */
557 
558     if (!UzpUnzipToMemory(archive, file, &flgopts, UsrFuncts, &retstr)) {
559        return -1;   /* not enough memory, file not found, or other error */
560     }
561 
562     if (SkipBin) {
563         if (retstr.strlength < 100)
564             buflen = retstr.strlength;
565         else
566             buflen = 100;
567         for (i = 0; i < buflen; i++) {
568             if (iscntrl(retstr.strptr[i])) {
569                 if ((retstr.strptr[i] != 0x0A) &&
570                     (retstr.strptr[i] != 0x0D) &&
571                     (retstr.strptr[i] != 0x09))
572                 {
573                     /* OK, we now think we have a binary file of some sort */
574                     free(retstr.strptr);
575                     return FALSE;
576                 }
577             }
578         }
579     }
580 
581     patternLen = strlen(pattern);
582 
583     if (retstr.strlength < patternLen) {
584         free(retstr.strptr);
585         return FALSE;
586     }
587 
588     sz = malloc(patternLen + 3); /* add two in case doing whole words only */
589     if (cmd > 1) {
590         strcpy(sz, " ");
591         strcat(sz, pattern);
592         strcat(sz, " ");
593     } else
594         strcpy(sz, pattern);
595 
596     if ((cmd == 0) || (cmd == 2)) {
597         for (i = 0; i < strlen(sz); i++)
598             sz[i] = toupper(sz[i]);
599         for (i = 0; i < retstr.strlength; i++)
600             retstr.strptr[i] = toupper(retstr.strptr[i]);
601     }
602 
603     for (i = 0; i < (retstr.strlength - patternLen); i++) {
604         p = &retstr.strptr[i];
605         compare = TRUE;
606         for (j = 0; j < patternLen; j++) {
607             /* We cannot do strncmp here, as we may be dealing with a
608              * "binary" file, such as a word processing file, or perhaps
609              * even a true executable of some sort. */
610             if (p[j] != sz[j]) {
611                 compare = FALSE;
612                 break;
613             }
614         }
615         if (compare == TRUE) {
616             retcode = TRUE;
617             break;
618         }
619     }
620 
621     free(sz);
622     free(retstr.strptr);
623 
624     return retcode;
625 }
626 #endif /* !WINDLL */
627 #endif /* !__16BIT__ */
628 
629 
630 
UzpValidate(char * archive,int AllCodes)631 int UZ_EXP UzpValidate(char *archive, int AllCodes)
632 {
633     int retcode;
634     CONSTRUCTGLOBALS();
635 
636     uO.jflag = 1;
637     uO.tflag = 1;
638     uO.overwrite_none = 0;
639     G.extract_flag = (!uO.zipinfo_mode &&
640                       !uO.cflag && !uO.tflag && !uO.vflag && !uO.zflag
641 #ifdef TIMESTAMP
642                       && !uO.T_flag
643 #endif
644                      );
645 
646     uO.qflag = 2;                        /* turn off all messages */
647     G.fValidate = TRUE;
648     G.pfnames = (char **)&fnames[0];    /* assign default filename vector */
649 
650     if (archive == NULL) {      /* something is screwed up:  no filename */
651         DESTROYGLOBALS();
652         retcode = PK_NOZIP;
653         goto exit_retcode;
654     }
655 
656     if (strlen(archive) >= FILNAMSIZ) {
657        /* length of supplied archive name exceed the system's filename limit */
658        DESTROYGLOBALS();
659        retcode = PK_PARAM;
660        goto exit_retcode;
661     }
662 
663     G.wildzipfn = (char *)malloc(FILNAMSIZ);
664     strcpy(G.wildzipfn, archive);
665 #if (defined(WINDLL) && !defined(CRTL_CP_IS_ISO))
666     _ISO_INTERN(G.wildzipfn);
667 #endif
668 
669 #ifdef WINDLL
670     Wiz_NoPrinting(TRUE);
671 #endif
672 
673     G.process_all_files = TRUE;         /* for speed */
674 
675     if (setjmp(dll_error_return) != 0) {
676 #ifdef WINDLL
677         Wiz_NoPrinting(FALSE);
678 #endif
679         free(G.wildzipfn);
680         DESTROYGLOBALS();
681         retcode = PK_BADERR;
682         goto exit_retcode;
683     }
684 
685     retcode = process_zipfiles(__G);
686 
687     free(G.wildzipfn);
688 #ifdef WINDLL
689     Wiz_NoPrinting(FALSE);
690 #endif
691     DESTROYGLOBALS();
692 
693     /* PK_WARN == 1 and PK_FIND == 11. When we are just looking at an
694        archive, we should still be able to see the files inside it,
695        even if we can't decode them for some reason.
696 
697        We also still want to be able to get at files even if there is
698        something odd about the zip archive, hence allow PK_WARN,
699        PK_FIND, IZ_UNSUP as well as PK_ERR
700      */
701 
702 exit_retcode:
703     if (AllCodes)
704         return retcode;
705 
706     if ((retcode == PK_OK) || (retcode == PK_WARN) || (retcode == PK_ERR) ||
707         (retcode == IZ_UNSUP) || (retcode == PK_FIND))
708         return TRUE;
709     else
710         return FALSE;
711 }
712 
713 #endif /* !SFX */
714 #endif /* DLL */
715