2016-10-20 1 views
-1

CD 트레이가 열려 있거나 닫혀 있는지 감지하는 코드가 필요합니다.CD 트레이 상태 감지

나는 얼마 전에 나는 다음과 같은 발견하기 때문에 이것이 가능하다고 생각 :
http://www.technical-recipes.com/2014/reading-the-status-of-dvd-drives-in-c/

문제는이 코드가 작동 할 수 있도록 할 수 없다는 것입니다. Visual Studio 2015에서 새 프로젝트를 만들고 거기에 코드를 붙여 넣은 다음 몇 가지 (많은) 내용을 다시 작성했습니다.

여기 내 코드입니다 :

#include "stdafx.h" 
#include <Windows.h> 
#include <string> 
#include <iostream> 
#include <string> 


#define SCSI_IOCTL_DATA_OUT 0 // Give data to SCSI device (e.g. for writing) 
#define SCSI_IOCTL_DATA_IN 1 // Get data from SCSI device (e.g. for reading) 
#define SCSI_IOCTL_DATA_UNSPECIFIED 2 // No data (e.g. for ejecting) 

#define MAX_SENSE_LEN 18 //Sense data max length 
#define IOCTL_SCSI_PASS_THROUGH_DIRECT 0x4D014 

using namespace std; 

typedef unsigned short USHORT; 
typedef unsigned char UCHAR; 
typedef unsigned long ULONG; 
typedef void* PVOID; 

typedef struct _SCSI_PASS_THROUGH_DIRECT 
{ 
    USHORT Length; 
    UCHAR ScsiStatus; 
    UCHAR PathId; 
    UCHAR TargetId; 
    UCHAR Lun; 
    UCHAR CdbLength; 
    UCHAR SenseInfoLength; 
    UCHAR DataIn; 
    ULONG DataTransferLength; 
    ULONG TimeOutValue; 
    PVOID DataBuffer; 
    ULONG SenseInfoOffset; 
    UCHAR Cdb[16]; 
} 
SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; 

typedef struct _SCSI_PASS_THROUGH_DIRECT_AND_SENSE_BUFFER 
{ 
    SCSI_PASS_THROUGH_DIRECT sptd; 
    UCHAR SenseBuf[MAX_SENSE_LEN]; 
} 
T_SPDT_SBUF; 


// Get the drive letter of the first DVD device encountered 
string GetDvdDriveLetter() 
{ 
std::string dvdDriveLetter = ""; 

DWORD drives = GetLogicalDrives(); 
DWORD dwSize = MAX_PATH; 
char szLogicalDrives[MAX_PATH] = { 0 }; 
DWORD dwResult = GetLogicalDriveStrings(dwSize, (LPTSTR)szLogicalDrives); 

// DWORD dwResult = GetLogicalDriveStrings(dwSize, szLogicalDrives); 

if (dwResult > 0 && dwResult <= MAX_PATH) 
{ 
char* szSingleDrive = szLogicalDrives; 

while (*szSingleDrive) 
{ 
const UINT driveType = GetDriveType((LPTSTR)szSingleDrive); 

if (driveType == 5) 
{ 
dvdDriveLetter = szSingleDrive; 
dvdDriveLetter = dvdDriveLetter.substr(0, 2); 
break; 
} 

// Get the next drive 
szSingleDrive += strlen(szSingleDrive) + 1; 
} 
} 

return dvdDriveLetter; 
} 

int GetDvdStatus() 
{ 
const std::string dvdDriveLetter = GetDvdDriveLetter(); 

if (dvdDriveLetter.empty()) return -1; 

const std::string strDvdPath = "\\\\.\\" 
+ dvdDriveLetter; 

HANDLE hDevice; // handle to the drive to be examined 
int iResult = -1; // results flag 
ULONG ulChanges = 0; 
DWORD dwBytesReturned; 
T_SPDT_SBUF sptd_sb; //SCSI Pass Through Direct variable. 
byte DataBuf[8]; //Buffer for holding data to/from drive. 

hDevice = CreateFile((LPTSTR)strDvdPath.c_str(), // drive 
0, // no access to the drive 
FILE_SHARE_READ, // share mode 
NULL, // default security attributes 
OPEN_EXISTING, // disposition 
FILE_ATTRIBUTE_READONLY, // file attributes 
NULL); 

// If we cannot access the DVD drive 
if (hDevice == INVALID_HANDLE_VALUE) 
{ 
return -1; 
} 

// A check to see determine if a DVD has been inserted into the drive only when iResult = 1. 
// This will do it more quickly than by sending target commands to the SCSI 
iResult = DeviceIoControl((HANDLE)hDevice, // handle to device 
IOCTL_STORAGE_CHECK_VERIFY2, // dwIoControlCode 
NULL, // lpInBuffer 
0, // nInBufferSize 
&ulChanges, // lpOutBuffer 
sizeof(ULONG), // nOutBufferSize 
&dwBytesReturned, // number of bytes returned 
NULL); // OVERLAPPED structure 

CloseHandle(hDevice); 

// Don't request the tray status as we often don't need it 
if (iResult == 1) return 2; 

hDevice = CreateFile((LPTSTR)strDvdPath.c_str(), 
GENERIC_READ | GENERIC_WRITE, 
FILE_SHARE_READ | FILE_SHARE_WRITE, 
NULL, 
OPEN_EXISTING, 
FILE_ATTRIBUTE_READONLY, 
NULL); 

if (hDevice == INVALID_HANDLE_VALUE) 
{ 
return -1; 
} 

sptd_sb.sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT); 
sptd_sb.sptd.PathId = 0; 
sptd_sb.sptd.TargetId = 0; 
sptd_sb.sptd.Lun = 0; 
sptd_sb.sptd.CdbLength = 10; 
sptd_sb.sptd.SenseInfoLength = MAX_SENSE_LEN; 
sptd_sb.sptd.DataIn = SCSI_IOCTL_DATA_IN; 
sptd_sb.sptd.DataTransferLength = sizeof(DataBuf); 
sptd_sb.sptd.TimeOutValue = 2; 
sptd_sb.sptd.DataBuffer = (PVOID) &(DataBuf); 
sptd_sb.sptd.SenseInfoOffset = sizeof(SCSI_PASS_THROUGH_DIRECT); 
sptd_sb.sptd.Cdb[0] = 0x4a; 
sptd_sb.sptd.Cdb[1] = 1; 
sptd_sb.sptd.Cdb[2] = 0; 
sptd_sb.sptd.Cdb[3] = 0; 
sptd_sb.sptd.Cdb[4] = 0x10; 
sptd_sb.sptd.Cdb[5] = 0; 
sptd_sb.sptd.Cdb[6] = 0; 
sptd_sb.sptd.Cdb[7] = 0; 
sptd_sb.sptd.Cdb[8] = 8; 
sptd_sb.sptd.Cdb[9] = 0; 
sptd_sb.sptd.Cdb[10] = 0; 
sptd_sb.sptd.Cdb[11] = 0; 
sptd_sb.sptd.Cdb[12] = 0; 
sptd_sb.sptd.Cdb[13] = 0; 
sptd_sb.sptd.Cdb[14] = 0; 
sptd_sb.sptd.Cdb[15] = 0; 

ZeroMemory(DataBuf, 8); 
ZeroMemory(sptd_sb.SenseBuf, MAX_SENSE_LEN); 

//Send the command to drive - request tray status for drive 
iResult = DeviceIoControl((HANDLE)hDevice, 
IOCTL_SCSI_PASS_THROUGH_DIRECT, 
(PVOID)&sptd_sb, 
(DWORD)sizeof(sptd_sb), 
(PVOID)&sptd_sb, 
(DWORD)sizeof(sptd_sb), 
&dwBytesReturned, 
NULL); 

CloseHandle(hDevice); 

if (iResult) 
{ 
if (DataBuf[5] == 0) iResult = 0; // DVD tray closed 
else if (DataBuf[5] == 1) iResult = 1; // DVD tray open 
else return iResult = 2; // DVD tray closed, media present 
} 

return iResult; 
} 

int main() 
{ 
// Uses the following information to obtain the status of a DVD/CD-ROM drive: 
// 1. GetLogicalDriveStrings() to list all logical drives 
// 2. GetDriveType() to obtain the type of drive 
// 3. DeviceIoControl() to obtain the device status 
// 
switch (GetDvdStatus()) 
{ 
case 0: 
std::cout << "DVD tray closed, no media" << std::endl; 
break; 
case 1: 
std::cout << "DVD tray open" << std::endl; 
break; 
case 2: 
std::cout << "DVD tray closed, media present" << std::endl; 
break; 
default: 
std::cout << "Drive not ready" << std::endl; 
break; 
} 

std::cout << GetDvdDriveLetter() << std::endl; 
getchar(); 
return 0; 
} 

이제 프로젝트가 내장되어 있습니다,하지만 응용 프로그램을 실행하면 "드라이브가 준비되지 않음"라는 아무 것도 반환하지 않습니다. 나는 무슨 일이 일어나는지 알 수 없다.

CD 트레이의 상태에 따라 올바른 결과를 얻으려면 어떻게해야합니까?

답변

0

좋아, 해결책을 찾았습니다. 리소스보기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 속성을 클릭해야했습니다. 특성 창에서 구성 특성 -> 일반으로 가서 문자 세트를 설정하지 않음으로 설정하십시오. 그게 다야. 이 솔루션은 다음을 기반으로합니다. cannot convert parameter 1 from 'char' to 'LPCWSTR'