/* 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;
}