DWORD VMCAAllocateStringW( PCWSTR pwszSrc, PWSTR* ppwszDst ) { DWORD dwError = 0; if (!pwszSrc || !ppwszDst) { dwError = ERROR_INVALID_PARAMETER; } else { #ifdef _WIN32 PWSTR pwszNewString = NULL; size_t len = wcslen(pwszSrc); dwError = VMCAAllocateMemory( (DWORD) (len + 1)*sizeof(WCHAR), (PVOID *)&pwszNewString ); BAIL_ON_VMCA_ERROR(dwError); wcscpy_s(pwszNewString, (len + 1), pwszSrc); *ppwszDst = pwszNewString; #else dwError = LwNtStatusToWin32Error( LwRtlWC16StringDuplicate(ppwszDst, pwszSrc)); BAIL_ON_VMCA_ERROR(dwError); #endif } error: return dwError; }
NTSTATUS RdrResolveToDomain( PCWSTR pwszHostname, PWSTR* ppwszDomain ) { NTSTATUS status = STATUS_SUCCESS; BOOLEAN bLocked = FALSE; PWSTR pwszDomain = NULL; LWIO_LOCK_MUTEX(bLocked, &gRdrRuntime.Lock); if (!gRdrRuntime.pDomainHints) { status = STATUS_NOT_FOUND; } else { status = LwRtlHashMapFindKey( gRdrRuntime.pDomainHints, OUT_PPVOID(&pwszDomain), pwszHostname); } BAIL_ON_NT_STATUS(status); status = LwRtlWC16StringDuplicate(ppwszDomain, pwszDomain); BAIL_ON_NT_STATUS(status); error: LWIO_UNLOCK_MUTEX(bLocked, &gRdrRuntime.Lock); return status; }
DWORD RegWC16StringDuplicate( PWSTR* ppwszNewString, PCWSTR pwszOriginalString ) { return RegNtStatusToWin32Error( LwRtlWC16StringDuplicate(ppwszNewString, pwszOriginalString) ); }
DWORD IDMAllocateString( PWSTR pszString, PWSTR* ppszString ) { DWORD dwError = 0; PWSTR pszNewString = NULL; if (!pszString || !ppszString) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_ERROR(dwError); } #ifdef _WIN32 { SIZE_T len = 0; len = wcslen(pszString); dwError = IDMAllocateMemory( (len + 1) * sizeof(WCHAR), (PVOID*)&pszNewString); BAIL_ON_ERROR(dwError); wcscpy_s(pszNewString, len+1, pszString); } #else dwError = LwRtlWC16StringDuplicate( &pszNewString, pszString); BAIL_ON_ERROR(dwError); #endif *ppszString = pszNewString; cleanup: return dwError; error: if (ppszString) { *ppszString = NULL; } IDM_SAFE_FREE_MEMORY(pszNewString); 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; }
static NTSTATUS RdrIsInPlaceRename( PRDR_CCB pFile, PFILE_RENAME_INFORMATION pRenameInfo, PBOOLEAN pbIsInPlace ) { NTSTATUS status = STATUS_SUCCESS; PWSTR pwszShare = NULL; PWSTR pwszFile = NULL; PWSTR pwszExisting = NULL; PWSTR pwszNew = NULL; status = RdrConvertPath( pRenameInfo->FileName, NULL, &pwszShare, &pwszFile ); BAIL_ON_NT_STATUS(status); status = LwRtlWC16StringAllocatePrintfW( &pwszNew, L"%ws%ws", pwszShare, pwszFile); BAIL_ON_NT_STATUS(status); status = LwRtlWC16StringDuplicate(&pwszExisting, pFile->pwszCanonicalPath); BAIL_ON_NT_STATUS(status); RdrTrimLastPathElement(pwszNew); RdrTrimLastPathElement(pwszExisting); *pbIsInPlace = LwRtlWC16StringIsEqual(pwszNew, pwszExisting, FALSE); cleanup: RTL_FREE(&pwszShare); RTL_FREE(&pwszFile); RTL_FREE(&pwszExisting); RTL_FREE(&pwszNew); return status; error: *pbIsInPlace = FALSE; goto cleanup; }
NTSTATUS RegWcStrDupOrNull( PCWSTR pwszInputString, PWSTR *ppwszOutputString ) { if (pwszInputString == NULL) { *ppwszOutputString = NULL; return STATUS_SUCCESS; } else { return LwRtlWC16StringDuplicate(ppwszOutputString, pwszInputString); } }
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; }
ULONG VmDirAllocateStringW( PCWSTR pwszSrc, PWSTR* ppwszDst ) { ULONG ulError = 0; if (!pwszSrc || !ppwszDst) { ulError = ERROR_INVALID_PARAMETER; } else { ulError = LwNtStatusToWin32Error( LwRtlWC16StringDuplicate(ppwszDst, pwszSrc)); } return ulError; }
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 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 SqliteSetValueAttributes( IN HANDLE hRegConnection, IN HKEY hKey, IN OPTIONAL PCWSTR pwszSubKey, IN PCWSTR pValueName, IN PLWREG_VALUE_ATTRIBUTES pValueAttributes ) { NTSTATUS status = STATUS_SUCCESS; PWSTR pwszValueName = NULL; BOOLEAN bIsWrongType = TRUE; wchar16_t wszEmptyValueName[] = REG_EMPTY_VALUE_NAME_W; PWSTR pwszKeyNameWithSubKey = NULL; PREG_KEY_HANDLE pKeyHandle = (PREG_KEY_HANDLE)hKey; PREG_KEY_CONTEXT pKeyCtx = NULL; PREG_KEY_HANDLE pKeyHandleInUse = NULL; PREG_KEY_CONTEXT pKeyCtxInUse = NULL; // Do not free PBYTE pData = NULL; DWORD cbData = 0; BAIL_ON_NT_INVALID_POINTER(pKeyHandle); pKeyCtx = pKeyHandle->pKey; BAIL_ON_INVALID_KEY_CONTEXT(pKeyCtx); if (!RegValidValueAttributes(pValueAttributes)) { status = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(status); } if (pwszSubKey) { status = LwRtlWC16StringAllocatePrintfW( &pwszKeyNameWithSubKey, L"%ws\\%ws", pKeyCtx->pwszKeyName, pwszSubKey); BAIL_ON_NT_STATUS(status); } status = SqliteOpenKeyInternal(hRegConnection, pwszSubKey ? pwszKeyNameWithSubKey : pKeyCtx->pwszKeyName, KEY_SET_VALUE, &pKeyHandleInUse); BAIL_ON_NT_STATUS(status); status = RegSrvAccessCheckKeyHandle(pKeyHandleInUse, KEY_SET_VALUE); BAIL_ON_NT_STATUS(status); pKeyCtxInUse = pKeyHandleInUse->pKey; BAIL_ON_INVALID_KEY_CONTEXT(pKeyCtxInUse); status = LwRtlWC16StringDuplicate(&pwszValueName, !pValueName ? wszEmptyValueName : pValueName); BAIL_ON_NT_STATUS(status); status = RegDbGetValueAttributes( ghCacheConnection, pKeyCtxInUse->qwId, (PCWSTR)pwszValueName, (REG_DATA_TYPE)pValueAttributes->ValueType, &bIsWrongType, NULL); if (!status) { status = STATUS_DUPLICATE_NAME; BAIL_ON_NT_STATUS(status); } else if (STATUS_OBJECT_NAME_NOT_FOUND == status) { status = 0; } BAIL_ON_NT_STATUS(status); pData = pValueAttributes->pDefaultValue; cbData = pValueAttributes->DefaultValueLen; if (cbData == 0) { goto done; } switch (pValueAttributes->ValueType) { case REG_BINARY: case REG_DWORD: break; case REG_MULTI_SZ: case REG_SZ: if (cbData == 1) { status = STATUS_INTERNAL_ERROR; BAIL_ON_NT_STATUS(status); } if (!pData || pData[cbData-1] != '\0' || pData[cbData-2] != '\0' ) { status = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(status); } break; default: status = STATUS_NOT_SUPPORTED; BAIL_ON_NT_STATUS(status); } done: status = RegDbSetValueAttributes(ghCacheConnection, pKeyCtxInUse->qwId, pwszValueName, pValueAttributes); BAIL_ON_NT_STATUS(status); SqliteCacheResetKeyValueInfo(pKeyCtxInUse->pwszKeyName); cleanup: LWREG_SAFE_FREE_MEMORY(pwszValueName); LWREG_SAFE_FREE_MEMORY(pwszKeyNameWithSubKey); SqliteSafeFreeKeyHandle(pKeyHandleInUse); return status; error: goto cleanup; }
NTSTATUS SqliteDeleteValueAttributes( IN HANDLE hRegConnection, IN HKEY hKey, IN OPTIONAL PCWSTR pwszSubKey, IN PCWSTR pValueName ) { NTSTATUS status = STATUS_SUCCESS; PWSTR pwszValueName = NULL; wchar16_t wszEmptyValueName[] = REG_EMPTY_VALUE_NAME_W; PWSTR pwszKeyNameWithSubKey = NULL; PREG_KEY_HANDLE pKeyHandle = (PREG_KEY_HANDLE)hKey; PREG_KEY_CONTEXT pKeyCtx = NULL; PREG_KEY_HANDLE pKeyHandleInUse = NULL; PREG_KEY_CONTEXT pKeyCtxInUse = NULL; BAIL_ON_NT_INVALID_POINTER(pKeyHandle); pKeyCtx = pKeyHandle->pKey; BAIL_ON_INVALID_KEY_CONTEXT(pKeyCtx); if (pwszSubKey) { status = LwRtlWC16StringAllocatePrintfW( &pwszKeyNameWithSubKey, L"%ws\\%ws", pKeyCtx->pwszKeyName, pwszSubKey); BAIL_ON_NT_STATUS(status); } status = SqliteOpenKeyInternal(hRegConnection, pwszSubKey ? pwszKeyNameWithSubKey : pKeyCtx->pwszKeyName, KEY_SET_VALUE | DELETE, &pKeyHandleInUse); BAIL_ON_NT_STATUS(status); status = RegSrvAccessCheckKeyHandle(pKeyHandleInUse, KEY_SET_VALUE); BAIL_ON_NT_STATUS(status); pKeyCtxInUse = pKeyHandleInUse->pKey; BAIL_ON_INVALID_KEY_CONTEXT(pKeyCtxInUse); status = LwRtlWC16StringDuplicate(&pwszValueName, !pValueName ? wszEmptyValueName : pValueName); BAIL_ON_NT_STATUS(status); status = RegDbGetValueAttributes( ghCacheConnection, pKeyCtxInUse->qwId, (PCWSTR)pwszValueName, REG_NONE, NULL, NULL); BAIL_ON_NT_STATUS(status); status = RegDbDeleteValueAttributes(ghCacheConnection, pKeyCtxInUse->qwId, (PCWSTR)pwszValueName); BAIL_ON_NT_STATUS(status); SqliteCacheResetKeyValueInfo(pKeyCtxInUse->pwszKeyName); cleanup: SqliteSafeFreeKeyHandle(pKeyHandleInUse); LWREG_SAFE_FREE_MEMORY(pwszValueName); LWREG_SAFE_FREE_MEMORY(pwszKeyNameWithSubKey); return status; error: goto cleanup; }
NTSTATUS SqliteGetValueAttributes_Internal( IN HANDLE hRegConnection, IN HKEY hKey, IN OPTIONAL PCWSTR pwszSubKey, IN PCWSTR pValueName, IN OPTIONAL REG_DATA_TYPE dwType, // Whether bail or not in case there is no value attributes IN BOOLEAN bDoBail, OUT OPTIONAL PLWREG_CURRENT_VALUEINFO* ppCurrentValue, OUT OPTIONAL PLWREG_VALUE_ATTRIBUTES* ppValueAttributes ) { NTSTATUS status = STATUS_SUCCESS; PWSTR pwszValueName = NULL; PREG_DB_VALUE_ATTRIBUTES pRegEntry = NULL; PREG_DB_VALUE pRegValueEntry = NULL; BOOLEAN bIsWrongType = FALSE; wchar16_t wszEmptyValueName[] = REG_EMPTY_VALUE_NAME_W; PWSTR pwszKeyNameWithSubKey = NULL; PREG_KEY_HANDLE pKeyHandle = (PREG_KEY_HANDLE)hKey; PREG_KEY_CONTEXT pKeyCtx = NULL; PREG_KEY_HANDLE pKeyHandleInUse = NULL; PREG_KEY_CONTEXT pKeyCtxInUse = NULL; PLWREG_CURRENT_VALUEINFO pCurrentValue = NULL; BOOLEAN bInDbLock = FALSE; BOOLEAN bInLock = FALSE; PSTR pszError = NULL; PREG_DB_CONNECTION pConn = (PREG_DB_CONNECTION)ghCacheConnection; PREG_SRV_API_STATE pServerState = (PREG_SRV_API_STATE)hRegConnection; BAIL_ON_NT_INVALID_POINTER(pKeyHandle); pKeyCtx = pKeyHandle->pKey; BAIL_ON_INVALID_KEY_CONTEXT(pKeyCtx); if (!ppCurrentValue && !ppValueAttributes) { status = STATUS_INVALID_PARAMETER; BAIL_ON_NT_STATUS(status); } if (pwszSubKey) { status = LwRtlWC16StringAllocatePrintfW( &pwszKeyNameWithSubKey, L"%ws\\%ws", pKeyCtx->pwszKeyName, pwszSubKey); BAIL_ON_NT_STATUS(status); } if (!pServerState->pToken) { status = RegSrvCreateAccessToken(pServerState->peerUID, pServerState->peerGID, &pServerState->pToken); BAIL_ON_NT_STATUS(status); } LWREG_LOCK_MUTEX(bInLock, &gActiveKeyList.mutex); ENTER_SQLITE_LOCK(&pConn->lock, bInDbLock); status = sqlite3_exec( pConn->pDb, "begin;", NULL, NULL, &pszError); BAIL_ON_SQLITE3_ERROR(status, pszError); // pServerState->pToken should be created at this point status = SqliteOpenKeyInternal_inlock_inDblock( hRegConnection, pwszSubKey ? pwszKeyNameWithSubKey : pKeyCtx->pwszKeyName, KEY_QUERY_VALUE, &pKeyHandleInUse); BAIL_ON_NT_STATUS(status); // ACL check status = RegSrvAccessCheckKeyHandle(pKeyHandleInUse, KEY_QUERY_VALUE); BAIL_ON_NT_STATUS(status); pKeyCtxInUse = pKeyHandleInUse->pKey; BAIL_ON_INVALID_KEY_CONTEXT(pKeyCtxInUse); status = LwRtlWC16StringDuplicate(&pwszValueName, !pValueName ? wszEmptyValueName : pValueName); BAIL_ON_NT_STATUS(status); // Optionally get value if (ppCurrentValue) { status = RegDbGetKeyValue_inlock( ghCacheConnection, pKeyCtxInUse->qwId, pwszValueName, dwType, &bIsWrongType, &pRegValueEntry); if (!status) { status = LW_RTL_ALLOCATE((PVOID*)&pCurrentValue, LWREG_CURRENT_VALUEINFO, sizeof(*pCurrentValue)); BAIL_ON_NT_STATUS(status); pCurrentValue->cbData = pRegValueEntry->dwValueLen; pCurrentValue->dwType = pRegValueEntry->type; if (pCurrentValue->cbData) { status = LW_RTL_ALLOCATE((PVOID*)&pCurrentValue->pvData, VOID, pCurrentValue->cbData); BAIL_ON_NT_STATUS(status); memcpy(pCurrentValue->pvData, pRegValueEntry->pValue, pCurrentValue->cbData); } } else if (LW_STATUS_OBJECT_NAME_NOT_FOUND == status) { status = 0; } BAIL_ON_NT_STATUS(status); } // Get value attributes if (ppValueAttributes) { status = RegDbGetValueAttributes_inlock( ghCacheConnection, pKeyCtxInUse->qwId, pwszValueName, REG_NONE, &bIsWrongType, &pRegEntry); if (!bDoBail && LW_STATUS_OBJECT_NAME_NOT_FOUND == status) { status = LW_RTL_ALLOCATE((PVOID*)&pRegEntry, REG_DB_VALUE_ATTRIBUTES, sizeof(*pRegEntry)); BAIL_ON_NT_STATUS(status); } BAIL_ON_NT_STATUS(status); } status = sqlite3_exec( pConn->pDb, "end", NULL, NULL, &pszError); BAIL_ON_SQLITE3_ERROR(status, pszError); REG_LOG_VERBOSE("Registry::sqldb.c SqliteGetValueAttributes_Internal() finished"); if (ppCurrentValue) { *ppCurrentValue = pCurrentValue; pCurrentValue = NULL; } if (ppValueAttributes) { *ppValueAttributes = pRegEntry->pValueAttributes; pRegEntry->pValueAttributes = NULL; } cleanup: LEAVE_SQLITE_LOCK(&pConn->lock, bInDbLock); LWREG_UNLOCK_MUTEX(bInLock, &gActiveKeyList.mutex); SqliteSafeFreeKeyHandle(pKeyHandleInUse); LWREG_SAFE_FREE_MEMORY(pwszValueName); LWREG_SAFE_FREE_MEMORY(pwszKeyNameWithSubKey); RegDbSafeFreeEntryValue(&pRegValueEntry); RegSafeFreeCurrentValueInfo(&pCurrentValue); RegDbSafeFreeEntryValueAttributes(&pRegEntry); return status; error: if (pszError) { sqlite3_free(pszError); } sqlite3_exec(pConn->pDb, "rollback", NULL, NULL, NULL); if (ppCurrentValue) { *ppCurrentValue = NULL; } if (ppValueAttributes) { *ppValueAttributes = NULL; } goto cleanup; }
NTSTATUS RdrTreeConnect( PCWSTR pwszHostname, PCWSTR pwszSharename, PIO_CREDS pCreds, uid_t Uid, BOOLEAN bStopOnDfs, PRDR_OP_CONTEXT pContinue ) { NTSTATUS status = STATUS_SUCCESS; PRDR_OP_CONTEXT pContext = NULL; BOOLEAN bSocketLocked = FALSE; PRDR_SOCKET pSocket = NULL; status = RdrCreateContext(pContinue->pIrp, &pContext); BAIL_ON_NT_STATUS(status); LWIO_LOG_DEBUG("Tree connect context %p will continue %p\n", pContext, pContinue); pContext->State.TreeConnect.Uid = Uid; pContext->State.TreeConnect.bStopOnDfs = bStopOnDfs; pContext->State.TreeConnect.pContinue = pContinue; status = LwRtlWC16StringDuplicate( &pContext->State.TreeConnect.pwszSharename, pwszSharename); BAIL_ON_NT_STATUS(status); pContext->State.TreeConnect.pCreds = pCreds; status = RdrSocketFindOrCreate( pwszHostname, &pSocket); BAIL_ON_NT_STATUS(status); pContext->State.TreeConnect.pSocket = pSocket; LWIO_LOCK_MUTEX(bSocketLocked, &pSocket->mutex); switch (pSocket->state) { case RDR_SOCKET_STATE_NOT_READY: pSocket->state = RDR_SOCKET_STATE_CONNECTING; LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex); /* Add extra reference to socket for work item */ RdrSocketRetain(pSocket); status = LwRtlQueueWorkItem( gRdrRuntime.pThreadPool, RdrSocketConnectWorkItem, pSocket, 0); if (status) { /* Nevermind */ RdrSocketRelease(pSocket); } BAIL_ON_NT_STATUS(status); pContext->Continue = RdrProcessNegotiateResponse; status = RdrTransceiveNegotiate(pContext, pSocket); BAIL_ON_NT_STATUS(status); break; case RDR_SOCKET_STATE_CONNECTING: case RDR_SOCKET_STATE_NEGOTIATING: pContext->Continue = RdrNegotiateComplete; LwListInsertTail(&pSocket->StateWaiters, &pContext->Link); status = STATUS_PENDING; BAIL_ON_NT_STATUS(status); break; case RDR_SOCKET_STATE_READY: LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex); RdrNegotiateComplete(pContext, STATUS_SUCCESS, pSocket); status = STATUS_PENDING; BAIL_ON_NT_STATUS(status); break; case RDR_SOCKET_STATE_ERROR: status = pSocket->error; BAIL_ON_NT_STATUS(status); break; } cleanup: LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex); if (status != STATUS_PENDING) { RdrFreeTreeConnectContext(pContext); } return status; error: if (status != STATUS_PENDING && pSocket) { LWIO_UNLOCK_MUTEX(bSocketLocked, &pSocket->mutex); RdrSocketInvalidate(pSocket, status); RdrSocketRelease(pSocket); } 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; }
BOOLEAN RdrCreateTreeConnect2Complete( PRDR_OP_CONTEXT pContext, NTSTATUS status, PVOID pParam ) { PRDR_TREE2 pTree = pParam; PIRP pIrp = pContext->pIrp; ACCESS_MASK DesiredAccess = pIrp->Args.Create.DesiredAccess; LONG64 AllocationSize = pIrp->Args.Create.AllocationSize; FILE_SHARE_FLAGS ShareAccess = pIrp->Args.Create.ShareAccess; FILE_CREATE_DISPOSITION CreateDisposition = pIrp->Args.Create.CreateDisposition; FILE_CREATE_OPTIONS CreateOptions = pIrp->Args.Create.CreateOptions; FILE_ATTRIBUTES FileAttributes = pIrp->Args.Create.FileAttributes; PIO_CREDS pCreds = IoSecurityGetCredentials(pIrp->Args.Create.SecurityContext); PIO_SECURITY_CONTEXT_PROCESS_INFORMATION pProcessInfo = IoSecurityGetProcessInfo(pIrp->Args.Create.SecurityContext); PRDR_CCB2 pFile = NULL; BAIL_ON_NT_STATUS(status); status = LwIoAllocateMemory( sizeof(RDR_CCB2), (PVOID*)&pFile); BAIL_ON_NT_STATUS(status); status = LwErrnoToNtStatus(pthread_mutex_init(&pFile->mutex, NULL)); BAIL_ON_NT_STATUS(status); pFile->bMutexInitialized = TRUE; pFile->version = SMB_PROTOCOL_VERSION_2; pFile->pTree = pTree; pTree = NULL; status = LwRtlWC16StringDuplicate(&pFile->pwszPath, pContext->State.Create.pwszFilename); BAIL_ON_NT_STATUS(status); status = LwRtlWC16StringDuplicate(&pFile->pwszCanonicalPath, pContext->State.Create.pwszCanonicalPath); BAIL_ON_NT_STATUS(status); pContext->Continue = RdrFinishCreate2; pContext->State.Create.pFile2 = pFile; status = RdrTransceiveCreate2( pContext, pFile, DesiredAccess, AllocationSize, FileAttributes, ShareAccess, CreateDisposition, CreateOptions); switch (status) { case STATUS_SUCCESS: case STATUS_PENDING: break; default: pContext->Continue = RdrCreateTreeConnectComplete; pContext->State.Create.pFile2 = NULL; status = RdrDfsConnect( pFile->pTree->pSession->pSocket, pIrp->Args.Create.FileName.FileName, pCreds, pProcessInfo->Uid, status, &pContext->usTry, &pContext->State.Create.pwszFilename, &pContext->State.Create.pwszCanonicalPath, pContext); RdrReleaseFile2(pFile); pFile = NULL; } BAIL_ON_NT_STATUS(status); cleanup: RTL_FREE(&pContext->State.Create.pwszFilename); RTL_FREE(&pContext->State.Create.pwszCanonicalPath); if (status != STATUS_PENDING) { RdrFreeContext(pContext); pIrp->IoStatusBlock.Status = status; IoIrpComplete(pIrp); } return FALSE; error: if (status != STATUS_PENDING && pFile) { RdrReleaseFile2(pFile); } if (status != STATUS_PENDING && pTree) { RdrTree2Release(pTree); } goto cleanup; }
NTSTATUS IoRtlPathUncToInternal( PCWSTR pwszUncPath, PWSTR* ppwszInternalPath ) { NTSTATUS status = STATUS_SUCCESS; PWSTR pwszCopy = NULL; PWSTR pwszIn = NULL; PWSTR pwszOut = NULL; CHAR szCwd[PATH_MAX]; status = LwRtlWC16StringDuplicate(&pwszCopy, pwszUncPath); BAIL_ON_NT_STATUS(status); for(pwszIn = pwszOut = pwszCopy; *pwszIn; pwszIn++) { if (IoRtlPathIsSeparator(*pwszIn)) { *(pwszOut++) = '/'; while (IoRtlPathIsSeparator(pwszIn[1])) { pwszIn++; } } else { *(pwszOut++) = *pwszIn; } } *pwszOut = '\0'; if (IoRtlPathIsSeparator(pwszUncPath[0]) && IoRtlPathIsSeparator(pwszUncPath[1])) { status = LwRtlWC16StringAllocatePrintfW(ppwszInternalPath, L"/rdr%ws", pwszCopy); BAIL_ON_NT_STATUS(status); } else if (IoRtlPathIsSeparator(pwszUncPath[0])) { status = LwRtlWC16StringAllocatePrintfW(ppwszInternalPath, L"/pvfs%ws", pwszCopy); BAIL_ON_NT_STATUS(status); } else { if (getcwd(szCwd, sizeof(szCwd)) == NULL) { status = STATUS_UNSUCCESSFUL; BAIL_ON_NT_STATUS(status); } status = LwRtlWC16StringAllocatePrintfW(ppwszInternalPath, L"/pvfs%s/%ws", szCwd, pwszCopy); BAIL_ON_NT_STATUS(status); } cleanup: RTL_FREE(&pwszCopy); return status; error: *ppwszInternalPath = NULL; goto cleanup; }