본문 바로가기
프로그래밍/C++

cpp 가상드라이브 제어하기

by 건우아빠유리남편 2017. 10. 26.
반응형

가상 디스크 img파일이든 vhd파일이든 생성 하고 마운트/언마운트 하고 포맷하고 실제 파일로 사용하는 방법도 있는반면

symbolic link와 같이 바로가기 형태로 기존 드라이브나 폴더에 이어서 사용하는 방법도 존재.


win2000부터 subst.exe 라는 프로그램이 윈도우에 딸려 오는데 subst내부 에서는 DefineDosDevice 함수를 사용해서 구현했다고 한다.


subst로 프로그램을 만들었다가 사용자가 해당 프로그램으로 제거하거나 하면 내가 만든 프로그램이 오동작할테니... subst와 비슷하게 동작할 방법을 찾고찾다가 없어서 찾은 자료를 토대로 구현해본 소스. 잘 동작한다.


1. 드라이브에 해당하는 disk번호를 알아야함.

2. 드라이브에 해당하는 disk에 해당하는 시스템이 설치된 파티션번호를 알아야함.

3. 아래 처럼 마운트 하면 끗.




//가상 드라이브 생성 버튼 클릭

void XXXDlg::OnBnClickedBtnCreateVirtualdrive()

{

TCHAR szLogical[MAX_PATH] = { 0, };

TCHAR szPhysical[MAX_PATH] = { 0, };

// 드라이브의 번호, 파티션번호를 알아온다.

int nDiskNumber = 0;

int nPartitionNumber = 0;

m_VirDrvHandler.GetDiskNPartitionNumber('C', nDiskNumber, nPartitionNumber);


wsprintf(szPhysical, _T("\\Device\\Harddisk%d\\Partition%d"), nDiskNumber, nPartitionNumber);


GetDlgItem(IDC_VCD_DRIVE_NAME)->GetWindowText(m_strDriveName);

WCHAR wchDriveLetter = m_strDriveName.Left(1).GetAt(0);

TCHAR vcDriveName[256];

wsprintf(vcDriveName, _T("%c:"), wchDriveLetter);


int iResult = VirtualDriveMount(szPhysical, vcDriveName);

}


// 가상드라이브 제거버튼 클릭. 

void XXXDlg::OnBnClickedBtnDeleteVirtualdrive()

{

GetDlgItem(IDC_VCD_DRIVE_NAME)->GetWindowText(m_strDriveName);

WCHAR wchDriveLetter = m_strDriveName.Left(1).GetAt(0);

TCHAR vcDriveName[256];

wsprintf(vcDriveName, _T("%c:"), wchDriveLetter);


int iResult = VirtualDriveUnmount(vcDriveName);

}


// 가상드라이브 마운트(subst)

int XXXDlg::VirtualDriveMount(TCHAR *DevName, TCHAR *driver)

{

if (!DefineDosDevice(

DDD_RAW_TARGET_PATH,

driver,

DevName))

{

return -1;

}

return 0;

}



// 가상드라이브 언마운트(subst)

int XXXDlg::VirtualDriveUnmount(TCHAR *driver)

{

if (!DefineDosDevice(

DDD_REMOVE_DEFINITION,

driver,

NULL))

{

TRACE("Unmount: Remove %s error.\n", driver);

return -1;

}

return 0;

}


// 드라이브 문자로 디스크번호와 파티션번호를 알아옴.

int CVirtualDiskHandler::GetDiskNPartitionNumber(char cDriveName, int &nOutDiskNum, int &nOutPartitionNum)

{


char vcDriveName[40];

// 해당 Drive의 정보를 얻는다.

sprintf(vcDriveName, "\\\\?\\%c:", cDriveName);


HANDLE h = ::CreateFileA(vcDriveName, 0, 0, NULL, OPEN_EXISTING, 0, NULL);


STORAGE_DEVICE_NUMBER info = {};

DWORD bytesReturned = 0;


::DeviceIoControl(h, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &info, sizeof(info), &bytesReturned, NULL);

CloseHandle(h);


  // info안에 disk번호와 파티션번호가 들었당.

nOutDiskNum = info.DeviceNumber;

nOutPartitionNum = info.PartitionNumber;


return 1;

}



촤하하~

반응형

댓글