Author: akhaldi Date: Wed Dec 4 16:18:44 2013 New Revision: 61220
URL: http://svn.reactos.org/svn/reactos?rev=61220&view=rev Log: [EXTRAC32] * Sync with Wine 1.7.1. CORE-7469
Modified: trunk/reactos/base/applications/extrac32/CMakeLists.txt trunk/reactos/base/applications/extrac32/extrac32.c trunk/reactos/media/doc/README.WINE
Modified: trunk/reactos/base/applications/extrac32/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/extrac32/... ============================================================================== --- trunk/reactos/base/applications/extrac32/CMakeLists.txt [iso-8859-1] (original) +++ trunk/reactos/base/applications/extrac32/CMakeLists.txt [iso-8859-1] Wed Dec 4 16:18:44 2013 @@ -1,9 +1,6 @@ -
add_executable(extrac32 extrac32.c) - target_link_libraries(extrac32 wine) - set_module_type(extrac32 win32gui UNICODE) add_importlibs(extrac32 shell32 setupapi shlwapi user32 msvcrt kernel32 ntdll) add_cd_file(TARGET extrac32 DESTINATION reactos/system32 FOR all)
Modified: trunk/reactos/base/applications/extrac32/extrac32.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/extrac32/... ============================================================================== --- trunk/reactos/base/applications/extrac32/extrac32.c [iso-8859-1] (original) +++ trunk/reactos/base/applications/extrac32/extrac32.c [iso-8859-1] Wed Dec 4 16:18:44 2013 @@ -24,12 +24,29 @@ #include <shellapi.h> #include <setupapi.h> #include <shlwapi.h> +#include <shlobj.h> #include <wine/unicode.h> #include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(extrac32);
static BOOL force_mode; +static BOOL show_content; + +static void create_target_directory(LPWSTR Target) +{ + WCHAR dir[MAX_PATH]; + int res; + + strcpyW(dir, Target); + *PathFindFileNameW(dir) = 0; /* Truncate file name */ + if(!PathIsDirectoryW(dir)) + { + res = SHCreateDirectoryExW(NULL, dir, NULL); + if(res != ERROR_SUCCESS && res != ERROR_ALREADY_EXISTS) + WINE_ERR("Can't create directory: %s\n", wine_dbgstr_w(dir)); + } +}
static UINT WINAPI ExtCabCallback(PVOID Context, UINT Notification, UINT_PTR Param1, UINT_PTR Param2) { @@ -40,9 +57,37 @@ { case SPFILENOTIFY_FILEINCABINET: pInfo = (FILE_IN_CABINET_INFO_W*)Param1; - lstrcpyW(pInfo->FullTargetName, (LPCWSTR)Context); - lstrcatW(pInfo->FullTargetName, pInfo->NameInCabinet); - return FILEOP_DOIT; + if(show_content) + { + FILETIME ft; + SYSTEMTIME st; + CHAR date[12], time[12], buf[2 * MAX_PATH]; + int count; + DWORD dummy; + + /* DosDate and DosTime already represented at local time */ + DosDateTimeToFileTime(pInfo->DosDate, pInfo->DosTime, &ft); + FileTimeToSystemTime(&ft, &st); + GetDateFormatA(0, 0, &st, "MM'-'dd'-'yyyy", date, sizeof date); + GetTimeFormatA(0, 0, &st, "HH':'mm':'ss", time, sizeof time); + count = wsprintfA(buf, "%s %s %c%c%c%c %15u %S\n", date, time, + pInfo->DosAttribs & FILE_ATTRIBUTE_ARCHIVE ? 'A' : '-', + pInfo->DosAttribs & FILE_ATTRIBUTE_HIDDEN ? 'H' : '-', + pInfo->DosAttribs & FILE_ATTRIBUTE_READONLY ? 'R' : '-', + pInfo->DosAttribs & FILE_ATTRIBUTE_SYSTEM ? 'S' : '-', + pInfo->FileSize, pInfo->NameInCabinet); + WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, count, &dummy, NULL); + return FILEOP_SKIP; + } + else + { + lstrcpyW(pInfo->FullTargetName, (LPCWSTR)Context); + lstrcatW(pInfo->FullTargetName, pInfo->NameInCabinet); + /* SetupIterateCabinet() doesn't create full path to target by itself, + so we should do it manually */ + create_target_directory(pInfo->FullTargetName); + return FILEOP_DOIT; + } case SPFILENOTIFY_FILEEXTRACTED: pFilePaths = (FILEPATHS_W*)Param1; WINE_TRACE("Extracted %s\n", wine_dbgstr_w(pFilePaths->Target)); @@ -82,6 +127,98 @@ CopyFileW(source, destination, FALSE); }
+static LPWSTR *get_extrac_args(LPWSTR cmdline, int *pargc) +{ + enum {OUTSIDE_ARG, INSIDE_ARG, INSIDE_QUOTED_ARG} state; + LPWSTR str; + int argc; + LPWSTR *argv; + int max_argc = 16; + BOOL new_arg; + + WINE_TRACE("cmdline: %s\n", wine_dbgstr_w(cmdline)); + str = HeapAlloc(GetProcessHeap(), 0, (strlenW(cmdline) + 1) * sizeof(WCHAR)); + if(!str) return NULL; + strcpyW(str, cmdline); + argv = HeapAlloc(GetProcessHeap(), 0, (max_argc + 1) * sizeof(LPWSTR)); + if(!argv) + { + HeapFree(GetProcessHeap(), 0, str); + return NULL; + } + + /* Split command line to separate arg-strings and fill argv */ + state = OUTSIDE_ARG; + argc = 0; + while(*str) + { + new_arg = FALSE; + /* Check character */ + if(isspaceW(*str)) /* white space */ + { + if(state == INSIDE_ARG) + { + state = OUTSIDE_ARG; + *str = 0; + } + } + else if(*str == '"') /* double quote */ + switch(state) + { + case INSIDE_QUOTED_ARG: + state = OUTSIDE_ARG; + *str = 0; + break; + case INSIDE_ARG: + *str = 0; + /* Fall through */ + case OUTSIDE_ARG: + if(!*++str) continue; + state = INSIDE_QUOTED_ARG; + new_arg = TRUE; + break; + } + else /* regular character */ + if(state == OUTSIDE_ARG) + { + state = INSIDE_ARG; + new_arg = TRUE; + } + + /* Add new argv entry, if need */ + if(new_arg) + { + if(argc >= max_argc - 1) + { + /* Realloc argv here because there always should be + at least one reserved cell for terminating NULL */ + max_argc *= 2; + argv = HeapReAlloc(GetProcessHeap(), 0, argv, + (max_argc + 1) * sizeof(LPWSTR)); + if(!argv) + { + HeapFree(GetProcessHeap(), 0, str); + return NULL; + } + } + argv[argc++] = str; + } + + str++; + } + + argv[argc] = NULL; + *pargc = argc; + + if(TRACE_ON(extrac32)) + { + int i; + for(i = 0; i < argc; i++) + WINE_TRACE("arg %d: %s\n", i, wine_dbgstr_w(argv[i])); + } + return argv; +} + int PASCAL wWinMain(HINSTANCE hInstance, HINSTANCE prev, LPWSTR cmdline, int show) { LPWSTR *argv; @@ -89,15 +226,20 @@ int i; WCHAR check, cmd = 0; WCHAR path[MAX_PATH]; - WCHAR backslash[] = {'\',0}; LPCWSTR cabfile = NULL;
path[0] = 0; - argv = CommandLineToArgvW(cmdline, &argc); + + /* Do not use CommandLineToArgvW() or __wgetmainargs() to parse + * command line for this program. It should treat each quote as argument + * delimiter. This doesn't match with behavior of mentioned functions. + * Do not use args provided by wmain() for the same reason. + */ + argv = get_extrac_args(cmdline, &argc);
if(!argv) { - WINE_ERR("Bad command line arguments\n"); + WINE_ERR("Command line parsing failed\n"); return 0; }
@@ -105,7 +247,7 @@ for(i = 0; i < argc; i++) { /* Get cabfile */ - if (argv[i][0] != '/') + if (argv[i][0] != '/' && argv[i][0] != '-') { if (!cabfile) { @@ -130,9 +272,6 @@ return 0; break; case 'C': - if (cmd) return 0; - cmd = check; - break; case 'E': case 'D': if (cmd) return 0; @@ -152,11 +291,14 @@ if (!GetFullPathNameW(argv[i], MAX_PATH, path, NULL)) return 0; } - - if (!path[0]) + else if (!cmd) + /* Use extraction by default if names of required files presents */ + cmd = i < argc ? 'E' : 'D'; + + if (cmd == 'E' && !path[0]) GetCurrentDirectoryW(MAX_PATH, path);
- lstrcatW(path, backslash); + PathAddBackslashW(path);
/* Execute the specified command */ switch(cmd) @@ -165,15 +307,14 @@ /* Copy file */ copy_file(cabfile, path); break; + case 'D': + /* Display CAB archive */ + show_content = TRUE; + /* Fall through */ case 'E': /* Extract CAB archive */ extract(cabfile, path); break; - case 0: - case 'D': - /* Display CAB archive */ - WINE_FIXME("/D not implemented\n"); - break; } return 0; }
Modified: trunk/reactos/media/doc/README.WINE URL: http://svn.reactos.org/svn/reactos/trunk/reactos/media/doc/README.WINE?rev=6... ============================================================================== --- trunk/reactos/media/doc/README.WINE [iso-8859-1] (original) +++ trunk/reactos/media/doc/README.WINE [iso-8859-1] Wed Dec 4 16:18:44 2013 @@ -230,7 +230,7 @@ reactos/base/applications/cmdutils/wmic # Synced to Wine-1.7.1 reactos/base/applications/cmdutils/xcopy # Synced to Wine-1.7.1 reactos/base/applications/games/winmine # Forked at Wine-1_3_5 -reactos/base/applications/extrac32 # Autosync +reactos/base/applications/extrac32 # Synced to Wine-1.7.1 reactos/base/applications/iexplore # Synced to Wine-1.5.26 reactos/base/applications/notepad # Forked at Wine-20041201 reactos/base/applications/regedit # Out of sync