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.
 
 
 
 
 
 

1086 lines
33 KiB

/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
mct.c
Abstract:
Test program for testing Medium Changer drivers. It calls the appropriate
dispatch routines of the changer driver based on the user input, and displays
the output from the driver.
Environment:
User mode
Revision History :
--*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <windows.h>
#include <devioctl.h>
#include <ntddchgr.h>
#define _NTSRB_ // to keep srb.h from being included
#include <scsi.h>
#include "mct.h" // Header file for thie file
HANDLE hChanger = INVALID_HANDLE_VALUE; // Handle to the open device
GET_CHANGER_PARAMETERS ChangerParams; // Changer Parameters
BOOLEAN ChangerParamsRead; // Flag to indicate if the changer params
// have been read.
//
// Changer's features flag corresponding to the
// bits set in Features0 and Features1 in the
// changer driver.
//
PUCHAR ChangerFlagStrings0[] = {
"CHANGER_BAR_CODE_SCANNER_INSTALLED",
"CHANGER_INIT_ELEM_STAT_WITH_RANGE",
"CHANGER_CLOSE_IEPORT",
"CHANGER_OPEN_IEPORT",
"CHANGER_STATUS_NON_VOLATILE",
"CHANGER_EXCHANGE_MEDIA",
"CHANGER_CLEANER_SLOT",
"CHANGER_LOCK_UNLOCK",
"CHANGER_CARTRIDGE_MAGAZINE",
"CHANGER_MEDIUM_FLIP",
"CHANGER_POSITION_TO_ELEMENT",
"CHANGER_REPORT_IEPORT_STATE",
"CHANGER_STORAGE_DRIVE",
"CHANGER_STORAGE_IEPORT",
"CHANGER_STORAGE_SLOT",
"CHANGER_STORAGE_TRANSPORT",
"CHANGER_DRIVE_CLEANING_REQUIRED",
"CHANGER_PREDISMOUNT_EJECT_REQUIRED",
"CHANGER_CLEANER_ACCESS_NOT_VALID",
"CHANGER_PREMOUNT_EJECT_REQUIRED",
"CHANGER_VOLUME_IDENTIFICATION",
"CHANGER_VOLUME_SEARCH",
"CHANGER_VOLUME_ASSERT",
"CHANGER_VOLUME_REPLACE",
"CHANGER_VOLUME_UNDEFINE",
"",
"CHANGER_SERIAL_NUMBER_VALID",
"CHANGER_DEVICE_REINITIALIZE_CAPABLE",
"CHANGER_KEYPAD_ENABLE_DISABLE",
"CHANGER_DRIVE_EMPTY_ON_DOOR_ACCESS"
};
PUCHAR ChangerFlagStrings1[] = {
"CHANGER_PREDISMOUNT_ALIGN_TO_SLOT",
"CHANGER_PREDISMOUNT_ALIGN_TO_DRIVE",
"CHANGER_CLEANER_AUTODISMOUNT",
"CHANGER_TRUE_EXCHANGE_CAPABLE",
"CHANGER_SLOTS_USE_TRAYS",
"CHANGER_RTN_MEDIA_TO_ORIGINAL_ADDR",
"CHANGER_CLEANER_OPS_NOT_SUPPORTED",
"CHANGER_IEPORT_USER_CONTROL_OPEN",
"CHANGER_IEPORT_USER_CONTROL_CLOSE",
"CHANGER_MOVE_EXTENDS_IEPORT",
"CHANGER_MOVE_RETRACTS_IEPORT",
};
int __cdecl main(int argc, char *argv[])
{
char switchChar;
BOOLEAN changerOpened;
if (argc == 1) {
mctPrintUsage();
return 0;
}
if (*argv[1] != '-') {
mctPrintUsage();
return 0;
}
//
// If the changer is not open,
// try to open the changer device.
//
if (hChanger == INVALID_HANDLE_VALUE) {
changerOpened = mctOpenChanger();
}
if (changerOpened == FALSE) {
mctDebugPrint(1, "Could not open changer. Aborting!\n");
return 0;
}
//
// Read the changer parameters.
//
/*
if (mctGetParameters(FALSE) != MCT_STATUS_SUCCESS) {
mctDebugPrint(0, "Unable to read changer parameters.\n");
ChangerParamsRead = FALSE;
} else {
ChangerParamsRead = TRUE;
}
*/
//
// Get the function to be called.
//
switchChar = *(argv[1]+1);
switch (switchChar) {
case INIT_ELEMENT_STATUS: {
if (mctInitElementStatus() != MCT_STATUS_SUCCESS) {
mctDebugPrint(1, "Error doing InitElement.\n");
}
break;
}
case GET_ELEMENT_STATUS: {
CHAR ElemType;
USHORT ElemAddress;
if (argc != 4) {
mctDebugPrint(0, "GetElementStatus : mct -e ElemType ElemAddress\n");
break;
}
ElemType = (CHAR)toupper(*argv[2]);
ElemAddress = (USHORT)atoi(argv[3]);
if (mctGetElementStatus(ElemType, ElemAddress) != MCT_STATUS_SUCCESS) {
mctDebugPrint(1, "Error doing GetElementStatus.\n");
}
break;
}
case GET_PARAMETERS: {
if (mctGetParameters(TRUE) != MCT_STATUS_SUCCESS) {
mctDebugPrint(1, "Error reading changer parameters.\n");
}
break;
}
case GET_STATUS: {
if (mctGetStatus() != MCT_STATUS_SUCCESS) {
mctDebugPrint(1, "Error doing GetStatus.\n");
}
break;
}
case GET_PRODUCT_DATA: {
if (mctGetProductData() != MCT_STATUS_SUCCESS) {
mctDebugPrint(1, "Error doing GetProductData.\n");
}
break;
}
case SET_ACCESS: {
CHAR ElemType, Control;
USHORT ElemAddr;
if (argc != 5) {
mctDebugPrint(0, "SetAccess : mct -a ElemType ElemAddr Control\n");
break;
}
ElemType = (CHAR)toupper(*argv[2]);
ElemAddr = (USHORT)atoi(argv[3]);
Control = (CHAR)toupper(*argv[4]);
if (mctSetAccess(ElemType, ElemAddr, Control) != MCT_STATUS_SUCCESS) {
mctDebugPrint(1, "Error doing SetAccess.\n");
}
break;
}
case SET_POSITION: {
USHORT Dest;
CHAR ElemType;
if (argc != 4) {
mctDebugPrint(0, "SetPosition: mct -o ElemType Dest\n");
break;
}
ElemType = (CHAR)toupper(*argv[2]);
Dest = (USHORT)atoi(argv[3]);
if (mctSetPosition(ElemType, Dest) != MCT_STATUS_SUCCESS) {
mctDebugPrint(1, "Error doing SetPosition.\n");
}
break;
}
case EXCHANGE_MEDIUM: {
USHORT Transport, Source, Dest1, Dest2;
CHAR TransType, SrcType, Dest1Type, Dest2Type;
if (argc != 10) {
mctDebugPrint(0, "ExchangeMedium: mct -x ElemType Trans ElemType Src ElemType");
mctDebugPrint(0, " Dest1 ElemType Dest2\n");
break;
}
TransType = (CHAR)toupper(*argv[2]);
Transport = (USHORT)atoi(argv[3]);
SrcType = (CHAR)toupper(*argv[4]);
Source = (USHORT)atoi(argv[5]);
Dest1Type = (CHAR)toupper(*argv[6]);
Dest1 = (USHORT)atoi(argv[7]);
Dest2Type = (CHAR)toupper(*argv[8]);
Dest2 = (USHORT)atoi(argv[9]);
if (mctExchangeMedium(TransType, Transport,
SrcType, Source,
Dest1Type, Dest1,
Dest2Type, Dest2) != MCT_STATUS_SUCCESS) {
mctDebugPrint(1, "Error doing Exchange Medium.\n");
}
break;
}
case MOVE_MEDIUM: {
USHORT Transport, Source, Dest;
CHAR TransType, SourceType, DestType;
if (argc != 8) {
mctDebugPrint(0, "MoveMedium : mct -m t N s\\d N s\\d N\n");
break;
}
Transport = (USHORT)atoi(argv[3]);
Source = (USHORT)atoi(argv[5]);
Dest = (USHORT)atoi(argv[7]);
TransType = (CHAR)toupper(*argv[2]);
SourceType = (CHAR)toupper(*argv[4]);
DestType = (CHAR)toupper(*argv[6]);
if (mctMoveMedium(TransType, Transport, SourceType, Source,
DestType, Dest) != MCT_STATUS_SUCCESS) {
mctDebugPrint(1, "Error doing Move Medium.\n");
}
break;
}
case REINITIALIZE_TRANSPORT: {
if (mctReinitTransport() != MCT_STATUS_SUCCESS) {
mctDebugPrint(1, "Error doing Reinitialize Transport.\n");
}
break;
}
case QUERY_VOLUME_TAG: {
if (mctQueryVolumeTag() != MCT_STATUS_SUCCESS) {
mctDebugPrint(1, "Error doing QueryVolumeTag.\n");
}
break;
}
default: mctPrintUsage();
break;
}
mctCloseChanger();
return 0;
}
VOID
mctPrintUsage()
{
printf("\nUsage : MCT\n");
printf(" -i [InitializeElementStatus]\n");
printf(" -e ElemType ElemAddress [GetElementStatus]\n");
printf(" -s [GetStatus]\n");
printf(" -p [GetParameters]\n");
printf(" -d [GetProductData]\n");
printf(" -a ElemType ElemAddr Control [SetAccess]\n");
printf(" -o ElemType Dest [SetPosition]\n");
printf(" -r [ReinitializeTransport]\n");
printf(" -q [QueryVolumeTag]\n");
printf(" -m ElemType Trans ElemType Src ElemType ");
printf("Dest [MoveMedium]\n");
printf(" -x ElemType Trans ElemType Src ElemType ");
printf("Dest1 ElemType Dest2 [ExchangeMedium]\n");
return;
}
BOOLEAN
mctOpenChanger()
{
DWORD nBytes = 0, nBlockSize;
ULONG retVal;
DWORD status;
UINT ChangerId;
CHAR ChangerName[128];
ChangerId = 0;
//printf("Enter the changer number (0, 1, 2,.., N) : ");
//scanf("%d", &ChangerId);
sprintf(ChangerName, "\\\\.\\Changer%d", ChangerId);
mctDebugPrint(3, "\nOpening changer %s\n", ChangerName);
hChanger = CreateFile(ChangerName, (GENERIC_READ | GENERIC_WRITE),
(FILE_SHARE_READ | FILE_SHARE_WRITE),
NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hChanger == INVALID_HANDLE_VALUE) {
mctDebugPrint(0, "Unable to open changer - Error %d. ", GetLastError());
mctDebugPrint(0, "Aborting test!\n");
return FALSE;
}
return TRUE;
}
VOID
mctCloseChanger()
{
if (hChanger != INVALID_HANDLE_VALUE) {
CloseHandle(hChanger);
} else {
mctDebugPrint(0, "Changer not open or invalid handle value.\n");
}
}
MCT_STATUS
mctInitElementStatus()
{
CHANGER_INITIALIZE_ELEMENT_STATUS initElementStatus;
ULONG retVal;
DWORD nBytes;
initElementStatus.ElementList.Element.ElementType = AllElements;
if ((ChangerParams.Features0) & CHANGER_BAR_CODE_SCANNER_INSTALLED) {
initElementStatus.BarCodeScan = TRUE;
} else {
initElementStatus.BarCodeScan = FALSE;
}
retVal = DeviceIoControl(hChanger, IOCTL_CHANGER_INITIALIZE_ELEMENT_STATUS,
&initElementStatus,
sizeof(CHANGER_INITIALIZE_ELEMENT_STATUS),
NULL, 0, &nBytes, NULL);
if (retVal == FALSE) {
mctDebugPrint(0, "Error doing Initialize Element Status : %d.\n",
GetLastError());
return MCT_STATUS_FAILED;
}
return MCT_STATUS_SUCCESS;
}
MCT_STATUS
mctGetElementStatus(CHAR ElementType, USHORT ElemAddress)
{
CHANGER_READ_ELEMENT_STATUS readElementStat;
PCHANGER_ELEMENT_STATUS_EX ChangerElementStat, tmpChangerElementStat;
DWORD nBytes;
ULONG retVal;
USHORT NoOfElems;
int i, inx;
readElementStat.VolumeTagInfo = FALSE;
switch (ElementType) {
case CHANGER_ALL_ELEMENTS : {
readElementStat.ElementList.Element.ElementType = AllElements;
readElementStat.ElementList.Element.ElementAddress = 0;
NoOfElems = ChangerParams.NumberTransportElements +
ChangerParams.NumberStorageElements +
ChangerParams.NumberIEElements + 1;
readElementStat.ElementList.NumberOfElements = NoOfElems;
break;
}
case CHANGER_TRANSPORT : {
readElementStat.ElementList.Element.ElementType = ChangerTransport;
readElementStat.ElementList.Element.ElementAddress = ElemAddress;
readElementStat.ElementList.NumberOfElements = 1;
NoOfElems = 1;
break;
}
case CHANGER_SLOT : {
readElementStat.ElementList.Element.ElementType = ChangerSlot;
readElementStat.ElementList.Element.ElementAddress = ElemAddress;
readElementStat.ElementList.NumberOfElements = 1;
NoOfElems = 1;
break;
}
case CHANGER_DRIVE : {
readElementStat.ElementList.Element.ElementType = ChangerDrive;
readElementStat.ElementList.Element.ElementAddress = ElemAddress;
readElementStat.ElementList.NumberOfElements = 1;
readElementStat.VolumeTagInfo = TRUE;
NoOfElems = 1;
break;
}
case CHANGER_IEPORT: {
readElementStat.ElementList.Element.ElementType = ChangerIEPort;
readElementStat.ElementList.Element.ElementAddress = ElemAddress;
readElementStat.ElementList.NumberOfElements = 1;
NoOfElems = 1;
break;
}
default: {
mctDebugPrint(0, "Invalid Element Type. \n");
mctDebugPrint(0, "Valid Types :\n");
mctDebugPrint(0, " All Elements : A or a\n");
mctDebugPrint(0, " Transport : T or t\n");
mctDebugPrint(0, " Slot : S or s\n");
mctDebugPrint(0, " Drive : D or d\n");
mctDebugPrint(0, " IEPort : I or i\n");
return MCT_STATUS_FAILED;
}
} // switch (ElementType)
ChangerElementStat = (PCHANGER_ELEMENT_STATUS_EX)malloc(NoOfElems *
sizeof(CHANGER_ELEMENT_STATUS_EX));
if (ChangerElementStat == NULL) {
mctDebugPrint(0, "Malloc failed for ReadElementStatus.\n");
return MCT_STATUS_FAILED;
}
retVal = DeviceIoControl(hChanger, IOCTL_CHANGER_GET_ELEMENT_STATUS,
&readElementStat,
sizeof(CHANGER_READ_ELEMENT_STATUS),
ChangerElementStat,
(NoOfElems * sizeof(CHANGER_ELEMENT_STATUS_EX)),
&nBytes,
NULL);
if (retVal == FALSE) {
mctDebugPrint(0, "ReadElementStatus failed : %d \n",
GetLastError());
free(ChangerElementStat);
return MCT_STATUS_FAILED;
}
//
// Print Element Status information
//
tmpChangerElementStat = ChangerElementStat;
for (i = 0; i < NoOfElems; i++) {
printf("Element Type : %d, ",
ChangerElementStat->Element.ElementType);
printf("Element Status Flag : 0x%08x\n", ChangerElementStat->Flags);
if ((ChangerElementStat->Flags) & ELEMENT_STATUS_EXCEPT) {
printf("Exception occured. Error %x\n",
ChangerElementStat->ExceptionCode);
}
if ((ChangerElementStat->Flags) & ELEMENT_STATUS_FULL) {
printf("Element has Media.\n");
} else {
printf("Element has no media.\n");
}
if ((ChangerElementStat->Flags) & ELEMENT_STATUS_SVALID) {
printf("SourceElementAddress Type : %d, Address : %ul\n",
ChangerElementStat->SrcElementAddress.ElementType,
ChangerElementStat->SrcElementAddress.ElementAddress);
} else {
printf("SourceElementAddress is not valid.\n");
}
if ((ChangerElementStat->Flags) & ELEMENT_STATUS_ID_VALID) {
printf("Target Id : %x\t", ChangerElementStat->TargetId);
}
if ((ChangerElementStat->Flags) & ELEMENT_STATUS_LUN_VALID) {
printf("LUN : %x", ChangerElementStat->Lun);
}
printf("\n");
if ((ChangerElementStat->Flags) & ELEMENT_STATUS_PVOLTAG) {
printf("Primary Volume Tag : ");
for (inx = 0; inx < MAX_VOLUME_ID_SIZE; inx++) {
printf("%d ", ChangerElementStat->PrimaryVolumeID[inx]);
}
printf("\n");
//
// Add code to print Primary volume tag.
//
} else {
printf("Primary Volume Tag information is not set.\n");
}
if ((ChangerElementStat->Flags) & ELEMENT_STATUS_AVOLTAG) {
printf("Alternate Volume Tag information is valid.\n");
//
// Add code to print Alternate volume tag.
//
} else {
printf("Alternate Volume Tag information is not set.\n");
}
ChangerElementStat++;
}
free(tmpChangerElementStat);
return MCT_STATUS_SUCCESS;
}
MCT_STATUS
mctGetStatus()
{
ULONG retVal;
DWORD nBytes;
retVal = DeviceIoControl(hChanger, IOCTL_CHANGER_GET_STATUS,
NULL, 0, NULL, 0, &nBytes, NULL);
if (retVal == FALSE) {
mctDebugPrint(0, "Error reading changer status : %d\n",
GetLastError());
return MCT_STATUS_FAILED;
}
return MCT_STATUS_SUCCESS;
}
MCT_STATUS
mctGetProductData()
{
PCHANGER_PRODUCT_DATA productData;
ULONG retVal;
DWORD nBytes;
CHAR SerialNum[SERIAL_NUMBER_LENGTH+1];
productData = (PCHANGER_PRODUCT_DATA)calloc(1, sizeof(CHANGER_PRODUCT_DATA));
retVal = DeviceIoControl(hChanger, IOCTL_CHANGER_GET_PRODUCT_DATA,
NULL, 0,
productData,
sizeof(CHANGER_PRODUCT_DATA),
&nBytes, NULL);
if (retVal == FALSE) {
mctDebugPrint(0, "Error reading product data : %d\n",
GetLastError());
free(productData);
return MCT_STATUS_FAILED;
}
productData->VendorId[VENDOR_ID_LENGTH - 1] = '\0';
productData->ProductId[PRODUCT_ID_LENGTH - 1] = '\0';
productData->Revision[REVISION_LENGTH - 1] = '\0';
strncpy(SerialNum, productData->SerialNumber, SERIAL_NUMBER_LENGTH);
printf("Product Data for Medium Changer device : \n");
printf(" Vendor Id : %s\n", productData->VendorId);
printf(" Product Id : %s\n", productData->ProductId);
printf(" Revision : %s\n", productData->Revision);
printf(" SerialNumber : %s\n", SerialNum);
free(productData);
return MCT_STATUS_SUCCESS;
}
MCT_STATUS
mctSetAccess(CHAR ElementType, USHORT ElemAddr, CHAR Control)
{
CHANGER_SET_ACCESS setAccess;
DWORD nBytes;
ULONG retVal;
switch (ElementType) {
case CHANGER_IEPORT : {
setAccess.Element.ElementType = ChangerIEPort;
setAccess.Element.ElementAddress = ElemAddr;
if (Control == CHANGER_RETRACT_IEPORT) {
setAccess.Control = RETRACT_IEPORT;
} else if (Control == CHANGER_EXTEND_IEPORT) {
setAccess.Control = EXTEND_IEPORT;
} else if (Control == CHANGER_LOCK_ELEMENT) {
setAccess.Control = LOCK_ELEMENT;
} else if ((Control == CHANGER_UNLOCK_ELEMENT)) {
setAccess.Control = UNLOCK_ELEMENT;
} else {
mctDebugPrint(0, "Invalid Control type in SetAccess\n");
mctDebugPrint(0, "Valid types are R\\r or E\\e or L\\l or U\\u \n");
return MCT_STATUS_FAILED;
}
break;
}
case CHANGER_DOOR : {
setAccess.Element.ElementType = ChangerDoor;
setAccess.Element.ElementAddress = ElemAddr;
if (Control == CHANGER_LOCK_ELEMENT) {
setAccess.Control = LOCK_ELEMENT;
} else if (Control == CHANGER_UNLOCK_ELEMENT) {
setAccess.Control = UNLOCK_ELEMENT;
} else {
mctDebugPrint(0, "Invalid Control type in SetAccess\n");
mctDebugPrint(0, " Valid types are L\\l or U\\u \n");
return MCT_STATUS_FAILED;
}
break;
}
case CHANGER_KEYPAD : {
setAccess.Element.ElementType = ChangerKeypad;
setAccess.Element.ElementAddress = ElemAddr;
if (Control == CHANGER_LOCK_ELEMENT) {
setAccess.Control = LOCK_ELEMENT;
} else if (Control == CHANGER_UNLOCK_ELEMENT) {
setAccess.Control = UNLOCK_ELEMENT;
} else {
mctDebugPrint(0, "Invalid Control type in SetAccess\n");
mctDebugPrint(0, " Valid types are L\\l or U\\u \n");
return MCT_STATUS_FAILED;
}
break;
}
default: {
mctDebugPrint(0, "Invalid ElementType for SetAccess.\n");
mctDebugPrint(0, "Valid Type : \n");
mctDebugPrint(0, " IEPort : I or i\n");
mctDebugPrint(0, " Door : O or o\n");
mctDebugPrint(0, " KeyPad : K or k\n");
return MCT_STATUS_FAILED;
}
} // switch (ElementType)
retVal = DeviceIoControl(hChanger, IOCTL_CHANGER_SET_ACCESS,
&setAccess, sizeof(CHANGER_SET_ACCESS),
NULL, 0, &nBytes, NULL);
if (retVal == FALSE) {
mctDebugPrint(0, "Error doing SetAccess : %d\n",
GetLastError());
return MCT_STATUS_FAILED;
}
return MCT_STATUS_SUCCESS;
}
MCT_STATUS
mctSetPosition(CHAR ElemType, USHORT Dest)
{
CHANGER_SET_POSITION setPosition;
DWORD nBytes;
ULONG retVal;
setPosition.Transport.ElementType = ChangerTransport;
setPosition.Transport.ElementAddress = 0;
if (ElemType == CHANGER_SLOT) {
setPosition.Destination.ElementType = ChangerSlot;
} else if (ElemType == CHANGER_DRIVE) {
setPosition.Destination.ElementType = ChangerDrive;
} else if (ElemType == CHANGER_IEPORT) {
setPosition.Destination.ElementType = ChangerIEPort;
} else {
mctDebugPrint(0, "Invalid element type in SetPosition\n");
mctDebugPrint(0, " Valid element types are S\\s or D\\d \n");
return MCT_STATUS_FAILED;
}
setPosition.Destination.ElementAddress = Dest;
retVal = DeviceIoControl(hChanger, IOCTL_CHANGER_SET_POSITION,
&setPosition,
sizeof (CHANGER_SET_POSITION),
NULL, 0, &nBytes, NULL);
if (retVal == FALSE) {
mctDebugPrint(0, "SetPosition failed : %d \n", GetLastError());
return MCT_STATUS_FAILED;
}
return MCT_STATUS_SUCCESS;
}
MCT_STATUS
mctReinitTransport()
{
CHANGER_ELEMENT changerElem;
ULONG retVal;
DWORD nBytes;
changerElem.ElementType = ChangerTransport;
changerElem.ElementAddress = 0;
retVal = DeviceIoControl(hChanger, IOCTL_CHANGER_REINITIALIZE_TRANSPORT,
&changerElem, sizeof(CHANGER_ELEMENT),
NULL, 0, &nBytes, NULL);
if (retVal == FALSE) {
mctDebugPrint(0, "Error reinitializing transport : %d\n",
GetLastError());
return MCT_STATUS_FAILED;
}
return MCT_STATUS_SUCCESS;
}
MCT_STATUS
mctQueryVolumeTag()
{
mctDebugPrint(0, "QueryVolumeTag function to be implemented.\n");
return MCT_STATUS_SUCCESS;
}
MCT_STATUS
mctExchangeMedium(
CHAR TransType,
USHORT Transport,
CHAR SrcType,
USHORT Source,
CHAR Dest1Type,
USHORT Dest1,
CHAR Dest2Type,
USHORT Dest2)
{
CHANGER_EXCHANGE_MEDIUM ExchangeMedium;
DWORD nBytes;
ULONG retVal;
CHAR ElemType;
if(hChanger == INVALID_HANDLE_VALUE) {
mctDebugPrint(0, "Invalid handle to changer. Aborting!\n");
return MCT_STATUS_FAILED;
}
if (TransType != CHANGER_TRANSPORT) {
mctDebugPrint(0, "Invalid Transport ElementType to ExchangeMedium.\n");
mctDebugPrint(0, " Valid type is T\\t \n");
return MCT_STATUS_FAILED;
}
ExchangeMedium.Transport.ElementType = ChangerTransport;
ExchangeMedium.Transport.ElementAddress = Transport;
if (SrcType == CHANGER_SLOT) {
ExchangeMedium.Source.ElementType = ChangerSlot;
} else if (SrcType == CHANGER_DRIVE) {
ExchangeMedium.Source.ElementType = ChangerDrive;
} else {
mctDebugPrint(0, "Invalid Source ElementType to ExchangeMedium.\n");
mctDebugPrint(0, " Valid types are S\\s or D\\d \n");
return MCT_STATUS_FAILED;
}
ExchangeMedium.Source.ElementAddress = Source;
if (Dest1Type == CHANGER_SLOT) {
ExchangeMedium.Destination1.ElementType = ChangerSlot;
} else if (Dest1Type == CHANGER_DRIVE) {
ExchangeMedium.Destination1.ElementType = ChangerDrive;
} else {
mctDebugPrint(0, "Invalid Destination1 ElementType to ExchangeMedium.\n");
mctDebugPrint(0, " Valid types are S\\s or D\\d \n");
return MCT_STATUS_FAILED;
}
ExchangeMedium.Destination1.ElementAddress = Dest1;
if (Dest2Type == CHANGER_SLOT) {
ExchangeMedium.Destination2.ElementType = ChangerSlot;
} else if (Dest2Type == CHANGER_DRIVE) {
ExchangeMedium.Destination2.ElementType = ChangerDrive;
} else {
mctDebugPrint(0, "Invalid Destination2 ElementType to ExchangeMedium.\n");
mctDebugPrint(0, " Valid types are S\\s or D\\d \n");
return MCT_STATUS_FAILED;
}
ExchangeMedium.Destination2.ElementAddress = Dest2;
ExchangeMedium.Flip1 = FALSE;
ExchangeMedium.Flip2 = FALSE;
mctDebugPrint(3, "Exchange : Source - %d, Dest1 - %d, Dest2 - %d",
Source, Dest1, Dest2);
mctDebugPrint(3, " using Transport %d.\n", Transport);
retVal = DeviceIoControl(hChanger, IOCTL_CHANGER_EXCHANGE_MEDIUM,
&ExchangeMedium, sizeof(CHANGER_EXCHANGE_MEDIUM),
NULL, 0, &nBytes, NULL);
if (retVal == FALSE) {
mctDebugPrint(0, "Error doing exchange medium : %d\n", GetLastError());
return MCT_STATUS_FAILED;
}
return MCT_STATUS_SUCCESS;
}
MCT_STATUS
mctMoveMedium(
CHAR TransType,
USHORT Transport,
CHAR SourceType,
USHORT Source,
CHAR DestType,
USHORT Dest)
{
CHANGER_MOVE_MEDIUM MoveMedium;
DWORD nBytes;
ULONG retVal;
USHORT ElemType;
if(hChanger == INVALID_HANDLE_VALUE) {
mctDebugPrint(0, "Invalid handle to changer. Aborting!\n");
return MCT_STATUS_FAILED;
}
if (TransType != CHANGER_TRANSPORT) {
mctDebugPrint(0, "Invalid Transport ElementType to MoveMedium.\n");
mctDebugPrint(0, " Valid type is T\\t \n");
return MCT_STATUS_FAILED;
}
MoveMedium.Transport.ElementType = ChangerTransport;
MoveMedium.Transport.ElementAddress = Transport;
if (SourceType == CHANGER_SLOT) {
mctDebugPrint(3, "Source is a Slot\n");
MoveMedium.Source.ElementType = ChangerSlot;
} else if (SourceType == CHANGER_DRIVE) {
mctDebugPrint(3, "Source is a Drive\n");
MoveMedium.Source.ElementType = ChangerDrive;
} else if (SourceType == CHANGER_IEPORT) {
mctDebugPrint(3, "Source is a IEPort\n");
MoveMedium.Source.ElementType = ChangerIEPort;
}
else {
mctDebugPrint(0, "Invalid Source ElementType to MoveMedium.\n");
mctDebugPrint(0, " Valid types are S\\s or D\\d \n");
return MCT_STATUS_FAILED;
}
MoveMedium.Source.ElementAddress = Source;
if (DestType == CHANGER_SLOT) {
mctDebugPrint(3, "Destination is a Slot\n");
MoveMedium.Destination.ElementType = ChangerSlot;
} else if (DestType == CHANGER_DRIVE) {
mctDebugPrint(3, "Destination is a Drive\n");
MoveMedium.Destination.ElementType = ChangerDrive;
} else if (DestType == CHANGER_IEPORT) {
mctDebugPrint(3, "Destination is a IEPort\n");
MoveMedium.Destination.ElementType = ChangerIEPort;
} else {
mctDebugPrint(0, "Invalid Destination ElementType to MoveMedium.\n");
mctDebugPrint(0, " Valid types are S\\s or D\\d \n");
return MCT_STATUS_FAILED;
}
MoveMedium.Destination.ElementAddress = Dest;
MoveMedium.Flip = FALSE;
mctDebugPrint(3, "Move : Transport - %d, Src - %d, Dest - %d\n",
Transport, Source, Dest);
retVal = DeviceIoControl(hChanger, IOCTL_CHANGER_MOVE_MEDIUM,
&MoveMedium, sizeof(CHANGER_MOVE_MEDIUM),
NULL, 0, &nBytes, NULL);
if (retVal == FALSE) {
mctDebugPrint(0, "Error doing move medium : %d\n", GetLastError());
return MCT_STATUS_FAILED;
}
return MCT_STATUS_SUCCESS;
}
MCT_STATUS
mctGetParameters(BOOLEAN PrintParams)
{
ULONG retVal;
DWORD nBytes;
int i;
DWORD Features;
if(hChanger == INVALID_HANDLE_VALUE) {
mctDebugPrint(0, "Invalid handle to changer. Aborting!\n");
return MCT_STATUS_FAILED;
}
//
// Read changer params only if it hasn't been done already.
//
if (ChangerParamsRead == FALSE) {
//
// Get the parameters for this changer device.
//
retVal = DeviceIoControl(hChanger, IOCTL_CHANGER_GET_PARAMETERS,
NULL, 0, &ChangerParams, sizeof(GET_CHANGER_PARAMETERS),
&nBytes, NULL);
if (retVal == FALSE) {
mctDebugPrint(0, "Error reading changer parametes : %d.\n",
GetLastError());
return MCT_STATUS_FAILED;
}
}
if (PrintParams == FALSE) {
return MCT_STATUS_SUCCESS;
}
//
// Read the parameters of the changer. Display it.
//
printf("\n ********** Changer Parameters ********** \n\n");
printf("\t Number of Transport Elements : %d\n",
ChangerParams.NumberTransportElements);
printf("\t Number of Storage Elements : %d\n",
ChangerParams.NumberStorageElements);
printf("\t Number of Cleaner Slots : %d\n",
ChangerParams.NumberCleanerSlots);
printf("\t Number of of IE Elements : %d\n",
ChangerParams.NumberIEElements);
printf("\t Number of NumberDataTransferElements : %d\n",
ChangerParams.NumberDataTransferElements);
printf("\t Number of Doors : %d\n", ChangerParams.NumberOfDoors);
printf("\n\t First Slot Number : %d\n", ChangerParams.FirstSlotNumber);
printf("\t First Drive Number : %d\n", ChangerParams.FirstDriveNumber);
printf("\t First Transport Number : %d\n",
ChangerParams.FirstTransportNumber);
printf("\t First IEPort number : %d\n", ChangerParams.FirstIEPortNumber);
printf("\t First Cleaner Slot Address : %d\n",
ChangerParams.FirstCleanerSlotAddress);
printf("\n\t Magazine Size : %d\n", ChangerParams.MagazineSize);
printf("\n\t Drive Clean Timeout : %u\n", ChangerParams.DriveCleanTimeout);
printf("\n Flags set for the changer : \n");
Features = ChangerParams.Features0;
for (i = 0; i < 30; i++) {
if (Features & 1) {
printf("\t %s\n", ChangerFlagStrings0[i]);
}
Features >>= 1;
}
Features = ChangerParams.Features1;
for (i = 0; i < 11; i++) {
if (Features & 1) {
printf("\t %s\n", ChangerFlagStrings1[i]);
}
Features >>= 1;
}
PRINT_MOVE_CAPABILITIES(ChangerParams.MoveFromTransport, "Transport");
PRINT_MOVE_CAPABILITIES(ChangerParams.MoveFromSlot, "Slot");
PRINT_MOVE_CAPABILITIES(ChangerParams.MoveFromIePort, "IEPort");
PRINT_MOVE_CAPABILITIES(ChangerParams.MoveFromDrive, "Drive");
PRINT_EXCHANGE_CAPABILITIES(ChangerParams.ExchangeFromTransport, "Transport");
PRINT_EXCHANGE_CAPABILITIES(ChangerParams.ExchangeFromSlot, "Slot");
PRINT_EXCHANGE_CAPABILITIES(ChangerParams.ExchangeFromIePort, "IEPort");
PRINT_EXCHANGE_CAPABILITIES(ChangerParams.ExchangeFromDrive, "Drive");
if ((ChangerParams.Features0) & CHANGER_LOCK_UNLOCK) {
PRINT_LOCK_UNLOCK_CAPABILITY(ChangerParams.LockUnlockCapabilities,
LOCK_UNLOCK_IEPORT, "IEport");
PRINT_LOCK_UNLOCK_CAPABILITY(ChangerParams.LockUnlockCapabilities,
LOCK_UNLOCK_DOOR, "Drive");
PRINT_LOCK_UNLOCK_CAPABILITY(ChangerParams.LockUnlockCapabilities,
LOCK_UNLOCK_KEYPAD, "Keypad");
}
if ((ChangerParams.Features0) & CHANGER_POSITION_TO_ELEMENT) {
PRINT_POSITION_CAPABILITY(ChangerParams.PositionCapabilities,
CHANGER_TO_TRANSPORT, "Transport");
PRINT_POSITION_CAPABILITY(ChangerParams.PositionCapabilities,
CHANGER_TO_SLOT, "Slot");
PRINT_POSITION_CAPABILITY(ChangerParams.PositionCapabilities,
CHANGER_TO_DRIVE, "Drive");
PRINT_POSITION_CAPABILITY(ChangerParams.PositionCapabilities,
CHANGER_TO_IEPORT, "IEPort");
}
return MCT_STATUS_SUCCESS;
}
#if DBG
ULONG mctDebug = 8;
UCHAR DebugBuffer[128];
#endif
#if DBG
VOID
mctDebugPrint(
ULONG DebugPrintLevel,
PCHAR DebugMessage,
...
)
/*++
Routine Description:
Debug print for all medium changer drivers
Arguments:
Debug print level between 0 and 3, with 3 being the most verbose.
Return Value:
None
--*/
{
va_list ap;
va_start(ap, DebugMessage);
if (DebugPrintLevel <= mctDebug) {
vsprintf(DebugBuffer, DebugMessage, ap);
printf(DebugBuffer);
}
va_end(ap);
} // end mctDebugPrint()
#else
//
// DebugPrint stub
//
VOID
mctDebugPrint(
ULONG DebugPrintLevel,
PCHAR DebugMessage,
...
)
{
}
#endif