
/*
 *@@sourcefile xwppgmf.c:
 *      This file contains SOM code for the following XWorkplace classes:
 *
 *      --  XWPProgramFile (WPProgramFile replacement)
 *
 *      XFldProgram is only responsible for
 *
 *      --  changing the default icons of executable files;
 *
 +      --  adding a few more instance settings pages (V0.9.9).
 *
 *      Installation of this class is optional.
 *
 *      Starting with V0.9.0, the files in classes\ contain only
 *      i.e. the methods themselves.
 *      The implementation for this class is in filesys\filesys.c.
 *
 *      With V0.9.16, the class name has been changed from
 *      XFldProgramFile to XWPProgramFile.
 *
 *@@somclass XWPProgramFile xpgf_
 *@@somclass M_XWPProgramFile xpgfM_
 */

/*
 *      Copyright (C) 1997-2003 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_xpgf_Source
#define SOM_Module_xpgf_Source
#endif
#define XWPProgramFile_Class_Source
#define M_XWPProgramFile_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_DOSEXCEPTIONS
#define INCL_DOSSEMAPHORES
#define INCL_DOSSESMGR          // DosQueryAppType
#define INCL_DOSMODULEMGR
#define INCL_DOSERRORS

#define INCL_WINPOINTERS
#define INCL_WINPROGRAMLIST     // needed for PROGDETAILS, wppgm.h
#include <os2.h>

// C library headers
#include <stdio.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\apps.h"               // application helpers
#include "helpers\dosh.h"               // Control Program helper routines
#include "helpers\except.h"             // exception handling
#include "helpers\exeh.h"               // executable helpers
#include "helpers\nls.h"                // National Language Support helpers
#include "helpers\standards.h"          // some standard macros
#include "helpers\winh.h"               // PM helper routines

// SOM headers which don't crash with prec. header files
#include "xfdataf.ih"
#include "xwppgmf.ih"

// XWorkplace implementation headers
#include "dlgids.h"                     // all the IDs that are shared with NLS
#include "shared\classtest.h"           // some cheap funcs for WPS class checks
#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 "shared\wpsh.h"                // some pseudo-SOM functions (WPS helper routines)

#include "filesys\filesys.h"            // various file-system object implementation code
#include "filesys\filetype.h"           // extended file types implementation
#include "filesys\icons.h"              // icons handling
#include "filesys\program.h"            // program implementation; WARNING: this redefines macros

#pragma hdrstop                         // VAC++ keeps crashing otherwise

/* ******************************************************************
 *
 *   Global variables
 *
 ********************************************************************/

static PCSZ G_pcszPgmFileFilter = "OS2KRNL,*.ADD,*.COM,*.DLL,*.DMD,*.EXE,*.FLT,*.IFS,*.SNP,*.SYS";

/* ******************************************************************
 *
 *   XWPProgramFile instance methods
 *
 ********************************************************************/

/*
 *@@ xwpAddResourcesPage:
 *      this new XWPProgramFile method adds the "Resources"
 *      page to an executable's settings notebook.
 *
 *      Gets called from our
 *      XWPProgramFile::wpAddProgramSessionPage override.
 *
 *@@added V0.9.9 (2001-03-07) [umoeller]
 *@@changed V0.9.9 (2001-03-30) [umoeller]: replaced dialog resource with generic cnr page
 */

SOM_Scope ULONG  SOMLINK xpgf_xwpAddResourcesPage(XWPProgramFile *somSelf,
                                                  HWND hwndNotebook)
{
    ULONG ulrc = SETTINGS_PAGE_REMOVED;
    INSERTNOTEBOOKPAGE inbp;

    // XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_xwpAddResourcesPage");

#ifndef __NOMODULEPAGES__
    memset(&inbp, 0, sizeof(INSERTNOTEBOOKPAGE));
    inbp.somSelf = somSelf;
    inbp.hwndNotebook = hwndNotebook;
    inbp.hmod = cmnQueryNLSModuleHandle(FALSE);
    inbp.usPageStyleFlags = BKA_MAJOR;
    inbp.pcszName = cmnGetString(ID_XSSI_PGMFILE_RESOURCES);  // pszResourcesPage
    inbp.ulDlgID = ID_XFD_CONTAINERPAGE; // ID_XSD_PGMFILE_RESOURCES;
    inbp.ulDefaultHelpPanel  = ID_XSH_SETTINGS_PGMFILE_RESOURCES;
    inbp.ulPageID = SP_PROG_RESOURCES;
    // V0.9.9 (2001-03-30) [umoeller]: added resize
    inbp.pampControlFlags = G_pampGenericCnrPage;
    inbp.cControlFlags = G_cGenericCnrPage;
    inbp.pfncbInitPage    = progResourcesInitPage;
    inbp.pfncbMessage     = progResourcesMessage;
    ulrc = ntbInsertPage(&inbp);
#endif

    return ulrc;
}

/*
 *@@ xwpAddModulePage:
 *      this new XWPProgramFile method adds the "Module"
 *      pages to an executable's settings notebook.
 *
 *      Gets called from our
 *      XWPProgramFile::wpAddProgramSessionPage override.
 *
 *@@added V0.9.9 (2001-03-07) [umoeller]
 *@@changed V0.9.9 (2001-03-11) [lafaix]: added two subpages (imports and exports)
 *@@changed V0.9.9 (2001-03-30) [umoeller]: replaced dialog resource with generic cnr page
 */

SOM_Scope ULONG  SOMLINK xpgf_xwpAddModulePage(XWPProgramFile *somSelf,
                                               HWND hwndNotebook)
{
    ULONG ulrc = SETTINGS_PAGE_REMOVED;
    INSERTNOTEBOOKPAGE inbp;

    // XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_xwpAddModulePage");

#ifndef __NOMODULEPAGES__
    memset(&inbp, 0, sizeof(INSERTNOTEBOOKPAGE));
    inbp.somSelf = somSelf;
    inbp.hwndNotebook = hwndNotebook;
    inbp.hmod = cmnQueryNLSModuleHandle(FALSE);
    inbp.usPageStyleFlags = BKA_MINOR;
    inbp.fEnumerate = TRUE;
    inbp.pcszName = cmnGetString(ID_XSSI_PGMFILE_MODULE2);  // pszModule2Page
    inbp.ulDlgID = ID_XFD_CONTAINERPAGE; // ID_XSD_PGMFILE_MODULE2;
    inbp.ulDefaultHelpPanel  = ID_XSH_SETTINGS_PGMFILE_MODULE2;
    inbp.ulPageID = SP_PROG_DETAILS2;
    // V0.9.9 (2001-03-30) [umoeller]: added resize
    inbp.pampControlFlags = G_pampGenericCnrPage;
    inbp.cControlFlags = G_cGenericCnrPage;
    inbp.pfncbInitPage    = progFile2InitPage;
    ntbInsertPage(&inbp);

    memset(&inbp, 0, sizeof(INSERTNOTEBOOKPAGE));
    inbp.somSelf = somSelf;
    inbp.hwndNotebook = hwndNotebook;
    inbp.hmod = cmnQueryNLSModuleHandle(FALSE);
    inbp.usPageStyleFlags = BKA_MINOR;
    inbp.fEnumerate = TRUE;
    inbp.pcszName = cmnGetString(ID_XSSI_PGMFILE_MODULE1);  // pszModule1Page
    inbp.ulDlgID = ID_XFD_CONTAINERPAGE; // ID_XSD_PGMFILE_MODULE1;
    inbp.ulDefaultHelpPanel  = ID_XSH_SETTINGS_PGMFILE_MODULE1;
    inbp.ulPageID = SP_PROG_DETAILS1;
    // V0.9.9 (2001-03-30) [umoeller]: added resize
    inbp.pampControlFlags = G_pampGenericCnrPage;
    inbp.cControlFlags = G_cGenericCnrPage;
    inbp.pfncbInitPage    = progFile1InitPage;
    ntbInsertPage(&inbp);

    memset(&inbp, 0, sizeof(INSERTNOTEBOOKPAGE));
    inbp.somSelf = somSelf;
    inbp.hwndNotebook = hwndNotebook;
    inbp.hmod = cmnQueryNLSModuleHandle(FALSE);
    inbp.usPageStyleFlags = BKA_MAJOR;
    inbp.fEnumerate = TRUE;
    inbp.pcszName = cmnGetString(ID_XSSI_PGMFILE_MODULE);  // pszModulePage
    inbp.ulDlgID = ID_XSD_PGMFILE_MODULE;
    inbp.ulDefaultHelpPanel  = ID_XSH_SETTINGS_PGMFILE_MODULE;
    inbp.ulPageID = SP_PROG_DETAILS;
    inbp.pfncbInitPage    = progFileInitPage;
    ulrc = ntbInsertPage(&inbp);
#endif

    return ulrc;
}

/*
 *@@ xwpAddAssociationsPage:
 *      this new XWPProgramFile method adds our replacement
 *      "Associations" page to an executable's settings notebook.
 *
 *      Gets called from our
 *      XWPProgramFile::wpAddProgramAssociationPage override,
 *      if extended associations are enabled.
 *
 *@@added V0.9.9 (2001-03-07) [umoeller]
 */

SOM_Scope ULONG  SOMLINK xpgf_xwpAddAssociationsPage(XWPProgramFile *somSelf,
                                                     HWND hwndNotebook)
{
    ULONG   ulrc = 0;
    // XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_xwpAddAssociationsPage");

#ifndef __NOTURBOFOLDERS__
    ulrc = ftypInsertAssociationsPage(somSelf,
                                      hwndNotebook);
#endif

    return ulrc;
}

/*
 *@@ xwpQueryProgType:
 *      this returns the PROG_* flag signalling the executable
 *      type of the program file.
 *
 *      With the PVOID pvExec parameter, you can pass in a
 *      PEXECUTABLE (from exehOpen) if you currently have
 *      one open. This is used from XWPProgramFile::wpSetProgIcon
 *      because that method needs to open a PEXECUTABLE anyway
 *      and we'd rather avoid opening that twice.
 *
 *      If NULL is passed in for pvExec, this method calls exehOpen
 *      itself.
 *
 *      Same for pszFullFile: if you have run wpQueryFilename(TRUE)
 *      for the object already, you can pass that buffer in. Otherwise,
 *      if (pszFullFile == NULL), we'll run wpQueryFilename(TRUE)
 *      ourselves here.
 *
 *      Note that if a folder is opened, the first time this gets
 *      called is as a result of XWPProgramFile::wpSetProgIcon,
 *      because that is in turn invoked on the first invocation
 *      of wpQueryIcon (when the folder first needs to display
 *      the icon). As a result, duplicate exehOpen's are only
 *      invoked in certain pathological cases where speed isn't
 *      high priority in the first case.
 *
 *@@changed V0.9.9 (2001-03-07) [umoeller]: extracted winhQueryAppType
 *@@changed V0.9.16 (2001-12-08) [umoeller]: added pvExec param
 */

SOM_Scope ULONG  SOMLINK xpgf_xwpQueryProgType(XWPProgramFile *somSelf,
                                               PVOID pvExec,
                                               PSZ pszFullFile)
{
    CHAR    szFullFile[CCHMAXPATH];

    XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_xwpQueryProgType");

    /*
       #define PROG_DEFAULT             (PROGCATEGORY)0
       #define PROG_FULLSCREEN          (PROGCATEGORY)1
       #define PROG_WINDOWABLEVIO       (PROGCATEGORY)2
       #define PROG_PM                  (PROGCATEGORY)3
       #define PROG_GROUP               (PROGCATEGORY)5
       #define PROG_REAL                (PROGCATEGORY)4
       #define PROG_VDM                 (PROGCATEGORY)4
       #define PROG_WINDOWEDVDM         (PROGCATEGORY)7
       #define PROG_DLL                 (PROGCATEGORY)6
       #define PROG_PDD                 (PROGCATEGORY)8
       #define PROG_VDD                 (PROGCATEGORY)9
       #define PROG_WINDOW_REAL         (PROGCATEGORY)10
       #define PROG_WINDOW_PROT         (PROGCATEGORY)11
       #define PROG_30_STD              (PROGCATEGORY)11
       #define PROG_WINDOW_AUTO         (PROGCATEGORY)12
       #define PROG_SEAMLESSVDM         (PROGCATEGORY)13
       #define PROG_30_STDSEAMLESSVDM   (PROGCATEGORY)13
       #define PROG_SEAMLESSCOMMON      (PROGCATEGORY)14
       #define PROG_30_STDSEAMLESSCOMMON (PROGCATEGORY)14
       #define PROG_31_STDSEAMLESSVDM   (PROGCATEGORY)15
       #define PROG_31_STDSEAMLESSCOMMON (PROGCATEGORY)16
       #define PROG_31_ENHSEAMLESSVDM   (PROGCATEGORY)17
       #define PROG_31_ENHSEAMLESSCOMMON (PROGCATEGORY)18
       #define PROG_31_ENH              (PROGCATEGORY)19
       #define PROG_31_STD              (PROGCATEGORY)20
       #define PROG_DOS_GAME            (PROGCATEGORY)21
       #define PROG_WIN_GAME            (PROGCATEGORY)22
       #define PROG_DOS_MODE            (PROGCATEGORY)23
       #define PROG_RESERVED            (PROGCATEGORY)255
    */

    if (_ulAppType == -1)
    {
        // not queried yet, and not restored in wpRestoreData:

        if (!pszFullFile)
            // full file not given: get it now
            if (_wpQueryFilename(somSelf,
                                 szFullFile,
                                 TRUE))
                pszFullFile = szFullFile;

        if (pszFullFile)
        {
            _ulAppType = progQueryProgType(pszFullFile,
                                           pvExec);
        }
    }

    PMPF_ASSOCS(("  End of xwpQueryProgType, returning: 0x%lX (%s)",
                _ulAppType, exehDescribeProgType(_ulAppType)));

    return _ulAppType;

}

/*
 *@@ xwpQuerySetup2:
 *      this XFldObject method is overridden to support
 *      setup strings for program files.
 *
 *      This uses code in filesys\filesys.c which is
 *      shared for WPProgram and WPProgramFile instances.
 *
 *      See XFldObject::xwpQuerySetup2 for details.
 *
 *@@added V0.9.4 (2000-08-02) [umoeller]
 *@@changed V0.9.16 (2001-10-11) [umoeller]: adjusted to new implementation
 *@@changed V1.0.1 (2002-12-08) [umoeller]: now calling parent methods directly
 */

SOM_Scope BOOL  SOMLINK xpgf_xwpQuerySetup2(XWPProgramFile *somSelf,
                                            PVOID pstrSetup)
{
    // XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_xwpQuerySetup2");

    // call implementation
    if (progQuerySetup(somSelf, pstrSetup))
        return parent_xwpQuerySetup2(somSelf,
                                     pstrSetup);

    return FALSE;
}

/*
 *@@ 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.
 */

SOM_Scope void  SOMLINK xpgf_wpInitData(XWPProgramFile *somSelf)
{
    XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_wpInitData");

    XWPProgramFile_parent_WPProgramFile_wpInitData(somSelf);

    // initialize instance data
    _ulDosAppType = -1;
    _ulAppType = -1;

    _pWszUsingIconFile = NULL;

    _pulStartupDirHandle = NULL;
    _pProgType = NULL;
    _ppszStartupDir = NULL;
    _ppszEnvironment = NULL;
    _pswpInitial = NULL;
}

/*
 *@@ wpUnInitData:
 *      this WPObject instance method is called when the object
 *      is destroyed as a SOM object, either because it's being
 *      made dormant (via wpMakeDormant) or being deleted for
 *      good (via wpFree). All allocated in-memory resources
 *      should be freed here, but to destroy the physical
 *      representation of the object, override wpDestroyObject
 *      instead.
 *
 *      The parent method must always be called last.
 *
 *@@added V0.9.18 (2002-03-24) [umoeller]
 */

SOM_Scope void  SOMLINK xpgf_wpUnInitData(XWPProgramFile *somSelf)
{
    XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_wpUnInitData");

    wpshStore(somSelf,
              &_pWszUsingIconFile,
              NULL,
              NULL);

    XWPProgramFile_parent_WPProgramFile_wpUnInitData(somSelf);
}

/*
 *@@ wpDestroyObject:
 *      this undocumented WPObject method gets called during
 *      wpFree processing to destroy the physical storage of
 *      an object (for file-system objects, the file or folder,
 *      for abstracts, the INI data).
 *
 *      Starting with V0.9.20, we are now able to override this
 *      undocumented WPS method too, so the previous overhead
 *      with xwpDestroyStorage has been removed.
 *
 *      We override this in order to prevent the original
 *      WPProgramFile::wpDestroyObject to be called, which
 *      messes wrongly with our association data. Instead,
 *      we destroy any association data in the OS2.INI
 *      file ourselves and them jump directly to
 *      WPDataFile::wpDestroyObject.
 *
 *@@added V0.9.20 (2002-07-25) [umoeller]
 */

SOM_Scope BOOL  SOMLINK xpgf_wpDestroyObject(XWPProgramFile *somSelf)
{
    static somTD_WPObject_wpDestroyObject pXFldDataFile_wpDestroyObject = NULL;

    BOOL brc = FALSE;

    // XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_wpDestroyObject");

    if (!pXFldDataFile_wpDestroyObject)
    {
        // first call:
        // resolve XFldDataFile::xwpDestroyStorage
        pXFldDataFile_wpDestroyObject
            = (somTD_WPObject_wpDestroyObject)wpshResolveFor(somSelf,
                                                    _XFldDataFile,
                                                    "wpDestroyObject");
    }

    if (pXFldDataFile_wpDestroyObject)
    {
        // clean up program resources in INI file;
        // there's no way to avoid running through
        // the entire handles cache, unfortunately...
        // @@todo once we get the file handles engine
        // running, make sure we won't call wpQueryHandle
        // here!!
        ftypAssocObjectDeleted(somSelf);        // V0.9.20 (2002-07-31) [umoeller]

        // call WPAbstract::wpDestroyObject explicitly,
        // skipping WPProgram
        brc = pXFldDataFile_wpDestroyObject(somSelf);
    }
    else
        cmnLog(__FILE__, __LINE__, __FUNCTION__,
               "Cannot resolve WPDataFile::wpDestroyObject.");

    return brc;

    // return XWPProgramFile_parent_WPProgramFile_wpDestroyObject(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.
 */

SOM_Scope void  SOMLINK xpgf_wpObjectReady(XWPProgramFile *somSelf,
                                           ULONG ulCode,
                                           WPObject* refObject)
{
    XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_wpObjectReady");

    XWPProgramFile_parent_WPProgramFile_wpObjectReady(somSelf,
                                                       ulCode,
                                                       refObject);

    if (ulCode & OR_REFERENCE)
    {
        // according to wpobject.h, this flag is set for
        // OR_FROMTEMPLATE, OR_FROMCOPY, OR_SHADOW; this
        // means that refObject is valid

        // reset our app type flags, because when program files
        // are _copied_, wpSetProgIcon gets called one time too early
        // (between wpInitData and wpObjectReady; at this point,
        // the PROGDETAILS have no meaningful values, and xwpQueryProgType
        // has returned garbage data),
        // and a second time in time (after wpObjectReady);
        // for this second time we need to pretend that we haven't
        // queried the app type yet, because for the second call
        // of wpSetProgIcon, the icon will then be set correctly
        _ulDosAppType = -1;
        _ulAppType = -1;
    }
}

/*
 *@@ wpRestoreState:
 *
 */

SOM_Scope BOOL  SOMLINK xpgf_wpRestoreState(XWPProgramFile *somSelf,
                                            ULONG ulReserved)
{
    ULONG ulStyle;
    BOOL brc;
    // XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_wpRestoreState");

    /* _PmpfF(("%s, old style: 0x%lX %s %s",
                _wpQueryTitle(somSelf),
                 ulStyle = _wpQueryStyle(somSelf),
                 (ulStyle & OBJSTYLE_NOTDEFAULTICON) ? "OBJSTYLE_NOTDEFAULTICON" : "",
                 (ulStyle & OBJSTYLE_CUSTOMICON) ? "OBJSTYLE_CUSTOMICON" : ""));
      */
    _wpModifyStyle(somSelf,
                   OBJSTYLE_NOTDEFAULTICON,
                   0);

    brc = XWPProgramFile_parent_WPProgramFile_wpRestoreState(somSelf,
                                                              ulReserved);
    /* _PmpfF(("%s, new style: 0x%lX %s %s",
                _wpQueryTitle(somSelf),
                 ulStyle = _wpQueryStyle(somSelf),
                 (ulStyle & OBJSTYLE_NOTDEFAULTICON) ? "OBJSTYLE_NOTDEFAULTICON" : "",
                 (ulStyle & OBJSTYLE_CUSTOMICON) ? "OBJSTYLE_CUSTOMICON" : ""));
    */

    return brc;
}

/*
 *@@ wpRestoreData:
 *
 *@@added V0.9.16 (2001-12-08) [umoeller]
 */

SOM_Scope BOOL  SOMLINK xpgf_wpRestoreData(XWPProgramFile *somSelf,
                                           PSZ pszClass,
                                           ULONG ulKey,
                                           PBYTE pValue,
                                           PULONG pcbValue)
{
    XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_wpRestoreData");

    // intercept pointer to internal WPProgram data
    if (    (pValue)
         && (!strcmp(pszClass, "WPProgramFile"))
       )
    {
        switch (ulKey)
        {
            case 10:            // longs array
                _pulStartupDirHandle = (PULONG)pValue;
                // progtype comes next
                _pProgType = (PPROGTYPE)(_pulStartupDirHandle + 1);
                if (_pProgType->progc)
                    // if this is set explicitly, we shouldn't
                    // make the default assumptions in xwpqueryprogtype
                    _ulAppType = _pProgType->progc;
            break;

            case 11:            // strings array
                // ppszStartupDir
            break;

            case 5:             // environment
                // _ppszEnvironment = pValue;
                        // warning, this appears to be a heap buffer
                        // and can change
            break;

            case 6:             // initial SWP
                _pswpInitial = (PSWP)pValue;
            break;
        }
    }

    return XWPProgramFile_parent_WPProgramFile_wpRestoreData(somSelf,
                                                             pszClass,
                                                             ulKey,
                                                             pValue,
                                                             pcbValue);
}

/*
 *@@ wpQueryDefaultView:
 *      this WPObject method returns the default view of an object,
 *      that is, which view is opened if the program file is
 *      double-clicked upon. This is also used to mark
 *      the default view in the "Open" context submenu.
 *
 *      For WPProgramFile, the WPS always returns
 *      OPEN_RUNNING (0x04), which doesn't make sense
 *      for DLL's and drivers, which cannot be executed.
 *      We therefore return the value for "first associated
 *      program", which is 0x1000.
 *      Oh yes, as usual, this value is undocumented. ;-)
 */

SOM_Scope ULONG  SOMLINK xpgf_wpQueryDefaultView(XWPProgramFile *somSelf)
{
    ULONG ulView;

    ULONG ulProgType = _xwpQueryProgType(somSelf, NULL, NULL);

    // XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_wpQueryDefaultView");

    PMPF_ASSOCS(("[%s]", _wpQueryTitle(somSelf) ));

    ulView = XWPProgramFile_parent_WPProgramFile_wpQueryDefaultView(somSelf);

    if (    (ulProgType == PROG_DLL)
         || (ulProgType == PROG_PDD)
         || (ulProgType == PROG_VDD)
         || (ulProgType == PROG_DEFAULT)
       )
        if (ulView == OPEN_RUNNING)
            // we can neither run DLL's nor drivers, so we
            // pass the first context menu item
            ulView = 0x1000;        // this is the WPS internal code
                                    // for the first association view

    return ulView;
}

/*
 *@@ wpQueryDefaultHelp:
 *      this WPObject instance method specifies the default
 *      help panel for an object (when "Extended help" is
 *      selected from the object's context menu). This should
 *      describe what this object can do in general.
 *      We must return TRUE to report successful completion.
 *
 *      The WPObject implementation checks for whether the
 *      object has instance help settings set (HELPLIBRARY,
 *      HELPPANEL) and, if so, returns those settings or
 *      calls the class method wpclsQueryDefaultHelp instead.
 *      It is thus recommended to always override the class
 *      method because otherwise instance help settings
 *      break for objects of a class (fixed with 0.9.20).
 *
 *      We make an exception here because we need to select
 *      the default help panel based on the program type
 *      of this program file, and no sane person would
 *      change the default help panel for a program file
 *      on disk anyway.
 *
 *      We replace the default help panel for program files
 *      because the WPS even displays the standard data
 *      file help for them: "This data file is associated
 *      with the system editor per default." Yeah, right.
 *
 *@@added V0.9.16 (2002-01-13) [umoeller]
 *@@changed V0.9.20 (2002-07-12) [umoeller]: added more help
 */

SOM_Scope BOOL  SOMLINK xpgf_wpQueryDefaultHelp(XWPProgramFile *somSelf,
                                                PULONG pHelpPanelId,
                                                PSZ HelpLibrary)
{
    // XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_wpQueryDefaultHelp");

    strcpy(HelpLibrary, cmnQueryHelpLibrary());

    // V0.9.20 (2002-07-12) [umoeller]
    if (ctsIsCommandFile(somSelf))
    {
        // batch file:
        CHAR szFilename[CCHMAXPATH];
        if (    (_wpQueryFilename(somSelf, szFilename, FALSE))
             && (!stricmp(szFilename, "AUTOEXEC.BAT"))
           )
            *pHelpPanelId = ID_XSH_PROGRAMFILE_AUTOEXEC;
        else
            *pHelpPanelId = ID_XSH_PROGRAMFILE_BATCH;

        return TRUE;
    }

    switch (_xwpQueryProgType(somSelf, NULL, NULL))
    {
        // DLLs, drivers
        case PROG_DLL:                  // (PROGCATEGORY)6
            *pHelpPanelId = ID_XSH_PROGRAMFILE_DLL;
        break;

        case PROG_PDD:                  // (PROGCATEGORY)8
        case PROG_VDD:                  // (PROGCATEGORY)9
            *pHelpPanelId = ID_XSH_PROGRAMFILE_DRIVER;
        break;

        /*
        // OS/2 text mode
        case PROG_FULLSCREEN:           // (PROGCATEGORY)1
        case PROG_WINDOWABLEVIO:        // (PROGCATEGORY)2

        // PM
        case PROG_PM:                   // (PROGCATEGORY)3

        // DOS
        case PROG_VDM:                  // (PROGCATEGORY)4
        // case PROG_REAL:                // (PROGCATEGORY)4
        case PROG_WINDOWEDVDM:          // (PROGCATEGORY)7

        // windoze
        case PROG_WINDOW_REAL:          // (PROGCATEGORY)10
        case PROG_WINDOW_PROT:          // (PROGCATEGORY)11
        // case PROG_30_STD:               // (PROGCATEGORY)11
        case PROG_WINDOW_AUTO:          // (PROGCATEGORY)12
        case PROG_SEAMLESSVDM:          // (PROGCATEGORY)13
        // case PROG_30_STDSEAMLESSVDM:    // (PROGCATEGORY)13
        case PROG_SEAMLESSCOMMON:       // (PROGCATEGORY)14
        // case PROG_30_STDSEAMLESSCOMMON:  // (PROGCATEGORY)14
        case PROG_31_STDSEAMLESSVDM:    // (PROGCATEGORY)15
        case PROG_31_STDSEAMLESSCOMMON:  // (PROGCATEGORY)16
        case PROG_31_ENHSEAMLESSVDM:    // (PROGCATEGORY)17
        case PROG_31_ENHSEAMLESSCOMMON:  // (PROGCATEGORY)18
        case PROG_31_ENH:               // (PROGCATEGORY)19
        case PROG_31_STD:               // (PROGCATEGORY)20

        case PROG_DOS_GAME:             // (PROGCATEGORY)21
        case PROG_WIN_GAME:             // (PROGCATEGORY)22
        case PROG_DOS_MODE:             // (PROGCATEGORY)23
        case PROG_RESERVED:             // (PROGCATEGORY)255
        case PROG_DEFAULT:             // (PROGCATEGORY)0
        case PROG_GROUP:               // (PROGCATEGORY)5
        */

        default:
            *pHelpPanelId = ID_XSH_PROGRAMFILE_MAIN;
        break;

    }

    return TRUE;

    /* return XWPProgramFile_parent_WPProgramFile_wpQueryDefaultHelp(somSelf,
                                                                     pHelpPanelId,
                                                                     HelpLibrary);
    */
// #endif
}

/*
 *@@ ProgramFileIconHandler:
 *      common handler for XWPProgramFile::wpSetProgIcon
 *      and XWPProgramFile::wpQueryIconData. See remarks there.
 *
 *      Returns FALSE only on crashes.
 *
 *@@added V0.9.18 (2002-03-19) [umoeller]
 */

STATIC BOOL ProgramFileIconHandler(XWPProgramFile *somSelf,
                                   HPOINTER *phptr,      // out: if != NULL, newly build icon handle
                                   PULONG pcbIconInfo,   // out: if != NULL, size of ICONINFO buffer required
                                   PICONINFO pIconInfo,  // out: if != NULL, icon info
                                   BOOL *pfNotDefaultIcon)
{
    BOOL        brc = FALSE;
    BOOL        fLocked = FALSE;

    TRY_LOUD(excpt1)
    {
        APIRET      arc;
        CHAR        szProgramFile[CCHMAXPATH];
        BOOL        fFound = FALSE;

        #ifdef __DEBUG__
            ULONG ulStyle = _wpQueryStyle(somSelf);
            PMPF_ICONREPLACEMENTS(("%s, old style: 0x%lX %s %s",
                        _wpQueryTitle(somSelf),
                         ulStyle,
                         (ulStyle & OBJSTYLE_NOTDEFAULTICON) ? "OBJSTYLE_NOTDEFAULTICON" : "",
                         (ulStyle & OBJSTYLE_CUSTOMICON) ? "OBJSTYLE_CUSTOMICON" : ""));
        #endif

        if (    (fLocked = !_wpRequestObjectMutexSem(somSelf, SEM_INDEFINITE_WAIT))
             && (_wpQueryFilename(somSelf, szProgramFile, TRUE))
           )
        {
            XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);

            // first: check if an .ICO file of the same filestem
            // exists in the folder. If so, _always_ use that icon.
            PCSZ pExt;
            if (pExt = doshGetExtension(szProgramFile))
            {
                ULONG ulStemLen = pExt - szProgramFile;
                CHAR szIconFile[CCHMAXPATH];
                memcpy(szIconFile, szProgramFile, ulStemLen);
                memcpy(szIconFile + ulStemLen, "ico", 4);  // include 0
                // use the new icoLoadICOFile, this is way faster
                // V0.9.16 (2001-12-08) [umoeller]
                        // NOTE: This only gets called for "create icon"
                        // mode, never with the "fill icon info" mode,
                        // because in that case wpQueryIconData checks
                        // _pWszUsingIconFile
                        // V0.9.18 (2002-03-19) [umoeller]
                if (!(arc = icoLoadICOFile(szIconFile,
                                           phptr,
                                           NULL,
                                           NULL)))
                {
                    // store this in the instance data so
                    // that wpQueryIconData can properly
                    // return this... we can't do this
                    // otherwise because we can't check
                    // if the icon file data is valid
                    // without building a pointer handle
                    // V0.9.18 (2002-03-19) [umoeller]
                    wpshStore(somSelf,
                              &_pWszUsingIconFile,
                              szIconFile,
                              NULL);

                    if (pfNotDefaultIcon)
                        *pfNotDefaultIcon = TRUE;
                    fFound = TRUE;
                }
                // else: .ICO file doesn't exist, or bad format, so go on
            }

            if (!fFound)
            {
                PEXECUTABLE pExec = NULL;

                wpshStore(somSelf,
                          &_pWszUsingIconFile,
                          NULL,
                          NULL);

                PMPF_ICONREPLACEMENTS(("%s, calling exehOpen",
                            szProgramFile));

                if (!(arc = exehOpen(szProgramFile, &pExec)))
                {
                    _xwpQueryProgType(somSelf,
                                      pExec,                // can be NULL
                                      szProgramFile);

                    PMPF_ICONREPLACEMENTS(("  _xwpQueryProgType returned %d",
                                exehDescribeProgType(_ulAppType)));

                    if (!progFindIcon(pExec,
                                      _ulAppType,
                                      phptr,
                                      pcbIconInfo,
                                      pIconInfo,
                                      pfNotDefaultIcon))
                        fFound = TRUE;

                    exehClose(&pExec);

                } // end if (!(arc = exehOpen(szProgramFile, &pExec)))
            }

            if (!fFound)
            {
                cmnGetStandardIcon(STDICON_PROG_UNKNOWN,
                                   phptr,
                                   pcbIconInfo,
                                   pIconInfo);
            }
        }

        brc = TRUE;
    }
    CATCH(excpt1)
    {
    } END_CATCH();

    if (fLocked)
        _wpReleaseObjectMutexSem(somSelf);

    return brc;
}

/*
 *@@ wpQueryIconData:
 *      this WPObject instance method can be called to find out the
 *      object's icon data.
 *
 *      The method name is really misleading since this method does
 *      not always return the actual icon data, but rather information
 *      about where to find the data to build an icon for the object.
 *      In addition, it is badly designed because there's no way
 *      of telling whether the buffer passed in is large enough
 *      to hold the output data because there is no input parameter
 *      for the size of the buffer.
 *
 *      Anyway, this returns the size of the buffer that is
 *      required to hold this information. Normally the caller
 *      is supposed to call this twice: once with pIconInfo == NULL
 *      to learn about the required size, then again with a
 *      sufficient buffer.
 *
 *      Note that the caller cannot request the icon format
 *      that the data should be returned in. Instead, this
 *      function sets ICONINFO.fFormat to one of the following:
 *
 *      --  ICON_FILE: ICONINFO.pszFileName contains an icon
 *          file where the icon can be loaded from. This is
 *          used with XWorkplace if this is an themed icon
 *          returned by cmnGetStandardIcon; this can also
 *          happen if the program file's icon results from
 *          an .ICO file in the same directory. In that case
 *          the returned size is sizeof(ICONINFO) plus the
 *          length of the file name buffer, where
 *          ICONINFO.pszFileName points to the first byte
 *          after the ICONINFO structure on output.
 *
 *      --  ICON_RESOURCE: ICONINFO.hmod und resid contain
 *          information where the icon resource can be found.
 *          The returned size is sizeof(ICONINFO) only.
 *
 *      --  ICON_DATA: only in this case the actual icon data
 *          is returned, with ICONINFO.cbIconData containing
 *          the size and ICONINFO.pIconData containing the
 *          actual data. This is a standard OS/2 bitmap array
 *          and can be passed to the undocumented WinBuildPtrHandle
 *          API (see icoBuildPtrHandle). In this case, the size
 *          returned is sizeof(ICONINFO) plus the icon data size,
 *          where ICONINFO.pIconData points to the first byte
 *          after the ICONINFO structure on output.
 *
 *      Again, it is not possible for this method to check if
 *      the input buffer is large enough to hold the data.
 *      Always call the method twice to be able to allocate
 *      sufficient memory. Of course, if the icon changes
 *      in between the two calls, we'll crash, but then sue
 *      IBM for the method design.
 *
 *      From what I can see, this method gets called
 *
 *      --  from the "Icon" page in each object's settings
 *          notebook (our replacement does that too);
 *
 *      --  for drag'n'drop, to build the drag icon;
 *
 *      --  possibly a bunch of other places.
 *
 *      We need to override this too to fully support our replacement
 *      program file icons in the WPS. Up to V0.9.18, the "Icon"
 *      notebook page was severly broken for program files.
 *
 *@@added V0.9.18 (2002-03-19) [umoeller]
 */

SOM_Scope ULONG  SOMLINK xpgf_wpQueryIconData(XWPProgramFile *somSelf,
                                              PICONINFO pIconInfo)
{
    XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_wpQueryIconData");

    // turbo folders enabled?
    if (icomRunReplacement())
    {
        APIRET          arc = ERROR_NO_DATA;
        ULONG           cbRequired = sizeof(ICONINFO);
        CHAR            szFilename[CCHMAXPATH];

        // FIRST of all, check if we have a non-default icon
        // from an .ICON EA... if so, this overrides anything else
        if (_wpQueryFilename(somSelf, szFilename, TRUE))
            arc = icoBuildPtrFromEAs(szFilename,
                                     NULL,              // no HPOINTER
                                     &cbRequired,
                                     pIconInfo);        // can be NULL
                    // returns NO_ERROR only if we have an .ICON EA

        if (arc)
        {
            // .ICON EA not found, or bad data:
            PMINIRECORDCORE pmrc = _wpQueryCoreRecord(somSelf);
            if (!pmrc->hptrIcon)
                // we haven't set the icon yet (improbable but possible):
                _wpSetProgIcon(somSelf, NULL);

            // now we can use the cached instance data fields
            if (_pWszUsingIconFile)
            {
                // wpSetProgIcon has found an .ICO file:
                ULONG ulNameLen = strlen(_pWszUsingIconFile);
                cbRequired += ulNameLen;
                if (pIconInfo)
                {
                    PSZ psz = (PSZ)(pIconInfo + 1);
                    ZERO(pIconInfo);
                    pIconInfo->cb = cbRequired;
                    pIconInfo->fFormat = ICON_FILE;
                    memcpy(psz, _pWszUsingIconFile, ulNameLen + 1);
                    pIconInfo->pszFileName = psz;
                }
            }
            else
            {
                // not icon file: run the icon handler again
                PMPF_ICONREPLACEMENTS(("calling ProgramFileIconHandler, cbRequired %d, pIconInfo 0x%lX",
                              cbRequired, pIconInfo));

                if (!(ProgramFileIconHandler(somSelf,
                                             NULL,          // HPOINTER *phptr,
                                             &cbRequired,   // PULONG pcbIconInfo,
                                             pIconInfo,     // can be NULL
                                             NULL)))
                    // crash:
                    cbRequired = 0;
            }
        }

        return cbRequired;
    }

    return XWPProgramFile_parent_WPProgramFile_wpQueryIconData(somSelf,
                                                               pIconInfo);
}

/*
 *@@ wpSetIconData:
 *      this WPObject method sets a new persistent icon for
 *      the object and stores the new icon permanently.
 *
 *      We need to override this for our icon replacements
 *      because the WPS will do evil things to our standard
 *      icons again.
 *
 *      Note that we only handle the ICON_CLEAR case here
 *      to reload the exe default icon. The other cases
 *      are handled by our XWPFileSystem::wpSetIconData
 *      override.
 *
 *@@added V0.9.18 (2002-03-19) [umoeller]
 */

SOM_Scope BOOL  SOMLINK xpgf_wpSetIconData(XWPProgramFile *somSelf,
                                           PICONINFO pIconInfo)
{
    CHAR        szFilename[CCHMAXPATH];

    XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_wpSetIconData");

    if (icomRunReplacement())
    {
        if (    (pIconInfo)
             && (pIconInfo->fFormat == ICON_CLEAR)
             && (_wpQueryFilename(somSelf, szFilename, TRUE))
           )
        {
            // this case is now overridden by XFldDataFile
            // and XWPProgramFile
            if (WinSetFileIcon(szFilename, pIconInfo))
            {
                // use default executable icon
                _wpSetProgIcon(somSelf, NULL);
                return TRUE;
            }
        }
    }

    // all other cases, or icon replacements disabled:
    // call parent, which will end up in XWPFileSystem
    // (WPProgramFile doesn't override this)
    return XWPProgramFile_parent_WPProgramFile_wpSetIconData(somSelf,
                                                             pIconInfo);
}

/*
 *@@ wpSetProgIcon:
 *      this instance method exists for both WPProgram and
 *      WPProgramFile and is supposed to set the visual icon
 *      for this executable file to the appropriate custom or
 *      default icon.
 *
 *      This isn't entirely correct if the executable has its
 *      own non-default icon data (from OS2.INI or its .ICON
 *      EA) because in that case, wpRestoreState sets the icon
 *      directly, and this never gets called.
 *
 *      For WPProgramFile, this gets called from the
 *      wpSetAssociatedFileIcon override (which in turn gets
 *      called from WPDataFile::wpQueryIcon if a data file doesn't
 *      have a custom icon in its .ICON EA...).
 *      See icons.c for an introduction to all this mess.
 *
 *      In that situation, if turbo folders are enabled, we replace
 *      the icon loading entirely to avoid the problems with PE
 *      executables. In that case, we invoke cmnGetStandardIcon
 *      to return either an icon from ICONS.DLL (if enabled)
 *      or from PMWP.DLL.
 *
 *      Note that I have never seen the PFEA2LIST pointer to be
 *      set to anything but NULL, so we do not handle loading
 *      an icon from EAs here.
 *
 *      Note that this also gets called for instances of the
 *      WPCommandFile subclass (BAT and CMD extension), so we
 *      better not open the executable for those here.
 *
 *      One important difference: The WPS always returns a new
 *      icon for each executable, even if it's one of the standard
 *      icon resources from PMWP.DLL. We handle this differently
 *      and will return a global icon if it's from ICONS.DLL or
 *      PMWP.DLL to speed things up and reduce memory usage.
 *      However, this implies that we must reset the OBJSTYLE_NOTDEFAULTICON
 *      style flag in those cases or the icon will be nuked when
 *      the program file goes dormant.
 *
 *@@changed V0.9.16 (2001-12-08) [umoeller]: mostly rewritten for speed and global icons support
 *@@changed V0.9.18 (2002-03-19) [umoeller]: extracted ProgramFileIconHandler, reworked logic to no longer call the parent
 */

SOM_Scope BOOL  SOMLINK xpgf_wpSetProgIcon(XWPProgramFile *somSelf,
                                           PFEA2LIST pfeal)
{
    // XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_wpSetProgIcon");

    // turbo folders enabled?
    if (icomRunReplacement())
    {
        BOOL        brc = FALSE;
        HPOINTER    hptr = NULLHANDLE;
        BOOL        fNotDefaultIcon = FALSE;

        if (brc = ProgramFileIconHandler(somSelf,
                                         &hptr,
                                         NULL,
                                         NULL,
                                         &fNotDefaultIcon))
        {
            // some icon was found: set it...
            _wpSetIcon(somSelf, hptr);
            _wpModifyStyle(somSelf,
                           OBJSTYLE_NOTDEFAULTICON,
                           (fNotDefaultIcon) ? OBJSTYLE_NOTDEFAULTICON : 0);

            #ifdef __DEBUG__
            {
                ULONG ulStyle;
                PMPF_ICONREPLACEMENTS(("leaving, new style: 0x%lX %s %s",
                         ulStyle = _wpQueryStyle(somSelf),
                         (ulStyle & OBJSTYLE_NOTDEFAULTICON) ? "OBJSTYLE_NOTDEFAULTICON" : "",
                         (ulStyle & OBJSTYLE_CUSTOMICON) ? "OBJSTYLE_CUSTOMICON" : ""));
            }
            #endif
        }

        return brc;
    }

    // only if features are disabled:
    // call default parent method
    return XWPProgramFile_parent_WPProgramFile_wpSetProgIcon(somSelf,
                                                             pfeal);
}

/*
 *@@ wpQueryProgDetails:
 *      this instance method exists for both WPProgram
 *      and WPProgramFile and returns information about
 *      the executable program file in the given buffer.
 *      If pProgDetails is NULL, *pulSize receives the
 *      required size of the buffer; otherwise *pulSize
 *      is expected to specify the size of the buffer
 *      on input, which better be large enough.
 *
 *      This is a complete rewrite. We no longer call
 *      the parent because it's so damn slow and messes
 *      with too many things. The shared implementation
 *      for WPProgram and WPProgramFile is in
 *      progFillProgDetails; see remarks there.
 *
 *@@added V0.9.16 (2001-12-08) [umoeller]
 *@@changed V0.9.19 (2002-05-01) [umoeller]: this always used the replacement, even if disabled; fixed
 */

SOM_Scope BOOL  SOMLINK xpgf_wpQueryProgDetails(XWPProgramFile *somSelf,
                                                PPROGDETAILS pProgDetails,
                                                PULONG pulSize)
{
    BOOL    brc = FALSE;
    ULONG   ulSize = 0;
    PSZ     pszTitle;
    CHAR    szExecutable[CCHMAXPATH];

    XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_wpQueryProgDetails");

    if (icomRunReplacement()) // V0.9.19 (2002-05-01) [umoeller]
    {
        if (    (_wpQueryFilename(somSelf, szExecutable, TRUE))
             && (_pProgType)
             && (pszTitle = _wpQueryTitle(somSelf))
             && (pulSize)
           )
        {
            brc = progFillProgDetails(pProgDetails,     // can be NULL
                                      _xwpQueryProgType(somSelf, NULL, NULL),
                                      _pProgType->fbVisible,
                                      _pswpInitial,
                                      pszTitle,
                                      szExecutable,
                                      *_pulStartupDirHandle,
                                      NULL,         // parameters
                                      NULL,         // environment
                                      pulSize);
        }
    }
    else brc = XWPProgramFile_parent_WPProgramFile_wpQueryProgDetails(somSelf,
                                                                      pProgDetails,
                                                                      pulSize);

    return brc;
}

/*
 *@@ wpSetProgDetails:
 *
 */

SOM_Scope BOOL  SOMLINK xpgf_wpSetProgDetails(XWPProgramFile *somSelf,
                                              PPROGDETAILS pProgDetails)
{
    XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_wpSetProgDetails");

    return XWPProgramFile_parent_WPProgramFile_wpSetProgDetails(somSelf,
                                                                pProgDetails);
}

/*
 *@@ 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 "Program" context menu entry for
 *      DLL's and drivers.
 */

SOM_Scope ULONG  SOMLINK xpgf_wpFilterPopupMenu(XWPProgramFile *somSelf,
                                                ULONG ulFlags,
                                                HWND hwndCnr,
                                                BOOL fMultiSelect)
{
    ULONG ulFilter;
    ULONG ulProgType = _xwpQueryProgType(somSelf, NULL, NULL);

    /* XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf); */
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_wpFilterPopupMenu");

    ulFilter = XWPProgramFile_parent_WPProgramFile_wpFilterPopupMenu(somSelf,
                                                                      ulFlags,
                                                                      hwndCnr,
                                                                      fMultiSelect);
    if (    (ulProgType == PROG_DLL)
         || (ulProgType == PROG_PDD)
         || (ulProgType == PROG_VDD)
         || (ulProgType == PROG_DEFAULT)
       )
        ulFilter &= ~ CTXT_PROGRAM;

    return ulFilter;
}

/*
 *@@ 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.
 *
 *@@added V0.9.20 (2002-08-08) [umoeller]
 */

SOM_Scope HWND  SOMLINK xpgf_wpOpen(XWPProgramFile *somSelf,
                                    HWND hwndCnr, ULONG ulView,
                                    ULONG param)
{
    // XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_wpOpen");

#ifndef __NOTURBOFOLDERS__
    if (cmnQuerySetting(sfTurboFolders))        // V1.0.1 (2002-12-15) [umoeller]
    {
        if (ulView == OPEN_RUNNING)
        {
            HWND hwnd = NULLHANDLE;
            APIRET arc;
            CHAR szFailing[CCHMAXPATH];

            if (arc = progOpenProgram(somSelf,
                                      NULL,      // no assoc data file
                                      ulView,
                                      &hwnd,
                                      sizeof(szFailing),
                                      szFailing))
            {
                // error opening program: ask user if he wants
                // to change the settings
                if (cmnProgramErrorMsgBox(NULLHANDLE,
                                          somSelf,
                                          szFailing,
                                          arc)
                            == MBID_YES)
                    krnPostThread1ObjectMsg(T1M_OPENOBJECTFROMPTR,
                                            (MPARAM)somSelf,
                                            (MPARAM)OPEN_SETTINGS);
            }

            return hwnd;
        }
    } // end if (cmnQuerySetting(sfTurboFolders))
#endif

    return XWPProgramFile_parent_WPProgramFile_wpOpen(somSelf,
                                                      hwndCnr,
                                                      ulView,
                                                      param);
}

/*
 *@@ wpAddProgramAssociationPage:
 *      this WPProgramFile method adds the "Associations" page
 *      to an executable's settings notebook.
 *
 *      If extended associations are enabled, we replace the
 *      standard "Associations" page with a new page which
 *      lists the extended file types.
 *
 *      We need to remove this page for DLLs and drivers,
 *      since with XWorkplace, these modules are instances
 *      of XWPProgramFile as well.
 *
 *@@added V0.9.9 (2001-03-07) [umoeller]
 *@@changed V0.9.11 (2001-04-25) [umoeller]: removing page for DLLs and drivers now
 */

SOM_Scope ULONG  SOMLINK xpgf_wpAddProgramAssociationPage(XWPProgramFile *somSelf,
                                                          HWND hwndNotebook)
{
    ULONG ulType = _xwpQueryProgType(somSelf, NULL, NULL);

    // XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_wpAddProgramAssociationPage");

    // don't add this page for drivers and DLLs V0.9.11 (2001-04-25) [umoeller]
    switch (ulType)
    {
        case PROG_DLL:
        case PROG_PDD:
        case PROG_VDD:
            return SETTINGS_PAGE_REMOVED;
    }

#ifndef __NOTURBOFOLDERS__
    if (cmnQuerySetting(sfTurboFolders))        // V1.0.1 (2002-12-15) [umoeller]
        return _xwpAddAssociationsPage(somSelf, hwndNotebook);
#endif

    return XWPProgramFile_parent_WPProgramFile_wpAddProgramAssociationPage(somSelf,
                                                                           hwndNotebook);
}

/*
 *@@ wpAddProgramPage:
 *      this WPProgramFile method adds the "Program" page
 *      to an executable's settings notebook.
 *
 *      We need to remove this page for DLLs and drivers,
 *      since with XWorkplace, these modules are instances
 *      of XWPProgramFile as well.
 *
 *@@added V0.9.11 (2001-04-25) [umoeller]
 */

SOM_Scope ULONG  SOMLINK xpgf_wpAddProgramPage(XWPProgramFile *somSelf,
                                               HWND hwndNotebook)
{
    // XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    ULONG ulType = _xwpQueryProgType(somSelf, NULL, NULL);

    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_wpAddProgramPage");

    // don't add this page for drivers and DLLs V0.9.11 (2001-04-25) [umoeller]
    switch (ulType)
    {
        case PROG_DLL:
        case PROG_PDD:
        case PROG_VDD:
            return SETTINGS_PAGE_REMOVED;
    }

    return XWPProgramFile_parent_WPProgramFile_wpAddProgramPage(somSelf,
                                                                hwndNotebook);
}

/*
 *@@ wpAddProgramSessionPage:
 *      this instance method adds the "Session" page to
 *      an executable's settings notebook.
 *
 *      We override this method to add our additional
 *      "Module" page after that page, displaying
 *      additional information from the executable module.
 *
 *      We need to remove this page for DLLs and drivers,
 *      since with XWorkplace, these modules are instances
 *      of XWPProgramFile as well.
 *
 *@@added V0.9.0 [umoeller]
 *@@changed V0.9.5 (2000-08-27) [umoeller]: now skipping for WPCommandFiles
 *@@changed V0.9.11 (2001-04-25) [umoeller]: removing page for DLLs and drivers now
 */

SOM_Scope ULONG  SOMLINK xpgf_wpAddProgramSessionPage(XWPProgramFile *somSelf,
                                                      HWND hwndNotebook)
{
    ULONG ulType = _xwpQueryProgType(somSelf, NULL, NULL);

    // XWPProgramFileData *somThis = XWPProgramFileGetData(somSelf);
    XWPProgramFileMethodDebug("XWPProgramFile","xpgf_wpAddProgramSessionPage");

    // insert "Module" settings page, but not for command files
#ifndef __NOMODULEPAGES__
    if (!ctsIsCommandFile(somSelf))
    {
        if (cmnQuerySetting(sfReplaceFilePage))
        {
            _xwpAddResourcesPage(somSelf, hwndNotebook);

            _xwpAddModulePage(somSelf, hwndNotebook);
        }
    }
#endif

    // don't add this page for drivers and DLLs V0.9.11 (2001-04-25) [umoeller]
    switch (ulType)
    {
        case PROG_DLL:
        case PROG_PDD:
        case PROG_VDD:
            return SETTINGS_PAGE_REMOVED;
    }

    return XWPProgramFile_parent_WPProgramFile_wpAddProgramSessionPage(somSelf,
                                                                       hwndNotebook);
}

/* ******************************************************************
 *
 *   XWPProgramFile class methods
 *
 ********************************************************************/

/*
 *@@ wpclsInitData:
 *      this M_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.
 *
 *@@changed V0.9.0 [umoeller]: added class object to KERNELGLOBALS
 */

SOM_Scope void  SOMLINK xpgfM_wpclsInitData(M_XWPProgramFile *somSelf)
{
    // M_XWPProgramFileData *somThis = M_XWPProgramFileGetData(somSelf);
    M_XWPProgramFileMethodDebug("M_XWPProgramFile","xpgfM_wpclsInitData");

    M_XWPProgramFile_parent_M_WPProgramFile_wpclsInitData(somSelf);

    krnClassInitialized(G_pcszXWPProgramFile);
}

/*
 *@@ wpclsQueryInstanceFilter:
 *      this M_WPFileSystem class method determines which file-system
 *      objects will be instances of a certain class according
 *      to a file filter.
 *
 *      To avoid the annoying behavior of OS/2 Warp 4 that some
 *      DLL's are instances of WPProgramFile and some are not,
 *      we make all DLL's instances of WPProgramFile by specifying
 *      "*.DLL" too.
 *
 *      This does not work using wpclsQueryInstanceType
 *      because the WPS seems to be using some default file
 *      type of "Executable", which is determined in some hidden
 *      place.
 *
 *@@changed V0.9.16 (2001-11-25) [umoeller]: now returning *.com, *.exe always for turbo folders
 */

SOM_Scope PSZ  SOMLINK xpgfM_wpclsQueryInstanceFilter(M_XWPProgramFile *somSelf)
{
    /* M_XWPProgramFileData *somThis = M_XWPProgramFileGetData(somSelf); */
    M_XWPProgramFileMethodDebug("M_XWPProgramFile","xpgfM_wpclsQueryInstanceFilter");

    if (somSelf == _XWPProgramFile)
    {
#ifndef __NOICONREPLACEMENTS__
        if (cmnQuerySetting(sfIconReplacements))
            return (PSZ)G_pcszPgmFileFilter;
#endif

        return "*.COM,*.EXE";
        // the below code doesn't work: there is no wpclsQueryInstanceFilter
        // method in WPProgramFile. Apparently the WPS uses some internal hack
        // to explicitly make COM and EXE files program files, but this won't
        // work if turbo folders are enabled, so set this explicitly.
        // V0.9.16 (2001-11-25) [umoeller]
    }

    return M_XWPProgramFile_parent_M_WPProgramFile_wpclsQueryInstanceFilter(somSelf);
}

