//+------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1995 // // File: ofsfldr.cpp // // Contents: Implements most of COFSFolder class // // History: 6-26-95 Davepl,JonBe Created // //-------------------------------------------------------------------------- #include "precomp.h" #include #include //+------------------------------------------------------------------------- // // COFSFolder Constructor // //-------------------------------------------------------------------------- COFSFolder::COFSFolder() { m_cRef = 1L; m_pidl = NULL; m_fIsDSFolder = FALSE; m_fCachedCLSID = FALSE; m_fHasCLSID = FALSE; } //+------------------------------------------------------------------------- // // COFSFolder Destructor // //-------------------------------------------------------------------------- COFSFolder::~COFSFolder() { if (m_pidl) { SHFree(m_pidl); } } //+------------------------------------------------------------------------- // // COFSFolder::QueryInterface // //-------------------------------------------------------------------------- STDMETHODIMP COFSFolder::QueryInterface(REFIID riid, LPVOID FAR *ppv) { HRESULT hr = S_OK; *ppv = NULL; if (IsEqualIID(riid, IID_IShellFolder)) { *ppv = (LPSHELLFOLDER) this; } else if (IsEqualIID(riid, IID_IUnknown)) { *ppv = (LPUNKNOWN) (LPSHELLFOLDER) this; } else if (IsEqualIID(riid, IID_IPersistFolder)) { *ppv = (LPPERSISTFOLDER) this; } else if (IsEqualIID(riid, IID_IShellIcon)) { *ppv = (LPSHELLICON) this; } if (*ppv) { AddRef(); hr = NOERROR; } else { hr = E_NOINTERFACE; } return hr; } //+------------------------------------------------------------------------- // // COFSFolder RefCounting // //-------------------------------------------------------------------------- STDMETHODIMP_(ULONG) COFSFolder::AddRef() { InterlockedIncrement((LONG *)&m_cRef); return m_cRef; } STDMETHODIMP_(ULONG) COFSFolder::Release() { if (0 != InterlockedDecrement((LONG *)&m_cRef)) { return m_cRef; } delete this; return 0L; } //+------------------------------------------------------------------------- // // Member: COFSFolder::InitializeFromIDList // // Synopsis: Initializes this COFSFolder object based on the pidl passed // in, and returns an IShellFolder ptr on the OUT ptr. // // History: 6-26-95 davepl Created // // Notes: Currently, we create an FSFolder object to delegate // everything to // //-------------------------------------------------------------------------- HRESULT COFSFolder::InitializeFromIDList(const CIDList * pidl, REFIID riid, LPVOID * ppvOut) { HRESULT hr; m_wSpecialFID = CSIDL_NOTCACHED; // // Make a copy of the pidl, then QI for the interface. // hr = pidl->CloneTo(&m_pidl); if (SUCCEEDED(hr)) { hr = QueryInterface(riid, ppvOut); } Release(); m_fIsDSFolder = IsDSFolder((LPCITEMIDLIST) m_pidl); return hr; } //+------------------------------------------------------------------------- // // Member: COFSFolder::ParseDisplayName // // History: 6-26-95 davepl Created // // Notes: // //-------------------------------------------------------------------------- STDMETHODIMP COFSFolder::ParseDisplayName(HWND hwnd, LPBC pbcReserved, LPOLESTR lpszDisplayName, ULONG * pchEaten, LPITEMIDLIST * ppidl, ULONG * pdwAttributes) { HRESULT hr; hr = CFSFolder_ParseDisplayName( (LPSHELLFOLDER) this, hwnd, pbcReserved, lpszDisplayName, pchEaten, ppidl, pdwAttributes); return hr; } //+------------------------------------------------------------------------- // // Member: COFSFolder::EnumObjects // // History: 6-26-95 davepl Created // // Notes: // //-------------------------------------------------------------------------- STDMETHODIMP COFSFolder::EnumObjects(HWND hwndOwner, DWORD grfFlags, LPENUMIDLIST * ppenumIDList) { HRESULT hr; TCHAR szFolder[MAX_PATH]; CEnumOLEDB * pEnumOLEDB = new CEnumOLEDB; if (NULL == pEnumOLEDB) { return E_OUTOFMEMORY; } hr = pEnumOLEDB->InitInstance(); if (FAILED(hr)) { delete pEnumOLEDB; return hr; } if (FALSE == SHGetPathFromIDList((LPITEMIDLIST) m_pidl, szFolder)) { // // NOTES: We assume SHGetpathFromIDList fails only bacause // the path is too long in this context. If not, we should // change SHGetPathFromIDList so that it returns HRESULT // instead of BOOL. // if (hwndOwner) { (void) ShellMessageBox(HINST_THISDLL, hwndOwner, MAKEINTRESOURCE(IDS_ENUMERR_PATHTOOLONG), NULL, // get the title from hwndOwner MB_OK | MB_ICONHAND); } delete pEnumOLEDB; hr = E_INVALIDARG; return hr; } hr = SynchronousQuery(szFolder, grfFlags, pEnumOLEDB); // // If successful, set the out pointer. If anything failed along the way, // release the enumerator BUGBUG Release vs. delete? // if (SUCCEEDED(hr)) { *ppenumIDList = pEnumOLEDB; // Lie to DefView_FillObjects, which will only call your enumerator // if you return exactly S_OK (and no other success HRESULTs) // (JonBe, 8/11/95) hr = S_OK; } else { delete pEnumOLEDB; } return hr; } //+------------------------------------------------------------------------- // // Member: COFSFolder::BindToObject // // Synopsis: // // History: 6-26-95 davepl Created // // Notes: // //-------------------------------------------------------------------------- STDMETHODIMP COFSFolder::BindToObject(LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut) { HRESULT hr; hr = CFSFolder_BindToObject( (LPSHELLFOLDER) this, pidl, pbcReserved, riid, ppvOut); return hr; } //+------------------------------------------------------------------------- // // Member: COFSFolder::BindToStorage // // // History: 6-26-95 davepl Created // // Notes: // //-------------------------------------------------------------------------- STDMETHODIMP COFSFolder::BindToStorage(LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvObj) { HRESULT hr; hr = CFSFolder_BindToObject( (LPSHELLFOLDER) this, pidl, pbcReserved, riid, ppvObj); return hr; } //+------------------------------------------------------------------------- // // Member: COFSFolder::CompareIDs // // Synopsis: // // History: 6-26-95 davepl Created // // Notes: // //-------------------------------------------------------------------------- STDMETHODIMP COFSFolder::CompareIDs(LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2) { HRESULT hr; hr = CFSFolder_CompareIDs( (LPSHELLFOLDER) this, lParam, pidl1, pidl2); return hr; } //+------------------------------------------------------------------------- // // Member: COFSFolder::CreateViewObject // // Synopsis: // // History: 6-26-95 davepl Created // // Notes: // //-------------------------------------------------------------------------- // BUGBUG This string is also defined in fstreex.c There should be one // common def'n TCHAR const c_szCLSIDView[] = TEXT("UICLSID"); STDMETHODIMP COFSFolder::CreateViewObject(HWND hwnd, REFIID riid, LPVOID * ppvOut) { HRESULT hr; if (IsEqualIID(riid, IID_IShellView) || IsEqualIID(riid, IID_IDropTarget)) { if (FALSE == m_fCachedCLSID) { LPIDFOLDER pidf = (LPIDFOLDER) (m_pidl->FindLastID()); if (pidf && (pidf->fs.wAttrs & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM))) { TCHAR szPath[MAX_PATH]; if (FALSE == SHGetPathFromIDList((LPITEMIDLIST) m_pidl, szPath)) { return E_FAIL; } m_fHasCLSID = _GetFolderCLSID(szPath, NULL, &m_clsidView, c_szCLSIDView); } m_fCachedCLSID = TRUE; } // // Use the view handler if it exists. // if (m_fHasCLSID) { LPPERSISTFOLDER ppf; HRESULT hres = SHCoCreateInstance(NULL, &m_clsidView, NULL, IID_IPersistFolder, (LPVOID *) &ppf); if (SUCCEEDED(hres)) { hres = ppf->Initialize((LPITEMIDLIST) m_pidl); if (SUCCEEDED(hres)) { hres = ppf->QueryInterface(riid, ppvOut); } ppf->Release(); } if (SUCCEEDED(hres)) { return hres; } } if (IsEqualIID(riid, IID_IDropTarget)) { if (this->m_fIsDSFolder) { hr = CDS_IDLDropTarget_CreateFromPidl(hwnd, (LPITEMIDLIST) m_pidl, (LPDROPTARGET *)ppvOut); } else { hr = CIDLDropTarget_CreateFromPidl(hwnd, (LPITEMIDLIST) m_pidl, (LPDROPTARGET *)ppvOut); } } else { CSFV csfv = { SIZEOF(CSFV), // cbSize (LPSHELLFOLDER) this, // pshf NULL, // psvOuter (LPITEMIDLIST) m_pidl, // pidl SHCNE_DISKEVENTS | SHCNE_ASSOCCHANGED | SHCNE_NETSHARE | SHCNE_NETUNSHARE, FS_FNVCallBack, // pfnCallback (FOLDERVIEWMODE) 0, // BUGBUG add 0 to enumeration }; LPSHELLBROWSER psb = FileCabinet_GetIShellBrowser(hwnd); HWND hwndTree; // // If in explorer mode, we want to register for freespace changes too // psb->GetControlWindow(FCW_TREE, &hwndTree); if (hwndTree) { csfv.lEvents |= SHCNE_FREESPACE; } return SHCreateShellFolderViewEx(&csfv, (LPSHELLVIEW *)ppvOut); } } else if (IsEqualIID(riid, IID_IContextMenu)) { // // Do background menu. // hr = CDefFolderMenu_Create((LPITEMIDLIST) m_pidl, hwnd, 0, NULL, (LPSHELLFOLDER) this, CFSFolder_DFMCallBackBG, NULL, NULL, (LPCONTEXTMENU *) ppvOut); } else { hr = E_NOINTERFACE; } return hr; } //+------------------------------------------------------------------------- // // Member: COFSFolder::GetAttributesOf // // Synopsis: Returns attributers of a set of items // // Arguments: [cidl] -- count of items in the ID List // [apidl] -- the IDList of items to get attrigutes for // [rgfInOut] -- flags to be evaluated // // Returns: HRESULT // // History: 6-26-95 davepl Created // // Notes: // //-------------------------------------------------------------------------- STDMETHODIMP COFSFolder::GetAttributesOf (UINT cidl, LPCITEMIDLIST * apidl, ULONG * prgfInOut) { HRESULT hr; hr = CFSFolder_GetAttributesOf( (LPSHELLFOLDER) this, cidl, apidl, prgfInOut); return hr; } //+------------------------------------------------------------------------- // // Member: COFSFolder::GetUIObjectOf // // Synopsis: // // History: 6-26-95 davepl Created // // Notes: // //-------------------------------------------------------------------------- STDMETHODIMP COFSFolder::GetUIObjectOf(HWND hwnd, UINT cidl, LPCITEMIDLIST * apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut) { HRESULT hr; hr = CFSFolder_GetUIObjectOf( (LPSHELLFOLDER) this, hwnd, cidl, apidl, riid, prgfInOut, ppvOut); return hr; } //+------------------------------------------------------------------------- // // Member: COFSFolder::GetDisplayNameOf // // Synopsis: // // History: 6-26-95 davepl Created // // Notes: // //-------------------------------------------------------------------------- STDMETHODIMP COFSFolder::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD uFlags, LPSTRRET lpName) { HRESULT hr; hr = CFSFolder_GetDisplayNameOf( (LPSHELLFOLDER) this, pidl, uFlags, lpName); return hr; } //+------------------------------------------------------------------------- // // Member: COFSFolder::SetNameOf // // Synopsis: // // History: 6-26-95 davepl Created // // Notes: // //-------------------------------------------------------------------------- STDMETHODIMP COFSFolder::SetNameOf (HWND hwnd, LPCITEMIDLIST pidl, LPCOLESTR lpszName, DWORD uFlags, LPITEMIDLIST * ppidlOut) { HRESULT hr; hr = CFSFolder_SetNameOf( (LPSHELLFOLDER) this, hwnd, pidl, lpszName, uFlags, ppidlOut); return hr; } //+------------------------------------------------------------------------- // // Member: COFSFolder::GetClassID [IPersist] // // Synopsis: // // History: 6-28-95 davepl Created // // Notes: // //-------------------------------------------------------------------------- STDMETHODIMP COFSFolder::GetClassID(LPCLSID lpClassID) { HRESULT hr; hr = CFSFolder_PF_GetClassID( (LPPERSISTFOLDER) this, lpClassID); return hr; } //+------------------------------------------------------------------------- // // Member: COFSFolder::Initialize [IPersistFolder] // // Synopsis: // // History: 6-28-95 davepl Created // // Notes: // //-------------------------------------------------------------------------- STDMETHODIMP COFSFolder::Initialize(LPCITEMIDLIST pidl) { HRESULT hr; hr = CFSFolder_PF_Initialize( (LPPERSISTFOLDER) this, pidl); return hr; } //+------------------------------------------------------------------------- // // Member: COFSFolder::GetIconOf [IShellIcon] // // Synopsis: // // History: 6-28-95 davepl Created // // Notes: // //-------------------------------------------------------------------------- STDMETHODIMP COFSFolder::GetIconOf(LPCITEMIDLIST pidl, UINT flags, LPINT lpIconIndex) { HRESULT hr; hr = CFSFolder_Icon_GetIconOf( (LPSHELLICON) this, pidl, flags, lpIconIndex); return hr; } //+------------------------------------------------------------------------- // // Member: COFSFolder::IsDSFolder [private helper member] // // Synopsis: // // History: 9 19 95 jimharr created // // Notes: // //-------------------------------------------------------------------------- BOOL COFSFolder::IsDSFolder (LPCITEMIDLIST pidl) { BOOL fSuccess = FALSE; BOOL fGotPath; TCHAR szPath[MAX_PATH]; TCHAR szClassName[40]; // REVIEW: This len should be in a header NTSTATUS nts; HANDLE h; CLSID clsid; UNICODE_STRING UFileName; OBJECT_ATTRIBUTES Obja; IO_STATUS_BLOCK IoStatusBlock; CHAR EaBuffer[sizeof(FILE_FULL_EA_INFORMATION) + sizeof(EA_NAME_OPENIFJP)]; ULONG cbOpenIfJPEa = sizeof(EaBuffer); PFILE_FULL_EA_INFORMATION pOpenIfJPEa = (PFILE_FULL_EA_INFORMATION)EaBuffer; DWORD err = GetLastError(); fGotPath = SHGetPathFromIDList (pidl, szPath); RtlDosPathNameToNtPathName_U(szPath, &UFileName, NULL, NULL); InitializeObjectAttributes( &Obja, &UFileName, OBJ_CASE_INSENSITIVE, NULL, NULL ); pOpenIfJPEa->NextEntryOffset = 0; pOpenIfJPEa->Flags = 0; pOpenIfJPEa->EaNameLength = lstrlenA(EA_NAME_OPENIFJP); pOpenIfJPEa->EaValueLength = 0; lstrcpyA(pOpenIfJPEa->EaName, EA_NAME_OPENIFJP); nts = NtCreateFile( &h, SYNCHRONIZE | FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES, &Obja, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN_IF, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, pOpenIfJPEa, cbOpenIfJPEa ); if ((nts == STATUS_DFS_EXIT_PATH_FOUND) || (nts == STATUS_PATH_NOT_COVERED)) { nts = NtCreateFile( &h, SYNCHRONIZE | FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES, &Obja, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN_IF, FILE_STORAGE_TYPE_SPECIFIED | FILE_STORAGE_TYPE_JUNCTION_POINT | FILE_SYNCHRONOUS_IO_NONALERT, pOpenIfJPEa, cbOpenIfJPEa ); } if (!NT_SUCCESS(nts)) { return FALSE; } nts = RtlQueryClassId(h, &clsid); CloseHandle( h ); if (nts == STATUS_NOT_FOUND) { return FALSE; } if (!NT_SUCCESS(nts)) { nts = GetClassFile (szPath, &clsid); } if (!NT_SUCCESS(nts)) { return FALSE; } fSuccess = (IsEqualCLSID (CLSID_CDSFolder, clsid)); return fSuccess; }