/* Editor Settings: expandtabs and use 4 spaces for indentation * ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: * * -*- mode: c, c-basic-offset: 4 -*- */ /* * Copyright Likewise Software 2004-2008 * All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. You should have received a copy of the GNU General * Public License along with this program. If not, see * . * * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING * TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU * GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT * license@likewisesoftware.com */ /* * Copyright (C) Likewise Software. All rights reserved. * * Module Name: * * ipc_registry.c * * Abstract: * * Registry * * Inter-process communication (Server) API for Users * * Authors: Krishna Ganugapati (krishnag@likewisesoftware.com) * Sriram Nambakam (snambakam@likewisesoftware.com) * Marc Guy (mguy@likewisesoftware.com) * Wei Fu (wfu@likewise.com) */ #include "api.h" static NTSTATUS RegSrvIpcCheckPermissions( LWMsgSecurityToken* token, uid_t* puid, gid_t* pgid ) { NTSTATUS status = 0; uid_t euid; gid_t egid; if (strcmp(lwmsg_security_token_get_type(token), "local")) { REG_LOG_WARNING("Unsupported authentication type"); status = STATUS_UNHANDLED_EXCEPTION; BAIL_ON_NT_STATUS(status); } status = MAP_LWMSG_ERROR(lwmsg_local_token_get_eid(token, &euid, &egid)); BAIL_ON_NT_STATUS(status); REG_LOG_VERBOSE("Permission granted for (uid = %i, gid = %i) to open RegIpcServer", (int) euid, (int) egid); *puid = euid; *pgid = egid; error: return status; } static NTSTATUS RegSrvIpcRegisterHandle( LWMsgCall* pCall, PCSTR pszHandleType, PVOID pHandle, LWMsgHandleCleanupFunction pfnCleanup ) { NTSTATUS status = 0; LWMsgSession* pSession = lwmsg_call_get_session(pCall); status = MAP_LWMSG_ERROR(lwmsg_session_register_handle(pSession, pszHandleType, pHandle, pfnCleanup)); BAIL_ON_NT_STATUS(status); error: return status; } static NTSTATUS RegSrvIpcRetainHandle( LWMsgCall* pCall, PVOID pHandle ) { NTSTATUS status = 0; LWMsgSession* pSession = lwmsg_call_get_session(pCall); status = MAP_LWMSG_ERROR(lwmsg_session_retain_handle(pSession, pHandle)); BAIL_ON_NT_STATUS(status); error: return status; } static VOID RegSrvIpcCloseHandle( PVOID pHandle ) { return RegSrvCloseKey((HKEY)pHandle); } static NTSTATUS RegSrvIpcUnregisterHandle( LWMsgCall* pCall, PVOID pHandle ) { NTSTATUS status = 0; LWMsgSession* pSession = lwmsg_call_get_session(pCall); status = MAP_LWMSG_ERROR(lwmsg_session_unregister_handle(pSession, pHandle)); BAIL_ON_NT_STATUS(status); error: return status; } static HANDLE RegSrvIpcGetSessionData( LWMsgCall* pCall ) { LWMsgSession* pSession = lwmsg_call_get_session(pCall); return lwmsg_session_get_data(pSession); } void RegSrvIpcDestructSession( LWMsgSecurityToken* pToken, void* pSessionData ) { RegSrvCloseServer(pSessionData); } LWMsgStatus RegSrvIpcConstructSession( LWMsgSecurityToken* pToken, void* pData, void** ppSessionData ) { NTSTATUS status = 0; HANDLE Handle = (HANDLE)NULL; uid_t UID; gid_t GID; status = RegSrvIpcCheckPermissions(pToken, &UID, &GID); BAIL_ON_NT_STATUS(status); status = RegSrvOpenServer(UID, GID, &Handle); BAIL_ON_NT_STATUS(status); *ppSessionData = Handle; cleanup: return MAP_REG_ERROR_IPC(status); error: 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; status = RegSrvCreateAccessToken(peerUID, peerGID, &pServerState->pToken); BAIL_ON_NT_STATUS(status); *phServer = (HANDLE)pServerState; cleanup: return status; error: *phServer = (HANDLE)NULL; if (pServerState) { RegSrvCloseServer((HANDLE)pServerState); } goto cleanup; } void RegSrvCloseServer( HANDLE hServer ) { PREG_SRV_API_STATE pServerState = (PREG_SRV_API_STATE)hServer; if (pServerState->hEventLog != (HANDLE)NULL) { //RegSrvCloseEventLog(pServerState->hEventLog); } if (pServerState->pToken) { RtlReleaseAccessToken(&pServerState->pToken); } LwRtlMemoryFree(pServerState); } 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; } 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; iCountdata; PREG_IPC_CREATE_KEY_EX_RESPONSE pRegResp = NULL; PREG_IPC_STATUS pStatus = NULL; HKEY hkResult = NULL; DWORD dwDisposition = 0; status = RegSrvCreateKeyEx( RegSrvIpcGetSessionData(pCall), pReq->hKey, pReq->pSubKey, 0, pReq->pClass, pReq->dwOptions, pReq->AccessDesired, pReq->pSecDescRel, pReq->ulSecDescLen, &hkResult, &dwDisposition ); if (!status) { status = LW_RTL_ALLOCATE((PVOID*)&pRegResp, REG_IPC_CREATE_KEY_EX_RESPONSE, sizeof(*pRegResp)); BAIL_ON_NT_STATUS(status); pRegResp->dwDisposition = dwDisposition; pRegResp->hkResult = hkResult; hkResult = NULL; status = RegSrvIpcRegisterHandle( pCall, "HKEY", (PVOID)pRegResp->hkResult, RegSrvIpcCloseHandle); BAIL_ON_NT_STATUS(status); pOut->tag = REG_R_CREATE_KEY_EX; pOut->data = pRegResp; status = RegSrvIpcRetainHandle(pCall, pRegResp->hkResult); BAIL_ON_NT_STATUS(status); } else { status = RegSrvIpcCreateError(status, &pStatus); BAIL_ON_NT_STATUS(status); pOut->tag = REG_R_ERROR; pOut->data = pStatus; } cleanup: RegSrvIpcCloseHandle((PVOID)hkResult); return MAP_REG_ERROR_IPC(status); error: goto cleanup; } LWMsgStatus RegSrvIpcOpenKeyExW( LWMsgCall* pCall, const LWMsgParams* pIn, LWMsgParams* pOut, void* data ) { NTSTATUS status = 0; PREG_IPC_OPEN_KEY_EX_REQ pReq = pIn->data; PREG_IPC_OPEN_KEY_EX_RESPONSE pRegResp = NULL; PREG_IPC_STATUS pStatus = NULL; HKEY hkResult = NULL; status = RegSrvOpenKeyExW( RegSrvIpcGetSessionData(pCall), pReq->hKey, pReq->pSubKey, 0, pReq->AccessDesired, &hkResult ); if (!status) { status = LW_RTL_ALLOCATE((PVOID*)&pRegResp, REG_IPC_OPEN_KEY_EX_RESPONSE, sizeof(*pRegResp)); BAIL_ON_NT_STATUS(status); pRegResp->hkResult = hkResult; hkResult = NULL; status = RegSrvIpcRegisterHandle( pCall, "HKEY", (PVOID)pRegResp->hkResult, RegSrvIpcCloseHandle); BAIL_ON_NT_STATUS(status); pOut->tag = REG_R_OPEN_KEYW_EX; pOut->data = pRegResp; status = RegSrvIpcRetainHandle(pCall, pRegResp->hkResult); BAIL_ON_NT_STATUS(status); } else { status = RegSrvIpcCreateError(status, &pStatus); BAIL_ON_NT_STATUS(status); pOut->tag = REG_R_ERROR; pOut->data = pStatus; } cleanup: RegSrvIpcCloseHandle((PVOID)hkResult); return MAP_REG_ERROR_IPC(status); error: goto cleanup; } LWMsgStatus RegSrvIpcCloseKey( LWMsgCall* pCall, const LWMsgParams* pIn, LWMsgParams* pOut, void* data ) { NTSTATUS status = 0; PREG_IPC_CLOSE_KEY_REQ pReq = pIn->data; PREG_IPC_STATUS pStatus = NULL; status = RegSrvIpcUnregisterHandle(pCall, pReq->hKey); if (!status) { pOut->tag = REG_R_CLOSE_KEY; pOut->data = NULL; } 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; } LWMsgStatus RegSrvIpcDeleteKey( LWMsgCall* pCall, const LWMsgParams* pIn, LWMsgParams* pOut, void* data ) { NTSTATUS status = 0; PREG_IPC_DELETE_KEY_REQ pReq = pIn->data; PREG_IPC_STATUS pStatus = NULL; status = RegSrvDeleteKey( RegSrvIpcGetSessionData(pCall), pReq->hKey, pReq->pSubKey ); if (!status) { pOut->tag = REG_R_DELETE_KEY; pOut->data = NULL; } 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; } LWMsgStatus RegSrvIpcEnumKeyExW( LWMsgCall* pCall, const LWMsgParams* pIn, LWMsgParams* pOut, void* data ) { NTSTATUS status = 0; PREG_IPC_ENUM_KEY_EX_REQ pReq = pIn->data; PREG_IPC_ENUM_KEY_EX_RESPONSE pRegResp = NULL; PWSTR pKeyName = NULL; PWSTR pClassName = NULL; PREG_IPC_STATUS pStatus = NULL; if (pReq->cName) { status = LW_RTL_ALLOCATE((PVOID*)&pKeyName, WCHAR, pReq->cName*sizeof(*pKeyName)); BAIL_ON_NT_STATUS(status); } if (pReq->cClass) { status = LW_RTL_ALLOCATE((PVOID*)&pClassName, WCHAR, pReq->cClass*sizeof(*pClassName)); BAIL_ON_NT_STATUS(status); } status = RegSrvEnumKeyExW( RegSrvIpcGetSessionData(pCall), pReq->hKey, pReq->dwIndex, pKeyName, &pReq->cName, NULL, pClassName, &pReq->cClass, NULL ); if (!status) { status = LW_RTL_ALLOCATE((PVOID*)&pRegResp, REG_IPC_ENUM_KEY_EX_RESPONSE, sizeof(*pRegResp)); BAIL_ON_NT_STATUS(status); pRegResp->pName= pKeyName; pKeyName = NULL; pRegResp->cName = pReq->cName; pRegResp->pClass= pClassName; pClassName = NULL; pRegResp->cClass = pReq->cClass; pOut->tag = REG_R_ENUM_KEYW_EX; 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(pKeyName); LWREG_SAFE_FREE_MEMORY(pClassName); return MAP_REG_ERROR_IPC(status); error: goto cleanup; } LWMsgStatus RegSrvIpcQueryInfoKeyW( LWMsgCall* pCall, const LWMsgParams* pIn, LWMsgParams* pOut, void* data ) { NTSTATUS status = 0; PREG_IPC_QUERY_INFO_KEY_REQ pReq = pIn->data; PREG_IPC_QUERY_INFO_KEY_RESPONSE pRegResp = NULL; PREG_IPC_STATUS pStatus = NULL; DWORD dwSubKeyCount = 0; DWORD dwMaxKeyLength = 0; DWORD dwValueCount = 0; DWORD dwMaxValueNameLen = 0; DWORD dwMaxValueLen = 0; DWORD dwSecurityDescriptorLen = 0; status = RegSrvQueryInfoKeyW( RegSrvIpcGetSessionData(pCall), pReq->hKey, NULL, pReq->pcClass, NULL, &dwSubKeyCount, &dwMaxKeyLength, NULL, &dwValueCount, &dwMaxValueNameLen, &dwMaxValueLen, &dwSecurityDescriptorLen, NULL ); if (!status) { status = LW_RTL_ALLOCATE((PVOID*)&pRegResp, REG_IPC_QUERY_INFO_KEY_RESPONSE, sizeof(*pRegResp)); BAIL_ON_NT_STATUS(status); pRegResp->cSubKeys = dwSubKeyCount; pRegResp->cMaxSubKeyLen = dwMaxKeyLength; pRegResp->cValues = dwValueCount; pRegResp->cMaxValueNameLen = dwMaxValueNameLen; pRegResp->cMaxValueLen = dwMaxValueLen; pRegResp->cSecurityDescriptor = dwSecurityDescriptorLen; pOut->tag = REG_R_QUERY_INFO_KEYW; 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; } 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; if (pReq->cbData) { status = LW_RTL_ALLOCATE((PVOID*)&pData, BYTE, pReq->cbData*sizeof(*pData)); BAIL_ON_NT_STATUS(status); } status = RegSrvGetValueW( RegSrvIpcGetSessionData(pCall), pReq->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; } LWMsgStatus RegSrvIpcDeleteKeyValue( LWMsgCall* pCall, const LWMsgParams* pIn, LWMsgParams* pOut, void* data ) { NTSTATUS status = 0; PREG_IPC_DELETE_KEY_VALUE_REQ pReq = pIn->data; PREG_IPC_STATUS pStatus = NULL; status = RegSrvDeleteKeyValue( RegSrvIpcGetSessionData(pCall), pReq->hKey, pReq->pSubKey, pReq->pValueName ); if (!status) { pOut->tag = REG_R_DELETE_KEY_VALUE; pOut->data = NULL; } 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; } LWMsgStatus RegSrvIpcDeleteTree( LWMsgCall* pCall, const LWMsgParams* pIn, LWMsgParams* pOut, void* data ) { NTSTATUS status = 0; PREG_IPC_DELETE_TREE_REQ pReq = pIn->data; PREG_IPC_STATUS pStatus = NULL; status = RegSrvDeleteTree( RegSrvIpcGetSessionData(pCall), pReq->hKey, pReq->pSubKey ); if (!status) { pOut->tag = REG_R_DELETE_TREE; pOut->data = NULL; } 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; } LWMsgStatus RegSrvIpcDeleteValue( LWMsgCall* pCall, const LWMsgParams* pIn, LWMsgParams* pOut, void* data ) { NTSTATUS status = 0; PREG_IPC_DELETE_VALUE_REQ pReq = pIn->data; PREG_IPC_STATUS pStatus = NULL; status = RegSrvDeleteValue( RegSrvIpcGetSessionData(pCall), pReq->hKey, pReq->pValueName ); if (!status) { pOut->tag = REG_R_DELETE_VALUE; pOut->data = NULL; } 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; } 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_UNKNOWN; 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), pReq->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; } 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; status = RegSrvQueryMultipleValues( RegSrvIpcGetSessionData(pCall), pReq->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; } LWMsgStatus RegSrvIpcSetValueExW( LWMsgCall* pCall, const LWMsgParams* pIn, LWMsgParams* pOut, void* data ) { NTSTATUS status = 0; PREG_IPC_SET_VALUE_EX_REQ pReq = pIn->data; PREG_IPC_STATUS pStatus = NULL; status = RegSrvSetValueExW( RegSrvIpcGetSessionData(pCall), pReq->hKey, pReq->pValueName, 0, pReq->dwType, pReq->pData, pReq->cbData ); if (!status) { pOut->tag = REG_R_SET_VALUEW_EX; pOut->data = NULL; } 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; } LWMsgStatus RegSrvIpcSetKeySecurity( LWMsgCall* pCall, const LWMsgParams* pIn, LWMsgParams* pOut, void* data ) { NTSTATUS status = 0; PREG_IPC_SET_KEY_SECURITY_REQ pReq = pIn->data; PREG_IPC_STATUS pStatus = NULL; status = RegSrvSetKeySecurity(RegSrvIpcGetSessionData(pCall), pReq->hKey, pReq->SecurityInformation, pReq->SecurityDescriptor, pReq->Length); if (!status) { pOut->tag = REG_R_SET_KEY_SECURITY; pOut->data = NULL; } 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; } 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; if (pReq->Length) { status = LW_RTL_ALLOCATE((PVOID*)&pSecDescRel, VOID, pReq->Length); BAIL_ON_NT_STATUS(status); } status = RegSrvGetKeySecurity(RegSrvIpcGetSessionData(pCall), pReq->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; }