MSIEXEC: fix command line parsing
Mike McCormack
mike at codeweavers.com
Fri Feb 4 04:32:37 CST 2005
ChangeLog:
* Fix msiexec's command line parsing.
* Don't allocate memory for fixed size structure.
* Remove a few non-tab indents, since the rest of the file uses tabbed
indent.
-------------- next part --------------
Index: programs/msiexec/msiexec.c
===================================================================
RCS file: /home/wine/wine/programs/msiexec/msiexec.c,v
retrieving revision 1.19
diff -u -p -r1.19 msiexec.c
--- programs/msiexec/msiexec.c 23 Nov 2004 12:12:31 -0000 1.19
+++ programs/msiexec/msiexec.c 4 Feb 2005 10:32:01 -0000
@@ -67,7 +67,7 @@ static void ShowUsage(int ExitCode)
ExitProcess(ExitCode);
}
-static BOOL GetProductCode(LPCSTR str, LPCSTR *PackageName, LPGUID *ProductCode)
+static BOOL GetProductCode(LPCSTR str, LPCSTR *PackageName, LPGUID ProductCode)
{
BOOL ret = FALSE;
int len = 0;
@@ -77,17 +77,13 @@ static BOOL GetProductCode(LPCSTR str, L
{
len = MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, 0);
wstr = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
- ret = (CLSIDFromString(wstr, *ProductCode) == NOERROR);
+ ret = (CLSIDFromString(wstr, ProductCode) == NOERROR);
HeapFree(GetProcessHeap(), 0, wstr);
wstr = NULL;
}
if(!ret)
- {
- HeapFree(GetProcessHeap(), 0, *ProductCode);
- *ProductCode = NULL;
*PackageName = str;
- }
return ret;
}
@@ -183,7 +179,98 @@ static void DllUnregisterServer(LPCSTR D
FreeLibrary(DllHandle);
}
-int main(int argc, char *argv[])
+/*
+ * state machine to break up the command line properly
+ */
+
+enum chomp_state
+{
+ cs_whitespace,
+ cs_token,
+ cs_quote
+};
+
+static int chomp( char *str )
+{
+ enum chomp_state state = cs_whitespace;
+ char *p, *out;
+ int count = 0, ignore;
+
+ for( p = str, out = str; *p; p++ )
+ {
+ ignore = 1;
+ switch( state )
+ {
+ case cs_whitespace:
+ switch( *p )
+ {
+ case ' ':
+ break;
+ case '"':
+ state = cs_quote;
+ count++;
+ break;
+ default:
+ count++;
+ ignore = 0;
+ state = cs_token;
+ }
+ break;
+
+ case cs_token:
+ switch( *p )
+ {
+ case '"':
+ state = cs_quote;
+ break;
+ case ' ':
+ state = cs_whitespace;
+ *out++ = 0;
+ break;
+ default:
+ ignore = 0;
+ }
+ break;
+
+ case cs_quote:
+ switch( *p )
+ {
+ case '"':
+ state = cs_token;
+ break;
+ default:
+ ignore = 0;
+ }
+ break;
+ }
+ if( !ignore )
+ *out++ = *p;
+ }
+
+ *out = 0;
+
+ return count;
+}
+
+void process_args( char *cmdline, int *pargc, char ***pargv )
+{
+ char **argv, *p = strdup(cmdline);
+ int i, n;
+
+ n = chomp( p );
+ argv = HeapAlloc(GetProcessHeap(), 0, sizeof (char*)*(n+1));
+ for( i=0; i<n; i++ )
+ {
+ argv[i] = p;
+ p += strlen(p) + 1;
+ }
+ argv[i] = NULL;
+
+ *pargc = n;
+ *pargv = argv;
+}
+
+int main(int argc, char **argv)
{
int i;
BOOL FunctionInstall = FALSE;
@@ -199,7 +286,7 @@ int main(int argc, char *argv[])
BOOL GotProductCode = FALSE;
LPCSTR PackageName = NULL;
- LPGUID ProductCode = HeapAlloc(GetProcessHeap(), 0, sizeof(GUID));
+ GUID ProductCode;
LPSTR Properties = HeapAlloc(GetProcessHeap(), 0, 1);
DWORD RepairMode = 0;
@@ -222,25 +309,28 @@ int main(int argc, char *argv[])
Properties[0] = 0;
Transforms[0] = 0;
+ process_args( GetCommandLineA(), &argc, &argv );
+
for(i = 1; i < argc; i++)
{
WINE_TRACE("argv[%d] = %s\n", i, argv[i]);
- if (!lstrcmpiA(argv[i], "/regserver"))
- {
- FunctionRegServer = TRUE;
- }
- else if (!lstrcmpiA(argv[i], "/unregserver") || !lstrcmpiA(argv[i], "/unregister"))
- {
- FunctionUnregServer = TRUE;
- }
+ if (!lstrcmpiA(argv[i], "/regserver"))
+ {
+ FunctionRegServer = TRUE;
+ }
+ else if (!lstrcmpiA(argv[i], "/unregserver") || !lstrcmpiA(argv[i], "/unregister"))
+ {
+ FunctionUnregServer = TRUE;
+ }
else if(!MSIEXEC_lstrncmpiA(argv[i], "/i", 2))
{
char *argvi = argv[i];
FunctionInstall = TRUE;
if(strlen(argvi) > 2)
argvi += 2;
- else {
+ else
+ {
i++;
if(i >= argc)
ShowUsage(1);
More information about the wine-patches
mailing list