/* * Copyright Likewise Software 2004-2009 * All rights reserved. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the license, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy * of the GNU Lesser General Public License along with this program. If * not, see . * * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING * TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU * LESSER GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT * license@likewisesoftware.com */ /* * Copyright (C) Likewise Software. All rights reserved. * * Module Name: * * reglex.c * * Abstract: * * Registry * * Registry .REG parser lexical analyzer * * Authors: Adam Bernstein (abernstein@likewise.com) */ #include "includes.h" DWORD RegLexOpen( PREGLEX_ITEM *ppLexHandle) { DWORD dwError = 0; DWORD indx = 0; PREGLEX_ITEM pLexHandle; dwError = RegAllocateMemory(sizeof(*pLexHandle), (LW_PVOID*)&pLexHandle); BAIL_ON_REG_ERROR(dwError); memset(pLexHandle, 0, sizeof(REGLEX_ITEM)); /* Initialize table of function pointers to parsing routines */ for (indx=0; indx<256; indx++) { pLexHandle->parseFuncArray[indx] = RegLexParseDefaultState; } pLexHandle->parseFuncArray[REGLEX_CHAR_INDEX('[')] = RegLexParseOpenBracket; pLexHandle->parseFuncArray[REGLEX_CHAR_INDEX(']')] = RegLexParseCloseBracket; pLexHandle->parseFuncArray[REGLEX_CHAR_INDEX('"')] = RegLexParseQuote; pLexHandle->parseFuncArray[REGLEX_CHAR_INDEX('@')] = RegLexParseAt; pLexHandle->parseFuncArray[REGLEX_CHAR_INDEX('=')] = RegLexParseEquals; pLexHandle->parseFuncArray[REGLEX_CHAR_INDEX(',')] = RegLexParseComma; pLexHandle->parseFuncArray[REGLEX_CHAR_INDEX('\\')] = RegLexParseBackslash; pLexHandle->parseFuncArray[REGLEX_CHAR_INDEX(':')] = RegLexParseColon; pLexHandle->parseFuncArray[REGLEX_CHAR_INDEX('\r')] = RegLexParseNewline; pLexHandle->parseFuncArray[REGLEX_CHAR_INDEX('\n')] = RegLexParseNewline; pLexHandle->parseFuncArray[REGLEX_CHAR_INDEX(' ')] = RegLexParseWhitespace; pLexHandle->parseFuncArray[REGLEX_CHAR_INDEX('\t')] = RegLexParseWhitespace; pLexHandle->parseFuncArray[REGLEX_CHAR_INDEX('#')] = RegLexParseComment; *ppLexHandle = pLexHandle; cleanup: return dwError; error: goto cleanup; } void RegLexClose( PREGLEX_ITEM pLexHandle) { if (pLexHandle) { if (pLexHandle->curToken.pszValue) { RegMemoryFree(pLexHandle->curToken.pszValue); pLexHandle->curToken.pszValue = NULL; } RegMemoryFree(pLexHandle); } } DWORD RegLexTokenToString( REGLEX_TOKEN token, PSTR tokenStr) { static char *tokenStrs[] = { "REGLEX_FIRST", "REGLEX_QUOTE_BEGIN", "REGLEX_QUOTE_END", "REGLEX_KEY_PREFIX", "REGLEX_KEY_SUFFIX", "REGLEX_KEY_NAME", "REGLEX_EQUALS", "REGLEX_COMMA", "REGLEX_HEXPAIR", "REGLEX_HEXPAIR_END", "REGLEX_PLAIN_TEXT", "REGLEX_REG_DWORD", /* dword: */ "REGLEX_REG_SZ", /* ="REG_SZ" */ "REGLEX_REG_BINARY", /* hex: */ "REGLEX_REG_NONE", /* hex(0): */ "REGLEX_REG_EXPAND_SZ", /* hex(2): */ "REGLEX_REG_MULTI_SZ", /* hex(7): */ "REGLEX_REG_RESOURCE_LIST", /* hex(8): */ "REGLEX_REG_FULL_RESOURCE_DESCRIPTOR", /* hex(9): */ "REGLEX_REG_RESOURCE_REQUIREMENTS_LIST", /* hex(a): */ "REGLEX_REG_QUADWORD", /* hex(b): */ "REGLEX_REG_KEY", "REGLEX_REG_NAME_DEFAULT", "REGLEX_REG_STRING_ARRAY", /* sza: */ }; if (token < (sizeof(tokenStrs)/sizeof(char *))) { strcpy(tokenStr, tokenStrs[token]); } else { sprintf(tokenStr, "ERROR: No Such Token %d", token); } return 0; } DWORD RegLexGetLineNumber( PREGLEX_ITEM pLexHandle, PDWORD pLineNum) { DWORD dwError = 0; BAIL_ON_INVALID_HANDLE(pLexHandle); *pLineNum = pLexHandle->curToken.lineNum + 1; cleanup: return dwError; error: goto cleanup; } DWORD RegLexGetAttribute( PREGLEX_ITEM pLexHandle, PDWORD pValueSize, PSTR *ppszTokenValue) { DWORD dwError = 0; BAIL_ON_INVALID_HANDLE(pLexHandle); BAIL_ON_INVALID_HANDLE(pValueSize); BAIL_ON_INVALID_HANDLE(ppszTokenValue); *ppszTokenValue = pLexHandle->curToken.pszValue; *pValueSize = pLexHandle->curToken.valueCursor; cleanup: return dwError; error: goto cleanup; } DWORD RegLexAppendChar( PREGLEX_ITEM lexHandle, CHAR inC) { DWORD dwError = 0; BAIL_ON_INVALID_HANDLE(lexHandle); PVOID pNewMemory = NULL; DWORD newValueSize = 0; if (lexHandle->curToken.valueCursor >= lexHandle->curToken.valueSize) { newValueSize = lexHandle->curToken.valueSize * 2; dwError = RegReallocMemory( lexHandle->curToken.pszValue, &pNewMemory, newValueSize + 1); /* Extra byte for string termination */ BAIL_ON_REG_ERROR(dwError); lexHandle->curToken.pszValue = pNewMemory; lexHandle->curToken.valueSize = newValueSize; } /* Append current character to string */ lexHandle->curToken.pszValue[lexHandle->curToken.valueCursor] = inC; lexHandle->curToken.valueCursor++; lexHandle->curToken.pszValue[lexHandle->curToken.valueCursor] = '\0'; cleanup: return dwError; error: goto cleanup; } DWORD RegLexParseQuote( PREGLEX_ITEM lexHandle, HANDLE ioHandle, CHAR inC) { DWORD dwError = 0; if (lexHandle->curToken.token == REGLEX_PLAIN_TEXT) { lexHandle->isToken = TRUE; dwError = RegIOUnGetChar(ioHandle, NULL); return dwError; } /* * Track state of "in quote" and "out quote" since * the same character begins/ends a string literal. * This is further complicated by escaped '\"' sequences * which are a literal quote in a quoted string. */ if (lexHandle->state == REGLEX_STATE_IN_KEY) { RegLexAppendChar(lexHandle, inC); } else if (lexHandle->state != REGLEX_STATE_IN_QUOTE) { /* Close quote found, done with current string */ lexHandle->curToken.token = REGLEX_QUOTE_BEGIN; lexHandle->state = REGLEX_STATE_IN_QUOTE; lexHandle->curToken.valueCursor = 0; lexHandle->curToken.pszValue[lexHandle->curToken.valueCursor] = '\0'; } else { lexHandle->isToken = TRUE; lexHandle->curToken.lineNum = lexHandle->parseLineNum; lexHandle->curToken.token = REGLEX_REG_SZ; lexHandle->state = REGLEX_STATE_INIT; return dwError; } return dwError; } DWORD RegLexParseOpenBracket( PREGLEX_ITEM lexHandle, HANDLE ioHandle, CHAR inC) { DWORD dwError = 0; if (lexHandle->curToken.token == REGLEX_PLAIN_TEXT) { lexHandle->isToken = TRUE; dwError = RegIOUnGetChar(ioHandle, NULL); return dwError; } if (lexHandle->state != REGLEX_STATE_IN_QUOTE) { lexHandle->curToken.token = REGLEX_KEY_PREFIX; if (lexHandle->state == REGLEX_STATE_IN_KEY) { /* This is a problem, can't have [ then another [ */ dwError = LWREG_ERROR_UNEXPECTED_TOKEN; } else { lexHandle->curToken.token = REGLEX_KEY_PREFIX; lexHandle->state = REGLEX_STATE_IN_KEY; lexHandle->curToken.valueCursor = 0; } } else { RegLexAppendChar(lexHandle, inC); } return dwError; } DWORD RegLexParseCloseBracket( PREGLEX_ITEM lexHandle, HANDLE ioHandle, CHAR inC) { DWORD dwError = 0; if (lexHandle->state != REGLEX_STATE_IN_QUOTE) { lexHandle->curToken.token = REGLEX_KEY_SUFFIX; if (lexHandle->state != REGLEX_STATE_IN_KEY) { /* This is a problem, can't have ] without a previous [ */ dwError = LWREG_ERROR_UNEXPECTED_TOKEN; } else { lexHandle->isToken = TRUE; lexHandle->curToken.lineNum = lexHandle->parseLineNum; lexHandle->curToken.token = REGLEX_REG_KEY; lexHandle->state = REGLEX_STATE_INIT; } } else { RegLexAppendChar(lexHandle, inC); } return dwError; } DWORD RegLexParseAt( PREGLEX_ITEM lexHandle, HANDLE ioHandle, CHAR inC) { DWORD dwError = 0; if (lexHandle->state != REGLEX_STATE_IN_QUOTE) { /* Default value for a registry key */ lexHandle->isToken = TRUE; lexHandle->curToken.lineNum = lexHandle->parseLineNum; lexHandle->curToken.token = REGLEX_KEY_NAME_DEFAULT; lexHandle->state = REGLEX_STATE_INIT; lexHandle->curToken.valueCursor = 0; RegLexAppendChar(lexHandle, inC); } else { RegLexAppendChar(lexHandle, inC); } return dwError; } DWORD RegLexParseEquals( PREGLEX_ITEM lexHandle, HANDLE ioHandle, CHAR inC) { DWORD dwError = 0; if (lexHandle->state != REGLEX_STATE_IN_QUOTE && lexHandle->state != REGLEX_STATE_IN_KEY) { lexHandle->isToken = TRUE; lexHandle->curToken.token = REGLEX_EQUALS; lexHandle->curToken.valueCursor = 0; } else { RegLexAppendChar(lexHandle, inC); } return dwError; } DWORD RegLexParseComma( PREGLEX_ITEM lexHandle, HANDLE ioHandle, CHAR inC) { DWORD dwError = 0; if (lexHandle->state != REGLEX_STATE_IN_QUOTE && lexHandle->state != REGLEX_STATE_IN_KEY) { if (lexHandle->curToken.valueCursor > 0 && lexHandle->curToken.valueCursor <=2) { lexHandle->isToken = TRUE; lexHandle->curToken.token = REGLEX_HEXPAIR; } else { /* Syntax error: Hex pair is only 2 characters */ dwError = LWREG_ERROR_UNEXPECTED_TOKEN; } } else { RegLexAppendChar(lexHandle, inC); } return dwError; } DWORD RegLexParseBackslash( PREGLEX_ITEM lexHandle, HANDLE ioHandle, CHAR inC) { DWORD dwError = 0; BOOLEAN eof = FALSE; if (lexHandle->state == REGLEX_STATE_BINHEX_STR || lexHandle->tokenDataType == REGLEX_REG_STRING_ARRAY) { /* Eat line continuation character when in BINHEX state */ dwError = RegIOGetChar(ioHandle, &inC, &eof); if (eof) { return dwError; } if (inC == '\r' || inC == '\n') { lexHandle->parseLineNum++; dwError = RegIOGetChar(ioHandle, &inC, &eof); if (eof) { return dwError; } if (inC != '\r' && inC != '\n') { dwError = RegIOUnGetChar(ioHandle, NULL); } } else { dwError = RegIOUnGetChar(ioHandle, NULL); } } else if (lexHandle->state == REGLEX_STATE_IN_QUOTE) { /* * Treat sequence '\C' (C=any character) as * the literal escaped character. Only handle backslashes * in this way when in quoted strings. When processing a * registry key value, this is a "bad thing" to do. * [HKEY_LOCAL_MACHINE\HARDWARE] * This processing in this case would be an escaped 'H', not * what is intended. */ dwError = RegIOGetChar(ioHandle, &inC, &eof); if (!eof) { RegLexAppendChar(lexHandle, inC); } } else { RegLexAppendChar(lexHandle, inC); } lexHandle->curToken.lineNum = lexHandle->parseLineNum; return dwError; } DWORD RegLexParseBinary( PREGLEX_ITEM lexHandle) { DWORD dwError = 0; /* Test for type prefix */ if (lexHandle->curToken.valueCursor > 0) { if (strcasecmp(lexHandle->curToken.pszValue, "dword") == 0 || strcasecmp(lexHandle->curToken.pszValue, "REG_DWORD") == 0) { lexHandle->curToken.token = REGLEX_REG_DWORD; lexHandle->state = REGLEX_STATE_DWORD; lexHandle->curToken.valueCursor = 0; } else if (strcasecmp(lexHandle->curToken.pszValue, "hex") == 0 || strcasecmp(lexHandle->curToken.pszValue, "REG_BINARY") == 0) { lexHandle->isToken = TRUE; lexHandle->curToken.token = REGLEX_REG_BINARY; lexHandle->state = REGLEX_STATE_BINHEX_STR; lexHandle->curToken.valueCursor = 0; } else if (strcasecmp(lexHandle->curToken.pszValue, "hex(0)") == 0 || strcasecmp(lexHandle->curToken.pszValue, "REG_NONE") == 0) { /* REG_NONE */ lexHandle->isToken = TRUE; lexHandle->curToken.token = REGLEX_REG_NONE; lexHandle->state = REGLEX_STATE_BINHEX_STR; lexHandle->curToken.valueCursor = 0; } else if (strcasecmp(lexHandle->curToken.pszValue, "hex(2)") == 0 || strcasecmp(lexHandle->curToken.pszValue, "REG_EXPAND_SZ") == 0) { /* REG_EXPAND_SZ */ lexHandle->isToken = TRUE; lexHandle->curToken.token = REGLEX_REG_EXPAND_SZ; lexHandle->state = REGLEX_STATE_BINHEX_STR; lexHandle->curToken.valueCursor = 0; } else if (strcasecmp(lexHandle->curToken.pszValue, "hex(7)") == 0 || strcasecmp(lexHandle->curToken.pszValue, "REG_MULTI_SZ") == 0) { /* REG_MULTI_SZ */ lexHandle->isToken = TRUE; lexHandle->curToken.token = REGLEX_REG_MULTI_SZ; lexHandle->state = REGLEX_STATE_BINHEX_STR; lexHandle->curToken.valueCursor = 0; } else if (strcasecmp(lexHandle->curToken.pszValue, "sza") == 0 || strcasecmp(lexHandle->curToken.pszValue, "REG_STRING_ARRAY") == 0) { /* REG_STRING_ARRAY * Similar to REG_MULTI_SZ (token type returned will be MULTI_SZ). * However, the parse format is: * "ValueName"=sza:"String 1" "String 2" \ * "String 3" "Last string" */ lexHandle->isToken = TRUE; lexHandle->curToken.token = REGLEX_REG_STRING_ARRAY; lexHandle->tokenDataType = REGLEX_REG_STRING_ARRAY; lexHandle->state = REGLEX_STATE_INIT; lexHandle->curToken.valueCursor = 0; } else if (strcasecmp(lexHandle->curToken.pszValue, "hex(8)") == 0 || strcasecmp(lexHandle->curToken.pszValue, "REG_RESOURCE_LIST") == 0) { /* REG_RESOURCE_LIST */ lexHandle->isToken = TRUE; lexHandle->curToken.token = REGLEX_REG_RESOURCE_LIST; lexHandle->state = REGLEX_STATE_BINHEX_STR; lexHandle->curToken.valueCursor = 0; } else if (strcasecmp(lexHandle->curToken.pszValue, "hex(9)") == 0 || strcasecmp(lexHandle->curToken.pszValue, "REG_FULL_RESOURCE_DESCRIPTOR") == 0) { /* REG_FULL_RESOURCE_DESCRIPTOR */ lexHandle->isToken = TRUE; lexHandle->curToken.token = REGLEX_REG_FULL_RESOURCE_DESCRIPTOR; lexHandle->state = REGLEX_STATE_BINHEX_STR; lexHandle->curToken.valueCursor = 0; } else if (strcasecmp(lexHandle->curToken.pszValue, "hex(a)") == 0 || strcasecmp(lexHandle->curToken.pszValue, "REG_RESOURCE_REQUIREMENTS_LIST") == 0) { /* REG_RESOURCE_REQUIREMENTS_LIST */ lexHandle->isToken = TRUE; lexHandle->curToken.token = REGLEX_REG_RESOURCE_REQUIREMENTS_LIST; lexHandle->state = REGLEX_STATE_BINHEX_STR; lexHandle->curToken.valueCursor = 0; } else if (strcasecmp(lexHandle->curToken.pszValue, "hex(b)") == 0 || strcasecmp(lexHandle->curToken.pszValue, "REG_QUADWORD") == 0) { /* REG_QUADWORD */ lexHandle->isToken = TRUE; lexHandle->curToken.token = REGLEX_REG_QUADWORD; lexHandle->state = REGLEX_STATE_BINHEX_STR; lexHandle->curToken.valueCursor = 0; } } if (lexHandle->isToken) { lexHandle->curToken.lineNum = lexHandle->parseLineNum; } return dwError; } DWORD RegLexParseColon( PREGLEX_ITEM lexHandle, HANDLE ioHandle, CHAR inC) { DWORD dwError = 0; if (lexHandle->state == REGLEX_STATE_IN_QUOTE || lexHandle->state == REGLEX_STATE_IN_KEY) { RegLexAppendChar(lexHandle, inC); return dwError; } return RegLexParseBinary(lexHandle); } DWORD RegLexParseNewline( PREGLEX_ITEM lexHandle, HANDLE ioHandle, CHAR inC) { DWORD dwError = 0; CHAR prevC = '\0'; BOOLEAN eof = 0; if (lexHandle->state != REGLEX_STATE_IN_QUOTE) { /* * Throw out CR when not in a quoted string. CR/LF * is still handled correctly by this treatment. */ if (inC == '\r') { return dwError; } } else { /* * Count CR/LF sequence in a quoted string as a single newline. * A bare CR is maintained, but not counted as a newline. */ if (inC == '\r') { RegLexAppendChar(lexHandle, inC); dwError = RegIOGetChar(ioHandle, &inC, &eof); if (eof) { return dwError; } if (inC == '\n') { RegLexAppendChar(lexHandle, inC); lexHandle->parseLineNum++; } else { dwError = RegIOUnGetChar(ioHandle, &inC); } } } if (lexHandle->state != REGLEX_STATE_IN_QUOTE) { lexHandle->parseLineNum++; } /* Emit the final token in a BINHEX_STR sequence */ if (lexHandle->state == REGLEX_STATE_BINHEX_STR) { /* Don't care about "\\n sequence */ dwError = RegIOGetPrevChar(ioHandle, &prevC); if (dwError == ERROR_SUCCESS && prevC == '\\') { return dwError; } lexHandle->isToken = TRUE; lexHandle->curToken.token = REGLEX_HEXPAIR_END; lexHandle->state = REGLEX_STATE_INIT; return dwError; } else if (lexHandle->tokenDataType == REGLEX_REG_STRING_ARRAY) { lexHandle->isToken = TRUE; lexHandle->tokenDataType = REGLEX_FIRST; return dwError; } else if (lexHandle->state == REGLEX_STATE_DWORD) { if (lexHandle->curToken.valueCursor == 8) { lexHandle->isToken = TRUE; lexHandle->curToken.token = REGLEX_REG_DWORD; return dwError; } else { dwError = LWREG_ERROR_UNEXPECTED_TOKEN; return dwError; } } else if ((lexHandle->state == REGLEX_STATE_INIT || lexHandle->state == REGLEX_PLAIN_TEXT) && lexHandle->curToken.valueCursor > 0) { /* * This is "junk" accumulated so far, since no valid token start * has been found before the current end-of-line. */ lexHandle->isToken = TRUE; lexHandle->curToken.token = REGLEX_PLAIN_TEXT; return dwError; } else { /* Syntax error case... */ /* Error needed */ } return dwError; } DWORD RegLexParseComment( PREGLEX_ITEM lexHandle, HANDLE ioHandle, CHAR inC) { DWORD dwError = 0; BOOLEAN eof = FALSE; if (lexHandle->state == REGLEX_STATE_IN_QUOTE || lexHandle->state == REGLEX_STATE_IN_KEY) { RegLexAppendChar(lexHandle, inC); } else { do { dwError = RegIOGetChar(ioHandle, &inC, &eof); } while (dwError == 0 && !eof && inC != '\n' && inC != '\r'); if (!eof && (inC == '\n' || inC == '\r')) { dwError = RegIOUnGetChar(ioHandle, NULL); } } return dwError; } DWORD RegLexParseWhitespace( PREGLEX_ITEM lexHandle, HANDLE ioHandle, CHAR inC) { DWORD dwError = 0; if (lexHandle->state == REGLEX_STATE_IN_QUOTE || lexHandle->state == REGLEX_STATE_IN_KEY) { RegLexAppendChar(lexHandle, inC); } else if (lexHandle->state == REGLEX_STATE_BINHEX_STR) { if (lexHandle->curToken.valueCursor > 0 && lexHandle->curToken.valueCursor <= 2) { lexHandle->isToken = TRUE; lexHandle->curToken.token = REGLEX_HEXPAIR; } } else { dwError = RegLexParseBinary(lexHandle); if (dwError || lexHandle->isToken) { return dwError; } if (lexHandle->curToken.token != REGLEX_FIRST) { lexHandle->isToken = TRUE; } } return dwError; } DWORD RegLexParseDefaultState( PREGLEX_ITEM lexHandle, HANDLE ioHandle, CHAR inC) { DWORD dwError = 0; if (lexHandle->state == REGLEX_STATE_IN_QUOTE || lexHandle->state == REGLEX_STATE_IN_KEY) { /* Append current character to string */ RegLexAppendChar(lexHandle, inC); } else if (lexHandle->state == REGLEX_STATE_BINHEX_STR) { if (inC == ' ' || inC == ',') { /* Eat white spaces in binhex strings */ lexHandle->isToken = TRUE; lexHandle->curToken.token = REGLEX_HEXPAIR; return dwError; } if (!isxdigit((int)inC)) { dwError = LWREG_ERROR_UNEXPECTED_TOKEN; return dwError; } if (lexHandle->curToken.valueCursor == 2) { dwError = RegIOUnGetChar(ioHandle, &inC); lexHandle->isToken = TRUE; lexHandle->curToken.token = REGLEX_HEXPAIR; return dwError; } RegLexAppendChar(lexHandle, inC); } else { RegLexAppendChar(lexHandle, inC); if (lexHandle->state != REGLEX_STATE_DWORD) { lexHandle->curToken.token = REGLEX_PLAIN_TEXT; } #ifdef _LW_DEBUG if (lexHandle->state != REGLEX_STATE_IN_QUOTE && lexHandle->state != REGLEX_STATE_IN_KEY && lexHandle->state != REGLEX_STATE_BINHEX_STR) { printf("<%c> <%02x>\n", inC, inC); } #endif } return dwError; } DWORD RegLexUnGetToken(PREGLEX_ITEM lexHandle) { DWORD dwError = 0; BAIL_ON_INVALID_HANDLE(lexHandle); if (lexHandle->prevToken.token) { if (lexHandle->prevToken.pszValue) { RegMemoryFree(lexHandle->prevToken.pszValue); lexHandle->prevToken.pszValue = NULL; } } lexHandle->prevToken = lexHandle->curToken; cleanup: return dwError; error: goto cleanup; } DWORD RegLexResetToken( PREGLEX_ITEM lexHandle) { DWORD dwError = 0; BAIL_ON_INVALID_HANDLE(lexHandle); lexHandle->state = REGLEX_FIRST; lexHandle->tokenDataType = REGLEX_FIRST; lexHandle->isToken = FALSE; memset(&lexHandle->curToken, 0, sizeof(lexHandle->curToken)); cleanup: return dwError; error: goto cleanup; } DWORD RegLexGetToken( HANDLE ioHandle, PREGLEX_ITEM lexHandle, PREGLEX_TOKEN pRetToken, PBOOLEAN pEof) { DWORD dwError = 0; CHAR inC = 0; BOOLEAN eof = FALSE; BAIL_ON_INVALID_HANDLE(ioHandle); BAIL_ON_INVALID_HANDLE(lexHandle); BAIL_ON_INVALID_HANDLE(pRetToken); *pRetToken = REGLEX_FIRST; if (lexHandle->isToken && lexHandle->curToken.token != REGLEX_HEXPAIR && lexHandle->curToken.token != REGLEX_REG_BINARY) { if ( lexHandle->curToken.token == REGLEX_REG_DWORD) { lexHandle->state = REGLEX_FIRST; } lexHandle->isToken = FALSE; lexHandle->curToken.token = REGLEX_FIRST; lexHandle->curToken.valueCursor = 0; } /* Return pushed back token, if one is present */ if (lexHandle->prevToken.token != REGLEX_FIRST) { lexHandle->curToken = lexHandle->prevToken; lexHandle->prevToken.token = REGLEX_FIRST; *pRetToken = lexHandle->curToken.token; return dwError; } if (lexHandle->state == REGLEX_STATE_INIT || lexHandle->curToken.token == REGLEX_HEXPAIR || lexHandle->curToken.token == REGLEX_HEXPAIR_END) { lexHandle->curToken.valueCursor = 0; } if (!lexHandle->curToken.pszValue) { /* Extra byte for string termination */ dwError = RegAllocateMemory(REGLEX_DEFAULT_SZ_LEN + 1, (LW_PVOID) &lexHandle->curToken.pszValue); BAIL_ON_REG_ERROR(dwError); lexHandle->curToken.valueCursor = 0; lexHandle->curToken.valueSize = REGLEX_DEFAULT_SZ_LEN; } do { lexHandle->isToken = FALSE; dwError = RegIOGetChar(ioHandle, &inC, &eof); if (eof) { if (lexHandle->curToken.token != REGLEX_FIRST && lexHandle->curToken.valueCursor > 0) { lexHandle->isToken = TRUE; *pRetToken = lexHandle->curToken.token; } else { if (lexHandle->state == REGLEX_STATE_IN_QUOTE) { dwError = LWREG_ERROR_INVALID_CONTEXT; } *pEof = eof; } break; } dwError = lexHandle->parseFuncArray[REGLEX_CHAR_INDEX(inC)]( lexHandle, ioHandle, inC); BAIL_ON_REG_ERROR(dwError); if (lexHandle->isToken) { *pRetToken = lexHandle->curToken.token; break; } } while (dwError == ERROR_SUCCESS); cleanup: return dwError; error: goto cleanup; }