2016-06-26 27 views
5

Trong phiên bản Windows của dự án cá nhân hiện tại của tôi, tôi đang tìm cách hỗ trợ extended length filepaths. Kết quả là, tôi hơi bối rối với cách sử dụng API GetFullPathNameW để giải quyết tên đầy đủ của một filepath dài.GetFullPathNameW và đường dẫn tệp Windows dài

Theo MSDN (liên quan đến các thông số lpFileName):

Trong phiên bản ANSI của chức năng này, tên của nó là giới hạn ký tự MAX_PATH. Để mở rộng giới hạn này thành 32.767 ký tự rộng, hãy gọi phiên bản Unicode của hàm và thêm "\? \" Vào đường dẫn. Để biết thêm thông tin, hãy xem Đặt tên tệp.

Nếu tôi hiểu chính xác điều này, để sử dụng đoạn phim dài mở rộng với GetFullPathNameW, tôi cần chỉ định đường dẫn có tiền tố \\?\ được đính kèm. Vì tiền tố \\?\ chỉ hợp lệ trước chữ cái khối lượng hoặc đường dẫn UNC, điều này có nghĩa là API không sử dụng được để giải quyết tên đầy đủ của đường dẫn tương đối so với thư mục hiện tại.

Nếu trường hợp đó xảy ra, có API nào khác mà tôi có thể sử dụng để giải quyết tên đầy đủ của một filepath như ..\somedir\somefile.txt nếu độ dài của tên kết quả vượt quá MAX_PATH không? Nếu không, tôi có thể kết hợp GetCurrentDirectory với filepath tương đối (\\?\C:\my\cwd\..\somedir\somefile.txt) và sử dụng nó với GetFullPathNameW hoặc tôi có cần xử lý tất cả các giải pháp về filepath của riêng mình không?

+0

Nó không âm thanh hợp lý rằng một chức năng để tìm đường dẫn đầy đủ, đòi hỏi bạn phải cung cấp đường dẫn đầy đủ. Vì vậy, tại sao không thử những gì các tài liệu nói. Có lẽ bạn sẽ ngạc nhiên. –

+2

GetCurrentDirectory() là một unixism về cơ bản là MAX_PATH đã bị khóa. Hệ điều hành gốc không có khái niệm về đường dẫn tương đối hoặc thư mục mặc định, bạn phải * luôn * cung cấp nó với tên đường dẫn đầy đủ. Bạn sẽ phải loại bỏ nó để đi trước. –

+0

@ Cheersandhth.-Alf Không thực sự rõ ràng nếu bạn đang đề xuất tôi thử '\\? \ C: \ my \ cwd \ .. \ somedir \ somefile.txt' hoặc' \\? \ .. \ somedir \ somefile .txt', vì vậy tôi đã thử cả hai. Đầu tiên, giải quyết chính xác thành '\\? \ C: \ my \ somedir \ somefile.txt', (trả lời một phần câu hỏi của tôi) trong khi câu lệnh thứ hai giải quyết không chính xác thành' \\? \ Somedir \ somefile.txt'. –

Trả lời

6
  1. GetFullPathNameA được giới hạn MAX_PATH nhân vật, vì nó chuyển đổi tên ANSI để một tên UNICODE trước sử dụng một hardcoded MAX_PATH -sized (trong chars) UNICODE đệm. Nếu chuyển đổi không thành công do giới hạn độ dài, thì GetFullPathNameW (hoặc trực tiếp GetFullPathName_U[Ex]) được gọi và kết quả là tên UNICODE được chuyển thành ANSI.

  2. GetFullPathNameW là lớp vỏ rất mỏng trên GetFullPathName_U. Nó được giới hạn ở độ dài MAXSHORT (0x7fff) trong WCHAR, độc lập với tiền tố \\?\ tệp. Ngay cả khi không có \\?\, nó sẽ hoạt động lâu dài (>MAX_PATH) tên liên quan. Tuy nhiên, nếu thông số lpFileName không bắt đầu bằng tiền tố \\?\, tên kết quả trong thông số lpBuffer cũng sẽ không bắt đầu bằng \\?\.

  3. nếu bạn sẽ sử dụng lpBuffer với các chức năng như CreateFileW - chức năng này chuyển nội bộ Win32Name thành NtName. và kết quả sẽ phụ thuộc vào loại nape (RTL_PATH_TYPE). nếu tên không bắt đầu bằng \\?\ tiền tố, việc chuyển đổi không thành công vì RtlDosPathNameToRelativeNtPathName_U[_WithStatus] thất bại (vì nếu con đường không bắt đầu bằng \\?\ nó sẽ được nội bộ gọi GetFullPathName_U (chức năng tương tự gọi bằng GetFullPathNameW) với nBufferLength hardcoded MAX_PATH (chính xác 2*MAX_PATH theo byte - Ntdll các hàm sử dụng kích thước bộ đệm theo byte, không phải trong WCHAR s).Nếu tên bắt đầu với \\?\ tiền tố, một trường hợp khác ở RtlDosPathNameToRelativeNtPathName_U[_WithStatus] được thực hiện - RtlpWin32NtNameToNtPathName, thay thế \\?\ với \??\ và không có MAX_PATH giới hạn

Vì vậy, các giải pháp có thể trông như thế này:

if(ULONG len = GetFullPathNameW(FileName, 0, 0, 0)) 
{ 
    PWSTR buf = (PWSTR)_alloca((4 + len) * sizeof(WCHAR)); 
    buf[0] = L'\\', buf[1] = L'\\', buf[2] = L'?', buf[3] = L'\\'; 
    if (len - 1 == GetFullPathName(FileName, len, buf + 4, &c)) 
    { 
     CreateFile(buf, ...); 
    } 
} 

Vì vậy, chúng tôi cần phải chỉ định đường dẫn có tiền tố \\?\ được đính kèm, nhưng không phải trước khi GetFullPathName - sau!

Mọi chi tiết, đọc - The Definitive Guide on Win32 to NT Path Conversion

+0

Được thăng hạng chỉ dành cho cấp chi tiết tuyệt đối, chia sẻ kiến ​​thức. Mặc dù nghĩ rằng có một chút rủi ro khi giả định rằng việc triển khai nội bộ cũng giống nhau trong tất cả các phiên bản Windows. Là nó? –

+1

Win32 để chuyển đổi đường dẫn NT sẽ luôn luôn. tuy nhiên các chi tiết mỏng của chuyển đổi này thực sự có thể được thay đổi từ phiên bản này sang phiên bản khác. một số đường dẫn win32 ở tất cả các chuyển đổi không chính xác. nói chung, nếu sử dụng đường dẫn Win32 - chúng ta có giới hạn thực tế MAX_PATH. ví dụ, chúng tôi không thể tạo quy trình từ exe, nếu chiều dài đường dẫn tuyệt đối vượt quá MAX_PATH. nếu cần sử dụng tên đường dẫn dài mà không có bất kỳ hạn chế hoặc một số đường dẫn đặc biệt - cần sử dụng đường dẫn NT (bản địa) và ntdll API – RbMm

+0

Cảm ơn, điều này cực kỳ hữu ích. Hy vọng bạn không phiền - tôi đã gửi một bản chỉnh sửa để dọn dẹp tiếng Anh một chút trong hai điểm đầu tiên. –

Các vấn đề liên quan