JJ_MKVMaker/lib/core/files/windows_drives.dart

51 lines
2.1 KiB
Dart

import 'dart:ffi';
import 'dart:io';
import 'package:ffi/ffi.dart';
// 약속 (나누기 file_ops): Windows 저장 장치 - 드라이브 목록 · 드라이브 종류 · 네트워크 공유의 맨 위.
// 입력: 드라이브 맨 위 ("C:\") · 경로. 출력: 목록 · 종류 번호 · 글.
// 오류: 던지지 않는다. Windows API 를 부르지 못하면 [windowsDrives] 는 C: 하나, [driveType] 은 0 (모름).
// 드라이브를 열어 보지 않는다 (끊긴 네트워크 드라이브에서 멈추지 않게).
/// 저장 장치 (맨 위 폴더): Windows 는 드라이브 (C:\ …), 그 밖은 주어진 목록.
/// 165: 드라이브 문자는 Windows 가 알려 주는 목록 (GetLogicalDrives) 으로 - 드라이브마다 열어 보지 않는다
/// (끊긴 · 느린 네트워크 드라이브 (NAS) 를 열어 보느라 탐색기가 10초씩 멈췄다)
List<(String path, String label)> windowsDrives() {
int mask;
try {
mask = DynamicLibrary.open('kernel32.dll').lookupFunction<Uint32 Function(), int Function()>('GetLogicalDrives')();
} catch (_) {
mask = 0;
}
if (mask == 0) return [(r'C:\', 'C:')];
return [
for (final c in 'CDEFGHIJKLMNOPQRSTUVWXYZAB'.split(''))
if (mask & (1 << (c.codeUnitAt(0) - 65)) != 0) ('$c:\\', '$c:'),
];
}
/// 165: 드라이브 종류 (GetDriveTypeW: 2 꺼내는 장치 (카드 리더 · USB) · 3 고정 · 4 네트워크 · 5 CD). 드라이브를 열어 보지 않는다. 모르면 0
int driveType(String root) {
if (!Platform.isWindows) return 0;
final w = root.toNativeUtf16();
try {
final f = DynamicLibrary.open('kernel32.dll')
.lookupFunction<Uint32 Function(Pointer<Utf16>), int Function(Pointer<Utf16>)>('GetDriveTypeW');
return f(w);
} catch (_) {
return 0;
} finally {
calloc.free(w);
}
}
/// 네트워크 드라이브인지
bool isNetworkDrive(String root) => driveType(root) == 4;
/// Windows 네트워크 공유 경로의 맨 위 (\\서버\공유). 37
String uncRoot(String path) {
final parts = path.replaceAll('/', r'\').split(r'\').where((s) => s.isNotEmpty).toList();
return parts.length < 2 ? path : '\\\\${parts[0]}\\${parts[1]}';
}