들어가기에 앞서
이 시리즈는 나래온 툴의 내부 구조를 정리하여, 해당 프로그램의 일부 기능을 구현하는 사람들에게 도움을 줄 목적으로 작성되었다. 따라서 이 글은 그동안 질문 받았던 부분을 중심으로 쓰게 될 것이다. 더 궁금한 점이 있으면 메일로 문의하면 된다. 다만 코드 스니펫의 델파이 -> C++ 번역 요청은 받지 않는다.
필요성
디스크 툴이 처음 시작할 때 가장 먼저 하는 것은 디스크를 찾는 일이다. 여기에는 OS에서 제공하는 데이터베이스인 WMI를 이용하거나, 다른 API를 이용하는 방법이 있다. 나래온 툴에서는 어느 한 가지를 선택하지 않고, 두 가지 방법을 모두 순서대로 수행한다. 이처럼 나래온 툴에는 처음부터 어떤 방식을 써야 할 지 모르고 하나씩 시도해 보아야 할 것들이 많은데, 이것을 패턴으로 만든 것이 TAutoXXX 객체들이다.
어떤 스토리지를 가져올 것인가?
스토리지 목록을 가져오려면 가장 먼저 정의해야 할 것은, 어떤 드라이브를 가져올 지에 대한 계획이다. 로컬 드라이브인가? 네트워크 드라이브인가? 논리 파티션인가? 물리 드라이브인가? 이동식 디스크인가? 디스크를 분류하는 수많은 방법들이 있으며, 이것들은 한 API로 가져올 수 있는 게 아니라 흩어져 있다. 나래온 툴의 경우에는 물리 드라이브 (\\.\PhysicalDriveXX)를 가져온다.
이 부분을 확인하고 싶다면, TListChangeGetter의 GetPhysicalDriveList function에 중단점을 찍어보면 된다. 이 함수는 리스트가 달라지거나(USB 연결 등 PnP Signal) 프로그램을 켤 때 수행된다. 결과는 다음과 유사하게 나올 것이다. 당신의 PC에 달린 스토리지 갯수에 따라 리스트 길이는 달라질 수 있다. IPhysicalDrive 인터페이스와 TPhysicalDrive 객체에 대해서는 다음 편에 다룰 것이다.
두 가지 방법: WMI(TWMIPhysicalDriveListGetter), OS(TOSPhysicalDriveListGetter)
WMI는 Query 기반이므로 매우 간단하다. 이 부분은 TWMIPhysicalDriveListGetter 객체에 있다. 먼저 GetDiskDriveSearchResult에서 ‘Select * from Win32_DiskDrive’ 쿼리를 수행한다.
[snippet slug=getdiskdrivesearchresult lang=pascal]
그 후 TraverseResultAndAddFixedOrUSBDrive 내의 IfFixedOrUSBDriveAddToList에서 물리 디스크인지를 체크한다. 먼저 체크 과정에 오류가 없게 하기 위해서 해당 드라이브가 실재하고 각 항목이 Null이 아닌지를 확인해야 한다. IsCurrentDriveAvailable이 그 일을 하는데, 각 항목의 MediaLoaded가 True이고, MediaType이 Null이 아니고, DeviceID가 Null이 아닌 경우 Available이라고 판단한다.
[snippet slug=iscurrentdriveavailable lang=pascal]
그러면 CheckMediaTypeAndAddIfRequirementMet으로 넘어가 최종적으로 물리 디스크 여부를 체크한다. 이는 MediaType에 ‘hard’가 들어가고, InterfaceType이 ‘IDE’, ‘SCSI’, ‘USB’ 중 하나인 경우를 말한다. 이 모든 걸 만족하면 결과 리스트에 추가된다.
[snippet slug=checkmediatypeandaddifrequirementmet lang=pascal]
OS 방식은 QueryDosDevice API를 이용해 먼저 PhysicalDrive로 시작하는 경로명들을 얻어온다. 이 부분은 TOSPhysicalDriveGetter에 있다. TOSPhysicalDrivePathGetter에서 경로명들을 얻어온 뒤 파싱하는 작업을 한다. Null로 구분되어 있기 때문에 파싱은 매우 쉬운데, 델파이의 null-terminated string pointer(PChar)형이 해당 위치를 가리키게 하기만 하면 다음은 자동이다.
[snippet slug=parsevolumenameintolist lang=pascal]
PhysicalDrive의 존재 여부는 IOCTL_STORAGE_CHECK_VERIFY ioctl code로 알아낼 수 있다. 자세한 내용은 다음 편인 PhysicalDrive에서 알아볼 예정이다.
나래온 툴 내의 패턴(?): TAutoXXX
나래온 툴 내에는 한 가지 설계 패턴이 있다. 어떤 방식으로 해야 할지 알 수 없을 때, TAuto로 시작하는 객체에 일을 시키면 알아서 결정해주는 방식이다. 여기서도 다른 모든 객체들은 TAutoPhysicalDriveListGetter를 사용해 리스트를 얻어온다. 여기서는 WMI를 먼저 시도해본 뒤, 안 되면 OS에 직접 요청하는 식으로 이루어진다. 전체적으로 명령어 셋이나(ATA, SAT, NVMe, etc.), 파티션 종류에서도(NTFS, FAT32) 이 방식을 사용한다. 이는 델파이의 메타클래스 기능을 이용한 것이다.