mirror of
https://github.com/mirror/processhacker
synced 2026-06-08 16:03:24 +00:00
command line parsing progress
git-svn-id: svn://svn.code.sf.net/p/processhacker/code@2910 21ef857c-d57f-4fe0-8362-d861dc6d29cd
This commit is contained in:
@@ -1860,20 +1860,17 @@ NTSTATUS PhIsExecutablePacked(
|
||||
typedef struct _PH_COMMAND_LINE_OPTION
|
||||
{
|
||||
ULONG Id;
|
||||
PWSTR LongName;
|
||||
PWSTR ShortName;
|
||||
PWSTR Name;
|
||||
BOOLEAN AcceptArgument;
|
||||
|
||||
PWSTR Description;
|
||||
} PH_COMMAND_LINE_OPTION, *PPH_COMMAND_LINE_OPTION;
|
||||
|
||||
typedef VOID (NTAPI *PPH_COMMAND_LINE_CALLBACK)(
|
||||
__in PPH_COMMAND_LINE_OPTION Option,
|
||||
__in PPH_STRING Value,
|
||||
__in_opt PPH_STRING Value,
|
||||
__in PVOID Context
|
||||
);
|
||||
|
||||
VOID PhParseCommandLine(
|
||||
BOOLEAN PhParseCommandLine(
|
||||
__in PPH_STRINGREF CommandLine,
|
||||
__in PPH_COMMAND_LINE_OPTION Options,
|
||||
__in ULONG NumberOfOptions,
|
||||
|
||||
@@ -313,6 +313,27 @@ FORCEINLINE PH_STRINGREF PhCreateStringRef(
|
||||
return string;
|
||||
}
|
||||
|
||||
FORCEINLINE INT PhStringRefCompare2(
|
||||
__in PPH_STRINGREF String1,
|
||||
__in PWSTR String2,
|
||||
__in BOOLEAN IgnoreCase
|
||||
)
|
||||
{
|
||||
if (!IgnoreCase)
|
||||
return wcsncmp(String1->Buffer, String2, String1->Length / sizeof(WCHAR));
|
||||
else
|
||||
return wcsnicmp(String1->Buffer, String2, String1->Length / sizeof(WCHAR));
|
||||
}
|
||||
|
||||
FORCEINLINE BOOLEAN PhStringRefEquals2(
|
||||
__in PPH_STRINGREF String1,
|
||||
__in PWSTR String2,
|
||||
__in BOOLEAN IgnoreCase
|
||||
)
|
||||
{
|
||||
return PhStringRefCompare2(String1, String2, IgnoreCase) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Unicode string object.
|
||||
*/
|
||||
|
||||
@@ -1724,7 +1724,7 @@ CleanupExit:
|
||||
return status;
|
||||
}
|
||||
|
||||
VOID PhParseCommandLine(
|
||||
BOOLEAN PhParseCommandLine(
|
||||
__in PPH_STRINGREF CommandLine,
|
||||
__in PPH_COMMAND_LINE_OPTION Options,
|
||||
__in ULONG NumberOfOptions,
|
||||
@@ -1733,19 +1733,156 @@ VOID PhParseCommandLine(
|
||||
)
|
||||
{
|
||||
ULONG i;
|
||||
ULONG j;
|
||||
ULONG length;
|
||||
PPH_STRING_BUILDER stringBuilder;
|
||||
BOOLEAN cont;
|
||||
|
||||
ULONG optionNameLength;
|
||||
PH_STRINGREF optionName;
|
||||
PPH_COMMAND_LINE_OPTION option;
|
||||
PPH_STRING_BUILDER optionValueBuilder;
|
||||
|
||||
BOOLEAN inEscape;
|
||||
BOOLEAN inQuote;
|
||||
BOOLEAN endOfValue;
|
||||
|
||||
if (CommandLine->Length == 0)
|
||||
return TRUE;
|
||||
|
||||
stringBuilder = PhCreateStringBuilder(10);
|
||||
i = 0;
|
||||
length = CommandLine->Length / 2;
|
||||
|
||||
while (TRUE)
|
||||
while (i < length)
|
||||
{
|
||||
// Check for an option specifier.
|
||||
if (i < length)
|
||||
// Skip spaces.
|
||||
while (i < length && CommandLine->Buffer[i] == ' ')
|
||||
i++;
|
||||
|
||||
if (option && option->AcceptArgument)
|
||||
{
|
||||
|
||||
// Read the value.
|
||||
|
||||
optionValueBuilder = PhCreateStringBuilder(10);
|
||||
inEscape = FALSE;
|
||||
inQuote = FALSE;
|
||||
endOfValue = FALSE;
|
||||
|
||||
for (; i < length; i++)
|
||||
{
|
||||
if (inEscape)
|
||||
{
|
||||
switch (CommandLine->Buffer[i])
|
||||
{
|
||||
case '\\':
|
||||
case '\"':
|
||||
case '\'':
|
||||
PhStringBuilderAppendEx(
|
||||
optionValueBuilder,
|
||||
&CommandLine->Buffer[i],
|
||||
2
|
||||
);
|
||||
break;
|
||||
default:
|
||||
// Unknown escape. Append both the backslash and
|
||||
// escape character.
|
||||
PhStringBuilderAppendEx(
|
||||
optionValueBuilder,
|
||||
&CommandLine->Buffer[i - 1],
|
||||
4
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
inEscape = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (CommandLine->Buffer[i])
|
||||
{
|
||||
case '\"':
|
||||
case '\'':
|
||||
if (!inQuote)
|
||||
inQuote = TRUE;
|
||||
else
|
||||
inQuote = FALSE;
|
||||
|
||||
break;
|
||||
default:
|
||||
if (CommandLine->Buffer[i] == ' ' && !inQuote)
|
||||
{
|
||||
endOfValue = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
PhStringBuilderAppendEx(
|
||||
optionValueBuilder,
|
||||
&CommandLine->Buffer[i],
|
||||
2
|
||||
);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (endOfValue)
|
||||
break;
|
||||
}
|
||||
|
||||
cont = Callback(option, optionValueBuilder->String, Context);
|
||||
|
||||
PhDereferenceObject(optionValueBuilder);
|
||||
|
||||
if (!cont)
|
||||
return TRUE;
|
||||
|
||||
option = NULL;
|
||||
}
|
||||
else if (CommandLine->Buffer[i] == '-')
|
||||
{
|
||||
// Read the option (only alphanumeric characters allowed).
|
||||
|
||||
optionNameLength = 0;
|
||||
|
||||
// Skip the dash.
|
||||
i++;
|
||||
|
||||
for (; i < length; i++)
|
||||
{
|
||||
if (!iswalnum(CommandLine->Buffer[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
optionName.Buffer = &CommandLine->Buffer[i - optionNameLength];
|
||||
optionName.Length = optionNameLength * 2;
|
||||
|
||||
// Find the option descriptor.
|
||||
|
||||
option = NULL;
|
||||
|
||||
for (j = 0; j < NumberOfOptions; j++)
|
||||
{
|
||||
if (PhStringRefEquals2(&optionName, Options[i].Name, FALSE))
|
||||
{
|
||||
option = &Options[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!option)
|
||||
return FALSE;
|
||||
|
||||
if (!option->AcceptArgument)
|
||||
{
|
||||
cont = Callback(option, NULL, Context);
|
||||
|
||||
if (!cont)
|
||||
return TRUE;
|
||||
|
||||
option = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user