/****************************************************************************** FileInfo FileInfo モジュールソースファイル Coded by Wraith in Dec 17, 2007. ******************************************************************************/ /////////////////////////////////////////////////////////////////////////////// // // ■ fileinfo.cpp // http://tricklib.com/cxx/ex/fileinfo/fileinfo.cpp // // □ 関連ファイル // .defファイル(共通) // http://tricklib.com/cxx/ex/fileinfo/common_fileinfo.def // .defファイル(bcc専用) // http://tricklib.com/cxx/ex/fileinfo/bcc_fileinfo.def // リソースヘッダファイル // http://tricklib.com/cxx/ex/fileinfo/fileinfo.rh // リソースファイル // http://tricklib.com/cxx/ex/fileinfo/fileinfo.rc // 全ファイルパック // http://tricklib.com/cxx/ex/fileinfo/fileinfo.zip // // □ リファレンス・サポートページ // http://tricklib.com/cxx/ex/fileinfo/ // // □ ライセンス情報 // http://tricklib.com/license.htm // // □ コンパイル方法 // case Borland C++ // bcc32 -c fileinfo.cpp // brcc32 fileinfo.rc // ilink32 fileinfo.obj, fileinfo.dll, , c0d32w.obj import32.lib cw32mt.lib, bcc_fileinfo.def, fileinfo.res // case Visual C++ // rc fileinfo.rc // cl /EHsc /LD fileinfo.cpp /link /def:common_fileinfo.def /machine:IX86 fileinfo.res // case gcc(cygwin)※1 // windres fileinfo.rc fileinfo.res // dllwrap --driver-flag='-shared' -mno-cygwin -mwindows --def common_fileinfo.def -o fileinfo.dll fileinfo.cpp fileinfo.res // case gcc(migw)※1 // windres fileinfo.rc fileinfo.res // dllwrap -mwindows --def common_fileinfo.def -o fileinfo.dll fileinfo.cpp fileinfo.res // case CodeWarrior※2 // mwcc -c fileinfo.cpp // mwwinrc fileinfo.rc // mwld -shared -@export common_fileinfo.def fileinfo.obj fileinfo.res // // ※1 // 俺んとこのgccはいずれも、Windows SDK が古いバージョンのものみたいで // IExtractImage に対応してなかったんで実際にはコンパイルを通してないです。 // // ※2 // advapi32.lib が正しくリンクされる為にはライブラリのパスが正しく設定 // されている必要があります。 // #if !defined(FILEINFO_H) #define FILEINFO_H #if !defined(_UNICODE) #define _UNICODE #endif #if !defined(UNICODE) #define UNICODE #endif #if !defined(STRICT) #define STRICT #endif #if !defined(INC_OLE2) #define INC_OLE2 #endif #if !defined(_WIN32_WINNT) #define _WIN32_WINNT 0x500 #endif #include #include #include #include #pragma comment(lib, "USER32.lib") #pragma comment(lib, "ADVAPI32.lib") #pragma comment(lib, "OLEAUT32.lib") #include "fileinfo.rh" /////////////////////////////////////////////////////////////////////////////// // // Shell Extension Information // #define MODULE_DISPLAY_NAME "FileInfo Shell Extension ( fileinfo.dll )" ////////////////////////////////////////////////////////////////////////////// // // Declare auto closers // template class demi { public: T value; demi() {} demi(const T &X) :value(X) {} operator T& () { return value; } operator const T& () const { return value; } T * operator & () { return &value; } const T * operator & () const { return &value; } T & operator () () { return value; } const T & operator () () const { return value; } }; #define DECLARE_AUTO_CLOSE(name, type, param, init, close_command) \ class name :public demi \ { \ public: \ name(param) :demi(init) { } \ ~name() \ { \ close(); \ } \ void close() \ { \ if (value) \ { \ close_command; \ value = NULL; \ } \ } \ }; DECLARE_AUTO_CLOSE(AUTO_HANDLE, HANDLE, HANDLE X = NULL, X, INVALID_HANDLE_VALUE != value && (CloseHandle(value), false)) DECLARE_AUTO_CLOSE(AUTO_REGKEY, HKEY, HKEY X = NULL, X, RegCloseKey(value)) DECLARE_AUTO_CLOSE(AUTO_CRYPTPROV, HCRYPTPROV, HCRYPTPROV X = NULL, X, CryptReleaseContext(value, 0)) DECLARE_AUTO_CLOSE(AUTO_CRYPTHASH, HCRYPTHASH, HCRYPTHASH X = NULL, X, CryptDestroyHash(value)) DECLARE_AUTO_CLOSE(AUTO_MAPVIEW, LPVOID, LPVOID X = NULL, X, UnmapViewOfFile(value)) ////////////////////////////////////////////////////////////////////////////// // // Win32 Error // class win32_error :public std::runtime_error { DWORD code; public: win32_error(DWORD X_code = GetLastError()) :std::runtime_error(win32_error::make_error_message(X_code)), code(X_code) { } static const std::string make_error_message(DWORD X_code = GetLastError()); DWORD get_error_code() const { return code; } const char * get_error_message() const { return what(); } }; const std::string win32_error::make_error_message(DWORD X_code) { LPVOID lpMsgBuf; FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, X_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&lpMsgBuf, 0, NULL); const std::string result = (const char *)lpMsgBuf; LocalFree(lpMsgBuf); return result; } ////////////////////////////////////////////////////////////////////////////// // // ファイルオープン(読み込み専用、自動クローズ) // class OpenReadFile :public AUTO_HANDLE { public: OpenReadFile(const char *filename) :AUTO_HANDLE( CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ |FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL)) { } OpenReadFile(const wchar_t *filename) :AUTO_HANDLE( CreateFileW( filename, GENERIC_READ, FILE_SHARE_READ |FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL)) { } }; #if !defined(ARRAY_SIZE) #define ARRAY_SIZE(X) (sizeof(X)/sizeof(X[0])) #endif // ARRAY_SIZE #endif // FILEINFO_H #if !defined(FILEINFO_CPP) #define FILEINFO_CPP ////////////////////////////////////////////////////////////////////////////// // // 主機能 // ////////////////////////////////////////////////////////////////////////////// // // ヘッダーの読み込み // #if !defined(HEADER_SIZE) #define HEADER_SIZE 8 #endif DWORD ReadHeader(HANDLE stream, BYTE *buffer) { DWORD read_size = 0; if ( NULL == stream || INVALID_HANDLE_VALUE == stream || !ReadFile(stream, buffer, HEADER_SIZE, &read_size, NULL) ) { throw win32_error(); } return read_size; }; ////////////////////////////////////////////////////////////////////////////// // // ハッシュ値の取得 // DWORD CalcHash(ALG_ID algid, HANDLE stream, BYTE *buffer, DWORD buffer_size) { // // 準備 // AUTO_CRYPTPROV prov_handle = NULL; AUTO_CRYPTHASH hash_handle = NULL; AUTO_HANDLE file_mapping = NULL; LARGE_INTEGER file_size; file_size.QuadPart = 0L; if ( NULL == stream || INVALID_HANDLE_VALUE == stream || ( !CryptAcquireContext(&prov_handle, NULL, NULL, PROV_RSA_FULL, CRYPT_SILENT) && ( (DWORD)NTE_BAD_KEYSET != GetLastError() || !CryptAcquireContext(&prov_handle, NULL, NULL, PROV_RSA_FULL, CRYPT_SILENT | CRYPT_NEWKEYSET) ) ) || !CryptCreateHash(prov_handle, algid, 0, 0, &hash_handle) || !GetFileSizeEx(stream, &file_size) || ( 0L < file_size.QuadPart && NULL == (file_mapping.value = CreateFileMapping(stream, NULL, PAGE_READONLY, file_size.HighPart, file_size.LowPart, NULL)) ) ) { throw win32_error(); } // // pump // LARGE_INTEGER file_pos; file_pos.QuadPart = 0L; __int64 rest_size = file_size.QuadPart; SYSTEM_INFO sys_info; GetSystemInfo(&sys_info); const DWORD pump_buffer_size = sys_info.dwAllocationGranularity; while(0 < rest_size) { SIZE_T data_size = ((__int64)pump_buffer_size <= rest_size) ? pump_buffer_size: rest_size; AUTO_MAPVIEW data; if ( NULL == (LPVOID)(data.value = MapViewOfFile(file_mapping, FILE_MAP_READ, file_pos.HighPart, file_pos.LowPart, data_size)) || FALSE == CryptHashData(hash_handle, (LPBYTE)(LPVOID)data, data_size, 0) ) { throw win32_error(); } file_pos.QuadPart += data_size; rest_size -= data_size; } // // ハッシュ値の取得 // DWORD hash_size = buffer_size; if (FALSE == CryptGetHashParam(hash_handle, HP_HASHVAL, buffer, &hash_size, NULL)) { throw win32_error(); } return hash_size; } #endif // FILEINFO_CPP /////////////////////////////////////////////////////////////////////////////// // // Interface for Shell(explorer.exe) // #if !defined(EXPLORER_IF_CPP) #define EXPLORER_IF_CPP #include #pragma data_seg(".text") #define INITGUID #include #include // {055F1E01-0EB2-4772-B8B1-1A1E8C8265F2} DEFINE_GUID(CLSID_FileInfoShellExtension, 0x055F1E01L, 0x0EB2, 0x4772, 0xB8, 0xB1, 0x1A, 0x1E, 0x8C, 0x82, 0x65, 0xF2 ); // this module GUID LPCTSTR szCLSID_FileInfoShellExtension = _T("{055F1E01-0EB2-4772-B8B1-1A1E8C8265F2}"); class ReferenceCounter { private: ULONG m_cRef; public: ReferenceCounter(); virtual ~ReferenceCounter(); public: STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release(); void RefCheck(); }; class FileInfoClassFactory :public IClassFactory, ReferenceCounter { public: //IUnknown members STDMETHODIMP QueryInterface(REFIID, LPVOID *); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release(); //IClassFactory members STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, LPVOID *); STDMETHODIMP LockServer(BOOL); }; class FileInfoColumnProvider : public IColumnProvider, ReferenceCounter { public: // IUnknown methods STDMETHODIMP QueryInterface (REFIID riid, LPVOID *ppvObject); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release(); // IColumnProvider methods STDMETHODIMP Initialize (LPCSHCOLUMNINIT psci); STDMETHODIMP GetColumnInfo (DWORD dwIndex, LPSHCOLUMNINFO psci); STDMETHODIMP GetItemData (LPCSHCOLUMNID pscid, LPCSHCOLUMNDATA pscd, VARIANT *pvartData); }; #pragma data_seg() // // Global variables // UINT g_cRefThisDll = 0; // Reference count of this DLL. HINSTANCE g_hmodThisDll = NULL; // Handle to this DLL itself. extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { hInstance, dwReason, lpReserved; if (dwReason == DLL_PROCESS_ATTACH) { g_hmodThisDll = hInstance; } return 1; } STDAPI DllCanUnloadNow() { if (g_cRefThisDll) { return S_FALSE; } else { return S_OK; } } STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppvOut) { *ppvOut = NULL; try { if (IsEqualIID(rclsid, CLSID_FileInfoShellExtension)) { return (new FileInfoClassFactory)->QueryInterface(riid, ppvOut); } } catch(...) { } OutputDebugStringA("DllGetClassObject@" MODULE_DISPLAY_NAME " is faild."); return CLASS_E_CLASSNOTAVAILABLE; } // *********************** ReferenceCounter ************************* ReferenceCounter::ReferenceCounter() :m_cRef(0) { ++g_cRefThisDll; } ReferenceCounter::~ReferenceCounter() { --g_cRefThisDll; } STDMETHODIMP_(ULONG) ReferenceCounter::AddRef() { return ++m_cRef; } STDMETHODIMP_(ULONG) ReferenceCounter::Release() { if (--m_cRef) { return m_cRef; } delete this; return 0L; } void ReferenceCounter::RefCheck() { if (!m_cRef) { delete this; } } // *********************** FileInfoClassFactory ************************* STDMETHODIMP FileInfoClassFactory::QueryInterface(REFIID riid, LPVOID *ppv) { *ppv = NULL; if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory)) { *ppv = (LPCLASSFACTORY)this; } else { RefCheck(); return E_NOINTERFACE; } AddRef(); return S_OK; } STDMETHODIMP_(ULONG) FileInfoClassFactory::AddRef() { return ReferenceCounter::AddRef(); } STDMETHODIMP_(ULONG) FileInfoClassFactory::Release() { return ReferenceCounter::Release(); } STDMETHODIMP FileInfoClassFactory::CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppv) { *ppv = NULL; if (pUnkOuter) { return CLASS_E_NOAGGREGATION; } try { return (new FileInfoColumnProvider())->QueryInterface(riid, ppv); } catch(...) { } OutputDebugStringA("CreateInstance@" MODULE_DISPLAY_NAME " is faild."); return E_OUTOFMEMORY; } STDMETHODIMP FileInfoClassFactory::LockServer(BOOL fLock) { fLock; return S_OK; } // *********************** FileInfo ************************* STDMETHODIMP FileInfoColumnProvider::QueryInterface(REFIID riid, LPVOID *ppv) { *ppv = NULL; if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IColumnProvider)) { *ppv = (IColumnProvider*)this; } else { RefCheck(); return E_NOINTERFACE; } AddRef(); return S_OK; } STDMETHODIMP_(ULONG) FileInfoColumnProvider::AddRef() { return ReferenceCounter::AddRef(); } STDMETHODIMP_(ULONG) FileInfoColumnProvider::Release() { return ReferenceCounter::Release(); } // *********************** IColumnProvider Implementation ****************** #define STR_FMTID_Header _T("{17F098ED-FD3F-49A7-A2C3-5FEEC38A915B}") GUID FMTID_Header = {0x17F098ED, 0xFD3F, 0x49A7, {0xA2, 0xC3, 0x5F, 0xEE, 0xC3, 0x8A, 0x91, 0x5B}}; #define STR_FMTID_MD5 _T("{5E669299-7E08-44EB-AD88-FA22FDD27348}") GUID FMTID_MD5 = {0x5E669299, 0x7E08, 0x44EB, {0xAD, 0x88, 0xFA, 0x22, 0xFD, 0xD2, 0x73, 0x48}}; #define STR_FMTID_SHA1 _T("{FAE7730A-1ECE-49B7-B1A4-165B460DC12B}") GUID FMTID_SHA1 = {0xFAE7730A, 0x1ECE, 0x49B7, {0xB1, 0xA4, 0x16, 0x5B, 0x46, 0x0D, 0xC1, 0x2B}}; STDMETHODIMP FileInfoColumnProvider::Initialize(LPCSHCOLUMNINIT psci) { psci; // 初期化処理 return S_OK; } // // カラム(ヘッダ)の登録 // STDMETHODIMP FileInfoColumnProvider::GetColumnInfo(DWORD dwIndex, LPSHCOLUMNINFO psci) { switch(dwIndex) { case 0: psci->scid.fmtid = FMTID_Header; psci->scid.pid = 0; psci->vt = VT_BSTR; psci->fmt = LVCFMT_LEFT; psci->cChars = 20; psci->csFlags = SHCOLSTATE_TYPE_STR |SHCOLSTATE_SECONDARYUI; #if !defined(STR_COLUMNTITLE_HEADER) lstrcpy(psci->wszTitle, _T("先頭8バイト")); #else LoadString(g_hmodThisDll, STR_COLUMNTITLE_HEADER, psci->wszTitle, sizeof(psci->wszTitle)); #endif #if !defined(STR_COLUMNDESCRIPTION_HEADER) lstrcpy(psci->wszDescription, _T("Displays the file header.")); #else LoadString(g_hmodThisDll, STR_COLUMNDESCRIPTION_HEADER, psci->wszDescription, sizeof(psci->wszDescription)); #endif break; case 1: psci->scid.fmtid = FMTID_MD5; psci->scid.pid = 0; psci->vt = VT_BSTR; psci->fmt = LVCFMT_LEFT; psci->cChars = 48; psci->csFlags = SHCOLSTATE_TYPE_STR |SHCOLSTATE_SLOW |SHCOLSTATE_SECONDARYUI; #if !defined(STR_COLUMNTITLE_MD5) lstrcpy(psci->wszTitle, _T("MD5")); #else LoadString(g_hmodThisDll, STR_COLUMNTITLE_MD5, psci->wszTitle, sizeof(psci->wszTitle)); #endif #if !defined(STR_COLUMNDESCRIPTION_MD5) lstrcpy(psci->wszDescription, _T("Displays the file MD5 hash.")); #else LoadString(g_hmodThisDll, STR_COLUMNDESCRIPTION_MD5, psci->wszDescription, sizeof(psci->wszDescription)); #endif break; case 2: psci->scid.fmtid = FMTID_SHA1; psci->scid.pid = 0; psci->vt = VT_BSTR; psci->fmt = LVCFMT_LEFT; psci->cChars = 60; psci->csFlags = SHCOLSTATE_TYPE_STR |SHCOLSTATE_SLOW |SHCOLSTATE_SECONDARYUI; #if !defined(STR_COLUMNTITLE_SHA1) lstrcpy(psci->wszTitle, _T("SHA1")); #else LoadString(g_hmodThisDll, STR_COLUMNTITLE_SHA1, psci->wszTitle, sizeof(psci->wszTitle)); #endif #if !defined(STR_COLUMNDESCRIPTION_SHA1) lstrcpy(psci->wszDescription, _T("Displays the file SHA1 hash.")); #else LoadString(g_hmodThisDll, STR_COLUMNDESCRIPTION_SHA1, psci->wszDescription, sizeof(psci->wszDescription)); #endif break; default: return S_FALSE; } return S_OK; } // // エスケープテーブル // LPCWSTR escape_table[] = { L"\\x00", L"\\x01", L"\\x02", L"\\x03", L"\\x04", L"\\x05", L"\\x06", L"\\x07", L"\\x08", L"\\x09", L"\\x0A", L"\\x0B", L"\\x0C", L"\\x0D", L"\\x0E", L"\\x0F", L"\\x10", L"\\x11", L"\\x12", L"\\x13", L"\\x14", L"\\x15", L"\\x16", L"\\x17", L"\\x18", L"\\x19", L"\\x1A", L"\\x1B", L"\\x1C", L"\\x1D", L"\\x1E", L"\\x1F", L" ", L"!", L"\"", L"#", L"$", L"%", L"&", L"'", L"(", L")", L"*", L"+", L",", L"-", L".", L"/", L"0", L"1", L"2", L"3", L"4", L"5", L"6", L"7", L"8", L"9", L":", L";", L"<", L"=", L">", L"?", L"@", L"A", L"B", L"C", L"D", L"E", L"F", L"G", L"H", L"I", L"J", L"K", L"L", L"M", L"N", L"O", L"P", L"Q", L"R", L"S", L"T", L"U", L"V", L"W", L"X", L"Y", L"Z", L"[", L"\\x5C", L"]", L"^", L"_", L"`", L"a", L"b", L"c", L"d", L"e", L"f", L"g", L"h", L"i", L"j", L"k", L"l", L"m", L"n", L"o", L"p", L"q", L"r", L"s", L"t", L"u", L"v", L"w", L"x", L"y", L"z", L"{", L"|", L"}", L"~", L"\\x7F", L"\\x80", L"\\x81", L"\\x82", L"\\x83", L"\\x84", L"\\x85", L"\\x86", L"\\x87", L"\\x88", L"\\x89", L"\\x8A", L"\\x8B", L"\\x8C", L"\\x8D", L"\\x8E", L"\\x8F", L"\\x90", L"\\x91", L"\\x92", L"\\x93", L"\\x94", L"\\x95", L"\\x96", L"\\x97", L"\\x98", L"\\x99", L"\\x9A", L"\\x9B", L"\\x9C", L"\\x9D", L"\\x9E", L"\\x9F", L"\\xA0", L"\\xA1", L"\\xA2", L"\\xA3", L"\\xA4", L"\\xA5", L"\\xA6", L"\\xA7", L"\\xA8", L"\\xA9", L"\\xAA", L"\\xAB", L"\\xAC", L"\\xAD", L"\\xAE", L"\\xAF", L"\\xB0", L"\\xB1", L"\\xB2", L"\\xB3", L"\\xB4", L"\\xB5", L"\\xB6", L"\\xB7", L"\\xB8", L"\\xB9", L"\\xBA", L"\\xBB", L"\\xBC", L"\\xBD", L"\\xBE", L"\\xBF", L"\\xC0", L"\\xC1", L"\\xC2", L"\\xC3", L"\\xC4", L"\\xC5", L"\\xC6", L"\\xC7", L"\\xC8", L"\\xC9", L"\\xCA", L"\\xCB", L"\\xCC", L"\\xCD", L"\\xCE", L"\\xCF", L"\\xD0", L"\\xD1", L"\\xD2", L"\\xD3", L"\\xD4", L"\\xD5", L"\\xD6", L"\\xD7", L"\\xD8", L"\\xD9", L"\\xDA", L"\\xDB", L"\\xDC", L"\\xDD", L"\\xDE", L"\\xDF", L"\\xE0", L"\\xE1", L"\\xE2", L"\\xE3", L"\\xE4", L"\\xE5", L"\\xE6", L"\\xE7", L"\\xE8", L"\\xE9", L"\\xEA", L"\\xEB", L"\\xEC", L"\\xED", L"\\xEE", L"\\xEF", L"\\xF0", L"\\xF1", L"\\xF2", L"\\xF3", L"\\xF4", L"\\xF5", L"\\xF6", L"\\xF7", L"\\xF8", L"\\xF9", L"\\xFA", L"\\xFB", L"\\xFC", L"\\xFD", L"\\xFE", L"\\xFF", }; // // ファイル毎のカラムデータ取得 // STDMETHODIMP FileInfoColumnProvider::GetItemData(LPCSHCOLUMNID pscid, LPCSHCOLUMNDATA pscd, VARIANT *pvartData) { HRESULT hresult = S_OK; if (0 == pscid->pid) { if (IsEqualGUID(pscid->fmtid, FMTID_Header)) { LPCWSTR file_header_text = L"\\error"; WCHAR file_header_buffer[128]; try { if (pscd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { file_header_text = L"\\directory"; } else { BYTE header[HEADER_SIZE]; int read_size = ReadHeader(OpenReadFile(pscd->wszFile), header); if (read_size) { LPWSTR current = file_header_buffer; for (int i = 0; i < read_size; ++i) { current += wsprintf(current, L"%s", escape_table[header[i]]); } file_header_text = file_header_buffer; } else { file_header_text = L"\\zerobyte"; } } } catch(...) { file_header_text = L"\\unknown"; } VARIANT varTemp; varTemp.vt = VT_BSTR; varTemp.bstrVal = SysAllocString(file_header_text); if (varTemp.bstrVal) { *pvartData = varTemp; } else { hresult = E_OUTOFMEMORY; } } else { ALG_ID algid = 0; if (IsEqualGUID(pscid->fmtid, FMTID_MD5)) { algid = CALG_MD5; } else if (IsEqualGUID(pscid->fmtid, FMTID_SHA1)) { algid = CALG_SHA1; } if (0 != algid) { LPCWSTR file_hash_text = L"\\error"; WCHAR file_hash_buffer[128]; try { if (pscd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { file_hash_text = L"\\directory"; } else { BYTE hash[32]; int hash_size = CalcHash(algid, OpenReadFile(pscd->wszFile), hash, sizeof(hash)); if (hash_size) { LPWSTR current = file_hash_buffer; for (int i = 0; i < hash_size; ++i) { current += wsprintf(current, L"%02.2X", hash[i]); } file_hash_text = file_hash_buffer; } } } catch(...) { file_hash_text = L"\\unknown"; } VARIANT varTemp; varTemp.vt = VT_BSTR; varTemp.bstrVal = SysAllocString(file_hash_text); if (varTemp.bstrVal) { *pvartData = varTemp; } else { hresult = E_OUTOFMEMORY; } } else { hresult = S_FALSE; } } } else { hresult = S_FALSE; } return hresult; } #endif // EXPLORER_IF_CPP /////////////////////////////////////////////////////////////////////////////// // // Interface for regsvr32.exe // #if !defined(REGSVR32_IF_CPP) #define REGSVR32_IF_CPP #include // // レジストリキーの削除 // void delete_reg_key(HKEY hKey, LPCTSTR pszSubKey) { do { AUTO_REGKEY hEnumKey; if (ERROR_SUCCESS == RegOpenKeyEx(hKey, pszSubKey, 0, KEY_ALL_ACCESS, &hEnumKey)) { TCHAR szKey[MAX_PATH]; DWORD dwSize = MAX_PATH; while(ERROR_SUCCESS == RegEnumKeyEx(hEnumKey, 0, szKey, &dwSize, NULL, NULL, NULL, NULL)) { delete_reg_key(hEnumKey, szKey); dwSize = MAX_PATH; } } } while(false); RegDeleteKey(hKey, pszSubKey); } // // DLLの登録 // extern "C" HRESULT __declspec(dllexport) DllRegisterServer() { // ... SECURITY_ATTRIBUTES SA; SA.nLength = sizeof(SECURITY_ATTRIBUTES); SA.bInheritHandle = TRUE; TCHAR *pwszSD = _T("D:(A;OICI;GA;;;SY)(A;OICI;GA;;;BA)(A;OICI;GA;;;CO)(A;OICI;GRGWGX;;;IU)"); if ( !ConvertStringSecurityDescriptorToSecurityDescriptor ( pwszSD, SDDL_REVISION_1, &(SA.lpSecurityDescriptor), NULL ) ) { return E_FAIL; } // this module GUID LPCTSTR szCLSID = szCLSID_FileInfoShellExtension; // this module name LPCTSTR szModuleName = _T("File Header and Hash Info"); // DLL パスの取得 TCHAR szModulePath[MAX_PATH]; GetModuleFileName(g_hmodThisDll, szModulePath, ARRAY_SIZE(szModulePath)); struct REGSTRUCT { HKEY hRootKey; LPCTSTR lpszSubKey; LPCTSTR lpszValueName; LPCTSTR lpszData; }; REGSTRUCT RegEntries[] = { HKEY_CLASSES_ROOT, _T("CLSID\\%s"), NULL, szModuleName, HKEY_CLASSES_ROOT, _T("CLSID\\%s\\InProcServer32"), NULL, _T("\"%s\""), HKEY_CLASSES_ROOT, _T("CLSID\\%s\\InProcServer32"), _T("ThreadingModel"), _T("Apartment"), HKEY_CLASSES_ROOT, _T("Folder\\shellex\\ColumnHandlers\\%s"), NULL, szModuleName, }; for(int i = 0; i < (int)ARRAY_SIZE(RegEntries); ++i) { AUTO_REGKEY RegKey; DWORD dwDisp; HRESULT lResult; TCHAR szSubKey[1024]; wsprintf(szSubKey, RegEntries[i].lpszSubKey, szCLSID); if (ERROR_SUCCESS == RegOpenKeyEx(RegEntries[i].hRootKey, szSubKey, 0, KEY_SET_VALUE, &RegKey) || ERROR_SUCCESS == RegCreateKeyEx(RegEntries[i].hRootKey, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, &SA, &RegKey, &dwDisp)) { TCHAR szData[1024]; wsprintf(szData, RegEntries[i].lpszData, szModulePath); RegSetValueEx(RegKey, RegEntries[i].lpszValueName, 0, REG_SZ, (LPBYTE)szData, (lstrlen(szData) + 1) * sizeof(TCHAR)); } else { return E_FAIL; } } return S_OK; } // // DLLの登録解除 // extern "C" HRESULT __declspec(dllexport) DllUnregisterServer() { LPCTSTR fileinfo_application_subkey_path = _T("SOFTWARE\\TrickLibrary\\fileinfo"); { AUTO_REGKEY hFileInfoKey; if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, fileinfo_application_subkey_path, 0, KEY_ALL_ACCESS, &hFileInfoKey)) { TCHAR buffer[256]; DWORD reg_type = REG_SZ; DWORD buffer_size = sizeof(buffer); if (ERROR_SUCCESS == RegQueryValueEx(hFileInfoKey, _T("selfdelete"), NULL, ®_type, (LPBYTE)buffer, &buffer_size) && 0 == lstrcmp(_T("true"), buffer)) { // DLL パスの取得 TCHAR szModulePath[MAX_PATH]; GetModuleFileName(g_hmodThisDll, szModulePath, MAX_PATH); // DLL の削除 MoveFileEx(szModulePath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); } } } delete_reg_key(HKEY_LOCAL_MACHINE, fileinfo_application_subkey_path); // this module GUID LPCTSTR szCLSID = szCLSID_FileInfoShellExtension; LPCTSTR reg_subkey_list[] = { _T("CLSID\\%s"), _T("Folder\\shellex\\ColumnHandlers\\%s"), }; for(int i = 0; i < (int)ARRAY_SIZE(reg_subkey_list); ++i) { TCHAR szSubKey[1024]; wsprintf(szSubKey, reg_subkey_list[i], szCLSID); delete_reg_key(HKEY_CLASSES_ROOT, szSubKey); } return S_OK; } #endif // REGSVR32_IF_CPP /****************************************************************************** □■□■ Wraith the Trickster □■□■ ■□■□ 〜I'll go with heaven's advantage and fool's wisdom.〜 ■□■□ ******************************************************************************/