Sample Code
Windows Driver Samples/ GenPrint Print Processor Sample/ C++/ parsparm.cpp/
/*++ Copyright (c) 1990-2003 Microsoft Corporation All Rights Reserved Abstract: Routine to parse parameters. --*/ #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_ PWSTR pParmString, _In_ PWSTR pKeyName, _In_ USHORT ValueType, _Inout_ PUSHORT pDestLength, _Out_writes_bytes_(*pDestLength) PVOID pDestBuffer) { PWCHAR pKey = NULL, pVal = NULL, pValEnd = NULL; WCHAR HoldChar; USHORT State = ST_KEY; /** Start looking for a key **/ ULONG length; HRESULT hr; /** 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 L' ': case L'\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, L';')) != NULL) { 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 L'=': if (State == ST_EQUAL) { if (_wcsnicmp(pKey, pKeyName, lstrlen(pKeyName))) { /** Error - go to next key **/ if ((pParmString = wcschr(pParmString, L';')) != NULL) { pParmString++; } State = ST_KEY; pValEnd = NULL; break; } pParmString++; State = ST_VALUE; } else { /** Error - go to next key **/ if ((pParmString = wcschr(pParmString, L';')) != NULL) { pParmString++; } State = ST_KEY; pValEnd = NULL; } break; case L';': if (State == ST_DELIM) { if (!pValEnd) { pValEnd = pParmString; } if (ValueType == VALUE_ULONG) { if (!iswdigit(*pVal)) { if ((pParmString = wcschr(pParmString, L';')) != NULL) { 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 = 0; /** Make sure the buffer is big enough **/ length = lstrlen(pVal); if (*pDestLength < (length+1) * sizeof(WCHAR) ) { *pDestLength = 0; return ERROR_INSUFFICIENT_BUFFER; } /** Copy the data, restore the character where we ASCIIZ'd the string, set up the length and return. **/ hr = StringCchCopy ( (LPWSTR)pDestBuffer, *pDestLength/sizeof(WCHAR), pVal); if ( FAILED(hr) ) { *pDestLength = 0; // // For the hr values returned by StringCchCopy, the following macro // is sufficient // return (USHORT) HRESULT_CODE(hr); } *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, L';')) != NULL) { 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; }
Our Services
-
What our customers say about us?
Read our customer testimonials to find out why our clients keep returning for their projects.
View Testimonials