2010-08-09 14 views
6

Używam Delphi 2010 i mój program chce uzyskać ścieżkę temp systemu. Używam TPath.GetTempPath i wszystko działa dobrze ... przynajmniej dla mnie i moich współpracowników. Ale na niektórych maszynach klienta ta metoda zwraca przyciętą ścieżkę, która (oczywiście) nie istnieje. Odkryłem, że problem wydaje się być wynikiem wywołania funkcji GetLongPathName().Delphi TPath.GetTempPath wynik jest przycięty

Kompletny kod wygląda następująco:

[...] 
var 
TmpDir : String; 
Len : Integer; 
begin 

[... Call to GetTempPath succeeds and we have a valid temp directory in short "~" notation in var TmpDir ...] 

Len := GetLongPathName(PChar(TmpDir), nil, 0);  // Len = 37 
    SetLength(TmpDir, Len - 1);       // We want to set the len of TmpDir to 37 - 1. 
    GetLongPathName(PChar(TmpDir), PChar(TmpDir), Len); // Only 32 (instead of 36) characters are copied - so we have a cropped path - But why?! 

end; 
[...] 

Dzieje się tak tylko w niektórych systemach i nie wiem dlaczego. Znalazłem na to paskudne obejście, ale chciałbym się dowiedzieć, co się tutaj dzieje.

Czy ktoś może rzucić trochę światła na to?

+0

Czy możesz podać przykłady prawidłowych (oczekiwanych) i złych (rzeczywistych) nazw ścieżek? Może to być kodowanie Unicode lub kodowanie? –

+0

Myśleliśmy, że również na pierwszym miejscu, ale nazwy ścieżek nie zawierają żadnych znaków, które mogłyby powodować problemy z konwersjami Unicode. W nazwie ścieżki wyniku GetLongPathName brakuje tylko 4 ostatnich znaków ("emp \" w "Temp \") - wszystkie pozostałe znaki są poprawne. – Patrick

+0

Brzmi jak http://qc.embarcadero.com/wc/qcmain.aspx?d=92006 –

Odpowiedz

4

Jest tam wzmianka o tej funkcji API systemu Windows na stronach Ojczyzna Bezpieczeństwo:

„Bufor powrót do GetLongPathName() i podobnych funkcji może zwrócić obciętą drogę i prowadzić do trudnych do - znajdź błędy. "

https://buildsecurityin.us-cert.gov/bsi-rules/home/g1/753-BSI.html

Jeśli masz kodu źródłowego, można sprawdzić, czy problem opisany w tym artykule występuje w realizacji Delphi 2010.

+0

Masz rację, również to znalazłem i moim "przykrym obejściem" jest ustawienie Len na MAX_PATH na początku i sprawdzenie wyniku GetLongPathName(), ale zastanawiam się, dlaczego Embarcadero używa innego podejścia ... ale dziękuję za opublikowanie tego, ponieważ to zweryfikowało moje podejście. – Patrick

+0

Powinieneś zgłosić ten fakt do QC. –

+1

Więc w czym problem? Kod w pytaniu poprawnie wywołuje funkcję dwukrotnie, prawda? Raz, aby dowiedzieć się wymaganej długości, a następnie po raz drugi, aby wypełnić rzeczywisty bufor. Najpierw przydziela się bufor, aby pierwsze wywołanie funkcji mogło działać, ale jeśli się nie powiedzie, alokuje nowy bufor i używa go zamiast tego. Czy to naprawdę ważna różnica? Ten artykuł ostrzega przed założeniem, że pierwsze wywołanie zawsze zakończy się sukcesem, gdy otrzymamy bufor wielkości MAX_PATH. Jak to ostrzeżenie dotyczy tej sytuacji? –

3

Co się stanie, jeśli spróbujesz:

var 
    longpath : string; 

SetLength(longpath,MAX_PATH); 
SetLength(longpath, GetLongPathName(PChar(TmpDir),PChar(LongPath),MAX_PATH)); 

ten pracował dla mnie, wersja skrócona ścieżkę.

+0

To właśnie robię w moim "obejściu" - jeśli problem występuje na komputerze: byłoby interesujące, gdyby funkcja TPath.GetTempPath() działała dla ciebie? – Patrick

+1

Ten kod może pozostawić ci ciąg dłuższy niż Max_Path, ale z przypisanymi tylko znakami Max_Path. Oznacza to, że "Długość (longpath)> StrLen (PChar (longpath))". Możesz również pozostać z łańcuchem zawierającym śmieci - doktorzy nie mówią, co funkcja przechowuje w buforze, gdy bufor jest zbyt mały. W biuletynie zabezpieczeń i dokumentacji opisano sposób uniknięcia tego problemu. –

+0

OK, powinniśmy tutaj wspomnieć, że wartość zwracana GetLongPathName jest ważna i powinna być sprawdzona. – Patrick

Powiązane problemy