/*++ 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 #include #include #include #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; }