NTSTATUS _MemCreateHkeyReply( IN PMEMREG_NODE pSubKey, OUT PHKEY phkResult) { NTSTATUS status = 0; PREG_KEY_HANDLE phKeyResponse = NULL; PREG_KEY_CONTEXT pRetKey = NULL; PREG_KEY_HANDLE *phKeyResult = (PREG_KEY_HANDLE *)phkResult; status = LW_RTL_ALLOCATE( (PVOID*)&phKeyResponse, PREG_KEY_HANDLE, sizeof(*phKeyResponse)); BAIL_ON_NT_STATUS(status); status = LW_RTL_ALLOCATE( (PVOID*)&pRetKey, PREG_KEY_CONTEXT, sizeof(*pRetKey)); BAIL_ON_NT_STATUS(status); pRetKey->hNode = pSubKey; phKeyResponse->pKey = pRetKey; *phKeyResult = phKeyResponse; cleanup: return status; error: LWREG_SAFE_FREE_MEMORY(pRetKey); LWREG_SAFE_FREE_MEMORY(phKeyResponse); goto cleanup; }
NTSTATUS MemRegStoreChangeNodeValue( IN PMEMREG_VALUE pNodeValue, IN const BYTE *pData, DWORD cbData) { NTSTATUS status = 0; if (pNodeValue->Data) { LWREG_SAFE_FREE_MEMORY(pNodeValue->Data); pNodeValue->DataLen = 0; } status = LW_RTL_ALLOCATE( (PVOID*) &pNodeValue->Data, BYTE, sizeof(*pData) * cbData); BAIL_ON_NT_STATUS(status); memcpy(pNodeValue->Data, pData, cbData); pNodeValue->DataLen = cbData; cleanup: return status; error: LWREG_SAFE_FREE_MEMORY(pNodeValue->Data); goto cleanup; }
NTSTATUS MemRegStoreClose( IN PMEMREG_NODE hRootNode) { NTSTATUS status = 0; /* Validate is actually root of registry */ if (!hRootNode || hRootNode->NodeType != 1) { status = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(status); } if (hRootNode->Name) { LWREG_SAFE_FREE_MEMORY(hRootNode->Name); } LWREG_SAFE_FREE_MEMORY(hRootNode); cleanup: return status; error: goto cleanup; }
static VOID _MemDbFreeWC16Array( IN PWSTR *ppwszArray) { DWORD index = 0; if (ppwszArray) { for (index=0; ppwszArray[index]; index++) { LWREG_SAFE_FREE_MEMORY(ppwszArray[index]); } LWREG_SAFE_FREE_MEMORY(ppwszArray); } }
NTSTATUS SqliteCacheKeySecurityDescriptor_inlock( IN PREG_KEY_CONTEXT pKeyResult ) { NTSTATUS status = 0; PSECURITY_DESCRIPTOR_RELATIVE pSecurityDescriptor = NULL; ULONG ulSecDescRelLen = 0; if (pKeyResult->bHasSdInfo) goto cleanup; status = RegDbGetKeyAclByKeyId(ghCacheConnection, pKeyResult->qwId, &pKeyResult->qwSdId, &pSecurityDescriptor, &ulSecDescRelLen); BAIL_ON_NT_STATUS(status); status = SqliteSetKeySecurityDescriptor_inlock(pKeyResult, pSecurityDescriptor, ulSecDescRelLen); BAIL_ON_NT_STATUS(status); cleanup: LWREG_SAFE_FREE_MEMORY(pSecurityDescriptor); return status; error: pKeyResult->bHasSdInfo = FALSE; goto cleanup; }
DWORD RegLexAppendChar( PREGLEX_ITEM lexHandle, CHAR inC) { DWORD dwError = 0; PVOID pNewMemory = NULL; DWORD newValueSize = 0; BAIL_ON_INVALID_HANDLE(lexHandle); 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: LWREG_SAFE_FREE_MEMORY(pNewMemory); goto cleanup; }
NTSTATUS SqliteGetParentKeyName( PCWSTR pwszInputString, wchar16_t c, PWSTR *ppwszOutputString ) { NTSTATUS status = STATUS_SUCCESS; // Do not free PCWSTR pwszFound = NULL; PWSTR pwszOutputString = NULL; BAIL_ON_NT_INVALID_STRING(pwszInputString); pwszFound = RegStrrchr(pwszInputString, c); if (pwszFound) { status = LW_RTL_ALLOCATE((PVOID*)&pwszOutputString, wchar16_t, sizeof(*pwszOutputString)* (pwszFound - pwszInputString +1)); BAIL_ON_NT_STATUS(status); memcpy(pwszOutputString, pwszInputString,(pwszFound - pwszInputString) * sizeof(*pwszOutputString)); } *ppwszOutputString = pwszOutputString; cleanup: return status; error: LWREG_SAFE_FREE_MEMORY(pwszOutputString); goto cleanup; }
LWMsgStatus RegSrvIpcGetKeySecurity( LWMsgCall* pCall, const LWMsgParams* pIn, LWMsgParams* pOut, void* data ) { NTSTATUS status = 0; PREG_IPC_GET_KEY_SECURITY_REQ pReq = pIn->data; PREG_IPC_GET_KEY_SECURITY_RES pRegResp = NULL; PSECURITY_DESCRIPTOR_RELATIVE pSecDescRel = NULL; PREG_IPC_STATUS pStatus = NULL; HKEY hKey = NULL; status = RegSrvIpcGetHandleData(pCall, pReq->hKey, &hKey); BAIL_ON_NT_STATUS(status); if (pReq->bRetSecurityDescriptor && pReq->Length) { status = LW_RTL_ALLOCATE((PVOID*)&pSecDescRel, VOID, pReq->Length); BAIL_ON_NT_STATUS(status); } status = RegSrvGetKeySecurity(RegSrvIpcGetSessionData(pCall), hKey, pReq->SecurityInformation, pSecDescRel, &pReq->Length); if (!status) { status = LW_RTL_ALLOCATE((PVOID*)&pRegResp, REG_IPC_GET_KEY_SECURITY_RES, sizeof(*pRegResp)); BAIL_ON_NT_STATUS(status); pRegResp->SecurityDescriptor = pSecDescRel; pSecDescRel = NULL; pRegResp->Length = pReq->Length; pOut->tag = REG_R_GET_KEY_SECURITY; pOut->data = pRegResp; } else { status = RegSrvIpcCreateError(status, &pStatus); BAIL_ON_NT_STATUS(status); pOut->tag = REG_R_ERROR; pOut->data = pStatus; } cleanup: LWREG_SAFE_FREE_MEMORY(pSecDescRel); return MAP_REG_ERROR_IPC(status); error: goto cleanup; }
LWMsgStatus RegSrvIpcEnumRootKeysW( LWMsgCall* pCall, const LWMsgParams* pIn, LWMsgParams* pOut, void* data ) { NTSTATUS status = 0; PREG_IPC_ENUM_ROOTKEYS_RESPONSE pRegResp = NULL; PREG_IPC_STATUS pStatus = NULL; PWSTR* ppwszRootKeyNames = NULL; DWORD dwNumRootKeys = 0; int iCount = 0; status = RegSrvEnumRootKeysW( RegSrvIpcGetSessionData(pCall), &ppwszRootKeyNames, &dwNumRootKeys ); if (!status) { status = LW_RTL_ALLOCATE((PVOID*)&pRegResp, REG_IPC_ENUM_ROOTKEYS_RESPONSE, sizeof(*pRegResp)); BAIL_ON_NT_STATUS(status); pRegResp->ppwszRootKeyNames = ppwszRootKeyNames; ppwszRootKeyNames = NULL; pRegResp->dwNumRootKeys = dwNumRootKeys; pOut->tag = REG_R_ENUM_ROOT_KEYSW; pOut->data = pRegResp; } else { status = RegSrvIpcCreateError(status, &pStatus); BAIL_ON_NT_STATUS(status); pOut->tag = REG_R_ERROR; pOut->data = pStatus; } cleanup: if (ppwszRootKeyNames) { for (iCount=0; iCount<dwNumRootKeys; iCount++) { LWREG_SAFE_FREE_MEMORY(ppwszRootKeyNames[iCount]); } ppwszRootKeyNames = NULL; } return MAP_REG_ERROR_IPC(status); error: goto cleanup; }
void RegFreeStringBufferContents( REG_STRING_BUFFER *pBuffer) { LWREG_SAFE_FREE_MEMORY(pBuffer->pszBuffer); pBuffer->sLen = 0; pBuffer->sCapacity = 0; }
static NTSTATUS _MemRegDuplicateWC16Array( IN PWSTR *ppwszArray, OUT PWSTR **pppwszCopyArray) { NTSTATUS status = 0; PWSTR *ppwszRetStrings = NULL; PWSTR pwszRetString = NULL; DWORD index = 0; /* Count number of entries first */ for (index=0; ppwszArray[index]; index++) ; index++; /* Allocate array of pointers to wide strings */ status = LW_RTL_ALLOCATE( (PVOID*) &ppwszRetStrings, PWSTR, sizeof(PWSTR) * index); BAIL_ON_NT_STATUS(status); memset(ppwszRetStrings, 0, sizeof(PWSTR) * index); /* Duplicate the strings */ for (index=0; ppwszArray[index]; index++) { status = LwRtlWC16StringDuplicate( &pwszRetString, ppwszArray[index]); BAIL_ON_NT_STATUS(status); ppwszRetStrings[index] = pwszRetString; pwszRetString = NULL; } *pppwszCopyArray = ppwszRetStrings; cleanup: return status; error: LWREG_SAFE_FREE_MEMORY(ppwszRetStrings); LWREG_SAFE_FREE_MEMORY(pwszRetString); goto cleanup; }
VOID MemProvider_Shutdown( PREGPROV_PROVIDER_FUNCTION_TABLE pFnTable ) { REG_DB_CONNECTION regDbConn = {0}; NTSTATUS status = 0; PWSTR pwszRootKey = NULL; BOOLEAN bInLock = FALSE; PREG_DB_CONNECTION pMemRegRoot = MemRegRoot(); MEMDB_FILE_EXPORT_CTX exportCtx = {0}; exportCtx.hNode = pMemRegRoot->pMemReg; LWREG_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &pMemRegRoot->lock); status = MemDbExportToFile(&exportCtx); BAIL_ON_REG_ERROR(status); regDbConn.pMemReg = pMemRegRoot->pMemReg; status = MemDbClose(®DbConn); BAIL_ON_REG_ERROR(status); BAIL_ON_REG_ERROR(RegMapErrnoToLwRegError( pthread_mutex_destroy(&pMemRegRoot->ExportMutex))); BAIL_ON_REG_ERROR(RegMapErrnoToLwRegError( pthread_mutex_destroy(&pMemRegRoot->ExportMutexStop))); BAIL_ON_REG_ERROR(RegMapErrnoToLwRegError( pthread_cond_destroy(&pMemRegRoot->ExportCond))); BAIL_ON_REG_ERROR(RegMapErrnoToLwRegError( pthread_cond_destroy(&pMemRegRoot->ExportCondStop))); LWREG_UNLOCK_RWMUTEX(bInLock, &pMemRegRoot->lock); BAIL_ON_REG_ERROR(RegMapErrnoToLwRegError( pthread_rwlock_destroy(&pMemRegRoot->lock))); cleanup: LWREG_SAFE_FREE_MEMORY(pMemRegRoot->ExportCtx); LWREG_SAFE_FREE_MEMORY(pMemRegRoot); LWREG_SAFE_FREE_MEMORY(pwszRootKey); return; error: goto cleanup; }
NTSTATUS MemRegStoreCreateNodeSdFromSddl( IN PSTR SecurityDescriptor, IN ULONG SecurityDescriptorLen, PMEMREG_NODE_SD *ppRetNodeSd) { NTSTATUS status = 0; PMEMREG_NODE_SD pNodeSd = NULL; if (!SecurityDescriptor || SecurityDescriptorLen == 0) { status = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(status); } status = LW_RTL_ALLOCATE((PVOID*) &pNodeSd, PMEMREG_NODE_SD, sizeof(*pNodeSd)); BAIL_ON_NT_STATUS(status); /* Add security descriptor to current key node */ status = RtlAllocateSecurityDescriptorFromSddlCString( &pNodeSd->SecurityDescriptor, &pNodeSd->SecurityDescriptorLen, SecurityDescriptor, SDDL_REVISION_1); BAIL_ON_NT_STATUS(status); pNodeSd->SecurityDescriptorAllocated = TRUE; *ppRetNodeSd = pNodeSd; cleanup: return status; error: LWREG_SAFE_FREE_MEMORY(pNodeSd->SecurityDescriptor); LWREG_SAFE_FREE_MEMORY(pNodeSd); goto cleanup; }
void SqliteSafeFreeKeyHandle_inlock( PREG_KEY_HANDLE pKeyHandle ) { if (!pKeyHandle) { return; } SqliteReleaseKeyContext_inlock(pKeyHandle->pKey); memset(pKeyHandle, 0, sizeof(*pKeyHandle)); LWREG_SAFE_FREE_MEMORY(pKeyHandle); }
// This can be called when a DB lock and active key list lock are both held NTSTATUS SqliteDeleteKeyInternal_inlock_inDblock( IN HANDLE handle, IN PCWSTR pwszKeyName ) { NTSTATUS status = STATUS_SUCCESS; PWSTR pwszParentKeyName = NULL; PREG_KEY_HANDLE pKeyHandle = NULL; // Do not free PREG_KEY_CONTEXT pKeyCtx = NULL; status = SqliteDeleteActiveKey_inlock((PCWSTR)pwszKeyName); BAIL_ON_NT_STATUS(status); status = SqliteOpenKeyInternal_inlock_inDblock(handle, pwszKeyName, 0, &pKeyHandle); BAIL_ON_NT_STATUS(status); BAIL_ON_NT_INVALID_POINTER(pKeyHandle); pKeyCtx = pKeyHandle->pKey; BAIL_ON_INVALID_KEY_CONTEXT(pKeyCtx); // Delete all the values of this key status = RegDbDeleteKey_inlock(ghCacheConnection, pKeyCtx->qwId, pKeyCtx->qwSdId, pwszKeyName); BAIL_ON_NT_STATUS(status); status = SqliteGetParentKeyName(pwszKeyName, '\\',&pwszParentKeyName); BAIL_ON_NT_STATUS(status); if (!LW_IS_NULL_OR_EMPTY_STR(pwszParentKeyName)) { SqliteCacheResetParentKeySubKeyInfo_inlock(pwszParentKeyName); } cleanup: SqliteSafeFreeKeyHandle_inlock(pKeyHandle); LWREG_SAFE_FREE_MEMORY(pwszParentKeyName); return status; error: goto cleanup; }
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('{')] = RegLexParseOpenBrace; pLexHandle->parseFuncArray[REGLEX_CHAR_INDEX('}')] = RegLexParseCloseBrace; pLexHandle->parseFuncArray[REGLEX_CHAR_INDEX('"')] = RegLexParseQuote; pLexHandle->parseFuncArray[REGLEX_CHAR_INDEX('-')] = RegLexParseDash; 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: LWREG_SAFE_FREE_MEMORY(pLexHandle); goto cleanup; }
NTSTATUS SqliteCreateKeyHandle( IN PACCESS_TOKEN pToken, IN ACCESS_MASK AccessDesired, IN PREG_KEY_CONTEXT pKey, OUT PREG_KEY_HANDLE* ppKeyHandle ) { NTSTATUS status = STATUS_SUCCESS; PREG_KEY_HANDLE pKeyHandle = NULL; ACCESS_MASK AccessGranted = 0; BAIL_ON_INVALID_KEY_CONTEXT(pKey); status = RegSrvAccessCheckKey(pToken, pKey->pSecurityDescriptor, pKey->ulSecDescLength, AccessDesired, &AccessGranted); if (STATUS_NO_TOKEN == status) { status = 0; AccessGranted = 0; } BAIL_ON_NT_STATUS(status); status = LW_RTL_ALLOCATE((PVOID*)&pKeyHandle, REG_KEY_HANDLE, sizeof(*pKeyHandle)); BAIL_ON_NT_STATUS(status); pKeyHandle->AccessGranted = AccessGranted; pKeyHandle->pKey = pKey; *ppKeyHandle = pKeyHandle; cleanup: return status; error: LWREG_SAFE_FREE_MEMORY(pKeyHandle); goto cleanup; }
DWORD RegLexResetToken( PREGLEX_ITEM lexHandle) { DWORD dwError = 0; BAIL_ON_INVALID_HANDLE(lexHandle); lexHandle->state = (REGLEX_STATE)REGLEX_FIRST; lexHandle->tokenDataType = REGLEX_FIRST; lexHandle->isToken = FALSE; LWREG_SAFE_FREE_MEMORY(lexHandle->curToken.pszValue); memset(&lexHandle->curToken, 0, sizeof(lexHandle->curToken)); lexHandle->prevToken.pszValue = NULL; cleanup: return dwError; error: goto cleanup; }
DWORD RegLexUnGetToken(PREGLEX_ITEM lexHandle) { DWORD dwError = 0; BAIL_ON_INVALID_HANDLE(lexHandle); if (lexHandle->prevToken.token) { if (lexHandle->prevToken.pszValue) { LWREG_SAFE_FREE_MEMORY(lexHandle->prevToken.pszValue); } } lexHandle->prevToken = lexHandle->curToken; cleanup: return dwError; error: goto cleanup; }
NTSTATUS MemDeleteValue( IN HANDLE Handle, IN HKEY hKey, IN OPTIONAL PCWSTR pValueName ) { NTSTATUS status = 0; PREG_KEY_HANDLE pKeyHandle = (PREG_KEY_HANDLE) hKey; PMEMREG_VALUE pRegValue = NULL; BOOLEAN bInLock = FALSE; LWREG_LOCK_RWMUTEX_EXCLUSIVE(bInLock, &MemRegRoot()->lock); status = MemRegStoreFindNodeValue( pKeyHandle->pKey->hNode, pValueName, &pRegValue); BAIL_ON_NT_STATUS(status); if (!pRegValue->Data) { status = STATUS_CANNOT_DELETE; BAIL_ON_NT_STATUS(status); } LWREG_SAFE_FREE_MEMORY(pRegValue->Data); pRegValue->DataLen = 0; MemDbExportEntryChanged(); cleanup: LWREG_UNLOCK_RWMUTEX(bInLock, &MemRegRoot()->lock); return status; error: goto cleanup; }
DWORD RegCopyValueAToW( IN REG_DATA_TYPE dwType, IN PVOID pData, IN DWORD cbData, OUT PVOID* ppOutData, OUT PDWORD pcbOutDataLen ) { DWORD dwError = 0; PVOID pOutData = NULL; DWORD cbOutDataLen = 0; BOOLEAN bIsStrType = FALSE; if (dwType == REG_MULTI_SZ) { if (!pData) { pData = (PBYTE) ""; } if (cbData == 0) { cbData = 1; } } if (pData) { if (REG_MULTI_SZ == dwType) { dwError = RegConvertByteStreamA2W((PBYTE)pData, cbData, (PBYTE*)&pOutData, &cbOutDataLen); BAIL_ON_REG_ERROR(dwError); bIsStrType = TRUE; } else if (REG_SZ == dwType) { /* Verify correct null termination of input data */ if (strlen((char *) pData) != (cbData-1)) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_REG_ERROR(dwError); } dwError = RegWC16StringAllocateFromCString((PWSTR*)&pOutData, pData); BAIL_ON_REG_ERROR(dwError); cbOutDataLen = (mbstrlen((const char*) pData)+1) * sizeof(WCHAR); bIsStrType = TRUE; } } if (!bIsStrType && cbData) { dwError = RegAllocateMemory(cbData, &pOutData); BAIL_ON_REG_ERROR(dwError); if (pData) { memcpy(pOutData, pData, cbData); cbOutDataLen = cbData; } } *ppOutData = pOutData; *pcbOutDataLen = cbOutDataLen; cleanup: return dwError; error: LWREG_SAFE_FREE_MEMORY(pOutData); *ppOutData = NULL; *pcbOutDataLen = 0; goto cleanup; }
NTSTATUS RegHexStrToByteArray( IN PCSTR pszHexString, IN OPTIONAL DWORD* pdwHexStringLength, OUT UCHAR** ppucByteArray, OUT DWORD* pdwByteArrayLength ) { NTSTATUS status = 0; DWORD i = 0; DWORD dwHexChars = 0; UCHAR* pucByteArray = NULL; DWORD dwByteArrayLength = 0; BAIL_ON_NT_INVALID_POINTER(pszHexString); if (pdwHexStringLength) { dwHexChars = *pdwHexStringLength; } else { dwHexChars = strlen(pszHexString); } dwByteArrayLength = dwHexChars / 2; if ((dwHexChars & 0x00000001) != 0) { status = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(status); } status = LW_RTL_ALLOCATE((PVOID*)&pucByteArray, UCHAR, sizeof(*pucByteArray)* dwByteArrayLength); BAIL_ON_NT_STATUS(status); for (i = 0; i < dwByteArrayLength; i++) { CHAR hexHi = pszHexString[2*i]; CHAR hexLow = pszHexString[2*i + 1]; UCHAR ucHi = 0; UCHAR ucLow = 0; status = RegHexCharToByte(hexHi, &ucHi); BAIL_ON_NT_STATUS(status); status = RegHexCharToByte(hexLow, &ucLow); BAIL_ON_NT_STATUS(status); pucByteArray[i] = (ucHi * 16) + ucLow; } *ppucByteArray = pucByteArray; *pdwByteArrayLength = dwByteArrayLength; cleanup: return status; error: LWREG_SAFE_FREE_MEMORY(pucByteArray); *ppucByteArray = NULL; *pdwByteArrayLength = 0; goto cleanup; }
NTSTATUS MemRegStoreGetNodeValueAttributes( PMEMREG_VALUE hValue, OUT OPTIONAL PLWREG_CURRENT_VALUEINFO* ppCurrentValue, OUT OPTIONAL PLWREG_VALUE_ATTRIBUTES* ppValueAttributes) { NTSTATUS status = 0; PWSTR *ppwszEnumStrings = NULL; PWSTR pwszEnumString = NULL; PWSTR pwszDocString = NULL; PLWREG_CURRENT_VALUEINFO pCurrentValue = NULL; PLWREG_VALUE_ATTRIBUTES pValueAttributes = NULL; PBYTE pRetCurrentValueData = NULL; PBYTE pRetAttributeValueData = NULL; DWORD dwValueLen = 0; BOOLEAN bHasAttributes = FALSE; dwValueLen = hValue->DataLen; if (ppCurrentValue) { if ((dwValueLen > 0 && hValue->Data && hValue->Attributes.DefaultValueLen && hValue->Attributes.pDefaultValue && (dwValueLen != hValue->Attributes.DefaultValueLen || memcmp(hValue->Data, hValue->Attributes.pDefaultValue, dwValueLen))) || (dwValueLen > 0 && hValue->Data)) { status = LW_RTL_ALLOCATE((PVOID*) &pCurrentValue, LWREG_CURRENT_VALUEINFO, sizeof(*pCurrentValue)); BAIL_ON_NT_STATUS(status); status = LW_RTL_ALLOCATE((PVOID*) &pRetCurrentValueData, BYTE, dwValueLen); BAIL_ON_NT_STATUS(status); memset(pRetCurrentValueData, 0, dwValueLen); memcpy(pRetCurrentValueData, hValue->Data, dwValueLen); } } if (ppValueAttributes) { /* Always allocate a return attributes block */ status = LW_RTL_ALLOCATE((PVOID*) &pValueAttributes, LWREG_VALUE_ATTRIBUTES, sizeof(*pValueAttributes)); BAIL_ON_NT_STATUS(status); memset(pValueAttributes, 0, sizeof(*pValueAttributes)); if (hValue->Attributes.DefaultValueLen > 0) { status = LW_RTL_ALLOCATE( (PVOID*) &pRetAttributeValueData, BYTE, sizeof(BYTE) * hValue->Attributes.DefaultValueLen); BAIL_ON_NT_STATUS(status); memset(pRetAttributeValueData, 0, sizeof(*pRetAttributeValueData) * hValue->Attributes.DefaultValueLen); memcpy(pRetAttributeValueData, hValue->Attributes.pDefaultValue, hValue->Attributes.DefaultValueLen); bHasAttributes = TRUE; } /* * Duplicate the documentation string, if present */ if (hValue->Attributes.pwszDocString) { status = LwRtlWC16StringDuplicate(&pwszDocString, hValue->Attributes.pwszDocString); BAIL_ON_NT_STATUS(status); bHasAttributes = TRUE; } if (hValue->Attributes.RangeType == LWREG_VALUE_RANGE_TYPE_ENUM && hValue->Attributes.Range.ppwszRangeEnumStrings) { status = _MemRegDuplicateWC16Array( hValue->Attributes.Range.ppwszRangeEnumStrings, &ppwszEnumStrings); BAIL_ON_NT_STATUS(status); bHasAttributes = TRUE; } } if (!bHasAttributes && ppValueAttributes) { status = STATUS_OBJECT_NAME_NOT_FOUND; BAIL_ON_NT_STATUS(status); } /* Assign all allocated data to return optional return structures */ if (pCurrentValue) { pCurrentValue->dwType = hValue->Type; pCurrentValue->pvData = pRetCurrentValueData; pCurrentValue->cbData = dwValueLen; *ppCurrentValue = pCurrentValue; } if (pValueAttributes) { *pValueAttributes = hValue->Attributes; /* * The default type must always be returned by the * attributes structure. Seems like a bug with value * handling on the client-side. */ if (hValue->Attributes.ValueType == 0) { pValueAttributes->ValueType = hValue->Type; } pValueAttributes->pDefaultValue = pRetAttributeValueData; pValueAttributes->pwszDocString = pwszDocString; if (ppwszEnumStrings) { pValueAttributes->Range.ppwszRangeEnumStrings = ppwszEnumStrings; } *ppValueAttributes = pValueAttributes; } cleanup: return status; error: /* Free a bunch of stuff here if something fails */ LWREG_SAFE_FREE_MEMORY(pValueAttributes); LWREG_SAFE_FREE_MEMORY(pCurrentValue); LWREG_SAFE_FREE_MEMORY(pRetCurrentValueData); LWREG_SAFE_FREE_MEMORY(pRetAttributeValueData); LWREG_SAFE_FREE_MEMORY(pwszDocString); LWREG_SAFE_FREE_MEMORY(pwszEnumString); _MemDbFreeWC16Array(ppwszEnumStrings); goto cleanup; }
NTSTATUS MemRegStoreAddNodeAttribute( PMEMREG_VALUE hValue, IN PLWREG_VALUE_ATTRIBUTES pAttributes) { NTSTATUS status = 0; BYTE *pbData = NULL; PWSTR *ppwszEnumStrings = NULL; PWSTR pwszEnumString = NULL; PWSTR pwszDocString = NULL; /* * Assign all scaler types first. Then allocate data and duplicate * pointer types. */ if (pAttributes->DefaultValueLen > 0) { status = LW_RTL_ALLOCATE( (PVOID*) &pbData, BYTE, sizeof(*pbData) * pAttributes->DefaultValueLen); BAIL_ON_NT_STATUS(status); memset(pbData, 0, sizeof(*pbData) * pAttributes->DefaultValueLen); memcpy(pbData, pAttributes->pDefaultValue, pAttributes->DefaultValueLen); } /* * Duplicate the documentation string, if present */ if (pAttributes->pwszDocString) { status = LwRtlWC16StringDuplicate(&pwszDocString, pAttributes->pwszDocString); BAIL_ON_NT_STATUS(status); } /* * Duplicate the multi-string range array when * range type is RANGE_ENUM and the array is present. */ if (pAttributes->RangeType == LWREG_VALUE_RANGE_TYPE_ENUM && pAttributes->Range.ppwszRangeEnumStrings) { status = _MemRegDuplicateWC16Array( pAttributes->Range.ppwszRangeEnumStrings, &ppwszEnumStrings); BAIL_ON_NT_STATUS(status); } /* * Assign all allocated memory present in the attributes structure * to the value node. */ if (pbData) { LWREG_SAFE_FREE_MEMORY(hValue->Attributes.pDefaultValue); } if (pwszDocString) { LWREG_SAFE_FREE_MEMORY(hValue->Attributes.pwszDocString); } hValue->Attributes = *pAttributes; if (pAttributes->DefaultValueLen > 0) { hValue->Attributes.pDefaultValue = (PVOID) pbData; } hValue->Attributes.pwszDocString = pwszDocString; if (pAttributes->RangeType == LWREG_VALUE_RANGE_TYPE_ENUM) { hValue->Attributes.Range.ppwszRangeEnumStrings = ppwszEnumStrings; } cleanup: return status; error: /* Free a bunch of stuff here if something fails */ LWREG_SAFE_FREE_MEMORY(pbData); LWREG_SAFE_FREE_MEMORY(pwszDocString); LWREG_SAFE_FREE_MEMORY(pwszEnumString); _MemDbFreeWC16Array(ppwszEnumStrings); goto cleanup; }
NTSTATUS MemRegStoreDeleteNodeValue( IN PMEMREG_NODE hDbNode, IN PCWSTR Name) { NTSTATUS status = 0; BOOLEAN bFoundValue = FALSE; BOOLEAN bValueDeleted = FALSE; DWORD valueIndex = 0; if (!Name) { Name = (PCWSTR) L""; } for (valueIndex=0; valueIndex<hDbNode->ValuesLen; valueIndex++) { if (LwRtlWC16StringIsEqual(Name, hDbNode->Values[valueIndex]->Name, FALSE)) { bFoundValue = TRUE; break; } } if (bFoundValue) { if (hDbNode->Values[valueIndex]->Data) { LWREG_SAFE_FREE_MEMORY(hDbNode->Values[valueIndex]->Data); hDbNode->Values[valueIndex]->DataLen = 0; bValueDeleted = TRUE; } if (hDbNode->Values[valueIndex]->Attributes.ValueType == 0) { if (valueIndex+1 < hDbNode->ValuesLen) { memmove( &hDbNode->Values[valueIndex], &hDbNode->Values[valueIndex+1], (hDbNode->ValuesLen - valueIndex - 1) * sizeof(PMEMREG_VALUE)); } hDbNode->Values[hDbNode->ValuesLen-1] = NULL; hDbNode->ValuesLen--; if (hDbNode->ValuesLen == 0) { LWREG_SAFE_FREE_MEMORY(hDbNode->Values); hDbNode->Values = NULL; } } else { if (!bValueDeleted) { status = STATUS_CANNOT_DELETE; } } } else { status = STATUS_OBJECT_NAME_NOT_FOUND; } return status; }
NTSTATUS MemRegStoreAddNodeValue( PMEMREG_NODE hDbNode, IN OPTIONAL PCWSTR pValueName, IN DWORD dwReserved, IN DWORD dwType, IN const BYTE *pData, DWORD cbData) { NTSTATUS status = 0; PMEMREG_VALUE pNodeValue = NULL; PWSTR pwszName = NULL; WCHAR pwszNull[2] = {0}; BYTE *pbData = NULL; PMEMREG_VALUE *newValues; DWORD index = 0; status = LW_RTL_ALLOCATE( (PVOID*) &pNodeValue, MEMREG_VALUE, sizeof(*pNodeValue)); BAIL_ON_NT_STATUS(status); if (!pValueName || *pValueName == '\0') { pValueName = pwszNull; } status = LwRtlWC16StringDuplicate(&pwszName, pValueName); BAIL_ON_NT_STATUS(status); if (cbData > 0) { status = LW_RTL_ALLOCATE( (PVOID*) &pbData, BYTE, sizeof(*pbData) * cbData); BAIL_ON_NT_STATUS(status); memset(pbData, 0, sizeof(*pbData) * cbData); if (pData) { memcpy(pbData, pData, cbData); } } status = NtRegReallocMemory(hDbNode->Values, (PVOID) &newValues, (hDbNode->ValuesLen + 1) * sizeof(PMEMREG_VALUE)); BAIL_ON_NT_STATUS(status); hDbNode->Values = newValues; pNodeValue->Name = pwszName; pNodeValue->Type = dwType; /* Clear out existing data before overwriting with new buffer */ LWREG_SAFE_FREE_MEMORY(pNodeValue->Data); pNodeValue->Data = pbData; pNodeValue->DataLen = cbData; /* Insert new value in sorted order */ if (hDbNode->ValuesLen > 0 && pValueName) { for (index=0; index<hDbNode->ValuesLen && LwRtlWC16StringCompare(pValueName, hDbNode->Values[index]->Name)>0; index++) { ; } if (index < (hDbNode->ValuesLen+1)) { memmove(&hDbNode->Values[index+1], &hDbNode->Values[index], sizeof(PMEMREG_NODE) * (hDbNode->ValuesLen - index)); hDbNode->Values[index] = pNodeValue; } else { hDbNode->Values[hDbNode->ValuesLen] = pNodeValue; } } else { hDbNode->Values[hDbNode->ValuesLen] = pNodeValue; } hDbNode->ValuesLen++; cleanup: return status; error: LWREG_SAFE_FREE_MEMORY(pNodeValue); LWREG_SAFE_FREE_MEMORY(pwszName); LWREG_SAFE_FREE_MEMORY(pbData); LWREG_SAFE_FREE_MEMORY(newValues); goto cleanup; }
NTSTATUS MemRegStoreAddNode( IN PMEMREG_NODE hParentNode, PCWSTR Name, DWORD NodeType, PSECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor, ULONG SecurityDescriptorLen, OUT PMEMREG_NODE *phRetParentNode, OUT OPTIONAL PMEMREG_NODE *ppRetNewNode) { NTSTATUS status = 0; PMEMREG_NODE *pNodesArray = NULL; PMEMREG_NODE pNewNode = NULL; PWSTR newNodeName = NULL; DWORD index = 0; PMEMREG_NODE_SD pUpdatedNodeSd = NULL; if (hParentNode->SubNodeDepth == MEMREG_MAX_SUBNODES) { status = STATUS_TOO_MANY_NAMES; BAIL_ON_NT_STATUS(status); } status = NtRegReallocMemory( hParentNode->SubNodes, (PVOID) &pNodesArray, (hParentNode->NodesLen + 1) * sizeof(PMEMREG_NODE)); BAIL_ON_NT_STATUS(status); status = LW_RTL_ALLOCATE( (PVOID*) &pNewNode, PMEMREG_NODE, sizeof(MEMREG_NODE)); BAIL_ON_NT_STATUS(status); memset(pNewNode, 0, sizeof(*pNewNode)); status = LwRtlWC16StringDuplicate(&newNodeName, Name); BAIL_ON_NT_STATUS(status); pNodesArray[hParentNode->NodesLen] = NULL; hParentNode->SubNodes = pNodesArray; pNodesArray = NULL; if (NodeType > 1) { /* * Point new node to parent, if not root. Needed by some operations * that would manipulate parent structure (e.g. MemDeleteKey) */ pNewNode->ParentNode = hParentNode; } /* Insert new node in sorted order */ if (hParentNode->NodesLen > 0) { for (index=0; index<hParentNode->NodesLen && LwRtlWC16StringCompare(Name, hParentNode->SubNodes[index]->Name)>0; index++) { ; } if (index < (hParentNode->NodesLen+1)) { memmove(&hParentNode->SubNodes[index+1], &hParentNode->SubNodes[index], sizeof(PMEMREG_NODE) * (hParentNode->NodesLen - index)); hParentNode->SubNodes[index] = pNewNode; } else { hParentNode->SubNodes[hParentNode->NodesLen] = pNewNode; } } else { hParentNode->SubNodes[hParentNode->NodesLen] = pNewNode; } pNewNode->NodeType = NodeType; pNewNode->Name = newNodeName; newNodeName = NULL; status = MemRegStoreCreateSecurityDescriptor( hParentNode->pNodeSd, SecurityDescriptor, SecurityDescriptorLen, &pUpdatedNodeSd); BAIL_ON_NT_STATUS(status); if (pNewNode->pNodeSd) { LWREG_SAFE_FREE_MEMORY(pNewNode->pNodeSd->SecurityDescriptor); } LWREG_SAFE_FREE_MEMORY(pNewNode->pNodeSd); pNewNode->pNodeSd = pUpdatedNodeSd; hParentNode->NodesLen++; pNewNode->SubNodeDepth = hParentNode->SubNodeDepth+1; if (phRetParentNode) { *phRetParentNode = hParentNode; } if (ppRetNewNode) { *ppRetNewNode = pNewNode; } cleanup: return status; error: LWREG_SAFE_FREE_MEMORY(pNodesArray); LWREG_SAFE_FREE_MEMORY(pNewNode); LWREG_SAFE_FREE_MEMORY(newNodeName); goto cleanup; }
NTSTATUS MemRegStoreDeleteNode( IN PMEMREG_NODE hDbNode) { NTSTATUS status = 0; DWORD index = 0; BOOLEAN bNodeFound = FALSE; if (!hDbNode->ParentNode) { status = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(status); } /* Delete memory for this node here */ for (index=0; index < hDbNode->ValuesLen; index++) { LWREG_SAFE_FREE_MEMORY(hDbNode->Values[index]->Name); LWREG_SAFE_FREE_MEMORY(hDbNode->Values[index]->Data); hDbNode->Values[index]->DataLen = 0; LWREG_SAFE_FREE_MEMORY(hDbNode->Values[index]->Attributes.pDefaultValue); LWREG_SAFE_FREE_MEMORY(hDbNode->Values[index]->Attributes.pwszDocString); if (hDbNode->Values[index]->Attributes.RangeType == LWREG_VALUE_RANGE_TYPE_ENUM) { _MemDbFreeWC16Array( hDbNode->Values[index]->Attributes.Range.ppwszRangeEnumStrings); } LWREG_SAFE_FREE_MEMORY(hDbNode->Values[index]); } LWREG_SAFE_FREE_MEMORY(hDbNode->Values); /* Remove this node from parent SubNodes list */ for (index=0; index < hDbNode->ParentNode->NodesLen; index++) { if (hDbNode->ParentNode->SubNodes[index] == hDbNode) { bNodeFound = TRUE; break; } } if (bNodeFound) { hDbNode->ParentNode->SubNodes[index] = NULL; /* Shift all pointers right of node just removed left over empty slot */ if (index+1 < hDbNode->ParentNode->NodesLen) { memmove(&hDbNode->ParentNode->SubNodes[index], &hDbNode->ParentNode->SubNodes[index+1], (hDbNode->ParentNode->NodesLen-index-1) * sizeof(hDbNode->ParentNode->SubNodes[index])); hDbNode->ParentNode->SubNodes[hDbNode->ParentNode->NodesLen-1] = NULL; hDbNode->ParentNode->NodesLen--; } else if (hDbNode->ParentNode->NodesLen == 1) { LWREG_SAFE_FREE_MEMORY(hDbNode->ParentNode->SubNodes); hDbNode->ParentNode->NodesLen = 0; } else if (index+1 == hDbNode->ParentNode->NodesLen) { /* Last entry on the list. Value is nulled out, decrement len */ hDbNode->ParentNode->NodesLen--; } } if (hDbNode->pNodeSd && hDbNode->pNodeSd->SecurityDescriptorAllocated) { LWREG_SAFE_FREE_MEMORY(hDbNode->pNodeSd->SecurityDescriptor); } LWREG_SAFE_FREE_MEMORY(hDbNode->pNodeSd); LWREG_SAFE_FREE_MEMORY(hDbNode->Name); LWREG_SAFE_FREE_MEMORY(hDbNode); cleanup: return status; error: goto cleanup; }
NTSTATUS MemRegStoreFindNodeSubkey( IN PMEMREG_NODE hDbNode, IN PCWSTR pwszSubKeyPath, OUT PMEMREG_NODE * phNode) { NTSTATUS status = 0; PWSTR pwszTmpFullPath = NULL; PWSTR pwszSubKey = NULL; PWSTR pwszPtr = NULL; PMEMREG_NODE hParentKey = NULL; PMEMREG_NODE hSubKey = NULL; BOOLEAN bEndOfString = FALSE; BAIL_ON_NT_STATUS(status); if (!pwszSubKeyPath) { pwszSubKeyPath = (PCWSTR) L""; } status = LwRtlWC16StringDuplicate(&pwszTmpFullPath, pwszSubKeyPath); BAIL_ON_NT_STATUS(status); hParentKey = hDbNode; pwszSubKey = pwszTmpFullPath; do { pwszPtr = pwstr_wcschr(pwszSubKey, L'\\'); if (pwszPtr) { *pwszPtr++ = L'\0'; } else { pwszPtr = pwszSubKey; bEndOfString = TRUE; } /* * Iterate over subkeys in \ sepearated path. */ status = MemRegStoreFindNode( hParentKey, pwszSubKey, &hSubKey); hParentKey = hSubKey; pwszSubKey = pwszPtr; } while (status == 0 && !bEndOfString); if (status == 0) { *phNode = hParentKey; } cleanup: LWREG_SAFE_FREE_MEMORY(pwszTmpFullPath); return status; error: goto cleanup; }
NTSTATUS MemRegStoreOpen( OUT PMEMREG_NODE *pphDbNode) { NTSTATUS status = 0; PMEMREG_NODE hRegNode = NULL; PWSTR rootKey = NULL; PMEMREG_NODE hRootNode = NULL; DWORD i = 0; PSECURITY_DESCRIPTOR_RELATIVE pSecDescRel = NULL; ULONG ulSecDescLen = 0; /* This is the ROOT node (\) of the registry */ status = LW_RTL_ALLOCATE( (PVOID*)&hRegNode, PMEMREG_NODE, sizeof(*hRegNode)); BAIL_ON_NT_STATUS(status); memset(hRegNode, 0, sizeof(*hRegNode)); hRegNode->NodeType = MEMREG_TYPE_ROOT; status = LwRtlWC16StringAllocateFromCString( &hRegNode->Name, "\\"); BAIL_ON_NT_STATUS(status); status = RegSrvCreateDefaultSecDescRel( &pSecDescRel, &ulSecDescLen); BAIL_ON_NT_STATUS(status); /* Populate the subkeys under the root node */ for (i=0; gRootKeys[i]; i++) { status = LwRtlWC16StringAllocateFromCString( &rootKey, gRootKeys[i]); BAIL_ON_NT_STATUS(status); status = MemRegStoreAddNode( hRegNode, rootKey, MEMREG_TYPE_HIVE, pSecDescRel, // SD parameter ulSecDescLen, &hRootNode, NULL); BAIL_ON_NT_STATUS(status); LWREG_SAFE_FREE_MEMORY(rootKey); } *pphDbNode = hRegNode; cleanup: LWREG_SAFE_FREE_MEMORY(pSecDescRel); return status; error: LWREG_SAFE_FREE_MEMORY(hRegNode->Name); LWREG_SAFE_FREE_MEMORY(hRegNode); LWREG_SAFE_FREE_MEMORY(rootKey); goto cleanup; }