[SHELL32]
[reactos.git] / reactos / dll / win32 / shell32 / CDefView.cpp
index 09ffe8e..3004bdd 100644 (file)
@@ -93,6 +93,7 @@ class CDefView :
         UINT                      m_uState;
         UINT                      m_cidl;
         PCUITEMID_CHILD_ARRAY     m_apidl;
+        PIDLIST_ABSOLUTE          m_pidlParent;
         LISTVIEW_SORT_INFO        m_sortInfo;
         ULONG                     m_hNotify;            /* change notification handle */
         HACCEL                    m_hAccel;
@@ -112,6 +113,7 @@ class CDefView :
 
         CLSID m_Category;
         HMENU m_hView;
+        BOOL m_Destroyed;
     private:
 
         HRESULT _MergeToolbar();
@@ -123,6 +125,7 @@ class CDefView :
         HRESULT IncludeObject(PCUITEMID_CHILD pidl);
         HRESULT OnDefaultCommand();
         HRESULT OnStateChange(UINT uFlags);
+        void UpdateStatusbar();
         void CheckToolbar();
         void SetStyle(DWORD dwAdd, DWORD dwRemove);
         BOOL CreateList();
@@ -137,6 +140,7 @@ class CDefView :
         BOOLEAN LV_AddItem(PCUITEMID_CHILD pidl);
         BOOLEAN LV_DeleteItem(PCUITEMID_CHILD pidl);
         BOOLEAN LV_RenameItem(PCUITEMID_CHILD pidlOld, PCUITEMID_CHILD pidlNew);
+        BOOLEAN LV_ProdItem(PCUITEMID_CHILD pidl);
         static INT CALLBACK fill_list(LPVOID ptr, LPVOID arg);
         HRESULT FillList();
         HMENU BuildFileMenu();
@@ -246,6 +250,8 @@ class CDefView :
         LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
         LRESULT OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
         LRESULT OnGetShellBrowser(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
+        LRESULT OnNCCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
+        LRESULT OnNCDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
         LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
         LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
         LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
@@ -294,6 +300,8 @@ class CDefView :
         MESSAGE_HANDLER(WM_SIZE, OnSize)
         MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
         MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
+        MESSAGE_HANDLER(WM_NCCREATE, OnNCCreate)
+        MESSAGE_HANDLER(WM_NCDESTROY, OnNCDestroy)
         MESSAGE_HANDLER(WM_CREATE, OnCreate)
         MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
         MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
@@ -313,7 +321,8 @@ class CDefView :
         END_MSG_MAP()
 
         BEGIN_COM_MAP(CDefView)
-        COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
+        // Windows returns E_NOINTERFACE for IOleWindow
+        // COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
         COM_INTERFACE_ENTRY_IID(IID_IShellView, IShellView)
         COM_INTERFACE_ENTRY_IID(IID_IFolderView, IFolderView)
         COM_INTERFACE_ENTRY_IID(IID_IShellFolderView, IShellFolderView)
@@ -354,6 +363,7 @@ CDefView::CDefView() :
     m_uState(0),
     m_cidl(0),
     m_apidl(NULL),
+    m_pidlParent(NULL),
     m_hNotify(0),
     m_hAccel(NULL),
     m_dwAspects(0),
@@ -361,7 +371,8 @@ CDefView::CDefView() :
     m_iDragOverItem(0),
     m_cScrollDelay(0),
     m_isEditing(FALSE),
-    m_hView(NULL)
+    m_hView(NULL),
+    m_Destroyed(FALSE)
 {
     ZeroMemory(&m_FolderSettings, sizeof(m_FolderSettings));
     ZeroMemory(&m_sortInfo, sizeof(m_sortInfo));
@@ -459,6 +470,26 @@ void CDefView::CheckToolbar()
     }
 }
 
+void CDefView::UpdateStatusbar()
+{
+    WCHAR szFormat[MAX_PATH] = {0};
+    WCHAR szObjects[MAX_PATH] = {0};
+    UINT cSelectedItems;
+
+    cSelectedItems = m_ListView.GetSelectedCount();
+    if (cSelectedItems)
+    {
+        LoadStringW(shell32_hInstance, IDS_OBJECTS_SELECTED, szFormat, _countof(szFormat));
+        StringCchPrintfW(szObjects, MAX_PATH, szFormat, cSelectedItems);
+    }
+    else
+    {
+        LoadStringW(shell32_hInstance, IDS_OBJECTS, szFormat, _countof(szFormat));
+        StringCchPrintfW(szObjects, MAX_PATH, szFormat, m_ListView.GetItemCount());
+    }
+    m_pShellBrowser->SetStatusTextSB(szObjects);
+}
+
 /**********************************************************
  *
  * ##### helperfunctions for initializing the view #####
@@ -785,6 +816,7 @@ BOOLEAN CDefView::LV_AddItem(PCUITEMID_CHILD pidl)
     lvItem.lParam = reinterpret_cast<LPARAM>(ILClone(pidl)); /*set the item's data*/
     lvItem.pszText = LPSTR_TEXTCALLBACKW;                 /*get text on a callback basis*/
     lvItem.iImage = I_IMAGECALLBACK;                      /*get the image on a callback basis*/
+    lvItem.stateMask = LVIS_CUT;
 
     if (m_ListView.InsertItem(&lvItem) == -1)
         return FALSE;
@@ -837,6 +869,31 @@ BOOLEAN CDefView::LV_RenameItem(PCUITEMID_CHILD pidlOld, PCUITEMID_CHILD pidlNew
     return FALSE;
 }
 
+/**********************************************************
+* LV_ProdItem()
+*/
+BOOLEAN CDefView::LV_ProdItem(PCUITEMID_CHILD pidl)
+{
+    int nItem;
+    LVITEMW lvItem;
+
+    TRACE("(%p)(pidl=%p)\n", this, pidl);
+
+    nItem = LV_FindItemByPidl(pidl);
+
+    if ( -1 != nItem )
+    {
+        lvItem.mask = LVIF_IMAGE;
+        lvItem.iItem = nItem;
+        lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0);
+        m_ListView.SetItem(&lvItem);
+        m_ListView.Update(nItem);
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
 /**********************************************************
 * ShellView_FillList()
 *
@@ -879,7 +936,10 @@ HRESULT CDefView::FillList()
         {
             /* if the value is 1, then show all hidden files/folders */
             if (flagVal == 1)
+            {
                 dFlags |= SHCONTF_INCLUDEHIDDEN;
+                m_ListView.SendMessageW(LVM_SETCALLBACKMASK, LVIS_CUT, 0);
+            }
         }
 
         /* close the key */
@@ -939,10 +999,20 @@ LRESULT CDefView::OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bH
 
 LRESULT CDefView::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
 {
-    if (m_hMenu)
-        DestroyMenu(m_hMenu);
-    RevokeDragDrop(m_hWnd);
-    SHChangeNotifyDeregister(m_hNotify);
+    if (!m_Destroyed)
+    {
+        m_Destroyed = TRUE;
+        if (m_hMenu)
+        {
+            DestroyMenu(m_hMenu);
+            m_hMenu = NULL;
+        }
+        RevokeDragDrop(m_hWnd);
+        SHChangeNotifyDeregister(m_hNotify);
+        m_hNotify = NULL;
+        SHFree(m_pidlParent);
+        m_pidlParent = NULL;
+    }
     bHandled = FALSE;
     return 0;
 }
@@ -971,6 +1041,20 @@ LRESULT CDefView::OnGetShellBrowser(UINT uMsg, WPARAM wParam, LPARAM lParam, BOO
     return reinterpret_cast<LRESULT>(m_pShellBrowser.p);
 }
 
+LRESULT CDefView::OnNCCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
+{
+    this->AddRef();
+    bHandled = FALSE;
+    return 0;
+}
+
+LRESULT CDefView::OnNCDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
+{
+    this->Release();
+    bHandled = FALSE;
+    return 0;
+}
+
 /**********************************************************
 *  ShellView_OnCreate()
 */
@@ -1000,16 +1084,16 @@ LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
     m_pSFParent->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
     if (ppf2)
     {
-        PIDLIST_ABSOLUTE pidlParent;
-        ppf2->GetCurFolder(&pidlParent);
+        ppf2->GetCurFolder(&m_pidlParent);
         ntreg.fRecursive = TRUE;
-        ntreg.pidl = pidlParent;
-        m_hNotify = SHChangeNotifyRegister(m_hWnd, SHCNF_IDLIST, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
-        SHFree(pidlParent);
+        ntreg.pidl = m_pidlParent;
+        m_hNotify = SHChangeNotifyRegister(m_hWnd, SHCNRF_InterruptLevel | SHCNRF_ShellLevel, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
     }
 
     m_hAccel = LoadAcceleratorsW(shell32_hInstance, MAKEINTRESOURCEW(IDA_SHELLVIEW));
 
+    UpdateStatusbar();
+
     return S_OK;
 }
 
@@ -1067,6 +1151,8 @@ void CDefView::PrepareShowFileMenu(HMENU hSubMenu)
         }
     }
 
+#if 0
+    /* FIXME/TODO: Reenable when they implemented AND localizable (not hardcoded). */
     /* Insert This item at the beginning of the menu. */
     _InsertMenuItemW(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
     _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM + 4, MFT_STRING, L"Properties", MFS_DISABLED);
@@ -1075,13 +1161,20 @@ void CDefView::PrepareShowFileMenu(HMENU hSubMenu)
     _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM + 1, MFT_STRING, L"Create Shortcut", MFS_DISABLED);
     _InsertMenuItemW(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
     _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, L"New", MFS_ENABLED);
+#endif
 
     HMENU menubase = BuildFileMenu();
     if (menubase)
     {
         int count = ::GetMenuItemCount(menubase);
+        int count2 = ::GetMenuItemCount(hSubMenu);
 
-        for (int i = 0; i < count; i++)
+        if (count2 > 0 && count > 0)
+        {
+            _InsertMenuItemW(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
+        }
+
+        for (int i = count-1; i >= 0; i--)
         {
             WCHAR label[128];
 
@@ -1096,10 +1189,9 @@ void CDefView::PrepareShowFileMenu(HMENU hSubMenu)
 
             mii.fType |= MFT_RADIOCHECK;
 
-            ::InsertMenuItemW(hSubMenu, IDM_MYFILEITEM, FALSE, &mii);
+            ::InsertMenuItemW(hSubMenu, 0, TRUE, &mii);
         }
 
-        _InsertMenuItemW(hSubMenu, IDM_MYFILEITEM, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
 
         ::DestroyMenu(menubase);
     }
@@ -1184,10 +1276,6 @@ HRESULT CDefView::OpenSelectedItems()
     if (FAILED(hResult))
         goto cleanup;
 
-    hResult = IUnknown_SetSite(m_pCM, (IShellView *)this);
-    //if (FAILED( hResult))
-    //    goto cleanup;
-
     hResult = m_pCM->QueryContextMenu(hMenu, 0, 0x20, 0x7fff, CMF_DEFAULTONLY);
     if (FAILED(hResult))
         goto cleanup;
@@ -1212,10 +1300,7 @@ cleanup:
         DestroyMenu(hMenu);
 
     if (m_pCM)
-    {
-        IUnknown_SetSite(m_pCM, NULL);
         m_pCM.Release();
-    }
 
     return hResult;
 }
@@ -1251,10 +1336,6 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
     if (FAILED( hResult))
         goto cleanup;
 
-    hResult = IUnknown_SetSite(m_pCM, (IShellView *)this);
-    //if (FAILED( hResult))
-    //    goto cleanup;
-
     hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
     if (FAILED( hResult))
         goto cleanup;
@@ -1280,10 +1361,7 @@ LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &b
 cleanup:
     
     if (m_pCM)
-    {
-        IUnknown_SetSite(m_pCM, NULL);
         m_pCM.Release();
-    }
 
     if (hMenu)
         DestroyMenu(hMenu);
@@ -1305,10 +1383,6 @@ LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
     if (FAILED( hResult))
         goto cleanup;
 
-    hResult = IUnknown_SetSite(m_pCM, (IShellView *)this);
-    //if (FAILED( hResult))
-    //    goto cleanup;
-
     hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
     if (FAILED( hResult))
         goto cleanup;
@@ -1322,10 +1396,7 @@ LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
 cleanup:
 
     if (m_pCM)
-    {
-        IUnknown_SetSite(m_pCM, NULL);
         m_pCM.Release();
-    }
 
     if (hMenu)
         DestroyMenu(hMenu);
@@ -1541,9 +1612,10 @@ LRESULT CDefView::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHa
 */
 LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
 {
-    DWORD                                dwCmdID;
-    DWORD                                dwCmd;
-    HWND                                hwndCmd;
+    DWORD dwCmdID;
+    DWORD dwCmd;
+    HWND  hwndCmd;
+    int   nCount; 
 
     dwCmdID = GET_WM_COMMAND_ID(wParam, lParam);
     dwCmd = GET_WM_COMMAND_CMD(wParam, lParam);
@@ -1588,6 +1660,16 @@ LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHand
             m_ListView.SortItems(ListViewCompareItems, &m_sortInfo);
             break;
 
+        case FCIDM_SHVIEW_SELECTALL:
+            m_ListView.SetItemState(-1, LVIS_SELECTED, LVIS_SELECTED);
+            break;
+
+        case FCIDM_SHVIEW_INVERTSELECTION:
+            nCount = m_ListView.GetItemCount();
+            for (int i=0; i < nCount; i++)
+                m_ListView.SetItemState(i, m_ListView.GetItemState(i, LVIS_SELECTED) ? 0 : LVIS_SELECTED, LVIS_SELECTED);
+            break;
+
         case FCIDM_SHVIEW_REFRESH:
             Refresh();
             break;
@@ -1746,12 +1828,24 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
             {
                 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0);
             }
+            if(lpdi->item.mask & LVIF_STATE)
+            {
+                ULONG attributes = SFGAO_HIDDEN;
+                if (SUCCEEDED(m_pSFParent->GetAttributesOf(1, &pidl, &attributes)))
+                {
+                    if (attributes & SFGAO_HIDDEN)
+                    {
+                        lpdi->item.state |= LVIS_CUT;
+                    }
+                }
+            }
             lpdi->item.mask |= LVIF_DI_SETITEM;
             break;
 
         case LVN_ITEMCHANGED:
             TRACE("-- LVN_ITEMCHANGED %p\n", this);
             OnStateChange(CDBOSC_SELCHANGE);  /* the browser will get the IDataObject now */
+            UpdateStatusbar();
             break;
 
         case LVN_BEGINDRAG:
@@ -1840,12 +1934,48 @@ LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
     return 0;
 }
 
+/*
+ * This is just a quick hack to make the desktop work correctly.
+ * ITranslateShellChangeNotify's IsChildID is undocumented, but most likely the way that
+ * a folder should know if it should update upon a change notification.
+ * It is exported by merged folders at a minimum.
+ */
+static BOOL ILIsParentOrSpecialParent(PCIDLIST_ABSOLUTE pidl1, PCIDLIST_ABSOLUTE pidl2)
+{
+    if (!pidl1 || !pidl2)
+        return FALSE;
+    if (ILIsParent(pidl1, pidl2, TRUE))
+        return TRUE;
+
+    if (_ILIsDesktop(pidl1))
+    {
+        PIDLIST_ABSOLUTE deskpidl;
+        SHGetFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, &deskpidl);
+        if (ILIsParent(deskpidl, pidl2, TRUE))
+        {
+            ILFree(deskpidl);
+            return TRUE;
+        }
+        ILFree(deskpidl);
+        SHGetFolderLocation(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, NULL, 0, &deskpidl);
+        if (ILIsParent(deskpidl, pidl2, TRUE))
+        {
+            ILFree(deskpidl);
+            return TRUE;
+        }
+        ILFree(deskpidl);
+    }
+    return FALSE;
+}
+
 /**********************************************************
 * ShellView_OnChange()
 */
 LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
 {
     PCIDLIST_ABSOLUTE *Pidls = reinterpret_cast<PCIDLIST_ABSOLUTE*>(wParam);
+    BOOL bParent0 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[0]);
+    BOOL bParent1 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[1]);
 
     TRACE("(%p)(%p,%p,0x%08x)\n", this, Pidls[0], Pidls[1], lParam);
 
@@ -1853,21 +1983,38 @@ LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &
     {
         case SHCNE_MKDIR:
         case SHCNE_CREATE:
-            LV_AddItem(ILFindLastID(Pidls[0]));
+            if (bParent0)
+            {
+                if (LV_FindItemByPidl(ILFindLastID(Pidls[0])) == -1)
+                {
+                    LV_AddItem(ILFindLastID(Pidls[0]));
+                }
+                else
+                {
+                    LV_ProdItem(ILFindLastID(Pidls[0]));
+                }
+            }
             break;
 
         case SHCNE_RMDIR:
         case SHCNE_DELETE:
-            LV_DeleteItem(ILFindLastID(Pidls[0]));
+            if (bParent0)
+                LV_DeleteItem(ILFindLastID(Pidls[0]));
             break;
 
         case SHCNE_RENAMEFOLDER:
         case SHCNE_RENAMEITEM:
-            LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[1]));
+            if (bParent0 && bParent1)
+                LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[1]));
+            else if (bParent0)
+                LV_DeleteItem(ILFindLastID(Pidls[0]));
+            else if (bParent1)
+                LV_AddItem(ILFindLastID(Pidls[1]));
             break;
 
         case SHCNE_UPDATEITEM:
-            LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[0]));
+            if (bParent0)
+                LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[0]));
             break;
 
         case SHCNE_UPDATEDIR:
@@ -1889,12 +2036,9 @@ LRESULT CDefView::OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bH
         return FALSE;
     }
 
-    CComPtr<IContextMenu2> pCM2;
-    HRESULT hres = m_pCM.p->QueryInterface(IID_PPV_ARG(IContextMenu2, &pCM2));
-    if(FAILED(hres))
-        return FALSE;
-
-    if (pCM2.p->HandleMenuMsg(uMsg, (WPARAM)m_hWnd, lParam) == S_OK)
+    LRESULT result;
+    HRESULT hres = SHForwardContextMenuMsg(m_pCM, uMsg, wParam, lParam, &result, TRUE);
+    if (SUCCEEDED(hres))
         return TRUE;
     else
         return FALSE;
@@ -2074,7 +2218,7 @@ HRESULT WINAPI CDefView::CreateViewWindow(IShellView *lpPrevView, LPCFOLDERSETTI
         TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView->left, prcView->top, prcView->right, prcView->bottom);
 
     /* Validate the Shell Browser */
-    if (psb == NULL)
+    if (psb == NULL || m_hWnd)
         return E_UNEXPECTED;
 
     /*set up the member variables*/
@@ -2139,7 +2283,7 @@ HRESULT WINAPI CDefView::DestroyViewWindow()
     if (m_hMenu)
     {
         DestroyMenu(m_hMenu);
-        m_hView = NULL;
+        m_hMenu = NULL;
     }
 
     if (m_ListView)
@@ -2795,7 +2939,7 @@ HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEf
     {
         /* We are not above one of the listview's subitems. Bind to the parent folder's
          * DropTarget interface. */
-        hr = m_pSFParent->QueryInterface(IID_PPV_ARG(IDropTarget,&m_pCurDropTarget));
+        hr = m_pSFParent->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget,&m_pCurDropTarget));
     }
     else
     {
@@ -2990,3 +3134,8 @@ HRESULT WINAPI IShellView_Constructor(IShellFolder *pFolder, IShellView **newVie
 {
     return ShellObjectCreatorInit<CDefView>(pFolder, IID_IShellView, newView);
 }
+
+HRESULT WINAPI CDefView_Constructor(IShellFolder *pFolder, REFIID riid, LPVOID * ppvOut)
+{
+    return ShellObjectCreatorInit<CDefView>(pFolder, riid, ppvOut);
+}