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; }
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; }
NTSTATUS LwRtlRBTreeCreate( PFN_LWRTL_RB_TREE_COMPARE pfnRBTreeCompare, PFN_LWRTL_RB_TREE_FREE_KEY pfnRBTreeFreeKey, PFN_LWRTL_RB_TREE_FREE_DATA pfnRBTreeFreeData, PLWRTL_RB_TREE* ppRBTree ) { NTSTATUS ntStatus = 0; PLWRTL_RB_TREE pRBTree = NULL; PLWRTL_RB_TREE_NODE pSentinel = NULL; if (!pfnRBTreeCompare) { ntStatus = STATUS_INVALID_PARAMETER_1; BAIL_ON_NT_STATUS(ntStatus); } ntStatus = LW_RTL_ALLOCATE(&pRBTree, LWRTL_RB_TREE, sizeof(LWRTL_RB_TREE)); BAIL_ON_NT_STATUS(ntStatus); pRBTree->pfnCompare = pfnRBTreeCompare; pRBTree->pfnFreeKey = pfnRBTreeFreeKey; pRBTree->pfnFreeData = pfnRBTreeFreeData; ntStatus = LW_RTL_ALLOCATE( &pSentinel, LWRTL_RB_TREE_NODE, sizeof(LWRTL_RB_TREE_NODE)); BAIL_ON_NT_STATUS(ntStatus); RB_COLOR_BLACK(pSentinel); pRBTree->pRoot = pSentinel; pRBTree->pSentinel = pSentinel; *ppRBTree = pRBTree; cleanup: return ntStatus; error: if (pRBTree) { LwRtlRBTreeFree(pRBTree); } *ppRBTree = NULL; goto cleanup; }
NTSTATUS SqliteCreateKeyContext( IN PREG_DB_KEY pRegEntry, OUT PREG_KEY_CONTEXT* ppKeyResult ) { NTSTATUS status = STATUS_SUCCESS; PREG_KEY_CONTEXT pKeyResult = NULL; BAIL_ON_INVALID_REG_ENTRY(pRegEntry); status = LW_RTL_ALLOCATE((PVOID*)&pKeyResult, REG_KEY_CONTEXT, sizeof(*pKeyResult)); BAIL_ON_NT_STATUS(status); pKeyResult->refCount = 1; pthread_rwlock_init(&pKeyResult->mutex, NULL); pKeyResult->pMutex = &pKeyResult->mutex; status = LwRtlWC16StringDuplicate(&pKeyResult->pwszKeyName, pRegEntry->pwszFullKeyName); BAIL_ON_NT_STATUS(status); status = SqliteGetParentKeyName(pKeyResult->pwszKeyName, (wchar16_t)'\\',&pKeyResult->pwszParentKeyName); BAIL_ON_NT_STATUS(status); pKeyResult->qwId = pRegEntry->version.qwDbId; pKeyResult->qwSdId = pRegEntry->qwAclIndex; // Cache ACL if (pRegEntry->ulSecDescLength) { status = LW_RTL_ALLOCATE((PVOID*)&pKeyResult->pSecurityDescriptor, VOID, pRegEntry->ulSecDescLength); BAIL_ON_NT_STATUS(status); memcpy(pKeyResult->pSecurityDescriptor, pRegEntry->pSecDescRel, pRegEntry->ulSecDescLength); pKeyResult->ulSecDescLength = pRegEntry->ulSecDescLength; pKeyResult->bHasSdInfo = TRUE; } *ppKeyResult = pKeyResult; cleanup: return status; error: RegSrvSafeFreeKeyContext(pKeyResult); *ppKeyResult = NULL; 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 RegSrvOpenServer( uid_t peerUID, gid_t peerGID, PHANDLE phServer ) { NTSTATUS status = 0; PREG_SRV_API_STATE pServerState = NULL; status = LW_RTL_ALLOCATE((PVOID*)&pServerState, REG_SRV_API_STATE, sizeof(*pServerState)); BAIL_ON_NT_STATUS(status); pServerState->peerUID = peerUID; pServerState->peerGID = peerGID; *phServer = (HANDLE)pServerState; cleanup: return status; error: *phServer = (HANDLE)NULL; if (pServerState) { RegSrvCloseServer((HANDLE)pServerState); } goto cleanup; }
NTSTATUS RegByteArrayToHexStr( IN UCHAR* pucByteArray, IN DWORD dwByteArrayLength, OUT PSTR* ppszHexString ) { NTSTATUS status = 0; DWORD i = 0; PSTR pszHexString = NULL; status = LW_RTL_ALLOCATE((PVOID*)&pszHexString, CHAR, sizeof(*pszHexString)* (dwByteArrayLength*2 + 1)); BAIL_ON_NT_STATUS(status); for (i = 0; i < dwByteArrayLength; i++) { sprintf(pszHexString+(2*i), "%.2X", pucByteArray[i]); } *ppszHexString = pszHexString; cleanup: return status; error: LWREG_SAFE_FREE_STRING(pszHexString); *ppszHexString = NULL; goto cleanup; }
NTSTATUS RegInitializeStringBuffer( REG_STRING_BUFFER *pBuffer, size_t sCapacity ) { NTSTATUS status = STATUS_SUCCESS; PSTR pszBuffer = NULL; pBuffer->sLen = 0; pBuffer->sCapacity = 0; if (sCapacity > DWORD_MAX - 1) { status = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(status); } status = LW_RTL_ALLOCATE((PVOID*)&pszBuffer, CHAR, sCapacity + 1); BAIL_ON_NT_STATUS(status); pBuffer->pszBuffer = pszBuffer; pBuffer->sCapacity = sCapacity; cleanup: return status; error: pBuffer->pszBuffer = NULL; 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; }
static NTSTATUS SMBGssGetSessionKey( gss_ctx_id_t Context, PBYTE* ppSessionKey, PDWORD pdwSessionKeyLength ) { NTSTATUS status = STATUS_SUCCESS; PBYTE pSessionKey = NULL; DWORD dwSessionKeyLength = 0; OM_uint32 gssMajor = GSS_S_COMPLETE; OM_uint32 gssMinor = 0; gss_buffer_set_t sessionKey = NULL; gssMajor = gss_inquire_sec_context_by_oid( &gssMinor, Context, GSS_C_INQ_SSPI_SESSION_KEY, &sessionKey); if (gssMajor != GSS_S_COMPLETE) { smb_display_status("gss_inquire_sec_context_by_oid", gssMajor, gssMinor); // TODO - error code conversion status = gssMajor; BAIL_ON_LWIO_ERROR(status); } // The key is in element 0 and the key type OID is in element 1 if (!sessionKey || (sessionKey->count < 1) || !sessionKey->elements[0].value || (0 == sessionKey->elements[0].length)) { LWIO_ASSERT_MSG(FALSE, "Invalid session key"); status = STATUS_ASSERTION_FAILURE; BAIL_ON_LWIO_ERROR(status); } status = LW_RTL_ALLOCATE(&pSessionKey, BYTE, sessionKey->elements[0].length); BAIL_ON_LWIO_ERROR(status); memcpy(pSessionKey, sessionKey->elements[0].value, sessionKey->elements[0].length); dwSessionKeyLength = sessionKey->elements[0].length; cleanup: gss_release_buffer_set(&gssMinor, &sessionKey); *ppSessionKey = pSessionKey; *pdwSessionKeyLength = dwSessionKeyLength; return status; error: LWIO_SAFE_FREE_MEMORY(pSessionKey); dwSessionKeyLength = 0; 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; }
LWMsgStatus RegSrvIpcQueryMultipleValues( LWMsgCall* pCall, const LWMsgParams* pIn, LWMsgParams* pOut, void* data ) { NTSTATUS status = 0; PREG_IPC_QUERY_MULTIPLE_VALUES_REQ pReq = pIn->data; PREG_IPC_QUERY_MULTIPLE_VALUES_RESPONSE pRegResp = NULL; PREG_IPC_STATUS pStatus = NULL; HKEY hKey = NULL; status = RegSrvIpcGetHandleData(pCall, pReq->hKey, &hKey); BAIL_ON_NT_STATUS(status); status = RegSrvQueryMultipleValues( RegSrvIpcGetSessionData(pCall), hKey, pReq->val_list, pReq->num_vals, pReq->pValue, &pReq->dwTotalsize); if (!status) { status = LW_RTL_ALLOCATE((PVOID*)&pRegResp, REG_IPC_QUERY_MULTIPLE_VALUES_RESPONSE, sizeof(*pRegResp)); BAIL_ON_NT_STATUS(status); pRegResp->dwTotalsize = pReq->dwTotalsize; pRegResp->num_vals = pReq->num_vals; pRegResp->val_list = pReq->val_list; pReq->val_list = NULL; pRegResp->pValue = pReq->pValue; pReq->pValue = NULL; pOut->tag = REG_R_QUERY_MULTIPLE_VALUES; pOut->data = pRegResp; } else { status = RegSrvIpcCreateError(status, &pStatus); BAIL_ON_NT_STATUS(status); pOut->tag = REG_R_ERROR; pOut->data = pStatus; } cleanup: return MAP_REG_ERROR_IPC(status); error: goto cleanup; }
DWORD LsaPstoreGetJoinedDomainsA( OUT PSTR** DnsDomainNames, OUT PDWORD Count ) { DWORD dwError = 0; int EE = 0; PSTR* dnsDomainNames = NULL; DWORD count = 0; PWSTR* dnsDomainNamesW = NULL; DWORD countW = 0; dwError = LsaPstoreGetJoinedDomainsW( &dnsDomainNamesW, &countW); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); if (!countW) { GOTO_CLEANUP_EE(EE); } dwError = LwNtStatusToWin32Error(LW_RTL_ALLOCATE( &dnsDomainNames, VOID, countW * sizeof(dnsDomainNames[0]))); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); for (count = 0; count < countW; count++) { dwError = LwNtStatusToWin32Error(LwRtlCStringAllocateFromWC16String( &dnsDomainNames[count], dnsDomainNamesW[count])); GOTO_CLEANUP_ON_WINERROR_EE(dwError, EE); } cleanup: if (dwError) { LSA_PSTORE_FREE_STRING_ARRAY_A(&dnsDomainNames, &count); } LSA_PSTORE_FREE_STRING_ARRAY_W(&dnsDomainNamesW, &countW); *DnsDomainNames = dnsDomainNames; *Count = count; LSA_PSTORE_LOG_LEAVE_ERROR_EE(dwError, EE); return dwError; }
NTSTATUS NtRegOpenConfig( PCSTR pszConfigKey, PCSTR pszPolicyKey, PLWREG_CONFIG_REG *ppReg ) { NTSTATUS ntStatus = STATUS_SUCCESS; PLWREG_CONFIG_REG pReg = NULL; ntStatus = LW_RTL_ALLOCATE( (PVOID*)&pReg, LWREG_CONFIG_REG, sizeof(LWREG_CONFIG_REG)); BAIL_ON_NT_STATUS(ntStatus); ntStatus = LwRtlCStringDuplicate(&pReg->pszConfigKey, pszConfigKey); BAIL_ON_NT_STATUS(ntStatus); if (pszPolicyKey) { ntStatus = LwRtlCStringDuplicate(&pReg->pszPolicyKey, pszPolicyKey); BAIL_ON_NT_STATUS(ntStatus); } ntStatus = NtRegOpenServer(&pReg->hConnection); BAIL_ON_NT_STATUS(ntStatus); ntStatus = NtRegOpenKeyExA( pReg->hConnection, NULL, HKEY_THIS_MACHINE, 0, KEY_READ, &(pReg->hKey)); BAIL_ON_NT_STATUS(ntStatus); cleanup: *ppReg = pReg; return ntStatus; error: NtRegCloseConfig(pReg); pReg = NULL; goto cleanup; }
DWORD RegGetErrorMessageForLoggingEvent( DWORD dwErrCode, PSTR* ppszErrorMsg ) { DWORD dwErrorBufferSize = 0; DWORD dwError = 0; DWORD dwLen = 0; PSTR pszErrorMsg = NULL; PSTR pszErrorBuffer = NULL; dwErrorBufferSize = LwRegGetErrorString(dwErrCode, NULL, 0); if (!dwErrorBufferSize) goto cleanup; dwError = LW_RTL_ALLOCATE((PVOID*)&pszErrorBuffer, CHAR, sizeof(*pszErrorBuffer) * dwErrorBufferSize); BAIL_ON_REG_ERROR(dwError); dwLen = LwRegGetErrorString(dwErrCode, pszErrorBuffer, dwErrorBufferSize); if ((dwLen == dwErrorBufferSize) && !IsNullOrEmptyString(pszErrorBuffer)) { dwError = RegCStringAllocatePrintf( &pszErrorMsg, "Error: %s [error code: %d]", pszErrorBuffer, dwErrCode); BAIL_ON_REG_ERROR(dwError); } *ppszErrorMsg = pszErrorMsg; cleanup: LWREG_SAFE_FREE_STRING(pszErrorBuffer); return dwError; error: LWREG_SAFE_FREE_STRING(pszErrorMsg); *ppszErrorMsg = NULL; goto cleanup; }
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; }
NTSTATUS RegSrvIpcCreateError( DWORD statusCode, PREG_IPC_STATUS* ppStatus ) { NTSTATUS status = 0; PREG_IPC_STATUS pStatus = NULL; status = LW_RTL_ALLOCATE((PVOID*)&pStatus, REG_IPC_STATUS, sizeof(*pStatus)); BAIL_ON_NT_STATUS(status); pStatus->status = statusCode; *ppStatus = pStatus; error: return status; }
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; }
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; }
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 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 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; }
LWMsgStatus RegSrvIpcGetValueW( LWMsgCall* pCall, const LWMsgParams* pIn, LWMsgParams* pOut, void* data ) { NTSTATUS status = 0; PREG_IPC_GET_VALUE_REQ pReq = pIn->data; PREG_IPC_GET_VALUE_RESPONSE pRegResp = NULL; PREG_IPC_STATUS pStatus = NULL; DWORD dwType = 0; PBYTE pData = NULL; HKEY hKey = NULL; status = RegSrvIpcGetHandleData(pCall, pReq->hKey, &hKey); BAIL_ON_NT_STATUS(status); if (pReq->cbData) { status = LW_RTL_ALLOCATE((PVOID*)&pData, BYTE, pReq->cbData*sizeof(*pData)); BAIL_ON_NT_STATUS(status); } status = RegSrvGetValueW( RegSrvIpcGetSessionData(pCall), hKey, pReq->pSubKey, pReq->pValue, pReq->Flags, &dwType, pData, &pReq->cbData); if (!status) { status = LW_RTL_ALLOCATE((PVOID*)&pRegResp, REG_IPC_GET_VALUE_RESPONSE, sizeof(*pRegResp)); BAIL_ON_NT_STATUS(status); pRegResp->cbData = pReq->cbData; pRegResp->pvData = pData; pData = NULL; pRegResp->dwType = dwType; pOut->tag = REG_R_GET_VALUEW; 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(pData); return MAP_REG_ERROR_IPC(status); error: goto cleanup; }
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; }
LW_NTSTATUS LwRtlSvcmLoadModule( LW_IN LW_PCWSTR pServiceName, LW_IN LW_PCWSTR pModulePath, LW_OUT PLW_SVCM_INSTANCE* ppInstance ) { NTSTATUS status = STATUS_SUCCESS; PLW_SVCM_INSTANCE pInstance = NULL; PSTR pModulePathA = NULL; LW_SVCM_MODULE_ENTRY_FUNCTION Entry = NULL; PSTR pEntryName = NULL; PSTR pBareName = NULL; PSTR pFinalSlash = NULL; PSTR pFinalDot = NULL; status = InitPool(); GCOS(status); status = LwRtlCStringAllocateFromWC16String(&pModulePathA, pModulePath); GCOS(status); pFinalSlash = strrchr(pModulePathA, '/'); pFinalDot = strrchr(pModulePathA, '.'); if (!pFinalSlash) { pFinalSlash = pModulePathA; } else { pFinalSlash++; } if (!pFinalDot) { pFinalDot = pModulePathA + strlen(pModulePathA); } status = LW_RTL_ALLOCATE(&pBareName, CHAR, (pFinalDot - pFinalSlash) + 1); GCOS(status); memcpy(pBareName, pFinalSlash, pFinalDot - pFinalSlash); status = LwRtlCStringAllocatePrintf(&pEntryName, "_LwSvcmEntry_%s", pBareName); GCOS(status); status = LW_RTL_ALLOCATE_AUTO(&pInstance); GCOS(status); LW_RTL_LOG_DEBUG("Loading service module: %s", pModulePathA); (void) dlerror(); pInstance->pDlHandle = dlopen(pModulePathA, RTLD_LOCAL | RTLD_NOW); if (!pInstance->pDlHandle) { LW_RTL_LOG_ERROR( "Could not load service module '%s': %s", pModulePathA, dlerror()); status = LwErrnoToNtStatus(errno); GCOS(status); } (void) dlerror(); Entry = dlsym(pInstance->pDlHandle, pEntryName); if (!Entry) { LW_RTL_LOG_ERROR( "Could not load entry point from service module '%s': %s", pModulePathA, dlerror()); status = LwErrnoToNtStatus(errno); if (!status) { status = STATUS_BAD_DLL_ENTRYPOINT; } GCOS(status); } status = LwRtlSvcmInitializeInstance(pInstance, pServiceName, pModulePathA, Entry); GCOS(status); cleanup: RTL_FREE(&pModulePathA); RTL_FREE(&pBareName); RTL_FREE(&pEntryName); if (!NT_SUCCESS(status)) { LwRtlSvcmUnload(pInstance); pInstance = NULL; } *ppInstance = pInstance; return status; }
LWMsgStatus RegSrvIpcEnumValueW( LWMsgCall* pCall, const LWMsgParams* pIn, LWMsgParams* pOut, void* data ) { NTSTATUS status = 0; PREG_IPC_ENUM_VALUE_REQ pReq = pIn->data; PREG_IPC_ENUM_VALUE_RESPONSE pRegResp = NULL; PWSTR pValueName = NULL; PBYTE pValue = NULL; PREG_IPC_STATUS pStatus = NULL; REG_DATA_TYPE type = REG_NONE; HKEY hKey = NULL; status = RegSrvIpcGetHandleData(pCall, pReq->hKey, &hKey); BAIL_ON_NT_STATUS(status); if (pReq->cName) { status = LW_RTL_ALLOCATE((PVOID*)&pValueName, WCHAR, pReq->cName*sizeof(*pValueName)); BAIL_ON_NT_STATUS(status); } if (pReq->cValue) { status = LW_RTL_ALLOCATE((PVOID*)&pValue, BYTE, pReq->cValue*sizeof(*pValue)); BAIL_ON_NT_STATUS(status); } status = RegSrvEnumValueW( RegSrvIpcGetSessionData(pCall), hKey, pReq->dwIndex, pValueName, &pReq->cName, NULL, &type, pValue, &pReq->cValue); if (!status) { status = LW_RTL_ALLOCATE((PVOID*)&pRegResp, REG_IPC_ENUM_VALUE_RESPONSE, sizeof(*pRegResp)); BAIL_ON_NT_STATUS(status); pRegResp->pName= pValueName; pValueName = NULL; pRegResp->cName = pReq->cName; pRegResp->pValue = pValue; pValue = NULL; pRegResp->cValue = pReq->cValue; pRegResp->type = type; pOut->tag = REG_R_ENUM_VALUEW; 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(pValueName); LWREG_SAFE_FREE_MEMORY(pValue); return MAP_REG_ERROR_IPC(status); error: goto cleanup; }
NTSTATUS LwRtlRBTreeAdd( PLWRTL_RB_TREE pRBTree, PVOID pKey, PVOID pData ) { NTSTATUS ntStatus = 0; PLWRTL_RB_TREE_NODE pTreeNode = NULL; PLWRTL_RB_TREE_NODE pUncle = NULL; PLWRTL_RB_TREE_NODE pParent = NULL; PLWRTL_RB_TREE_NODE pGrandParent = NULL; if (!pKey) { ntStatus = STATUS_INVALID_PARAMETER_2; BAIL_ON_NT_STATUS(ntStatus); } ntStatus = LW_RTL_ALLOCATE( &pTreeNode, LWRTL_RB_TREE_NODE, sizeof(LWRTL_RB_TREE_NODE)); BAIL_ON_NT_STATUS(ntStatus); pTreeNode->pKey = pKey; pTreeNode->pData = pData; pTreeNode->pRight = pRBTree->pSentinel; pTreeNode->pLeft = pRBTree->pSentinel; pTreeNode->pParent = NULL; LwRtlRBTreeInsert(pRBTree, pTreeNode); RB_COLOR_RED(pTreeNode); while ((pTreeNode != pRBTree->pRoot) && RB_IS_RED(pTreeNode->pParent)) { pParent = RB_PARENT(pTreeNode); pGrandParent = RB_PARENT(pParent); if (pParent == pGrandParent->pLeft) { if (!RB_IS_NIL(pRBTree, pGrandParent)) { pUncle = pGrandParent->pRight; if (RB_IS_RED(pUncle)) { RB_COLOR_BLACK(pParent); RB_COLOR_BLACK(pUncle); RB_COLOR_RED(pGrandParent); pTreeNode = pGrandParent; continue; } } if (pTreeNode == pParent->pRight) { pTreeNode = pParent; LwRtlRBTreeRotateLeft(pRBTree, pTreeNode); pParent = RB_PARENT(pTreeNode); } RB_COLOR_BLACK(pParent); if (!RB_IS_NIL(pRBTree, pGrandParent)) { RB_COLOR_RED(pGrandParent); LwRtlRBTreeRotateRight(pRBTree, pGrandParent); } } else { if (!RB_IS_NIL(pRBTree, pGrandParent)) { pUncle = pGrandParent->pLeft; if (RB_IS_RED(pUncle)) { RB_COLOR_BLACK(pParent); RB_COLOR_BLACK(pUncle); RB_COLOR_RED(pGrandParent); pTreeNode = pGrandParent; continue; } } if (pTreeNode == pParent->pLeft) { pTreeNode = pParent; LwRtlRBTreeRotateRight(pRBTree, pTreeNode); pParent = RB_PARENT(pTreeNode); } RB_COLOR_BLACK(pParent); if (!RB_IS_NIL(pRBTree, pGrandParent)) { RB_COLOR_RED(pGrandParent); LwRtlRBTreeRotateLeft(pRBTree, pGrandParent); } } } RB_COLOR_BLACK(pRBTree->pRoot); cleanup: return ntStatus; error: if (pTreeNode) { LwRtlRBTreeFreeNode(pRBTree, pTreeNode); } goto cleanup; }
NTSTATUS MemRegStoreCreateSecurityDescriptor( PMEMREG_NODE_SD pParentSd, PSECURITY_DESCRIPTOR_RELATIVE SecurityDescriptor, ULONG SecurityDescriptorLen, PMEMREG_NODE_SD *ppUpdatedNodeSd) { NTSTATUS status = 0; PSECURITY_DESCRIPTOR_RELATIVE NewSecurityDescriptor = NULL; PMEMREG_NODE_SD pNodeSd = NULL; PMEMREG_NODE_SD pNewNodeSd = NULL; BOOLEAN bInheritParent = FALSE; if (pParentSd) { if (SecurityDescriptor && SecurityDescriptorLen) { if (pParentSd->SecurityDescriptorLen == SecurityDescriptorLen && memcmp(pParentSd->SecurityDescriptor, SecurityDescriptor, SecurityDescriptorLen) == 0) { bInheritParent = TRUE; } } else { bInheritParent = TRUE; } } status = LW_RTL_ALLOCATE( (PVOID *) &pNodeSd, PMEMREG_NODE_SD, sizeof(*pNewNodeSd)); BAIL_ON_NT_STATUS(status); if (bInheritParent) { /* Inherit SD from parent node if one is not provided */ pNodeSd->SecurityDescriptor = pParentSd->SecurityDescriptor; pNodeSd->SecurityDescriptorLen = pParentSd->SecurityDescriptorLen; } else { status = LW_RTL_ALLOCATE((PVOID *) &NewSecurityDescriptor, PSECURITY_DESCRIPTOR_RELATIVE, SecurityDescriptorLen); BAIL_ON_NT_STATUS(status); pNodeSd->SecurityDescriptor = NewSecurityDescriptor; memcpy(pNodeSd->SecurityDescriptor, SecurityDescriptor, SecurityDescriptorLen); pNodeSd->SecurityDescriptorLen = SecurityDescriptorLen; pNodeSd->SecurityDescriptorAllocated = TRUE; } *ppUpdatedNodeSd = pNodeSd; cleanup: return status; error: LWREG_SAFE_FREE_MEMORY(pNodeSd); LWREG_SAFE_FREE_MEMORY(NewSecurityDescriptor); goto cleanup; }