⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shfldr_fs.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 4 页
字号:

/*
 * file system folder
 *
 * Copyright 1997             Marcus Meissner
 * Copyright 1998, 1999, 2002 Juergen Schmied
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "config.h"
#include "wine/port.h"

#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>

#define COBJMACROS
#define NONAMELESSUNION
#define NONAMELESSSTRUCT

#include "winerror.h"
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "wingdi.h"
#include "winuser.h"

#include "ole2.h"
#include "shlguid.h"

#include "enumidlist.h"
#include "pidl.h"
#include "undocshell.h"
#include "shell32_main.h"
#include "shresdef.h"
#include "shlwapi.h"
#include "shellfolder.h"
#include "wine/debug.h"
#include "debughlp.h"
#include "shfldr.h"

WINE_DEFAULT_DEBUG_CHANNEL (shell);

/***********************************************************************
*   IShellFolder implementation
*/

typedef struct {
    const IUnknownVtbl        *lpVtbl;
    LONG                ref;
    const IShellFolder2Vtbl   *lpvtblShellFolder;
    const IPersistFolder3Vtbl *lpvtblPersistFolder3;
    const IDropTargetVtbl     *lpvtblDropTarget;
    const ISFHelperVtbl       *lpvtblSFHelper;

    IUnknown *pUnkOuter; /* used for aggregation */

    CLSID *pclsid;

    /* both paths are parsible from the desktop */
    LPSTR sPathTarget;     /* complete path to target used for enumeration and ChangeNotify */

    LPITEMIDLIST pidlRoot; /* absolute pidl */

    UINT cfShellIDList;    /* clipboardformat for IDropTarget */
    BOOL fAcceptFmt;       /* flag for pending Drop */
} IGenericSFImpl;

static const IUnknownVtbl unkvt;
static const IShellFolder2Vtbl sfvt;
static const IPersistFolder3Vtbl vt_FSFldr_PersistFolder3; /* IPersistFolder3 for a FS_Folder */
static const IDropTargetVtbl dtvt;
static const ISFHelperVtbl shvt;

static inline IGenericSFImpl *impl_from_IShellFolder2( IShellFolder2 *iface )
{
    return (IGenericSFImpl *)((char*)iface - FIELD_OFFSET(IGenericSFImpl, lpvtblShellFolder));
}

static inline IGenericSFImpl *impl_from_IPersistFolder3( IPersistFolder3 *iface )
{
    return (IGenericSFImpl *)((char*)iface - FIELD_OFFSET(IGenericSFImpl, lpvtblPersistFolder3));
}

static inline IGenericSFImpl *impl_from_IDropTarget( IDropTarget *iface )
{
    return (IGenericSFImpl *)((char*)iface - FIELD_OFFSET(IGenericSFImpl, lpvtblDropTarget));
}

static inline IGenericSFImpl *impl_from_ISFHelper( ISFHelper *iface )
{
    return (IGenericSFImpl *)((char*)iface - FIELD_OFFSET(IGenericSFImpl, lpvtblSFHelper));
}


/*
  converts This to an interface pointer
*/
#define _IUnknown_(This)        (IUnknown*)&(This->lpVtbl)
#define _IShellFolder_(This)    (IShellFolder*)&(This->lpvtblShellFolder)
#define _IShellFolder2_(This)   (IShellFolder2*)&(This->lpvtblShellFolder)
#define _IPersist_(This)        (IPersist*)&(This->lpvtblPersistFolder3)
#define _IPersistFolder_(This)  (IPersistFolder*)&(This->lpvtblPersistFolder3)
#define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpvtblPersistFolder3)
#define _IPersistFolder3_(This) (IPersistFolder3*)&(This->lpvtblPersistFolder3)
#define _IDropTarget_(This)     (IDropTarget*)&(This->lpvtblDropTarget)
#define _ISFHelper_(This)       (ISFHelper*)&(This->lpvtblSFHelper)

/**************************************************************************
* registers clipboardformat once
*/
static void SF_RegisterClipFmt (IGenericSFImpl * This)
{
    TRACE ("(%p)\n", This);

    if (!This->cfShellIDList) {
        This->cfShellIDList = RegisterClipboardFormatA (CFSTR_SHELLIDLIST);
    }
}

/**************************************************************************
* we need a separate IUnknown to handle aggregation
* (inner IUnknown)
*/
static HRESULT WINAPI IUnknown_fnQueryInterface (IUnknown * iface, REFIID riid, LPVOID * ppvObj)
{
    IGenericSFImpl *This = (IGenericSFImpl *)iface;

    TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj);

    *ppvObj = NULL;

    if (IsEqualIID (riid, &IID_IUnknown))
        *ppvObj = _IUnknown_ (This);
    else if (IsEqualIID (riid, &IID_IShellFolder))
        *ppvObj = _IShellFolder_ (This);
    else if (IsEqualIID (riid, &IID_IShellFolder2))
        *ppvObj = _IShellFolder_ (This);
    else if (IsEqualIID (riid, &IID_IPersist))
        *ppvObj = _IPersist_ (This);
    else if (IsEqualIID (riid, &IID_IPersistFolder))
        *ppvObj = _IPersistFolder_ (This);
    else if (IsEqualIID (riid, &IID_IPersistFolder2))
        *ppvObj = _IPersistFolder2_ (This);
    else if (IsEqualIID (riid, &IID_IPersistFolder3))
        *ppvObj = _IPersistFolder3_ (This);
    else if (IsEqualIID (riid, &IID_ISFHelper))
        *ppvObj = _ISFHelper_ (This);
    else if (IsEqualIID (riid, &IID_IDropTarget)) {
        *ppvObj = _IDropTarget_ (This);
        SF_RegisterClipFmt (This);
    }

    if (*ppvObj) {
        IUnknown_AddRef ((IUnknown *) (*ppvObj));
        TRACE ("-- Interface = %p\n", *ppvObj);
        return S_OK;
    }
    TRACE ("-- Interface: E_NOINTERFACE\n");
    return E_NOINTERFACE;
}

static ULONG WINAPI IUnknown_fnAddRef (IUnknown * iface)
{
    IGenericSFImpl *This = (IGenericSFImpl *)iface;
    ULONG refCount = InterlockedIncrement(&This->ref);

    TRACE ("(%p)->(count=%lu)\n", This, refCount - 1);

    return refCount;
}

static ULONG WINAPI IUnknown_fnRelease (IUnknown * iface)
{
    IGenericSFImpl *This = (IGenericSFImpl *)iface;
    ULONG refCount = InterlockedDecrement(&This->ref);

    TRACE ("(%p)->(count=%lu)\n", This, refCount + 1);

    if (!refCount) {
        TRACE ("-- destroying IShellFolder(%p)\n", This);

        if (This->pidlRoot)
            SHFree (This->pidlRoot);
        if (This->sPathTarget)
            SHFree (This->sPathTarget);
        LocalFree ((HLOCAL) This);
    }
    return refCount;
}

static const IUnknownVtbl unkvt =
{
      IUnknown_fnQueryInterface,
      IUnknown_fnAddRef,
      IUnknown_fnRelease,
};

static shvheader GenericSFHeader[] = {
    {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
    {IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
    {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
    {IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12},
    {IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5}
};

#define GENERICSHELLVIEWCOLUMNS 5

/**************************************************************************
* IFSFolder_Constructor
*
* NOTES
*  creating undocumented ShellFS_Folder as part of an aggregation
*  {F3364BA0-65B9-11CE-A9BA-00AA004AE837}
*
*/
HRESULT WINAPI
IFSFolder_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
{
    IGenericSFImpl *sf;

    TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid));

    if (pUnkOuter && !IsEqualIID (riid, &IID_IUnknown))
        return CLASS_E_NOAGGREGATION;
    sf = (IGenericSFImpl *) LocalAlloc (LMEM_ZEROINIT, sizeof (IGenericSFImpl));
    if (!sf)
        return E_OUTOFMEMORY;

    sf->ref = 0;
    sf->lpVtbl = &unkvt;
    sf->lpvtblShellFolder = &sfvt;
    sf->lpvtblPersistFolder3 = &vt_FSFldr_PersistFolder3;
    sf->lpvtblDropTarget = &dtvt;
    sf->lpvtblSFHelper = &shvt;
    sf->pclsid = (CLSID *) & CLSID_ShellFSFolder;
    sf->pUnkOuter = pUnkOuter ? pUnkOuter : _IUnknown_ (sf);

    if (!SUCCEEDED (IUnknown_QueryInterface (_IUnknown_ (sf), riid, ppv))) {
        IUnknown_Release (_IUnknown_ (sf));
        return E_NOINTERFACE;
    }

    TRACE ("--%p\n", *ppv);
    return S_OK;
}

/**************************************************************************
 *  IShellFolder_fnQueryInterface
 *
 * PARAMETERS
 *  REFIID riid       [in ] Requested InterfaceID
 *  LPVOID* ppvObject [out] Interface* to hold the result
 */
static HRESULT WINAPI
IShellFolder_fnQueryInterface (IShellFolder2 * iface, REFIID riid,
                               LPVOID * ppvObj)
{
    IGenericSFImpl *This = impl_from_IShellFolder2(iface);

    TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj);

    return IUnknown_QueryInterface (This->pUnkOuter, riid, ppvObj);
}

/**************************************************************************
*  IShellFolder_AddRef
*/

static ULONG WINAPI IShellFolder_fnAddRef (IShellFolder2 * iface)
{
    IGenericSFImpl *This = impl_from_IShellFolder2(iface);

    TRACE ("(%p)->(count=%lu)\n", This, This->ref);

    return IUnknown_AddRef (This->pUnkOuter);
}

/**************************************************************************
 *  IShellFolder_fnRelease
 */
static ULONG WINAPI IShellFolder_fnRelease (IShellFolder2 * iface)
{
    IGenericSFImpl *This = impl_from_IShellFolder2(iface);

    TRACE ("(%p)->(count=%lu)\n", This, This->ref);

    return IUnknown_Release (This->pUnkOuter);
}

/**************************************************************************
 *  SHELL32_CreatePidlFromBindCtx  [internal]
 *
 *  If the caller bound File System Bind Data, assume it is the 
 *   find data for the path.
 *  This allows binding of paths that don't exist.
 */
LPITEMIDLIST SHELL32_CreatePidlFromBindCtx(IBindCtx *pbc, LPCWSTR path)
{
    static const WCHAR szfsbc[] = {
        'F','i','l','e',' ','S','y','s','t','e','m',' ',
        'B','i','n','d',' ','D','a','t','a',0 };
    IFileSystemBindData *fsbd = NULL;
    LPITEMIDLIST pidl = NULL;
    IUnknown *param = NULL;
    WIN32_FIND_DATAW wfd;
    HRESULT r;

    TRACE("%p %s\n", pbc, debugstr_w(path));

    if (!pbc)
        return NULL;

    /* see if the caller bound File System Bind Data */
    r = IBindCtx_GetObjectParam( pbc, (LPOLESTR) szfsbc, &param );
    if (FAILED(r))
        return NULL;

    r = IUnknown_QueryInterface( param, &IID_IFileSystemBindData,
                                 (LPVOID*) &fsbd );
    if (SUCCEEDED(r))
    {
        r = IFileSystemBindData_GetFindData( fsbd, &wfd );
        if (SUCCEEDED(r))
        {
            lstrcpynW( &wfd.cFileName[0], path, MAX_PATH );
            pidl = _ILCreateFromFindDataW( &wfd );
        }
        IFileSystemBindData_Release( fsbd );
    }
    
    return pidl;
}

/**************************************************************************
* IShellFolder_ParseDisplayName {SHELL32}
*
* Parse a display name.
*
* PARAMS
*  hwndOwner       [in]  Parent window for any message's
*  pbc             [in]  optional FileSystemBindData context
*  lpszDisplayName [in]  Unicode displayname.
*  pchEaten        [out] (unicode) characters processed
*  ppidl           [out] complex pidl to item
*  pdwAttributes   [out] items attributes
*
* NOTES
*  Every folder tries to parse only its own (the leftmost) pidl and creates a
*  subfolder to evaluate the remaining parts.
*  Now we can parse into namespaces implemented by shell extensions
*
*  Behaviour on win98: lpszDisplayName=NULL -> crash
*                      lpszDisplayName="" -> returns mycoputer-pidl
*
* FIXME
*    pdwAttributes is not set
*    pchEaten is not set like in windows
*/
static HRESULT WINAPI
IShellFolder_fnParseDisplayName (IShellFolder2 * iface,
                                 HWND hwndOwner,
                                 LPBC pbc,
                                 LPOLESTR lpszDisplayName,
                                 DWORD * pchEaten, LPITEMIDLIST * ppidl,
                                 DWORD * pdwAttributes)
{
    IGenericSFImpl *This = impl_from_IShellFolder2(iface);

    HRESULT hr = E_INVALIDARG;
    LPCWSTR szNext = NULL;
    WCHAR szElement[MAX_PATH];
    WCHAR szPath[MAX_PATH];
    LPITEMIDLIST pidlTemp = NULL;
    DWORD len;

    TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
     This, hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName),
     pchEaten, ppidl, pdwAttributes);

    if (!lpszDisplayName || !ppidl)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -