Folder.cpp
上传用户:hy_wanghao
上传日期:2007-01-08
资源大小:279k
文件大小:21k
- // Folder.cpp : Implementation of CFolder
- #include "stdafx.h"
- #include "Folder.h"
- #include "View.h"
- #include "Misc.h"
- #include "ExtractIcon.h"
- #include "DropTarget.h"
- #include "DataObject.h"
- #include "ContextMenu.h"
- /////////////////////////////////////////////////////////////////////////////
- // CComCoClass<CFolder> - COM registration
- BOOL CFolder::_FindAmigaDrive(LPTSTR pstrDevice)
- {
- const int MAX_PHYSICAL_DRIVES = 6;
- ATLASSERT(pstrDevice);
- // Scan harddrives for an Amiga disk
- // (excludes drive0 because it's likely it's the C: disk)
- for( int i=1; i<MAX_PHYSICAL_DRIVES; i++ ) {
- ::wsprintf(pstrDevice, _T("|H%d"), i);
- #ifdef _DEBUG
- // DEBUG: We fake an Amiga harddisk in DEBUG mode
- if( i==3 ) {
- _tcscpy( pstrDevice, _T("C:\Temp\drive.adf") );
- return TRUE;
- }
- #endif
- CAdfDevice dev;
- if( dev.Open(pstrDevice, TRUE) ) return TRUE;
- }
- return FALSE;
- }
- HRESULT CFolder::_RegisterObject(CLSID clsid, UINT id, BOOL bRegister, _ATL_REGMAP_ENTRY *rm, LPCTSTR pstrDeviceName)
- {
- HRESULT Hr;
- HR( _Module.UpdateRegistryFromResource(id, bRegister, rm) );
- if( !bRegister ) return S_OK;
- // Uh, need to write additional attribute data to registry...
- CRegKey reg;
- OLECHAR szCLSID[64];
- ::StringFromGUID2(clsid, szCLSID, lengthof(szCLSID));
- TCHAR szSubKey[128];
- LONG lResult;
-
- // Write DeviceName and Partition for Drive
- ::wsprintf( szSubKey, _T("CLSID\%ls"), szCLSID);
- lResult = reg.Open(HKEY_CLASSES_ROOT, szSubKey);
- if( lResult!=ERROR_SUCCESS ) return E_FAIL;
- if( (clsid==CLSID_Drive) && (pstrDeviceName!=NULL) ) {
- reg.SetValue(pstrDeviceName, _T("DeviceName"));
- reg.SetValue((DWORD)0L, _T("Partition"));
- }
-
- // Write EditFlags to prevent Download Security dialog
- #define FTA_OpenIsSafe 0x00010000
- DWORD dwFlags = FTA_OpenIsSafe;
- lResult = ::RegSetValueEx(reg,
- _T("EditFlags"),
- 0,
- REG_BINARY,
- (LPBYTE)&dwFlags,
- sizeof(dwFlags));
- // Write ShellFolder attributes
- ::wsprintf(szSubKey, _T("CLSID\%ls\ShellFolder"), szCLSID);
- lResult = reg.Open(HKEY_CLASSES_ROOT, szSubKey);
- if( lResult!=ERROR_SUCCESS ) return E_FAIL;
- reg.SetValue(m_dwShellAttributes, _T("Attributes"));
- return S_OK;
- }
- HRESULT WINAPI CFolder::UpdateRegistry(BOOL bRegister)
- {
- CComBSTR bstrDescription;
- CComBSTR bstrDriveDescription;
- CComBSTR bstrProject;
- CComBSTR bstrInfoTip;
- CComBSTR bstrCLSID(CLSID_Folder);
- CComBSTR bstrDriveCLSID(CLSID_Drive);
- bstrDescription.LoadString(IDS_DESCRIPTION);
- bstrDriveDescription.LoadString(IDS_DRIVEDESCRIPTION);
- bstrProject.LoadString(IDS_PROJNAME);
- bstrInfoTip.LoadString(IDS_INFOTIP);
- _ATL_REGMAP_ENTRY rm[] = {
- { OLESTR("DESCRIPTION"), bstrDescription },
- { OLESTR("PROJECTNAME"), bstrProject },
- { OLESTR("CLSID"), bstrCLSID },
- { OLESTR("INFOTIP"), bstrInfoTip },
- { OLESTR("DRIVECLSID"), bstrDriveCLSID },
- { OLESTR("DRIVEDESCRIPTION"), bstrDriveDescription },
- { NULL,NULL } };
- HRESULT Hr;
- HR( _RegisterObject(CLSID_Folder, IDR_FOLDER, bRegister, rm, NULL) );
-
- // Process the CLSID_Drive registry entries
- OSVERSIONINFO vi;
- vi.dwOSVersionInfoSize = sizeof(vi);
- ::GetVersionEx(&vi);
- if( bRegister && (vi.dwPlatformId==VER_PLATFORM_WIN32_NT) ) {
- // Register on >= WinNT: we can add a native drive if found
- TCHAR szDevice[MAX_PATH];
- if( _FindAmigaDrive(szDevice) ) {
- HR( _RegisterObject(CLSID_Drive, IDR_DRIVE, bRegister, rm, szDevice) );
- }
- }
- else if( !bRegister ) {
- // Unregister - straight ahead
- HR( _RegisterObject(CLSID_Drive, IDR_DRIVE, bRegister, rm, NULL) );
- }
- return S_OK;
- }
- /////////////////////////////////////////////////////////////////////////////
- // CFolder
- HRESULT CFolder::FinalConstruct()
- {
- ATLTRACE(_T("CFolder::FinalConstructn"));
-
- // Get a unique folder ID
- SYSTEMTIME st;
- ::GetSystemTime(&st);
- m_dwFolderID = (st.wMilliseconds<<16) | (st.wSecond<<8) | (st.wMinute);
- // BUG: This is not unique. And it doesn't reflect the actual path!
- m_bErrorShown = false;
-
- return S_OK;
- }
- void CFolder::FinalRelease()
- {
- ATLTRACE(_T("CFolder::FinalReleasen"));
- }
- /////////////////////////////////////////////////////////////////////////////
- // Implementation
- // This helper function creates the actual PIDL entry
- // from the supplied arguments.
- LPITEMIDLIST CFolder::_CreateItem(
- LPCTSTR pstrName,
- LPCTSTR pstrComment,
- PIDLTYPE pidlType,
- int DosType,
- DWORD dwSize,
- SYSTEMTIME ftTime,
- DWORD dwAccess,
- DWORD dwEntryFlags)
- {
- ATLTRACE(_T("CFolder::_CreateItem '%s'n"), pstrName);
- ATLASSERT(pstrName);
- ATLASSERT(pidlType==PT_FOLDER || pidlType==PT_FILE);
- UINT TypeID;
- switch(pidlType) {
- case PT_FOLDER: TypeID = IDS_FOLDER; break;
- case PT_FILE: TypeID = IDS_FILE; break;
- default: TypeID = IDS_UNKNOWN; break;
- }
- if( CAdfFile::_IsLink(DosType) ) TypeID = IDS_LINK;
- if( dwEntryFlags & EF_DELETED ) TypeID = IDS_DELETEDENTRY;
- PIDLDATA data = { 0 };
- _tcsncpy(data.szName, pstrName, lengthof(data.szName)-1);
- _tcsncpy(data.szComment, pstrComment==NULL ? _T("") : pstrComment, lengthof(data.szComment)-1);
- data.type = pidlType;
- data.iDosType = DosType;
- ::LoadString(_Module.GetResourceInstance(), TypeID, data.szType, lengthof(data.szType)-1);
- data.ftTime = ftTime;
- data.dwSize = dwSize;
- data.dwAccess = dwAccess;
- data.dwEntryFlags = dwEntryFlags;
- // Add PIDL
- BYTE buf[ sizeof(PIDLDATA) + sizeof(ITEMIDLIST) ];
- LPPIDLDATA pci = reinterpret_cast<LPPIDLDATA>(buf);
- ::CopyMemory(pci, &data, sizeof(PIDLDATA));
- pci->cb = (WORD)sizeof(PIDLDATA);
- pci->tag = PIDL_TAG;
- // Terminate the IDList
- *(WORD *)(((LPBYTE)pci)+pci->cb) = 0;
- return CPidl::_Copy( (LPITEMIDLIST)pci );
- }
- SYSTEMTIME CFolder::_ConvertEntryTime(Entry *p)
- {
- ATLASSERT(p);
- SYSTEMTIME st;
- st.wYear = (WORD)p->year;
- st.wMonth = (WORD)p->month;
- st.wDay = (WORD)p->days;
- st.wHour = (WORD)p->hour;
- st.wMinute = (WORD)p->mins;
- st.wSecond = (WORD)p->secs;
- st.wMilliseconds = 0;
- st.wDayOfWeek = 0;
- return st;
- }
- HRESULT CFolder::_CreateShellFolderView(LPVOID *ppvObj)
- {
- ATLTRACE(_T("CFolder::_CreateShellFolderViewn"));
- VALIDATE_OUT_POINTER(ppvObj);
- HRESULT Hr;
- CComObject<CView> *obj;
- HR( CComObject<CView>::CreateInstance(&obj) );
- HR( obj->_Init(this) );
- return obj->QueryInterface(IID_IShellView, ppvObj);
- }
- // Bind To Parent.
- // Actually the W2K Shell supplies the ::SHBindToParent() function,
- // but we need it for other platforms too.
- HRESULT CFolder::_BindToParent(CComObject<CFolder> **pFolder)
- {
- VALIDATE_OUT_POINTER(pFolder);
- // Create the PIDL for the parent
- CPidl pidl;
- pidl.Copy(m_pidlPath);
- pidl.RemoveLast();
- // Bind it.
- return _BindToObject(pidl, pFolder);
- }
- // Internal version of IShellFolder::BindToObject().
- // It allows us to bind to any folder.
- // The 'pidl' argument is a full PIDL path relative to the root (not desktop)!
- // Because we return a CComObject<CFolder> take good care to check reference count.
- HRESULT CFolder::_BindToObject(LPCITEMIDLIST pidl, CComObject<CFolder> **pFolder)
- {
- ATLTRACE(_T("CFolder::_BindToObject '%s'n"), DbgGetPidlPath(pidl));
- ATLASSERT(pFolder);
- HRESULT Hr;
- HR( CComObject<CFolder>::CreateInstance(pFolder) );
- (*pFolder)->Initialize(m_pidl);
- (*pFolder)->m_pidlPath.Copy(pidl);
- return S_OK;
- }
- short CFolder::_CompareItems(short iColumn, LPCPIDLDATA pData1, LPCPIDLDATA pData2)
- {
- #define COMPARE_INT(a,b) if(a!=b) return a>b ? (short)1 : (short)-1
- // If data missing, default...
- BOOL bIsEmpty1 = CPidl::_IsEmpty((LPCITEMIDLIST)pData1);
- BOOL bIsEmpty2 = CPidl::_IsEmpty((LPCITEMIDLIST)pData2);
- if( bIsEmpty1 && bIsEmpty2 ) return 0;
- if( bIsEmpty1 ) return -1;
- if( bIsEmpty2 ) return 1;
- // Validate
- ATLASSERT(pData1->tag==pData2->tag);
- // Folders always come before files
- if( pData1->type==PT_FOLDER && pData2->type==PT_FILE ) return -1;
- if( pData1->type==PT_FILE && pData2->type==PT_FOLDER ) return 1;
- // Compare item data (if data is equal, use filename to determine sort
- // order).
- switch( iColumn ) {
- case COL_SIZE:
- COMPARE_INT(pData1->dwSize, pData2->dwSize);
- break;
- case COL_TYPE:
- return (short)_tcscmp(pData1->szType, pData2->szType);
- case COL_TIME:
- COMPARE_INT(pData1->ftTime.wYear, pData2->ftTime.wYear);
- COMPARE_INT(pData1->ftTime.wMonth, pData2->ftTime.wMonth);
- COMPARE_INT(pData1->ftTime.wDay, pData2->ftTime.wDay);
- COMPARE_INT(pData1->ftTime.wHour, pData2->ftTime.wHour);
- COMPARE_INT(pData1->ftTime.wMinute, pData2->ftTime.wMinute);
- COMPARE_INT(pData1->ftTime.wSecond, pData2->ftTime.wSecond);
- break;
- case COL_ATTRIBS:
- COMPARE_INT(pData1->dwAccess, pData2->dwAccess);
- break;
- }
- return (short)_tcsicmp(pData1->szName, pData2->szName);
- #undef COMPARE_INT
- }
- /////////////////////////////////////////////////////////////////////////////
- // IShellFolder
- STDMETHODIMP CFolder::CreateViewObject(HWND hWnd, REFIID riid, LPVOID* ppRetVal)
- {
- ATLTRACE(_T("CFolder::CreateViewObject %sn"), DbgGetIID(riid));
- VALIDATE_OUT_POINTER(ppRetVal);
- HRESULT Hr;
- if( riid == IID_IDropTarget ) {
- CComObject<CDropTarget> *pDropTarget;
- HR( CComObject<CDropTarget>::CreateInstance(&pDropTarget) );
- HR( pDropTarget->_Init(this, hWnd) );
- return pDropTarget->QueryInterface(IID_IDropTarget, ppRetVal);
- }
- if( riid == IID_IContextMenu ) {
- CComObject<CContextMenu> *pContextMenu;
- HR( CComObject<CContextMenu>::CreateInstance(&pContextMenu) );
- HR( pContextMenu->_Init(this, hWnd, NULL) );
- return pContextMenu->QueryInterface(IID_IContextMenu, ppRetVal);
- }
- if( riid == IID_IShellView ) {
- return _CreateShellFolderView(ppRetVal);
- }
-
- return E_NOINTERFACE;
- }
- // Adds entries in a directory list to the PIDL list.
- void CFolder::_AddFolderToEnum(CPidl &pidl, List *cell, DWORD dwFlags, DWORD dwEntryFlags)
- {
- while( cell!=NULL ) {
- Entry *entry = (Entry *)cell->content;
-
- PIDLTYPE pidlType = PT_UNKNOWN;
- switch( entry->type ) {
- case ST_DIR:
- case ST_LDIR:
- if( dwFlags & SHCONTF_FOLDERS ) pidlType = PT_FOLDER;
- break;
- case ST_FILE:
- case ST_LFILE:
- if( dwFlags & SHCONTF_NONFOLDERS ) pidlType = PT_FILE;
- break;
- }
- if( pidlType!=PT_UNKNOWN ) {
- SYSTEMTIME st = _ConvertEntryTime(entry);
- pidl.Concatenate( _CreateItem(
- A2CT(entry->name),
- A2CT(entry->comment),
- pidlType,
- entry->type,
- entry->size,
- st,
- entry->access,
- dwEntryFlags) );
- }
- cell = cell->next;
- }
- }
- // Adds entries in a deleted files list to the PIDL list.
- void CFolder::_AddDeletedToEnum(CPidl &pidl, List *cell, SECTNUM nDirSector, DWORD dwFlags, DWORD dwEntryFlags)
- {
- while( cell!=NULL ) {
- GenBlock *entry = (GenBlock *)cell->content;
- cell = cell->next;
- if( entry->parent != nDirSector ) continue;
- PIDLTYPE pidlType = PT_UNKNOWN;
- switch( entry->secType ) {
- case ST_DIR:
- if( dwFlags & SHCONTF_FOLDERS ) pidlType = PT_FOLDER;
- break;
- case ST_FILE:
- if( dwFlags & SHCONTF_NONFOLDERS ) pidlType = PT_FILE;
- break;
- }
- if( pidlType!=PT_UNKNOWN ) {
- SYSTEMTIME st;
- ::GetSystemTime(&st);
- pidl.Concatenate( _CreateItem(
- A2CT(entry->name),
- NULL,
- pidlType,
- entry->type,
- 0, // don't know the size yet
- st,
- 0,
- dwEntryFlags) );
- }
- }
- }
- STDMETHODIMP CFolder::EnumObjects(HWND hWnd, DWORD dwFlags, LPENUMIDLIST* ppRetVal)
- {
- ATLTRACE(_T("CFolder::EnumObjectsn"));
- VALIDATE_OUT_POINTER(ppRetVal);
- // Open Amiga device.
- // This is actually the first time we attempt to open the volume
- // if the folder was just created.
- HRESULT Hr;
- CAdfDevice dev;
- CAdfVolume vol;
- Hr = _OpenAmigaDevice(m_pidl, TRUE, m_pidlPath, dev, vol);
- if( FAILED(Hr) ) {
- CResString<200> sText(IDS_DISKERROR);
- CResString<64> sCaption(IDS_ERROR);
- if( !m_bErrorShown ) ::MessageBox(hWnd, sText, sCaption, MB_OK|MB_ICONWARNING|MB_TASKMODAL);
- m_bErrorShown = true;
- return Hr;
- }
- CPidl pidl;
- // Gather files from current directory
- CAdfDirList list;
- if( vol.GetCurrentDirctory(list)==FALSE ) return E_FAIL;
- _AddFolderToEnum(pidl, list, dwFlags, 0);
- // Check if we need to display 'deleted' files too
- if( dwFlags & SHCONTF_INCLUDEDELETED ) {
- // So add 'deleted' files to the list
- CAdfDelList list;
- if( vol.GetDeletedEntries(list)==FALSE ) return E_FAIL;
- _AddDeletedToEnum(pidl, list, vol.GetDirectoryPtr(), dwFlags, EF_DELETED);
- }
- CComObject<CPidlEnum> *pEnum;
- HR( CComObject<CPidlEnum>::CreateInstance(&pEnum) );
- HR( pEnum->_Init( pidl, pidl.GetCount() ) );
- HR( pEnum->QueryInterface(IID_IEnumIDList, (LPVOID *)ppRetVal) );
- return S_OK;
- }
- STDMETHODIMP CFolder::CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
- {
- #ifdef _DEBUG
- TCHAR szName1[MAX_PATH];
- TCHAR szName2[MAX_PATH];
- _tcscpy( szName1, DbgGetPidlPath(pidl1) );
- _tcscpy( szName2, DbgGetPidlPath(pidl2) );
- ATLTRACE(_T("CFolder::CompareIDs (%d) '%s'<-->'%s'n"), lParam, szName1, szName2);
- #endif
- // The lParam is used to determine whether to compare items or sub-items.
- // We must compare the complete ITEMIDLIST.
- while( pidl1!=NULL || pidl2!=NULL ) {
- short lCmd = _CompareItems((short)lParam, (LPPIDLDATA)pidl1, (LPPIDLDATA)pidl2);
- if( lCmd<0 ) return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(-1));
- if( lCmd>0 ) return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(1));
- pidl1 = CPidl::_GetNextItem(pidl1);
- pidl2 = CPidl::_GetNextItem(pidl2);
- if( CPidl::_IsEmpty(pidl1) ) pidl1=NULL;
- if( CPidl::_IsEmpty(pidl2) ) pidl2=NULL;
- }
- return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0);
- }
- STDMETHODIMP CFolder::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD uFlags, LPSTRRET lpName)
- {
- ATLTRACE(_T("CFolder::GetDisplayNameOf (%d) '%s'n"), uFlags, DbgGetPidlPath(pidl));
- ATLASSERT(CPidl::_GetCount(pidl)==1);
- LPCPIDLDATA pData = pidl_cast(pidl);
- LPCTSTR pstrFileName = pData->szName;
- #ifdef _UNICODE
- USES_CONVERSION;
- // Allocate the wide character string
- int cchOleStr = ::lstrlen(pstrFileName) + 1;
- lpName->pOleStr = (LPWSTR)_Module.m_Allocator.Alloc(cchOleStr * sizeof(OLECHAR));
- if( lpName->pOleStr==NULL ) return E_OUTOFMEMORY;
- lpName->uType = STRRET_WSTR;
- ocscpy( lpName->pOleStr, T2CW(pstrFileName));
- #else
- lpName->uType = STRRET_CSTR;
- _tcscpy( lpName->cStr, pstrFileName);
- #endif
- return S_OK;
- }
- STDMETHODIMP CFolder::GetAttributesOf(UINT nCount, LPCITEMIDLIST pidls[], LPDWORD rgfInOut)
- {
- ATLTRACE(_T("CFolder::GetAttributesOf #%d, '%s'...n"), nCount, DbgGetPidlPath(pidls==NULL ? NULL : pidls[0]));
- ATLASSERT(rgfInOut);
- // Parse over all pidls and OR together attributes
- DWORD dwAttr = 0;
- if( nCount==0 ) {
- // Can happen on Win95. Queries the view folder.
- dwAttr |= SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_BROWSABLE | SFGAO_DROPTARGET;
- }
- for( UINT i=0; i<nCount; i++ ) {
- LPCPIDLDATA pData = pidl_cast(pidls[i]);
- switch( pData->type ) {
- case PT_FOLDER:
- dwAttr |= SFGAO_FOLDER;
- if( pData->dwEntryFlags & EF_DELETED ) {
- dwAttr |= SFGAO_GHOSTED;
- }
- else {
- dwAttr |= SFGAO_HASSUBFOLDER | SFGAO_BROWSABLE | SFGAO_DROPTARGET |
- SFGAO_HASPROPSHEET |
- SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_CANDELETE | SFGAO_CANRENAME;
- if( hasW(pData->dwAccess) ) dwAttr |= SFGAO_READONLY;
- if( pData->iDosType==ST_LDIR ) dwAttr |= SFGAO_LINK;
- }
- break;
- case PT_FILE:
- if( pData->dwEntryFlags & EF_DELETED ) {
- dwAttr |= SFGAO_GHOSTED;
- }
- else {
- dwAttr |= SFGAO_HASPROPSHEET |
- SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_CANDELETE | SFGAO_CANRENAME;
- if( hasW(pData->dwAccess) ) dwAttr |= SFGAO_READONLY;
- if( pData->iDosType==ST_LFILE ) dwAttr |= SFGAO_LINK;
- }
- break;
- }
- }
- *rgfInOut = dwAttr & (*rgfInOut);
- return S_OK;
- }
- STDMETHODIMP CFolder::SetNameOf(HWND, LPCITEMIDLIST pidl, LPCOLESTR pstrName, DWORD, LPITEMIDLIST *ppidlOut)
- {
- ATLTRACE(_T("CFolder::SetNameOf '%s'n"), DbgGetPidlPath(pidl));
- ATLASSERT(pidl);
- ATLASSERT(pstrName);
- USES_CONVERSION;
- if( ppidlOut!=NULL ) *ppidlOut=NULL;
- DWORD dwAttr = SFGAO_CANRENAME;
- GetAttributesOf(1, &pidl, &dwAttr);
- if( (dwAttr & SFGAO_CANRENAME)==0 ) return E_FAIL;
- TCHAR szNewName[MAXNAMELEN+1];
- if( wcslen(pstrName)>MAXNAMELEN ) return E_FAIL;
- _tcscpy( szNewName, OLE2CT(pstrName));
-
- LPCPIDLDATA pOldData = pidl_cast(pidl);
- CPidl pidlNew;
- pidlNew.Attach( _CreateItem(
- szNewName,
- pOldData->szComment,
- pOldData->type,
- pOldData->iDosType,
- pOldData->dwSize,
- pOldData->ftTime,
- pOldData->dwAccess,
- pOldData->dwEntryFlags) );
- HRESULT Hr;
- HR( _RenameFile(pidl, pidlNew) );
- if( ppidlOut!=NULL ) *ppidlOut = pidlNew.Detach();
- return S_OK;
- }
- STDMETHODIMP CFolder::BindToObject(LPCITEMIDLIST pidl, LPBC, REFIID riid, LPVOID* ppRetVal)
- {
- ATLTRACE(_T("CFolder::BindToObject '%s' %sn"), DbgGetPidlPath(pidl), DbgGetIID(riid));
- VALIDATE_OUT_POINTER(ppRetVal);
-
- if( riid != IID_IShellFolder ) return E_NOINTERFACE;
- CPidl pidlFull;
- pidlFull.Copy(m_pidlPath);
- pidlFull.Concatenate(pidl);
- HRESULT Hr;
- CComObject<CFolder> *pObj;
- HR( _BindToObject(pidlFull, &pObj) );
- return pObj->QueryInterface(riid, ppRetVal);
- }
- STDMETHODIMP CFolder::GetUIObjectOf(HWND hWnd, UINT nCount, LPCITEMIDLIST* pidls, REFIID riid, LPUINT, LPVOID* ppRetVal)
- {
- ATLTRACE(_T("CFolder::GetUIObjectOf %s, #%d, '%s'...n"), DbgGetIID(riid), nCount, DbgGetPidlPath(pidls==NULL ? NULL : pidls[0]));
- VALIDATE_OUT_POINTER(ppRetVal);
- ATLASSERT(nCount>0);
- if( nCount==0 ) return E_INVALIDARG;
- HRESULT Hr;
- if( riid == IID_IExtractIcon ) {
- CComObject< CExtractIcon<const PIDLDATA> > *pExtractIcon;
- HR( CComObject< CExtractIcon<const PIDLDATA> >::CreateInstance(&pExtractIcon) );
- HR( pExtractIcon->_Init(*pidls) );
- return pExtractIcon->QueryInterface(IID_IExtractIcon, ppRetVal);
- }
- if( riid == IID_IDropTarget ) {
- if( nCount!=1 ) return E_FAIL;
- // Need to create a IShellFolder for the subfolder
- CComObject<CFolder> *pFolder;
- CPidl pidl;
- pidl.Copy(m_pidlPath);
- pidl.Concatenate(pidls[0]);
- HR( _BindToObject(pidl, &pFolder) );
- // Do the bungy
- CComObject<CDropTarget> *pDropTarget;
- HR( CComObject<CDropTarget>::CreateInstance(&pDropTarget) );
- HR( pDropTarget->_Init(pFolder, hWnd) );
- return pDropTarget->QueryInterface(IID_IDropTarget, ppRetVal);
- }
- if( riid == IID_IContextMenu ) {
- if( nCount!=1 ) return E_FAIL;
- CComObject<CContextMenu> *pContextMenu;
- HR( CComObject<CContextMenu>::CreateInstance(&pContextMenu) );
- HR( pContextMenu->_Init(this, hWnd, pidls[0]) );
- return pContextMenu->QueryInterface(IID_IContextMenu, ppRetVal);
- }
- if( riid == IID_IDataObject ) {
- CComObject<CDataObject> *pDataObject;
- HR( CComObject<CDataObject>::CreateInstance(&pDataObject) );
- HR( pDataObject->_Init(this, hWnd, pidls, nCount) );
- return pDataObject->QueryInterface(IID_IDataObject, ppRetVal);
- }
- return E_NOINTERFACE;
- }
- /////////////////////////////////////////////////////////////////////////////
- // IQueryInfo
- STDMETHODIMP CFolder::GetInfoFlags(DWORD *pdwFlags)
- {
- VALIDATE_OUT_POINTER(pdwFlags);
- *pdwFlags = 0;
- return S_OK;
- }
- STDMETHODIMP CFolder::GetInfoTip(DWORD, LPWSTR *ppwszTip)
- {
- VALIDATE_OUT_POINTER(ppwszTip);
- CComBSTR bstr;
- bstr.LoadString(IDS_INFOTIP);
- *ppwszTip = (LPWSTR)_Module.m_Allocator.Alloc((bstr.Length()+1) * sizeof(WCHAR));
- if( *ppwszTip==NULL ) return E_OUTOFMEMORY;
- USES_CONVERSION;
- wcscpy(*ppwszTip, bstr);
- return S_OK;
- }