windows-nt/Source/XPSP1/NT/printscan/print/spooler/prtprocs/winprint/parsparm.c

294 lines
8.2 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1990-1998 Microsoft Corporation
All Rights Reserved
// @@BEGIN_DDKSPLIT
Module Name:
windows\spooler\prtprocs\winprint\formfeed.c
// @@END_DDKSPLIT
Abstract:
Table and routine to send formfeed to a printer.
// @@BEGIN_DDKSPLIT
Author:
Tommy Evans (vtommye) 10-21-1993
Revision History:
// @@END_DDKSPLIT
--*/
#include <windows.h>
#include <winspool.h>
#include <winsplp.h>
#include <wchar.h>
#include "winprint.h"
/** Constants for our various states **/
#define ST_KEY 0x01 /** Looking for a key **/
#define ST_VALUE 0x02 /** Looking for a value **/
#define ST_EQUAL 0x04 /** Looking for an = sign **/
#define ST_EQNODATA 0x08 /** Looking for equal w/ no data **/
#define ST_DELIM 0x10 /** Looking for a ; **/
#define ST_DMNODATA 0x20 /** Looking for a ; w/ no data **/
/*++
*******************************************************************
G e t K e y V a l u e
Routine Description:
Returns the value for a given key in the given
parameter string. The key/values are in the order of
KEY = VALUE;. The spaces are optional, the ';' is
required and MUST be present, directly after the value.
If the call fails, the return length will be 0 and the
return code will give the error. This routine is written
as a state machine, driven by the current character.
Arguments:
pParmString => Parameter string to parse
pKeyName => Key to search for
ValueType = type of value to return, string or ULONG
pDestLength => length of dest buffer on enter,
new length on exit.
pDestBuffer => area to store the key value
Return Value:
0 if okay
error if failed (from winerror.h)
*******************************************************************
--*/
USHORT
GetKeyValue(
IN PWCHAR pParmString,
IN PWCHAR pKeyName,
IN USHORT ValueType,
IN OUT PUSHORT pDestLength,
OUT PVOID pDestBuffer)
{
PWCHAR pKey, pVal, pValEnd = NULL;
WCHAR HoldChar;
USHORT State = ST_KEY; /** Start looking for a key **/
ULONG length;
/** If any of the pointers are bad, return error **/
if ((pParmString == NULL) ||
(pKeyName == NULL) ||
(pDestLength == NULL) ||
(pDestBuffer == NULL)) {
if (pDestLength) {
*pDestLength = 0;
}
return ERROR_INVALID_PARAMETER;
}
/**
If we are looking for a ULONG, make sure they passed
in a big enough buffer.
**/
if (ValueType == VALUE_ULONG) {
if (*pDestLength < sizeof(ULONG)) {
*pDestLength = 0;
return ERROR_INSUFFICIENT_BUFFER;
}
}
while (pParmString && *pParmString) {
/**
Update our state, if necessary, depending on
the current character.
**/
switch (*pParmString) {
/**
We got a white space. If we were looking for an equal
sign or delimiter, then note that we got a space. If
we run across more data, then we have an error.
**/
case (WCHAR)' ':
case (WCHAR)'\t':
/**
If we were looking for an equal sign,
check to see if this is the key they
wanted. If not, jump to the next key.
**/
if (State == ST_EQUAL) {
if (_wcsnicmp(pKey, pKeyName, lstrlen(pKeyName))) {
if (pParmString = wcschr(pParmString, (WCHAR)';')) {
pParmString++;
}
State = ST_KEY;
pValEnd = NULL;
break;
}
/** Looking for an equal sign with no more data **/
State = ST_EQNODATA;
}
else if (State == ST_DELIM) {
/** If this is the end of the value, remember it **/
if (!pValEnd) {
pValEnd = pParmString;
}
/** Now looking for a delimiter with no more data **/
State = ST_DMNODATA;
}
pParmString++;
break;
/**
Found an equal sign. If we were looking for one,
then great - we will then be looking for a value.
We will check to see if this is the key they wanted.
Otherwise, this is an error and we will start over
with the next key.
**/
case (WCHAR)'=':
if (State == ST_EQUAL) {
if (_wcsnicmp(pKey, pKeyName, lstrlen(pKeyName))) {
/** Error - go to next key **/
if (pParmString = wcschr(pParmString, (WCHAR)';')) {
pParmString++;
}
State = ST_KEY;
pValEnd = NULL;
break;
}
pParmString++;
State = ST_VALUE;
}
else {
/** Error - go to next key **/
if (pParmString = wcschr(pParmString, (WCHAR)';')) {
pParmString++;
}
State = ST_KEY;
pValEnd = NULL;
}
break;
// @@BEGIN_DDKSPLIT
/**
Found a delimeter. If this is what we were looking
for, great - we have a complete key/value pair.
**/
// @@END_DDKSPLIT
case (WCHAR)';':
if (State == ST_DELIM) {
if (!pValEnd) {
pValEnd = pParmString;
}
if (ValueType == VALUE_ULONG) {
if (!iswdigit(*pVal)) {
if (pParmString = wcschr(pParmString, (WCHAR)';')) {
pParmString++;
}
State = ST_KEY;
pValEnd = NULL;
break;
}
*(PULONG)pDestBuffer = wcstoul(pVal, NULL, 10);
return 0;
}
else if (ValueType == VALUE_STRING) {
/**
ASCIIZ the value to copy it out without
any trailing spaces.
**/
HoldChar = *pValEnd;
*pValEnd = (WCHAR)0;
/** Make sure the buffer is big enough **/
length = lstrlen(pVal);
if (*pDestLength < length) {
*pDestLength = 0;
return ERROR_INSUFFICIENT_BUFFER;
}
/**
Copy the data, restore the character where
we ASCIIZ'd the string, set up the length
and return.
**/
lstrcpy(pDestBuffer, pVal);
*pValEnd = HoldChar;
*(PULONG)pDestLength = length;
return 0;
}
}
else {
/** We weren't looking for a delimiter - next key **/
State = ST_KEY;
pValEnd = NULL;
pParmString++;
}
break;
/**
Found some data. If we had hit a space,
and were expecting a equal sign or delimiter,
this is an error.
**/
default:
if ((State == ST_EQNODATA) ||
(State == ST_DMNODATA)) {
if (pParmString = wcschr(pParmString, (WCHAR)';')) {
pParmString++;
}
State = ST_KEY;
pValEnd = NULL;
break;
}
else if (State == ST_KEY) {
pKey = pParmString;
State = ST_EQUAL;
}
else if (State == ST_VALUE) {
pVal = pParmString;
State = ST_DELIM;
}
pParmString++;
break;
} /* End switch */
} /* While parms data */
*pDestLength = 0;
return ERROR_NO_DATA;
}