Figure 4   Registry Keys

 HKEY_CLASSES_ROOT\CLSID\{CLSID}\InProcServer32\(default)= path\filename.dll
HKEY_CLASSES_ROOT\CLSID\{CLSID}\InProcServer32\"ThreadingModel" = "Apartment"
HKEY_CLASSES_ROOT\CLSID\{CLSID}\DefaultIcon\(default)="path\filename.dll", IconIndex ; Icon to use for the name space data file itself (i.e. .CAB file)
HKEY_CLASSES_ROOT\CLSID\{CLSID}\Shell\Open\Command\(default) = c:\windows\Explorer.exe /root,%1
HKEY_CLASSES_ROOT\CLSID\{CLSID}\Shell\Explore\Command\(default) = c:\windows\Explorer.exe /e,/root,%1
HKEY_CLASSES_ROOT\CLSID\{CLSID}\ShellFolder\Attributes = 00 00 00 00 ; i.e. IShellFolder::GetAttributes() ; optional

Figure 9   CAB File Viewer Source Files

File(s)

Contents

Description

THISDLL.H, THISDLL.CPP

IClassFactory

Generic OLE DLL routines

FOLDER.H, FOLDER.CPP

IPersistFolder and IShellFolder

Implementation file for CCabFolder

SFVWND.H, SFVWND.CPP

IShellView and IDropSource

Implementation file for CSFVDropSource and CSFViewDlg

MENU.H, MENU.CPP

IContextMenu

Implementation file for CCabItemMenu

ICON.H, ICON.CPP

IExtractIcon

Implementation file for CCabItemIcon

ENUM.H, ENUM.CPP

IEnumIDList

Implementation for CEnumCabObjs

DATAOBJ.H, DATAOBJ.CPP

IDataObject, IEnumFORMATETC

Implementation file for CObjFormats and CCabObj

File(s)

Description

DEBUG.H, DEBUG.C

Debugging routines

XICON.H, XICON.CPP

Implementation file for CIconTemp and CXIcon

VIEW.H, VIEW.CPP

Implementation file for CCabView

UNKNOWN.H, UNKNOWN.CPP

Custom CUnknown implementations

STRINGS.H, STRINGS.C

DBCS-aware string routines

SFVIEW.H, SFVIEW.CPP

Implementation file for CSFView

PATH.H, PATH.C

Useful path manipulation routines

OS.H, OS.CPP

Implementation file for CFileTime

DLG.H, DLG.CPP

Implementation file for CDlg, CFileDlg and CPropPage

CABITMS.H, CABITMS.CPP

Implementation file for CMemFile, CCabEnum and CCabExtract

SFVMENU.CPP

Implementation file for CSFView menu related methods

IUTIL.C

Implementation of Shell_MergeMenus and some other useful routines

DA.C

Implementation of dynamic pointer arrays (DPAs)

FDI.LIB, FDI.H

Header and corresponding library for the File Decompression Interface

THISGUID.H

Definition of GUID for ThisDll

PCH.H

Common precompiled header file

DPDA.H

Definitions of dynamic pointer array routines

Figure 10   CAB File Viewer Source Excerpts

 

ThisDll.h

 //***********************************************************************
//                Generic OLE header file 
// Copyright (c) 1994 - 1996 Microsoft Corporation. All rights reserved
//***********************************************************************
.
.
.
class CWaitCursor
{
public:
    CWaitCursor() {m_cOld=SetCursor(LoadCursor(NULL, IDC_WAIT));}
    ~CWaitCursor() {SetCursor(m_cOld);}
private:
    HCURSOR m_cOld;
} ;

class CRefCount
{
public:
    CRefCount() : m_cRef(0) {};
    UINT AddRef()  {return(++m_cRef);}
    UINT Release() {return(--m_cRef);}
    UINT GetRef()  {return(  m_cRef);}

private:
    UINT m_cRef;
} ;

class CThisDll
{
public:
    CThisDll() {
        m_hInst=NULL;
    }
    // Make no destructor for global classes (requires CRT stuff)
    void SetInstance(HINSTANCE hInst) {m_hInst=hInst;}
    HINSTANCE GetInstance() {return(m_hInst);}

    CRefCount m_cRef;
    CRefCount m_cLock;
private:
    HINSTANCE    m_hInst;
} ;
.
.
.

ThisDll.cpp

 // ******************************************************************
//                Generic OLE DLL routines
// Copyright (c) 1994 - 1996 Microsoft Corporation. All rights reserved
// ******************************************************************
.
.
.
// ******************************************************************
// DllMain
STDAPI_(BOOL) APIENTRY DllMain(
   HINSTANCE hDll, 
   DWORD dwReason, 
   LPVOID lpReserved)
{
   switch(dwReason)
   {
      case DLL_PROCESS_ATTACH:
         g_ThisDll.SetInstance(hDll);
         // Initialize the various modules.
         //
         break;
      case DLL_PROCESS_DETACH:
         break;
      case DLL_THREAD_ATTACH:
         break;
      case DLL_THREAD_DETACH:
         break;
      default:
         break;
        } // switch
   return(TRUE);
}

// DllCanUnloadNow
STDAPI DllCanUnloadNow()
{
    HRESULT retval = (HRESULT)((g_ThisDll.m_cRef.GetRef() == 0)
        && (g_ThisDll.m_cLock.GetRef() == 0) ? S_OK : S_FALSE);
    return(retval);
}
.
.
.

class CThisDllClassFactory : public IClassFactory
{
public:
    // *** IUnknown methods ***
    STDMETHODIMP QueryInterface(REFIID riid,
        LPVOID FAR* ppvObj);
    STDMETHODIMP_(ULONG) AddRef(void);
    STDMETHODIMP_(ULONG) Release(void);
     // *** IClassFactory methods ***
    STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter,
        REFIID riid,
        LPVOID FAR* ppvObject);
    STDMETHODIMP LockServer(BOOL fLock);
private:
    CRefDll m_cRefDll;
    CRefCount m_cRef;
};

// DllGetClassObject
STDAPI DllGetClassObject(
   REFCLSID rclsid, 
   REFIID riid, 
   LPVOID FAR* ppvObj)
{
    *ppvObj = NULL;
    if(! (rclsid == CLSID_ThisDll))
    {
        return(E_FAIL);
    }
    CThisDllClassFactory *pcf = new CThisDllClassFactory;
    if (!pcf)
    {
        return(E_OUTOFMEMORY);
    }

    // Note if the QueryInterface fails, the Release will delete the object
    pcf->AddRef();
    HRESULT hRes = pcf->QueryInterface(riid, ppvObj);
    pcf->Release(); 
     return(hRes);
}

// CImpIClassFactory member functions
// *** IUnknown methods ***
STDMETHODIMP CThisDllClassFactory::QueryInterface(REFIID riid, 
                                                  LPVOID FAR* ppvObj)
{
    *ppvObj = NULL;
    // Any interface on this object is the object pointer
    if((riid == IID_IUnknown) || (riid == IID_IClassFactory))
    {
        *ppvObj = (LPVOID)(IClassFactory *)this;
    }
    if(*ppvObj)
    {
        ((LPUNKNOWN)*ppvObj)->AddRef();
        return NOERROR;
    }
    return(E_NOINTERFACE);
}

STDMETHODIMP_(ULONG) CThisDllClassFactory::AddRef(void)
{
    return(m_cRef.AddRef());
}

STDMETHODIMP_(ULONG) CThisDllClassFactory::Release(void)
{
    if (!m_cRef.Release())
    {
        delete this;
        return(0);
    }
  return(m_cRef.GetRef());
}
 
// *** IClassFactory methods ***
STDMETHODIMP CThisDllClassFactory::CreateInstance(LPUNKNOWN pUnkOuter,
        REFIID riid,
        LPVOID FAR* ppvObj)
{
    // we do not support aggregation
    if(pUnkOuter)
    {
        return(CLASS_E_NOAGGREGATION);
    }
    return(::CreateInstance(riid, ppvObj));
}

STDMETHODIMP CThisDllClassFactory::LockServer(BOOL fLock)
{
    if(fLock)
    {
        g_ThisDll.m_cLock.AddRef();
    }
    else
    {
        g_ThisDll.m_cLock.Release();
    }
    return(NOERROR);
}
.
.
.

Folder.h

 // ******************************************************************
//                Definitions of CCabFolder and CCabItemList
// Copyright (c) 1994 - 1996 Microsoft Corporation. All rights reserved
// ******************************************************************
.
.
.
class CCabFolder : public IPersistFolder, public IShellFolder
{
public:
    CCabFolder() : m_pidlHere(0), m_lItems(1024/sizeof(LPVOID)) {}
    ~CCabFolder()
    {
        if (m_pidlHere)
        {
            ILFree(m_pidlHere);
        }
    }

    // *** IUnknown methods ***
    STDMETHODIMP QueryInterface(
        REFIID riid, 
        LPVOID FAR* ppvObj);
    STDMETHODIMP_(ULONG) AddRef(void);
    STDMETHODIMP_(ULONG) Release(void);

    // *** IParseDisplayName method ***
    STDMETHODIMP ParseDisplayName(
        HWND hwndOwner,
        LPBC pbc, 
        LPOLESTR lpszDisplayName,
        ULONG FAR* pchEaten, 
        LPITEMIDLIST * ppidl,
        ULONG *pdwAttributes);
    
    //
    // *** IOleContainer methods ***
    //
    STDMETHODIMP EnumObjects(
        HWND hwndOwner, 
        DWORD grfFlags,
        LPENUMIDLIST * ppenumIDList);

    //
    // *** IShellFolder methods ***
    //
    STDMETHODIMP BindToObject(
        LPCITEMIDLIST pidl, 
        LPBC pbc,
        REFIID riid, 
        LPVOID FAR* ppvObj);
    STDMETHODIMP BindToStorage(
        LPCITEMIDLIST pidl, 
        LPBC pbc,
        REFIID riid, 
        LPVOID FAR* ppvObj);
    STDMETHODIMP CompareIDs(
        LPARAM lParam, 
        LPCITEMIDLIST pidl1,
        LPCITEMIDLIST pidl2);
    STDMETHODIMP CreateViewObject(
        HWND hwndOwner, 
        REFIID riid,
        LPVOID FAR* ppvObj);
    STDMETHODIMP GetAttributesOf(
        UINT cidl, 
        LPCITEMIDLIST FAR* apidl,
        ULONG FAR* rgfInOut);
    STDMETHODIMP GetUIObjectOf(
        HWND hwndOwner, 
        UINT cidl, 
        LPCITEMIDLIST FAR* apidl, 
        REFIID riid, 
        UINT FAR* prgfInOut, 
        LPVOID FAR* ppvObj);
    STDMETHODIMP GetDisplayNameOf(
        LPCITEMIDLIST pidl, 
        DWORD dwReserved, 
        LPSTRRET lpName);
    STDMETHODIMP SetNameOf(
        HWND hwndOwner, 
        LPCITEMIDLIST pidl,
        LPCOLESTR lpszName, 
        DWORD dwReserved,
        LPITEMIDLIST FAR* ppidlOut);
    //
    // *** IPersist methods ***
    //
    STDMETHODIMP GetClassID(
        LPCLSID lpClassID);
    //
    // *** IPersistFolder methods ***
    //
     STDMETHODIMP Initialize(
        LPCITEMIDLIST pidl);

public:
    static LPITEMIDLIST CreateIDList(LPCSTR pszName, DWORD dwFileSize,
        UINT uFileDate, UINT uFileTime, UINT uFileAttribs);
    static void GetNameOf(LPCABITEM pit, LPSTRRET lpName);
    static void GetTypeOf(LPCABITEM pit, LPSTRRET lpName);

    BOOL GetPath(LPSTR szPath);

private:
    static void CALLBACK EnumToList(LPCSTR pszFile, DWORD dwSize, UINT date,
        UINT time, UINT attribs, LPARAM lParam);

    HRESULT InitItems();

private:
    CRefDll m_cRefDll;

    CRefCount m_cRef;

    LPITEMIDLIST m_pidlHere;        // maintains the current pidl

    CCabItemList m_lItems;

    friend class CEnumCabObjs;
} ;
.
.
.

folder.cpp

 // ******************************************************************    
//                CAB Files Shell Extension
// Copyright (c) 1994 - 1996 Microsoft Corporation. All rights reserved
// ******************************************************************
.
.
.
// *** IUnknown methods ***
STDMETHODIMP CCabFolder::QueryInterface(
   REFIID riid, 
   LPVOID FAR* ppvObj)
{
    *ppvObj = NULL;

    LPVOID pObj;
 
    if (riid == IID_IUnknown)
    {
        pObj = (IUnknown*)((IShellFolder*)this); 
        // The (IShellFolder*) ^^^ up there is to disambiguate the reference
    }
    else if (riid == IID_IShellFolder)
    {
        pObj = (IShellFolder*)this;
    }
    else if (riid == IID_IPersistFolder)
    {
        pObj = (IPersistFolder*)this;
    }
    else
    {
           return(E_NOINTERFACE);
    }

    ((LPUNKNOWN)pObj)->AddRef();
    *ppvObj = pObj;

    return(NOERROR);
}


STDMETHODIMP_(ULONG) CCabFolder::AddRef(void)
{
    return(m_cRef.AddRef());
}


STDMETHODIMP_(ULONG) CCabFolder::Release(void)
{
    if (!m_cRef.Release())
    {
           delete this;
        return(0);
    }

    return(m_cRef.GetRef());
}

// *** IParseDisplayName method ***
STDMETHODIMP CCabFolder::ParseDisplayName(
   HWND hwndOwner,
   LPBC pbc, 
   LPOLESTR lpszDisplayName,
   ULONG FAR* pchEaten, 
   LPITEMIDLIST * ppidl,
   ULONG *pdwAttributes)
{
    return(E_NOTIMPL);
}

// *** IOleContainer methods ***
//**********************************************************************
// CCabFolder::EnumObjects
// Purpose:
//      Creates an item enumeration object 
//      (an IEnumIDList interface) that can be used to 
//      enumerate the contents of a folder.
// Parameters:
//       HWND hwndOwner       -    handle to the owner window
//       DWORD grFlags        -    flags about which items to include
//       LPENUMIDLIST *ppenumIDList - address that receives IEnumIDList
//                                    interface pointer 
//********************************************************************
STDMETHODIMP CCabFolder::EnumObjects(
   HWND hwndOwner, 
   DWORD grfFlags,
   LPENUMIDLIST * ppenumIDList) // LPENUMUNKNOWN FAR* ppenumUnknown)
{
    CEnumCabObjs *pce = new CEnumCabObjs(this, grfFlags);
    if (!pce)
    {
        return(E_OUTOFMEMORY);
    }

    pce->AddRef();
    HRESULT hRes = pce->QueryInterface(IID_IEnumIDList, (LPVOID*)ppenumIDList);
    pce->Release();

    return(hRes);
}

// *** IShellFolder methods ***
// subfolders not implemented
STDMETHODIMP CCabFolder::BindToObject(
   LPCITEMIDLIST pidl, 
   LPBC pbc,
   REFIID riid, 
   LPVOID FAR* ppvObj)
{
    return(E_NOTIMPL);
}


STDMETHODIMP CCabFolder::BindToStorage(
   LPCITEMIDLIST pidl, 
   LPBC pbc,
   REFIID riid, 
   LPVOID FAR* ppvObj)
{
    return(E_NOTIMPL);
}

//**********************************************************************
// CCabFolder::CompareIDs
// Purpose:
//      Determines the relative ordering of two file
//      objects or folders, given their item identifier lists
// Parameters:
//      LPARAM lParam         -    type of comparison
//      LPCITEMIDLIST pidl1   -    address to ITEMIDLIST
//      LPCITEMIDLIST pidl2   -    address to ITEMIDLIST
//********************************************************************
STDMETHODIMP CCabFolder::CompareIDs(
   LPARAM lParam, 
   LPCITEMIDLIST pidl1,
   LPCITEMIDLIST pidl2)
{
    LPCABITEM pit1 = (LPCABITEM)pidl1;
    LPCABITEM pit2 = (LPCABITEM)pidl2;
    short nCmp = 0;
    switch (lParam)
    {
    case CV_COL_NAME:
        break;
    case CV_COL_SIZE:
        if (pit1->dwFileSize < pit2->dwFileSize)
        {
            nCmp = -1;
        }
        else if (pit1->dwFileSize > pit2->dwFileSize)
        {
            nCmp = 1;
        }
        break;
    case CV_COL_TYPE:
    {
        STRRET srName1, srName2;
        GetTypeOf(pit1, &srName1);
        GetTypeOf(pit2, &srName2);
        nCmp = (SHORT)lstrcmp(srName1.cStr, srName2.cStr);
        break;
    }
    case CV_COL_MODIFIED:
        FILETIME ft1, ft2;
        DosDateTimeToFileTime(pit1->uFileDate, pit1->uFileTime, &ft1);
        DosDateTimeToFileTime(pit2->uFileDate, pit2->uFileTime, &ft2);
        nCmp = (SHORT)CompareFileTime(&ft1, &ft2);
        break;
    default:
        break;
    }
    if (nCmp != 0)
    {
        return(ResultFromShort(nCmp));
    }
    return(ResultFromShort(lstrcmpi(pit1->szName, pit2->szName)));
}

//**********************************************************************
// CCabFolder::CreateViewObject
// Purpose:
//      IShellbrowser calls this to create a ShellView object 
// Parameters:
//      HWND   hwndOwner     -
//      REFIID riid          -  interface ID
//      LPVOID * ppvObj      -  pointer to the Shellview object
// Return Value:
//      NOERROR
//      E_OUTOFMEMORY
//      E_NOINTERFACE
// Comments:
//      ShellBrowser interface calls this to request the ShellFolder
//      to create a ShellView object
//********************************************************************
STDMETHODIMP CCabFolder::CreateViewObject(
   HWND hwndOwner, 
   REFIID riid,
   LPVOID FAR* ppvObj)
{
    IUnknown *pObj = NULL;
    if (riid == IID_IShellView)
    {
        // Create a call back for the ShellView
        IShellFolderViewCallback *pcb;
        HRESULT hRes = CabView_CreateCallback(&pcb);
        hRes = CreateShellFolderView(this, pcb, (LPSHELLVIEW FAR*)&pObj);
        if (pcb)
        {
            // The ShellFolderView should have AddRef'ed if it needed it.
            pcb->Release();
        }
        if (FAILED(hRes))
        {
            return(hRes);
        }
    }
    else
    {
        return(E_NOINTERFACE);
    }
    if (!pObj)
    {
        return(E_OUTOFMEMORY);
    }
    // The ref count is already 1
    HRESULT hRes = pObj->QueryInterface(riid, ppvObj);
    pObj->Release();
    return(NOERROR);
}
// ***************************************************************************
// CCabFolder::GetAttributesOf
// Purpose: Retrieves attributes of one of more file objects
// Parameters:
//    UINT cidl                -    number of file objects
//    LPCITEMIDLIST  *apidl    -    pointer to array of ITEMIDLIST
//    ULONG *rgfInOut          -    array of values that specify file object
//                                  attributes
// Return Value:
//     NOERROR
//********************************************************************
STDMETHODIMP CCabFolder::GetAttributesOf(
   UINT cidl, 
   LPCITEMIDLIST FAR* apidl,
   ULONG FAR* rgfInOut)
{
    *rgfInOut &= SFGAO_CANCOPY;
    return(NOERROR);
}

//********************************************************************
// CCabFolder::GetUIObjectOf
// Purpose: Returns an interface that can be used to carry out actions on
//          the specified file objects or folders
// Parameters:
//        HWND hwndOwner        -    handle of the Owner window
//        UINT cidl             -    Number of file objects
//        LPCITEMIDLIST *apidl  -    array of file object pidls
//        REFIID                -    Identifier of interface to return
//        UINT * prgfInOut      -    reserved
//        LPVOID *ppvObj        -    address that receives interface pointer
// Return Value:
//         E_INVALIDARG
//         E_NOINTERFACE
//         E_OUTOFMEMORY
// **********************************************************************
STDMETHODIMP CCabFolder::GetUIObjectOf(
   HWND hwndOwner, 
   UINT cidl, 
   LPCITEMIDLIST FAR* apidl, 
   REFIID riid, 
   UINT FAR* prgfInOut, 
   LPVOID FAR* ppvObj)
{
    LPUNKNOWN pObj = NULL;
    if (riid == IID_IExtractIcon)
    {
        if (cidl != 1)
        {
            return(E_INVALIDARG);
        }
        LPCABITEM pci = (LPCABITEM)*apidl;
        pObj = (LPUNKNOWN)(IExtractIcon *)(new CCabItemIcon(pci->szName));
    }
    else if (riid == IID_IContextMenu)
    {
        if (cidl < 1)
        {
            return(E_INVALIDARG);
        }
        pObj = (LPUNKNOWN)(IContextMenu *)(new CCabItemMenu(hwndOwner, this,
            (LPCABITEM *)apidl, cidl));
    }
    else if (riid == IID_IDataObject)
    {
        if (cidl < 1)
        {
            return(E_INVALIDARG);
        }
        pObj = (LPUNKNOWN)(IDataObject *)(new CCabObj(hwndOwner, this,
            (LPCABITEM *)apidl, cidl));
    }
    else
    {
        return(E_NOINTERFACE);
    }
    if (!pObj)
    {
        return(E_OUTOFMEMORY);
    }
    pObj->AddRef();
    HRESULT hRes = pObj->QueryInterface(riid, ppvObj);
    pObj->Release();
    return(hRes);
}

// **********************************************************************
// CCabFolder::GetDisplayNameOf
// Purpose: Retrieves the display name for the specified file object or 
//          subfolder.
// Parameters:
//        LPCITEMIDLIST    pidl    -    pidl of the file object
//        DWORD  dwReserved        -    Value of the type of display name to 
//                                      return
//        LPSTRRET  lpName         -    address holding the name returned        
// **********************************************************************
STDMETHODIMP CCabFolder::GetDisplayNameOf(
   LPCITEMIDLIST pidl, 
   DWORD dwReserved, 
   LPSTRRET lpName)
{
    LPCABITEM pit = (LPCABITEM)pidl;
    GetNameOf(pit, lpName);
    return(NOERROR);
}

STDMETHODIMP CCabFolder::SetNameOf(
   HWND hwndOwner, 
   LPCITEMIDLIST pidl,
   LPCOLESTR lpszName, 
   DWORD dwReserved,
   LPITEMIDLIST FAR* ppidlOut)
{
    return(E_NOTIMPL);
}
// *** IPersist methods ***
//**********************************************************************
// CCabFolder::GetClassID
// Purpose: Return the class id
// Parameters:
//      LPCLSID lpClassID       -   pointer to the ClassID member
// Return Value:
//      NOERROR
// Comments:
//      This routine returns the Class ID for the DLL
//********************************************************************
STDMETHODIMP CCabFolder::GetClassID(
   LPCLSID lpClassID)
{
    *lpClassID = CLSID_ThisDll;
    return NOERROR;
}

// *** IPersistFolder methods ***
//**********************************************************************
// CCabFolder::Initialize folder
// Purpose: Explorer calls this while initializing the ShellFolder 
//          object
// Parameters:
//      LPCITEMIDLIST pidl        -   pidl passed by IShellBrowser
// Return Value:
//      S_OK
// Comments:
//      This routine is called by Explorer during initialization
//**********************************************************************
STDMETHODIMP CCabFolder::Initialize(
   LPCITEMIDLIST pidl)
{
    if (m_pidlHere)
    {
        ILFree(m_pidlHere);
    }
    // Clone the pidl passed by the explorer
    m_pidlHere = ILClone(pidl);
    if (!m_pidlHere)
    {
        return(E_OUTOFMEMORY);
    }
    return(S_OK);
}

// **********************************************************************
// CCabFolder::CreateIDList
// Purpose: Creates an item identifier list for the objects in the namespace
// **********************************************************************
LPITEMIDLIST CCabFolder::CreateIDList(LPCSTR pszName, DWORD dwFileSize,
    UINT uFileDate, UINT uFileTime, UINT uFileAttribs)
{
    // We'll assume no name is longer than MAX_PATH
    // Note the terminating NULL is already in the sizeof(CABITEM)
    BYTE bBuf[sizeof(CABITEM) + MAX_PATH + sizeof(WORD)];
    LPCABITEM pci = (LPCABITEM)bBuf;
    UINT uNameLen = lstrlen(pszName);
    if (uNameLen >= MAX_PATH)
    {
        uNameLen = MAX_PATH;
    }
    pci->wSize = (WORD)(sizeof(CABITEM) + uNameLen);
    pci->dwFileSize = dwFileSize;
    pci->uFileDate = (USHORT)uFileDate;
    pci->uFileTime = (USHORT)uFileTime;
    pci->uFileAttribs = (USHORT)uFileAttribs;
    lstrcpyn(pci->szName, pszName, uNameLen+1);
    // Terminate the IDList
    *(WORD *)(((LPSTR)pci)+pci->wSize) = 0;

    return(ILClone((LPCITEMIDLIST)pci));
}

// **********************************************************************
// CCabFolder::GetPath
// Purpose: Get the Path for the current pidl
// Parameters:
//        LPSTR szPath        -    return pointer for path string
// **********************************************************************
BOOL CCabFolder::GetPath(LPSTR szPath)
{
    if (!m_pidlHere || !SHGetPathFromIDList(m_pidlHere, szPath))
    {
        *szPath = '\0';
        return(FALSE);
    }
    return(TRUE);
}

void CCabFolder::GetNameOf(LPCABITEM pit, LPSTRRET lpName)
{
    lpName->uType = STRRET_OFFSET;
    lpName->uOffset = FIELDOFFSET(CABITEM, szName);
    SHFILEINFO sfi;
    if (SHGetFileInfo(pit->szName, 0, &sfi, sizeof(sfi),
        SHGFI_USEFILEATTRIBUTES | SHGFI_DISPLAYNAME)
        && lstrcmp(sfi.szDisplayName, pit->szName) != 0)
    {
        lpName->uType = STRRET_CSTR;
        lstrcpy(lpName->cStr, sfi.szDisplayName);
    }
}

void CCabFolder::GetTypeOf(LPCABITEM pit, LPSTRRET lpName)
{
    lpName->uType = STRRET_CSTR;
    lpName->cStr[0] = '\0';
    SHFILEINFO sfi;
    if (SHGetFileInfo(pit->szName, 0, &sfi, sizeof(sfi),
        SHGFI_USEFILEATTRIBUTES | SHGFI_TYPENAME))
    {
        lstrcpy(lpName->cStr, sfi.szTypeName);
    }
}
// **********************************************************************
// CCabFolder::EnumToList
// Purpose: This notify callback is called by the FDI routines. It adds the
//          file object from the cab file to the list.  
// **********************************************************************
void CALLBACK CCabFolder::EnumToList(LPCSTR pszFile, DWORD dwSize, UINT date,
                                     UINT time, UINT attribs, LPARAM lParam)
{
    CCabFolder *pThis = (CCabFolder *)lParam;
    pThis->m_lItems.AddItem(pszFile, dwSize, date, time, attribs);
}

HRESULT CCabFolder::InitItems()
{
    switch (m_lItems.GetState())
    {
    case CCabItemList::State_Init:
        return(NOERROR);
    case CCabItemList::State_OutOfMem:
        return(E_OUTOFMEMORY);
    case CCabItemList::State_UnInit:
    default:
        break;
    }
    // Force the list to initialize
    m_lItems.InitList();
    char szHere[MAX_PATH];
    // the m_pidl has been set to current dir
    // get the path to the current directory
    if (!GetPath(szHere))
    {
        return(E_UNEXPECTED);
    }
    CCabItems ciHere(szHere);
    if (!ciHere.EnumItems(EnumToList, (LPARAM)this))
    {
        return(E_UNEXPECTED);
    }
    return(NOERROR);
}

// **********************************************************************
// CreateInstance
// Purpose: Create a CCabFolder object and returns it
// Parameters:
//        REFIID riid        -    a reference to the interface that is
//                                being queried    
//        LPVOID *ppvObj    -    an out parameter to return a pointer to
//                               interface being queried
// **********************************************************************
HRESULT CreateInstance(REFIID riid, LPVOID *ppvObj)
{   IUnknown *pObj = NULL;
    *ppvObj = NULL;
    if(riid == IID_IPersistFolder)
    {
        pObj = (IUnknown *)(IPersistFolder *)(new CCabFolder);
    }
    else if(riid == IID_IShellFolder)
    {
        pObj = (IUnknown *)(IShellFolder *)(new CCabFolder);
    }
    else
    {
        return(E_NOINTERFACE);
    }
    if (!pObj)
    {
        return(E_OUTOFMEMORY);
    }
    pObj->AddRef();
    HRESULT hRes = pObj->QueryInterface(riid, ppvObj);
    pObj->Release();
    return(hRes);
}
.
.
.

Enum.h

 // **********************************************************************
//
//                Definition of CEnumCabObjs
//
//  Copyright (c) 1994 - 1996 Microsoft Corporation. All rights reserved
//
// **********************************************************************
.
.
.

// Enumeration object for the CabFolder
class CEnumCabObjs : public IEnumIDList
{
public:
    CEnumCabObjs(CCabFolder *pcf, DWORD uFlags) : m_iCount(0)
    {
        m_uFlags = uFlags;
        m_pcfThis=pcf;
        pcf->AddRef();
    }
    ~CEnumCabObjs()
    {
        m_pcfThis->Release();
    }
    // *** IUnknown methods ***
    STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
    STDMETHODIMP_(ULONG) AddRef();
    STDMETHODIMP_(ULONG) Release();
    // *** IEnumIDList methods ***
    STDMETHODIMP Next(ULONG celt,
              LPITEMIDLIST *rgelt,
              ULONG *pceltFetched);
    STDMETHODIMP Skip(ULONG celt);
    STDMETHODIMP Reset();
    STDMETHODIMP Clone(IEnumIDList **ppenum);
private:
    CRefDll m_cRefDll;
    CRefCount m_cRef;
    CCabFolder *m_pcfThis;
    UINT m_iCount;
    DWORD m_uFlags;
} ;
.
.
.

Enum.cpp

 // **********************************************************************
//                Implementation for CEnumCabObjs
// Copyright (c) 1994 - 1996 Microsoft Corporation. All rights reserved
// **********************************************************************
.
.
.
// *** IUnknown methods ***
STDMETHODIMP CEnumCabObjs::QueryInterface(
   REFIID riid, 
   LPVOID FAR* ppvObj)
{
    *ppvObj = NULL;
    LPUNKNOWN pObj;
    if (riid == IID_IUnknown)
    {
        pObj = (IUnknown*)((IEnumIDList*)this); 
    }
    else if (riid == IID_IEnumIDList)
    {
        pObj = (IUnknown*)((IEnumIDList*)this); 
    }
    else
    {
           return(E_NOINTERFACE);
    }
    pObj->AddRef();
    *ppvObj = pObj;
    return(NOERROR);
}

STDMETHODIMP_(ULONG) CEnumCabObjs::AddRef(void)
{
    return(m_cRef.AddRef());
}

STDMETHODIMP_(ULONG) CEnumCabObjs::Release(void)
{
    if (!m_cRef.Release())
    {
        delete this;
        return(0);
    }
    return(m_cRef.GetRef());
}

// *** IEnumIDList methods ***
STDMETHODIMP CEnumCabObjs::Next(ULONG celt,
          LPITEMIDLIST *rgelt,
          ULONG *pceltFetched)
{
    *rgelt = NULL;
    if (pceltFetched)
    {
        *pceltFetched = 0;
    }
    HRESULT hRes = m_pcfThis->InitItems();
    if (FAILED(hRes))
    {
        return(hRes);
    }
    for ( ; ; ++m_iCount)
    {
        if (m_iCount >= m_pcfThis->m_lItems.GetCount())
        {
            return(S_FALSE);
        }
        LPCABITEM pit = m_pcfThis->m_lItems[m_iCount];
        if ((m_uFlags&(SHCONTF_FOLDERS|SHCONTF_NONFOLDERS))
            != (SHCONTF_FOLDERS|SHCONTF_NONFOLDERS))
        {
            DWORD gfInOut = SFGAO_FOLDER;
            if (FAILED(m_pcfThis->GetAttributesOf(1, (LPCITEMIDLIST *)&pit,
                &gfInOut)))
            {
                continue;
            }
            if (!(m_uFlags&SHCONTF_FOLDERS) && (gfInOut&SFGAO_FOLDER))
            {
                continue;
            }
            if ((m_uFlags&SHCONTF_FOLDERS) && !(gfInOut&SFGAO_FOLDER))
            {
                continue;
            }
        }
        if (!(m_uFlags&SHCONTF_INCLUDEHIDDEN)
            && (pit->uFileAttribs&
               (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM)))
        {
            continue;
        }
        break;
    }
    *rgelt = ILClone((LPCITEMIDLIST)m_pcfThis->m_lItems[m_iCount]);
    ++m_iCount;
    if (*rgelt)
    {
        if (pceltFetched)
        {
            *pceltFetched = 1;
        }
        return(S_OK);
    }
    return(E_OUTOFMEMORY);
}

STDMETHODIMP CEnumCabObjs::Skip(ULONG celt)
{
    return(E_NOTIMPL);
}

STDMETHODIMP CEnumCabObjs::Reset()
{
    m_iCount = 0;

    return(NOERROR);
}

STDMETHODIMP CEnumCabObjs::Clone(IEnumIDList **ppenum)
{
    return(E_NOTIMPL);
}
.
.
.

SFWnd.h

 //**********************************************************************
//     Definitions of CListView, CSFViewDlg, CAccelerator, CSFView
//  Copyright (c) 1994 - 1996 Microsoft Corporation. All rights reserved
//**********************************************************************
.
.
.
#define IDC_ARRANGE_BY (FCIDM_SHVIEWFIRST + 0x100)
.
.
.
#define SFV_CONTEXT_FIRST (FCIDM_SHVIEWFIRST + 0x1000)
#define SFV_CONTEXT_LAST (FCIDM_SHVIEWFIRST + 0x2000)
BOOL StrRetToStr(LPSTR szOut, UINT uszOut, LPSTRRET pStrRet, LPCITEMIDLIST pidl);
class CListView
{
public:
    CListView() {}
    ~CListView() {}
    operator HWND() const {return(m_hwndList);}
    void Init(HWND hwndList, HWND hwndLB, UINT idiDef)
    {
        m_hwndList = hwndList;
        m_cxi.Init(hwndLB, idiDef);
        ListView_SetImageList(hwndList, m_cxi.GetIML(TRUE), LVSIL_NORMAL);
        ListView_SetImageList(hwndList, m_cxi.GetIML(FALSE), LVSIL_SMALL);
    }
    int InsertItem(LV_ITEM *pItem)
    {
        return(ListView_InsertItem(m_hwndList, pItem));
    }
    void DeleteAllItems() {ListView_DeleteAllItems(m_hwndList);}
    enum
    {
        AI_LARGE = CXIcon::AI_LARGE,
        AI_SMALL = CXIcon::AI_SMALL,
    } ;
    int GetIcon(IShellFolder *psf, LPCITEMIDLIST pidl)
    {
        return(m_cxi.GetIcon(psf, pidl));
    }
private:
    HWND m_hwndList;
    CXIcon m_cxi;
} ;
.
.
.
// CSFView - IShellView implementation
class CSFView : public CUnknown, public IShellView
{
public:
    CSFView(LPSHELLFOLDER psf, IShellFolderViewCallback *psfvcb);
    virtual ~CSFView();
    STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
    STDMETHODIMP_(ULONG) AddRef();
    STDMETHODIMP_(ULONG) Release();
    // *** IOleWindow methods ***
    STDMETHODIMP GetWindow(HWND * lphwnd);
    STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode);
    // *** IShellView methods ***
    STDMETHODIMP TranslateAccelerator(LPMSG lpmsg);
    STDMETHODIMP EnableModeless(BOOL fEnable);
    STDMETHODIMP UIActivate(UINT uState);
    STDMETHODIMP Refresh();
    STDMETHODIMP CreateViewWindow(IShellView  *lpPrevView,
                    LPCFOLDERSETTINGS lpfs, IShellBrowser  * psb,
                    RECT * prcView, HWND  *phWnd);
    STDMETHODIMP DestroyViewWindow();
    STDMETHODIMP GetCurrentInfo(LPFOLDERSETTINGS lpfs);
    STDMETHODIMP AddPropertySheetPages(DWORD dwReserved,
                                       LPFNADDPROPSHEETPAGE lpfn, 
                                       LPARAM lparam);
    STDMETHODIMP SaveViewState();
    STDMETHODIMP SelectItem(LPCITEMIDLIST pidlItem, UINT uFlags);
    STDMETHODIMP GetItemObject(UINT uItem, REFIID riid, LPVOID *ppv);
private:
    static int CALLBACK CSFView::CompareIDs(LPVOID p1, LPVOID p2, 
                                            LPARAM lParam);
    void AddColumns();
    BOOL SaveColumns(LPSTREAM pstm);
    void RestoreColumns(LPSTREAM pstm, int nCols);
    void RestoreViewState();
    void ColumnClick(int iCol)
    {
        m_sfState.lParamSort = (LPARAM)DPA_GetPtr(m_aParamSort, iCol);
        m_cView.SortItems(CompareIDs);
    }
    HRESULT CallCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        return(m_psfvcb ? m_psfvcb->Message(uMsg, wParam, 
                                            lParam) : E_NOTIMPL);
    }
    int GetMenuIDFromViewMode();
    BOOL IsInCommDlg() {return(m_pCDB != NULL);}
    HRESULT IncludeObject(LPCITEMIDLIST pidl)
    {
        return(IsInCommDlg() ? m_pCDB->IncludeObject(this, pidl) : S_OK);
    }
    HRESULT OnDefaultCommand()
    {
        return(IsInCommDlg() ? m_pCDB->OnDefaultCommand(this) : S_FALSE);
    }
    HRESULT OnStateChange(UINT uFlags)
    {
        return(IsInCommDlg() ? m_pCDB->OnStateChange(this, uFlags) : S_FALSE);
    }
    void InitFileMenu(HMENU hmInit);
    void InitEditMenu(HMENU hmInit);
    void InitViewMenu(HMENU hmInit);
    int AddObject(LPCITEMIDLIST pidl);
    HRESULT FillList(BOOL bInteractive);
    BOOL ShowAllObjects() {return(TRUE);}
    void MergeArrangeMenu(HMENU hmView);
    void MergeViewMenu(HMENU hmenu, HMENU hmMerge);
    BOOL OnActivate(UINT uState);
    BOOL OnDeactivate();
    IContextMenu * GetSelContextMenu();
    void ReleaseSelContextMenu();
    BOOL OnInitMenuPopup(HMENU hmInit, int nIndex, BOOL fSystemMenu);
    void OnCommand(IContextMenu *pcm, WPARAM wParam, LPARAM lParam);
    void CheckToolbar();
    void MergeToolBar();
    BOOL GetArrangeText(int iCol, UINT idFmt, LPSTR pszText, UINT cText);
    void GetCommandHelpText(UINT id, LPSTR pszText, UINT cchText, BOOL bToolTip);
    LRESULT OnMenuSelect(UINT idCmd, UINT uFlags, HMENU hmenu);
    LPSHELLFOLDER m_psf;                       // ShellFolder pointer
    ICommDlgBrowser *m_pCDB;                   // ICommdlgBrowser
    IShellFolderViewCallback *m_psfvcb;        // pointer to ShellFolderView 
                                               // callback
    CEnsureRelease m_erFolder; 
    CEnsureRelease m_erCB;
    CSFViewDlg m_cView;                        //  ViewDlg which contains the
                                               //  listview in the right pane
    HWND m_hwndMain;
    FOLDERSETTINGS m_fs;
    IShellBrowser *m_psb;
    SFSTATE m_sfState;
    CMenuTemp m_cmCur;
    UINT m_uState;
    IContextMenu *m_pcmSel;
    HDPA m_aParamSort;                         // maintains a sorted list of 
                                               // items in a DPA
    CAccelerator m_cAccel;
    CSafeMalloc m_cMalloc;
    friend class CSFViewDlg;
} ;
.
.
.

Sfview.cpp

 // **********************************************************************
//                Implementation file for CSFView
//  Copyright (c) 1994 - 1996 Microsoft Corporation. All rights reserved
// **********************************************************************
.
.
.
CSFView::CSFView(LPSHELLFOLDER psf, IShellFolderViewCallback *psfvcb) :
    m_psf(psf), m_erFolder(psf), m_erCB(psfvcb), m_pCDB(NULL), m_cView(this),
    m_uState(SVUIA_DEACTIVATE), m_pcmSel(NULL), m_cAccel(IDA_MAIN)
{
    m_psfvcb = psfvcb;
    if (psfvcb)
    {
        psfvcb->AddRef();
    }
    psf->AddRef();
    m_aParamSort = DPA_Create(4);
    m_sfState.lParamSort = 0;
}
.
.
.
CSFView::~CSFView()
{
    ReleaseSelContextMenu();
}

STDMETHODIMP CSFView::QueryInterface(REFIID riid, LPVOID * ppvObj)
{
    static const IID *apiid[] = { &IID_IShellView, NULL };
    LPUNKNOWN aobj[] = { (IShellView *)this };

    return(QIHelper(riid, ppvObj, apiid, aobj));
}

STDMETHODIMP_(ULONG) CSFView::AddRef()
{
    return(AddRefHelper());
}

STDMETHODIMP_(ULONG) CSFView::Release()
{
    return(ReleaseHelper());
}

STDMETHODIMP CSFView::GetWindow(HWND * lphwnd)
{
    return(E_NOTIMPL);
}

STDMETHODIMP CSFView::ContextSensitiveHelp(BOOL fEnterMode)
{
    return(E_NOTIMPL);
}

// **********************************************************************
// CSFView::TranslateAccelerator
// Purpose: Handle the accelerator keystrokes
// Parameters:
//        LPMSG lpmsg    -    message structure
// **********************************************************************
STDMETHODIMP CSFView::TranslateAccelerator(LPMSG lpmsg)
{
    return(m_cAccel.TranslateAccelerator(m_cView, lpmsg) ? S_OK : S_FALSE);
}

STDMETHODIMP CSFView::EnableModeless(BOOL fEnable)
{
    return(E_NOTIMPL);
}

// **********************************************************************
// CSFView:UIActivate
// Purpose: The explorer calls this member function whenever the activation         
//  state of the view window is changed by a certain event that is           
//  NOT caused by the shell view itself.
// Parameters:
//        UINT uState    -    UI activate flag
// **********************************************************************
STDMETHODIMP CSFView::UIActivate(UINT uState)
{
    if (uState)
    {
        OnActivate(uState);
    }
    else
    {
        OnDeactivate();
    }
    return S_OK;
}

STDMETHODIMP CSFView::Refresh()
{
    return(E_NOTIMPL);
}

// **********************************************************************
// CSFView::CreateViewWindow
// Purpose: Called by IShellBrowser to create a contents pane window
// Parameters:
//    IShellView  *lpPrevView    -    previous view
//    LPCFOLDERSETTINGS lpfs     -    folder settings for the view
//    IShellBrowser *psb         -    pointer to the shell browser
//    RECT * prcView             -    view Rectangle
//    HWND * phWnd               -    pointer to Window handle
// **********************************************************************
STDMETHODIMP CSFView::CreateViewWindow(IShellView  *lpPrevView,
                                       LPCFOLDERSETTINGS lpfs, 
                                       IShellBrowser  * psb, RECT * prcView,
                                       HWND  *phWnd)
{
    *phWnd = NULL;
    if ((HWND)m_cView)
    {
        return(E_UNEXPECTED);
    }
    m_fs = *lpfs;
    m_psb = psb;
    // get the main window handle from shell browser
    psb->GetWindow(&m_hwndMain);
    // bring up the contents pane
    if (!m_cView.DoModeless(IDD_VIEW, m_hwndMain))
    {
        return(E_OUTOFMEMORY);
    }
    *phWnd = m_cView;
    // map the current view mode into menu id and set the contents pane
    // view mode accordingly
    OnCommand(NULL, GET_WM_COMMAND_MPS(GetMenuIDFromViewMode(), 0, 0));
    AddColumns();
    RestoreViewState();
    // size the contents pane
    SetWindowPos(m_cView, NULL, prcView->left, prcView->top,
                 prcView->right-prcView->left, prcView->bottom-prcView->top,
                 SWP_NOZORDER|SWP_SHOWWINDOW);
    FillList(TRUE);
    return(NOERROR);
}

STDMETHODIMP CSFView::DestroyViewWindow()
{
    if (!(HWND)m_cView)
    {
        return(E_UNEXPECTED);
    }
    m_cView.DestroyWindow();
    return(NOERROR);
}

STDMETHODIMP CSFView::GetCurrentInfo(LPFOLDERSETTINGS lpfs)
{
    *lpfs = m_fs;
    return(NOERROR);
}

STDMETHODIMP CSFView::AddPropertySheetPages(DWORD dwReserved,
                                            LPFNADDPROPSHEETPAGE lpfn, 
                                            LPARAM lparam)
{
    return(E_NOTIMPL);
}

STDMETHODIMP CSFView::SaveViewState()
{
    SFSTATE_HDR hdr;
    LPSTREAM pstm;
    HRESULT hres = m_psb->GetViewStateStream(STGM_WRITE, &pstm);
    if (FAILED(hres))
    {
        return(hres);
    }
    CEnsureRelease erStr(pstm);
    pstm->Write(&hdr, sizeof(hdr), NULL);
    hdr.clsThis = CLSID_ThisDll;
    hdr.sfState = m_sfState;
    hdr.nCols = SaveColumns(pstm);
    ULARGE_INTEGER libCurPosition;
    LARGE_INTEGER dlibMove;
    dlibMove.HighPart = 0;
    dlibMove.LowPart = 0;
    pstm->Seek(dlibMove, STREAM_SEEK_SET, &libCurPosition);
    hres = pstm->Write(&hdr, sizeof(hdr), NULL);
    return(hres);
}

STDMETHODIMP CSFView::SelectItem(LPCITEMIDLIST pidlItem, UINT uFlags)
{
    return(E_NOTIMPL);
}

STDMETHODIMP CSFView::GetItemObject(UINT uItem, REFIID riid,
                LPVOID *ppv)
{
    return(E_NOTIMPL);
}

int CSFView::AddObject(LPCITEMIDLIST pidl)
{
    // Check the commdlg hook to see if we should include this
    // object.
    if (IncludeObject(pidl) != S_OK)
    {
        return(-1);
    }
    return(m_cView.AddObject(pidl));
}

int CALLBACK CSFView::CompareIDs(LPVOID p1, LPVOID p2, LPARAM lParam)
{
    PFNDPACOMPARE pfnCheckAPI = CompareIDs;
    CSFView *pThis = (CSFView *)lParam;
    HRESULT hres = pThis->m_psf->CompareIDs(pThis->m_sfState.lParamSort,
        (LPITEMIDLIST)p1, (LPITEMIDLIST)p2);
    return (hres);
}

// **********************************************************************
// CSFView::FillList
// Purpose: Enumerates the objects in the namespace and fills up the
//          data structures
// **********************************************************************
HRESULT CSFView::FillList(BOOL bInteractive)
{
    m_cView.DeleteAllItems();
    // Setup the enum flags.
    DWORD dwEnumFlags = SHCONTF_NONFOLDERS;
    if (ShowAllObjects())
    {
        dwEnumFlags |= SHCONTF_INCLUDEHIDDEN ;
    }
    if (!(m_fs.fFlags & FWF_NOSUBFOLDERS))
    {
        dwEnumFlags |= SHCONTF_FOLDERS;
    }
    // Create an enum object and get the IEnumIDList ptr
    LPENUMIDLIST peIDL;
    HRESULT hres = m_psf->EnumObjects(bInteractive ? m_hwndMain : NULL,
                                      dwEnumFlags, &peIDL);
    // Note the return may be S_FALSE which indicates no enumerator.
    // That's why we shouldn't use if (FAILED(hres))
    if (hres != S_OK)
    {
        if (hres == S_FALSE)
        {
            return(NOERROR);
        }
        return(hres);
    }
    CEnsureRelease erEnum(peIDL);
    HDPA hdpaNew = DPA_Create(16);
    if (!hdpaNew)
    {
        return(E_OUTOFMEMORY);
    }
    LPITEMIDLIST pidl;
    ULONG celt;
    // Enumerate the idlist and insert into the DPA
    while (peIDL->Next(1, &pidl, &celt) == S_OK)
    {
        if (DPA_InsertPtr(hdpaNew, 0x7fff, pidl) == -1)
        {
            m_cMalloc.Free(pidl);
        }
    }
    DPA_Sort(hdpaNew, CompareIDs, (LPARAM)this);
    int cNew = DPA_GetPtrCount(hdpaNew);
    for (int i=0; i<cNew; ++i)
    {
        LPITEMIDLIST pidl = (LPITEMIDLIST)DPA_GetPtr(hdpaNew, i);
        if (AddObject(pidl) < 0)
        {
            m_cMalloc.Free(pidl);
        }
    }
    return(NOERROR);
}
// **********************************************************************
// CSFView::AddColumns
// Purpose: Adds columns to the contents pane listview
// **********************************************************************
void CSFView::AddColumns()
{
    UINT cxChar = m_cView.CharWidth();
    // add columns to the listview in the contents pane
    for (int i=0; ; ++i)
    {
        SFVCB_GETDETAILSOF_DATA gdo;
        gdo.pidl = NULL;
        // get the first column
        HRESULT hres = CallCB(SFVCB_GETDETAILSOF, i, (LPARAM)&gdo);
        if (hres != S_OK)
        {
            if (i != 0)
            {
                break;
            }
            // If there is no first column, fake one up
            gdo.fmt = LVCFMT_LEFT;
            gdo.cChar = 40;
            gdo.lParamSort = 0;
            gdo.str.uType = STRRET_CSTR;
            LoadString(g_ThisDll.GetInstance(), IDS_NAME, gdo.str.cStr,  
                       sizeof(gdo.str.cStr));
        }
        char szText[MAX_PATH];
        // init the column info for the details view ...
        LV_COLUMN col;
        col.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
        col.fmt = gdo.fmt;
        col.cx = gdo.cChar * cxChar;
        col.pszText = szText;
        col.cchTextMax = sizeof(szText);
        col.iSubItem = i;
        StrRetToStr(szText, sizeof(szText), &gdo.str, NULL);
        // insert the column into the list view
        if (m_cView.InsertColumn(i, &col)>=0 && m_aParamSort)
        {
            DPA_InsertPtr(m_aParamSort, 0x7fff, (LPVOID)gdo.lParamSort);
        }
        if (hres != S_OK)
        {
            break;
        }
    }
}

// Save (and check) column header information
// Returns TRUE if the columns are the default width, FALSE otherwise
// Side effect: the stream pointer is left right after the last column
BOOL CSFView::SaveColumns(LPSTREAM pstm)
{
    UINT cxChar = m_cView.CharWidth();
    BOOL bDefaultCols = TRUE;
    for (int i=0; ; ++i)
    {
        SFVCB_GETDETAILSOF_DATA gdo;
        gdo.pidl = NULL;
        if (CallCB(SFVCB_GETDETAILSOF, i, (LPARAM)&gdo) != S_OK)
        {
            break;
        }
        LV_COLUMN col;
        col.mask = LVCF_WIDTH;
        if (!m_cView.GetColumn(i, &col))
        {
            // There is some problem, so just assume
            // default column widths
            bDefaultCols = TRUE;
            break;
        }
        if (col.cx != (int)(gdo.cChar * cxChar))
        {
            bDefaultCols = FALSE;
        }
        // HACK: I don't really care about column widths larger
        // than 64K
        if (FAILED(pstm->Write(&col.cx, sizeof(USHORT), NULL)))
        {
            // There is some problem, so just assume
            // default column widths
            bDefaultCols = TRUE;
            break;
        }
    }
    return(bDefaultCols ? 0 : i);
}

void CSFView::RestoreColumns(LPSTREAM pstm, int nCols)
{
    for (int i=0; i<nCols; ++i)
    {
        LV_COLUMN col;
        col.mask = LVCF_WIDTH;
        if (FAILED(pstm->Read(&col.cx, sizeof(USHORT), NULL)))
        {
            break;
        }
        m_cView.SetColumn(i, &col);
    }
}

void CSFView::RestoreViewState()
{
    SFSTATE_HDR hdr;
    LPSTREAM pstm;
    // get the stream for storing view specific info
    if (FAILED(m_psb->GetViewStateStream(STGM_READ, &pstm)))
    {
        return;
    }
    CEnsureRelease erStr(pstm);
    if (FAILED(pstm->Read(&hdr, sizeof(hdr), NULL)))
    {
        return;
    }
    // Validate the header
    if (hdr.clsThis != CLSID_ThisDll)
    {
        return;
    }
    m_sfState = hdr.sfState;
    RestoreColumns(pstm, hdr.nCols);
    MergeToolBar();
}

void CSFView::CheckToolbar()
{
    UINT idCmdCurView = GetMenuIDFromViewMode();
    for (UINT idCmd=IDC_VIEW_ICON; idCmd<=IDC_VIEW_DETAILS; ++idCmd)
    {
        m_psb->SendControlMsg(FCW_TOOLBAR, TB_CHECKBUTTON, idCmd,
            (LPARAM)(idCmd == idCmdCurView), NULL);
    }
}

void CSFView::MergeToolBar()
{
    enum
    {
        IN_STD_BMP = 0x4000,
        IN_VIEW_BMP = 0x8000,
    } ;
    static const TBBUTTON c_tbDefault[] =
    {
        { STD_COPY | IN_STD_BMP, IDC_EDIT_COPY, TBSTATE_ENABLED,
          TBSTYLE_BUTTON, {0,0}, 0, -1},
        { 0,    0,        TBSTATE_ENABLED, TBSTYLE_SEP, {0,0}, 0, -1 },
        // the bitmap indexes here are relative to the view bitmap
        { VIEW_LARGEICONS | IN_VIEW_BMP, IDC_VIEW_ICON,
          TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0L, -1 },
        { VIEW_SMALLICONS | IN_VIEW_BMP, IDC_VIEW_SMALLICON,
          TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0L, -1 },
        { VIEW_LIST       | IN_VIEW_BMP, IDC_VIEW_LIST,         TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0L, -1 },
        { VIEW_DETAILS    | IN_VIEW_BMP, IDC_VIEW_DETAILS,      TBSTATE_ENABLED, TBSTYLE_BUTTON, {0,0}, 0L, -1 },
    } ;

    LRESULT iStdBMOffset;
    LRESULT iViewBMOffset;
    TBADDBITMAP ab;
    ab.hInst = HINST_COMMCTRL;        // hinstCommctrl
    ab.nID   = IDB_STD_SMALL_COLOR;    // std bitmaps
    m_psb->SendControlMsg(FCW_TOOLBAR, TB_ADDBITMAP, 8, (LPARAM)&ab, &iStdBMOffset);

    ab.nID   = IDB_VIEW_SMALL_COLOR;    // std view bitmaps
    m_psb->SendControlMsg(FCW_TOOLBAR, TB_ADDBITMAP, 8, (LPARAM)&ab, &iViewBMOffset);

    TBBUTTON tbActual[ARRAYSIZE(c_tbDefault)];

    for (int i=0; i<ARRAYSIZE(c_tbDefault); ++i)
    {
        tbActual[i] = c_tbDefault[i];
        if (!(tbActual[i].fsStyle & TBSTYLE_SEP))
        {
            if (tbActual[i].iBitmap & IN_VIEW_BMP)
            {
                tbActual[i].iBitmap = (tbActual[i].iBitmap & ~IN_VIEW_BMP) + iViewBMOffset;
            }
            else if (tbActual[i].iBitmap & IN_STD_BMP)
            {
                tbActual[i].iBitmap = (tbActual[i].iBitmap & ~IN_STD_BMP) + iStdBMOffset;
            }
        }
    }

    m_psb->SetToolbarItems(tbActual, ARRAYSIZE(c_tbDefault), FCT_MERGE);

    CheckToolbar();
}


HRESULT CreateShellFolderView(LPSHELLFOLDER psf, 
                              IShellFolderViewCallback *psfvcb,
                              LPSHELLVIEW * ppsv)
{
    CSFView *pSFView = new CSFView(psf, psfvcb);
    if (!pSFView)
    {
        return(E_OUTOFMEMORY);
    }

    pSFView->AddRef();
    HRESULT hRes = pSFView->QueryInterface(IID_IShellView, (LPVOID *)ppsv);
    pSFView->Release();

    return(hRes);
}
.
.
.