|
|
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
dataman.h
Abstract:
Contains data structures and function prototypes for the Service Controller Database Manager and the Group List Database Manager. (Dataman.c & Groupman.c)
Author:
Dan Lafferty (danl) 22-Oct-1993
Environment:
User Mode -Win32
Revision History:
04-Dec-1996 AnirudhS Added CCrashRecord.
17-Aug-1995 AnirudhS Removed State field from LOAD_ORDER_GROUP, since it is recomputed every time it is read.
26-Jun-1995 AnirudhS Added ScNotifyServiceObject.
12-Apr-1995 AnirudhS Added AccountName field to image record.
06-Oct-1993 danl Re-arranged comments so that structures are easier to read.
19-Jan-1992 danl Modified for use with the "real" service controller
20-Mar-1991 danl created --*/
#ifndef SCDATAMAN_INCLUDED
#define SCDATAMAN_INCLUDED
#define USE_GROUPS
//
// ImageFlag definitions
//
#define CANSHARE_FLAG 0x00000001 // service can run in a shared process
#define IS_SYSTEM_SERVICE 0x00000002 // service runs in this exe or the security process
//
// StatusFlag definitions
//
#define DELETE_FLAG 0x00000001 // service is marked for delete
#define UPDATE_FLAG 0x00000002 //
#define CURRENTSTART_FLAG 0x00000004 //
//
// StatusFlag Macros. SR = ServiceRecord
//
#define SET_DELETE_FLAG(SR) (((SR)->StatusFlag) |= DELETE_FLAG)
#define CLEAR_DELETE_FLAG(SR) (((SR)->StatusFlag) &= (~DELETE_FLAG))
#define DELETE_FLAG_IS_SET(SR) (((SR)->StatusFlag) & DELETE_FLAG)
#define SET_UPDATE_FLAG(SR) (((SR)->StatusFlag) |= UPDATE_FLAG)
#define CLEAR_UPDATE_FLAG(SR) (((SR)->StatusFlag) &= (~UPDATE_FLAG))
#define UPDATE_FLAG_IS_SET(SR) (((SR)->StatusFlag) & UPDATE_FLAG)
//
// To get a demand start service to be started correctly in group
// order specified by the ServiceGroupOrder list, we need an additional
// flag to indicate that this service must be included in the same start
// request.
//
#define SET_CURRENTSTART_FLAG(SR) (((SR)->StatusFlag) |= CURRENTSTART_FLAG)
#define CLEAR_CURRENTSTART_FLAG(SR) (((SR)->StatusFlag) &= (~CURRENTSTART_FLAG))
#define CURRENTSTART_FLAG_IS_SET(SR) (((SR)->StatusFlag) & CURRENTSTART_FLAG)
//
// Data Structures
//
//
//==================
// LOAD_ORDER_GROUP
//==================
// NOTE: This is an ordered linked list. The Next group is loaded after
// this group.
//
// Reference count which indicates the number of members in this
// group plus any dependency pointer that points to this group.
// This field is only used for standalone groups so that we know
// when to delete the group entry. This value is always set to
// 0xffffffff if this entry represents an order group.
//
typedef struct _LOAD_ORDER_GROUP { struct _LOAD_ORDER_GROUP *Next; struct _LOAD_ORDER_GROUP *Prev; LPWSTR GroupName; DWORD RefCount;
} LOAD_ORDER_GROUP, *PLOAD_ORDER_GROUP, *LPLOAD_ORDER_GROUP;
//================
// IMAGE_RECORD
//================
typedef struct _IMAGE_RECORD { struct _IMAGE_RECORD *Prev; // linked list
struct _IMAGE_RECORD *Next; // linked list
LPWSTR ImageName; // fully qualified .exe name
DWORD Pid; // Process ID
DWORD ServiceCount; // Num services running in process
HANDLE PipeHandle; // Handle to Service
HANDLE ProcessHandle; // Handle for process
HANDLE ObjectWaitHandle; // Handle for waiting on the process
HANDLE TokenHandle; // Logon token handle
LUID AccountLuid; // Unique LUID for this logon session
HANDLE ProfileHandle; // User profile handle
LPWSTR AccountName; // Account process was started under
DWORD ImageFlags; // Flags for the IMAGE_RECORD
}IMAGE_RECORD, *PIMAGE_RECORD, *LPIMAGE_RECORD;
typedef enum _DEPEND_TYPE { TypeNone = 0, TypeDependOnService = 128, TypeDependOnGroup, TypeDependOnUnresolved // only for service
} DEPEND_TYPE, *PDEPEND_TYPE, *LPDEPEND_TYPE;
//================
// DEPEND_RECORD
//================
// A service record has a pointer to this structure if the service
// must be started after some services, or must be stopped after some
// services.
// NOTE: This is an ordered linked list. This service depends on the
// "Next" service. Question: Does this service depend on all the services
// in the Next chain?
//
// Depend union:
// Based on the DependType field, this pointer may point to a
// service or a group which the service depends on, or an
// unresolved dependency structure.
//
typedef struct _DEPEND_RECORD { struct _DEPEND_RECORD *Next; DEPEND_TYPE DependType; union { struct _SERVICE_RECORD * DependService; struct _LOAD_ORDER_GROUP * DependGroup; struct _UNRESOLVED_DEPEND * DependUnresolved; LPVOID Depend; // used when type doesn't matter
}; } DEPEND_RECORD, *PDEPEND_RECORD, *LPDEPEND_RECORD;
//================
// CCrashRecord
//================
// This structure counts a service's crashes and remembers the time of the
// last crash. It is allocated only for services that crash.
//
class CCrashRecord { public: CCrashRecord() : _LastCrashTime(0), _Count(0) { }
DWORD IncrementCount(DWORD ResetSeconds);
private:
__int64 _LastCrashTime; // FILETIME = __int64
DWORD _Count; };
//================
// SERVICE_RECORD
//================
// Dependency information:
// StartDepend is a linked list of services and groups that must be
// started first before this service can start.
// StopDepend is a linked list of services and groups that must be
// stopped first before this service can stop.
// Dependencies is a string read in from the registry. Deleted when
// the info has been converted to a StartDepend list.
//
// StartError:
// Error encountered by service controller when starting a service.
// This is distinguished from error posted by the service itself in
// the exitcode field.
//
// StartState:
// SC managed service state which is distinguished from the service
// current state to enable correct handling of start dependencies.
//
// Load order group information:
//
// MemberOfGroup is a pointer to a load order group which this service
// is currently a member of. This value is set to NULL if this
// service does not belong to a group. A non-NULL pointer could
// point to a group entry in either the order group or standalone
// group list.
//
// RegistryGroup is a pointer to a group which we have recorded in the
// registry as the group this service belongs to. This is not the
// same as MemberOfGroup whenever the service is running and the
// load order group of the service has been changed
//
typedef struct _SERVICE_RECORD { struct _SERVICE_RECORD *Prev; // linked list
struct _SERVICE_RECORD *Next; // linked list
LPWSTR ServiceName; // points to service name
LPWSTR DisplayName; // points to display name
DWORD ResumeNum; // Ordered number for this rec
DWORD ServerAnnounce; // Server announcement bit flags
DWORD Signature; // Identifies this as a service record.
DWORD UseCount; // How many open handles to service
DWORD StatusFlag; // status(delete,update...)
union { LPIMAGE_RECORD ImageRecord; // Points to image record
LPWSTR ObjectName; // Points to driver object name
}; SERVICE_STATUS ServiceStatus; // see winsvc.h
DWORD StartType; // AUTO, DEMAND, etc.
DWORD ErrorControl; // NORMAL, SEVERE, etc.
DWORD Tag; // DWORD Id for the service,0=none.
LPDEPEND_RECORD StartDepend; LPDEPEND_RECORD StopDepend; LPWSTR Dependencies; PSECURITY_DESCRIPTOR ServiceSd; DWORD StartError; DWORD StartState; LPLOAD_ORDER_GROUP MemberOfGroup; LPLOAD_ORDER_GROUP RegistryGroup; CCrashRecord * CrashRecord; } SERVICE_RECORD, *PSERVICE_RECORD, *LPSERVICE_RECORD;
//===================
// UNRESOLVED_DEPEND
//===================
// Unresolved dependency record structure
//
// Unresolved dependency entries are linked together so that when a
// new service or group is created (installed) we can look it up in this
// list to see if the service or group is already depended on by some
// other service.
//
typedef struct _UNRESOLVED_DEPEND { struct _UNRESOLVED_DEPEND *Next; struct _UNRESOLVED_DEPEND *Prev; LPWSTR Name; // Service or group name
DWORD RefCount; } UNRESOLVED_DEPEND, *PUNRESOLVED_DEPEND, *LPUNRESOLVED_DEPEND;
//
// Macros & Constants
//
//
// for every service record in the database...
//
#define FOR_ALL_SERVICES(SR) \
SC_ASSERT(ScServiceListLock.Have()); \ for (LPSERVICE_RECORD SR = ScGetServiceDatabase(); \ SR != NULL; \ SR = SR->Next)
//
// for every service record in the database that meets this condition...
//
#define FOR_SERVICES_THAT(SR, condition) \
FOR_ALL_SERVICES(SR) \ if (!(condition)) \ continue; \ else
#define FIND_END_OF_LIST(record) while((record)->Next != NULL) { \
(record)=(record)->Next; \ }
#define REMOVE_FROM_LIST(record) (record)->Prev->Next = (record)->Next; \
if ((record)->Next != NULL) { \ (record)->Next->Prev = (record)->Prev; \ }
#define ADD_TO_LIST(record, newRec) FIND_END_OF_LIST((record)) \
(record)->Next = (newRec); \ (newRec)->Prev = (record); \ (newRec)->Next = NULL;
//
// Service controller maintains the state of a service when
// starting up a service and its dependencies in the StartState
// field of the service record.
//
#define SC_NEVER_STARTED 0x00000000
#define SC_START_NOW 0x00000001
#define SC_START_PENDING 0x00000002
#define SC_START_SUCCESS 0x00000003
#define SC_START_FAIL 0x00000004
#define TERMINATE_TIMEOUT 20000 // wait response to terminate req.
//
// External Globals
//
extern LPLOAD_ORDER_GROUP ScGlobalTDIGroup; extern LPLOAD_ORDER_GROUP ScGlobalPNP_TDIGroup;
//
// Function Prototypes
//
LPLOAD_ORDER_GROUP ScGetOrderGroupList( VOID );
LPLOAD_ORDER_GROUP ScGetStandaloneGroupList( VOID );
LPSERVICE_RECORD ScGetServiceDatabase( VOID );
LPUNRESOLVED_DEPEND ScGetUnresolvedDependList( VOID );
BOOL ScInitDatabase( VOID );
VOID ScInitGroupDatabase(VOID);
VOID ScEndGroupDatabase(VOID);
DWORD ScCreateDependRecord( IN BOOL IsStartList, IN OUT PSERVICE_RECORD ServiceRecord, OUT PDEPEND_RECORD *DependRecord );
DWORD ScCreateImageRecord ( OUT LPIMAGE_RECORD *ImageRecordPtr, IN LPWSTR ImageName, IN LPWSTR AccountName, IN DWORD Pid, IN HANDLE PipeHandle, IN HANDLE ProcessHandle, IN HANDLE TokenHandle, IN HANDLE ProfileHandle, IN DWORD ImageFlags );
DWORD ScCreateServiceRecord( IN LPWSTR ServiceName, OUT LPSERVICE_RECORD *ServiceRecord );
VOID ScFreeServiceRecord( IN LPSERVICE_RECORD ServiceRecord );
VOID ScDecrementUseCountAndDelete( LPSERVICE_RECORD ServiceRecord );
BOOL ScFindEnumStart( IN DWORD ResumeIndex, OUT LPSERVICE_RECORD *ServiceRecordPtr );
BOOL ScGetNamedImageRecord ( IN LPWSTR ImageName, OUT LPIMAGE_RECORD *ImageRecordPtr );
DWORD ScGetNamedServiceRecord ( IN LPWSTR ServiceName, OUT LPSERVICE_RECORD *ServiceRecordPtr );
LPLOAD_ORDER_GROUP ScGetNamedGroupRecord( IN LPCWSTR GroupName );
DWORD ScGetDisplayNamedServiceRecord ( IN LPWSTR ServiceDisplayName, OUT LPSERVICE_RECORD *ServiceRecordPtr );
DWORD ScGetTotalNumberOfRecords( VOID );
VOID ScProcessCleanup( HANDLE ProcessHandle );
VOID ScQueueRecoveryAction( IN LPSERVICE_RECORD ServiceRecord );
VOID ScDeleteMarkedServices( VOID );
DWORD ScUpdateServiceRecord ( IN LPSERVICE_STATUS ServiceStatus, IN LPSERVICE_RECORD ServiceRecord );
DWORD ScRemoveService ( IN LPSERVICE_RECORD ServiceRecord );
DWORD ScTerminateServiceProcess ( IN PIMAGE_RECORD ImageRecord );
VOID ScDeleteImageRecord ( IN LPIMAGE_RECORD ImageRecord );
VOID ScActivateServiceRecord ( IN LPSERVICE_RECORD ServiceRecord, IN LPIMAGE_RECORD ImageRecord );
DWORD ScDeactivateServiceRecord ( IN LPSERVICE_RECORD ServiceRecord );
DWORD ScCreateOrderGroupEntry( IN LPWSTR GroupName );
DWORD ScAddConfigInfoServiceRecord( IN LPSERVICE_RECORD ServiceRecord, IN DWORD ServiceType, IN DWORD StartType, IN DWORD ErrorControl, IN LPWSTR Group OPTIONAL, IN DWORD Tag, IN LPWSTR Dependencies OPTIONAL, IN LPWSTR DisplayName OPTIONAL, IN PSECURITY_DESCRIPTOR Sd OPTIONAL );
VOID ScGenerateDependencies( VOID );
DWORD ScSetDependencyPointers( LPSERVICE_RECORD Service );
DWORD ScResolveDependencyToService( LPSERVICE_RECORD Service );
VOID ScUnresolveDependencyToService( LPSERVICE_RECORD Service );
DWORD ScCreateDependencies( OUT PSERVICE_RECORD ServiceRecord, IN LPWSTR Dependencies OPTIONAL );
VOID ScDeleteStartDependencies( IN PSERVICE_RECORD ServiceRecord );
VOID ScDeleteStopDependencies( IN PSERVICE_RECORD ServiceToBeDeleted );
DWORD ScCreateGroupMembership( OUT PSERVICE_RECORD ServiceRecord, IN LPWSTR Group OPTIONAL );
VOID ScDeleteGroupMembership( IN OUT PSERVICE_RECORD ServiceRecord );
DWORD ScCreateRegistryGroupPointer( OUT PSERVICE_RECORD ServiceRecord, IN LPWSTR Group OPTIONAL );
VOID ScDeleteRegistryGroupPointer( IN OUT PSERVICE_RECORD ServiceRecord );
VOID ScGetUniqueTag( IN LPWSTR GroupName, OUT LPDWORD Tag );
DWORD ScUpdateServiceRecordConfig( LPSERVICE_RECORD ServiceRecord, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPWSTR lpLoadOrderGroup, LPBYTE lpDependencies );
VOID ScGetDependencySize( LPSERVICE_RECORD ServiceRecord, LPDWORD DependSize, LPDWORD MaxDependSize );
DWORD ScGetDependencyString( LPSERVICE_RECORD ServiceRecord, DWORD MaxDependSize, DWORD DependSize, LPWSTR lpDependencies );
BOOL ScAllocateSRHeap( DWORD HeapSize );
#if DBG
VOID ScDumpGroups( VOID );
VOID ScDumpServiceDependencies( VOID ); #endif // if DBG
#endif // ifndef SCDATAMAN_INCLUDED
|