Code/Resource
Windows Develop
Linux-Unix program
Internet-Socket-Network
Web Server
Browser Client
Ftp Server
Ftp Client
Browser Plugins
Proxy Server
Email Server
Email Client
WEB Mail
Firewall-Security
Telnet Server
Telnet Client
ICQ-IM-Chat
Search Engine
Sniffer Package capture
Remote Control
xml-soap-webservice
P2P
WEB(ASP,PHP,...)
TCP/IP Stack
SNMP
Grid Computing
SilverLight
DNS
Cluster Service
Network Security
Communication-Mobile
Game Program
Editor
Multimedia program
Graph program
Compiler program
Compress-Decompress algrithms
Crypt_Decrypt algrithms
Mathimatics-Numerical algorithms
MultiLanguage
Disk/Storage
Java Develop
assembly language
Applications
Other systems
Database system
Embeded-SCM Develop
FlashMX/Flex
source in ebook
Delphi VCL
OS Develop
MiddleWare
MPI
MacOS develop
LabView
ELanguage
Software/Tools
E-Books
Artical/Document
netfldr.cpp
Package: shell.rar [view]
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 129k
Category:
Windows Kernel
Development Platform:
Visual C++
- BOOL CNetFolder::_GetPathForShare(LPCIDNETRESOURCE pidn, LPTSTR pszPath)
- {
- NETRESOURCE nr;
- DWORD err, dwRedir, dwResult;
- TCHAR szAccessName[MAX_PATH], szRemoteName[MAX_PATH], szProviderName[MAX_PATH];
- UINT cbAccessName;
- NET_CopyResName(pidn, szRemoteName, ARRAYSIZE(szRemoteName));
- if (NULL != _pszResName)
- {
- //
- // Combine the folder name with the share name
- // to create a UNC path.
- //
- // Borrow the szProviderName[] buffer for a bit.
- //
- PathCombine(szProviderName, _pszResName, szRemoteName);
- //
- // To be safe: UNC prefix implies that name is available using FS access
- // Theoretically it also should be routed to MPR, but it is late to do this
- //
- if (PathIsUNC(szProviderName))
- {
- lstrcpy(pszPath, szProviderName);
- return FALSE;
- }
- szProviderName[0] = TEXT('');
- }
- // Check cache
- ENTERCRITICAL;
- if (lstrcmpi(g_szLastAttemptedJunctionName, szRemoteName) == 0)
- {
- // cache hit
- lstrcpy(pszPath, g_szLastResolvedJunctionName);
- LEAVECRITICAL;
- return TRUE;
- }
- LEAVECRITICAL;
- memset(&nr, 0, SIZEOF(NETRESOURCE));
- nr.lpRemoteName = szRemoteName;
- nr.lpProvider = (LPTSTR) _GetProvider(pidn, szProviderName, ARRAYSIZE(szProviderName));
- nr.dwType = NET_GetType(pidn);
- nr.dwUsage = NET_GetUsage(pidn);
- nr.dwDisplayType = NET_GetDisplayType(pidn);
- dwRedir = CONNECT_TEMPORARY;
- // Prepare access name buffer and net resource request buffer
- cbAccessName = SIZEOF(szAccessName); // BUGBUG verify this is cb, not cch
- szAccessName[0] = 0;
- err = WNetUseConnection(NULL, &nr, NULL, NULL, dwRedir, szAccessName, (LPDWORD) &cbAccessName, &dwResult);
- if ((WN_SUCCESS != err) || !szAccessName[0])
- {
- lstrcpy(pszPath, szRemoteName);
- return FALSE;
- }
- // Get the return name
- lstrcpy(pszPath, szAccessName);
- // Update cache entry
- // BUGBUG We also want to record insuccessful resolution, although
- // it is not really important, as we come to resolving code often
- // only if it succeeded at least once.
- {
- ENTERCRITICAL;
- lstrcpy(g_szLastAttemptedJunctionName, szRemoteName);
- lstrcpy(g_szLastResolvedJunctionName, szAccessName);
- LEAVECRITICAL;
- }
- return TRUE;
- }
- // in:
- // pidn may be multi-level net resource pidl like
- // [entire net] [provider] [server] [share] [... file sys]
- // or [server] [share] [... file sys]
- HRESULT CNetFolder::_GetPathForItem(LPCIDNETRESOURCE pidn, LPTSTR pszPath)
- {
- *pszPath = 0;
- // loop down
- for (; !ILIsEmpty((LPCITEMIDLIST)pidn) ; pidn = (LPCIDNETRESOURCE)_ILNext((LPCITEMIDLIST)pidn))
- {
- if (NET_GetFlags(pidn) & SHID_JUNCTION) // \servershare or strike/sys
- {
- _GetPathForShare(pidn, pszPath);
- break; // below this we don't know about any of the PIDLs
- }
- else
- {
- NET_CopyResName(pidn, pszPath, MAX_PATH);
- }
- }
- return *pszPath ? S_OK : E_NOTIMPL;
- }
- HRESULT CNetFolder::_GetPathForItemW(LPCIDNETRESOURCE pidn, LPWSTR pszPath)
- {
- #ifdef UNICODE
- return _GetPathForItem(pidn, pszPath);
- #else // UNICODE
- TCHAR szPath[MAX_PATH];
- HRESULT hres = _GetPathForItem(pidn, szPath);
- if (SUCCEEDED(hres))
- SHTCharToUnicode(szPath, pszPath, MAX_PATH);
- else
- *pszPath = 0;
- return hres;
- #endif // UNICODE
- }
- // in:
- // pidl
- //
- // takes the last items and create a folder for it, assuming the first section is the
- // used to initialze. the riid and ppv are used to return an object.
- //
- HRESULT CNetFolder::_CreateFolderForItem(LPCITEMIDLIST pidl, LPCITEMIDLIST pidlTarget, LPCIDNETRESOURCE pidnForProvider, REFIID riid, void** ppv)
- {
- LPCITEMIDLIST pidlLast = ILFindLastID(pidl);
- LPCIDNETRESOURCE pidn = NET_IsValidID(pidlLast);
- if ( !pidn )
- return E_INVALIDARG;
- if (NET_IsRemoteFld(pidn))
- {
- // note: I think this is dead functionality. it was used in NT4 but we can't find
- // the impl of this CLSID_Remote anymore...
- IPersistFolder * ppf;
- HRESULT hres = SHCoCreateInstance(NULL, &CLSID_Remote, NULL, IID_IPersistFolder, (void **)&ppf);
- if (SUCCEEDED(hres))
- {
- hres = ppf->Initialize(pidl);
- if (SUCCEEDED(hres))
- hres = ppf->QueryInterface(riid, ppv);
- ppf->Release();
- }
- return hres;
- }
- else if (NET_GetFlags(pidn) & SHID_JUNCTION) // \servershare or strike/sys
- {
- PERSIST_FOLDER_TARGET_INFO pfti = {0};
- pfti.pidlTargetFolder = (LPITEMIDLIST)pidlTarget;
- _GetPathForItemW(pidn, pfti.szTargetParsingName);
- pfti.csidl = -1;
- pfti.dwAttributes = FILE_ATTRIBUTE_DIRECTORY; // maybe add system?
- return CFSFolder_CreateFolder(NULL, pidl, &pfti, riid, ppv);
- }
- else
- {
- TCHAR szPath[MAX_PATH];
- NET_CopyResName(pidn, szPath, ARRAYSIZE(szPath));
- return CNetFldr_CreateInstance(pidl, pidlTarget, NET_GetDisplayType(pidn), pidnForProvider, szPath, riid, ppv);
- }
- }
- // find the share part of a UNC
- // \servershare
- // return pointer to "share" or pointer to empty string if none
- LPCTSTR PathFindShareName(LPCTSTR pszUNC)
- {
- LPCTSTR psz = SkipServerSlashes(pszUNC);
- if (*psz)
- {
- psz = StrChr(psz + 1, TEXT('\'));
- if (psz)
- psz++;
- else
- psz = TEXT("");
- }
- return psz;
- }
- //
- // To be called back from within SHCreateEnumObjects
- //
- // lParam - LPDEFENUM
- // pvData - pointer to ENUMNETWORK constructed by CNetRoot_EnumObjects
- // ecid - enumeration command (event)
- // index - LPDEFENUM->iCur (unused)
- HRESULT CALLBACK CNetFolder::EnumCallBack(LPARAM lParam, void *pvData, UINT ecid, UINT index)
- {
- HRESULT hres = S_OK;
- ENUM_DATA *penet = (ENUM_DATA *)pvData;
- if (ecid == ECID_SETNEXTID)
- {
- // Time to stop enumeration?
- if (penet->dwRemote & RMF_STOP_ENUM)
- return S_FALSE; // Yes
- //
- // should we try and get the links enumerator?
- //
- if ( penet->dwRemote & RMF_GETLINKENUM )
- {
- CreateNetHoodShortcuts();
- IShellFolder2* psfNetHood;
- if (SUCCEEDED(penet->pnf->v_GetFileFolder(&psfNetHood)))
- psfNetHood->EnumObjects(NULL, penet->grfFlags, &penet->peunk);
- if (penet->peunk)
- penet->dwRemote |= RMF_SHOWLINKS;
- penet->dwRemote &= ~RMF_GETLINKENUM;
- }
- //
- // should we be showing the links?
- //
- if (penet->dwRemote & RMF_SHOWLINKS)
- {
- if (penet->peunk)
- {
- ULONG celtFetched;
- LPITEMIDLIST pidl;
- hres = penet->peunk->Next(1, &pidl, &celtFetched);
- if (hres == S_OK && celtFetched == 1)
- {
- ASSERT(pidl);
- CDefEnum_SetReturn(lParam, pidl);
- return S_OK; // Added link
- }
- }
- penet->dwRemote &= ~RMF_SHOWLINKS; // Done enumerating links
- }
- hres = S_OK;
- // Do we add the remote folder?
- // (Note: as a hack to ensure that the remote folder is added
- // to the 'hood despite what MPR says, RMF_SHOWREMOTE can be
- // set without RMF_CONTEXT set.)
- if ((penet->dwRemote & RMF_SHOWREMOTE) && !(penet->dwRemote & RMF_REMOTESHOWN))
- {
- // Yes
- // Only try to put the remote entry in once.
- penet->dwRemote |= RMF_REMOTESHOWN;
- // Is this not the Context container?
- // (See note above as to why we are asking this question.)
- if ( !(penet->dwRemote & RMF_CONTEXT) )
- {
- // Yes; stop after the next time
- penet->dwRemote |= RMF_STOP_ENUM;
- }
- // We have fallen thru because the remote services is not
- // installed.
- // Is this not the Context container AND the remote folder
- // is not installed?
- if ( !(penet->dwRemote & RMF_CONTEXT) )
- {
- // Yes; nothing else to enumerate
- return S_FALSE;
- }
- }
- if ( penet->dwRemote & RMF_FAKENETROOT )
- {
- if ( !(penet->dwRemote & RMF_ENTIRENETSHOWN) )
- {
- _CreateEntireNetwork(NULL, lParam); // fake entire net
- penet->dwRemote |= RMF_ENTIRENETSHOWN;
- }
- else
- {
- return S_FALSE; // no more to enumerate
- }
- }
- else
- {
- while (TRUE)
- {
- ULONG err = WN_SUCCESS;
- LPNETRESOURCE pnr;
- if (penet->iItem >= penet->cItems)
- {
- DWORD dwSize = SIZEOF(penet->szBuffer);
- // Figure that on average no item over 128 bytes...
- //penet->cItems = sizeof(penet->szBuffer) >> 7;
- penet->cItems = -1;
- penet->iItem = 0;
- err = WNetEnumResource(penet->hEnum, (DWORD*)&penet->cItems, penet->szBuffer, &dwSize);
- DebugMsg(DM_TRACE, TEXT("Net EnumCallback: err=%d Count=%d"),
- err, penet->cItems);
- }
- pnr = &penet->anr[penet->iItem++];
- // Output some debug messages to help us track
- #ifdef NET_TRACE
- DebugMsg(DM_TRACE, TEXT("Net EnumCallback: err=%d s=%d, t=%d, dt=%d, u=%d, %s"),
- err, pnr->dwScope, pnr->dwType, pnr->dwDisplayType,
- pnr->dwUsage, pnr->lpRemoteName ? pnr->lpRemoteName : TEXT("[NULL]"));
- #endif //NET_TRACE
- // Note: the <= below is correct as we already incremented the index...
- if (err == WN_SUCCESS && (penet->iItem <= penet->cItems))
- {
- // decide if the thing is a folder or not
- ULONG grfFlagsItem = ((pnr->dwUsage & RESOURCEUSAGE_CONTAINER) ||
- (pnr->dwType == RESOURCETYPE_DISK) ||
- (pnr->dwType == RESOURCETYPE_ANY)) ?
- SHCONTF_FOLDERS : SHCONTF_NONFOLDERS;
- // If this is the context enumeration, we want to insert the
- // Remote Services after the first container.
- // Remember that we need to return the Remote Services
- // in the next iteration.
- //
- if ((pnr->dwUsage & RESOURCEUSAGE_CONTAINER) &&
- (penet->dwRemote & RMF_CONTEXT))
- {
- penet->dwRemote |= RMF_SHOWREMOTE;
- }
- if ((penet->pnf->_uDisplayType == RESOURCEDISPLAYTYPE_SERVER) &&
- (penet->grfFlags & SHCONTF_SHAREABLE))
- {
- // filter out ADMIN$ and IPC$, lame, based on str len
- if (lstrlen(PathFindShareName(pnr->lpRemoteName)) > 2)
- grfFlagsItem = 0;
- }
- // Check if we found requested type of net resource.
- if (penet->grfFlags & grfFlagsItem)
- {
- // Yes.
- ASSERT(lParam); // else we leak here
- if ( SUCCEEDED(_NetResToIDList(pnr, FALSE, TRUE, (penet->grfFlags & SHCONTF_NONFOLDERS), NULL, lParam)) )
- {
- break;
- }
- }
- }
- else if (err == WN_NO_MORE_ENTRIES)
- {
- hres = S_FALSE; // no more element
- break;
- }
- else
- {
- DebugMsg(DM_ERROR, TEXT("sh ER - WNetEnumResource failed (%lx)"), err);
- hres = E_FAIL;
- break;
- }
- }
- }
- }
- else if (ecid == ECID_RELEASE)
- {
- penet->pnf->Release(); // release the "this" ptr we have
- if (penet->peunk)
- penet->peunk->Release();
- if ( penet->hEnum )
- WNetCloseEnum(penet->hEnum);
- LocalFree((HLOCAL)penet);
- }
- return hres;
- }
- // get the provider for an item or the folder itself. since some items don't have the
- // provider stored we fall back to the folder to get the provider in that case
- //
- // in:
- // pidn item to get provider for. if NULL get provider for the folder
- //
- // returns:
- // NULL no provider in the item or the folder
- // non NULL address of passed in buffer
- LPCTSTR CNetFolder::_GetProvider(LPCIDNETRESOURCE pidn, LPTSTR pszProvider, UINT cchProvider)
- {
- if (pidn && NET_CopyProviderName(pidn, pszProvider, cchProvider))
- return pszProvider;
- if ( _pidnForProvider )
- {
- NET_CopyProviderName( _pidnForProvider, pszProvider, cchProvider );
- return pszProvider;
- }
- return NULL;
- }
- // construct a net idlist either copying the existing data from a pidl or
- // from a NETRESOURCE structure
- HRESULT CNetFolder::_CreateNetIDList(LPIDNETRESOURCE pidnIn,
- LPCTSTR pszName, LPCTSTR pszProvider, LPCTSTR pszComment,
- LPITEMIDLIST *ppidl)
- {
- LPBYTE pb;
- UINT cbmkid = SIZEOF(IDNETRESOURCE)-SIZEOF(CHAR);
- UINT cchName, cchProvider, cchComment, cbProviderType = 0;
- LPIDNETRESOURCE pidn;
- WORD wNetType = 0;
- BOOL fUnicode = FALSE;
- UINT cchAnsiName, cchAnsiProvider, cchAnsiComment;
- CHAR szAnsiName[MAX_PATH], szAnsiProvider[MAX_PATH], szAnsiComment[MAX_PATH];
- ASSERT(ppidl != NULL);
- *ppidl = NULL;
- if (!pszName)
- pszName = c_szNULL; // For now put in an empty string...
- if ( pszProvider )
- cbProviderType += SIZEOF(WORD);
- #ifdef WINNT
- //
- // Win9x shipped with one set of provider name which are
- // different on NT. Therefore lets convert the NT one to
- // something that Win9x can understand.
- //
- if (pszProvider)
- {
- DWORD dwRes, dwType;
- INT i;
- cbProviderType = SIZEOF(WORD);
- dwRes = WNetGetProviderType(pszProvider, &dwType);
- if (dwRes == WN_SUCCESS)
- {
- wNetType = HIWORD(dwType);
- for (i=0; i < c_cProviders; i++)
- {
- if (c_rgProviderMap[i].wNetType == wNetType)
- {
- pszProvider = c_rgProviderMap[i].lpName;
- break;
- }
- }
- }
- }
- #endif
- // compute the string lengths ready to build an IDLIST
- cchName = lstrlen(pszName)+1;
- cchProvider = pszProvider ? lstrlen(pszProvider)+1 : 0;
- cchComment = pszComment ? lstrlen(pszComment)+1 : 0;
- cchAnsiName = 0;
- cchAnsiProvider = 0;
- cchAnsiComment = 0;
- fUnicode = !DoesStringRoundTrip(pszName, szAnsiName, ARRAYSIZE(szAnsiProvider));
- cchAnsiName = lstrlenA(szAnsiName)+1;
- if ( pszProvider )
- {
- fUnicode |= !DoesStringRoundTrip(pszProvider, szAnsiProvider, ARRAYSIZE(szAnsiProvider));
- cchAnsiProvider = lstrlenA(szAnsiProvider)+1;
- }
- if ( pszComment )
- {
- fUnicode |= !DoesStringRoundTrip(pszComment, szAnsiComment, ARRAYSIZE(szAnsiComment));
- cchAnsiComment = lstrlenA(szAnsiComment)+1;
- }
- // allocate and fill the IDLIST header
- cbmkid += cbProviderType+cchAnsiName + cchAnsiProvider + cchAnsiComment;
- if ( fUnicode )
- cbmkid += (SIZEOF(WCHAR)*(cchName+cchProvider+cchComment));
- pidn = (LPIDNETRESOURCE)_ILCreate(cbmkid + SIZEOF(USHORT));
- if (!pidn)
- return E_OUTOFMEMORY;
- pidn->cb = (WORD)cbmkid;
- pidn->bFlags = pidnIn->bFlags;
- pidn->uType = pidnIn->uType;
- pidn->uUsage = pidnIn->uUsage;
- if (pszProvider)
- pidn->uUsage |= NET_HASPROVIDER;
- if (pszComment)
- pidn->uUsage |= NET_HASCOMMENT;
- pb = (LPBYTE) pidn->szNetResName;
- //
- // write the ANSI strings into the IDLIST
- //
- StrCpyA((PSTR) pb, szAnsiName);
- pb += cchAnsiName;
- if ( pszProvider )
- {
- StrCpyA((PSTR) pb, szAnsiProvider);
- pb += cchAnsiProvider;
- }
- if ( pszComment )
- {
- StrCpyA((PSTR) pb, szAnsiComment);
- pb += cchAnsiComment;
- }
- // if we are going to be UNICODE then lets write those strings also.
- // Note that we must use unaligned string copies since the is no
- // promse that the ANSI strings will have an even number of characters
- // in them.
- #ifdef UNICODE
- if ( fUnicode )
- {
- pidn->uUsage |= NET_UNICODE;
- ualstrcpyW((UNALIGNED WCHAR *)pb, pszName);
- pb += cchName*SIZEOF(WCHAR);
- if ( pszProvider )
- {
- ualstrcpyW((UNALIGNED WCHAR *)pb, pszProvider);
- pb += cchProvider*SIZEOF(WCHAR);
- }
- if ( pszComment )
- {
- ualstrcpyW((UNALIGNED WCHAR *)pb, pszComment);
- pb += cchComment*SIZEOF(WCHAR);
- }
- }
- #endif
- //
- // and the trailing provider type
- //
- if (cbProviderType)
- {
- // Store the provider type
- pb = (LPBYTE)pidn + pidn->cb - SIZEOF(WORD);
- *((UNALIGNED WORD *)pb) = wNetType;
- }
- *ppidl = (LPITEMIDLIST)pidn;
- return S_OK;
- }
- // wrapper for converting a NETRESOURCE into an IDLIST via _CreateNetPidl
- HRESULT CNetFolder::_NetResToIDList(NETRESOURCE *pnr,
- BOOL fAllowNull, BOOL fKeepProviderName, BOOL fKeepComment,
- LPITEMIDLIST *ppidl, LPARAM lParam)
- {
- NETRESOURCE nr = *pnr;
- LPITEMIDLIST pidl;
- LPTSTR pszName, pszProvider, pszComment;
- IDNETRESOURCE idn;
- LPTSTR psz;
- if ( ppidl )
- *ppidl = NULL;
- switch (pnr->dwDisplayType)
- {
- case RESOURCEDISPLAYTYPE_NETWORK:
- pszName = pnr->lpProvider;
- break;
- case RESOURCEDISPLAYTYPE_ROOT:
- pszName =pnr->lpComment;
- break;
- default:
- {
- // check the name for a NULL string (returned sometimes in NT4 domains)
- pszName = pnr->lpRemoteName;
- if ( !fAllowNull && !*pszName )
- return E_FAIL;
- // pretty stuff after the "\"
- psz = (LPTSTR)SkipServerSlashes(pnr->lpRemoteName);
- if ( *psz )
- PathMakePretty(psz);
- break;
- }
- }
- pszProvider = fKeepProviderName ? nr.lpProvider:NULL;
- pszComment = fKeepComment ? nr.lpComment:NULL;
- idn.bFlags = (BYTE)(SHID_NET | (pnr->dwDisplayType & 0x0f));
- idn.uType = (BYTE)(pnr->dwType & 0x0f);
- idn.uUsage = (BYTE)(pnr->dwUsage & 0x0f);
- // Is the current resource a share of some kind and not a container
- if ((pnr->dwDisplayType == RESOURCEDISPLAYTYPE_SHARE || pnr->dwDisplayType == RESOURCEDISPLAYTYPE_SHAREADMIN) &&
- !(pnr->dwUsage & RESOURCEUSAGE_CONTAINER))
- {
- // If so, remember to delegate children of this folder to FSFolder
- idn.bFlags |= (BYTE)SHID_JUNCTION; // \servershare type thing
- }
- HRESULT hres = _CreateNetIDList(&idn, pszName, pszProvider, pszComment, &pidl);
- if ( SUCCEEDED(hres) )
- {
- if ( lParam )
- CDefEnum_SetReturn(lParam, (LPITEMIDLIST)pidl);
- if ( ppidl )
- *ppidl = pidl;
- }
- return hres;
- }
- HRESULT CNetFolder::_CreateEntireNetwork(LPITEMIDLIST *ppidl, LPARAM lParam)
- {
- TCHAR szPath[MAX_PATH];
- NETRESOURCE nr = {0};
- // We need to add the Rest of network entry. This is psuedo
- // bogus, as we should either always do it ourself or have
- // MPR always do it, but here it goes...
- LoadString(HINST_THISDLL, IDS_RESTOFNET, szPath, ARRAYSIZE(szPath));
- nr.dwDisplayType = RESOURCEDISPLAYTYPE_ROOT;
- nr.dwType = RESOURCETYPE_ANY;
- nr.dwUsage = RESOURCEUSAGE_CONTAINER;
- nr.lpComment = szPath;
- return _NetResToIDList(&nr, TRUE, FALSE, FALSE, ppidl, lParam); // allows NULL namess
- }
- //===========================================================================
- //
- // To be called back from within CDefFolderMenu
- //
- STDAPI CNetwork_DFMCallBackBG(IShellFolder *psf, HWND hwnd,
- IDataObject *pdtobj, UINT uMsg,
- WPARAM wParam, LPARAM lParam)
- {
- HRESULT hres = S_OK;
- CNetFolder* pThis;
- if (FAILED(psf->QueryInterface(CLSID_CNetFldr, (void**) &pThis)))
- return E_UNEXPECTED;
- switch(uMsg)
- {
- case DFM_MERGECONTEXTMENU:
- if (!(wParam & (CMF_VERBSONLY | CMF_DVFILE)))
- {
- CDefFolderMenu_MergeMenu(HINST_THISDLL, POPUP_NETWORK_BACKGROUND,
- POPUP_NETWORK_POPUPMERGE, (LPQCMINFO)lParam);
- }
- break;
- case DFM_GETHELPTEXT:
- LoadStringA(HINST_THISDLL, LOWORD(wParam) + IDS_MH_FSIDM_FIRST, (LPSTR)lParam, HIWORD(wParam));
- break;
- case DFM_GETHELPTEXTW:
- LoadStringW(HINST_THISDLL, LOWORD(wParam) + IDS_MH_FSIDM_FIRST, (LPWSTR)lParam, HIWORD(wParam));
- break;
- case DFM_INVOKECOMMAND:
- switch(wParam)
- {
- case FSIDM_SORTBYNAME:
- case FSIDM_SORTBYCOMMENT:
- ShellFolderView_ReArrange(hwnd, (wParam == FSIDM_SORTBYNAME) ? 0 : 1);
- break;
- case FSIDM_PROPERTIESBG:
- hres = SHPropertiesForPidl(hwnd, pThis->_pidl, (LPCTSTR)lParam);
- break;
- default:
- // This is one of view menu items, use the default code.
- hres = S_FALSE;
- break;
- }
- break;
- default:
- hres = E_NOTIMPL;
- break;
- }
- return hres;
- }
- //===========================================================================
- //
- // To be called back from within CDefFolderMenu
- //
- STDAPI CNetFolder::DFMCallBack(IShellFolder* psf, HWND hwnd,
- IDataObject* pdtobj, UINT uMsg,
- WPARAM wParam, LPARAM lParam)
- {
- HRESULT hres = S_OK;
- switch(uMsg)
- {
- case DFM_MERGECONTEXTMENU:
- if (pdtobj)
- {
- STGMEDIUM medium;
- LPIDA pida;
- LPQCMINFO pqcm = (LPQCMINFO)lParam;
- UINT idCmdBase = pqcm->idCmdFirst; // must be called before merge
- CDefFolderMenu_MergeMenu(HINST_THISDLL, POPUP_NETWORK_ITEM, 0, pqcm);
- pida = DataObj_GetHIDA(pdtobj, &medium);
- if (pida)
- {
- if (pida->cidl > 0)
- {
- LPIDNETRESOURCE pidn = (LPIDNETRESOURCE)IDA_GetIDListPtr(pida, 0);
- // Only enable "connect" command if the first one is a share.
- if (pidn)
- {
- ULONG rgf = 0;
- if( NET_GetFlags(pidn) & SHID_JUNCTION &&
- !SHRestricted( REST_NONETCONNECTDISCONNECT ) )
- {
- EnableMenuItem(pqcm->hmenu, idCmdBase + FSIDM_CONNECT,
- MF_CHECKED | MF_BYCOMMAND);
- }
- }
- }
- HIDA_ReleaseStgMedium(pida, &medium);
- }
- }
- break;
- case DFM_GETHELPTEXT:
- LoadStringA(HINST_THISDLL, LOWORD(wParam) + IDS_MH_FSIDM_FIRST, (LPSTR)lParam, HIWORD(wParam));
- break;
- case DFM_GETHELPTEXTW:
- LoadStringW(HINST_THISDLL, LOWORD(wParam) + IDS_MH_FSIDM_FIRST, (LPWSTR)lParam, HIWORD(wParam));
- break;
- case DFM_INVOKECOMMAND:
- switch(wParam)
- {
- case DFM_CMD_PROPERTIES:
- SHLaunchPropSheet(_PropertiesThreadProc, pdtobj, (LPCTSTR)lParam, psf, NULL);
- break;
- case DFM_CMD_LINK:
- {
- hres = S_FALSE; // do the default shortcut stuff
- CNetFolder* pThis;
- if (SUCCEEDED(psf->QueryInterface(CLSID_CNetFldr, (void**) &pThis)))
- {
- // net hood special case. in this case we want to create the shortuct
- // in the net hood, not offer to put this on the desktop
- IShellFolder2* psfFiles;
- if (SUCCEEDED(pThis->v_GetFileFolder(&psfFiles)))
- {
- FS_CreateLinks(hwnd, psfFiles, pdtobj, (LPCTSTR)lParam, CMIC_MASK_FLAG_NO_UI);
- hres = S_OK; // we created the links
- }
- }
- }
- break;
- case FSIDM_CONNECT:
- if (pdtobj)
- {
- STGMEDIUM medium;
- LPIDA pida = DataObj_GetHIDA(pdtobj, &medium);
- if (pida)
- {
- UINT iidl;
- for (iidl = 0; iidl < pida->cidl; iidl++)
- {
- LPIDNETRESOURCE pidn = (LPIDNETRESOURCE)IDA_GetIDListPtr(pida, iidl);
- // Only execute "connect" on shares.
- if (NET_GetFlags(pidn) & SHID_JUNCTION)
- {
- TCHAR szName[MAX_PATH];
- LPTSTR pszName = NET_CopyResName(pidn, szName, ARRAYSIZE(szName));
- DWORD err = SHStartNetConnectionDialog(hwnd, pszName, RESOURCETYPE_DISK);
- DebugMsg(DM_TRACE, TEXT("CNet FSIDM_CONNECT (%s, %x)"), szName, err);
- // events will get generated automatically
- }
- }
- HIDA_ReleaseStgMedium(pida, &medium);
- }
- }
- break;
- default:
- // This is one of view menu items, use the default code.
- hres = S_FALSE;
- break;
- }
- break;
- default:
- hres = E_NOTIMPL;
- break;
- }
- return hres;
- }
- STDAPI CNetFolder::PrinterDFMCallBack(IShellFolder* psf, HWND hwnd,
- IDataObject* pdtobj, UINT uMsg,
- WPARAM wParam, LPARAM lParam)
- {
- HRESULT hres = S_OK;
- switch(uMsg)
- {
- case DFM_MERGECONTEXTMENU:
- //
- // Returning S_FALSE indicates no need to get verbs from
- // extensions.
- //
- hres = S_FALSE;
- break;
- // if anyone hooks our context menu, we want to be on top (Open)
- case DFM_MERGECONTEXTMENU_TOP:
- if (pdtobj)
- {
- LPQCMINFO pqcm = (LPQCMINFO)lParam;
- // insert verbs
- CDefFolderMenu_MergeMenu(HINST_THISDLL, POPUP_NETWORK_PRINTER, 0, pqcm);
- #ifndef WINNT
- //
- // WINNT does not support Capturing print ports, so no
- // need to check.
- //
- if (!(GetSystemMetrics(SM_NETWORK) & RNC_NETWORKS))
- {
- // remove "map" if no net
- DeleteMenu(pqcm->hmenu, pqcm->idCmdFirst + FSIDM_CONNECT_PRN, MF_BYCOMMAND);
- }
- #endif
- SetMenuDefaultItem(pqcm->hmenu, 0, MF_BYPOSITION);
- }
- break;
- case DFM_GETHELPTEXT:
- LoadStringA(HINST_THISDLL, LOWORD(wParam) + IDS_MH_FSIDM_FIRST, (LPSTR)lParam, HIWORD(wParam));
- break;
- case DFM_GETHELPTEXTW:
- LoadStringW(HINST_THISDLL, LOWORD(wParam) + IDS_MH_FSIDM_FIRST, (LPWSTR)lParam, HIWORD(wParam));
- break;
- case DFM_INVOKECOMMAND:
- switch(wParam)
- {
- case DFM_CMD_PROPERTIES:
- SHLaunchPropSheet(_PropertiesThreadProc, pdtobj, (LPCTSTR)lParam, psf, NULL);
- break;
- case DFM_CMD_LINK:
- // do the default create shortcut crap
- return S_FALSE;
- case FSIDM_OPENPRN:
- case FSIDM_NETPRN_INSTALL:
- #ifndef WINNT
- case FSIDM_CONNECT_PRN:
- #endif
- {
- STGMEDIUM medium;
- LPIDA pida = DataObj_GetHIDA(pdtobj, &medium);
- if (pida)
- {
- UINT action, i;
- // set up the operation we are going to perform
- switch (wParam) {
- case FSIDM_OPENPRN:
- action = PRINTACTION_OPENNETPRN;
- break;
- case FSIDM_NETPRN_INSTALL:
- action = PRINTACTION_NETINSTALL;
- break;
- default: // FSIDM_CONNECT_PRN
- action = (UINT)-1;
- break;
- }
- for (i = 0; i < pida->cidl; i++)
- {
- LPIDNETRESOURCE pidn = (LPIDNETRESOURCE)IDA_GetIDListPtr(pida, i);
- // Only execute command for a net print share
- if (_IsPrintShare(pidn))
- {
- TCHAR szName[MAX_PATH];
- NET_CopyResName(pidn,szName,ARRAYSIZE(szName));
- #ifndef WINNT // PRINTQ
- if (action == (UINT)-1)
- {
- SHNetConnectionDialog(hwnd, szName, RESOURCETYPE_PRINT);
- }
- else
- #endif
- {
- SHInvokePrinterCommand(hwnd, action, szName, NULL, FALSE);
- }
- }
- } // for (i...
- HIDA_ReleaseStgMedium(pida, &medium);
- } // if (medium.hGlobal)
- break;
- } // case ID_NETWORK_PRINTER_INSTALL, FSIDM_CONNECT_PRN
- } // switch(wparam)
- break;
- default:
- hres = E_NOTIMPL;
- break;
- }
- return hres;
- }
- //
- // REVIEW: Almost identical code in fstreex.c
- //
- DWORD CALLBACK CNetFolder::_PropertiesThreadProc(void *pv)
- {
- PROPSTUFF* pps = (PROPSTUFF *)pv;
- CNetFolder* pThis;
- if (SUCCEEDED(pps->psf->QueryInterface(CLSID_CNetFldr, (void**) &pThis)))
- {
- STGMEDIUM medium;
- LPIDA pida = DataObj_GetHIDA(pps->pdtobj, &medium);
- if (pida)
- {
- // Yes, do context menu.
- HKEY ahkeys[NKID_COUNT];
- HRESULT hres = pThis->_OpenKeys((LPCIDNETRESOURCE)IDA_GetIDListPtr(pida, 0), ahkeys);
- if (SUCCEEDED(hres))
- {
- LPTSTR pszCaption = SHGetCaption(medium.hGlobal);
- SHOpenPropSheet(pszCaption, ahkeys, ARRAYSIZE(ahkeys),
- &CLSID_ShellNetDefExt,
- pps->pdtobj, NULL, pps->pStartPage);
- if (pszCaption)
- SHFree(pszCaption);
- SHRegCloseKeys(ahkeys, ARRAYSIZE(ahkeys));
- }
- HIDA_ReleaseStgMedium(pida, &medium);
- }
- }
- return S_OK;
- }
- STDAPI CNetFolder::GAOCallbackNet(IShellFolder2* psf, LPCITEMIDLIST pidl, ULONG* prgfInOut)
- {
- LPCIDNETRESOURCE pidn = (LPCIDNETRESOURCE)pidl;
- ULONG rgfOut = SFGAO_CANLINK | SFGAO_HASPROPSHEET | SFGAO_HASSUBFOLDER |
- SFGAO_FOLDER | SFGAO_FILESYSANCESTOR | SFGAO_CANMONIKER;
- if (NET_GetFlags(pidn) & SHID_JUNCTION)
- {
- if ((NET_GetType(pidn) == RESOURCETYPE_DISK) ||
- (NET_GetType(pidn) == RESOURCETYPE_ANY))
- rgfOut |= SFGAO_FILESYSTEM | SFGAO_DROPTARGET;
- else
- rgfOut &= ~SFGAO_FILESYSANCESTOR;
- }
- if (_IsPrintShare(pidn))
- {
- rgfOut |= SFGAO_DROPTARGET; // for drag and drop printing
- rgfOut &= ~(SFGAO_FILESYSANCESTOR | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_CANMONIKER | SFGAO_HASSUBFOLDER);
- }
- if (NET_IsRemoteFld(pidn))
- {
- rgfOut &= ~(SFGAO_FILESYSANCESTOR | SFGAO_FILESYSTEM | SFGAO_CANMONIKER);
- }
- *prgfInOut = rgfOut;
- return S_OK;
- }
- // This is only used by the CNetRootFolder subclass, but because we can only QI for
- // CLSID_NetFldr, and we can't access protected members of any CNetFolder instance
- // from a member function of CNetRootFolder, we'll make it belong to CNetFolder
- HRESULT CALLBACK CNetFolder::GAOCallbackNetRoot(IShellFolder2* psf, LPCITEMIDLIST pidl, ULONG* prgfInOut)
- {
- CNetFolder* pNetF;
- HRESULT hres = psf->QueryInterface(CLSID_CNetFldr, (void**) &pNetF);
- if (SUCCEEDED(hres))
- {
- if (NET_IsValidID(pidl))
- {
- hres = pNetF->CNetFolder::GetAttributesOf(1, &pidl, prgfInOut);
- }
- else
- {
- IShellFolder2* psfFiles;
- hres = pNetF->v_GetFileFolder(&psfFiles);
- if (SUCCEEDED(hres))
- hres = psfFiles->GetAttributesOf(1, &pidl, prgfInOut);
- }
- }
- return hres;
- }
- // this is called by netfind.c
- STDMETHODIMP CNetwork_EnumSearches(IShellFolder2* psf2, LPENUMEXTRASEARCH *ppenum)
- {
- HRESULT hres;
- if (NULL != psf2)
- {
- CNetFolder* pNetF;
- hres = psf2->QueryInterface(CLSID_CNetFldr, (void**) &pNetF);
- if (SUCCEEDED(hres))
- hres = pNetF->EnumSearches(ppenum);
- }
- else
- {
- hres = E_INVALIDARG;
- }
- return hres;
- }
- // given the resulting ppidl and a pszRest continue to parse through and add in the remainder
- // of the file system path.
- HRESULT CNetFolder::_ParseRest(LPBC pbc, LPCWSTR pszRest, LPITEMIDLIST* ppidl, DWORD* pdwAttributes)
- {
- HRESULT hres = S_OK;
- if ( pszRest && pszRest[0] )
- {
- IShellFolder* psfBind;
- // need to QI to get the agregated case
- hres = QueryInterface(IID_IShellFolder, (void**) &psfBind);
- if (SUCCEEDED(hres))
- {
- IShellFolder* psfSub;
- // pass down to pick off stuff below including regitems and file names
- hres = psfBind->BindToObject(*ppidl, NULL, IID_IShellFolder, (void**) &psfSub);
- if (SUCCEEDED(hres))
- {
- LPITEMIDLIST pidlSubDir;
- // skip leading if there is one present
- if ( pszRest[0] == L'\' )
- pszRest++;
- hres = psfSub->ParseDisplayName(NULL, pbc, (LPWSTR)pszRest, NULL, &pidlSubDir, pdwAttributes);
- if (SUCCEEDED(hres))
- {
- hres = SHILAppend(pidlSubDir, ppidl);
- }
- psfSub->Release();
- }
- psfBind->Release();
- }
- }
- else
- {
- if ( pdwAttributes )
- {
- LPCITEMIDLIST apidlLast[1] = { ILFindLastID(*ppidl) };
- hres = GetAttributesOf(1, apidlLast, pdwAttributes);
- }
- }
- return hres;
- }
- // handle parsing a net name into a IDLIST structure that represents that NETRESOURCE
- // up to the root. we loop using each NETRESOURCE and calling NetResourceGetParent,
- // we assume that if we receive a ERROR_BAD_NET_NAME we are done.
- HRESULT CNetFolder::_NetResToIDLists(NETRESOURCE *pnr, DWORD dwbuf, LPITEMIDLIST *ppidl)
- {
- HRESULT hres = S_OK;
- do
- {
- LPITEMIDLIST pidlT;
- hres = _NetResToIDList(pnr, FALSE, TRUE, TRUE, &pidlT, 0);
- if ( SUCCEEDED(hres) )
- {
- hres = SHILPrepend(pidlT, ppidl);
- if ( FAILED(hres) )
- {
- ILFree(pidlT);
- }
- else
- {
- // lets get the resource parent, if the display type is ROOT
- // then there is no point as we are already at the top of the
- // chain, calling for root will just fail (or on Win9x cause
- // us to loop forever, eat all the stack and die!).
- if ( (pnr->dwDisplayType == RESOURCEDISPLAYTYPE_NETWORK) ||
- (pnr->dwDisplayType == RESOURCEDISPLAYTYPE_ROOT) ||
- (WNetGetResourceParent(pnr, pnr, &dwbuf) != WN_SUCCESS) )
- {
- break;
- }
- }
- }
- }
- while ( SUCCEEDED(hres) );
- return hres;
- }
- // get the parsable network name from the object
- LPTSTR CNetFolder::_GetNameForParsing(LPCWSTR pwszName, LPTSTR pszBuffer, INT cchBuffer, LPTSTR *ppszRegItem)
- {
- LPTSTR pszRegItem = NULL;
- INT cSlashes = 0;
- *ppszRegItem = NULL;
- SHUnicodeToTChar(pwszName, pszBuffer, cchBuffer);
- // remove the trailing if there is one, NTLanMan barfs if we pass a string containing it
- INT cchPath = lstrlen(pszBuffer)-1;
- if ( (cchPath > 2) && (pszBuffer[cchPath] == TEXT('\')) )
- pszBuffer[cchPath] = TEXT('');
- // lets walk the name, look for :: squence to signify the start of a regitem name,
- // and if the number of slashes is > 2 then we should bail
- LPTSTR pszUNC = pszBuffer+2;
- while ( pszUNC && *pszUNC && (cSlashes < 2) )
- {
- if ( (pszUNC[0] == TEXT('\')) &&
- (pszUNC[1] == TEXT(':')) && (pszUNC[2] == TEXT(':')) )
- {
- *ppszRegItem = pszUNC;
- break;
- }
- pszUNC = StrChr(pszUNC+1, TEXT('\'));
- cSlashes++;
- }
- return pszUNC;
- }
- HRESULT CNetFolder::_ParseNetName(HWND hwnd, LPBC pbc,
- LPCWSTR pwszName, ULONG* pchEaten,
- LPITEMIDLIST *ppidl, DWORD *pdwAttrib)
- {
- HRESULT hres;
- NETRESOURCE nr = { 0 };
- struct _NRTEMP
- {
- NETRESOURCE nr;
- TCHAR szBuffer[1024];
- } nrOut = { 0 };
- TCHAR szPath[MAX_PATH];
- TCHAR szTemp[MAX_PATH];
- DWORD dwres, dwbuf = SIZEOF(nrOut.szBuffer);
- LPTSTR pszServerShare = NULL;
- LPTSTR pszRestOfName = NULL;
- LPTSTR pszFakeRestOfName = NULL;
- LPTSTR pszRegItem = NULL;
- // validate the name before we start cracking it...
- if ( !PathIsUNCW(pwszName) )
- return HRESULT_FROM_WIN32(ERROR_BAD_NET_NAME);
- pszFakeRestOfName = _GetNameForParsing(pwszName, szPath, ARRAYSIZE(szPath), &pszRegItem);
- nr.lpRemoteName = szPath;
- nr.lpProvider = (LPTSTR)_GetProvider(NULL, szTemp, ARRAYSIZE(szTemp));
- nr.dwType = RESOURCETYPE_ANY;
- // if there is a regitem string then we must truncate at it, otherwise MPR will
- // try and parse it as part of the name
- if ( pszRegItem )
- *pszRegItem = TEXT('');
- #ifdef WINNT
- dwres = WNetGetResourceInformation(&nr, &nrOut.nr, &dwbuf, &pszRestOfName);
- if ( WN_SUCCESS != dwres )
- #endif
- {
- TCHAR cT;
- LPTSTR pszTemp;
- // truncate the string at the \servershare to try and parse the name,
- // note at this point if MPR resolves the alias on a Novel server this could
- // get very confusing (eg. \strikefoobah may resolve to \stringbla,
- // yet our concept of what pszRestOfName will be wrong!
- if ( pszFakeRestOfName )
- {
- cT = *pszFakeRestOfName;
- *pszFakeRestOfName = TEXT('');
- }
- dwres = WNetGetResourceInformation(&nr, &nrOut.nr, &dwbuf, &pszTemp);
- if ( dwres != WN_SUCCESS )
- {
- // we failed to get the net connection information using the truncated
- // string, therefore lets try and add a connection. if that works
- // then we can assume that the connection exists, and we should
- // just fake up a NR output structure.
- dwres = WNetAddConnection3(NULL, &nr, NULL, NULL, 0);
- if ( dwres == WN_SUCCESS )
- {
- nrOut.nr = nr;
- nrOut.nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
- nrOut.nr.dwUsage = RESOURCEUSAGE_CONNECTABLE;
- StrCpy(szTemp, nrOut.nr.lpRemoteName); // copy away the \servershare string
- nrOut.nr.lpRemoteName = szTemp;
- }
- }
- if ( pszFakeRestOfName )
- *pszFakeRestOfName = cT;
- pszRestOfName = pszFakeRestOfName;
- }
- if ( WN_SUCCESS == dwres )
- {
- WCHAR wszRestOfName[MAX_PATH] = { 0 };
- if ( pszRestOfName )
- SHTCharToUnicode(pszRestOfName, wszRestOfName, ARRAYSIZE(wszRestOfName));
- // assume we are truncating at the regitem and parsing through
- if ( pszRegItem )
- pszRestOfName = pszRegItem;
- // attempt to convert the NETRESOURCE to a string to IDLISTS by walking the
- // parents, then add in Entire Network
- hres = _NetResToIDLists(&nrOut.nr, dwbuf, ppidl);
- if ( SUCCEEDED(hres) )
- {
- LPITEMIDLIST pidlT;
- hres = _CreateEntireNetwork(&pidlT, 0);
- if ( SUCCEEDED(hres) )
- {
- hres = SHILPrepend(pidlT, ppidl);
- if ( FAILED(hres) )
- ILFree(pidlT);
- }
- }
- // if we have a local string then lets continue to parse it by binding to
- // its parent folder, otherwise we just want to return the attributes
- if ( SUCCEEDED(hres) )
- hres = _ParseRest(pbc, wszRestOfName, ppidl, pdwAttrib);
- }
- else
- {
- hres = HRESULT_FROM_WIN32(dwres);
- }
- if ( FAILED(hres) )
- {
- ILFree(*ppidl);
- *ppidl = NULL;
- }
- return hres;
- }
- //
- // simple name parsing for the network paths. this makes big assumptions about the
- // \servershare format we are given, and the type of IDLISTs to return.
- //
- HRESULT CNetFolder::_AddUnknownIDList(DWORD dwDisplayType, LPITEMIDLIST *ppidl)
- {
- HRESULT hres = E_OUTOFMEMORY;
- NETRESOURCE nr = { 0 };
- LPITEMIDLIST pidlT;
- nr.dwScope = RESOURCE_GLOBALNET;
- nr.dwDisplayType = dwDisplayType;
- nr.dwUsage = RESOURCEUSAGE_CONTAINER;
- nr.lpRemoteName = TEXT(""); // null name means fake item
- hres = _NetResToIDList(&nr, TRUE, FALSE, FALSE, &pidlT, 0);
- if ( SUCCEEDED(hres) )
- {
- hres = SHILAppend(pidlT, ppidl);
- if ( FAILED(hres) )
- ILFree(pidlT);
- }
- return hres;
- }
- HRESULT CNetFolder::_ParseSimple(LPBC pbc, LPWSTR pszName, LPITEMIDLIST* ppidl, DWORD* pdwAttributes)
- {
- HRESULT hres = S_OK;
- NETRESOURCE nr = {0};
- TCHAR szName[MAX_PATH];
- LPTSTR psz;
- LPWSTR pszSlash;
- LPCITEMIDLIST pidlMapped;
- LPITEMIDLIST pidlT;
- USES_CONVERSION;
- *ppidl = NULL;
- if ( !PathIsUNCW(pszName) )
- return E_INVALIDARG;
- // see if there is a UNC root mapping for this, if so we are golden
- SHUnicodeToTChar(pszName, szName, ARRAYSIZE(szName));
- psz = (LPTSTR)NPTMapNameToPidl(szName, &pidlMapped);
- if (pidlMapped)
- {
- hres = SHILClone(_ILNext(pidlMapped), ppidl); // skip the MyNetPlaces part
- pszSlash = (LPWSTR)pszName + (psz - szName);
- }
- else
- {
- // create the entire network IDLIST, provider and domain elements
- hres = _CreateEntireNetwork(ppidl, 0);
- #ifdef WINNT
- if ( SUCCEEDED(hres) )
- hres = _AddUnknownIDList(RESOURCEDISPLAYTYPE_NETWORK, ppidl);
- #endif
- if ( SUCCEEDED(hres) )
- hres = _AddUnknownIDList(RESOURCEDISPLAYTYPE_DOMAIN, ppidl);
- // create the server IDLIST
- if ( SUCCEEDED(hres) )
- {
- pszSlash = StrChrW(pszName+2, L'\');
- if ( pszSlash )
- *pszSlash = L'';
- nr.dwScope = RESOURCE_GLOBALNET;
- nr.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER;
- nr.dwType = RESOURCETYPE_DISK;
- nr.dwUsage = RESOURCEUSAGE_CONTAINER;
- nr.lpRemoteName = W2T(pszName);
- hres = _NetResToIDList(&nr, FALSE, FALSE, FALSE, &pidlT, 0);
- if ( SUCCEEDED(hres) )
- hres = SHILAppend(pidlT, ppidl);
- if ( pszSlash )
- *pszSlash = L'\';
- // if we have a trailing then lets add in the share part of the IDLIST
- if ( SUCCEEDED(hres) && pszSlash )
- {
- pszSlash = StrChrW(pszSlash+1, L'\');
- if (pszSlash)
- *pszSlash = L'';
- nr.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE;
- nr.dwUsage = RESOURCEUSAGE_CONNECTABLE;
- nr.lpRemoteName = W2T(pszName);
- hres = _NetResToIDList(&nr, FALSE, FALSE, FALSE, &pidlT, 0);
- if ( SUCCEEDED(hres) )
- hres = SHILAppend(pidlT, ppidl);
- if (pszSlash)
- *pszSlash = L'\';
- }
- }
- }
- if ( FAILED(hres) )
- {
- ILFree(*ppidl);
- *ppidl = NULL;
- }
- else
- {
- hres = _ParseRest(pbc, pszSlash, ppidl, pdwAttributes);
- }
- return hres;
- }
- // try parsing out the EntireNet or localised version. if we find that object then try and
- // parse through that to the regitems or other objects which live below. this inturn
- // will cause an instance of CNetFolder to be created to generate the other parsing names.
- //
- // returns:
- // S_FALSE - not rest of net, try something else
- // S_OK - was rest of net, use this
- // FAILED(hres) - error result, return
- HRESULT CNetRootFolder::_TryParseEntireNet(HWND hwnd, LPBC pbc, WCHAR *pwszName, LPITEMIDLIST *ppidl, DWORD *pdwAttributes)
- {
- HRESULT hres = S_FALSE; // skip, not rest of net
- *ppidl = NULL;
- if ( !PathIsUNCW(pwszName) )
- {
- const WCHAR szEntireNetwork[] = L"EntireNetwork";
- WCHAR szRestOfNet[128];
- INT cchRestOfNet = LoadStringW(HINST_THISDLL, IDS_RESTOFNET, szRestOfNet, ARRAYSIZE(szRestOfNet));
- BOOL fRestOfNet = !StrCmpNIW(szRestOfNet, pwszName, cchRestOfNet);
- if ( !fRestOfNet && !StrCmpNIW(szEntireNetwork, pwszName, ARRAYSIZE(szEntireNetwork)-1) )
- {
- fRestOfNet = TRUE;
- cchRestOfNet = ARRAYSIZE(szEntireNetwork)-1;
- }
- if ( fRestOfNet )
- {
- hres = _CreateEntireNetwork(ppidl, 0);
- if (SUCCEEDED(hres))
- {
- if (pdwAttributes)
- GetAttributesOf(1, (LPCITEMIDLIST *)ppidl, pdwAttributes);
- hres = S_OK;
- }
- //
- // if we find extra stuff after the name then lets bind and continue the parsing
- // from there on. this is needed so the we can access regitems burried inside
- // entire net.
- //
- // eg: EntireNetwork\::{clsid}
- //
- if ( SUCCEEDED(hres) &&
- (pwszName[cchRestOfNet] == L'\') && pwszName[cchRestOfNet+1] )
- {
- IShellFolder *psfRestOfNet;
- hres = BindToObject(*ppidl, NULL, IID_IShellFolder, (void **)&psfRestOfNet);
- if ( SUCCEEDED(hres) )
- {
- LPITEMIDLIST pidl;
- hres = psfRestOfNet->ParseDisplayName(hwnd, pbc,
- pwszName+cchRestOfNet+1,
- NULL,
- &pidl,
- pdwAttributes);
- if ( SUCCEEDED(hres) )
- hres = SHILAppend(pidl, ppidl);
- psfRestOfNet->Release();
- }
- }
- }
- }
- return hres;
- }
- // CNetRootFolder::ParseDisplayname
- // - swtich based on the file system context to see if we need to do a simple parse or not,
- // - check for "EntireNet" and delegate parsing as required.
- STDMETHODIMP CNetRootFolder::ParseDisplayName(HWND hwnd, LPBC pbc, WCHAR* pszName, ULONG* pchEaten,
- LPITEMIDLIST* ppidl, DWORD* pdwAttributes)
- {
- HRESULT hres = _TryParseEntireNet(hwnd, pbc, pszName, ppidl, pdwAttributes);
- if (hres == S_OK)
- return hres;
- hres = SHIsFileSysBindCtx(pbc, NULL);
- if (S_OK == hres)
- {
- hres = _ParseSimple(pbc, pszName, ppidl, pdwAttributes);
- }
- else
- {
- hres = _ParseNetName(hwnd, pbc, pszName, pchEaten, ppidl, pdwAttributes);
- if ((HRESULT_FROM_WIN32(ERROR_BAD_NET_NAME) == hres))
- {
- IShellFolder2 *psfFiles;
- if (SUCCEEDED(v_GetFileFolder(&psfFiles)))
- hres = psfFiles->ParseDisplayName(hwnd, pbc, pszName, pchEaten, ppidl, pdwAttributes);
- }
- }
- return hres;
- }
- STDMETHODIMP CNetRootFolder::EnumObjects(HWND hwnd, DWORD grfFlags, IEnumIDList** ppenum)
- {
- HRESULT hres = E_OUTOFMEMORY;
- ENUM_DATA *penet = (ENUM_DATA *)LocalAlloc(LPTR, SIZEOF(ENUM_DATA));
- if (penet)
- {
- //
- // get the link enumerator on the first call into the net enumerator
- //
- AddRef();
- penet->pnf = this;
- penet->dwRemote |= RMF_GETLINKENUM;
- //
- // Do we enumerate the workgroup?
- //
- if ( !SHRestricted(REST_ENUMWORKGROUP) )
- {
- DWORD dwValue, dwSize = SIZEOF(dwValue);
- // Don't enumerate the workgroup, if the restriction says so
- penet->dwRemote |= RMF_FAKENETROOT;
- // Check the WNet policy to see if we should be showing the entire net object, if not
- // mark it as shown so that the enumerator doesn't return it.
- if ( ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER, WNET_POLICY_KEY, TEXT("NoEntireNetwork"),
- NULL, (void *)&dwValue, &dwSize) )
- {
- if ( dwValue )
- penet->dwRemote |= RMF_ENTIRENETSHOWN;
- }
- }
- //
- // if we are not faking the net root then lets call _OpenEnum, otherwise lets ignore
- //
- if (!(penet->dwRemote & RMF_FAKENETROOT))
- {
- DWORD err = _OpenEnum(hwnd, grfFlags, NULL, &penet->hEnum);
- // Always add the remote folder to the 'hood
- if (WN_SUCCESS != err)
- {
- // Yes; still show remote anyway (only)
- penet->dwRemote |= RMF_SHOWREMOTE;
- }
- else
- {
- // No; allow everything to be enumerated in the 'hood.
- penet->dwRemote |= RMF_CONTEXT;
- }
- }
- penet->grfFlags = grfFlags;
- hres = SHCreateEnumObjects(hwnd, penet, EnumCallBack, ppenum);
- }
- return hres;
- }
- STDMETHODIMP CNetRootFolder::BindToObject(LPCITEMIDLIST pidl, LPBC pbc, REFIID riid, void** ppvOut)
- {
- HRESULT hres;
- if (NET_IsValidID(pidl))
- hres = CNetFolder::BindToObject(pidl, pbc, riid, ppvOut);
- else
- {
- IShellFolder2* psfFiles;
- hres = v_GetFileFolder(&psfFiles);
- if (SUCCEEDED(hres))
- hres = psfFiles->BindToObject(pidl, pbc, riid, ppvOut);
- }
- return hres;
- }
- STDMETHODIMP CNetRootFolder::CompareIDs(LPARAM iCol, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
- {
- HRESULT hres = E_INVALIDARG;
- // First obtain the collate type of the pidls and their respective
- // collate order.
- LONG iColateType1 = _GetFilePIDLType(pidl1);
- LONG iColateType2 = _GetFilePIDLType(pidl2);
- if (iColateType1 == iColateType2)
- {
- // pidls are of same type.
- if (iColateType1 == _HOOD_COL_FILE) // two file system pidls
- {
- SHCOLUMNID scid;
- IShellFolder2* psfFiles;
- if (SUCCEEDED(v_GetFileFolder(&psfFiles)) &&
- SUCCEEDED(MapColumnToSCID((UINT)iCol & SHCIDS_COLUMNMASK, &scid)))
- {
- if (IsEqualSCID(scid, SCID_NAME))
- {
- // Name is a no-brainer; delegate directly to the fs folder
- return psfFiles->CompareIDs(iCol, pidl1, pidl2);
- }
- else
- {
- // Other columns are extended columns. Let FS folder
- // acquire the extended column data abstractly from handlers,
- // then we'll compare the values ourselves.
- // BUGBUG [scotthan]: We're limited to VT_BSTR values.
- VARIANT var1 = {0}, var2 = {0};
- if (FAILED(psfFiles->GetDetailsEx(pidl1, &scid, &var1)) || var1.vt != VT_BSTR)
- VariantClear(&var1);
- if (FAILED(psfFiles->GetDetailsEx(pidl2, &scid, &var2)) || var2.vt != VT_BSTR)
- VariantClear(&var2);
- if (var1.bstrVal && var2.bstrVal)
- hres = ResultFromShort(StrCmpW(var1.bstrVal, var2.bstrVal));
- else if (var1.bstrVal)
- hres = ResultFromShort(1);
- else if (var2.bstrVal)
- hres = ResultFromShort(-1);
- else
- hres = ResultFromShort(0);
- VariantClear(&var1);
- VariantClear(&var2);
- }
- }
- }
- else
- {
- // pidls same and are not of type file,
- // so both must be a type understood
- // by the CNetwork class - pass on to compare.
- return CNetFolder::CompareIDs(iCol, pidl1, pidl2);
- }
- }
- else
- {
- // ensure that entire network ends up at the head of the list
- LPCIDNETRESOURCE pidn1 = NET_IsValidID(pidl1);
- LPCIDNETRESOURCE pidn2 = NET_IsValidID(pidl2);
- if ( (pidn1 && (NET_GetDisplayType(pidn1) == RESOURCEDISPLAYTYPE_ROOT)) ||
- (pidn2 && (NET_GetDisplayType(pidn2) == RESOURCEDISPLAYTYPE_ROOT)) )
- {
- if ( iColateType1 == _HOOD_COL_FILE )
- return ResultFromShort(1);
- else
- return ResultFromShort(-1);
- }
- // pidls are not of same type, so have already been correctly
- // collated (consequently, sorting is first by type and
- // then by subfield).
- return ResultFromShort(((iColateType2 - iColateType1) > 0) ? 1 : -1);
- }
- return hres;
- }
- STDMETHODIMP CNetRootFolder::CreateViewObject(HWND hwnd, REFIID riid, void** ppvOut)
- {
- ASSERT(ILIsEqual(_pidl, (LPCITEMIDLIST)&c_idlNet));
- if (IsEqualIID(riid, IID_IDropTarget))
- {
- return CIDLDropTarget_Create(hwnd, &c_CNetRootTargetVtbl, _pidl, (IDropTarget**) ppvOut);
- }
- return CNetFolder::CreateViewObject(hwnd, riid, ppvOut);
- }
- STDMETHODIMP CNetRootFolder::GetAttributesOf(UINT cidl, LPCITEMIDLIST* apidl, ULONG* prgfInOut)
- {
- HRESULT hres;
- if (cidl == 0)
- {
- //
- // The user can rename links in the hood.
- //
- hres = CNetFolder::GetAttributesOf(cidl, apidl, prgfInOut);
- *prgfInOut |= SFGAO_CANRENAME;
- }
- else
- {
- hres = Multi_GetAttributesOf((IShellFolder2*) this, cidl, apidl, prgfInOut, GAOCallbackNetRoot);
- }
- return hres;
- }
- STDMETHODIMP CNetRootFolder::GetDisplayNameOf(LPCITEMIDLIST pidl, DWORD dwFlags, STRRET* pStrRet)
- {
- HRESULT hres;
- if (NET_IsValidID(pidl) || IsSelf(1, &pidl))
- {
- hres = CNetFolder::GetDisplayNameOf(pidl, dwFlags, pStrRet);
- }
- else
- {
- IShellFolder2* psfFiles;
- hres = v_GetFileFolder(&psfFiles);
- if (SUCCEEDED(hres))
- hres = psfFiles->GetDisplayNameOf(pidl, dwFlags, pStrRet);
- }
- return hres;
- }
- STDMETHODIMP CNetRootFolder::SetNameOf(HWND hwnd, LPCITEMIDLIST pidl, LPCOLESTR lpszName,
- DWORD dwRes, LPITEMIDLIST* ppidl)
- {
- HRESULT hres;
- if (NET_IsValidID(pidl))
- {
- hres = CNetFolder::SetNameOf(hwnd, pidl, lpszName, dwRes, ppidl);
- }
- else
- {
- IShellFolder2* psfFiles;
- hres = v_GetFileFolder(&psfFiles);
- if (SUCCEEDED(hres))
- hres = psfFiles->SetNameOf(hwnd, pidl, lpszName, dwRes, ppidl);
- }
- return hres;
- }
- STDMETHODIMP CNetRootFolder::GetUIObjectOf(HWND hwnd, UINT cidl, LPCITEMIDLIST* apidl,
- REFIID riid, UINT* prgfInOut, void** ppvOut)
- {
- HRESULT hres = E_INVALIDARG;
- LPCIDNETRESOURCE pidn = cidl ? NET_IsValidID(apidl[0]) : NULL;
- BOOL fStriped = FALSE;
- ASSERT(ILIsEqual(_pidl, (LPCITEMIDLIST)&c_idlNet));
- *ppvOut = NULL;
- if (pidn)
- {
- fStriped = _MakeStripToLikeKinds(&cidl, &apidl, TRUE);
- if (IsEqualIID(riid, IID_IContextMenu))
- {
- HKEY ahkeys[NKID_COUNT];
- hres = _OpenKeys(pidn, ahkeys);
- if (SUCCEEDED(hres))
- {
- IShellFolder* psfOuter;
- hres = QueryInterface(IID_IShellFolder, (void**) &psfOuter);
- if (SUCCEEDED(hres))
- {
- hres = CDefFolderMenu_Create2(_pidl, hwnd, cidl, apidl,
- psfOuter, _GetCallbackType(pidn),
- ARRAYSIZE(ahkeys), ahkeys, (IContextMenu**) ppvOut);
- psfOuter->Release();
- }
- SHRegCloseKeys(ahkeys, ARRAYSIZE(ahkeys));
- }
- }
- else
- hres = CNetFolder::GetUIObjectOf(hwnd, cidl, apidl, riid, prgfInOut, ppvOut);
- }
- else
- {
- fStriped = _MakeStripToLikeKinds(&cidl, &apidl, FALSE);
- IShellFolder2* psfFiles;
- hres = v_GetFileFolder(&psfFiles);
- if (SUCCEEDED(hres))
- hres = psfFiles->GetUIObjectOf(hwnd, cidl, apidl, riid, prgfInOut, ppvOut);
- }
- if (fStriped)
- LocalFree((HLOCAL)apidl);
- return hres;
- }
- STDMETHODIMP CNetRootFolder::GetClassID(CLSID* pCLSID)
- {
- *pCLSID = CLSID_NetworkPlaces;
- return S_OK;
- }
- STDMETHODIMP CNetRootFolder::Initialize(LPCITEMIDLIST pidl)
- {
- ASSERT(ILIsEqual(pidl, (LPCITEMIDLIST)&c_idlNet));
- // Only allow the Net root on the desktop
- HRESULT hres = !IsIDListInNameSpace(pidl, &CLSID_NetworkPlaces) || !ILIsEmpty(_ILNext(pidl)) ? E_INVALIDARG : S_OK;
- if (SUCCEEDED(hres))
- {
- hres = SHILClone(pidl, &_pidl);
- }
- return hres;
- }
- LONG CNetFolder::_GetFilePIDLType(LPCITEMIDLIST pidl)
- {
- if (NET_IsValidID(pidl))
- {
- if (NET_IsRemoteFld((LPIDNETRESOURCE)pidl))
- {
- return _HOOD_COL_REMOTE;
- }
- if (NET_GetDisplayType((LPIDNETRESOURCE)pidl) == RESOURCEDISPLAYTYPE_ROOT)
- {
- return _HOOD_COL_RON;
- }
- return _HOOD_COL_NET;
- }
- return _HOOD_COL_FILE;
- }
- /* This function adds a provider name to an IDLIST that doesn't already have one. */
- /* A new IDLIST pointer is returned; the old pointer is no longer valid. */
- LPITEMIDLIST CNetFolder::_AddProviderToPidl(LPITEMIDLIST pidl, LPCTSTR lpProvider)
- {
- LPIDNETRESOURCE pidn = (LPIDNETRESOURCE)pidl;
- if ( !NET_FHasProvider(pidn) )
- {
- LPITEMIDLIST pidlres;
- TCHAR szName[MAX_PATH], szComment[MAX_PATH];
- // construct a new IDLIST preserving the name, comment and other information
- NET_CopyResName(pidn, szName, ARRAYSIZE(szName));
- NET_CopyComment(pidn, szComment, ARRAYSIZE(szComment));
- HRESULT hres = _CreateNetIDList(pidn, szName, lpProvider, szComment[0] ? szComment:NULL, &pidlres);
- if ( SUCCEEDED(hres) && !ILIsEmpty(_ILNext(pidl)) )
- {
- LPITEMIDLIST pidlT;
- hres = SHILCombine(pidlres, _ILNext(pidl), &pidlT);
- if ( SUCCEEDED(hres) )
- {
- ILFree(pidlres);
- pidlres = pidlT;
- }
- }
- // if we have a result, free the old PIDL and return the new
- if ( SUCCEEDED(hres) )
- {
- ILFree(pidl);
- pidl = pidlres;
- }
- }
- return pidl;
- }
- BOOL CNetFolder::_MakeStripToLikeKinds(UINT *pcidl, LPCITEMIDLIST **papidl, BOOL fNetObjects)
- {
- LPITEMIDLIST *apidl = (LPITEMIDLIST*)*papidl;
- int iidl, cidl = *pcidl;
- for (iidl = 0; iidl < cidl; iidl++)
- {
- if ((NET_IsValidID(apidl[iidl]) != NULL) != fNetObjects)
- {
- int cpidlHomo;
- LPCITEMIDLIST *apidlHomo = (LPCITEMIDLIST *)LocalAlloc(LPTR, SIZEOF(LPCITEMIDLIST) * cidl);
- if (!apidlHomo)
- return FALSE;
- cpidlHomo = 0;
- for (iidl = 0; iidl < cidl; iidl++)
- {
- if ((NET_IsValidID(apidl[iidl]) != NULL) == fNetObjects)
- apidlHomo[cpidlHomo++] = apidl[iidl];
- }
- // Setup to use the stripped version of the pidl array...
- *pcidl = cpidlHomo;
- *papidl = apidlHomo;
- return TRUE;
- }
- }
- return FALSE;
- }
- HRESULT CNetRootFolder::v_GetFileFolder(IShellFolder2 **psf)
- {
- HRESULT hres;
- hres = SHCacheTrackingFolder((LPCITEMIDLIST)&c_idlNet, CSIDL_NETHOOD, &_psfFiles);
- *psf = _psfFiles;
- return hres;
- }