
/*
 *@@sourcefile xtrash.c:
 *      This file contains SOM code for the following XWorkplace classes:
 *
 *      --  XWPTrashCan: a subclass of WPFolder, which implements
 *             the actual trash can object. There must only be one
 *             instance of this class, which must have the object ID
 *             <XWORKPLACE_TRASHCAN> for the XFldObject "delete"
 *             support to work.
 *
 *             The trash can folder itself never contains the "real"
 *             Desktop objects which have been deleted, but only instances
 *             of XWPTrashObject (a subclass of WPTransient), which
 *             "mirror" the deleted objects.
 *             See xtrashobj.c for details.
 *             The actual deleted objects reside in the hidden
 *             "\trash" directories on each drive and are never
 *             visibly inserted into any folder.
 *
 *             Deleting objects is done by XWPTrashCan::xwpDeleteIntoTrashCan.
 *             See the notes there for details.
 *
 *             XWPTrashCan::wpPopulate creates as many instances of
 *             XWPTrashObject as objects exist in the "\Trash"
 *             directories of all drives on the system.
 *
 *      Installation of these two classes is completely optional, but
 *      you cannot install only one them, since one requires the other.
 *
 *      There are three ways to delete an object using the trash can:
 *
 *      1)  selecting "Delete" from an object's context menu;
 *
 *      2)  pressing the "Delete" key in a folder;
 *          both situations are implemented by the XFldObject class and the
 *          XFolder subclassed folder frame procedure,
 *          if this feature has been enabled by the user;
 *
 *      3)  dropping an object onto the trash can object or into
 *          an open trash can view (using XWPTrashCan::wpDrop).
 *
 *      After going through the labyrinth of the XWorkplace file
 *      operations engine (fops_bottom.c), this will eventually
 *      call XWPTrashCan::xwpDeleteIntoTrashCan, which does the
 *      actual work of moving the object(s) into the hidden "\trash"
 *      directories on each drive and creating an instance of
 *      XWPTrashObject in the trash can itself.
 *
 *      When a trash object is then created (trshCreateTrashObject),
 *      XFldObject::xwpSetTrashObject will get called automatically
 *      on the related object so that it knows about its trash object.
 *      We therefore have no concept of destroying a trash object
 *      any more; instead, we simply delete the related object,
 *      which will destroy the trash object automatically thru
 *      XFldObject::wpUnInitData.
 *      Use XWPTrashObject::xwpQueryRelatedObject to get the
 *      related object from a trash object.
 *
 *      This is how the "empty trash can" and "destroy object" menu
 *      items work as well, BTW, and this has been changed with
 *      V0.9.3. This allows us to use the file operations engine
 *      more easily.
 *
 *@@somclass XWPTrashCan xtrc_
 *@@somclass M_XWPTrashCan xtrcM_
 */

/*
 *      Copyright (C) 1999-2014 Ulrich M”ller.
 *      This file is part of the XWorkplace source package.
 *      XWorkplace is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published
 *      by the Free Software Foundation, in version 2 as it comes in the
 *      "COPYING" file of the XWorkplace main distribution.
 *      This program 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 General Public License for more details.
 */

/*
 *  This file was generated by the SOM Compiler and Emitter Framework.
 *  Generated using:
 *      SOM Emitter emitctm: 2.41
 */

#ifndef SOM_Module_xtrash_Source
#define SOM_Module_xtrash_Source
#endif
#define XWPTrashCan_Class_Source
#define M_XWPTrashCan_Class_Source

#pragma strings(readonly)

/*
 *  Suggested #include order:
 *  1)  os2.h
 *  2)  C library headers
 *  3)  setup.h (code generation and debugging options)
 *  4)  headers in helpers\
 *  5)  at least one SOM implementation header (*.ih)
 *  6)  dlgids.h, headers in shared\ (as needed)
 *  7)  headers in implementation dirs (e.g. filesys\, as needed)
 *  8)  #pragma hdrstop and then more SOM headers which crash with precompiled headers
 */

#define INCL_DOSPROCESS
#define INCL_DOSSEMAPHORES
#define INCL_DOSEXCEPTIONS
#define INCL_DOSERRORS
#define INCL_WINPOINTERS
#define INCL_WINMENUS
#include <os2.h>

// C library headers
#include <stdio.h>              // needed for except.h
#include <setjmp.h>             // needed for except.h
#include <assert.h>             // needed for except.h

// generic headers
#include "setup.h"                      // code generation and debugging options

// headers in /helpers
#include "helpers\except.h"             // exception handling
#include "helpers\nls.h"                // National Language Support helpers
#include "helpers\winh.h"               // PM helper routines
#include "helpers\stringh.h"            // string helper routines

// SOM headers which don't crash with prec. header files
#include "xfobj.ih"
#include "xfldr.ih"
#include "xtrash.ih"
#include "xtrashobj.ih"

// XWorkplace implementation headers
#include "dlgids.h"                     // all the IDs that are shared with NLS
#include "shared\common.h"              // the majestic XWorkplace include file
#include "shared\helppanels.h"          // all XWorkplace help panel IDs
#include "shared\kernel.h"              // XWorkplace Kernel
#include "shared\notebook.h"            // generic XWorkplace notebook handling

// #include "filesys\fdrmenus.h"           // shared folder menu logic
#include "filesys\folder.h"             // XFolder implementation
#include "filesys\icons.h"              // icons handling
#include "filesys\trash.h"              // trash can implementation

// other SOM headers
#pragma hdrstop

/* ******************************************************************
 *
 *   Global variables
 *
 ********************************************************************/

// default trash can
static XWPTrashCan *G_pDefaultTrashCan = NULL;

static BOOL        G_fDrivesInitialized = FALSE;

/* ******************************************************************
 *
 *   XWPTrashCan instance methods
 *
 ********************************************************************/

/*
 *@@ xwpDeleteIntoTrashCan:
 *      this new instance method takes any Desktop object and
 *      "deletes" it into the trash can (somSelf).
 *
 *      Call this method to move any Desktop object into the
 *      trash can. This can be called in any context, but
 *      is mostly called from the XWP file operations
 *      engine (fops_bottom.c) when WPS "delete" operations
 *      are intercepted in XFolder::xwpProcessViewCommand.
 *
 *      In other words, this gets called for every object
 *      on which the "Del" key was pressed in a folder or
 *      for which the "Delete" menu item has been selected.
 *
 *      See trshDeleteIntoTrashCan for details, which has the
 *      implementation.
 *
 *      To quickly delete an object into the trash can, use
 *      cmnDeleteIntoDefTrashCan, which automatically determines
 *      the default trash can on the system.
 */

SOM_Scope BOOL  SOMLINK xtrc_xwpDeleteIntoTrashCan(XWPTrashCan *somSelf,
                                                   WPObject* pObject)
{
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_xwpDeleteIntoTrashCan");

    return trshDeleteIntoTrashCan(somSelf,
                                  pObject);
}

/*
 *@@ xwpAddTrashCanSettingsPage:
 *      this adds the "Trash can" page to the
 *      settings notebook.
 *
 *@@changed V0.9.19 (2002-04-14) [umoeller]: now using dialog formatter
 */

SOM_Scope ULONG  SOMLINK xtrc_xwpAddTrashCanSettingsPage(XWPTrashCan *somSelf,
                                                         HWND hwndDlg)
{
    /* XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf); */

    INSERTNOTEBOOKPAGE inbp;

    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_xwpAddTrashCanSettingsPage");

    memset(&inbp, 0, sizeof(INSERTNOTEBOOKPAGE));
    inbp.somSelf = somSelf;
    inbp.hwndNotebook = hwndDlg;
    inbp.hmod = cmnQueryNLSModuleHandle(FALSE);
    inbp.ulDlgID = ID_XFD_EMPTYDLG; // ID_XTD_SETTINGS; V0.9.19 (2002-04-14) [umoeller]
    inbp.ulPageID = SP_TRASHCAN_SETTINGS;
    inbp.usPageStyleFlags = BKA_MAJOR;
    inbp.pcszName = cmnGetString(ID_XTSI_TRASHSETTINGSPAGE);  // pszTrashSettingsPage
    inbp.ulDefaultHelpPanel = ID_XSH_SETTINGS_TRASHCAN + 1;
    inbp.pfncbInitPage    = trshTrashCanSettingsInitPage;
    inbp.pfncbItemChanged = trshTrashCanSettingsItemChanged;

    return ntbInsertPage(&inbp);
}

/*
 *@@ xwpAddTrashCanDrivesPage:
 *      this adds the "Drives support" page to
 *      the trash can settings notebook.
 *
 *@@added V0.9.1 (99-12-19) [umoeller]
 */

SOM_Scope ULONG  SOMLINK xtrc_xwpAddTrashCanDrivesPage(XWPTrashCan *somSelf,
                                                       HWND hwndDlg)
{
    INSERTNOTEBOOKPAGE inbp;

    // XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_xwpAddTrashCanDrivesPage");

    memset(&inbp, 0, sizeof(INSERTNOTEBOOKPAGE));
    inbp.somSelf = somSelf;
    inbp.hwndNotebook = hwndDlg;
    inbp.hmod = cmnQueryNLSModuleHandle(FALSE);
    inbp.ulDlgID = ID_XTD_DRIVES;
    inbp.ulPageID = SP_TRASHCAN_DRIVES;
    inbp.usPageStyleFlags = BKA_MAJOR;
    inbp.pcszName = cmnGetString(ID_XTSI_TRASHDRIVESPAGE);  // pszTrashDrivesPage
    inbp.ulDefaultHelpPanel = ID_XSH_SETTINGS_TRASHCAN_DRIVES;
    inbp.pfncbInitPage    = trshTrashCanDrivesInitPage;
    inbp.pfncbItemChanged = trshTrashCanDrivesItemChanged;

    return ntbInsertPage(&inbp);
}

/*
 *@@ xwpAddTrashCanGeneralPage:
 *      this gets called by XWPTrashCan::wpAddObjectGeneralPage
 *      (which has been replaced) to add our replacement "General"
 *      page to the settings notebook.
 */

SOM_Scope ULONG  SOMLINK xtrc_xwpAddTrashCanGeneralPage(XWPTrashCan *somSelf,
                                                        HWND hwndDlg)
{
    INSERTNOTEBOOKPAGE inbp;

    /* XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf); */
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_xwpAddTrashCanGeneralPage");

    memset(&inbp, 0, sizeof(INSERTNOTEBOOKPAGE));
    inbp.somSelf = somSelf;
    inbp.hwndNotebook = hwndDlg;
    inbp.hmod = cmnQueryNLSModuleHandle(FALSE);

#ifndef __ALWAYSREPLACEICONPAGE__
    if (    (cmnQuerySetting(sfReplaceIconPage))
            // check if this is a folder;
            // if so, XFolder will insert the page
            // because otherwise this would be between
            // the two "Icon" pages...
         // && (!_somIsA(somSelf, _WPFolder))
                // removed V0.9.16 (2001-10-15) [umoeller]
        )
#endif
    {
        inbp.ulDlgID = ID_XFD_EMPTYDLG;
        inbp.ulPageID = SP_TRASHCAN_ICON;
        inbp.usPageStyleFlags = BKA_MAJOR;
        inbp.fEnumerate = TRUE;
        inbp.pcszName = cmnGetString(ID_XSSI_ICONPAGE);
        inbp.ulDefaultHelpPanel  = ID_XSH_SETTINGS_TRASHCAN_ICON;
        inbp.pfncbInitPage    = icoIcon1InitPage;
        inbp.pfncbItemChanged = icoIcon1ItemChanged;
    }
#ifndef __ALWAYSREPLACEICONPAGE__
    else
    {
        inbp.ulDlgID = ID_XTD_ICONPAGE;
        inbp.ulPageID = SP_TRASHCAN_ICON;
        inbp.usPageStyleFlags = BKA_MAJOR;
        inbp.pcszName = cmnGetString(ID_XSSI_ICONPAGE);  // pszIconPage
        inbp.ulDefaultHelpPanel = ID_XSH_SETTINGS_TRASHCAN_ICON;

        inbp.pfncbInitPage    = trshTrashCanIconInitPage;
        inbp.pfncbItemChanged = trshTrashCanIconItemChanged;
    }
#endif

    return (ntbInsertPage(&inbp));
}

/*
 *@@ xwpTrashCanBusy:
 *      sets and/or queries whether the trash can
 *      is considered "busy", that is, operations
 *      on the trash can or the trash objects will
 *      be disabled by disabling the respective
 *      context menu items.
 *
 *      If (lBusy > 0), the trash can busy count
 *      is incremented by 1.
 *
 *      If (lBusy < 0), the trash can busy count
 *      is decremented by 1.
 *
 *      If (lBusy == 0), the trash can busy count
 *      is not changed. Use this for querying the
 *      busy flag only.
 *
 *      Returns TRUE if the trash can is "busy".
 *
 *@@added V0.9.3 (2000-04-26) [umoeller]
 */

SOM_Scope BOOL  SOMLINK xtrc_xwpTrashCanBusy(XWPTrashCan *somSelf,
                                             long lBusy)
{
    BOOL    brc = FALSE;
    WPObject *pobjLock = NULL;
    XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_xwpTrashCanBusy");

    TRY_LOUD(excpt1)
    {
        if (pobjLock = cmnLockObject(somSelf))
        {
            if (lBusy > 0)
                // raise busy count:
                _ulBusyCount++;
            else if (lBusy < 0)
                // lower busy count:
                if (_ulBusyCount > 0)
                    _ulBusyCount--;

            brc = (    (_ulBusyCount != 0)
                    || (_cDrivePopulating != 0)
                  );
        }
        else
            // couldn't get mutex:
            // trash can is probably busy too
            brc = TRUE;
    }
    CATCH(excpt1) {} END_CATCH();

    if (pobjLock)
        _wpReleaseObjectMutexSem(pobjLock);

    return brc;
}

/*
 *@@ xwpAddObjectSize:
 *      adds the specified size to the total size of all
 *      objects in the trash can and updates the status bar.
 *      Gets called by XWPTrashObject::xwpSetExpandedObjectSize.
 *
 *@@added V0.9.2 (2000-02-28) [umoeller]
 *@@changed V0.9.4 (2000-08-03) [umoeller]: added object mutex
 */

SOM_Scope void  SOMLINK xtrc_xwpAddObjectSize(XWPTrashCan *somSelf,
                                              ULONG ulNewSize)
{
    // BOOL    fTrashCanLocked = FALSE;
    WPObject *pobjLock = NULL;
    XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_xwpAddObjectSize");

    TRY_LOUD(excpt1)
    {
        if (pobjLock = cmnLockObject(somSelf))
        {
            _dSizeOfAllObjects += ulNewSize;
            // update all visible status bars
            stbUpdate(somSelf);
        }
    }
    CATCH(excpt1) {} END_CATCH();

    if (pobjLock)
        _wpReleaseObjectMutexSem(pobjLock);
}

/*
 *@@ xwpQueryTrashObjectsCount:
 *      this will return the no. of trash objects in the
 *      trash can.
 *
 *      Note that this information is only accurate if the
 *      trash can has been fully populated. Otherwise,
 *      you will get a number too, but this might not
 *      reflect the precise no. of objects, since that no.
 *      is stored internally to be able to set the correct
 *      trash can icon even without populating.
 */

SOM_Scope ULONG  SOMLINK xtrc_xwpQueryTrashObjectsCount(XWPTrashCan *somSelf)
{
    XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_xwpQueryTrashObjectsCount");

    return (_ulTrashObjectCount);
}

/*
 *@@ xwpSetCorrectTrashIcon:
 *      this sets the trash can's icon according
 *      to its current state by calling wpSetIcon
 *      with either the "empty" or "not empty" icon.
 *
 *@@changed V0.9.1 (2000-01-29) [umoeller]: added fForce parameter
 *@@changed V0.9.4 (2000-08-02) [umoeller]: now pre-loading icons; added ICONS.DLL support
 *@@changed V0.9.4 (2000-08-03) [umoeller]: added object mutex
 *@@changed V0.9.7 (2000-12-19) [umoeller]: new state wasn't always saved, fixed
 *@@changed V0.9.16 (2002-01-01) [umoeller]: now using cmnGetStandardIcon
 */

SOM_Scope BOOL  SOMLINK xtrc_xwpSetCorrectTrashIcon(XWPTrashCan *somSelf,
                                                    BOOL fForce)
{
    BOOL    brc = FALSE,
            fSave = FALSE;
    HPOINTER hptr;
    WPObject *pobjLock = NULL;

    XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_xwpSetCorrectTrashIcon");

    TRY_LOUD(excpt1)
    {
        if (pobjLock = cmnLockObject(somSelf))
        {
            BOOL     fTrashFilled = FALSE;

            if (_ulTrashObjectCount)
                fTrashFilled = TRUE;

            if (fForce || fTrashFilled != _fFilledIconSet)
            {
                if ((hptr = _wpclsQueryIconN(_somGetClass(somSelf), fTrashFilled ? 1 : 0)))
                {
                    brc = _wpSetIcon(somSelf, hptr);

                    // make sure this icon never gets destroyed;
                    // the WPS destroys the icon when the OBJSTYLE_NOTDEFAULTICON
                    // bit is set (do not use OBJSTYLE_CUSTOMICON, it is ignored by the WPS)
                    _wpModifyStyle(somSelf, OBJSTYLE_NOTDEFAULTICON, 0);
                }

                _fFilledIconSet = fTrashFilled;
                fSave = TRUE;
            }
        }
    }
    CATCH(excpt1) {} END_CATCH();

    if (pobjLock)
        _wpReleaseObjectMutexSem(pobjLock);

    // save trash can state so that the correct icon
    // is displayed after a Desktop restart
    // V0.9.7 (2000-12-19) [umoeller]
    if (fSave)
        _wpSaveDeferred(somSelf);

    return brc;
}

/*
 *@@ xwpEmptyTrashCan:
 *      this will empty the trashcan.
 *
 *      Note that this is done on the XWorkplace File thread
 *      so this function returns BEFORE the trash can is empty.
 *
 *      However, if you specify the caller's anchor block in
 *      hab, processing takes place synchronously.
 *      See fopsStartTask for details.
 *
 *      If (hwndConfirmOwner != NULLHANDLE), a confirmation
 *      box is displayed before processing starts. In
 *      hwndConfirmOwner, specify the owner window for the
 *      confirmation box, e.g. the Desktop frame window handle.
 *
 *      Emptying the trash can is now implemented thru creating
 *      a list of the related objects from the trash objects
 *      in the trash can and starting a "true delete" file task
 *      with that list (fopsStartTaskFromList).
 *
 *      This function will populate the trash can if this is
 *      not done yet. However, this can only be done if hab
 *      is specified for synchronous mode. Otherwise this
 *      function will fail.
 *
 *      Returns NO_ERROR if emptying the trash can has started on
 *      the File thread or (in synchronous mode) if emptying succeeded.
 *
 *      If (pulDeleted != NULL) and NO_ERROR is returned, *pulDeleted
 *      receives the no. of objects which were deleted. This works
 *      only in synchronous mode. Note that if the trash can was
 *      empty, NO_ERROR is returned still, but *pulDeleted will be set
 *      to 0.
 *
 *      If something != NO_ERROR (0) is returned, it's either an
 *      OS/2 error code or one of the error codes in
 *      include\shared\errors.h.
 *
 *@@changed V0.9.5 (2000-08-10) [umoeller]: added hwndConfirmOwner
 *@@changed V0.9.7 (2001-01-17) [umoeller]: now returning FOPSRET
 */

SOM_Scope ULONG SOMLINK xtrc_xwpEmptyTrashCan(XWPTrashCan *somSelf,
                                              ULONG hab, PULONG pulDeleted,
                                              HWND hwndConfirmOwner)
{
    // XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_xwpEmptyTrashCan");

    return (trshEmptyTrashCan(somSelf,
                              hab,   // no anchor block == asynchronously
                              hwndConfirmOwner,
                              pulDeleted));
}

/*
 *@@ xwpProcessViewCommand:
 *      this XFolder method processes WM_COMMAND messages
 *      for objects in a container. For details refer to
 *      XFolder::xwpProcessViewCommand.
 *
 *      This is really a method override... but since SOM
 *      IDL doesn't know that XWPTrashCan is in fact
 *      derived from XFolder, we have to do it this way.
 *
 *      This replaces trash can subclassing now, which was
 *      used before V0.9.7. See trshProcessViewCommand for
 *      the implementation.
 *
 *@@added V0.9.7 (2001-01-13) [umoeller]
 *@@changed V1.0.0 (2002-08-26) [umoeller]: method renamed
 */

SOM_Scope BOOL  SOMLINK xtrc_xwpProcessViewCommand(XWPTrashCan *somSelf,
                                                   USHORT usCommand,
                                                   HWND hwndCnr,
                                                   WPObject* pFirstObject,
                                                   ULONG ulSelectionFlags)
{
    // XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_xwpProcessViewCommand");

    return trshProcessViewCommand(somSelf,
                                  usCommand,
                                  hwndCnr,
                                  pFirstObject,
                                  ulSelectionFlags);
}

/*
 *@@ xwpUpdateStatusBar:
 *      this XFolder instance method gets called when the status
 *      bar needs updating.
 *
 *      This always gets called using name-lookup resolution, so
 *      XFolder does not have to be installed for this to work.
 *      However, if it is, this method will be called. See
 *      XFolder::xwpUpdateStatusBar for more on this.
 *
 *      Note that this gets also called from trshPopulateFirstTime
 *      while the trash can is being populated to show the
 *      "current drive" stuff. Before every call, _cCurrentDrivePopulating
 *      is set to the drive letter currently being populated.
 *
 *      If (_cCurrentDrivePopulating == 0), we're not currently
 *      populating and display the correct total size instead.
 *
 *@@changed V0.9.1 (2000-02-04) [umoeller]: added "populating..." support
 *@@changed V0.9.5 (2000-08-24) [umoeller]: fixed NLS thousands separator
 */

SOM_Scope BOOL  SOMLINK xtrc_xwpUpdateStatusBar(XWPTrashCan *somSelf,
                                                HWND hwndStatusBar,
                                                HWND hwndCnr)
{
    CHAR        szText[1000] = "";
    // PNLSSTRINGS pNLSStrings = cmnQueryNLSStrings();
    XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_xwpUpdateStatusBar");

    if (_cDrivePopulating)
        // populating drive:
        sprintf(szText,
                cmnGetString(ID_XTSI_STB_POPULATING),   // "Populating drive %c:", // pszStbPopulating
                _cDrivePopulating);
    else
    {
        CHAR    szNum1[100],
                szNum2[100];
        // get thousands separator from "Country" object
        CHAR    cThousands = cmnQueryThousandsSeparator();
        // not populating:
        sprintf(szText,
                cmnGetString(ID_XTSI_STB_OBJCOUNT),  // "Total size of all objects: %s bytes", // pszStbObjCount
                nlsThousandsDouble(szNum1, _ulTrashObjectCount, cThousands),
                nlsThousandsDouble(szNum2, _dSizeOfAllObjects, cThousands));
    }

    WinSetWindowText(hwndStatusBar, szText);

    return TRUE;
}

/*
 *@@ xwpAddObjectSizeL:
 *      See xwpAddObjectSize for details.
 *
 *@@added V1.0.9 (2010-07-17) [pr]
 */

SOM_Scope void  SOMLINK xtrc_xwpAddObjectSizeL(XWPTrashCan *somSelf,
                                               PLONGLONG pllNewSize)
{
    WPObject *pobjLock = NULL;
    XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_xwpAddObjectSizeL");

    TRY_LOUD(excpt1)
    {
        if (pobjLock = cmnLockObject(somSelf))
        {
            _dSizeOfAllObjects += 65536.0 * 65536.0 * pllNewSize->ulHi + pllNewSize->ulLo;
            // update all visible status bars
            stbUpdate(somSelf);
        }
    }
    CATCH(excpt1) {} END_CATCH();

    if (pobjLock)
        _wpReleaseObjectMutexSem(pobjLock);
}

/*
 *@@ wpInitData:
 *      this WPObject instance method gets called when the
 *      object is being initialized (on wake-up or creation).
 *      We initialize our additional instance data here.
 *      Always call the parent method first.
 *
 *@@changed V0.9.4 (2000-08-02) [umoeller]: now pre-loading icons; added ICONS.DLL support
 */

SOM_Scope void  SOMLINK xtrc_wpInitData(XWPTrashCan *somSelf)
{
    XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpInitData");

    XWPTrashCan_parent_WPFolder_wpInitData(somSelf);

    _fAlreadyPopulated = FALSE;
    _fFilledIconSet = FALSE;
    _ulTrashObjectCount = 0;
    _dSizeOfAllObjects = 0;
    _cDrivePopulating = 0;
    _ulBusyCount = 0;
    _fOpeningSettings = FALSE;

    if (G_pDefaultTrashCan == NULL)
        // this is the first trash can to be initialized:
        G_pDefaultTrashCan = somSelf;
}

/*
 *@@ wpObjectReady:
 *      this WPObject notification method gets called by the
 *      WPS when object instantiation is complete, for any reason.
 *      ulCode and refObject signify why and where from the
 *      object was created.
 *      The parent method must be called first.
 *
 *      See XFldObject::wpObjectReady for remarks about using
 *      this method as a copy constructor.
 *
 *      For trash cans, we need to call
 *      XWPTrashCan::xwpSetCorrectTrashIcon.
 *
 *@@changed V0.9.9 (2001-02-06) [umoeller]: now repairing object ID automatically
 */

SOM_Scope void  SOMLINK xtrc_wpObjectReady(XWPTrashCan *somSelf,
                                           ULONG ulCode, WPObject* refObject)
{
    // XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpObjectReady");

    XWPTrashCan_parent_WPFolder_wpObjectReady(somSelf, ulCode,
                                              refObject);

    _xwpSetCorrectTrashIcon(somSelf, TRUE);

    // repair trash can ID if this has been broken
    // V0.9.9 (2001-02-06) [umoeller]
    if (somSelf == G_pDefaultTrashCan)
    {
        PSZ pszObjectID = _wpQueryObjectID(somSelf);
        if (    (!pszObjectID)
             || (strcmp(pszObjectID, XFOLDER_TRASHCANID))
           )
            _wpSetObjectID(somSelf, (PSZ)XFOLDER_TRASHCANID);
    }
}

/*
 *@@ wpUnInitData:
 *      this WPObject instance method is called when the object
 *      is destroyed as a SOM object, either because it's being
 *      made dormant or being deleted. All allocated resources
 *      should be freed here.
 *      The parent method must always be called last.
 */

SOM_Scope void  SOMLINK xtrc_wpUnInitData(XWPTrashCan *somSelf)
{
    XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpUnInitData");

    if (G_pDefaultTrashCan == somSelf)
        G_pDefaultTrashCan = NULL;

    XWPTrashCan_parent_WPFolder_wpUnInitData(somSelf);
}

/*
 *@@ wpSaveState:
 *      this WPObject instance method saves an object's state
 *      persistently so that it can later be re-initialized
 *      with wpRestoreState. This gets called during wpClose,
 *      wpSaveImmediate or wpSaveDeferred processing.
 *      All persistent instance variables should be stored here.
 *
 *      We store the trash can item count here so we don't have to
 *      populate the trash can at Desktop startup already to set the
 *      correct trash icon.
 *
 *      In addition, we now call wpSaveDeferred every time the
 *      trash dir mappings have changed. See trshInitMappings
 *      for an introduction to that concept.
 *
 *      With a couple of seconds of delay, wpSaveDeferred calls
 *      this function internally, and this then calls trshSaveMappings
 *      in turn.
 *
 *@@changed V0.9.9 (2001-02-06) [umoeller]: added mappings save
 */

SOM_Scope BOOL  SOMLINK xtrc_wpSaveState(XWPTrashCan *somSelf)
{
    XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpSaveState");

    if (_ulTrashObjectCount != 0)
        _wpSaveLong(somSelf,
                    (PSZ)G_pcszXWPTrashCan,
                    1,
                    (ULONG)_ulTrashObjectCount);

    // save dirty mappings back to the trash directories
    trshSaveMappings(somSelf);

    return (XWPTrashCan_parent_WPFolder_wpSaveState(somSelf));
}

/*
 *@@ wpRestoreState:
 *      this WPObject instance method gets called during object
 *      initialization (after wpInitData) to restore the data
 *      which was stored with wpSaveState.
 *
 *      We restore the trash can item count here so we don't have to
 *      populate the trash can at Desktop startup already to set the
 *      correct trash icon.
 */

SOM_Scope BOOL  SOMLINK xtrc_wpRestoreState(XWPTrashCan *somSelf,
                                            ULONG ulReserved)
{
    ULONG               ul;
    XWPTrashCanData     *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpRestoreState");

    if (_wpRestoreLong(somSelf,
                       (PSZ)G_pcszXWPTrashCan,
                       1,
                       &ul))
        _ulTrashObjectCount = ul;
    else
        _ulTrashObjectCount = 0;

    return (XWPTrashCan_parent_WPFolder_wpRestoreState(somSelf,
                                                       ulReserved));
}

/*
 *@@ wpSetup:
 *      this WPObject instance method is called to allow an
 *      object to set itself up according to setup strings.
 *      As opposed to wpSetupOnce, this gets called any time
 *      a setup string is invoked.
 *
 *      We allow the trash can to be emptied via setup string
 *      here.
 *
 *@@added V0.9.16 (2001-12-06) [umoeller]
 */

SOM_Scope BOOL  SOMLINK xtrc_wpSetup(XWPTrashCan *somSelf, PSZ pszSetupString)
{
    BOOL brc;
    // XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpSetup");

    if (brc = XWPTrashCan_parent_WPFolder_wpSetup(somSelf, pszSetupString))
    {
        CHAR    szTemp[50];
        ULONG   cbTemp;

        cbTemp = sizeof(szTemp);
        if (_wpScanSetupString(somSelf,
                               pszSetupString,
                               "EMPTYTRASH",
                               szTemp,
                               &cbTemp))
        {
            if (!stricmp(szTemp, "IMMEDIATE"))
                _xwpEmptyTrashCan(somSelf,
                                  winhMyAnchorBlock(),  // operate synchronously
                                  NULL,             // PULONG pulDeleted,
                                  NULLHANDLE);      // HWND hwndConfirmOwner
        }
    }

    return brc;
}

/*
 *@@ wpDisplayMenu:
 *      this override works around a problem whose cause is unknown.
 *      When displaying the TrashCan's menu by clicking on the
 *      system-menu button of an open view, the OpenAs menu's default
 *      item gets changed from whatever to Xview. This happens after
 *      XFolder's override of wpModifyMenu() but before control returns
 *      to its override of wpDisplayMenu(). Resetting the default item
 *      to its correct value at the end of WPS processing fixes the
 *      immediate problem.
 */

SOM_Scope HWND  SOMLINK xtrc_wpDisplayMenu(XWPTrashCan *somSelf,
                                           HWND hwndOwner,
                                           HWND hwndClient,
                                           POINTL* ptlPopupPt,
                                           ULONG ulMenuType,
                                           ULONG ulReserved)
{
    HWND hwndMenu;

    /* XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf); */
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpDisplayMenu");

    hwndMenu = XWPTrashCan_parent_WPFolder_wpDisplayMenu(somSelf,
                                                         hwndOwner,
                                                         hwndClient,
                                                         ptlPopupPt,
                                                         ulMenuType,
                                                         ulReserved);

    if (ulMenuType == (MENU_TITLEBARPULLDOWN | MENU_NODISPLAY)) {
        ULONG    mid;
        MENUITEM mi;

        // set the correct menuids
        mid = _wpQueryDefaultView(somSelf);
        if (mid == OPEN_CONTENTS)
            mid = WPMENUID_ICON;
        else
        if (mid == OPEN_DETAILS)
            mid = WPMENUID_DETAILS;

        // if we can locate the OpenAs menu, set its default id
        if (WinSendMsg(hwndMenu, MM_QUERYITEM, MPFROM2SHORT(WPMENUID_OPEN, TRUE), &mi))
            WinSendMsg(mi.hwndSubMenu, MM_SETDEFAULTITEMID, (MPARAM)mid, 0);
    }

    return hwndMenu;
}

/*
 *@@ wpFilterPopupMenu:
 *      this WPObject instance method allows the object to
 *      filter out unwanted menu items from the context menu.
 *      This gets called before wpModifyPopupMenu.
 *
 *      We remove the "Open tree view" and "Create another" items.
 *
 *@@changed V0.9.1 (2000-01-31) [umoeller]: now removing "Create another" also
 *@@changed V0.9.19 (2002-04-17) [umoeller]: now removing "switch to tree" also
 */

SOM_Scope ULONG  SOMLINK xtrc_wpFilterPopupMenu(XWPTrashCan *somSelf,
                                                ULONG ulFlags,
                                                HWND hwndCnr,
                                                BOOL fMultiSelect)
{
    /* XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf); */
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpFilterPopupMenu");

    return (XWPTrashCan_parent_WPFolder_wpFilterPopupMenu(somSelf,
                                                          ulFlags,
                                                          hwndCnr,
                                                          fMultiSelect)
                    &~ (CTXT_TREE | CTXT_NEW
                            // do not allow switching to Tree view
                            // V0.9.19 (2002-04-17) [umoeller]
                        | CTXT_CHANGETOTREE)
           );
}

/*
 *@@ wpModifyPopupMenu:
 *      this WPObject instance methods gets called by the WPS
 *      when a context menu needs to be built for the object
 *      and allows the object to manipulate its context menu.
 *      This gets called _after_ wpFilterPopupMenu.
 *
 *      We add the trash can menu items here.
 *
 *@@changed V0.9.3 (2000-04-26) [umoeller]: now disabling menu items if trash can is busy
 */

SOM_Scope BOOL  SOMLINK xtrc_wpModifyPopupMenu(XWPTrashCan *somSelf,
                                               HWND hwndMenu,
                                               HWND hwndCnr,
                                               ULONG iPosition)
{
    BOOL brc = 0;
    XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpModifyPopupMenu");

    brc = XWPTrashCan_parent_WPFolder_wpModifyPopupMenu(somSelf,
                                                          hwndMenu,
                                                          hwndCnr,
                                                          iPosition);

    if (    (brc)
         && (_ulTrashObjectCount)
       )
    {
        // PNLSSTRINGS pNLSStrings = cmnQueryNLSStrings();
        CHAR        szEmptyItem[200];
        ULONG       ulAttr = 0;
        ULONG       ulOfs = *G_pulVarMenuOfs;

        if (_xwpTrashCanBusy(somSelf, 0))
            // currently populating:
            ulAttr = MIA_DISABLED;

        winhInsertMenuSeparator(hwndMenu, MIT_END,
                                (ulOfs + ID_XFMI_OFS_SEPARATOR));

        // "empty trash can"
        strcpy(szEmptyItem, cmnGetString(ID_XTSI_TRASHEMPTY)) ; // pszTrashEmpty
        if (cmnQuerySetting(sflTrashConfirmEmpty) & TRSHCONF_EMPTYTRASH)
            // confirm empty on:
            strcat(szEmptyItem, "...");
        winhInsertMenuItem(hwndMenu, MIT_END,
                           (ulOfs + ID_XFMI_OFS_TRASHEMPTY),
                           szEmptyItem,
                           MIS_TEXT,
                           ulAttr);

    }

    return brc;
}

/*
 *@@ wpMenuItemSelected:
 *      this WPObject method processes menu selections.
 *      This must be overridden to support new menu
 *      items which have been added in wpModifyPopupMenu.
 *
 *      See XFldObject::wpMenuItemSelected for additional
 *      remarks.
 *
 *      We need to react to "Empty trash can" here.
 */

SOM_Scope BOOL  SOMLINK xtrc_wpMenuItemSelected(XWPTrashCan *somSelf,
                                                HWND hwndFrame,
                                                ULONG ulMenuId)
{
    BOOL    brc = TRUE;
    ULONG   ulMenuId2 = ulMenuId - *G_pulVarMenuOfs;

    /* XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf); */
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpMenuItemSelected");

    // "empty trashcan"
    if (ulMenuId2 == ID_XFMI_OFS_TRASHEMPTY)
    {
        _xwpEmptyTrashCan(somSelf,
                          WinQueryAnchorBlock(hwndFrame), // synchronously
                          NULL,
                          (cmnQuerySetting(sflTrashConfirmEmpty) & TRSHCONF_EMPTYTRASH)
                                // confirmations:
                                ? hwndFrame
                                : NULLHANDLE
                         );
    }
    // swallow "open tree view"
    else if (ulMenuId == WPMENUID_TREE)
    {
        brc = FALSE;
    }
    else
        brc = XWPTrashCan_parent_WPFolder_wpMenuItemSelected(somSelf,
                                                             hwndFrame,
                                                             ulMenuId);

    return brc;
}

/*
 *@@ wpMenuItemHelpSelected:
 *      this instance method gets called when help is
 *      requested for a menu item in the object's context menu.
 *
 *      We need to display help for our new menu items here.
 *
 *@@added V0.9.4 (2000-08-03) [umoeller]
 */

SOM_Scope BOOL  SOMLINK xtrc_wpMenuItemHelpSelected(XWPTrashCan *somSelf,
                                                    ULONG MenuId)
{
    /* XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf); */
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpMenuItemHelpSelected");

    if (MenuId - *G_pulVarMenuOfs == ID_XFMI_OFS_TRASHEMPTY)
    {
        // now open the help panel we've set above
        cmnDisplayHelp(somSelf,
                       ID_XSH_SETTINGS_TRASHCAN);
        return TRUE;
    }
    else
        return (XWPTrashCan_parent_WPFolder_wpMenuItemHelpSelected(somSelf,
                                                                   MenuId));
}

/*
 *@@ wpOpen:
 *      this WPObject instance method gets called when
 *      a new view needs to be opened. Normally, this
 *      gets called after wpViewObject has scanned the
 *      object's USEITEMs and has determined that a new
 *      view is needed.
 *
 *      This _normally_ runs on thread 1 of the WPS, but
 *      this is not always the case. If this gets called
 *      in response to a menu selection from the "Open"
 *      submenu or a double-click in the folder, this runs
 *      on the thread of the folder (which _normally_ is
 *      thread 1). However, if this results from WinOpenObject
 *      or an OPEN setup string, this will not be on thread 1.
 *
 *      We suppress the tree view here and do a hack for
 *      settings view.
 *
 *@@added V0.9.1 (2000-01-30) [umoeller]
 *@@changed V0.9.7 (2001-01-13) [umoeller]: removed trash can frame subclassing
 *@@changed V1.0.9 (2011-10-10) [rwalsh]: added SplitView as acceptable view
 *@@changed V1.0.10 (2014-05-11) [pr]: fix split view fallback
 */

SOM_Scope HWND  SOMLINK xtrc_wpOpen(XWPTrashCan *somSelf,
                                    HWND hwndCnr,
                                    ULONG ulView,
                                    ULONG param)
{
    HWND hwndFrame = NULLHANDLE;
    XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpOpen");

    if (   (ulView == *G_pulVarMenuOfs + ID_XFMI_OFS_SPLITVIEW)  // V1.0.10
        && !cmnQuerySetting(sfFdrSplitViews)
       )
        ulView = OPEN_DETAILS;

    if (    (ulView == OPEN_CONTENTS)
         || (ulView == OPEN_DETAILS)
         || (ulView == OPEN_SETTINGS)
         || (ulView == *G_pulVarMenuOfs + ID_XFMI_OFS_SPLITVIEW)
       )
    {
        if (ulView == OPEN_SETTINGS)
            // prevent wpSetIcon
            _fOpeningSettings = TRUE;

        hwndFrame = XWPTrashCan_parent_WPFolder_wpOpen(somSelf,
                                                       hwndCnr,
                                                       ulView,
                                                       param);
        /* if (    (ulView == OPEN_CONTENTS)
             || (ulView == OPEN_DETAILS)
           )
        {
            trshSubclassTrashCanFrame(hwndFrame,
                                      somSelf,
                                      ulView);
        } */

        _fOpeningSettings = FALSE;
    }

    return (hwndFrame);
}

/*
 *@@ wpPopulate:
 *      this instance method populates a folder, in this
 *      case, the trash can object.
 *
 *      This method only does anything if the trash can
 *      has not yet been populated. If so, we go over the
 *      "\TRASH" directories on all drives and recurse into
 *      the subdirectories to create XWPTrashObject instances
 *      in the trashcan.
 *
 *      After a call to this method, if objects are found,
 *      there will be instances of XWPTrashObject in the
 *      trash can, which can be queried using the normal
 *      wpQueryContent method. There will never be any
 *      instances of classes other than XWPTrashObject
 *      in the trash can.
 *
 *      Note that when objects are deleted into the trash can,
 *      XWPTrashCan::xwpDeleteIntoTrashCan will add trash objects
 *      only if the trash can has been populated already.
 *
 *@@changed V0.9.20 (2002-07-12) [umoeller]: finally requesting find sem properly
 */

SOM_Scope BOOL  SOMLINK xtrc_wpPopulate(XWPTrashCan *somSelf,
                                        ULONG ulReserved, PSZ pszPath,
                                        BOOL fFoldersOnly)
{
    BOOL    brc = TRUE;
    BOOL    fFindLocked = FALSE;
    ULONG   ulFldrFlags = _wpQueryFldrFlags(somSelf);

    XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpPopulate");

    // make trash can "busy"
    _xwpTrashCanBusy(somSelf,
                     +1);       // inc "busy"

    TRY_LOUD(excpt1)
    {
        // request the find mutex to avoid weird behavior;
        // there can only be one populate at a time
        // V0.9.20 (2002-07-12) [umoeller]
        if (fFindLocked = !_wpRequestFindMutexSem(somSelf, SEM_INDEFINITE_WAIT))
        {
            // we must call the parent first;
            // otherwise, we'll get a "Wait" pointer all the time
            if (XWPTrashCan_parent_WPFolder_wpPopulate(somSelf,
                                                       ulReserved,
                                                       pszPath,
                                                       fFoldersOnly))
            {
                PMPF_TRASHCAN(("%s -> wpPopulate, fFoldersOnly: %d, Flags: 0x%lX",
                                _wpQueryTitle(somSelf),
                                fFoldersOnly,
                                ulFldrFlags));

                if (!fFoldersOnly)
                {
                    if (!_fAlreadyPopulated)
                    {
                        // very first call:
                        _ulTrashObjectCount = 0;
                        _dSizeOfAllObjects = 0;

                        // tell XFolder to allow wpAddToContent hacks...
                        _xwpSetDisableCnrAdd(somSelf, TRUE);

                        brc = trshPopulateFirstTime(somSelf, ulFldrFlags);

                        _fAlreadyPopulated = TRUE;

                        // alright, now that we're done populating, we
                        // must re-enable cnr add or otherwise later
                        // objects won't get inserted
                        _xwpSetDisableCnrAdd(somSelf, FALSE);
                    }
                }

                PMPF_TRASHCAN(("End of %s -> wpPopulate, fFoldersOnly: %d",
                                _wpQueryTitle(somSelf),
                                fFoldersOnly));
            }
        }
    }
    CATCH(excpt1)
    {
        brc = FALSE;
    } END_CATCH();

    if (fFindLocked)
        _wpReleaseFindMutexSem(somSelf);

    _xwpSetCorrectTrashIcon(somSelf,
                            TRUE);      // always set icon, because wpPopulate gets
                                        // called quite frequently and the WPS keeps
                                        // resetting the icon then

    _xwpTrashCanBusy(somSelf,
                     -1);       // dec "busy"

    // save trash can's state; this will store
    // the trash object count in .CLASSINFO
    // (wpSaveState)
    // _wpSaveDeferred(somSelf);
            // now in xwpSetCorrectTrashIcon

    return brc;
}

/*
 *@@ wpRefresh:
 *      this updates a folder's contents. The default WPFolder
 *      version of this unsets the FOI_POPULATEDWITHALL folder
 *      flag and calls wpPopulate in turn, which is fine
 *      with us. However, for some stupid reason, the icon
 *      is also reset to the default icon, so we need to
 *      call XWPTrashCan::xwpSetCorrectTrashIcon again.
 */

SOM_Scope BOOL  SOMLINK xtrc_wpRefresh(XWPTrashCan *somSelf,
                                       ULONG ulView, PVOID pReserved)
{
    BOOL brc = FALSE;
    // XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpRefresh");

    brc = XWPTrashCan_parent_WPFolder_wpRefresh(somSelf, ulView,
                                                pReserved);

    trshRefresh(somSelf);

    _xwpSetCorrectTrashIcon(somSelf, TRUE);

    return brc;
}

/*
 *@@ wpAddToContent:
 *      this WPFolder method is overridden to receive
 *      notification when a trash object is added to
 *      the trash can. We update the trash can's icon
 *      and the total bytes count then.
 *
 *@@added V0.9.1 (2000-01-29) [umoeller]
 */

SOM_Scope BOOL  SOMLINK xtrc_wpAddToContent(XWPTrashCan *somSelf,
                                            WPObject* Object)
{
    BOOL brc = FALSE;
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpAddToContent");

    if (XWPTrashCan_parent_WPFolder_wpAddToContent(somSelf,
                                                   Object))
    {
        brc = TRUE;
        if (_somIsA(Object, _XWPTrashObject))
        {
            XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
            // successfully created:
            _ulTrashObjectCount++;
            // _dTotalSize += _xwpQueryRelatedSize(Object);
                    // doesn't work here yet, because related
                    // size is always zero at this point
            _xwpSetCorrectTrashIcon(somSelf, FALSE);
        }
    }

    return brc;
}

/*
 *@@ wpDeleteFromContent:
 *      this WPFolder method is overridden to receive
 *      notification when a trash object is deleted
 *      from the trash can. We update the trash can's
 *      icon and the total bytes count then.
 *
 *@@added V0.9.1 (2000-01-29) [umoeller]
 *@@changed V1.0.9 (2010-07-17) [pr]: added large file support @@fixes 586
 */

SOM_Scope BOOL  SOMLINK xtrc_wpDeleteFromContent(XWPTrashCan *somSelf,
                                                 WPObject* Object)
{
    BOOL brc = FALSE;
    // XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpDeleteFromContent");

    if (XWPTrashCan_parent_WPFolder_wpDeleteFromContent(somSelf,
                                                        Object))
    {
        brc = TRUE;
        if (_somIsA(Object, _XWPTrashObject))
        {
            // successfully created:
            XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
            LONGLONG llSize;

            _ulTrashObjectCount--;
            _xwpQueryRelatedSizeL(Object, &llSize);
            _dSizeOfAllObjects -= 65536.0 * 65536.0 * llSize.ulHi + llSize.ulLo;
            _xwpSetCorrectTrashIcon(somSelf, FALSE);
        }
    }

    return brc;
}

/*
 *@@ wpDeleteContents:
 *      this WPFolder method gets called when a folder is
 *      being deleted to first delete the contents of a
 *      folder before the folder can be deleted. From my
 *      testing, BOTH WPFolder::wpDelete and WPFolder::wpFree
 *      call this method to nuke the folder contents.
 *
 *      Even though the trash should not really be deleted,
 *      if it does, the standard WPFolder::wpDeleteContents
 *      produces total garbage. It first populates the folder and
 *      then invokes wpDelete on each item in the folder.
 *
 *      For the trash can, this is NOT the way to go. First
 *      of all, we produce all the transient trash objects during
 *      populate, so we do NOT want to have the trash can populated
 *      during delete. Even worse, WPFolder:.wpDeleteContents
 *      produces a silly message box for every single transient
 *      object then. Duh.
 *
 *      So override this method and just invoke wpFree on all
 *      objects in the folder without further discussion.
 *
 *@@added V0.9.9 (2001-02-08) [umoeller]
 */

SOM_Scope ULONG  SOMLINK xtrc_wpDeleteContents(XWPTrashCan *somSelf,
                                               ULONG fConfirmations)
{
    ULONG ulrc = NO_DELETE;
    // XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpDeleteContents");

    /* return (XWPTrashCan_parent_WPFolder_wpDeleteContents(somSelf,
                                                         fConfirmations)); */
    // note that we do not populate the folder first... if it
    // hasn't been populated, we shouldn't have a problem in the first
    // place, because there should only be trash objects in there...
    // and we don't want to create all objects first and then delete
    // them again.
    if (fdrNukeContents(somSelf))
        ulrc = OK_DELETE;

    return (ulrc);

}

/*
 *@@ wpDragOver:
 *      this instance method is called to inform the object
 *      that other objects are being dragged over it.
 *      This corresponds to the DM_DRAGOVER message received by
 *      the object.
 *
 *      See trshDragOver for the implementation.
 *
 *@@changed V0.9.1 (2000-02-01) [umoeller]: re-implemented the damn thing; support for DRM_OS2FILE added
 */

SOM_Scope MRESULT  SOMLINK xtrc_wpDragOver(XWPTrashCan *somSelf,
                                           HWND hwndCnr,
                                           PDRAGINFO pdrgInfo)
{
    // MRESULT     mrc;

    /* XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf); */
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpDragOver");

    return (trshDragOver(somSelf, pdrgInfo));
}

/*
 *@@ wpDrop:
 *      this instance method is called to inform an object that
 *      another object has been dropped on it.
 *      This corresponds to the DM_DROP message received by
 *      the object.
 *
 *      See trshMoveDropped2TrashCan for the implementation.
 *
 *@@changed V0.9.1 (2000-02-01) [umoeller]: re-implemented the damn thing; support for DRM_OS2FILE added
 */

SOM_Scope MRESULT  SOMLINK xtrc_wpDrop(XWPTrashCan *somSelf,
                                       HWND hwndCnr,
                                       PDRAGINFO pdrgInfo,
                                       PDRAGITEM pdrgItem)
{
    MRESULT     mrc = (MRESULT)RC_DROP_ERROR;

    /* XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf); */
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpDrop");

    PMPF_TRASHCAN(("pdrgInfo->hwndSource: 0x%lX", pdrgInfo->hwndSource));
            // this always has the HWND of
            // the source container
    PMPF_TRASHCAN(("pdrgInfo->cditem:     0x%lX", pdrgInfo->cditem));
            // this has the number of items that
            // are dropped; always >= 1

    mrc = trshMoveDropped2TrashCan(somSelf, pdrgInfo);

    return mrc;
}

/*
 *@@ wpAddObjectGeneralPage:
 *      this adds the object "General" page
 *      to the settings notebook.
 *      We use different icons for the trash can,
 *      so we replace this page with our own dialog
 *      by calling xwpAddTrashCanGeneralPage.
 */

SOM_Scope ULONG  SOMLINK xtrc_wpAddObjectGeneralPage(XWPTrashCan *somSelf,
                                                     HWND hwndNotebook)
{
    /* XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf); */
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpAddObjectGeneralPage");

    return (_xwpAddTrashCanGeneralPage(somSelf,
                                       hwndNotebook));
}

/*
 *@@ wpAddObjectGeneralPage2:
 *      this adds the second object "General" page
 *      for animation icons to the settings notebook.
 *      We don't support animation icons for the trash can,
 *      so we remove that page.
 */

SOM_Scope ULONG  SOMLINK xtrc_wpAddObjectGeneralPage2(XWPTrashCan *somSelf,
                                                      HWND hwndNotebook)
{
    /* XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf); */
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpAddObjectGeneralPage2");

    return SETTINGS_PAGE_REMOVED;
}

/*
 *@@ wpAddFolderIncludePage:
 *      this adds the folder "Include" page
 *      to the settings notebook.
 *      We remove that page.
 */

SOM_Scope ULONG  SOMLINK xtrc_wpAddFolderIncludePage(XWPTrashCan *somSelf,
                                                     HWND hwndNotebook)
{
    /* XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf); */
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpAddFolderIncludePage");

    return SETTINGS_PAGE_REMOVED;
}

/*
 *@@ wpAddFolderSelfClosePage:
 *      this adds the folder "Self close" page to
 *      the settings notebook. With Warp 4, this
 *      is "Window" page 2. We remove that.
 *
 *@@added V0.9.19 (2002-04-17) [umoeller]
 */

SOM_Scope ULONG  SOMLINK xtrc_wpAddFolderSelfClosePage(XWPTrashCan *somSelf,
                                                       HWND hwndNotebook)
{
    // XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpAddFolderSelfClosePage");

    /* return (XWPTrashCan_parent_WPFolder_wpAddFolderSelfClosePage(somSelf,
                                                                 hwndNotebook)); */

    return SETTINGS_PAGE_REMOVED;
}

/*
 *@@ wpAddFolderView2Page:
 *      this WPFolder method adds the "Tree view" page
 *      which we need to remove.
 *
 *@@added V0.9.1 (2000-01-29) [umoeller]
 */

SOM_Scope ULONG  SOMLINK xtrc_wpAddFolderView2Page(XWPTrashCan *somSelf,
                                                   HWND hwndNotebook)
{
    // XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpAddFolderView2Page");

    /* return (XWPTrashCan_parent_WPFolder_wpAddFolderView2Page(somSelf,
                                                             hwndNotebook)); */
    return SETTINGS_PAGE_REMOVED;
}

/*
 *@@ wpAddSettingsPages:
 *      this WPObject instance method gets called by the WPS
 *      when the Settings view is opened to have all the
 *      settings page inserted into hwndNotebook.
 *
 *      We add the "Trash can" settings page.
 */

SOM_Scope BOOL  SOMLINK xtrc_wpAddSettingsPages(XWPTrashCan *somSelf,
                                                HWND hwndNotebook)
{
    // XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpAddSettingsPages");

    XWPTrashCan_parent_WPFolder_wpAddSettingsPages(somSelf, hwndNotebook);
    _xwpAddTrashCanDrivesPage(somSelf, hwndNotebook);
    _xwpAddTrashCanSettingsPage(somSelf, hwndNotebook);

    return TRUE;
}

/*
 *@@ wpSetIcon:
 *      this instance method sets the current icon for
 *      an object. As opposed to with wpSetIconData,
 *      this does not change the icon permanently.
 *
 *      Note: If the OBJSTYLE_NOTDEFAULTICON object style
 *      flag has been set with wpSetStyle, the old icon
 *      (HPOINTER) will be destroyed.
 *      As a result, that flag needs to be unset if
 *      icons are shared between objects, as with class
 *      default icons. The OBJSTYLE_CUSTOMICON flag does
 *      NOT work, even if the WPS lists it with wpQueryStyle.
 *
 *      Also, the WPS annoyingly resets the icon to its
 *      default when a settings notebook is opened.
 *
 *@@added V0.9.4 (2000-08-03) [umoeller]
 */

SOM_Scope BOOL  SOMLINK xtrc_wpSetIcon(XWPTrashCan *somSelf,
                                       HPOINTER hptrNewIcon)
{
    XWPTrashCanData *somThis = XWPTrashCanGetData(somSelf);
    XWPTrashCanMethodDebug("XWPTrashCan","xtrc_wpSetIcon");

    if (!_fOpeningSettings)
        return XWPTrashCan_parent_WPFolder_wpSetIcon(somSelf, hptrNewIcon);

    return FALSE;
}


SOM_Scope HPOINTER  SOMLINK xtrc_wpQueryIcon(XWPTrashCan *somSelf)
{
    return _wpclsQueryIcon(_XWPTrashCan);
}


SOM_Scope HPOINTER  SOMLINK xtrc_wpQueryIconN(XWPTrashCan *somSelf, 
                                              ULONG ulIconIndex)
{
    return _wpclsQueryIconN(_XWPTrashCan, ulIconIndex);
}


SOM_Scope ULONG  SOMLINK xtrc_wpQueryIconData(XWPTrashCan *somSelf, 
                                              PICONINFO pIconInfo)
{
    return _wpclsQueryIconData(_XWPTrashCan, pIconInfo);
}


SOM_Scope ULONG  SOMLINK xtrc_wpQueryIconDataN(XWPTrashCan *somSelf, 
                                               PICONINFO pData, 
                                               ULONG ulIconIndex)
{
    return _wpclsQueryIconDataN(_XWPTrashCan, pData, ulIconIndex);
}

/* ******************************************************************
 *
 *   XWPTrashCan class methods
 *
 ********************************************************************/

/*
 *@@ xwpclsQueryDefaultTrashCan:
 *      this returns the default trash can (with the object ID
 *      &lt;XWORKPLACE_TRASHCAN&gt;).
 *
 *@@addded V0.9.1 (2000-01-31) [umoeller]
 *@@changed V0.9.9 (2001-02-06) [umoeller]: fixed dormant trash can
 */

SOM_Scope XWPTrashCan*  SOMLINK xtrcM_xwpclsQueryDefaultTrashCan(M_XWPTrashCan *somSelf)
{
    XWPTrashCan *pDefaultTrashCan = NULL;
    // M_XWPTrashCanData *somThis = M_XWPTrashCanGetData(somSelf);
    M_XWPTrashCanMethodDebug("M_XWPTrashCan","xtrcM_xwpclsQueryDefaultTrashCan");

    if (G_pDefaultTrashCan)
        pDefaultTrashCan = G_pDefaultTrashCan;
    else
        // not awake yet: try object ID
        // V0.9.9 (2001-02-06) [umoeller]
        pDefaultTrashCan = cmnQueryObjectFromID(XFOLDER_TRASHCANID);

    return (pDefaultTrashCan);
}

/*
 *@@ xwpclsSetDrivesSupport:
 *      this sets the drives which the trash can supports.
 *
 *      pabSupportedDrives must point to an array of 23
 *      bytes, specifiying the drives support. Index 0
 *      specifies drive C:, index 1 drive D:, and so on.
 *      (This implies that drives A: and B: are never
 *      supported.)
 *
 *      Each item in the array must be one of the following:
 *      -- XTRC_INVALID (0): drive is invalid, don't even
 *                  show it in the drives list.
 *      -- XTRC_SUPPORTED (1): drive is valid and supported
 *                  by the trash can.
 *      -- XTRC_UNSUPPORTED (2): drive is valid, but not
 *                  supported by the trash can.
 *
 *      NO CHECKING will be done on the values passed to
 *      this method. If you specify an invalid drive here,
 *      the trash can will probably go crazy with white
 *      hard-error boxes when populating.
 *
 *      If (pabSupportedDrives == NULL), the trash can
 *      will reset the drives support to safe default
 *      values.
 *
 *@@added V0.9.1 (99-12-13) [umoeller]
 */

SOM_Scope BOOL  SOMLINK xtrcM_xwpclsSetDrivesSupport(M_XWPTrashCan *somSelf,
                                                     PBYTE pabSupportedDrives)
{
    M_XWPTrashCanMethodDebug("M_XWPTrashCan","xtrcM_xwpclsSetDrivesSupport");

    return (trshSetDrivesSupport(pabSupportedDrives));
}

/*
 *@@ xwpclsQueryDrivesSupport:
 *      this copies the current trash can drives support
 *      to the specified buffer.
 *
 *      pabSupportedDrives must point to an array of 23
 *      bytes, receiving the drives support. Index 0 then
 *      specifies drive C:, index 1 drive D:, and so on.
 *      (This implies that drives A: and B: are never
 *      supported.)
 *
 *      Each item in the array will be one of the following:
 *      -- XTRC_INVALID (0): drive is invalid, don't even
 *                  show it in the drives list.
 *      -- XTRC_SUPPORTED (1): drive is valid and supported
 *                  by the trash can.
 *      -- XTRC_UNSUPPORTED (2): drive is valid, but not
 *                  supported by the trash can.
 *
 *@@added V0.9.1 (99-12-13) [umoeller]
 */

SOM_Scope BOOL  SOMLINK xtrcM_xwpclsQueryDrivesSupport(M_XWPTrashCan *somSelf,
                                                       PBYTE pabSupportedDrives)
{
    M_XWPTrashCanMethodDebug("M_XWPTrashCan","xtrcM_xwpclsQueryDrivesSupport");

    return (trshQueryDrivesSupport(pabSupportedDrives));
}

/*
 *@@ wpclsInitData:
 *      this WPObject class method gets called when a class
 *      is loaded by the WPS (probably from within a
 *      somFindClass call) and allows the class to initialize
 *      itself.
 *
 *      We set up some global trash can data and also make
 *      sure that the XWPTrashObject class gets initialized.
 *
 *@@changed V0.9.1 (2000-01-27) [umoeller]: finally fixed those strange crashes in some WPS background thread
 *@@changed V0.9.7 (2001-01-15) [umoeller]: added more error checking
 */

SOM_Scope void  SOMLINK xtrcM_wpclsInitData(M_XWPTrashCan *somSelf)
{
    SOMClass *pTrashObjectClassObject;
    M_XWPTrashCanData *somThis = M_XWPTrashCanGetData(somSelf);

    // M_XWPTrashCanData *somThis = M_XWPTrashCanGetData(somSelf);
    M_XWPTrashCanMethodDebug("M_XWPTrashCan","xtrcM_wpclsInitData");

    M_XWPTrashCan_parent_M_WPFolder_wpclsInitData(somSelf);

    if (krnClassInitialized(G_pcszXWPTrashCan))
    {
        // first call:

        // enforce initialization of XWPTrashObject class
        if (pTrashObjectClassObject = XWPTrashObjectNewClass(XWPTrashObject_MajorVersion,
                                                             XWPTrashObject_MinorVersion))
        {
            // now increment the class's usage count by one to
            // ensure that the class is never unloaded; if we
            // didn't do this, we'd get WPS CRASHES in some
            // background class because if no more trash objects
            // exist, the class would get unloaded automatically -- sigh...
            _wpclsIncUsage(pTrashObjectClassObject);
        }
        else
            cmnLog(__FILE__, __LINE__, __FUNCTION__,
                   "Cannot initialize XWPTrashObject class. Is it installed?!?");
    }

    // initialize supported drives
    if (!G_fDrivesInitialized)
    {
        trshLoadDrivesSupport(somSelf);
        G_fDrivesInitialized = TRUE;
    }

    cmnGetStandardIcon(STDICON_TRASH_EMPTY, &_hptrEmpty, 0, 0);
    cmnGetStandardIcon(STDICON_TRASH_FULL, &_hptrFilled, 0, 0);
}

/*
 *@@ wpclsUnInitData:
 *
 *@@added V0.9.1 (2000-01-29) [umoeller]
 */

SOM_Scope void  SOMLINK xtrcM_wpclsUnInitData(M_XWPTrashCan *somSelf)
{
    // M_XWPTrashCanData *somThis = M_XWPTrashCanGetData(somSelf);
    M_XWPTrashCanMethodDebug("M_XWPTrashCan","xtrcM_wpclsUnInitData");

    _wpclsDecUsage(_XWPTrashObject);

    M_XWPTrashCan_parent_M_WPFolder_wpclsUnInitData(somSelf);
}

/*
 *@@ wpclsCreateDefaultTemplates:
 *      this WPObject class method is called by the
 *      Templates folder to allow a class to
 *      create its default templates.
 *
 *      The default WPS behavior is to create new templates
 *      if the class default title is different from the
 *      existing templates.
 *
 *@@added V0.9.7 (2001-01-17) [umoeller]
 */

SOM_Scope BOOL  SOMLINK xtrcM_wpclsCreateDefaultTemplates(M_XWPTrashCan *somSelf,
                                                          WPObject* Folder)
{
    /* M_XWPTrashCanData *somThis = M_XWPTrashCanGetData(somSelf); */
    M_XWPTrashCanMethodDebug("M_XWPTrashCan","xtrcM_wpclsCreateDefaultTemplates");

    // pretend we've created the templates
    return TRUE;
}

/*
 *@@ wpclsQueryTitle:
 *      this WPObject class method tells the WPS the clear
 *      name of a class, which is shown in the third column
 *      of a Details view and also used as the default title
 *      for new objects of a class.
 */

SOM_Scope PSZ  SOMLINK xtrcM_wpclsQueryTitle(M_XWPTrashCan *somSelf)
{
    // PNLSSTRINGS pNLSStrings = cmnQueryNLSStrings();
    /* M_XWPTrashCanData *somThis = M_XWPTrashCanGetData(somSelf); */
    M_XWPTrashCanMethodDebug("M_XWPTrashCan","xtrcM_wpclsQueryTitle");

    return (cmnGetString(ID_XTSI_TRASHCAN)) ; // pszTrashCan
}

/*
 *@@ wpclsQueryStyle:
 *      we return a flag so that no trash can templates are created.
 *
 *@@changed V0.9.16 (2001-11-25) [umoeller]: added nevertemplate
 */

SOM_Scope ULONG  SOMLINK xtrcM_wpclsQueryStyle(M_XWPTrashCan *somSelf)
{
    /* M_XWPTrashCanData *somThis = M_XWPTrashCanGetData(somSelf); */
    M_XWPTrashCanMethodDebug("M_XWPTrashCan","xtrcM_wpclsQueryStyle");

    return (CLSSTYLE_NEVERTEMPLATE      // V0.9.16 (2001-11-25) [umoeller]
                | CLSSTYLE_NEVERCOPY    // but allow move
                | CLSSTYLE_NEVERDELETE
                | CLSSTYLE_NEVERPRINT);
}

/*
 *@@ wpclsQueryDefaultHelp:
 *      this WPObject class method returns the default help
 *      panel for objects of this class. This gets called
 *      from WPObject::wpQueryDefaultHelp if no instance
 *      help settings (HELPLIBRARY, HELPPANEL) have been
 *      set for an individual object. It is thus recommended
 *      to override this method instead of the instance
 *      method to change the default help panel for a class
 *      in order not to break instance help settings (fixed
 *      with 0.9.20).
 *
 *      We override the standard folder help and return help
 *      for the trash can here.
 *
 *@@added V0.9.20 (2002-07-12) [umoeller]
 */

SOM_Scope BOOL  SOMLINK xtrcM_wpclsQueryDefaultHelp(M_XWPTrashCan *somSelf,
                                                    PULONG pHelpPanelId,
                                                    PSZ pszHelpLibrary)
{
    /* M_XWPTrashCanData *somThis = M_XWPTrashCanGetData(somSelf); */
    M_XWPTrashCanMethodDebug("M_XWPTrashCan","xtrcM_wpclsQueryDefaultHelp");

    strcpy(pszHelpLibrary, cmnQueryHelpLibrary());
    *pHelpPanelId = ID_XSH_SETTINGS_TRASHCAN;
    return TRUE;
}

/*
 *@@ wpclsQueryIconData:
 *      this WPObject class method must return information
 *      about how to build the default icon for objects
 *      of a class. This gets called from various other
 *      methods whenever a class default icon is needed;
 *      most importantly, M_WPObject::wpclsQueryIcon
 *      calls this to build a class default icon, which
 *      is then cached in the class's instance data.
 *      If a subclass wants to change a class default icon,
 *      it should always override _this_ method instead of
 *      wpclsQueryIcon.
 *
 *      Note that the default WPS implementation does not
 *      allow for specifying the ICON_FILE format here,
 *      which is why we have overridden
 *      M_XFldObject::wpclsQueryIcon too. This allows us
 *      to return icon _files_ for theming too. For details
 *      about the WPS's crappy icon management, refer to
 *      src\filesys\icons.c.
 *
 *      We give the trash can a new standard icon here.
 */

SOM_Scope ULONG  SOMLINK xtrcM_wpclsQueryIconData(M_XWPTrashCan *somSelf,
                                                  PICONINFO pIconInfo)
{
    /* M_XWPTrashCanData *somThis = M_XWPTrashCanGetData(somSelf); */
    M_XWPTrashCanMethodDebug("M_XWPTrashCan","xtrcM_wpclsQueryIconData");

    if (pIconInfo)
    {
        pIconInfo->fFormat = ICON_RESOURCE;
        pIconInfo->resid   = ID_ICONXWPTRASHEMPTY;
        pIconInfo->hmod    = cmnQueryMainResModuleHandle();
    }

    return (sizeof(ICONINFO));
}

/*
 *@@ wpclsQueryIconDataN:
 *      this should return the class default
 *      "animation" icons (for open folders).
 *      The trashcan does not use an animation
 *      icon, but only "empty" or "not empty"
 *      icons, so we return the same icon
 *      as in M_XWPTrashCan::wpclsQueryIconData.
 */

SOM_Scope ULONG  SOMLINK xtrcM_wpclsQueryIconDataN(M_XWPTrashCan *somSelf,
                                                   ICONINFO* pIconInfo,
                                                   ULONG ulIconIndex)
{
    /* M_XWPTrashCanData *somThis = M_XWPTrashCanGetData(somSelf); */
    M_XWPTrashCanMethodDebug("M_XWPTrashCan","xtrcM_wpclsQueryIconDataN");

    if (pIconInfo)
    {
        pIconInfo->fFormat = ICON_RESOURCE;
        pIconInfo->resid   = ulIconIndex ? ID_ICONXWPTRASHFILLED : ID_ICONXWPTRASHEMPTY;
        pIconInfo->hmod    = cmnQueryMainResModuleHandle();
    }

    return (sizeof(ICONINFO));
}

SOM_Scope HPOINTER  SOMLINK xtrcM_wpclsQueryIcon(M_XWPTrashCan *somSelf)
{
    M_XWPTrashCanData *somThis = M_XWPTrashCanGetData(somSelf);

    return _hptrEmpty;
}


SOM_Scope HPOINTER  SOMLINK xtrcM_wpclsQueryIconN(M_XWPTrashCan *somSelf, 
                                                  ULONG ulIconIndex)
{
    M_XWPTrashCanData *somThis = M_XWPTrashCanGetData(somSelf);

    if (!ulIconIndex)
        return _hptrEmpty;

    if (ulIconIndex == 1)
        return _hptrFilled;

    return 0;
}

