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

📄 cpanelfolder.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * Control panel folder
 *
 * Copyright 2003 Martin Fuchs
 *
 * 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 "cpanel.h"
#include "enumidlist.h"
#include "pidl.h"
#include "undocshell.h"
#include "shell32_main.h"
#include "shresdef.h"
#include "shlwapi.h"
#include "wine/debug.h"
#include "debughlp.h"
#include "shfldr.h"

WINE_DEFAULT_DEBUG_CHANNEL(shell);

/***********************************************************************
*   control panel implementation in shell namespace
*/

typedef struct {
    const IShellFolder2Vtbl      *lpVtbl;
    LONG                   ref;
    const IPersistFolder2Vtbl    *lpVtblPersistFolder2;
    const IShellExecuteHookWVtbl *lpVtblShellExecuteHookW;
    const IShellExecuteHookAVtbl *lpVtblShellExecuteHookA;

    IUnknown *pUnkOuter;	/* used for aggregation */

    /* both paths are parsible from the desktop */
    LPITEMIDLIST pidlRoot;	/* absolute pidl */
    int dwAttributes;		/* attributes returned by GetAttributesOf FIXME: use it */
} ICPanelImpl;

static const IShellFolder2Vtbl vt_ShellFolder2;
static const IPersistFolder2Vtbl vt_PersistFolder2;
static const IShellExecuteHookWVtbl vt_ShellExecuteHookW;
static const IShellExecuteHookAVtbl vt_ShellExecuteHookA;

static inline ICPanelImpl *impl_from_IPersistFolder2( IPersistFolder2 *iface )
{
    return (ICPanelImpl *)((char*)iface - FIELD_OFFSET(ICPanelImpl, lpVtblPersistFolder2));
}

static inline ICPanelImpl *impl_from_IShellExecuteHookW( IShellExecuteHookW *iface )
{
    return (ICPanelImpl *)((char*)iface - FIELD_OFFSET(ICPanelImpl, lpVtblShellExecuteHookW));
}

static inline ICPanelImpl *impl_from_IShellExecuteHookA( IShellExecuteHookA *iface )
{
    return (ICPanelImpl *)((char*)iface - FIELD_OFFSET(ICPanelImpl, lpVtblShellExecuteHookA));
}


/*
  converts This to an interface pointer
*/
#define _IUnknown_(This)	   (IUnknown*)&(This->lpVtbl)
#define _IShellFolder_(This)	   (IShellFolder*)&(This->lpVtbl)
#define _IShellFolder2_(This)	   (IShellFolder2*)&(This->lpVtbl)

#define _IPersist_(This)	   (IPersist*)&(This->lpVtblPersistFolder2)
#define _IPersistFolder_(This)	   (IPersistFolder*)&(This->lpVtblPersistFolder2)
#define _IPersistFolder2_(This)	   (IPersistFolder2*)&(This->lpVtblPersistFolder2)
#define _IShellExecuteHookW_(This) (IShellExecuteHookW*)&(This->lpVtblShellExecuteHookW)
#define _IShellExecuteHookA_(This) (IShellExecuteHookA*)&(This->lpVtblShellExecuteHookA)

/***********************************************************************
*   IShellFolder [ControlPanel] implementation
*/

static shvheader ControlPanelSFHeader[] = {
    {IDS_SHV_COLUMN8, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},/*FIXME*/
    {IDS_SHV_COLUMN9, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 200},/*FIXME*/
};

#define CONROLPANELSHELLVIEWCOLUMNS 2

/**************************************************************************
*	IControlPanel_Constructor
*/
HRESULT WINAPI IControlPanel_Constructor(IUnknown* pUnkOuter, REFIID riid, LPVOID * ppv)
{
    ICPanelImpl *sf;

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

    if (!ppv)
	return E_POINTER;
    if (pUnkOuter && !IsEqualIID (riid, &IID_IUnknown))
	return CLASS_E_NOAGGREGATION;

    sf = (ICPanelImpl *) LocalAlloc(LMEM_ZEROINIT, sizeof(ICPanelImpl));
    if (!sf)
	return E_OUTOFMEMORY;

    sf->ref = 0;
    sf->lpVtbl = &vt_ShellFolder2;
    sf->lpVtblPersistFolder2 = &vt_PersistFolder2;
    sf->lpVtblShellExecuteHookW = &vt_ShellExecuteHookW;
    sf->lpVtblShellExecuteHookA = &vt_ShellExecuteHookA;
    sf->pidlRoot = _ILCreateControlPanel();	/* my qualified pidl */
    sf->pUnkOuter = pUnkOuter ? pUnkOuter : _IUnknown_ (sf);

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

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

/**************************************************************************
 *	ISF_ControlPanel_fnQueryInterface
 *
 * NOTES supports not IPersist/IPersistFolder
 */
static HRESULT WINAPI ISF_ControlPanel_fnQueryInterface(IShellFolder2 * iface, REFIID riid, LPVOID * ppvObject)
{
    ICPanelImpl *This = (ICPanelImpl *)iface;

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

    *ppvObject = NULL;

    if (IsEqualIID(riid, &IID_IUnknown) ||
	IsEqualIID(riid, &IID_IShellFolder) || IsEqualIID(riid, &IID_IShellFolder2))
	*ppvObject = This;
    else if (IsEqualIID(riid, &IID_IPersist) ||
	       IsEqualIID(riid, &IID_IPersistFolder) || IsEqualIID(riid, &IID_IPersistFolder2))
	*ppvObject = _IPersistFolder2_(This);
    else if (IsEqualIID(riid, &IID_IShellExecuteHookW))
	*ppvObject = _IShellExecuteHookW_(This);
    else if (IsEqualIID(riid, &IID_IShellExecuteHookA))
	*ppvObject = _IShellExecuteHookA_(This);

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

static ULONG WINAPI ISF_ControlPanel_fnAddRef(IShellFolder2 * iface)
{
    ICPanelImpl *This = (ICPanelImpl *)iface;
    ULONG refCount = InterlockedIncrement(&This->ref);

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

    return refCount;
}

static ULONG WINAPI ISF_ControlPanel_fnRelease(IShellFolder2 * iface)
{
    ICPanelImpl *This = (ICPanelImpl *)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);
        LocalFree((HLOCAL) This);
    }
    return refCount;
}

/**************************************************************************
*	ISF_ControlPanel_fnParseDisplayName
*/
static HRESULT WINAPI
ISF_ControlPanel_fnParseDisplayName(IShellFolder2 * iface,
				   HWND hwndOwner,
				   LPBC pbc,
				   LPOLESTR lpszDisplayName,
				   DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes)
{
    ICPanelImpl *This = (ICPanelImpl *)iface;

    HRESULT hr = E_INVALIDARG;

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

    *ppidl = 0;
    if (pchEaten)
	*pchEaten = 0;

    TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);

    return hr;
}

static LPITEMIDLIST _ILCreateCPanelApplet(LPCSTR name, LPCSTR displayName,
 LPCSTR comment, int iconIdx)
{
    PIDLCPanelStruct *p;
    LPITEMIDLIST pidl;
    PIDLDATA tmp;
    int size0 = (char*)&tmp.u.cpanel.szName-(char*)&tmp.u.cpanel;
    int size = size0;
    int l;

    tmp.type = PT_CPLAPPLET;
    tmp.u.cpanel.dummy = 0;
    tmp.u.cpanel.iconIdx = iconIdx;

    l = strlen(name);
    size += l+1;

    tmp.u.cpanel.offsDispName = l+1;
    l = strlen(displayName);
    size += l+1;

    tmp.u.cpanel.offsComment = tmp.u.cpanel.offsDispName+1+l;
    l = strlen(comment);
    size += l+1;

    pidl = SHAlloc(size+4);
    if (!pidl)
        return NULL;

    pidl->mkid.cb = size+2;
    memcpy(pidl->mkid.abID, &tmp, 2+size0);

    p = &((PIDLDATA*)pidl->mkid.abID)->u.cpanel;
    strcpy(p->szName, name);
    strcpy(p->szName+tmp.u.cpanel.offsDispName, displayName);
    strcpy(p->szName+tmp.u.cpanel.offsComment, comment);

    *(WORD*)((char*)pidl+(size+2)) = 0;

    pcheck(pidl);

    return pidl;
}

/**************************************************************************
 *  _ILGetCPanelPointer()
 * gets a pointer to the control panel struct stored in the pidl
 */
static PIDLCPanelStruct* _ILGetCPanelPointer(LPCITEMIDLIST pidl)
{
    LPPIDLDATA pdata = _ILGetDataPointer(pidl);

    if (pdata && pdata->type==PT_CPLAPPLET)
        return (PIDLCPanelStruct*)&(pdata->u.cpanel);

    return NULL;
}

 /**************************************************************************
 *		ISF_ControlPanel_fnEnumObjects
 */
static BOOL SHELL_RegisterCPanelApp(IEnumIDList* list, LPCSTR path)
{
    LPITEMIDLIST pidl;
    CPlApplet* applet;
    CPanel panel;
    CPLINFO info;
    unsigned i;
    int iconIdx;

    char displayName[MAX_PATH];
    char comment[MAX_PATH];

    WCHAR wpath[MAX_PATH];

    MultiByteToWideChar(CP_ACP, 0, path, -1, wpath, MAX_PATH);

    panel.first = NULL;
    applet = Control_LoadApplet(0, wpath, &panel);

    if (applet)
    {
        for(i=0; i<applet->count; ++i)
        {
            WideCharToMultiByte(CP_ACP, 0, applet->info[i].szName, -1, displayName, MAX_PATH, 0, 0);
            WideCharToMultiByte(CP_ACP, 0, applet->info[i].szInfo, -1, comment, MAX_PATH, 0, 0);

            applet->proc(0, CPL_INQUIRE, i, (LPARAM)&info);

            if (info.idIcon > 0)
                iconIdx = -info.idIcon; /* negative icon index instead of icon number */
            else
                iconIdx = 0;

            pidl = _ILCreateCPanelApplet(path, displayName, comment, iconIdx);

            if (pidl)
                AddToEnumList(list, pidl);
        }
        Control_UnloadApplet(applet);
    }
    return TRUE;
}

static int SHELL_RegisterRegistryCPanelApps(IEnumIDList* list, HKEY hkey_root, LPCSTR szRepPath)
{
    char name[MAX_PATH];
    char value[MAX_PATH];
    HKEY hkey;

    int cnt = 0;

    if (RegOpenKeyA(hkey_root, szRepPath, &hkey) == ERROR_SUCCESS)
    {
        int idx = 0;

        for(;; ++idx)
        {
            DWORD nameLen = MAX_PATH;
            DWORD valueLen = MAX_PATH;

            if (RegEnumValueA(hkey, idx, name, &nameLen, NULL, NULL, (LPBYTE)&value, &valueLen) != ERROR_SUCCESS)
                break;

            if (SHELL_RegisterCPanelApp(list, value))
                ++cnt;
        }
        RegCloseKey(hkey);

⌨️ 快捷键说明

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