-
Notifications
You must be signed in to change notification settings - Fork 165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Vistaスタイルのファイルダイアログ使用時に新規ファイルの保存が行えない問題を修正 #867
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -67,9 +67,9 @@ struct CDlgOpenFile_CommonItemDialog final | |
std::vector<std::tstring>* pFileNames, | ||
LPCWSTR fileName, | ||
const std::vector<COMDLG_FILTERSPEC>& specs ); | ||
bool DoModalSaveDlgImpl0( const TCHAR* pszPath ); | ||
bool DoModalSaveDlgImpl0( TCHAR* pszPath ); | ||
HRESULT DoModalSaveDlgImpl1( IFileSaveDialog* pFileSaveDialog, | ||
const TCHAR* pszPath ); | ||
TCHAR* pszPath ); | ||
|
||
HINSTANCE m_hInstance; /* アプリケーションインスタンスのハンドル */ | ||
HWND m_hwndParent; /* オーナーウィンドウのハンドル */ | ||
|
@@ -731,7 +731,7 @@ bool CDlgOpenFile_CommonItemDialog::DoModalOpenDlg( | |
|
||
HRESULT CDlgOpenFile_CommonItemDialog::DoModalSaveDlgImpl1( | ||
IFileSaveDialog* pFileSaveDialog, | ||
const TCHAR* pszPath) | ||
TCHAR* pszPath) | ||
{ | ||
//カレントディレクトリを保存。関数から抜けるときに自動でカレントディレクトリは復元される。 | ||
CCurrentDirectoryBackupPoint cCurDirBackup; | ||
|
@@ -753,6 +753,7 @@ HRESULT CDlgOpenFile_CommonItemDialog::DoModalSaveDlgImpl1( | |
specs[2].pszName = strs[2].c_str(); | ||
specs[2].pszSpec = _T("*.*"); | ||
#define RETURN_IF_FAILED if (FAILED(hr)) { /* __debugbreak(); */ return hr; } | ||
hr = pFileSaveDialog->SetDefaultExtension(_T("txt")); RETURN_IF_FAILED | ||
hr = pFileSaveDialog->SetFileTypes(specs.size(), &specs[0]); RETURN_IF_FAILED | ||
ComPtr<IShellItem> psiFolder; | ||
SHCreateItemFromParsingName(m_szInitialDir, NULL, IID_PPV_ARGS(&psiFolder)); | ||
|
@@ -765,12 +766,22 @@ HRESULT CDlgOpenFile_CommonItemDialog::DoModalSaveDlgImpl1( | |
hr = Customize(); RETURN_IF_FAILED | ||
} | ||
hr = pFileSaveDialog->Show(m_hwndParent); RETURN_IF_FAILED | ||
|
||
if (SUCCEEDED(hr)) { | ||
ComPtr<IShellItem> pShellItem; | ||
hr = pFileSaveDialog->GetResult(&pShellItem); RETURN_IF_FAILED | ||
PWSTR pszFilePath; | ||
hr = pShellItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath); RETURN_IF_FAILED | ||
_tcscpy(pszPath, pszFilePath); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 呟き。TCHARじゃダメじゃん:cry: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ここ、よくよく考えてみると これに関してはこのPRでは扱わないで新規Issueを作る事にします。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #881 を作成しました。厳密にはリファクタではなくて |
||
CoTaskMemFree(pszFilePath); | ||
} | ||
|
||
#undef RETURN_IF_FAILED | ||
|
||
return S_OK; | ||
} | ||
|
||
bool CDlgOpenFile_CommonItemDialog::DoModalSaveDlgImpl0( const TCHAR* pszPath ) | ||
bool CDlgOpenFile_CommonItemDialog::DoModalSaveDlgImpl0( TCHAR* pszPath ) | ||
{ | ||
using namespace Microsoft::WRL; | ||
ComPtr<IFileSaveDialog> pFileDialog; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
呟きです。指摘の意図はありません。
const
指定を外すなら何文字まで書き込みできるかの情報を渡してバッファオーバランを抑止したいです。引数を増やすのは嫌なので
std::basic_string
を参照渡しにしたらいいんじゃないかと思いました。パス文字列なのでW⇒A⇒Wのように変換を繰り返すと情報が失われるリスクがあると思います。
個人的にはパラメータを
std::wstring&
型に変えるのが安全策なのかな、と思います。There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
確かにバッファオーバーランを防ぐために引数を追加した方が良いですね。
ただ根元の
CDlgOpenFile::DoModal_GetSaveFileName
に何文字まで書き込めるか(もしくはバッファ長?)のパラメータが無いので、付けるとしたらそこから付けたいです。あと今調べてみたら呼び出し元での配列宣言時の長さは_MAX_PATH
だったり_MAX_PATH + 1
でした。終端 0 を含むのか含まないのかどっちか謎です。。std::wstring&
に変えるのも手だと思いますがそれをやるとしてもやはり根元のCDlgOpenFile::DoModal_GetSaveFileName
からの変更にしたいです。あとstd::wstring
にするのはメモリの動的確保を強制する事になるので、std::wstring_view
の方が良いと思います。あと実際にやるとしても、もしバッファーオーバーランする不具合が今無いのであれば別PRでの対処にしたいです。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
あ、なので「修正して」とは言いづらいっていうですね:smile:
ファイルパス長を表す固定値MAX_PATHには終端NULが含まれます。
char szPath[MAX_PATH];
とやったときに十分なバッファサイズが確保できるようにそうなってるっぽいです。サクラエディタのコード内にある
_MAX_PATH + 1
は 単に誤り だと思います。Windows関係のエロい人が薄かった時期があったようなので、その頃にコピペとかで拡散したんじゃないかと思います。
ググってみたらこんな記事が見つかって吹きました。 ⇒ Windows 10のデフォルトのパス長制限(MAX_PATH)は256文字です
_MAX_DIR=256
という定義があるので、それと混同してるんじゃないかと思います。あ、なので「修正して」とは言いづらいっていうですね... 😢
このPRに関していうと、
PWSTR pszFilePath
を_tcscpy
でTCHAR* pszPath
にコピーしている点が気になっています。TCHAR*
のままで行くならto_tchar
関数を噛ませる必要があるように思います。(実際そんな必要はない、ってのはto_tchar
の関数定義を見れば分かる通り。サクラエディタで書き込み可能文字列の参照型を扱うとしたら、CDataProfile.h に定義されている CStringBufferW 型を流用できないかなぁ、と思っています。
std::string_view型を使うには
/std:c++17
しないといかんはずなので、現状では使えないです。というか、std::string_viewは読み取り専用コピーなので、
const TCHAR*
と変わらん(=書き込みできない)と思います。GWだし、みんなキャンプとか行ってるのかなぁ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
お、
MAX_PATH
は終端 0 を含むんですね、ちゃんと理解してなかったです。調べたところ確かにMSのサイトにもそのように書かれてました。https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file#maximum-path-length-limitation より引用
あ、本当だ。間違ってますね。256 というのがきりが良くて覚えやすい数字なので脳みそが勝手に情報を圧縮して切り詰めちゃうんでしょうね。自分も
MAX_PATH
が 260 というのは覚えていなかったです。短期的にはまずきちんとファイルダイアログが機能していない問題を直したいです。
このPRで呼び出し元から含めて体裁を整えるというかより良いコードにする修正した方が良いとレビューワーが判断したなら、実施するのはやぶさかでは無いですがレビュー範囲が増えるという事は認識シテクダサーイ(ペリーの口調
実質問題ないかなと思いますが論理的には問題あるので直しておきます。
あ、確かに。string_view であって string_ref では無いんですね。うーん、制限が掛かってるんですね。
CStringBufferW
を使えないかは確認してみます。海外旅行に行ってる人も多そうですね。