unzipdll.pp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. {
  2. $Id$
  3. }
  4. unit UnzipDLL;
  5. {$IFDEF VIRTUALPASCAL}
  6. {$Cdecl+,AlignRec-,OrgName+}
  7. {$ELSE}
  8. {$IFDEF FPC}
  9. {$PACKRECORDS 1}
  10. {$ENDIF}
  11. {$ENDIF}
  12. interface
  13. uses
  14. ZipTypes;
  15. const
  16. UnzipErr: longint = 0;
  17. type
  18. TArgV = array [1..1024] of PChar;
  19. PArgV = ^TArgV;
  20. TCharArray = array [1..1024*1024] of char;
  21. PCharArray = ^TCharArray;
  22. TFileUnzipEx = function (SourceZipFile, TargetDirectory,
  23. FileSpecs: PChar): integer;
  24. function DllFileUnzipEx (SourceZipFile, TargetDirectory,
  25. FileSpecs: PChar): integer;
  26. const
  27. FileUnzipEx: TFileUnzipEx = @DllFileUnzipEx;
  28. (* Returns non-zero result on success. *)
  29. implementation
  30. uses
  31. {$IFDEF OS2}
  32. {$IFDEF FPC}
  33. DosCalls,
  34. {$ELSE FPC}
  35. {$IFDEF VirtualPascal}
  36. OS2Base,
  37. {$ELSE VirtualPascal}
  38. BseDos,
  39. {$ENDIF VirtualPascal}
  40. {$ENDIF FPC}
  41. {$ELSE}
  42. {$IFDEF WIN32}
  43. Windows,
  44. {$ENDIF WIN32}
  45. {$ENDIF OS2}
  46. Unzip, Dos;
  47. type
  48. UzpMainFunc = function (ArgC: longint; var ArgV: TArgV): longint; cdecl;
  49. const
  50. {$IFDEF OS2}
  51. AllFiles: string [1] = '*';
  52. {$ELSE}
  53. {$IFDEF WIN32}
  54. AllFiles: string [3] = '*.*';
  55. {$ENDIF}
  56. {$ENDIF}
  57. {$IFDEF OS2}
  58. LibPath = 'LIBPATH';
  59. {$ELSE}
  60. LibPath = 'PATH';
  61. {$ENDIF}
  62. UzpMainOrd = 4;
  63. DLLName: string [8] = 'UNZIP32'#0;
  64. UzpMain: UzpMainFunc = nil;
  65. QuiteOpt: array [1..4] of char = '-qq'#0;
  66. OverOpt: array [1..3] of char = '-o'#0;
  67. CaseInsOpt: array [1..3] of char = '-C'#0;
  68. ExDirOpt: array [1..3] of char = '-d'#0;
  69. OptCount = 4;
  70. var
  71. DLLHandle: longint;
  72. OldExit: pointer;
  73. C: char;
  74. function DLLInit: boolean;
  75. var
  76. {$IFDEF OS2}
  77. ErrPath: array [0..259] of char;
  78. {$ENDIF}
  79. DLLPath: PathStr;
  80. Dir: DirStr;
  81. Name: NameStr;
  82. Ext: ExtStr;
  83. begin
  84. DLLInit := false;
  85. FSplit (FExpand (ParamStr (0)), Dir, Name, Ext);
  86. DLLPath := Dir + DLLName;
  87. Insert ('.DLL', DLLPath, byte (DLLPath [0]));
  88. {$IFDEF OS2}
  89. if (DosLoadModule (@ErrPath, SizeOf (ErrPath), @DLLPath [1], DLLHandle) <> 0)
  90. and (DosLoadModule (@ErrPath, SizeOf (ErrPath), @DLLName [1], DLLHandle) <> 0)
  91. then
  92. begin
  93. if ErrPath [0] <> #0 then
  94. begin
  95. Write (#13#10'Error while loading module ');
  96. WriteLn (PChar (@ErrPath));
  97. end;
  98. {$IFDEF FPC}
  99. end else DLLInit := DosQueryProcAddr (DLLHandle, UzpMainOrd, nil, pointer (UzpMain)) = 0;
  100. {$ELSE}
  101. end else DLLInit := DosQueryProcAddr (DLLHandle, UzpMainOrd, nil, @UzpMain) = 0;
  102. {$ENDIF}
  103. {$ELSE}
  104. {$IFDEF WIN32}
  105. DLLHandle := LoadLibrary (@DLLPath [1]);
  106. if DLLHandle = 0 then DLLHandle := LoadLibrary (@DLLName [1]);
  107. if DLLHandle = 0 then WriteLn (#13#10'Error while loading DLL.') else
  108. begin
  109. (* UzpMain := UzpMainFunc (GetProcAddress (DLLHandle, 'UzpMain'));
  110. *)
  111. UzpMain := UzpMainFunc (GetProcAddress (DLLHandle, 'Unz_Unzip'));
  112. DLLInit := Assigned (UzpMain);
  113. end;
  114. {$ENDIF}
  115. {$ENDIF}
  116. end;
  117. procedure NewExit;
  118. begin
  119. ExitProc := OldExit;
  120. {$IFDEF OS2}
  121. DosFreeModule (DLLHandle);
  122. {$ELSE}
  123. {$IFDEF WIN32}
  124. FreeLibrary (DLLHandle);
  125. {$ENDIF}
  126. {$ENDIF}
  127. end;
  128. function DllFileUnzipEx (SourceZipFile, TargetDirectory,
  129. FileSpecs: PChar): integer;
  130. var
  131. I, FCount, ArgC: longint;
  132. ArgV: TArgV;
  133. P: PChar;
  134. StrLen: array [Succ (OptCount)..1024] of longint;
  135. begin
  136. ArgV [0] := @DLLName;
  137. ArgV [1] := @QuiteOpt;
  138. ArgV [2] := @OverOpt;
  139. ArgV [3] := @CaseInsOpt;
  140. ArgV [4] := SourceZipFile;
  141. FCount := 0;
  142. if FileSpecs^ <> #0 then
  143. begin
  144. P := FileSpecs;
  145. I := 0;
  146. repeat
  147. case FileSpecs^ of
  148. '"': begin
  149. Inc (FileSpecs);
  150. repeat Inc (I) until (FileSpecs^ = '"') or (FileSpecs^ = #0);
  151. Inc (FileSpecs);
  152. Inc (I);
  153. end;
  154. '''': begin
  155. Inc (FileSpecs);
  156. repeat Inc (I) until (FileSpecs^ = '''') or (FileSpecs^ = #0);
  157. Inc (FileSpecs);
  158. Inc (I);
  159. end;
  160. #0, ' ', #9: begin
  161. Inc (I);
  162. Inc (FCount);
  163. GetMem (ArgV [OptCount + FCount], I);
  164. Move (P^, ArgV [OptCount + FCount]^, Pred (I));
  165. PCharArray (ArgV [OptCount + FCount])^ [I] := #0;
  166. StrLen [OptCount + FCount] := I;
  167. while (FileSpecs^ = #9) or (FileSpecs^ = ' ') do Inc (FileSpecs);
  168. P := FileSpecs;
  169. I := 0;
  170. end;
  171. else
  172. begin
  173. Inc (I);
  174. Inc (FileSpecs);
  175. end;
  176. end;
  177. until (FileSpecs^ = #0) and (I = 0);
  178. end else
  179. begin
  180. FCount := 1;
  181. StrLen [OptCount + FCount] := Succ (byte (AllFiles [0]));
  182. GetMem (ArgV [OptCount + FCount], StrLen [OptCount + FCount]);
  183. Move (AllFiles [1], ArgV [OptCount + FCount]^, StrLen [OptCount + FCount]);
  184. end;
  185. ArgC := Succ (FCount + OptCount);
  186. ArgV [ArgC] := @ExDirOpt;
  187. Inc (ArgC);
  188. ArgV [ArgC] := TargetDirectory;
  189. Inc (ArgC);
  190. ArgV [ArgC] := @ExDirOpt [3]; (* contains #0 *)
  191. UnzipErr := UzpMain (ArgC, ArgV);
  192. if UnzipErr <> 0 then DllFileUnzipEx := 0 else DllFileUnzipEx := FCount;
  193. for I := 1 to FCount do FreeMem (ArgV [I + OptCount], StrLen [I + OptCount]);
  194. end;
  195. begin
  196. if DLLInit then
  197. begin
  198. OldExit := ExitProc;
  199. ExitProc := @NewExit;
  200. if GetEnv ('TZ') = '' then
  201. begin
  202. WriteLn (#13#10'TZ variable was not found in your environment.');
  203. WriteLn ('This variable is necessary for setting correct date/time of unpacked files.');
  204. WriteLn ('Please, add it to your environment and restart this program afterwards.');
  205. Halt (1);
  206. end;
  207. end else
  208. begin
  209. WriteLn (#13#10'Dynamic library UNZIP32.DLL from InfoZip is needed to unpack archives.');
  210. WriteLn ('This library could not be found on your system, however.');
  211. WriteLn ('Please, download the library, either from the location where you found');
  212. WriteLn ('this package, or from any FTP archive carrying InfoZip programs.');
  213. {$IFDEF OS2}
  214. WriteLn ('If you already have this DLL, please, check your configuration (' + LIBPATH + ').');
  215. {$ELSE}
  216. WriteLn ('If you already have this DLL, please, check your configuration (' + PATH + ').');
  217. {$ENDIF}
  218. WriteLn (#13#10'If you want to try unpacking the files with internal unpacking routine,');
  219. WriteLn ('answer the following question with Y. However, this might not work correctly');
  220. WriteLn ('under some conditions (e.g. for long names and drives not supporting them).');
  221. Write (#13#10'Do you want to continue now (y/N)? ');
  222. ReadLn (C);
  223. if UpCase (C) = 'Y' then FileUnzipEx := TFileUnzipEx (@Unzip.FileUnzipEx) else Halt (255);
  224. end;
  225. end.
  226. {
  227. $Log$
  228. Revision 1.5 2003-08-03 22:25:55 hajny
  229. * integer type inconsistency resolved
  230. Revision 1.4 2002/09/07 15:43:06 peter
  231. * old logs removed and tabs fixed
  232. Revision 1.3 2002/07/07 17:58:09 hajny
  233. * check for TZ variable added
  234. Revision 1.2 2002/07/07 08:22:17 hajny
  235. * warning message modified to be more general
  236. Revision 1.1 2002/01/29 17:55:23 peter
  237. * splitted to base and extra
  238. }