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=…
==============================================================================
--- 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