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

📄 desktop.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * ReactOS Explorer
 *
 * Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
 *
 * 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 <precomp.h>

#if USE_API_SHCREATEDESKTOP

typedef struct _DESKCREATEINFO
{
    HANDLE hEvent;
    ITrayWindow *Tray;
    HANDLE hDesktop;
} DESKCREATEINFO, *PDESKCREATEINFO;

static DWORD CALLBACK
DesktopThreadProc(IN OUT LPVOID lpParameter)
{
    volatile DESKCREATEINFO *DeskCreateInfo = (volatile DESKCREATEINFO *)lpParameter;
    IShellDesktopTray *pSdt;
    HANDLE hDesktop;
    HRESULT hRet;

    hRet = ITrayWindow_QueryInterface(DeskCreateInfo->Tray,
                                      &IID_IShellDesktopTray,
                                      (PVOID*)&pSdt);
    if (!SUCCEEDED(hRet))
        return 1;

    hDesktop = SHCreateDesktop(pSdt);

    IShellDesktopTray_Release(pSdt);
    if (hDesktop == NULL)
        return 1;

    (void)InterlockedExchangePointer(&DeskCreateInfo->hDesktop,
                                     hDesktop);

    if (!SetEvent(DeskCreateInfo->hEvent))
    {
        /* Failed to notify that we initialized successfully, kill ourselves
           to make the main thread wake up! */
        return 1;
    }

    SHDesktopMessageLoop(hDesktop);

    /* FIXME: Properly rundown the main thread! */
    ExitProcess(0);

    return 0;
}

HANDLE
DesktopCreateWindow(IN OUT ITrayWindow *Tray)
{
    HANDLE hThread;
    HANDLE hEvent;
    DWORD DesktopThreadId;
    HANDLE hDesktop = NULL;
    HANDLE Handles[2];
    DWORD WaitResult;

    hEvent = CreateEvent(NULL,
                         FALSE,
                         FALSE,
                         NULL);
    if (hEvent != NULL)
    {
        volatile DESKCREATEINFO DeskCreateInfo;

        DeskCreateInfo.hEvent = hEvent;
        DeskCreateInfo.Tray = Tray;
        DeskCreateInfo.hDesktop = NULL;

        hThread = CreateThread(NULL,
                               0,
                               DesktopThreadProc,
                               (PVOID)&DeskCreateInfo,
                               0,
                               &DesktopThreadId);
        if (hThread != NULL)
        {
            Handles[0] = hThread;
            Handles[1] = hEvent;

            for (;;)
            {
                WaitResult = MsgWaitForMultipleObjects(sizeof(Handles) / sizeof(Handles[0]),
                                                       Handles,
                                                       FALSE,
                                                       INFINITE,
                                                       QS_ALLEVENTS);
                if (WaitResult == WAIT_OBJECT_0 + (sizeof(Handles) / sizeof(Handles[0])))
                    TrayProcessMessages(Tray);
                else if (WaitResult != WAIT_FAILED && WaitResult != WAIT_OBJECT_0)
                {
                    hDesktop = DeskCreateInfo.hDesktop;
                    break;
                }
            }

            CloseHandle(hThread);
        }

        CloseHandle(hEvent);
    }

    return hDesktop;
}

VOID
DesktopDestroyShellWindow(IN HANDLE hDesktop)
{
    return;
}

#else /* USE_API_SHCREATEDESKTOP == 0 */

/*
 ******************************************************************************
 * NOTE: This could may be reused in a shell implementation of                *
 *       SHCreateDesktop().                                                   *
 ******************************************************************************
 */

#define WM_SHELL_ADDDRIVENOTIFY (WM_USER + 0x100)

static const IShellBrowserVtbl IDesktopShellBrowserImpl_Vtbl;
static const ICommDlgBrowserVtbl IDesktopShellBrowserImpl_ICommDlgBrowser_Vtbl;
static const IServiceProviderVtbl IDesktopShellBrowserImpl_IServiceProvider_Vtbl;
static const IShellFolderViewCBVtbl IDesktopShellBrowserImpl_IShellFolderViewCB_Vtbl;

/*
 * IShellBrowser
 */

typedef struct
{
    const IShellBrowserVtbl *lpVtbl;
    const ICommDlgBrowserVtbl *lpVtblCommDlgBrowser;
    const IServiceProviderVtbl *lpVtblServiceProvider;
    const IShellFolderViewCBVtbl *lpVtblShellFolderViewCB;
    LONG Ref;

    IShellView2 *DesktopView2;
    IShellView *DesktopView;
    IShellBrowser *DefaultShellBrowser;
    HWND hWnd;
    HWND hWndShellView;
    HWND hWndDesktopListView;

    ITrayWindow *Tray;

    LPITEMIDLIST pidlDesktopDirectory;
    LPITEMIDLIST pidlDesktop;
    IDropTarget *DropTarget;

    ULONG ChangeNotificationId;
} IDesktopShellBrowserImpl;

static IUnknown *
IUnknown_from_impl(IDesktopShellBrowserImpl *This)
{
    return (IUnknown *)&This->lpVtbl;
}

static IShellBrowser *
IShellBrowser_from_impl(IDesktopShellBrowserImpl *This)
{
    return (IShellBrowser *)&This->lpVtbl;
}

static IOleWindow *
IOleWindow_from_impl(IDesktopShellBrowserImpl *This)
{
    return (IOleWindow *)&This->lpVtbl;
}

static ICommDlgBrowser *
ICommDlgBrowser_from_impl(IDesktopShellBrowserImpl *This)
{
    return (ICommDlgBrowser *)&This->lpVtblCommDlgBrowser;
}

static IServiceProvider *
IServiceProvider_from_impl(IDesktopShellBrowserImpl *This)
{
    return (IServiceProvider *)&This->lpVtblServiceProvider;
}

static IShellFolderViewCB *
IShellFolderViewCB_from_impl(IDesktopShellBrowserImpl *This)
{
    return (IShellFolderViewCB *)&This->lpVtblShellFolderViewCB;
}

static IDesktopShellBrowserImpl *
impl_from_IShellBrowser(IShellBrowser *iface)
{
    return (IDesktopShellBrowserImpl *)((ULONG_PTR)iface - FIELD_OFFSET(IDesktopShellBrowserImpl,
                                                                        lpVtbl));
}

static IDesktopShellBrowserImpl *
impl_from_ICommDlgBrowser(ICommDlgBrowser *iface)
{
    return (IDesktopShellBrowserImpl *)((ULONG_PTR)iface - FIELD_OFFSET(IDesktopShellBrowserImpl,
                                                                        lpVtblCommDlgBrowser));
}

static IDesktopShellBrowserImpl *
impl_from_IServiceProvider(IServiceProvider *iface)
{
    return (IDesktopShellBrowserImpl *)((ULONG_PTR)iface - FIELD_OFFSET(IDesktopShellBrowserImpl,
                                                                        lpVtblServiceProvider));
}

static IDesktopShellBrowserImpl *
impl_from_IShellFolderViewCB(IShellFolderViewCB *iface)
{
    return (IDesktopShellBrowserImpl *)((ULONG_PTR)iface - FIELD_OFFSET(IDesktopShellBrowserImpl,
                                                                        lpVtblShellFolderViewCB));
}

static VOID
IDesktopShellBrowserImpl_Free(IDesktopShellBrowserImpl *This)
{
    if (This->DropTarget != NULL)
    {
        IDropTarget_Release(This->DropTarget);
        This->DropTarget = NULL;
    }

    if (This->Tray != NULL)
    {
        ITrayWindow_Release(This->Tray);
        This->Tray = NULL;
    }

    if (This->pidlDesktopDirectory != NULL)
    {
        ILFree(This->pidlDesktopDirectory);
        This->pidlDesktopDirectory = NULL;
    }

    if (This->pidlDesktop != NULL)
    {
        ILFree(This->pidlDesktop);
        This->pidlDesktop = NULL;
    }

    HeapFree(hProcessHeap,
             0,
             This);
}

static VOID
IDesktopShellBrowserImpl_Destroy(IDesktopShellBrowserImpl *This)
{
    if (This->ChangeNotificationId != 0)
    {
        SHChangeNotifyDeregister(This->ChangeNotificationId);
        This->ChangeNotificationId = 0;
    }

    if (This->Tray != NULL)
    {
        ITrayWindow_Close(This->Tray);
        This->Tray = NULL;
    }

    if (This->DropTarget != NULL && This->hWndDesktopListView != NULL)
    {
        RevokeDragDrop(This->hWndDesktopListView);
        This->hWndDesktopListView = NULL;
    }

    if (This->DesktopView2 != NULL)
    {
        IShellView2_Release(This->DesktopView2);
    }

    if (This->DesktopView != NULL)
    {
        if (This->hWndShellView != NULL)
        {
            IShellView_DestroyViewWindow(This->DesktopView);
        }

        IShellView_Release(This->DesktopView);
        This->DesktopView = NULL;
        This->hWndShellView = NULL;
        This->hWndDesktopListView = NULL;
    }
}

static HRESULT
IDesktopShellBrowserImpl_GetNotify(IN OUT IDesktopShellBrowserImpl *This,
                                   OUT LPITEMIDLIST *ppidl,
                                   OUT LONG *plEvents)
{
    *ppidl = This->pidlDesktopDirectory;
    *plEvents = SHCNE_DISKEVENTS;
    return S_OK;
}

static ULONG STDMETHODCALLTYPE
IDesktopShellBrowserImpl_Release(IN OUT IShellBrowser *iface)
{
    IDesktopShellBrowserImpl *This = impl_from_IShellBrowser(iface);
    ULONG Ret;

    Ret = InterlockedDecrement(&This->Ref);
    if (Ret == 0)
        IDesktopShellBrowserImpl_Free(This);

    return Ret;
}

static ULONG STDMETHODCALLTYPE
IDesktopShellBrowserImpl_AddRef(IN OUT IShellBrowser *iface)
{
    IDesktopShellBrowserImpl *This = impl_from_IShellBrowser(iface);

    return InterlockedIncrement(&This->Ref);
}

static HRESULT STDMETHODCALLTYPE
IDesktopShellBrowserImpl_QueryInterface(IN OUT IShellBrowser *iface,
                                        IN REFIID riid,
                                        OUT LPVOID *ppvObj)
{
    IDesktopShellBrowserImpl *This;

    if (ppvObj == NULL)
        return E_POINTER;

    This = impl_from_IShellBrowser(iface);

    if (IsEqualIID(riid,
                   &IID_IUnknown))
    {
        *ppvObj = IUnknown_from_impl(This);
    }
    else if (This->DefaultShellBrowser != NULL)
    {
        return IShellBrowser_QueryInterface(This->DefaultShellBrowser,
                                            riid,
                                            ppvObj);
    }
    else if (IsEqualIID(riid,
                        &IID_IOleWindow))
    {
        *ppvObj = IOleWindow_from_impl(This);
    }
    else if (IsEqualIID(riid,
                        &IID_IShellBrowser))
    {
        *ppvObj = IShellBrowser_from_impl(This);
    }
    else if (IsEqualIID(riid,
                        &IID_ICommDlgBrowser))
    {
        *ppvObj = ICommDlgBrowser_from_impl(This);
    }
    else if (IsEqualIID(riid,
                        &IID_IServiceProvider))
    {
        *ppvObj = IServiceProvider_from_impl(This);
    }
    else if (IsEqualIID(riid,
                        &IID_IShellFolderViewCB))
    {
        *ppvObj = IShellFolderViewCB_from_impl(This);
    }
    else
    {
        *ppvObj = NULL;
        return E_NOINTERFACE;
    }

    IDesktopShellBrowserImpl_AddRef(iface);
    return S_OK;
}

static IDesktopShellBrowserImpl *
IDesktopShellBrowserImpl_Construct(IN HWND hwndParent,
                                   IN LPCREATESTRUCT lpCreateStruct  OPTIONAL)
{
    IDesktopShellBrowserImpl *This;
    IShellBrowser *ShellBrowser;
    IShellFolder *psfDesktopFolder;
#if 1
    SFV_CREATE csfv;
#endif
    FOLDERSETTINGS fs;
    HRESULT hr;
    RECT rcClient;
    SHChangeNotifyEntry cne;

    This = HeapAlloc(hProcessHeap,
                     0,
                     sizeof(*This));
    if (This == NULL)
        return NULL;

    ZeroMemory(This,
               sizeof(*This));
    This->lpVtbl = &IDesktopShellBrowserImpl_Vtbl;
    This->lpVtblCommDlgBrowser = &IDesktopShellBrowserImpl_ICommDlgBrowser_Vtbl;
    This->lpVtblServiceProvider = &IDesktopShellBrowserImpl_IServiceProvider_Vtbl;
    This->lpVtblShellFolderViewCB = &IDesktopShellBrowserImpl_IShellFolderViewCB_Vtbl;
    This->Ref = 1;
    This->hWnd = hwndParent;

    ShellBrowser = IShellBrowser_from_impl(This);

    This->pidlDesktopDirectory = SHCloneSpecialIDList(This->hWnd,
                                                      CSIDL_DESKTOPDIRECTORY,
                                                      FALSE);

    hr = SHGetSpecialFolderLocation(This->hWnd,
                                    CSIDL_DESKTOP,
                                    &This->pidlDesktop);
    if (!SUCCEEDED(hr))
        goto Fail;

#if 1
    hr = SHGetDesktopFolder(&psfDesktopFolder);
#else
    hr = CoCreateInstance(&CLSID_ShellDesktop,
                          NULL,
                          CLSCTX_INPROC,
                          &IID_IShellFolder,
                          (PVOID*)&psfDesktopFolder);
#endif
    if (!SUCCEEDED(hr))
        goto Fail;

#if 0
    hr = IShellFolder_CreateViewObject(psfDesktopFolder,
                                       This->hWnd,
                                       &IID_IShellView,
                                       (PVOID*)&This->DesktopView);
#else
    csfv.cbSize = sizeof(csfv);
    csfv.pshf = psfDesktopFolder;
    csfv.psvOuter = NULL;

    hr = IDesktopShellBrowserImpl_QueryInterface(ShellBrowser,
                                                 &IID_IShellFolderViewCB,
                                                 (PVOID*)&csfv.psfvcb);
    if (!SUCCEEDED(hr))
        csfv.psfvcb = NULL;

    hr = SHCreateShellFolderView(&csfv,
                                 &This->DesktopView);

⌨️ 快捷键说明

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