Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

237 lines
5.5 KiB

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
argv.h
Abstract:
Implementation of CommandLineToArgv() API
Author:
Hakki T. Bostanci (hakkib) 06-Apr-2000
Revision History:
--*/
#ifndef __ARGV_H
#define __ARGV_H
#include <assert.h>
#ifndef ASSERT
#define ASSERT assert
#endif //ASSERT
PTSTR *
CommandLineToArgv(
PCTSTR pCmdLine,
int *pNumArgs
);
#ifdef IMPLEMENT_ARGV
//////////////////////////////////////////////////////////////////////////
//
// Parse_Cmdline
//
// Stolen directly from NT sources
//
void Parse_Cmdline (
LPCTSTR cmdstart,
LPTSTR*argv,
LPTSTR lpstr,
INT *numargs,
INT *numbytes
)
{
LPCTSTR p;
TCHAR c;
INT inquote; /* 1 = inside quotes */
INT copychar; /* 1 = copy char to *args */
WORD numslash; /* num of backslashes seen */
*numbytes = 0;
*numargs = 1; /* the program name at least */
/* first scan the program name, copy it, and count the bytes */
p = cmdstart;
if (argv)
*argv++ = lpstr;
/* A quoted program name is handled here. The handling is much
simpler than for other arguments. Basically, whatever lies
between the leading double-quote and next one, or a terminal null
character is simply accepted. Fancier handling is not required
because the program name must be a legal NTFS/HPFS file name.
Note that the double-quote characters are not copied, nor do they
contribute to numbytes. */
if (*p == TEXT('\"'))
{
/* scan from just past the first double-quote through the next
double-quote, or up to a null, whichever comes first */
while ((*(++p) != TEXT('\"')) && (*p != TEXT('\0')))
{
*numbytes += sizeof(TCHAR);
if (lpstr)
*lpstr++ = *p;
}
/* append the terminating null */
*numbytes += sizeof(TCHAR);
if (lpstr)
*lpstr++ = TEXT('\0');
/* if we stopped on a double-quote (usual case), skip over it */
if (*p == TEXT('\"'))
p++;
}
else
{
/* Not a quoted program name */
do {
*numbytes += sizeof(TCHAR);
if (lpstr)
*lpstr++ = *p;
c = (TCHAR) *p++;
} while (c > TEXT(' '));
if (c == TEXT('\0'))
{
p--;
}
else
{
if (lpstr)
*(lpstr - 1) = TEXT('\0');
}
}
inquote = 0;
/* loop on each argument */
for ( ; ; )
{
if (*p)
{
while (*p == TEXT(' ') || *p == TEXT('\t'))
++p;
}
if (*p == TEXT('\0'))
break; /* end of args */
/* scan an argument */
if (argv)
*argv++ = lpstr; /* store ptr to arg */
++*numargs;
/* loop through scanning one argument */
for ( ; ; )
{
copychar = 1;
/* Rules: 2N backslashes + " ==> N backslashes and begin/end quote
2N+1 backslashes + " ==> N backslashes + literal "
N backslashes ==> N backslashes */
numslash = 0;
while (*p == TEXT('\\'))
{
/* count number of backslashes for use below */
++p;
++numslash;
}
if (*p == TEXT('\"'))
{
/* if 2N backslashes before, start/end quote, otherwise
copy literally */
if (numslash % 2 == 0)
{
if (inquote)
if (p[1] == TEXT('\"'))
p++; /* Double quote inside quoted string */
else /* skip first quote char and copy second */
copychar = 0;
else
copychar = 0; /* don't copy quote */
inquote = !inquote;
}
numslash /= 2; /* divide numslash by two */
}
/* copy slashes */
while (numslash--)
{
if (lpstr)
*lpstr++ = TEXT('\\');
*numbytes += sizeof(TCHAR);
}
/* if at end of arg, break loop */
if (*p == TEXT('\0') || (!inquote && (*p == TEXT(' ') || *p == TEXT('\t'))))
break;
/* copy character into argument */
if (copychar)
{
if (lpstr)
*lpstr++ = *p;
*numbytes += sizeof(TCHAR);
}
++p;
}
/* null-terminate the argument */
if (lpstr)
*lpstr++ = TEXT('\0'); /* terminate string */
*numbytes += sizeof(TCHAR);
}
}
//////////////////////////////////////////////////////////////////////////
//
// CommandLineToArgv
//
PTSTR *
CommandLineToArgv(
PCTSTR pCmdLine,
int *pNumArgs
)
{
ASSERT(pNumArgs);
INT numbytes = 0;
Parse_Cmdline(pCmdLine, 0, 0, pNumArgs, &numbytes);
PTSTR *argv = (PTSTR *) LocalAlloc(
LMEM_FIXED | LMEM_ZEROINIT,
*pNumArgs * sizeof(PTSTR) + numbytes
);
if (argv)
{
Parse_Cmdline(
pCmdLine,
argv,
(PTSTR) ((PBYTE) argv + *pNumArgs * sizeof(PTSTR)),
pNumArgs,
&numbytes
);
}
return argv;
}
#endif //IMPLEMENT_ARGV
#endif //__ARGV_H