/* * 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: * * regparse.c * * Abstract: * * Registry * * Registry .REG parser * * Authors: Krishna Ganugapati (krishnag@likewisesoftware.com) * Adam Bernstein (abernstein@likewise.com) */ /* * Parser implementation: * * REG_KEY * | * +--------+---------+ * | | * Empty KeyValue * * * KeyValue * + * | * +----------+--------+-------+ * | | | | * NameDefault ValueName "=" TypeValue * ("@") (REG_SZ) * * * TypeValue * | * +----------+------------+------------+-------------+-----... * | | | | | * ValueNone ValueDword ValueBinary ValueString ValueMultiString * (REG_NONE) (REG_DWORD) (REG_BINARY) (REG_SZ) (REG_MULTI_SZ) * [hex(0)] [hex] [hex(7)] * * ...---+-----------------+-----------------------+----------... * | | | * ValueExpandSz ValueQuaword ValueResourceRequirementsList * (REG_EXPAND_SZ) (REG_QUADWORD) (REG_RESOURCE_REQUIREMENTS_LIST) * [hex(2)] [hex(b)] [hex(a)] * * * ...-------+-----------------------+-------------------------+ * | | | * ValueResourceList FullResourceDescriptor ValueStringArray * (REG_RESOURCE_LIST) (REG_FULL_RESOURCE_LIST) (REG_MULTI_SZ) * [hex(8)] [hex(9)] [sza] * * Note: All "hex()" types are TypeBinary, a sequence of binary * hex values. * * * TypeBinary * | * +-->(HexPair)---->(HexPairEnd) * | | * | | * +------+ */ #include "includes.h" void RegParseExternDataType( REGLEX_TOKEN valueType, PREG_DATA_TYPE externValueType) { if (!externValueType) { return; } switch (valueType) { case REGLEX_REG_DWORD: *externValueType = REG_DWORD; break; case REGLEX_REG_SZ: *externValueType = REG_SZ; break; case REGLEX_REG_BINARY: *externValueType = REG_BINARY; break; case REGLEX_REG_NONE: *externValueType = REG_NONE; break; case REGLEX_REG_EXPAND_SZ: *externValueType = REG_EXPAND_SZ; break; case REGLEX_REG_MULTI_SZ: *externValueType = REG_MULTI_SZ; break; case REGLEX_REG_RESOURCE_LIST: *externValueType = REG_RESOURCE_LIST; break; case REGLEX_REG_FULL_RESOURCE_DESCRIPTOR: *externValueType = REG_FULL_RESOURCE_DESCRIPTOR; break; case REGLEX_REG_RESOURCE_REQUIREMENTS_LIST: *externValueType = REG_RESOURCE_REQUIREMENTS_LIST; break; case REGLEX_REG_QUADWORD: *externValueType = REG_QWORD; break; case REGLEX_REG_KEY: *externValueType = REG_KEY; break; case REGLEX_KEY_NAME_DEFAULT: *externValueType = REG_KEY_DEFAULT; break; case REGLEX_PLAIN_TEXT: default: *externValueType = REG_PLAIN_TEXT; break; } } DWORD RegParseTypeNone( PREGPARSE_HANDLE parseHandle) { DWORD dwError = 0; parseHandle->dataType = REGLEX_REG_NONE; RegParseBinaryData(parseHandle); return dwError; } DWORD RegParseReAllocateData( PREGPARSE_HANDLE parseHandle) { DWORD dwError = 0; DWORD newValueSize = 0; PVOID pNewMemory = NULL; BAIL_ON_INVALID_POINTER(parseHandle); if (parseHandle->binaryDataLen >= parseHandle->binaryDataAllocLen) { newValueSize = parseHandle->binaryDataAllocLen * 2; dwError = RegReallocMemory( parseHandle->binaryData, &pNewMemory, newValueSize); BAIL_ON_REG_ERROR(dwError); parseHandle->binaryData = pNewMemory; parseHandle->binaryDataAllocLen = newValueSize; } cleanup: return dwError; error: goto cleanup; } DWORD RegParseAppendData( PREGPARSE_HANDLE parseHandle, PSTR pszHexValue) { DWORD dwError = 0; DWORD attrSize = 0; PSTR pszAttr = 0; DWORD binaryValue = 0; BAIL_ON_INVALID_POINTER(parseHandle); RegLexGetAttribute(parseHandle->lexHandle, &attrSize, &pszAttr); dwError = RegParseReAllocateData(parseHandle); BAIL_ON_REG_ERROR(dwError); switch(parseHandle->dataType) { case REGLEX_REG_DWORD: binaryValue = strtoul(pszHexValue, NULL, 16); memcpy(&parseHandle->binaryData[parseHandle->binaryDataLen], &binaryValue, sizeof(binaryValue)); parseHandle->binaryDataLen += sizeof(binaryValue); break; case REGLEX_REG_MULTI_SZ: case REGLEX_REG_BINARY: case REGLEX_REG_EXPAND_SZ: case REGLEX_REG_RESOURCE_REQUIREMENTS_LIST: case REGLEX_REG_RESOURCE_LIST: case REGLEX_REG_FULL_RESOURCE_DESCRIPTOR: case REGLEX_REG_QUADWORD: case REGLEX_REG_NONE: /* Need to enforce only 2 bytes are being converted */ binaryValue = strtoul(pszHexValue, NULL, 16); parseHandle->binaryData[parseHandle->binaryDataLen] = binaryValue; parseHandle->binaryDataLen++; break; default: break; } cleanup: return dwError; error: goto cleanup; } void RegParsePrintBinaryData( PUCHAR binaryData, DWORD binaryDataLen) { int i; for (i=0; ibinaryDataLen = 0; RegParseExternDataType(parseHandle->dataType, &parseHandle->registryEntry.type); switch (parseHandle->dataType) { case REGLEX_REG_MULTI_SZ: dataName = "MultiStringValue"; break; case REGLEX_REG_BINARY: dataName = "Binary"; break; case REGLEX_REG_EXPAND_SZ: dataName = "ExpandString"; break; case REGLEX_REG_RESOURCE_REQUIREMENTS_LIST: dataName = "ResourceRequirementsList"; break; case REGLEX_REG_RESOURCE_LIST: dataName = "ResourceList"; break; case REGLEX_REG_FULL_RESOURCE_DESCRIPTOR: dataName = "FullResourceDescriptor"; break; case REGLEX_REG_QUADWORD: dataName = "Quadword"; break; case REGLEX_REG_NONE: dataName = "REG_NONE"; break; default: break; } do { dwError = RegLexGetToken(parseHandle->ioHandle, parseHandle->lexHandle, &token, &eof); if (eof) { return dwError; } RegLexGetAttribute(parseHandle->lexHandle, &attrSize, &pszAttr); RegLexGetLineNumber(parseHandle->lexHandle, &lineNum); RegLexTokenToString(token, tokenName); if (token == REGLEX_HEXPAIR) { RegParseAppendData(parseHandle, parseHandle->lexHandle->curToken.pszValue); } else if (token == REGLEX_HEXPAIR_END) { if (parseHandle->lexHandle->curToken.valueCursor == 0) { return dwError; } RegParseAppendData(parseHandle, parseHandle->lexHandle->curToken.pszValue); parseHandle->registryEntry.valueLen = parseHandle->binaryDataLen; parseHandle->registryEntry.value = parseHandle->binaryData; return dwError; } else { printf("RegParseType%s: ERROR (syntax error) type '%s' " "unknown line=%d\n\n", dataName, tokenName, lineNum); return dwError; } } while (!eof); cleanup: return dwError; error: goto cleanup; } DWORD RegParseTypeBinary( PREGPARSE_HANDLE parseHandle) { DWORD dwError = 0; RegParseBinaryData(parseHandle); return dwError; } DWORD RegParseTypeExpandString( PREGPARSE_HANDLE parseHandle) { DWORD dwError = 0; RegParseBinaryData(parseHandle); return dwError; } DWORD RegParseTypeQuadWord( PREGPARSE_HANDLE parseHandle) { DWORD dwError = 0; RegParseBinaryData(parseHandle); return dwError; } DWORD RegParseTypeFullResDescriptor( PREGPARSE_HANDLE parseHandle) { DWORD dwError = 0; RegParseBinaryData(parseHandle); return dwError; } DWORD RegParseTypeResourceReqList( PREGPARSE_HANDLE parseHandle) { DWORD dwError = 0; RegParseBinaryData(parseHandle); return dwError; } DWORD RegParseTypeResourceList( PREGPARSE_HANDLE parseHandle) { DWORD dwError = 0; RegParseBinaryData(parseHandle); return dwError; } DWORD RegParseTypeDword( PREGPARSE_HANDLE parseHandle) { DWORD attrSize = 0; DWORD lineNum = 0; DWORD dwError = 0; PSTR pszAttr = 0; CHAR tokenName[256]; if (parseHandle->dataType == REGLEX_REG_DWORD) { RegLexGetAttribute(parseHandle->lexHandle, &attrSize, &pszAttr); RegLexGetLineNumber(parseHandle->lexHandle, &lineNum); parseHandle->binaryDataLen = 0; RegParseAppendData(parseHandle, pszAttr); } else { printf("RegParseTypeDword: ERROR (syntax error) type '%s' " "unknown line=%d\n\n", tokenName, lineNum); } return dwError; } DWORD RegParseTypeMultiStringValue( PREGPARSE_HANDLE parseHandle) { DWORD attrSize = 0; DWORD lineNum = 0; DWORD dwError = 0; PSTR pszAttr = 0; RegLexGetAttribute(parseHandle->lexHandle, &attrSize, &pszAttr); RegLexGetLineNumber(parseHandle->lexHandle, &lineNum); RegParseBinaryData(parseHandle); return dwError; } DWORD RegParseTypeStringArrayValue( PREGPARSE_HANDLE parseHandle) { DWORD attrSize = 0; DWORD lineNum = 0; DWORD dwError = 0; DWORD dwStrLen = 0; PSTR pszAttr = 0; REGLEX_TOKEN token = 0; BOOLEAN eof = FALSE; RegLexGetAttribute(parseHandle->lexHandle, &attrSize, &pszAttr); RegLexGetLineNumber(parseHandle->lexHandle, &lineNum); dwError = RegLexGetToken(parseHandle->ioHandle, parseHandle->lexHandle, &token, &eof); if (eof) { return eof; } while (token == REGLEX_REG_SZ || (token == REGLEX_PLAIN_TEXT && strcmp(pszAttr, "\\")==0)) { RegLexGetAttribute(parseHandle->lexHandle, &attrSize, &pszAttr); RegLexGetLineNumber(parseHandle->lexHandle, &lineNum); if (token == REGLEX_REG_SZ) { dwStrLen = strlen(pszAttr) + 1; while (parseHandle->binaryDataAllocLen < dwStrLen) { dwError = RegParseReAllocateData(parseHandle); BAIL_ON_REG_ERROR(dwError); } memcpy(&parseHandle->binaryData[parseHandle->binaryDataLen], pszAttr, dwStrLen); parseHandle->binaryDataLen += dwStrLen; } dwError = RegLexGetToken(parseHandle->ioHandle, parseHandle->lexHandle, &token, &eof); RegLexGetAttribute(parseHandle->lexHandle, &attrSize, &pszAttr); } parseHandle->binaryData[parseHandle->binaryDataLen++] = '\0'; parseHandle->binaryData[parseHandle->binaryDataLen++] = '\0'; RegLexUnGetToken(parseHandle->lexHandle); parseHandle->dataType = REGLEX_REG_MULTI_SZ; parseHandle->lexHandle->isToken = TRUE; RegParseExternDataType(parseHandle->dataType, &parseHandle->registryEntry.type); cleanup: return dwError; error: goto cleanup; } DWORD RegParseInstallCallback( PREGPARSE_HANDLE parseHandle, PFN_REG_CALLBACK parseCallback, HANDLE userContext, PDWORD indexCallback) { DWORD dwError = 0; DWORD i = 0; BAIL_ON_INVALID_POINTER(parseHandle); BAIL_ON_INVALID_POINTER(parseCallback); for (i=0; i < sizeof(parseHandle->parseCallback.callbacks) / sizeof(REGPARSE_CALLBACK_ENTRY); i++) { if (!parseHandle->parseCallback.callbacks[i].used) { parseHandle->parseCallback.callbacks[i].pfnCallback = parseCallback; parseHandle->parseCallback.callbacks[i].userContext = userContext; parseHandle->parseCallback.callbacks[i].used = TRUE; parseHandle->parseCallback.entries++; if (indexCallback) { *indexCallback = i; } break; } } cleanup: return dwError; error: goto cleanup; } DWORD RegParseRemoveCallback( PREGPARSE_HANDLE parseHandle, DWORD indexCallback) { DWORD dwError = 0; BAIL_ON_INVALID_POINTER(parseHandle); if (indexCallback >= 0 && (indexCallback < sizeof(parseHandle->parseCallback.callbacks) / sizeof(REGPARSE_CALLBACK_ENTRY)) && parseHandle->parseCallback.callbacks[indexCallback].used) { parseHandle->parseCallback.callbacks[indexCallback].used = FALSE; parseHandle->parseCallback.callbacks[indexCallback].pfnCallback = NULL; parseHandle->parseCallback.callbacks[indexCallback].userContext = NULL; parseHandle->parseCallback.entries--; } cleanup: return dwError; error: goto cleanup; } DWORD RegParseRunCallbacks( PREGPARSE_HANDLE parseHandle) { DWORD dwError = 0; DWORD i = 0; BAIL_ON_INVALID_POINTER(parseHandle); DWORD calledCallback = 0; if (parseHandle->parseCallback.entries == 0) { return dwError; } for (i=0; calledCallback < parseHandle->parseCallback.entries; i++) { if (parseHandle->parseCallback.callbacks[i].used) { parseHandle->parseCallback.callbacks[i].pfnCallback( &parseHandle->registryEntry, parseHandle->parseCallback.callbacks[i].userContext); calledCallback++; } } cleanup: return dwError; error: goto cleanup; } DWORD RegParseTypeStringValue( PREGPARSE_HANDLE parseHandle) { DWORD attrSize = 0; DWORD lineNum = 0; DWORD dwError = 0; PSTR pszAttr = 0; RegLexGetAttribute(parseHandle->lexHandle, &attrSize, &pszAttr); RegLexGetLineNumber(parseHandle->lexHandle, &lineNum); if (parseHandle->parseCallback.entries > 0) { parseHandle->registryEntry.value = pszAttr; parseHandle->registryEntry.valueLen = attrSize; } return dwError; } void RegParsePrintASCII( UCHAR *buf, DWORD buflen) { int i; char c; printf("PrintASCII: '"); for (i=0; iioHandle, parseHandle->lexHandle, &token, &eof); if (eof) { return dwError; } RegLexGetAttribute(parseHandle->lexHandle, &attrSize, &pszAttr); RegLexGetLineNumber(parseHandle->lexHandle, &lineNum); parseHandle->registryEntry.lineNumber = lineNum; parseHandle->dataType = REGLEX_FIRST; parseHandle->binaryDataLen = 0; switch(token) { case REGLEX_KEY_NAME_DEFAULT: parseHandle->valueType = REGLEX_KEY_NAME_DEFAULT; parseHandle->dataType = REGLEX_REG_SZ; RegParseTypeStringValue(parseHandle); break; case REGLEX_REG_SZ: parseHandle->dataType = REGLEX_REG_SZ; RegParseTypeStringValue(parseHandle); break; case REGLEX_REG_MULTI_SZ: parseHandle->dataType = REGLEX_REG_MULTI_SZ; RegParseTypeMultiStringValue(parseHandle); break; case REGLEX_REG_STRING_ARRAY: parseHandle->dataType = REGLEX_REG_STRING_ARRAY; RegParseTypeStringArrayValue(parseHandle); break; case REGLEX_REG_DWORD: parseHandle->dataType = REGLEX_REG_DWORD; RegParseTypeDword(parseHandle); break; case REGLEX_REG_BINARY: parseHandle->dataType = REGLEX_REG_BINARY; RegParseTypeBinary(parseHandle); break; case REGLEX_REG_EXPAND_SZ: parseHandle->dataType = REGLEX_REG_EXPAND_SZ; RegParseTypeExpandString(parseHandle); break; case REGLEX_REG_QUADWORD: parseHandle->dataType = REGLEX_REG_QUADWORD; RegParseTypeQuadWord(parseHandle); break; case REGLEX_REG_RESOURCE_REQUIREMENTS_LIST: parseHandle->dataType = REGLEX_REG_RESOURCE_REQUIREMENTS_LIST; RegParseTypeResourceReqList(parseHandle); break; case REGLEX_REG_RESOURCE_LIST: parseHandle->dataType = REGLEX_REG_RESOURCE_LIST; RegParseTypeResourceList(parseHandle); break; case REGLEX_REG_FULL_RESOURCE_DESCRIPTOR: parseHandle->dataType = REGLEX_REG_FULL_RESOURCE_DESCRIPTOR; RegParseTypeFullResDescriptor(parseHandle); break; case REGLEX_REG_NONE: parseHandle->dataType = REGLEX_REG_NONE; RegParseTypeNone(parseHandle); break; default: printf("RegParseTypeValue: ERROR (syntax error) type '%s' " "unknown line=%d\n\n", tokenName, lineNum); break; } RegLexResetToken(parseHandle->lexHandle); return 0; } DWORD RegParseKeyValue( PREGPARSE_HANDLE parseHandle) { DWORD attrSize = 0; DWORD lineNum = 0; DWORD dwError = 0; BOOLEAN eof = FALSE; PSTR pszAttr = 0; REGLEX_TOKEN token = 0; dwError = RegLexGetToken( parseHandle->ioHandle, parseHandle->lexHandle, &token, &eof); if (eof) { return dwError; } RegLexGetAttribute(parseHandle->lexHandle, &attrSize, &pszAttr); RegLexGetLineNumber(parseHandle->lexHandle, &lineNum); parseHandle->registryEntry.lineNumber = lineNum; if (token == REGLEX_EQUALS) { if (pszAttr) { if (parseHandle->registryEntry.valueName) { RegMemoryFree(parseHandle->registryEntry.valueName); parseHandle->registryEntry.valueName = NULL; } dwError = RegCStringDuplicate(&parseHandle->registryEntry.valueName, pszAttr); BAIL_ON_INVALID_POINTER(parseHandle->registryEntry.valueName); } } else { printf("RegParseKeyValue: ERROR (syntax error) line=%d\n\n", lineNum); return dwError; } dwError = RegParseTypeValue(parseHandle); if (dwError == 0) { RegLexGetLineNumber(parseHandle->lexHandle, &lineNum); RegParseExternDataType(parseHandle->dataType, &parseHandle->registryEntry.type); RegParseExternDataType(parseHandle->valueType, &parseHandle->registryEntry.valueType); if (parseHandle->dataType != REGLEX_REG_SZ) { parseHandle->registryEntry.valueLen = parseHandle->binaryDataLen; parseHandle->registryEntry.value = parseHandle->binaryData; } } RegParseRunCallbacks(parseHandle); cleanup: return dwError; error: goto cleanup; } DWORD RegParseKey( PREGPARSE_HANDLE parseHandle, REGLEX_TOKEN token) { DWORD attrSize = 0; DWORD lineNum = 0; DWORD dwError = 0; BOOLEAN eof = FALSE; PSTR pszAttr = 0; do { RegLexGetAttribute(parseHandle->lexHandle, &attrSize, &pszAttr); RegLexGetLineNumber(parseHandle->lexHandle, &lineNum); /* * Test for empty registry subkey case first */ if (token == REGLEX_REG_KEY) { /* Empty subkey, with no value, free any previous value */ if (parseHandle->registryEntry.valueName) { RegMemoryFree(parseHandle->registryEntry.valueName); parseHandle->registryEntry.valueName = NULL; } parseHandle->dataType = REGLEX_REG_KEY; parseHandle->valueType = REGLEX_REG_NONE; if (pszAttr) { if (parseHandle->registryEntry.keyName) { RegMemoryFree(parseHandle->registryEntry.keyName); } dwError = RegCStringDuplicate( &parseHandle->registryEntry.keyName, pszAttr); BAIL_ON_INVALID_POINTER(parseHandle->registryEntry.keyName); } if (parseHandle->parseCallback.entries > 0) { parseHandle->registryEntry.lineNumber = lineNum; RegParseExternDataType(parseHandle->dataType, &parseHandle->registryEntry.type); RegParseExternDataType(parseHandle->valueType, &parseHandle->registryEntry.valueType); parseHandle->registryEntry.valueLen = 0; parseHandle->registryEntry.value = NULL; RegParseRunCallbacks(parseHandle); } return dwError; } else if (token == REGLEX_REG_SZ || token == REGLEX_KEY_NAME_DEFAULT) { parseHandle->valueType = token; RegLexGetAttribute(parseHandle->lexHandle, &attrSize, &pszAttr); RegParseKeyValue(parseHandle); } else if (token == REGLEX_PLAIN_TEXT) { parseHandle->dataType = REGLEX_PLAIN_TEXT; parseHandle->valueType = REGLEX_REG_SZ; if (parseHandle->parseCallback.entries > 0) { parseHandle->registryEntry.lineNumber = lineNum; RegParseExternDataType(parseHandle->dataType, &parseHandle->registryEntry.type); RegParseExternDataType(parseHandle->valueType, &parseHandle->registryEntry.valueType); parseHandle->registryEntry.value = pszAttr; parseHandle->registryEntry.valueLen = attrSize; RegParseRunCallbacks(parseHandle); } } else { /* * Maybe treat as a syntax error here. May be in infinite loop * for poorly formed entries. */ parseHandle->valueType = token; RegLexGetAttribute(parseHandle->lexHandle, &attrSize, &pszAttr); RegParseKeyValue(parseHandle); printf("Unhandled token '%s'!\n", pszAttr); return dwError; } dwError = RegLexGetToken(parseHandle->ioHandle, parseHandle->lexHandle, &token, &eof); if (eof) { return dwError; } } while (!eof); cleanup: return dwError; error: goto cleanup; } DWORD RegParseOpen( PSTR pszRegFileName, PFN_REG_CALLBACK parseCallback, HANDLE userContext, HANDLE *ppNewHandle) { HANDLE ioHandle = NULL; PREGLEX_ITEM lexHandle = NULL; PREGPARSE_HANDLE newHandle = NULL; DWORD dwError = 0; void *binaryData = NULL; dwError = RegIOOpen(pszRegFileName, &ioHandle); BAIL_ON_REG_ERROR(dwError); dwError = RegLexOpen(&lexHandle); BAIL_ON_REG_ERROR(dwError); dwError = RegAllocateMemory(sizeof(REGPARSE_HANDLE), (LW_PVOID) &newHandle); BAIL_ON_INVALID_POINTER(newHandle); dwError = RegAllocateMemory(REGPARSE_BUFSIZ, &binaryData); BAIL_ON_INVALID_POINTER(newHandle); newHandle->ioHandle = ioHandle; newHandle->lexHandle = lexHandle; if (parseCallback) { RegParseInstallCallback(newHandle, parseCallback, userContext, NULL); } newHandle->binaryData = binaryData; newHandle->binaryDataAllocLen = REGPARSE_BUFSIZ; newHandle->binaryDataLen = 0; *ppNewHandle = (HANDLE) newHandle; cleanup: return dwError; error: goto cleanup; } void RegParseClose( HANDLE pHandle) { PREGPARSE_HANDLE pParseHandle = (PREGPARSE_HANDLE) pHandle; if (pParseHandle) { if (pParseHandle->registryEntry.keyName) { RegMemoryFree(pParseHandle->registryEntry.keyName); } if (pParseHandle->binaryData) { RegMemoryFree(pParseHandle->binaryData); } RegLexClose(pParseHandle->lexHandle); RegIOClose(pParseHandle->ioHandle); RegMemoryFree(pParseHandle); } } DWORD RegParseRegistry( HANDLE pHandle) { DWORD dwError = 0; REGLEX_TOKEN token = 0; BOOLEAN eof = 0; PREGPARSE_HANDLE parseHandle = (PREGPARSE_HANDLE) pHandle; do { dwError = RegLexGetToken(parseHandle->ioHandle, parseHandle->lexHandle, &token, &eof); if (!eof) { dwError = RegParseKey(parseHandle, token); } } while (!eof); return dwError; }