Seasons.NET

ちょっとした技術ブログです

IExtractImage2のGetDateStampで嵌る

Windowsエクスプローラーの縮小表示を独自のファイル形式でも表示するCOMを作っていて、
WindowsXPで動作確認ができたからよっしゃ公開や。と思って、意気揚々とWindows2000でも
テストしたらことごとく動作がおかしく悩みまくりました。


最初サムネイルが全て同じになるので、排他処理を行わないといけない?
と思いつつ、デバッグすると、ちゃんとファイル単位でCOMのインスタンスは作成されているので
そういうことではなかった。サムネイルを作成する時にキャッシュ更新の処理を担う、
IExtractImage2を継承していないのが原因
(厳密には、以下が原因)で、助けて下さった、id:shiba-yanさんにも報告。


んでこれでいいかな?と思ってたら、同じ作成日のファイルは、
同じサムネイルになることが発覚。でも、Windows側でデフォルトで対応している、

bmp,pngとかは、ちゃんと表示される。。。

んで、id:wraith13さんより指摘を受けまして。
GetLocationの第1引数返してないのではと。。。
よーく見てみる。

pszPathBuffer
[out] The buffer used to return the path description.
This value identifies the image so you can avoid loading the same one more than once.

あ!!同じ読み込みを避けるために、画像IDを返してね。実際には、MAXPATHのサイズが
渡されるので、そこにユニコードでパスを書き込めばいい。

というわけでCOMにwstringを持たせて、GetLocationにパスをコピーして、GetDateStampを元に戻して、実行!!

無事うまくいったのでした。

	STDMETHOD(GetDateStamp)(FILETIME *pDateStamp)
	{
		FILETIME ftCreationTime,ftLastAccessTime,ftLastWriteTime;
		// open the file and get last write time
		HANDLE hFile = CreateFile( (LPSTR)filepath_.string().data(),GENERIC_READ,FILE_SHARE_READ,NULL,
								   OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
		if ( !hFile ) return E_FAIL;
		GetFileTime(hFile,&ftCreationTime,&ftLastAccessTime,&ftLastWriteTime);
		CloseHandle(hFile);
		*pDateStamp = ftLastWriteTime;
		return NOERROR; 
	}

// 一応,GetLocationの実装も乗せておきます。
HRESULT CThumbnailExtract::GetLocation(LPWSTR pszPathBuffer,
									   DWORD cchMax, DWORD *pdwPriority,
									   const SIZE *prgSize, DWORD dwRecClrDepth,
									   DWORD *pdwFlags)
{
	// ************************************************** //
	// 作成しているプログラムの都合で、必要なコードをここに書いてます。
	// (ここでは割愛)
	// ************************************************** //

	// cchMax = 260(MAX_PATH)
	// filenameは、wstringで、メンバ変数に持たせている。Load関数でパスをコピーしておく。
	wcscpy( pszPathBuffer , filename.data() ); 

	if ( *pdwFlags & IEIFLAG_ASYNC )
	{
		// WindowsXPとそれ以前は、ここに来る。
		return E_PENDING;
	}
	else
	{
		// Windows Vista
		return S_OK;
	}
}