// ShlExt.cpp : Implementation of CVSSShellExt #include "stdafx.h" #include "Vssui.h" #include "ShlExt.h" #include "vssprop.h" #include ///////////////////////////////////////////////////////////////////////////// // CVSSShellExt CVSSShellExt::CVSSShellExt() { #ifdef DEBUG OutputDebugString(_T("CVSSShellExt::CVSSShellExt\n")); #endif m_lpszFile = NULL; } CVSSShellExt::~CVSSShellExt() { #ifdef DEBUG OutputDebugString(_T("CVSSShellExt::~CVSSShellExt\n")); #endif if (m_lpszFile) { delete [] m_lpszFile; m_lpszFile = NULL; } } STDMETHODIMP CVSSShellExt::Initialize( IN LPCITEMIDLIST pidlFolder, // For property sheet extensions, this parameter is NULL IN LPDATAOBJECT lpdobj, IN HKEY hkeyProgID // not used in property sheet extensions ) { HRESULT hr = S_OK; if ((IDataObject *)m_spiDataObject) m_spiDataObject.Release(); if (lpdobj) { m_spiDataObject = lpdobj; STGMEDIUM medium; FORMATETC fe = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; UINT uCount = 0; hr = m_spiDataObject->GetData(&fe, &medium); if (FAILED(hr)) { fe.cfFormat = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_MOUNTEDVOLUME); hr = m_spiDataObject->GetData(&fe, &medium); } if (SUCCEEDED(hr)) { if (m_lpszFile) { delete [] m_lpszFile; m_lpszFile = NULL; } uCount = DragQueryFile((HDROP)medium.hGlobal, (UINT)-1, NULL, 0); if (uCount > 0) { UINT uiChars = DragQueryFile ((HDROP) medium.hGlobal, 0, NULL, 0); m_lpszFile = new TCHAR [uiChars + 1]; if (!m_lpszFile) { hr = E_OUTOFMEMORY; } else { ZeroMemory(m_lpszFile, sizeof(TCHAR) * (uiChars + 1)); DragQueryFile ((HDROP) medium.hGlobal, 0, m_lpszFile, uiChars + 1); } } else { hr = E_FAIL; } ReleaseStgMedium(&medium); } } return hr; } LPFNPSPCALLBACK _OldPropertyPageCallback; UINT CALLBACK _NewPropertyPageCallback(HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp) { ASSERT(_OldPropertyPageCallback); AFX_MANAGE_STATE(AfxGetStaticModuleState()); // // First, let the old callback function handles the msg. // UINT i = _OldPropertyPageCallback(hwnd, uMsg, ppsp); // // Then, we release our page here // if (uMsg == PSPCB_RELEASE) { ASSERT(ppsp); CVSSProp* pPage = (CVSSProp*)(ppsp->lParam); ASSERT(pPage); delete pPage; } return i; } void ReplacePropertyPageCallback(void* vpsp) { ASSERT(vpsp); LPPROPSHEETPAGE ppsp = (LPPROPSHEETPAGE)vpsp; _OldPropertyPageCallback = ppsp->pfnCallback; // save the old callback function ppsp->pfnCallback = _NewPropertyPageCallback; // replace with our own callback } // // From RaymondC: // If you didn't add a page, you still return S_OK -- you successfully added zero pages. // If you add some pages and then you want one of those added pages to be the default, // you return ResultFromShort(pagenumber+1). S_FALSE = ResultFromShort(1). // STDMETHODIMP CVSSShellExt::AddPages( IN LPFNADDPROPSHEETPAGE lpfnAddPage, IN LPARAM lParam ) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); // // we only add our page if local machine is postW2K server // if (!IsPostW2KServer(NULL)) return S_OK; // // we only add our page for local fixed non-FAT drive // if (DRIVE_FIXED != GetDriveType(m_lpszFile)) return S_OK; TCHAR szFileSystemName[MAX_PATH] = _T(""); DWORD dwMaxCompLength = 0, dwFileSystemFlags = 0; GetVolumeInformation(m_lpszFile, NULL, 0, NULL, &dwMaxCompLength, &dwFileSystemFlags, szFileSystemName, MAX_PATH); if (CSTR_EQUAL != CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, _T("NTFS"), -1, szFileSystemName, -1)) return S_OK; CVSSProp *pPage = new CVSSProp(_T(""), m_lpszFile); if (!pPage) return E_OUTOFMEMORY; if (pPage->m_psp.dwFlags & PSP_USECALLBACK) { // // Replace with our own callback function such that we can delete pPage // when the property sheet is closed. // // Note: don't change m_psp.lParam, which has to point to CVSSProp object; // otherwise, MFC won't hook up message handler correctly. // ReplacePropertyPageCallback(&(pPage->m_psp)); // // Fusion MFC-based property page // PROPSHEETPAGE_V3 sp_v3 = {0}; CopyMemory (&sp_v3, &(pPage->m_psp), (pPage->m_psp).dwSize); sp_v3.dwSize = sizeof(sp_v3); HPROPSHEETPAGE hPage = CreatePropertySheetPage(&sp_v3); if (hPage) { if (lpfnAddPage(hPage, lParam)) { // Store this pointer in pPage in order to keep our dll loaded, // it will be released when pPage gets deleted. pPage->StoreShellExtPointer((IShellPropSheetExt *)this); return S_OK; } DestroyPropertySheetPage(hPage); hPage = NULL; } } delete pPage; return S_OK; } // // The shell doesn't call ReplacePage // STDMETHODIMP CVSSShellExt::ReplacePage( IN UINT uPageID, IN LPFNADDPROPSHEETPAGE lpfnReplaceWith, IN LPARAM lParam ) { return E_NOTIMPL; }