As part of an installation program I need control of the CD-Drive and in particular want to open it from software. This is fine on a local machine but, as best I can determine not possible on a networked machine.
I've tried this with mmi where I mapped \\Server\Share to a drive letter and also with winio passing a direct string.
Either I'm missing something with UNC names or this simply isn't doable (I have administrator rights on my network and the CD drive is shared anyway so it's not a privilage problem).
I've cludged together a cmdline test jig utility as proof of problem :
#include <stdio.h>
#include <stdos.h>
#include <mmsystem.h>
#include <Winioctl.h>
// Defines :
#define CD_DRIVE_OPEN 1
#define CD_DRIVE_CLOSE 2
// Prototypes :
BOOL parseoptions (INT argc, CHAR* argv[], INT& opendrive, CHAR& driveletter);
BOOL diskdoor_mci (BOOL opendrive, CHAR driveletter);
BOOL diskdoor_winio (BOOL opendrive, CHAR driveletter);
VOID openalldrives (BOOL opendrives);
INT main(INT argc, CHAR* argv[])
{ INT opendrive;
CHAR driveletter;
// Parse Command Line:
if (!parseoptions(argc, argv, opendrive, driveletter))
{ printf("Incorrect command line.\n Usage: cdeject <open|close> [Drive|ALL]\n"
printf("Example : cdeject open E:\n"
}
// Open all drives:
else if (driveletter == 0)
openalldrives((opendrive == CD_DRIVE_OPEN));
else
{ // Choose which drive to open/close:
switch(opendrive)
{ case CD_DRIVE_OPEN:
if (!diskdoor_mci(TRUE, driveletter))
diskdoor_winio(TRUE,driveletter);
break;
case CD_DRIVE_CLOSE:
if (!diskdoor_mci(FALSE, driveletter))
diskdoor_winio(FALSE, driveletter);
break;
}
}
return(0);
}
BOOL parseoptions(INT argc, CHAR* argv[], INT& opendrive, CHAR& driveletter)
{ // Sanity Check
if(argc < 2) return(FALSE); // Not enough params..
if(argc > 3) return(FALSE); // Too many params..
// Open or Close Drive?
opendrive = 0;
if(stricmp(argv[1], "open" == 0) opendrive = CD_DRIVE_OPEN;
if(stricmp(argv[1], "close" == 0) opendrive = CD_DRIVE_CLOSE;
if(opendrive == 0) return(FALSE); // argv[1] isn't "open" or "close"
// Which Drive?
if(argc == 2)
{ // No drive specified, so flag Default drive
driveletter = 1;
return(TRUE);
}
// If drive is "ALL" or "*" then flag all drives
if((stricmp(argv[2], "all" == 0) || (strcmp(argv[2], "*" == 0))
{ // ALL drives
driveletter = 0;
return(TRUE);
}
LPCTSTR drive = argv[2];
INT len = strlen(drive);
if(len > 2) return(FALSE);
if((len == 2) && (drive[1] != ':')) return(FALSE);
// Get Drive Letter
driveletter = drive[0];
if((driveletter >= 'a') && (driveletter <= 'z'))
driveletter = driveletter - 32; // Convert lowercase to uppercase
// Valid Drive Letter?
if( (driveletter < 'A') || (driveletter > 'Z') )
return(FALSE);
// OK
return(TRUE);
}
VOID openalldrives (BOOL opendrives)
{ // Determine All CD Drives and Open (or Close) each one
INT pos = 0;
UINT count = 0;
CHAR drive[4];
strcpy(drive, "?:\\"
DWORD drivelist = ::GetLogicalDrives ();
while (drivelist)
{ if (drivelist & 1)
{ drive[0] = 0x41 + pos;
if:GetDriveType(drive) == DRIVE_CDROM)
diskdoor_mci(opendrives, drive[0]);
}
drivelist >>= 1;
pos++;
}
}
BOOL diskdoor_mci(BOOL opendrive, CHAR driveletter)
// Open/close a single specified CD Drive using MCI interface :
{ MCI_OPEN_PARMS op;
MCI_STATUS_PARMS st;
DWORD flags;
CHAR drivename[4];
strcpy(drivename, "X:"
::ZeroMemory(&op, sizeof(MCI_OPEN_PARMS));
op.lpstrDeviceType = (LPCSTR) MCI_DEVTYPE_CD_AUDIO;
if(driveletter > 1)
{ drivename[0] = driveletter;
op.lpstrElementName = drivename;
flags = MCI_OPEN_TYPE
| MCI_OPEN_TYPE_ID
| MCI_OPEN_ELEMENT
| MCI_OPEN_SHAREABLE;
}
else flags = MCI_OPEN_TYPE
| MCI_OPEN_TYPE_ID
| MCI_OPEN_SHAREABLE;
if (!mciSendCommand(0,MCI_OPEN,flags,(unsigned long)&op))
{ st.dwItem = MCI_STATUS_READY;
if(opendrive)
mciSendCommand(op.wDeviceID,MCI_SET,MCI_SET_DOOR_OPEN,0);
else
mciSendCommand(op.wDeviceID,MCI_SET,MCI_SET_DOOR_CLOSED,0);
mciSendCommand(op.wDeviceID,MCI_CLOSE,MCI_WAIT,0);
}
else
printf ("Failed to Open the device.\n"
return FALSE;
}
BOOL diskdoor_winio(BOOL opendrive, CHAR driveletter)
// Open/close a single specified CD Drive using MCI interface :
{ CHAR Drive[MAX_PATH];
HANDLE hDrive = INVALID_HANDLE_VALUE;
DWORD dwErr;
BOOL bRetVal = TRUE;
DWORD dwDummy;
sprintf(Drive,"\\\\Pandora\\CD"
// Try this first.
if (GetVersion >= 0)
{ //WinNT, 2000 -->
hDrive = CreateFile(Drive, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
}
if(hDrive == INVALID_HANDLE_VALUE)
{ SetLastError(NO_ERROR);
hDrive = CreateFile("\\UNC\\Judes\\CD", GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
}
dwErr = GetLastError();
if(hDrive != INVALID_HANDLE_VALUE && dwErr == NO_ERROR)
{ // The drive is Open OK
if(opendrive)
{ // Eject it.
bRetVal = DeviceIoControl(hDrive, IOCTL_STORAGE_EJECT_MEDIA, NULL,
0, NULL, 0, &dwDummy, NULL);
}
else
{ // retract it
bRetVal = DeviceIoControl(hDrive, IOCTL_STORAGE_LOAD_MEDIA, NULL,
0, NULL, 0, &dwDummy, NULL);
}
if(bRetVal == FALSE)
{ // Couldn't do it, error
// Do error handling
bRetVal = FALSE;
printf("WINIO attempt failed.\n"
}
}
else
{ // Error Opening Device :
bRetVal = FALSE;
printf("Error Opening Device...Winio. GetLastError returns 0x%08X\n",dwErr);
}
if(hDrive != INVALID_HANDLE_VALUE) CloseHandle(hDrive);
return bRetVal;
}
Any help would be appreciated.
P.S. While hunting through the net for the above I came across this < - Any IE users should have a look (but not while burning a CD)
I've tried this with mmi where I mapped \\Server\Share to a drive letter and also with winio passing a direct string.
Either I'm missing something with UNC names or this simply isn't doable (I have administrator rights on my network and the CD drive is shared anyway so it's not a privilage problem).
I've cludged together a cmdline test jig utility as proof of problem :
#include <stdio.h>
#include <stdos.h>
#include <mmsystem.h>
#include <Winioctl.h>
// Defines :
#define CD_DRIVE_OPEN 1
#define CD_DRIVE_CLOSE 2
// Prototypes :
BOOL parseoptions (INT argc, CHAR* argv[], INT& opendrive, CHAR& driveletter);
BOOL diskdoor_mci (BOOL opendrive, CHAR driveletter);
BOOL diskdoor_winio (BOOL opendrive, CHAR driveletter);
VOID openalldrives (BOOL opendrives);
INT main(INT argc, CHAR* argv[])
{ INT opendrive;
CHAR driveletter;
// Parse Command Line:
if (!parseoptions(argc, argv, opendrive, driveletter))
{ printf("Incorrect command line.\n Usage: cdeject <open|close> [Drive|ALL]\n"
printf("Example : cdeject open E:\n"
}
// Open all drives:
else if (driveletter == 0)
openalldrives((opendrive == CD_DRIVE_OPEN));
else
{ // Choose which drive to open/close:
switch(opendrive)
{ case CD_DRIVE_OPEN:
if (!diskdoor_mci(TRUE, driveletter))
diskdoor_winio(TRUE,driveletter);
break;
case CD_DRIVE_CLOSE:
if (!diskdoor_mci(FALSE, driveletter))
diskdoor_winio(FALSE, driveletter);
break;
}
}
return(0);
}
BOOL parseoptions(INT argc, CHAR* argv[], INT& opendrive, CHAR& driveletter)
{ // Sanity Check
if(argc < 2) return(FALSE); // Not enough params..
if(argc > 3) return(FALSE); // Too many params..
// Open or Close Drive?
opendrive = 0;
if(stricmp(argv[1], "open" == 0) opendrive = CD_DRIVE_OPEN;
if(stricmp(argv[1], "close" == 0) opendrive = CD_DRIVE_CLOSE;
if(opendrive == 0) return(FALSE); // argv[1] isn't "open" or "close"
// Which Drive?
if(argc == 2)
{ // No drive specified, so flag Default drive
driveletter = 1;
return(TRUE);
}
// If drive is "ALL" or "*" then flag all drives
if((stricmp(argv[2], "all" == 0) || (strcmp(argv[2], "*" == 0))
{ // ALL drives
driveletter = 0;
return(TRUE);
}
LPCTSTR drive = argv[2];
INT len = strlen(drive);
if(len > 2) return(FALSE);
if((len == 2) && (drive[1] != ':')) return(FALSE);
// Get Drive Letter
driveletter = drive[0];
if((driveletter >= 'a') && (driveletter <= 'z'))
driveletter = driveletter - 32; // Convert lowercase to uppercase
// Valid Drive Letter?
if( (driveletter < 'A') || (driveletter > 'Z') )
return(FALSE);
// OK
return(TRUE);
}
VOID openalldrives (BOOL opendrives)
{ // Determine All CD Drives and Open (or Close) each one
INT pos = 0;
UINT count = 0;
CHAR drive[4];
strcpy(drive, "?:\\"
DWORD drivelist = ::GetLogicalDrives ();
while (drivelist)
{ if (drivelist & 1)
{ drive[0] = 0x41 + pos;
if:GetDriveType(drive) == DRIVE_CDROM)
diskdoor_mci(opendrives, drive[0]);
}
drivelist >>= 1;
pos++;
}
}
BOOL diskdoor_mci(BOOL opendrive, CHAR driveletter)
// Open/close a single specified CD Drive using MCI interface :
{ MCI_OPEN_PARMS op;
MCI_STATUS_PARMS st;
DWORD flags;
CHAR drivename[4];
strcpy(drivename, "X:"
::ZeroMemory(&op, sizeof(MCI_OPEN_PARMS));
op.lpstrDeviceType = (LPCSTR) MCI_DEVTYPE_CD_AUDIO;
if(driveletter > 1)
{ drivename[0] = driveletter;
op.lpstrElementName = drivename;
flags = MCI_OPEN_TYPE
| MCI_OPEN_TYPE_ID
| MCI_OPEN_ELEMENT
| MCI_OPEN_SHAREABLE;
}
else flags = MCI_OPEN_TYPE
| MCI_OPEN_TYPE_ID
| MCI_OPEN_SHAREABLE;
if (!mciSendCommand(0,MCI_OPEN,flags,(unsigned long)&op))
{ st.dwItem = MCI_STATUS_READY;
if(opendrive)
mciSendCommand(op.wDeviceID,MCI_SET,MCI_SET_DOOR_OPEN,0);
else
mciSendCommand(op.wDeviceID,MCI_SET,MCI_SET_DOOR_CLOSED,0);
mciSendCommand(op.wDeviceID,MCI_CLOSE,MCI_WAIT,0);
}
else
printf ("Failed to Open the device.\n"
return FALSE;
}
BOOL diskdoor_winio(BOOL opendrive, CHAR driveletter)
// Open/close a single specified CD Drive using MCI interface :
{ CHAR Drive[MAX_PATH];
HANDLE hDrive = INVALID_HANDLE_VALUE;
DWORD dwErr;
BOOL bRetVal = TRUE;
DWORD dwDummy;
sprintf(Drive,"\\\\Pandora\\CD"
// Try this first.
if (GetVersion >= 0)
{ //WinNT, 2000 -->
hDrive = CreateFile(Drive, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
}
if(hDrive == INVALID_HANDLE_VALUE)
{ SetLastError(NO_ERROR);
hDrive = CreateFile("\\UNC\\Judes\\CD", GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
}
dwErr = GetLastError();
if(hDrive != INVALID_HANDLE_VALUE && dwErr == NO_ERROR)
{ // The drive is Open OK
if(opendrive)
{ // Eject it.
bRetVal = DeviceIoControl(hDrive, IOCTL_STORAGE_EJECT_MEDIA, NULL,
0, NULL, 0, &dwDummy, NULL);
}
else
{ // retract it
bRetVal = DeviceIoControl(hDrive, IOCTL_STORAGE_LOAD_MEDIA, NULL,
0, NULL, 0, &dwDummy, NULL);
}
if(bRetVal == FALSE)
{ // Couldn't do it, error
// Do error handling
bRetVal = FALSE;
printf("WINIO attempt failed.\n"
}
}
else
{ // Error Opening Device :
bRetVal = FALSE;
printf("Error Opening Device...Winio. GetLastError returns 0x%08X\n",dwErr);
}
if(hDrive != INVALID_HANDLE_VALUE) CloseHandle(hDrive);
return bRetVal;
}
Any help would be appreciated.
P.S. While hunting through the net for the above I came across this < - Any IE users should have a look (but not while burning a CD)