да видел я этот блог, а толку то? IoVolumeDeviceToDosName - это kernel а если из win32? про RtlNtPathNameToDosPathName там ничего осмысленного не сказано я даже больше скажу, я эту функцию пытался дизасмить, только надоело оч быстро первый параметр, вроде, должен быть NULL, два следующих - похоже, сами стринги, не поймешь ANSI_STRING или UNICODE.. какая входная, какая выходная, тоже непонятно. Кажется, входная первая последний параметр вообще непоняно для чего сколько не вызывал ее, получал один только какой-то бред
Код (Text): c: -----+ | v m: --> \Device\HarddiskVolume1 ^ | z: -----+ c: ссылка на \Device\HarddiskVolume1. Можно создать ещё ссылок, например, m: и z:. Девайс \Device\HarddiskVolume1 не знает, кто на него ссылается. Т.о. обратной функции нет - только перебор.
самые очевидные вещи приходят в голову самыми последними )) а что же тогда такое RtlNtPathNameToDosPathName() да, кстати, и IoVolumeDeviceToDosName?
мда.. разбираться в оптимизированном коде RtlNtPathNameToDosPathName я не стал, но похоже, все, что эта функция умеет делать - это убирать префиксы вида "\\??\\" и "\\??\\UNC\\"
от нефиг делать набросал: Код (Text): BOOL ConvertInternalNtPathToNtPath(IN LPCTSTR lpNtInternalPath, OUT LPTSTR lpNtPath, IN SIZE_T nNtPathLengthInBytes) { BOOL fReturned= FALSE; HANDLE hVolume= INVALID_HANDLE_VALUE; TCHAR tszBuffer[2*MAX_PATH]; TCHAR tszBuffer1[2*MAX_PATH]; LPTSTR lpVolumeName; DWORD dwLastError; size_t nLen, nLen1, nLen2; __try { if(lpNtInternalPath==NULL) { SetLastError(ERROR_BAD_ARGUMENTS); __leave; } hVolume= FindFirstVolume(tszBuffer, sizeof(tszBuffer)/sizeof(tszBuffer[0])-1); if(hVolume==NULL || hVolume==INVALID_HANDLE_VALUE) __leave; do { tszBuffer[sizeof(tszBuffer)/sizeof(tszBuffer[0])-1]= _T('\0'); if(!_tcsncmp(tszBuffer, _T("\\\\?\\UNC\\"), sizeof(_T("\\\\?\\UNC\\"))/sizeof(TCHAR)-1)) { lpVolumeName= tszBuffer+sizeof(_T("\\\\?\\UNC\\"))/sizeof(TCHAR)-1; nLen2= sizeof(_T("\\\\?\\UNC\\"))/sizeof(TCHAR)-1; } else if(!_tcsncmp(tszBuffer, _T("\\\\?\\"), sizeof(_T("\\\\?\\"))/sizeof(TCHAR)-1)) { lpVolumeName= tszBuffer+sizeof(_T("\\\\?\\"))/sizeof(TCHAR)-1; nLen2= sizeof(_T("\\\\?\\"))/sizeof(TCHAR)-1; } else { lpVolumeName= tszBuffer; nLen2= 0; } nLen= _tcslen(lpVolumeName); if(!nLen) continue; if(lpVolumeName[nLen-1]==_T('\\')) lpVolumeName[--nLen]= _T('\0'); nLen1= QueryDosDevice(lpVolumeName, tszBuffer1, sizeof(tszBuffer1)/sizeof(tszBuffer1[0])); if(!nLen1 || nLen1>=sizeof(tszBuffer1)/sizeof(tszBuffer1[0])-1) continue; nLen1= _tcslen(tszBuffer1); if(!nLen1) continue; if(!_tcsncmp(lpNtInternalPath, tszBuffer1, nLen1)) { if(lpNtPath==NULL) { SetLastError(ERROR_INVALID_USER_BUFFER); __leave; } nLen+= nLen2; nLen2= _tcslen(lpNtInternalPath); if(nLen2<nLen1) { SetLastError(ERROR_INVALID_DATA); __leave; } nLen2-= nLen1; nNtPathLengthInBytes/= sizeof(TCHAR); if(nNtPathLengthInBytes<nLen+nLen2+1) { SetLastError(ERROR_INSUFFICIENT_BUFFER); __leave; } _tcscpy(lpNtPath, tszBuffer); _tcsncpy(lpNtPath+nLen, lpNtInternalPath+nLen1, nLen2); lpNtPath[nLen+nLen2]= _T('\0'); fReturned= TRUE; SetLastError(ERROR_SUCCESS); __leave; } } while(FindNextVolume(hVolume, tszBuffer, sizeof(tszBuffer)/sizeof(tszBuffer[0]))); if(GetLastError()==ERROR_NO_MORE_FILES) SetLastError(ERROR_PATH_NOT_FOUND); } __finally { if(hVolume!=NULL && hVolume!=INVALID_HANDLE_VALUE) { dwLastError= GetLastError(); FindVolumeClose(hVolume); SetLastError(dwLastError); } } return fReturned; }
Переписал всё это дело на Паскаль - мож кому пригодится: Код (Text): function ConvertUNCtoDOS(UNCPath: PChar; out DOSPath: String): Boolean; const sHead1 = '\\?\UNC\'; sHead2 = '\\?\'; var hVolume: THandle; VolumeName: array [0..MAX_PATH] of Char; DeviceName: array [0..MAX_PATH] of Char; DriveLetter: array [0..12] of Char; VolumeName2: PChar; PathExe: PChar; Bytes: DWORD; lhead, lvn, lvn2, ldn, ldl: Integer; begin Result := False; DOSPath := ''; if (UNCPath = nil) then begin SetLastError(ERROR_BAD_ARGUMENTS); Exit; end; hVolume := FindFirstVolumeA(@VolumeName, SizeOf(VolumeName)); if (hVolume = 0) or (hVolume = INVALID_HANDLE_VALUE) then Exit; repeat VolumeName[SizeOf(VolumeName)-1] := #0; lvn := lstrlen(@VolumeName); if (lvn = 0) then Continue; if AnsiStrPos(@VolumeName, sHead1) = @VolumeName then begin VolumeName2 := Pointer(Cardinal(@VolumeName) + SizeOf(sHead1)); end else if AnsiStrPos(@VolumeName, sHead2) = @VolumeName then begin VolumeName2 := Pointer(Cardinal(@VolumeName) + SizeOf(sHead2)); end else begin VolumeName2 := @VolumeName; end; lvn2 := lstrlen(VolumeName2); if (lvn2 = 0) then Continue; if VolumeName2[lvn2-1] = '\' then begin Dec(lvn2); VolumeName2[lvn2] := #0; end; ldn := QueryDosDevice(VolumeName2, @DeviceName, SizeOf(DeviceName)); if (ldn = 0) or (ldn >= SizeOf(DeviceName)-1) then Continue; ldn := lstrlen(@DeviceName); if (ldn = 0) then Continue; if AnsiStrPos(UNCPath, @DeviceName) = UNCPath then begin if VolumeName2[lvn2-1] <> '\' then begin VolumeName2[lvn2] := '\'; VolumeName2[lvn2+1] := #0; end; if GetVolumePathNamesForVolumeNameA(@VolumeName, @DriveLetter, SizeOf(DriveLetter), Bytes) then begin ldl := lstrlen(@DriveLetter); if (ldl < 2) then Break; DOSPath := DriveLetter[0] + DriveLetter[1]; PathExe := Pointer(Cardinal(UNCPath) + ldn); DOSPath := DOSPath + PathExe; Result := True; Break; end else begin Break; end; end; until not FindNextVolumeA(hVolume, @VolumeName, SizeOf(VolumeName)); FindVolumeClose(hVolume); end;