Comment vérifier par programmation si le processus en cours est compatible avec Windows?

Dans Windows 10 version 1607, les processus peuvent désormais activer la reconnaissance du chemin long à l’aide d’un atsortingbut manifeste ( https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath ).

Comment puis-je vérifier par programme si le processus appelant est conscient du chemin long? Notez que la vérification de la version du système d’exploitation ou de la clé de Registre seule est insuffisante en raison du cas où la version de Windows est> = 1607, les chemins longs sont désactivés à l’échelle du système et le processus ne se manifeste pas pour les longs chemins.

ntdll (in win10 1607) exporte la prochaine API BOOLEAN NTAPI RtlAreLongPathsEnabled(); – donc vous pouvez appeler ça. il retourne TRUE si LongPaths Enabled

ici le code spinet – si RtlAreLongPathsEnabled renvoyé false – STATUS_NAME_TOO_LONG (c0000106) est retourné

entrer la description de l'image ici

système besoin de convertir le chemin d’access Win32 au chemin NT avant de l’utiliser dans toutes les fonctions de fichier, qui appellent le kernel. Ceci est fait en appelant RtlDosPathNameTo*NtPathName* . cette fonction, si voir ce chemin dépasse MAX_PATH (~) – appelé RtlAreLongPathsEnabled() et continuer le travail uniquement si la fonction retourne TRUE . au cas où false – STATUS_NAME_TOO_LONG est retourné.

Le code de RtlAreLongPathsEnabled est simplement – quand il est appelé pour la première fois – il vérifie le registre (et seulement le registre) et enregistre le résultat. ne cherche pas du tout manifeste. ici exactement code de fonction:

 BOOLEAN RtlAreLongPathsEnabled() { static BOOLEAN init; static BOOLEAN elp; if (!init) { init = true; HANDLE hKey; KEY_VALUE_PARTIAL_INFORMATION kvpi; STATIC_OBJECT_ATTRIBUTES(FileSystemRegKeyName, "\\registry\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\FileSystem"); if (0 <= ZwOpenKey(&hKey, KEY_READ, &FileSystemRegKeyName)) { STATIC_UNICODE_STRING(LongPathRegKeyValue, "LongPathsEnabled"); if (0 <= ZwQueryValueKey(hKey, &LongPathRegKeyValue, KeyValuePartialInformation, &kvpi, sizeof(kvpi), &kvpi.TitleIndex) && kvpi.Type == REG_DWORD && kvpi.DataLength == sizeof(DWORD)) { elp = *(DWORD*)kvpi.Data != 0; } ZwClose(hKey); } } return elp; } 

donc ma conclusion - dans le comportement de construction long de long path dépend uniquement des parameters de registre et absolu ne dépend pas du manifeste de l'application, malgré MSDN.

pour les votes faibles - pour moi tout simplement intéressant - quelqu'un de vous crée-t-il une application de test (avec et sans manifeste) et testez-le vous-même, ou vous ne pouvez lire que de la documentation?

pour ceux qui ont du mal ou trop paresseux pour écrire le code vous-même. vous pouvez tester avec ce code:

 BOOL CreateFolder(LPCWSTR lpPathName) { return CreateDirectoryW(lpPathName, 0) || GetLastError() == ERROR_ALREADY_EXISTS; } void LPT() { WCHAR name[128], path[0x8000], *c; if (!SHGetFolderPath(0, CSIDL_PROFILE , 0, 0, path)) { *name = '\\'; __stosw((PUSHORT)name + 1, '3', RTL_NUMBER_OF(name) - 2); name[RTL_NUMBER_OF(name) - 1] = 0; c = path + wcslen(path); int n = 4; do { memcpy(c, name, sizeof(name)); c += RTL_NUMBER_OF(name) - 1; if (!CreateFolder(path)) { break; } } while (--n); if (!n) { wcscpy(c, L"\\1.txt"); HANDLE hFile = CreateFileW(path, FILE_GENERIC_WRITE, FILE_SHARE_VALID_FLAGS, 0, OPEN_ALWAYS, 0, 0); if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); return ; } } } GetLastError(); } 

et testez-le avec true dans le manifeste et LongPathsEnabled==0 dans le registre. ça échoue? puis testez-le sans manifeste mais avec LongPathsEnabled==1 dans le registre. travaillé ?

si oui, je teste sur Windows 10. version 1607. build 14393.0


sur win10 1709 implémentation modifiée: maintenant RtlAreLongPathsEnabled est très simple:

entrer la description de l'image ici

 BOOLEAN RtlAreLongPathsEnabled() { return NtCurrentTeb()->ProcessEnvironmentBlock->IsLongPathAwareProcess; } 

dans la construction précédente était:

entrer la description de l'image ici