diff --git a/programs/expand/Makefile.in b/programs/expand/Makefile.in index ac35d435846..7e4f98250c6 100644 --- a/programs/expand/Makefile.in +++ b/programs/expand/Makefile.in @@ -4,7 +4,7 @@ SRCDIR = @srcdir@ VPATH = @srcdir@ MODULE = expand.exe APPMODE = -mconsole -IMPORTS = lz32 kernel32 +IMPORTS = setupapi kernel32 C_SRCS = expand.c diff --git a/programs/expand/expand.c b/programs/expand/expand.c index 9f2af8e619f..6022fe2de98 100644 --- a/programs/expand/expand.c +++ b/programs/expand/expand.c @@ -1,6 +1,7 @@ /* * Copyright 1997 Victor Schneider * Copyright 2002 Alexandre Julliard + * Copyright 2007 Hans Leidekker * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,30 +24,100 @@ #include #include #include +#include + +static UINT CALLBACK extract_callback( PVOID context, UINT notification, UINT_PTR param1, UINT_PTR param2 ) +{ + FILE_IN_CABINET_INFO_A *info = (FILE_IN_CABINET_INFO_A *)param1; + + switch (notification) + { + case SPFILENOTIFY_FILEINCABINET: + { + LPCSTR targetname = context; + + strcpy( info->FullTargetName, targetname ); + return FILEOP_DOIT; + } + default: return NO_ERROR; + } +} int main(int argc, char *argv[]) { - OFSTRUCT SourceOpenStruct1, SourceOpenStruct2; - LONG ret; - HFILE hSourceFile, hDestFile; + int ret = 0; + char infile[MAX_PATH], outfile[MAX_PATH], actual_name[MAX_PATH]; + UINT comp; - if (argc < 2) - { - fprintf( stderr, "Usage: %s infile [outfile]\n", argv[0] ); - return 1; - } - hSourceFile = LZOpenFile(argv[1], &SourceOpenStruct1, OF_READ); - if (argv[2]) - hDestFile = LZOpenFile(argv[2], &SourceOpenStruct2, OF_CREATE | OF_WRITE); - else - { - char OriginalName[MAX_PATH]; - GetExpandedName(argv[1], OriginalName); - hDestFile = LZOpenFile(OriginalName, &SourceOpenStruct2, OF_CREATE | OF_WRITE); - } - ret = LZCopy(hSourceFile, hDestFile); - LZClose(hSourceFile); - LZClose(hDestFile); - if (ret <= 0) fprintf(stderr,"LZCopy failed: return is %d\n",ret); - return (ret <= 0); + if (argc < 3) + { + fprintf( stderr, "Usage: %s infile outfile\n", argv[0] ); + return 1; + } + + GetFullPathNameA( argv[1], sizeof(infile), infile, NULL ); + GetFullPathNameA( argv[2], sizeof(outfile), outfile, NULL ); + + if (!lstrcmpiA( infile, outfile )) + { + fprintf( stderr, "%s: can't expand file to itself\n", argv[0] ); + return 1; + } + if (!SetupGetFileCompressionInfoExA( infile, actual_name, sizeof(actual_name), NULL, NULL, NULL, &comp )) + { + fprintf( stderr, "%s: can't open input file %s\n", argv[0], infile ); + return 1; + } + + switch (comp) + { + case FILE_COMPRESSION_MSZIP: + { + if (!SetupIterateCabinetA( infile, 0, extract_callback, (PVOID)outfile )) + { + fprintf( stderr, "%s: cabinet extraction failed\n", argv[0] ); + return 1; + } + break; + } + case FILE_COMPRESSION_WINLZA: + { + INT hin, hout; + OFSTRUCT ofin, ofout; + LONG error; + + if ((hin = LZOpenFile( infile, &ofin, OF_READ )) < 0) + { + fprintf( stderr, "%s: can't open input file %s\n", argv[0], infile ); + return 1; + } + if ((hout = LZOpenFile( outfile, &ofout, OF_CREATE | OF_WRITE )) < 0) + { + LZClose( hin ); + fprintf( stderr, "%s: can't open output file %s\n", argv[0], outfile ); + return 1; + } + error = LZCopy( hin, hout ); + + LZClose( hin ); + LZClose( hout ); + + if (error < 0) + { + fprintf( stderr, "%s: LZCopy failed, error is %d\n", argv[0], error ); + return 1; + } + break; + } + default: + { + if (!CopyFileA( infile, outfile, FALSE )) + { + fprintf( stderr, "%s: CopyFileA failed\n", argv[0] ); + return 1; + } + break; + } + } + return ret; }