613 lines
15 KiB
C++
613 lines
15 KiB
C++
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1996 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
setupsrv.cpp
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Routines for secedit integration with system setup and component setup
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Jin Huang (jinhuang) 15-Aug-1997
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
jinhuang 26-Jan-1998 splitted to client-server
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "headers.h"
|
|||
|
#include "serverp.h"
|
|||
|
#include "srvrpcp.h"
|
|||
|
#include "pfp.h"
|
|||
|
#include <io.h>
|
|||
|
|
|||
|
|
|||
|
SCESTATUS
|
|||
|
ScepUpdateObjectInSection(
|
|||
|
IN PSCECONTEXT hProfile,
|
|||
|
IN SCETYPE ProfileType,
|
|||
|
IN PWSTR ObjectName,
|
|||
|
IN SE_OBJECT_TYPE ObjectType,
|
|||
|
IN UINT nFlag,
|
|||
|
IN PWSTR SDText,
|
|||
|
OUT UINT *pStatus
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// implementations
|
|||
|
//
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
ScepSetupUpdateObject(
|
|||
|
IN PSCECONTEXT Context,
|
|||
|
IN PWSTR ObjectFullName,
|
|||
|
IN SE_OBJECT_TYPE ObjectType,
|
|||
|
IN UINT nFlag,
|
|||
|
IN PWSTR SDText
|
|||
|
)
|
|||
|
/*
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is the private API called from the RPC interface to
|
|||
|
update object information in the database.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Context - the database context handle
|
|||
|
|
|||
|
ObjectFullName - the object's name
|
|||
|
|
|||
|
Objecttype - the object type
|
|||
|
|
|||
|
nFlag - the flag on how to update this object
|
|||
|
|
|||
|
SDText - the security descriptor in SDDL text
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
*/
|
|||
|
{
|
|||
|
|
|||
|
if ( !ObjectFullName || NULL == SDText ) {
|
|||
|
return ERROR_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
switch ( ObjectType ) {
|
|||
|
case SE_SERVICE:
|
|||
|
case SE_REGISTRY_KEY:
|
|||
|
case SE_FILE_OBJECT:
|
|||
|
break;
|
|||
|
default:
|
|||
|
return ERROR_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
SCESTATUS rc;
|
|||
|
|
|||
|
DWORD dwInSetup=0;
|
|||
|
|
|||
|
ScepRegQueryIntValue(HKEY_LOCAL_MACHINE,
|
|||
|
TEXT("System\\Setup"),
|
|||
|
TEXT("SystemSetupInProgress"),
|
|||
|
&dwInSetup
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// convert SDText to security descriptor
|
|||
|
//
|
|||
|
PSECURITY_DESCRIPTOR pSD=NULL;
|
|||
|
DWORD SDSize;
|
|||
|
SECURITY_INFORMATION SeInfo=0;
|
|||
|
HANDLE Token=NULL;
|
|||
|
|
|||
|
DWORD Win32rc=ERROR_SUCCESS;
|
|||
|
|
|||
|
if ( !(nFlag & SCESETUP_UPDATE_DB_ONLY) ) {
|
|||
|
//
|
|||
|
// security will be set, so compute the security descriptor
|
|||
|
//
|
|||
|
Win32rc = ConvertTextSecurityDescriptor (
|
|||
|
SDText,
|
|||
|
&pSD,
|
|||
|
&SDSize,
|
|||
|
&SeInfo
|
|||
|
);
|
|||
|
|
|||
|
if ( NO_ERROR == Win32rc ) {
|
|||
|
|
|||
|
ScepChangeAclRevision(pSD, ACL_REVISION);
|
|||
|
|
|||
|
//
|
|||
|
// get current thread/process's token
|
|||
|
//
|
|||
|
if (!OpenThreadToken( GetCurrentThread(),
|
|||
|
TOKEN_QUERY,
|
|||
|
FALSE,
|
|||
|
&Token)) {
|
|||
|
|
|||
|
if (!OpenProcessToken( GetCurrentProcess(),
|
|||
|
TOKEN_QUERY,
|
|||
|
&Token)) {
|
|||
|
|
|||
|
Win32rc = GetLastError();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( Token && (SeInfo & SACL_SECURITY_INFORMATION) ) {
|
|||
|
|
|||
|
SceAdjustPrivilege( SE_SECURITY_PRIVILEGE, TRUE, Token );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( NO_ERROR == Win32rc ) {
|
|||
|
|
|||
|
//
|
|||
|
// only update DB if it's in setup
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// on 64-bit platform, only update database if setup does not indicate SCE_SETUP_32KEY flag
|
|||
|
//
|
|||
|
|
|||
|
#ifdef _WIN64
|
|||
|
if ( dwInSetup && !(nFlag & SCE_SETUP_32KEY) ) {
|
|||
|
#else
|
|||
|
if ( dwInSetup ) {
|
|||
|
#endif
|
|||
|
|
|||
|
// save this into SCP and SMP, do not overwrite the status/container flag
|
|||
|
// if there is one exist, else use SCE_STATUS_CHECK and check for container
|
|||
|
//
|
|||
|
//
|
|||
|
// start a transaction since there are multiple operations
|
|||
|
//
|
|||
|
|
|||
|
rc = SceJetStartTransaction( Context );
|
|||
|
|
|||
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|||
|
|
|||
|
UINT Status=SCE_STATUS_CHECK;
|
|||
|
|
|||
|
rc = ScepUpdateObjectInSection(
|
|||
|
Context,
|
|||
|
SCE_ENGINE_SMP,
|
|||
|
ObjectFullName,
|
|||
|
ObjectType,
|
|||
|
nFlag,
|
|||
|
SDText,
|
|||
|
&Status
|
|||
|
);
|
|||
|
|
|||
|
if ( rc == SCESTATUS_SUCCESS &&
|
|||
|
(Context->JetSapID != JET_tableidNil) ) {
|
|||
|
//
|
|||
|
// the SAP table ID points to the tattoo table
|
|||
|
// should update the tattoo table too if it exist
|
|||
|
//
|
|||
|
rc = ScepUpdateObjectInSection(
|
|||
|
Context,
|
|||
|
SCE_ENGINE_SAP,
|
|||
|
ObjectFullName,
|
|||
|
ObjectType,
|
|||
|
nFlag,
|
|||
|
SDText,
|
|||
|
NULL
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
rc = SCESTATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
if ( rc == SCESTATUS_SUCCESS &&
|
|||
|
!(nFlag & SCESETUP_UPDATE_DB_ONLY) ) {
|
|||
|
|
|||
|
//
|
|||
|
// set security to the object
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// if 64-bit platform, no synchronization is done and setup will have
|
|||
|
// to call the exported API with SCE_SETUP_32KEY if 32-bit hive is desired
|
|||
|
//
|
|||
|
|
|||
|
#ifdef _WIN64
|
|||
|
if ( ObjectType == SE_REGISTRY_KEY && (nFlag & SCE_SETUP_32KEY) ){
|
|||
|
ObjectType = SE_REGISTRY_WOW64_32KEY;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
Win32rc = ScepSetSecurityWin32(
|
|||
|
ObjectFullName,
|
|||
|
SeInfo,
|
|||
|
pSD,
|
|||
|
ObjectType
|
|||
|
);
|
|||
|
|
|||
|
} else
|
|||
|
Win32rc = ScepSceStatusToDosError(rc);
|
|||
|
|
|||
|
if ( Win32rc == ERROR_SUCCESS ||
|
|||
|
Win32rc == ERROR_FILE_NOT_FOUND ||
|
|||
|
Win32rc == ERROR_PATH_NOT_FOUND ||
|
|||
|
Win32rc == ERROR_INVALID_OWNER ||
|
|||
|
Win32rc == ERROR_INVALID_PRIMARY_GROUP ||
|
|||
|
Win32rc == ERROR_INVALID_HANDLE ) {
|
|||
|
|
|||
|
if ( Win32rc )
|
|||
|
gWarningCode = Win32rc;
|
|||
|
|
|||
|
if ( dwInSetup ) { // in setup, update DB
|
|||
|
Win32rc = ScepSceStatusToDosError(
|
|||
|
SceJetCommitTransaction( Context, 0));
|
|||
|
} else {
|
|||
|
Win32rc = ERROR_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
} else if ( dwInSetup ) { // in setup
|
|||
|
|
|||
|
SceJetRollback( Context, 0 );
|
|||
|
}
|
|||
|
|
|||
|
if ( Token && (SeInfo & SACL_SECURITY_INFORMATION) )
|
|||
|
SceAdjustPrivilege( SE_SECURITY_PRIVILEGE, FALSE, Token );
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
CloseHandle(Token);
|
|||
|
|
|||
|
if ( pSD ) {
|
|||
|
LocalFree(pSD);
|
|||
|
pSD = NULL;
|
|||
|
}
|
|||
|
|
|||
|
return(Win32rc);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
SCESTATUS
|
|||
|
ScepUpdateObjectInSection(
|
|||
|
IN PSCECONTEXT Context,
|
|||
|
IN SCETYPE ProfileType,
|
|||
|
IN PWSTR ObjectName,
|
|||
|
IN SE_OBJECT_TYPE ObjectType,
|
|||
|
IN UINT nFlag,
|
|||
|
IN PWSTR SDText,
|
|||
|
OUT UINT *pStatus
|
|||
|
)
|
|||
|
/*
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Update SCP and SMP. if the table does not exist at all, ignore the update.
|
|||
|
Delete SAP entry for the object. If table or record not found, ignore the error.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
*/
|
|||
|
{
|
|||
|
if ( Context == NULL || ObjectName == NULL ) {
|
|||
|
return(SCESTATUS_INVALID_PARAMETER);
|
|||
|
}
|
|||
|
|
|||
|
SCESTATUS rc;
|
|||
|
PSCESECTION hSection=NULL;
|
|||
|
PCWSTR SectionName;
|
|||
|
|
|||
|
switch ( ObjectType ) {
|
|||
|
case SE_FILE_OBJECT:
|
|||
|
SectionName = szFileSecurity;
|
|||
|
break;
|
|||
|
case SE_REGISTRY_KEY:
|
|||
|
SectionName = szRegistryKeys;
|
|||
|
break;
|
|||
|
case SE_SERVICE:
|
|||
|
SectionName = szServiceGeneral;
|
|||
|
break;
|
|||
|
default:
|
|||
|
return(SCESTATUS_INVALID_PARAMETER);
|
|||
|
}
|
|||
|
|
|||
|
rc = ScepOpenSectionForName(
|
|||
|
Context,
|
|||
|
ProfileType,
|
|||
|
SectionName,
|
|||
|
&hSection
|
|||
|
);
|
|||
|
if ( rc == SCESTATUS_BAD_FORMAT ||
|
|||
|
rc == SCESTATUS_RECORD_NOT_FOUND ) {
|
|||
|
return(SCESTATUS_SUCCESS);
|
|||
|
}
|
|||
|
|
|||
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|||
|
|
|||
|
WCHAR StatusFlag=L'\0';
|
|||
|
DWORD ValueLen;
|
|||
|
BYTE Status=SCE_STATUS_CHECK;
|
|||
|
BOOL IsContainer=TRUE;
|
|||
|
BYTE StartType;
|
|||
|
|
|||
|
rc = SceJetGetValue(
|
|||
|
hSection,
|
|||
|
SCEJET_EXACT_MATCH_NO_CASE,
|
|||
|
ObjectName,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
NULL,
|
|||
|
(PWSTR)&StatusFlag,
|
|||
|
2,
|
|||
|
&ValueLen
|
|||
|
);
|
|||
|
|
|||
|
if ( rc == SCESTATUS_SUCCESS ||
|
|||
|
rc == SCESTATUS_BUFFER_TOO_SMALL ) {
|
|||
|
|
|||
|
rc = SCESTATUS_SUCCESS;
|
|||
|
|
|||
|
Status = *((BYTE *)&StatusFlag);
|
|||
|
|
|||
|
if ( pStatus ) {
|
|||
|
*pStatus = Status;
|
|||
|
}
|
|||
|
|
|||
|
if ( ObjectType == SE_SERVICE ) {
|
|||
|
StartType = *((BYTE *)&StatusFlag+1);
|
|||
|
} else {
|
|||
|
IsContainer = *((CHAR *)&StatusFlag+1) != '0' ? TRUE : FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if ( ObjectType == SE_SERVICE ) {
|
|||
|
|
|||
|
DWORD SDLen, Len;
|
|||
|
PWSTR ValueToSet;
|
|||
|
|
|||
|
StartType = (BYTE)nFlag;
|
|||
|
|
|||
|
if ( SDText != NULL ) {
|
|||
|
SDLen = wcslen(SDText);
|
|||
|
Len = ( SDLen+1)*sizeof(WCHAR);
|
|||
|
} else
|
|||
|
Len = sizeof(WCHAR);
|
|||
|
|
|||
|
ValueToSet = (PWSTR)ScepAlloc( (UINT)0, Len+sizeof(WCHAR) );
|
|||
|
|
|||
|
if ( ValueToSet != NULL ) {
|
|||
|
|
|||
|
//
|
|||
|
// The first byte is the flag, the second byte is IsContainer (1,0)
|
|||
|
//
|
|||
|
*((BYTE *)ValueToSet) = Status;
|
|||
|
|
|||
|
*((BYTE *)ValueToSet+1) = StartType;
|
|||
|
|
|||
|
if ( SDText != NULL ) {
|
|||
|
swprintf(ValueToSet+1, L"%s", SDText );
|
|||
|
ValueToSet[SDLen+1] = L'\0'; //terminate this string
|
|||
|
} else {
|
|||
|
ValueToSet[1] = L'\0';
|
|||
|
}
|
|||
|
|
|||
|
if ( SCESTATUS_SUCCESS == rc || ProfileType != SCE_ENGINE_SAP ) {
|
|||
|
//
|
|||
|
// only update tattoo table (pointed by SAP handle) if it finds a record there
|
|||
|
// for other table (SMP), ignore the error code, just set
|
|||
|
//
|
|||
|
rc = SceJetSetLine( hSection,
|
|||
|
ObjectName,
|
|||
|
FALSE,
|
|||
|
ValueToSet,
|
|||
|
Len,
|
|||
|
0);
|
|||
|
}
|
|||
|
|
|||
|
ScepFree( ValueToSet );
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
|
|||
|
}
|
|||
|
|
|||
|
} else if ( SCESTATUS_SUCCESS == rc || ProfileType != SCE_ENGINE_SAP ) {
|
|||
|
//
|
|||
|
// only update tattoo table (pointed by SAP handle) if it finds a record there
|
|||
|
// for other table (SMP), ignore the error code, just set
|
|||
|
//
|
|||
|
|
|||
|
rc = ScepSaveObjectString(
|
|||
|
hSection,
|
|||
|
ObjectName,
|
|||
|
IsContainer,
|
|||
|
Status,
|
|||
|
SDText,
|
|||
|
(SDText == NULL ) ? 0 : wcslen(SDText)
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
if ( rc == SCESTATUS_RECORD_NOT_FOUND )
|
|||
|
rc = SCESTATUS_SUCCESS;
|
|||
|
|
|||
|
SceJetCloseSection(&hSection, TRUE);
|
|||
|
}
|
|||
|
|
|||
|
return(rc);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
ScepSetupMoveFile(
|
|||
|
IN PSCECONTEXT Context,
|
|||
|
PWSTR OldName,
|
|||
|
PWSTR NewName OPTIONAL,
|
|||
|
PWSTR SDText OPTIONAL
|
|||
|
)
|
|||
|
/*
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Set security to OldName but save with NewName in SCE database if SDText
|
|||
|
is not NULL. If NewName is NULL, delete OldName from SCE database.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Context - the databaes context handle
|
|||
|
|
|||
|
SectionName - the section name
|
|||
|
|
|||
|
OldName - the object's old name
|
|||
|
|
|||
|
NewName - the new name to rename to, if NULL, delete the old object
|
|||
|
|
|||
|
SDText - security string
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Win32 error code
|
|||
|
*/
|
|||
|
{
|
|||
|
|
|||
|
if ( !Context || !OldName ) {
|
|||
|
return ERROR_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
DWORD rc32=ERROR_SUCCESS;
|
|||
|
|
|||
|
if ( NewName && SDText ) {
|
|||
|
//
|
|||
|
// set security on OldName with SDText
|
|||
|
//
|
|||
|
|
|||
|
rc32 = ScepSetupUpdateObject(
|
|||
|
Context,
|
|||
|
OldName,
|
|||
|
SE_FILE_OBJECT,
|
|||
|
0,
|
|||
|
SDText
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
if ( rc32 == ERROR_SUCCESS ) {
|
|||
|
|
|||
|
//
|
|||
|
// save this into SCP and SMP, do not overwrite the status/container flag
|
|||
|
// if there is one exist, else use SCE_STATUS_CHECK and check for container
|
|||
|
//
|
|||
|
|
|||
|
SCESTATUS rc = SceJetStartTransaction( Context );
|
|||
|
|
|||
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|||
|
|
|||
|
PSCESECTION hSection=NULL;
|
|||
|
//
|
|||
|
// process SMP section first
|
|||
|
//
|
|||
|
rc = ScepOpenSectionForName(
|
|||
|
Context,
|
|||
|
SCE_ENGINE_SMP,
|
|||
|
szFileSecurity,
|
|||
|
&hSection
|
|||
|
);
|
|||
|
|
|||
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|||
|
if ( NewName ) {
|
|||
|
//
|
|||
|
// rename this line
|
|||
|
//
|
|||
|
rc = SceJetRenameLine(
|
|||
|
hSection,
|
|||
|
OldName,
|
|||
|
NewName,
|
|||
|
FALSE);
|
|||
|
|
|||
|
} else {
|
|||
|
//
|
|||
|
// delete this line first
|
|||
|
//
|
|||
|
rc = SceJetDelete(
|
|||
|
hSection,
|
|||
|
OldName,
|
|||
|
FALSE,
|
|||
|
SCEJET_DELETE_LINE_NO_CASE
|
|||
|
);
|
|||
|
}
|
|||
|
SceJetCloseSection( &hSection, TRUE);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if ( (SCESTATUS_SUCCESS == rc ||
|
|||
|
SCESTATUS_RECORD_NOT_FOUND == rc ||
|
|||
|
SCESTATUS_BAD_FORMAT == rc) &&
|
|||
|
(Context->JetSapID != JET_tableidNil) ) {
|
|||
|
//
|
|||
|
// process tattoo table
|
|||
|
//
|
|||
|
rc = ScepOpenSectionForName(
|
|||
|
Context,
|
|||
|
SCE_ENGINE_SAP,
|
|||
|
szFileSecurity,
|
|||
|
&hSection
|
|||
|
);
|
|||
|
|
|||
|
if ( rc == SCESTATUS_SUCCESS ) {
|
|||
|
if ( NewName ) {
|
|||
|
//
|
|||
|
// rename this line
|
|||
|
//
|
|||
|
rc = SceJetRenameLine(
|
|||
|
hSection,
|
|||
|
OldName,
|
|||
|
NewName,
|
|||
|
FALSE);
|
|||
|
|
|||
|
} else {
|
|||
|
//
|
|||
|
// delete this line first
|
|||
|
//
|
|||
|
rc = SceJetDelete(
|
|||
|
hSection,
|
|||
|
OldName,
|
|||
|
FALSE,
|
|||
|
SCEJET_DELETE_LINE_NO_CASE
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
SceJetCloseSection( &hSection, TRUE);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
if ( SCESTATUS_RECORD_NOT_FOUND == rc ||
|
|||
|
SCESTATUS_BAD_FORMAT == rc ) {
|
|||
|
rc = SCESTATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
if ( SCESTATUS_SUCCESS == rc ) {
|
|||
|
//
|
|||
|
// commit the transaction
|
|||
|
//
|
|||
|
rc = SceJetCommitTransaction( Context, 0 );
|
|||
|
} else {
|
|||
|
//
|
|||
|
// rollback the transaction
|
|||
|
//
|
|||
|
SceJetRollback( Context, 0 );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
rc32 = ScepSceStatusToDosError(rc);
|
|||
|
}
|
|||
|
|
|||
|
return(rc32);
|
|||
|
}
|
|||
|
|
|||
|
|