2010-08-09 121 views
6

我正在使用Delphi 2010,我的程序想要獲得系統的臨時路徑。我正在使用TPath.GetTempPath,一切工作正常......至少對我和我的同事來說。但在某些客戶機器上,此方法返回(當然)不存在的裁剪路徑。我發現問題似乎是對GetLongPathName()的底層調用的結果。Delphi TPath.GetTempPath結果被裁剪

完整的代碼如下所示:

[...] 
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; 
[...] 

這只是發生在某些系統上,我不知道爲什麼。我發現了一個令人討厭的解決方法,但我想知道這裏發生了什麼。

有人可以對此有所瞭解嗎?

+0

您能否介紹一下正確的(預期的)和錯誤的(實際的)路徑名的例子嗎?可能是Unicode或編碼問題? – 2010-08-10 06:26:59

+0

我們認爲這也是第一位的,但路徑名不包含任何可能導致Unicode轉換問題的字符。 GetLongPathName的結果路徑名僅缺失最後4個字符(「Temp \」的「emp \」) - 所有其他字符都是有效的。 – Patrick 2010-08-10 08:07:28

+0

聽起來像http://qc.embarcadero.com/wc/qcmain.aspx?d=92006 – 2016-08-29 15:57:21

回答

4

有一個關於國土安全的頁面此Windows API函數注:

「爲 GetLongPathName()和類似 函數的返回緩衝區可能返回截斷 路徑,導致難以 - 查找錯誤。「

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

如果你的源代碼,你可以,如果這篇文章中所述的問題在Delphi 2010的實現存在檢查。

+0

你是對的,我也發現,我的「討厭的解決方法」是最初將Len設置爲MAX_PATH並檢查GetLongPathName的結果(),但我想知道爲什麼Embarcadero使用另一種方法...但感謝你張貼這個,因爲它驗證了我的方法。 – Patrick 2010-08-09 15:01:47

+0

您應該向QC報告。 – 2010-08-09 15:38:44

+1

那麼問題是什麼?問題中的代碼正確地調用了兩次函數,不是嗎?一旦找到所需的長度,然後第二次填充真實的緩衝區。您引用的代碼首先分配緩衝區,以便第一次調用該函數可能會起作用,但如果失敗,它將分配一個新的緩衝區並使用它。這真的是一個重要的區別嗎?文章警告,假設第一次調用在給定MAX_PATH大小的緩衝區時總會成功。這種警告如何適用於這種情況? – 2010-08-09 15:42:00

3

,如果你嘗試,會發生什麼:

var 
    longpath : string; 

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

這個工作對我來說,你的版本截短的路徑。

+0

這就是我在我的「解決方法」中所做的事情 - 如果問題在您的計算機上發生:如果TPath.GetTempPath()函數適合您,它會很有趣? – Patrick 2010-08-09 15:10:07

+1

此代碼可能會給您提供比Max_Path更長的字符串,但只分配Max_Path字符。也就是'Length(longpath)> StrLen(PChar(longpath))''。您可能還會留下一個帶有垃圾的字符串 - 當緩衝區太小時,文檔沒有說明函數存儲在緩衝區中的內容。安全公告和文檔都描述了避免該問題的方法。 – 2010-08-09 23:27:32

+0

好的,我們應該在這裏提到,GetLongPathName的返回值很重要,應該檢查。 – Patrick 2010-08-10 07:58:32