2010-12-14 23 views
5

Sto lavorando alla segnalazione di alcune informazioni ricavate dalle API di sistema native. (So ​​che questo è male .... ma sto ricevendo informazioni che non posso ottenere altrimenti, e ho poco problemi con dover aggiornare la mia app se/quando arriva il momento.)Come posso convertire un nome di percorso nativo (NT) in un nome di percorso Win32?

Il nativo L'API restituisce i nomi di percorso nativi, come visto da ob, ovvero \SystemRoot\System32\Ntoskrnl.exe o \??\C:\Program Files\VMWare Workstation\vstor-ws60.sys.

posso sostituire i prefissi comuni, vale a dire

std::wstring NtPathToWin32Path(std::wstring ntPath) 
{ 
    if (boost::starts_with(ntPath, L"\\\\?\\")) 
    { 
     ntPath.erase(ntPath.begin(), ntPath.begin() + 4); 
     return ntPath; 
    } 
    if (boost::starts_with(ntPath, L"\\??\\")) 
    { 
     ntPath.erase(ntPath.begin(), ntPath.begin() + 4); 
    } 
    if (boost::starts_with(ntPath, L"\\")) 
    { 
     ntPath.erase(ntPath.begin(), ntPath.begin() + 1); 
    } 
    if (boost::istarts_with(ntPath, L"globalroot\\")) 
    { 
     ntPath.erase(ntPath.begin(), ntPath.begin() + 11); 
    } 
    if (boost::istarts_with(ntPath, L"systemroot")) 
    { 
     ntPath.replace(ntPath.begin(), ntPath.begin() + 10, GetWindowsPath()); 
    } 
    if (boost::istarts_with(ntPath, L"windows")) 
    { 
     ntPath.replace(ntPath.begin(), ntPath.begin() + 7, GetWindowsPath()); 
    } 
    return ntPath; 
} 

TEST(Win32Path, NtPathDoubleQuestions) 
{ 
    ASSERT_EQ(L"C:\\Example", NtPathToWin32Path(L"\\??\\C:\\Example")); 
} 

TEST(Win32Path, NtPathUncBegin) 
{ 
    ASSERT_EQ(L"C:\\Example", NtPathToWin32Path(L"\\\\?\\C:\\Example")); 
} 

TEST(Win32Path, NtPathWindowsStart) 
{ 
    ASSERT_EQ(GetCombinedPath(GetWindowsPath(), L"Hello\\World"), NtPathToWin32Path(L"\\Windows\\Hello\\World")); 
} 

TEST(Win32Path, NtPathSystemrootStart) 
{ 
    ASSERT_EQ(GetCombinedPath(GetWindowsPath(), L"Hello\\World"), NtPathToWin32Path(L"\\SystemRoot\\Hello\\World")); 
} 

TEST(Win32Path, NtPathGlobalRootSystemRoot) 
{ 
    ASSERT_EQ(GetCombinedPath(GetWindowsPath(), L"Hello\\World"), NtPathToWin32Path(L"\\globalroot\\SystemRoot\\Hello\\World")); 
} 

ma sarei fortemente sorpreso se non c'è qualche API, nativo o meno, che permette di convertire questi in nomi di percorso Win32. Esiste una tale API?

+0

Condivide la funzione API di shell 'PathCanonicalize' fare il trucco? http://msdn.microsoft.com/en-us/library/bb773569%28v=vs.85%29.aspx – Praetorian

+0

@Praetorian: No, PathCanonicalize accetta i percorsi Win32. Sto cercando di ottenere un percorso Win32. –

+1

Non conosco nessuna di queste funzioni, e non è sempre possibile: NT può usare percorsi che Win32 non può affatto. Buona fortuna comunque ... – ephemient

risposta

6

Facciamo questo nel codice di produzione. Per quanto ne so non ci sono API (pubbliche o private) che gestiscono questo. Facciamo solo alcuni confronti di stringhe con alcuni prefissi e funziona per noi.

Apparentemente esiste una funzione denominata RtlNtPathNameToDosPathName() in ntdll.dll (introdotta con XP?), Ma non ho idea di cosa faccia; Immagino che abbia più a che fare con cose come \ Device \ Harddisk0, comunque.

Non sono sicuro che ci sia davvero bisogno di una tale funzione. Win32 passa i percorsi (nel senso di CreateFile, ecc.) A NT; NT non passa i percorsi a Win32. Quindi ntdll.dll non ha realmente bisogno di passare da percorsi NT a percorsi Win32. Nel raro caso in cui alcune funzioni di query NT restituiscano un percorso completo, qualsiasi funzione di conversione potrebbe essere interna alla dll Win32 (ad esempio non esportata). Non so nemmeno se si preoccupino, dato che cose come GetModuleFileName() restituiranno semplicemente qualsiasi percorso utilizzato per caricare l'immagine. Immagino che questa sia solo un'astrazione che perde.

+0

+1. Modificato la mia domanda - che qualcosa di simile a quello che fai? –

+0

Praticamente. Gli unici che ho visto su base regolare sono \\ ?? \\ e \\ SystemRoot, e anche in questo caso è abbastanza raro (in genere con processi di basso livello avviati all'inizio della sequenza di avvio. .. di solito correlate a dette processi – Luke

+0

sto gingillarsi con roba non documentata e tutti quei prefissi sembrano essere comune qui Credo che ci sia una ragione che stanno privi di documenti: P –

4

Ecco qualcosa che potresti provare. Per prima cosa utilizzare NtCreateFile per aprire il file, il volume ecc. Per la lettura. Quindi utilizzare la MANI restituita per ottenere il percorso completo come descritto here.

+1

+1 :) Si noti che è possibile saltare il passo di mappatura dei file chiamando 'NtQueryFileInformation' e chiedendo la classe informazioni' FileNameInformation'. (Anche se non l'ho ancora provato, e ovviamente quello che sta entrando nelle cose non documentate ...) –

+0

GetFinalPathNameByHandle potrebbe aiutare a ripulire questo! – Gbps

1

Vedere my answer to this question.

È necessario prima ottenere un handle per il file in tale percorso e quindi ottenere il percorso Win32 per l'handle.

+0

Questo funziona, ma il problema è che è necessario accedere alla posizione del file per poterlo eseguire (perché è necessario essere in grado di aprire un handle) - Spesso non lo sono. –

+0

@Billy: tutto ciò di cui hai bisogno è l'accesso a 'FILE_READ_ATTRIBUTES', che puoi sempre ottenere. Se non riesci a ottenerlo, provalo sulla directory superiore e quindi concatena il nome del file alla fine. (Non è possibile convertire senza alcun handle, perché non è sempre un mapping one-to-one.) – Mehrdad

+0

@Mehrdad: Deve essere possibile convertire senza un handle. FindFirstFile/FindNextFile/FindClose non aprire gli handle. Puoi usarli per elencare una struttura di directory anche se non puoi leggere alcun attributo sul file. Questa soluzione funziona, quindi +1, ma in realtà non mi aiuta :( –

0

Ho scritto una funzione che converte diversi tipi di nomi di dispositivi NT (nomi di file, porte COM, percorsi di rete, ecc.) In un percorso DOS.

Ci sono due funzioni. Uno converte un handle in un percorso NT e l'altro converte questo percorso NT in un percorso DOS.

Date un'occhiata qui: How to get name associated with open HANDLE

// "\Device\HarddiskVolume3"        (Harddisk Drive) 
// "\Device\HarddiskVolume3\Temp"       (Harddisk Directory) 
// "\Device\HarddiskVolume3\Temp\transparent.jpeg"   (Harddisk File) 
// "\Device\Harddisk1\DP(1)0-0+6\foto.jpg"     (USB stick) 
// "\Device\TrueCryptVolumeP\Data\Passwords.txt"   (Truecrypt Volume) 
// "\Device\Floppy0\Autoexec.bat"       (Floppy disk) 
// "\Device\CdRom1\VIDEO_TS\VTS_01_0.VOB"     (DVD drive) 
// "\Device\Serial1"          (real COM port) 
// "\Device\USBSER000"          (virtual COM port) 
// "\Device\Mup\ComputerName\C$\Boot.ini"     (network drive share, Windows 7) 
// "\Device\LanmanRedirector\ComputerName\C$\Boot.ini"  (network drive share, Windwos XP) 
// "\Device\LanmanRedirector\ComputerName\Shares\Dance.m3u" (network folder share, Windwos XP) 
// "\Device\Afd"           (internet socket) 
// "\Device\Console000F"         (unique name for any Console handle) 
// "\Device\NamedPipe\Pipename"        (named pipe) 
// "\BaseNamedObjects\Objectname"       (named mutex, named event, named semaphore) 
// "\REGISTRY\MACHINE\SOFTWARE\Classes\.txt"    (HKEY_CLASSES_ROOT\.txt) 
Problemi correlati