Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

764 lines
26 KiB

/*
* INTERNAL.H
*
* Internal header for RSM Service
*
* Author: ErvinP
*
* (c) 2001 Microsoft Corporation
*
*/
typedef struct _SESSION SESSION;
typedef struct _WORKITEM WORKITEM;
typedef struct _WORKGROUP WORKGROUP;
typedef struct _LIBRARY LIBRARY;
typedef struct _TRANSPORT TRANSPORT;
typedef struct _PICKER PICKER;
typedef struct _SLOT SLOT;
typedef struct _DRIVE DRIVE;
typedef struct _MEDIA_POOL MEDIA_POOL;
typedef struct _PHYSICAL_MEDIA PHYSICAL_MEDIA;
typedef struct _MEDIA_PARTITION MEDIA_PARTITION;
typedef struct _OPERATOR_REQUEST OPERATOR_REQUEST;
typedef struct _MEDIA_TYPE_OBJECT MEDIA_TYPE_OBJECT;
typedef struct _OBJECT_HEADER OBJECT_HEADER;
/*
* RSM Object Types
*
* The media hierarchy is as follows:
* ------------------------------
*
* Library
* Media Pool
* Media Sub-Pool - a subset (child pool) of a media pool
* ...
*
* Physical Media
* - a connected set of partitions that have to move together
* e.g. a cartridge or both sides of a disk
*
* Media Partition
* - e.g. a side of a disk or catridge tape
*
*
* Other library elements:
* --------------------
*
* Drives - for reading/writing data on media
*
* Slots - for passively storing media
*
* Changers - for moving media between and amongst slots and drives.
* A changer consists of a moving transport with
* one or more pickers.
*
*
* Logical media ID - a persistent GUID which identifies a media partition.
*
* Media type object - represents a recognized media type
*
*/
enum objectType {
OBJECTTYPE_NONE = 0,
OBJECTTYPE_LIBRARY,
OBJECTTYPE_MEDIAPOOL,
OBJECTTYPE_PHYSICALMEDIA,
OBJECTTYPE_MEDIAPARTITION,
OBJECTTYPE_DRIVE,
OBJECTTYPE_SLOT,
OBJECTTYPE_TRANSPORT,
OBJECTTYPE_PICKER,
OBJECTTYPE_MEDIATYPEOBJECT,
// OBJECTTYPE_OPERATORREQUEST, // BUGBUG - keep in session queue
};
/*
* This is a common header for all RSM objects that have GUIDs.
* It is used to sort guid-identified objects in our hash table.
*/
struct _OBJECT_HEADER {
LIST_ENTRY hashListEntry;
enum objectType objType;
NTMS_GUID guid;
ULONG refCount;
BOOL isDeleted;
};
enum libraryTypes {
LIBTYPE_NONE = 0,
LIBTYPE_UNKNOWN,
LIBTYPE_STANDALONE,
LIBTYPE_AUTOMATED,
};
enum libraryStates {
LIBSTATE_NONE = 0,
LIBSTATE_INITIALIZING,
LIBSTATE_ONLINE,
LIBSTATE_OFFLINE,
LIBSTATE_ERROR,
};
struct _LIBRARY {
OBJECT_HEADER objHeader;
enum libraryStates state;
enum libraryTypes type;
LIST_ENTRY allLibrariesListEntry; // entry in g_allLibrariesList
ULONG numMediaPools;
LIST_ENTRY mediaPoolsList;
ULONG numDrives;
DRIVE *drives;
ULONG numSlots;
SLOT *slots;
/*
* One (and only one) slot may be designated as a cleaner
* slot. That slot may receive a cleaner cartridge (via InjectNtmsCleaner).
* A cleaner cartridge has a limited number of cleans that it is good for.
*/
#define NO_SLOT_INDEX (ULONG)(-1)
ULONG cleanerSlotIndex; // index of cleaner slot or -1.
ULONG numCleansLeftInCartridge;
ULONG numTransports;
TRANSPORT *transports;
ULONG numTotalWorkItems;
LIST_ENTRY freeWorkItemsList;
LIST_ENTRY pendingWorkItemsList;
LIST_ENTRY completeWorkItemsList;
HANDLE somethingToDoEvent;
/*
* There is one thread per library. This is its handle.
*/
HANDLE hThread;
CRITICAL_SECTION lock;
};
enum mediaPoolTypes {
MEDIAPOOLTYPE_NONE = 0,
/*
* These are the 3 standard pool types.
*/
MEDIAPOOLTYPE_FREE,
MEDIAPOOLTYPE_IMPORT,
MEDIAPOOLTYPE_UNRECOGNIZED,
MEDIAPOOLTYPE_OTHER,
};
struct _MEDIA_POOL {
OBJECT_HEADER objHeader;
/*
* Entry in library's mediaPoolsList or
* parent pool's childPoolsList.
*/
LIST_ENTRY mediaPoolsListEntry;
LIBRARY *owningLibrary;
/*
* A media pool has a (default?) media type.
*/
MEDIA_TYPE_OBJECT *mediaTypeObj;
/*
* Media pools can be divided heirarchically into sub-pools.
* If a pool is top-level, its parentPool pointer is NULL.
*/
MEDIA_POOL *parentPool;
ULONG numChildPools;
LIST_ENTRY childPoolsList;
ULONG numPhysMedia;
LIST_ENTRY physMediaList;
HANDLE newMediaEvent;
WCHAR name[NTMS_OBJECTNAME_LENGTH];
CRITICAL_SECTION lock;
};
// BUGBUG - should this be in physical media or mediaTypeObj ?
enum physicalMediaTypes {
PHYSICALMEDIATYPE_NONE = 0,
PHYSICALMEDIATYPE_SINGLEPARTITION, // e.g. 1 disk,tape
PHYSICALMEDIATYPE_CARTRIDGE,
};
enum physicalMediaStates {
PHYSICALMEDIASTATE_NONE = 0,
PHYSICALMEDIASTATE_INITIALIZING,
PHYSICALMEDIASTATE_AVAILABLE, // i.e. in a slot
PHYSICALMEDIASTATE_INUSE, // i.e. in a drive
PHYSICALMEDIASTATE_RESERVED,
};
struct _PHYSICAL_MEDIA {
OBJECT_HEADER objHeader;
LIST_ENTRY physMediaListEntry; // entry in pool partition's physMediaList
enum physicalMediaStates state;
/*
* Pointer to application-defined media type object.
*/
MEDIA_TYPE_OBJECT *mediaTypeObj;
MEDIA_POOL *owningMediaPool;
SLOT *currentSlot;
DRIVE *currentDrive;
ULONG numPartitions;
MEDIA_PARTITION *partitions;
/*
* The owning session of a physicalMedia also holds
* the exclusive right to allocate partitions on it.
*/
SESSION *owningSession;
ULONG numPartitionsOwnedBySession;
HANDLE mediaFreeEvent;
CRITICAL_SECTION lock;
};
enum mediaPartitionTypes {
MEDIAPARTITIONTYPE_NONE = 0,
/*
* Major types
*/
MEDIAPARTITIONTYPE_TAPE,
MEDIAPARTITIONTYPE_DISK,
/*
* Subtypes
*/
// BUGBUG FINISH
};
enum mediaPartitionStates {
MEDIAPARTITIONSTATE_NONE = 0,
MEDIAPARTITIONSTATE_AVAILABLE,
MEDIAPARTITIONSTATE_ALLOCATED,
MEDIAPARTITIONSTATE_MOUNTED,
MEDIAPARTITIONSTATE_INUSE,
MEDIAPARTITIONSTATE_DECOMMISSIONED,
};
struct _MEDIA_PARTITION {
OBJECT_HEADER objHeader;
enum mediaPartitionTypes type;
enum mediaPartitionTypes subType;
enum mediaPartitionStates state;
/*
* When a media partition is 'complete',
* it is no longer writeable.
*/
BOOLEAN isComplete;
/*
* Can the owning physical medium be moved
* into a new media pool ?
*/
BOOLEAN allowImport;
PHYSICAL_MEDIA *owningPhysicalMedia;
/*
* The logical media id is the persistent identifier
* of a media partition that apps use to find it.
*/
GUID logicalMediaGuid;
SESSION *owningSession;
};
enum driveStates {
DRIVESTATE_NONE = 0,
DRIVESTATE_INITIALIZING,
DRIVESTATE_AVAILABLE,
DRIVESTATE_INUSE,
DRIVESTATE_RESERVED,
};
struct _DRIVE {
OBJECT_HEADER objHeader;
enum driveStates state;
ULONG driveIndex; // index into library's drives array
PHYSICAL_MEDIA *insertedMedia;
WCHAR path[MAX_PATH+1];
LIBRARY *lib;
};
enum slotStates {
SLOTSTATE_NONE = 0,
SLOTSTATE_EMPTY,
SLOTSTATE_OCCUPIED,
};
struct _SLOT {
OBJECT_HEADER objHeader;
enum slotStates state;
UINT slotIndex; // index into library's slots array
PHYSICAL_MEDIA *insertedMedia;
/*
* Is this the unique slot designated to hold the
* library's cleaner cartridge ?
*/
BOOLEAN isCleanerSlot;
GUID slotId;
LIBRARY *lib;
};
enum transportStates {
TRANSPORTSTATE_NONE = 0,
TRANSPORTSTATE_AVAILABLE,
TRANSPORTSTATE_INUSE,
};
struct _TRANSPORT {
OBJECT_HEADER objHeader;
enum transportStates state;
ULONG transportIndex; // index into library's transports array
ULONG numPickers;
PICKER *pickers;
LIBRARY *lib;
};
struct _PICKER {
OBJECT_HEADER objHeader;
TRANSPORT *owningTransport;
};
struct _SESSION {
#define SESSION_SIG 'SmsR'
ULONG sig;
LIST_ENTRY allSessionsListEntry; // entry in g_allSessionsList
LIST_ENTRY operatorRequestList;
CRITICAL_SECTION lock;
WCHAR serverName[NTMS_COMPUTERNAME_LENGTH];
WCHAR applicationName[NTMS_APPLICATIONNAME_LENGTH];
WCHAR clientName[NTMS_COMPUTERNAME_LENGTH];
WCHAR userName[NTMS_USERNAME_LENGTH];
};
struct _MEDIA_TYPE_OBJECT {
OBJECT_HEADER objHeader;
LIBRARY *lib;
/*
* The number of physical media pointing to this type
* as their media type.
*/
ULONG numPhysMediaReferences;
// BUGBUG FINISH - media type characteristics
CRITICAL_SECTION lock;
};
enum workItemStates {
WORKITEMSTATE_NONE,
/*
* WorkItem is in one of the library queues:
* free, pending, or complete.
*/
WORKITEMSTATE_FREE,
WORKITEMSTATE_PENDING,
WORKITEMSTATE_COMPLETE,
/*
* WorkItem is not in any library queue.
* It is in transit or being staged in a workGroup.
*/
WORKITEMSTATE_STAGING,
};
struct _WORKITEM {
enum workItemStates state;
LIST_ENTRY libListEntry; // entry in one of a libraries workItem lists
LIST_ENTRY workGroupListEntry; // entry in work group workItemList
LIBRARY *owningLib;
/*
* The current work group with which this
* work item is associated.
*/
WORKGROUP *workGroup;
// BUGBUG - ok to have a handle for each event ?
HANDLE workItemCompleteEvent;
/*
* Fields describing the workItem's current operation.
*/
struct {
ULONG opcode;
ULONG options;
HRESULT resultStatus;
DRIVE *drive;
PHYSICAL_MEDIA *physMedia;
MEDIA_PARTITION *mediaPartition;
ULONG lParam;
NTMS_GUID guidArg; // in/out guid used by some ops
PVOID buf;
ULONG bufLen;
SYSTEMTIME timeQueued;
SYSTEMTIME timeCompleted;
/*
* Request identifier, used to cancel a pending workItem.
*/
NTMS_GUID requestGuid;
//
// BUGBUG - unscrubbed fields from NtmsDbWorkItem
// clean this up.
//
// NtmsDbGuid m_PartitionId;
// NtmsDbGuid m_AssocWorkItem;
// short m_protected;
// unsigned long m_Priority;
} currentOp;
};
/*
* A WORKGROUP is a collection of WORKITEMs,
* not necessarily all on the same library.
*/
struct _WORKGROUP {
LIST_ENTRY workItemsList;
ULONG numTotalWorkItems;
ULONG numPendingWorkItems;
HANDLE allWorkItemsCompleteEvent;
HRESULT resultStatus;
CRITICAL_SECTION lock;
};
struct _OPERATOR_REQUEST {
LIST_ENTRY sessionOpReqsListEntry; // entry in session's operatorRequestList
SESSION *invokingSession;
ULONG numWaitingThreads; // num threads waiting for completion
// BUGBUG - I don't think we need an op request thread
HANDLE hThread; // thread spawned for op request
enum NtmsOpreqCommand opRequestCommand;
enum NtmsOpreqState state;
NTMS_GUID arg1Guid;
NTMS_GUID arg2Guid;
WCHAR appMessage[NTMS_MESSAGE_LENGTH];
WCHAR rsmMessage[NTMS_MESSAGE_LENGTH];
// NOTIFYICONDATA notifyData; // BUGBUG - use this in RSM Monitor app ?
NTMS_GUID opReqGuid;
SYSTEMTIME timeSubmitted;
HANDLE completedEvent;
};
/*
* The number of free workItems with which we initialize a library.
*/
#define MIN_LIBRARY_WORKITEMS 0
/*
* The maximum total number of workItems that we allow in a library pool.
* We will allocate new workItems as needed up to this number.
*/
#define MAX_LIBRARY_WORKITEMS 10000 // BUGBUG ?
/*
* List macros -- not defined in winnt.h for some reason.
*/
#define InitializeListHead(ListHead) (\
(ListHead)->Flink = (ListHead)->Blink = (ListHead))
#define IsListEmpty(ListHead) \
((ListHead)->Flink == (ListHead))
#define RemoveHeadList(ListHead) \
(ListHead)->Flink;\
{RemoveEntryList((ListHead)->Flink)}
#define RemoveTailList(ListHead) \
(ListHead)->Blink;\
{RemoveEntryList((ListHead)->Blink)}
#define RemoveEntryList(Entry) {\
PLIST_ENTRY _EX_Blink;\
PLIST_ENTRY _EX_Flink;\
_EX_Flink = (Entry)->Flink;\
_EX_Blink = (Entry)->Blink;\
_EX_Blink->Flink = _EX_Flink;\
_EX_Flink->Blink = _EX_Blink;\
}
#define InsertTailList(ListHead,Entry) {\
PLIST_ENTRY _EX_Blink;\
PLIST_ENTRY _EX_ListHead;\
_EX_ListHead = (ListHead);\
_EX_Blink = _EX_ListHead->Blink;\
(Entry)->Flink = _EX_ListHead;\
(Entry)->Blink = _EX_Blink;\
_EX_Blink->Flink = (Entry);\
_EX_ListHead->Blink = (Entry);\
}
#define InsertHeadList(ListHead,Entry) {\
PLIST_ENTRY _EX_Flink;\
PLIST_ENTRY _EX_ListHead;\
_EX_ListHead = (ListHead);\
_EX_Flink = _EX_ListHead->Flink;\
(Entry)->Flink = _EX_Flink;\
(Entry)->Blink = _EX_ListHead;\
_EX_Flink->Blink = (Entry);\
_EX_ListHead->Flink = (Entry);\
}
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
/*
* Internal function prototypes
*/
BOOLEAN RSMServiceGlobalInit();
VOID RSMServiceGlobalShutdown();
DWORD RSMServiceHandler(IN DWORD dwOpcode, IN DWORD dwEventType, IN PVOID pEventData, IN PVOID pData);
BOOL InitializeRSMService();
VOID ShutdownRSMService();
VOID RSMServiceLoop();
VOID StartLibraryManager();
LIBRARY *NewRSMLibrary(ULONG numDrives, ULONG numSlots, ULONG numTransports);
VOID FreeRSMLibrary(LIBRARY *lib);
LIBRARY *FindLibrary(LPNTMS_GUID libId);
SLOT *FindLibrarySlot(LIBRARY *lib, LPNTMS_GUID slotId);
BOOL ValidateSessionHandle(HANDLE hSession);
BOOL ValidateWStr(LPCWSTR str);
BOOL ValidateAStr(LPCSTR s);
BOOL ValidateBuffer(PVOID buf, ULONG len);
WORKITEM *NewWorkItem(LIBRARY *lib);
VOID FreeWorkItem(WORKITEM *workItem);
VOID EnqueueFreeWorkItem(LIBRARY *lib, WORKITEM *workItem);
WORKITEM *DequeueFreeWorkItem(LIBRARY *lib, BOOL allocOrYieldIfNeeded);
VOID EnqueuePendingWorkItem(LIBRARY *lib, WORKITEM *workItem);
WORKITEM *DequeuePendingWorkItem(LIBRARY *lib, WORKITEM *specificWorkItem);
WORKITEM *DequeuePendingWorkItemByGuid(LIBRARY *lib, LPNTMS_GUID lpRequestId);
VOID EnqueueCompleteWorkItem(LIBRARY *lib, WORKITEM *workItem);
WORKITEM *DequeueCompleteWorkItem(LIBRARY *lib, WORKITEM *specificWorkItem);
BOOL StartLibrary(LIBRARY *lib);
VOID HaltLibrary(LIBRARY *lib);
DWORD __stdcall LibraryThread(void *context);
VOID Library_DoWork(LIBRARY *lib);
OPERATOR_REQUEST *NewOperatorRequest(DWORD dwRequest, LPCWSTR lpMessage, LPNTMS_GUID lpArg1Id, LPNTMS_GUID lpArg2Id);
VOID FreeOperatorRequest(OPERATOR_REQUEST *opReq);
BOOL EnqueueOperatorRequest(SESSION *thisSession, OPERATOR_REQUEST *opReq);
OPERATOR_REQUEST *DequeueOperatorRequest(SESSION *thisSession, OPERATOR_REQUEST *specificOpReq, LPNTMS_GUID specificOpReqGuid);
OPERATOR_REQUEST *FindOperatorRequest(SESSION *thisSession, LPNTMS_GUID opReqGuid);
HRESULT CompleteOperatorRequest(SESSION *thisSession, LPNTMS_GUID lpRequestId, enum NtmsOpreqState completeState);
DWORD __stdcall OperatorRequestThread(void *context);
SESSION *NewSession(LPCWSTR lpServer, LPCWSTR lpApplication, LPCWSTR lpClientName, LPCWSTR lpUserName);
VOID FreeSession(SESSION *thisSession);
ULONG WStrNCpy(WCHAR *dest, const WCHAR *src, ULONG maxWChars);
ULONG AsciiToWChar(WCHAR *dest, const char *src, ULONG maxChars);
ULONG WCharToAscii(char *dest, WCHAR *src, ULONG maxChars);
BOOL WStringsEqualN(PWCHAR s, PWCHAR p, BOOL caseSensitive, ULONG maxLen);
VOID ConvertObjectInfoAToWChar(LPNTMS_OBJECTINFORMATIONW wObjInfo, LPNTMS_OBJECTINFORMATIONA aObjInfo);
VOID InitGuidHash();
VOID InsertObjectInGuidHash(OBJECT_HEADER *obj);
VOID RemoveObjectFromGuidHash(OBJECT_HEADER *obj);
OBJECT_HEADER *FindObjectInGuidHash(NTMS_GUID *guid);
MEDIA_POOL *NewMediaPool(LPCWSTR name, LPNTMS_GUID mediaType, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
MEDIA_POOL *FindMediaPool(LPNTMS_GUID mediaPoolId);
MEDIA_POOL *FindMediaPoolByName(PWSTR poolName);
PHYSICAL_MEDIA *FindPhysicalMedia(LPNTMS_GUID physMediaId);
VOID RefObject(PVOID objectPtr);
VOID DerefObject(PVOID objectPtr);
PHYSICAL_MEDIA *NewPhysicalMedia();
HRESULT AllocatePhysicalMediaExclusive(SESSION *thisSession, PHYSICAL_MEDIA *physMedia, LPNTMS_GUID lpPartitionId, DWORD dwTimeoutMsec);
HRESULT AllocateNextPartitionOnExclusiveMedia(SESSION *thisSession, PHYSICAL_MEDIA *physMedia, MEDIA_PARTITION **ppNextPartition);
HRESULT AllocateMediaFromPool(SESSION *thisSession, MEDIA_POOL *mediaPool, DWORD dwTimeoutMsec, PHYSICAL_MEDIA **ppPhysMedia, BOOL opReqIfNeeded);
MEDIA_PARTITION *FindMediaPartition(LPNTMS_GUID lpLogicalMediaId);
HRESULT ReleaseMediaPartition(SESSION *thisSession, MEDIA_PARTITION *thisMediaPartition);
MEDIA_POOL *FindMediaPoolByName(PWSTR poolName);
MEDIA_POOL *FindMediaPoolByNameInLibrary(LIBRARY *lib, PWSTR poolName);
HRESULT SetMediaPartitionState(MEDIA_PARTITION *mediaPart, enum mediaPartitionStates newState);
HRESULT SetMediaPartitionComplete(MEDIA_PARTITION *mediaPart);
HRESULT DeletePhysicalMedia(PHYSICAL_MEDIA *physMedia);
VOID InsertPhysicalMediaInPool(MEDIA_POOL *mediaPool, PHYSICAL_MEDIA *physMedia);
VOID RemovePhysicalMediaFromPool(PHYSICAL_MEDIA *physMedia);
HRESULT MovePhysicalMediaToPool(MEDIA_POOL *destMediaPool, PHYSICAL_MEDIA *physMedia, BOOLEAN setMediaTypeToPoolType);
BOOLEAN LockPhysicalMediaWithPool(PHYSICAL_MEDIA *physMedia);
VOID UnlockPhysicalMediaWithPool(PHYSICAL_MEDIA *physMedia);
BOOLEAN LockPhysicalMediaWithLibrary(PHYSICAL_MEDIA *physMedia);
VOID UnlockPhysicalMediaWithLibrary(PHYSICAL_MEDIA *physMedia);
HRESULT DeleteMediaPool(MEDIA_POOL *mediaPool);
MEDIA_TYPE_OBJECT *NewMediaTypeObject();
VOID DestroyMediaTypeObject(MEDIA_TYPE_OBJECT *mediaTypeObj);
MEDIA_TYPE_OBJECT *FindMediaTypeObject(LPNTMS_GUID lpMediaTypeId);
HRESULT DeleteMediaTypeObject(MEDIA_TYPE_OBJECT *mediaTypeObj);
VOID SetMediaType(PHYSICAL_MEDIA *physMedia, MEDIA_TYPE_OBJECT *mediaTypeObj);
WORKGROUP *NewWorkGroup();
VOID FreeWorkGroup(WORKGROUP *workGroup);
VOID FlushWorkGroup(WORKGROUP *workGroup);
VOID FlushWorkItem(WORKITEM *workItem);
HRESULT BuildMountWorkGroup(WORKGROUP *workGroup, LPNTMS_GUID lpMediaOrPartitionIds, LPNTMS_GUID lpDriveIds, DWORD dwCount, DWORD dwOptions, DWORD dwPriority);
VOID BuildSingleMountWorkItem(WORKITEM *workItem, DRIVE *drive OPTIONAL, OBJECT_HEADER *mediaOrPartObj, ULONG dwOptions, int dwPriority);
HRESULT BuildDismountWorkGroup(WORKGROUP *workGroup, LPNTMS_GUID lpMediaOrPartitionIds, DWORD dwCount, DWORD dwOptions);
VOID BuildSingleDismountWorkItem(WORKITEM *workItem, OBJECT_HEADER *mediaOrPartObj, DWORD dwOptions);
HRESULT ScheduleWorkGroup(WORKGROUP *workGroup);
DRIVE *NewDrive(LIBRARY *lib, PWCHAR path);
VOID FreeDrive(DRIVE *drive);
DRIVE *FindDrive(LPNTMS_GUID driveId);
VOID BuildEjectWorkItem(WORKITEM *workItem, PHYSICAL_MEDIA *physMedia, LPNTMS_GUID lpEjectOperation, ULONG dwAction);
VOID BuildInjectWorkItem(WORKITEM *workItem, LPNTMS_GUID lpInjectOperation, ULONG dwAction);
HRESULT StopCleanerInjection(LIBRARY *lib, LPNTMS_GUID lpInjectOperation);
HRESULT StopCleanerEjection(LIBRARY *lib, LPNTMS_GUID lpEjectOperation);
HRESULT DeleteLibrary(LIBRARY *lib);
HRESULT DeleteDrive(DRIVE *drive);
BOOL ServiceOneWorkItem(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceRemove(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceDisableChanger(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceDisableLibrary(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceEnableChanger(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceEnableLibrary(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceDisableDrive(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceEnableDrive(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceDisableMedia(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceEnableMedia(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceUpdateOmid(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceInventory(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceDoorAccess(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceEject(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceEjectCleaner(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceInject(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceInjectCleaner(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceProcessOmid(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceCleanDrive(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceDismount(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceMount(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceWriteScratch(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceClassify(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceReserveCleaner(LIBRARY *lib, WORKITEM *workItem);
BOOL ServiceReleaseCleaner(LIBRARY *lib, WORKITEM *workItem);
/*
* Externs for internal global data.
*/
extern CRITICAL_SECTION g_globalServiceLock;
extern LIST_ENTRY g_allLibrariesList;
extern LIST_ENTRY g_allSessionsList;
extern HANDLE g_terminateServiceEvent;
extern HINSTANCE g_hInstance;