Index: /trunk/include/helpers/animate.h
===================================================================
--- /trunk/include/helpers/animate.h	(revision 16)
+++ /trunk/include/helpers/animate.h	(revision 17)
@@ -37,5 +37,9 @@
                          ULONG ulAnimationTime);
 
-    VOID anmPowerOff(HPS hps, ULONG ulSteps);
+    VOID anmPowerOff(HPS hps,
+                     ULONG ulMaxTime1,
+                     ULONG ulMaxTime2,
+                     ULONG ulMaxTime3,
+                     ULONG ulWaitEnd);
 
 #endif
Index: /trunk/include/helpers/cnrh.h
===================================================================
--- /trunk/include/helpers/cnrh.h	(revision 16)
+++ /trunk/include/helpers/cnrh.h	(revision 17)
@@ -482,4 +482,8 @@
                               PRECORDCORE precc);
 
+    BOOL cnrhIsChildOf(HWND hwndCnr,
+                       PRECORDCORE precTest,
+                       PRECORDCORE precParent);
+
     typedef ULONG EXPENTRY FNCBRECC(HWND, PRECORDCORE, ULONG, ULONG);
     typedef FNCBRECC *PFNCBRECC;
Index: /trunk/include/helpers/dosh.h
===================================================================
--- /trunk/include/helpers/dosh.h	(revision 16)
+++ /trunk/include/helpers/dosh.h	(revision 17)
@@ -178,63 +178,26 @@
     /* ******************************************************************
      *
-     *   File helpers
-     *
-     ********************************************************************/
-
-    PSZ doshGetExtension(const char *pcszFilename);
-
-    BOOL doshIsFileOnFAT(const char* pcszFileName);
-
-    APIRET doshIsValidFileName(const char* pcszFile,
-                               BOOL fFullyQualified);
-
-    BOOL doshMakeRealName(PSZ pszTarget, PSZ pszSource, CHAR cReplace, BOOL fIsFAT);
-
-    ULONG doshQueryFileSize(HFILE hFile);
-
-    ULONG doshQueryPathSize(PSZ pszFile);
-
-    APIRET doshQueryPathAttr(const char* pcszFile,
-                             PULONG pulAttr);
-
-    APIRET doshSetPathAttr(const char* pcszFile,
-                           ULONG ulAttr);
-
-    APIRET doshReadTextFile(PSZ pszFile,
-                            PSZ* ppszContent);
-
-    PSZ doshCreateBackupFileName(const char* pszExisting);
-
-    APIRET doshWriteTextFile(const char* pszFile,
-                             const char* pszContent,
-                             PULONG pulWritten,
-                             PSZ pszBackup);
-
-    HFILE doshOpenLogFile(const char* pcszFilename);
-
-    APIRET doshWriteToLogFile(HFILE hfLog, const char* pcsz);
-
-    /* ******************************************************************
-     *
-     *   Directory helpers
-     *
-     ********************************************************************/
-
-    BOOL doshQueryDirExist(PSZ pszDir);
-
-    APIRET doshCreatePath(PSZ pszPath,
-                          BOOL fHidden);
-
-    APIRET doshQueryCurrentDir(PSZ pszBuf);
-
-    APIRET doshSetCurrentDir(const char *pcszDir);
-
-    #define DOSHDELDIR_RECURSE      0x0001
-    #define DOSHDELDIR_DELETEFILES  0x0002
-
-    APIRET doshDeleteDir(const char *pcszDir,
-                         ULONG flFlags,
-                         PULONG pulDirs,
-                         PULONG pulFiles);
+     *   Module handling helpers
+     *
+     ********************************************************************/
+
+    /*
+     *@@ RESOLVEFUNCTION:
+     *      one of these structures each define
+     *      a single function import to doshResolveImports.
+     *
+     *@@added V0.9.3 (2000-04-25) [umoeller]
+     */
+
+    typedef struct _RESOLVEFUNCTION
+    {
+        const char  *pcszFunctionName;
+        PFN         *ppFuncAddress;
+    } RESOLVEFUNCTION, *PRESOLVEFUNCTION;
+
+    APIRET doshResolveImports(PSZ pszModuleName,
+                              HMODULE *phmod,
+                              PRESOLVEFUNCTION paResolves,
+                              ULONG cResolves);
 
     /* ******************************************************************
@@ -304,4 +267,66 @@
     /* ******************************************************************
      *
+     *   File helpers
+     *
+     ********************************************************************/
+
+    PSZ doshGetExtension(const char *pcszFilename);
+
+    BOOL doshIsFileOnFAT(const char* pcszFileName);
+
+    APIRET doshIsValidFileName(const char* pcszFile,
+                               BOOL fFullyQualified);
+
+    BOOL doshMakeRealName(PSZ pszTarget, PSZ pszSource, CHAR cReplace, BOOL fIsFAT);
+
+    ULONG doshQueryFileSize(HFILE hFile);
+
+    ULONG doshQueryPathSize(PSZ pszFile);
+
+    APIRET doshQueryPathAttr(const char* pcszFile,
+                             PULONG pulAttr);
+
+    APIRET doshSetPathAttr(const char* pcszFile,
+                           ULONG ulAttr);
+
+    APIRET doshReadTextFile(PSZ pszFile,
+                            PSZ* ppszContent);
+
+    PSZ doshCreateBackupFileName(const char* pszExisting);
+
+    APIRET doshWriteTextFile(const char* pszFile,
+                             const char* pszContent,
+                             PULONG pulWritten,
+                             PSZ pszBackup);
+
+    HFILE doshOpenLogFile(const char* pcszFilename);
+
+    APIRET doshWriteToLogFile(HFILE hfLog, const char* pcsz);
+
+    /* ******************************************************************
+     *
+     *   Directory helpers
+     *
+     ********************************************************************/
+
+    BOOL doshQueryDirExist(PSZ pszDir);
+
+    APIRET doshCreatePath(PSZ pszPath,
+                          BOOL fHidden);
+
+    APIRET doshQueryCurrentDir(PSZ pszBuf);
+
+    APIRET doshSetCurrentDir(const char *pcszDir);
+
+    #define DOSHDELDIR_RECURSE      0x0001
+    #define DOSHDELDIR_DELETEFILES  0x0002
+
+    APIRET doshDeleteDir(const char *pcszDir,
+                         ULONG flFlags,
+                         PULONG pulDirs,
+                         PULONG pulFiles);
+
+    /* ******************************************************************
+     *
      *   Process helpers
      *
@@ -356,29 +381,4 @@
 
     APIRET doshFreeEnvironment(PDOSENVIRONMENT pEnv);
-
-    /* ******************************************************************
-     *
-     *   Module handling helpers
-     *
-     ********************************************************************/
-
-    /*
-     *@@ RESOLVEFUNCTION:
-     *      one of these structures each define
-     *      a single function import to doshResolveImports.
-     *
-     *@@added V0.9.3 (2000-04-25) [umoeller]
-     */
-
-    typedef struct _RESOLVEFUNCTION
-    {
-        const char  *pcszFunctionName;
-        PFN         *ppFuncAddress;
-    } RESOLVEFUNCTION, *PRESOLVEFUNCTION;
-
-    APIRET doshResolveImports(PSZ pszModuleName,
-                              HMODULE *phmod,
-                              PRESOLVEFUNCTION paResolves,
-                              ULONG cResolves);
 
     /********************************************************************
Index: /trunk/include/helpers/linklist.h
===================================================================
--- /trunk/include/helpers/linklist.h	(revision 16)
+++ /trunk/include/helpers/linklist.h	(revision 17)
@@ -159,4 +159,8 @@
     typedef LSTITEMFROMINDEX *PLSTITEMFROMINDEX;
 
+    unsigned long lstIndexFromItem(PLINKLIST pList, void *pItemData);
+    typedef unsigned long LSTINDEXFROMITEM(PLINKLIST pList, void *pItemData);
+    typedef LSTINDEXFROMITEM *PLSTINDEXFROMITEM;
+
     #ifdef __XWPMEMDEBUG__ // setup.h, helpers\memdebug.c
         PLISTNODE XWPENTRY lstAppendItemDebug(PLINKLIST pList,
Index: /trunk/src/helpers/animate.c
===================================================================
--- /trunk/src/helpers/animate.c	(revision 16)
+++ /trunk/src/helpers/animate.c	(revision 17)
@@ -44,4 +44,5 @@
 #define INCL_DOSERRORS
 
+#define INCL_WINWINDOWMGR
 #define INCL_WINPOINTERS
 #define INCL_WINSYS
@@ -55,10 +56,10 @@
 #include <string.h>
 
-#include "setup.h"                      // code generation and debugging options
-
-#include "helpers\animate.h"
-
-#include "helpers\winh.h"
-#include "helpers\gpih.h"
+// #include "setup.h"                      // code generation and debugging options
+
+// #include "helpers\animate.h"
+
+// #include "helpers\winh.h"
+// #include "helpers\gpih.h"
 
 /*
@@ -165,7 +166,5 @@
 }
 
-#define LAST_WIDTH 2
-#define LAST_STEPS 50
-#define WAIT_TIME  10
+#define LAST_LINE_WIDTH 2
 
 /* ******************************************************************
@@ -179,17 +178,27 @@
  *      displays an animation that looks like a
  *      monitor being turned off; hps must have
- *      been acquired using WinGetScreenPS,
- *      ulSteps should be around 40-50.
+ *      been acquired using WinGetScreenPS.
  *
  *@@changed V0.9.7 (2000-12-08) [umoeller]: got rid of dtGetULongTime
  */
 
-VOID anmPowerOff(HPS hps, ULONG ulSteps)
+VOID anmPowerOff(HPS hps,
+                 ULONG ulMaxTime1, //  = 500,
+                 ULONG ulMaxTime2, //  = 800,
+                 ULONG ulMaxTime3, //  = 200,
+                 ULONG ulWaitEnd)  //  = 300
 {
-    RECTL       rclScreen, rclNow, rclLast, rclDraw;
-    ULONG       ul = ulSteps;
-    ULONG       ulPhase = 1;
+    RECTL       rclScreen,
+                rclNow,
+                rclLast,
+                rclDraw;
+    ULONG       ulPhase = 1,
+                ulCXLastLine;
+
+    ULONG       ulStartTime = 0,
+                ulTimeNow = 0;
 
     WinQueryWindowRect(HWND_DESKTOP, &rclScreen);
+    ulCXLastLine = rclScreen.xRight / 3;
 
     WinShowPointer(HWND_DESKTOP, FALSE);
@@ -200,13 +209,17 @@
     // "phases", signified by the ulPhase variable. While
     // ulPhase != 99, we stay in a do-while loop.
-    ul = 0;
     ulPhase = 1;
 
     do
     {
-        ULONG ulFromTime, ulTime2;
+        // get current time
         DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT,
-                        &ulFromTime,
-                        sizeof(ulFromTime));
+                        &ulTimeNow,
+                        sizeof(ulTimeNow));
+
+        // get start time
+        if (ulStartTime == 0)
+            // this is reset when we enter a new phase
+            ulStartTime = ulTimeNow;
 
         if (ulPhase == 1)
@@ -218,28 +231,47 @@
             // the center is black too. Sort of like this:
 
-            //          ***************************
-            //          *       black             *
-            //          *                         *
-            //          *      .............      *
-            //          *      . rclNow:   .      *
-            //          *  ->  . untouched .  <-  *
-            //          *      .............      *
-            //          *            ^            *
-            //          *            !            *
-            //          ***************************
+            //          ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
+            //          º       black             º
+            //          º                         º
+            //          º      ÚÄÄÄÄÄÄÄÄÄÄÄ¿      º
+            //          º      ³ rclNow:   ³      º
+            //          º  ->  ³ untouched ³  <-  º
+            //          º      ÀÄÄÄÄÄÄÄÄÄÄÄÙ      º
+            //          º            ^            º
+            //          º            |            º
+            //          ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ
+
+            // This part lasts exactly (ulMaxTime1) milliseconds.
 
             // rclNow contains the rectangle _around_ which
             // the black rectangles are to be drawn. With
             // every iteration, rclNow is reduced in size.
-            rclNow.xLeft = ((rclScreen.yTop / 2) * ul / ulSteps );
+            ULONG ulMaxX = (rclScreen.xRight - ulCXLastLine) / 2,
+                  ulMaxY = rclScreen.yTop / 2 - LAST_LINE_WIDTH;
+            ULONG ulTimePassed = (ulTimeNow - ulStartTime);
+            if (ulTimePassed >= ulMaxTime1)
+            {
+                // time has elapsed:
+                ulTimePassed = ulMaxTime1;
+                // enter next phase on next loop
+                ulPhase++;
+                // reget start time
+                ulStartTime = 0;
+            }
+            rclNow.xLeft = ulMaxX * ulTimePassed / ulMaxTime1;
+            rclNow.yBottom = ulMaxY * ulTimePassed / ulMaxTime1;
+            rclNow.xRight = (rclScreen.xRight) - rclNow.xLeft;
+            rclNow.yTop = (rclScreen.yTop) - rclNow.yBottom;
+
+            /* rclNow.xLeft = ((rclScreen.yTop / 2) * ul / ulSteps );
             rclNow.xRight = (rclScreen.xRight) - rclNow.xLeft;
             rclNow.yBottom = ((rclScreen.yTop / 2) * ul / ulSteps );
-            rclNow.yTop = (rclScreen.yTop) - rclNow.yBottom;
-
-            if (rclNow.yBottom > (rclNow.yTop - LAST_WIDTH) )
+            rclNow.yTop = (rclScreen.yTop) - rclNow.yBottom; */
+
+            /* if (rclNow.yBottom > (rclNow.yTop - LAST_WIDTH) )
             {
                 rclNow.yBottom = (rclScreen.yTop / 2) - LAST_WIDTH;
                 rclNow.yTop = (rclScreen.yTop / 2) + LAST_WIDTH;
-            }
+            } */
 
             // draw black rectangle on top of rclNow
@@ -275,32 +307,90 @@
 
             // done with "shrinking"?
-            if ( rclNow.xRight < ((rclScreen.xRight / 2) + LAST_WIDTH) )
+            /* if ( rclNow.xRight < ((rclScreen.xRight / 2) + LAST_WIDTH) )
+            {
                 ulPhase = 2; // exit
+                // reget start time
+                ulStartTime = 0;
+            } */
+
+            if (ulPhase == 2)
+            {
+                // this was the last step in this phase:
+                memcpy(&rclLast, &rclScreen, sizeof(RECTL));
+            }
         }
         else if (ulPhase == 2)
         {
             // Phase 2: draw a horizontal white line about
-            // where the last rclNow was. This is only
-            // executed once.
-
-            //          ***************************
-            //          *       black             *
-            //          *                         *
-            //          *                         *
-            //          *        -----------      *
-            //          *                         *
-            //          *                         *
-            //          *                         *
-            //          ***************************
-
-            rclDraw.xLeft = (rclScreen.xRight / 2) - LAST_WIDTH;
-            rclDraw.xRight = (rclScreen.xRight / 2) + LAST_WIDTH;
-            rclDraw.yBottom = (rclScreen.yTop * 1 / 4);
-            rclDraw.yTop = (rclScreen.yTop * 3 / 4);
-            WinFillRect(hps, &rclDraw, CLR_WHITE);
-
-            ulPhase = 3;
-            ul = 0;
-
+            // where the last rclNow was. and shrink it
+            // towards the middle. This ends with a white
+            // dot in the middle of the screen.
+
+            //          ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
+            //          º       black             º
+            //          º                         º
+            //          º                         º
+            //          º  -->   ÄwhiteÄÄÄÄ   <-- º
+            //          º                         º
+            //          º                         º
+            //          º                         º
+            //          ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ
+
+            // This part lasts exactly (ulMaxTime2) milliseconds.
+
+            // start is same as max in step 1
+            ULONG ulStartX = (rclScreen.xRight - ulCXLastLine) / 2,
+                  ulY      = rclScreen.yTop / 2 - LAST_LINE_WIDTH;
+            ULONG ulMaxX = (rclScreen.xRight) / 2 - LAST_LINE_WIDTH;      // center
+            ULONG ulTimePassed = (ulTimeNow - ulStartTime);
+            if (ulTimePassed >= ulMaxTime2)
+            {
+                // time has elapsed:
+                ulTimePassed = ulMaxTime2;
+                // enter next phase on next loop
+                ulPhase++;
+                // reget start time
+                ulStartTime = 0;
+            }
+
+            rclNow.xLeft =  ulStartX
+                          + ( (ulMaxX - ulStartX) * ulTimePassed / ulMaxTime2 );
+            rclNow.yBottom = ulY;
+            rclNow.xRight = (rclScreen.xRight) - rclNow.xLeft;
+            rclNow.yTop = (rclScreen.yTop) - rclNow.yBottom;
+
+            // draw black rectangle left of rclNow
+            rclDraw.xLeft = rclLast.xLeft;
+            rclDraw.xRight = rclNow.xLeft;
+            rclDraw.yBottom = rclLast.yBottom;
+            rclDraw.yTop = rclLast.yTop;
+            WinFillRect(hps, &rclDraw, CLR_BLACK);
+
+            // draw black rectangle right of rclNow
+            rclDraw.xLeft = rclNow.xRight;
+            rclDraw.xRight = rclLast.xRight;
+            rclDraw.yBottom = rclLast.yBottom;
+            rclDraw.yTop = rclLast.yTop;
+            WinFillRect(hps, &rclDraw, CLR_BLACK);
+
+            // WinFillRect(hps, &rclNow, CLR_WHITE);
+
+            // remember rclNow for next iteration
+            memcpy(&rclLast, &rclNow, sizeof(RECTL));
+
+            if (ulPhase == 3)
+            {
+                // this was the last step in this phase:
+                // keep the dot visible for a while
+                DosSleep(ulMaxTime3);
+
+                // draw a white line for phase 3
+                rclLast.xLeft = ulMaxX;
+                rclLast.yBottom = rclScreen.yTop / 4;
+                rclLast.xRight = rclScreen.xRight - rclLast.xLeft;
+                rclLast.yTop = rclScreen.yTop - rclLast.yBottom;
+
+                WinFillRect(hps, &rclLast, CLR_WHITE);
+            }
         }
         else if (ulPhase == 3)
@@ -308,56 +398,81 @@
             // Phase 3: make the white line shorter with
             // every iteration by drawing black rectangles
-            // above it. These are drawn closer to the
-            // center with each iteration.
-
-            //          ***************************
-            //          *       black             *
-            //          *                         *
-            //          *                         *
-            //          *       ->  ----  <-      *
-            //          *                         *
-            //          *                         *
-            //          *                         *
-            //          ***************************
-
-            rclDraw.xLeft = (rclScreen.xRight / 2) - LAST_WIDTH;
-            rclDraw.xRight = (rclScreen.xRight / 2) + LAST_WIDTH;
+            // above and below it. These are drawn closer
+            // to the center with each iteration.
+
+            //          ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
+            //          º                         º
+            //          º                         º
+            //          º            |            º
+            //          º            |            º
+            //          º            |            º
+            //          º                         º
+            //          º                         º
+            //          ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ
+
+            // This part lasts exactly ulMaxTime3 milliseconds.
+            ULONG ulX = (rclScreen.xRight) / 2 - LAST_LINE_WIDTH,      // center
+                  ulStartY = rclScreen.yTop / 4;
+            ULONG ulMaxY = (rclScreen.yTop) / 2 - LAST_LINE_WIDTH;      // center
+            ULONG ulTimePassed = (ulTimeNow - ulStartTime);
+            if (ulTimePassed >= ulMaxTime3)
+            {
+                // time has elapsed:
+                ulTimePassed = ulMaxTime3;
+                // stop
+                ulPhase = 99;
+            }
+
+            rclNow.xLeft =  ulX;
+            rclNow.yBottom = ulStartY
+                          + ( (ulMaxY - ulStartY) * ulTimePassed / ulMaxTime3 );
+            rclNow.xRight = (rclScreen.xRight) - rclNow.xLeft;
+            rclNow.yTop = (rclScreen.yTop) - rclNow.yBottom;
+
+            // draw black rectangle on top of rclNow
+            rclDraw.xLeft = rclLast.xLeft;
+            rclDraw.xRight = rclLast.xRight;
+            rclDraw.yBottom = rclNow.yTop;
+            rclDraw.yTop = rclLast.yTop;
+            WinFillRect(hps, &rclDraw, CLR_BLACK);
+
+            // draw black rectangle at the bottom of rclNow
+            rclDraw.xLeft = rclLast.xLeft;
+            rclDraw.xRight = rclLast.xRight;
+            rclDraw.yBottom = rclLast.yBottom;
+            rclDraw.yTop = rclNow.yBottom;
+            WinFillRect(hps, &rclDraw, CLR_BLACK);
+
+            // remember rclNow for next iteration
+            memcpy(&rclLast, &rclNow, sizeof(RECTL));
+
+            /* rclDraw.xLeft = (rclScreen.xRight / 2) - LAST_LINE_WIDTH;
+            rclDraw.xRight = (rclScreen.xRight / 2) + LAST_LINE_WIDTH;
             rclDraw.yTop = (rclScreen.yTop * 3 / 4);
             rclDraw.yBottom = (rclScreen.yTop * 3 / 4) - ((rclScreen.yTop * 1 / 4) * ul / LAST_STEPS);
-            if (rclDraw.yBottom < ((rclScreen.yTop / 2) + LAST_WIDTH))
-                rclDraw.yBottom = ((rclScreen.yTop / 2) + LAST_WIDTH);
-            WinFillRect(hps, &rclDraw, CLR_BLACK);
-
-            rclDraw.xLeft = (rclScreen.xRight / 2) - LAST_WIDTH;
-            rclDraw.xRight = (rclScreen.xRight / 2) + LAST_WIDTH;
+            if (rclDraw.yBottom < ((rclScreen.yTop / 2) + LAST_LINE_WIDTH))
+                rclDraw.yBottom = ((rclScreen.yTop / 2) + LAST_LINE_WIDTH);
+            WinFillRect(hps, &rclDraw, CLR_BLACK);
+
+            rclDraw.xLeft = (rclScreen.xRight / 2) - LAST_LINE_WIDTH;
+            rclDraw.xRight = (rclScreen.xRight / 2) + LAST_LINE_WIDTH;
             rclDraw.yBottom = (rclScreen.yTop * 1 / 4);
             rclDraw.yTop = (rclScreen.yTop * 1 / 4) + ((rclScreen.yTop * 1 / 4) * ul / LAST_STEPS);
-            if (rclDraw.yTop > ((rclScreen.yTop / 2) - LAST_WIDTH))
-                rclDraw.yBottom = ((rclScreen.yTop / 2) - LAST_WIDTH);
+            if (rclDraw.yTop > ((rclScreen.yTop / 2) - LAST_LINE_WIDTH))
+                rclDraw.yBottom = ((rclScreen.yTop / 2) - LAST_LINE_WIDTH);
 
             WinFillRect(hps, &rclDraw, CLR_BLACK);
 
             ul++;
-            if (ul > LAST_STEPS)
-                ulPhase = 99;
+            if (ul > LAST_STEPS) */
+            //     ulPhase = 99;
         }
 
-        ul++;
-
-        DosSleep(WAIT_TIME);
-
-        /* do
-        {
-            DosSleep(0);
-            DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT,
-                            &ulTime2,
-                            sizeof(ulTime2));
-        }  while (ulTime2 < ulFromTime + WAIT_TIME); */
     } while (ulPhase != 99);
 
     // sleep a while
-    DosSleep(500);
+    DosSleep(ulWaitEnd / 2);
     WinFillRect(hps, &rclScreen, CLR_BLACK);
-    DosSleep(500);
+    DosSleep(ulWaitEnd / 2);
 
     WinShowPointer(HWND_DESKTOP, TRUE);
@@ -365,3 +480,27 @@
 
 
-
+// testcase
+
+/* int main(int argc, char* argp)
+{
+    HENUM henum;
+    HWND hwndTop;
+    HAB hab = WinInitialize(0);
+    HMQ hmq = WinCreateMsgQueue(hab, 0);
+    HPS hps = WinGetScreenPS(HWND_DESKTOP);
+
+    anmPowerOff(hps);
+
+    henum = WinBeginEnumWindows(HWND_DESKTOP);
+    while ((hwndTop = WinGetNextWindow(henum)))
+        if (WinIsWindowShowing(hwndTop))
+            WinInvalidateRect(hwndTop, NULL, TRUE);
+    WinEndEnumWindows(henum);
+
+    WinShowPointer(HWND_DESKTOP, TRUE);
+
+    WinDestroyMsgQueue(hmq);
+    WinTerminate(hab);
+
+    return (0);
+} */
Index: /trunk/src/helpers/cnrh.c
===================================================================
--- /trunk/src/helpers/cnrh.c	(revision 16)
+++ /trunk/src/helpers/cnrh.c	(revision 17)
@@ -1376,4 +1376,44 @@
 
 /*
+ *@@ cnrhIsChildOf:
+ *      returns TRUE only if precTest is a child record
+ *      of precParent in a tree view.
+ *
+ *@@added V0.9.7 (2000-12-13) [umoeller]
+ */
+
+BOOL cnrhIsChildOf(HWND hwndCnr,
+                   PRECORDCORE precTest,        // in: recc to test
+                   PRECORDCORE precParent)      // in: parent to test
+{
+    BOOL brc = FALSE;
+    if ((precTest) && (precParent))
+    {
+        PRECORDCORE precParentThis = precTest;
+
+        while (precParentThis)
+        {
+            // first call: get parent of precTest;
+            // subsequent calls: climb up
+            precParentThis = WinSendMsg(hwndCnr,
+                                        CM_QUERYRECORD,
+                                        precParentThis,
+                                        MPFROM2SHORT(CMA_PARENT,
+                                                     CMA_ITEMORDER));
+            if (precParentThis == (PRECORDCORE)-1)
+                break;
+            else
+                if (precParentThis == precParent)
+                {
+                    brc = TRUE;
+                    break;
+                }
+        }
+    }
+
+    return (brc);
+}
+
+/*
  *@@ cnrhForAllRecords:
  *      this monster function calls pfnwpCallback
@@ -1663,5 +1703,8 @@
  *
  *          Note: You must intercept CN_DROPNOTIFY in your window proc
- *          to clean up resources later.
+ *          to clean up resources later. For this, call:
+ *
+ +              DrgDeleteDraginfoStrHandles(pdrgInfo);
+ +              DrgFreeDraginfo(pdrgInfo);
  *
  *      2)  However, if (usNotifyCode == CN_INITDRAG), we will start
@@ -1669,5 +1712,6 @@
  *          will _not_ return until the object has been dropped or d'n'd
  *          has been cancelled. PM establishes another message loop
- *          internally for this.
+ *          internally for this. In this case, this function managed
+ *          cleanup automatically.
  *
  *      This function supports one single record core only. The following
Index: /trunk/src/helpers/dosh.c
===================================================================
--- /trunk/src/helpers/dosh.c	(revision 16)
+++ /trunk/src/helpers/dosh.c	(revision 17)
@@ -1530,4 +1530,61 @@
 
     return (arcReturn);
+}
+
+/*
+ *@@category: Helpers\Control program helpers\Module handling
+ */
+
+/* ******************************************************************
+ *
+ *   Module handling helpers
+ *
+ ********************************************************************/
+
+/*
+ *@@ doshResolveImports:
+ *      this function loads the module called pszModuleName
+ *      and resolves imports dynamically using DosQueryProcAddress.
+ *
+ *      To specify the functions to be imported, a RESOLVEFUNCTION
+ *      array is used. In each of the array items, specify the
+ *      name of the function and a pointer to a function pointer
+ *      where to store the resolved address.
+ *
+ *@@added V0.9.3 (2000-04-29) [umoeller]
+ */
+
+APIRET doshResolveImports(PSZ pszModuleName,    // in: DLL to load
+                          HMODULE *phmod,       // out: module handle
+                          PRESOLVEFUNCTION paResolves, // in/out: function resolves
+                          ULONG cResolves)      // in: array item count (not array size!)
+{
+    CHAR    szName[CCHMAXPATH];
+    APIRET arc = DosLoadModule(szName,
+                               sizeof(szName),
+                               pszModuleName,
+                               phmod);
+    if (arc == NO_ERROR)
+    {
+        ULONG  ul;
+        for (ul = 0;
+             ul < cResolves;
+             ul++)
+        {
+            arc = DosQueryProcAddr(*phmod,
+                                   0,               // ordinal, ignored
+                                   (PSZ)paResolves[ul].pcszFunctionName,
+                                   paResolves[ul].ppFuncAddress);
+
+            /* _Pmpf(("Resolved %s to 0x%lX, rc: %d",
+                    paResolves[ul].pcszFunctionName,
+                    *paResolves[ul].ppFuncAddress,
+                    arc)); */
+            if (arc != NO_ERROR)
+                break;
+        }
+    }
+
+    return (arc);
 }
 
Index: /trunk/src/helpers/dosh2.c
===================================================================
--- /trunk/src/helpers/dosh2.c	(revision 16)
+++ /trunk/src/helpers/dosh2.c	(revision 17)
@@ -714,61 +714,4 @@
             free(pEnv->papszVars);
             pEnv->cVars = 0;
-        }
-    }
-
-    return (arc);
-}
-
-/*
- *@@category: Helpers\Control program helpers\Module handling
- */
-
-/* ******************************************************************
- *
- *   Module handling helpers
- *
- ********************************************************************/
-
-/*
- *@@ doshResolveImports:
- *      this function loads the module called pszModuleName
- *      and resolves imports dynamically using DosQueryProcAddress.
- *
- *      To specify the functions to be imported, a RESOLVEFUNCTION
- *      array is used. In each of the array items, specify the
- *      name of the function and a pointer to a function pointer
- *      where to store the resolved address.
- *
- *@@added V0.9.3 (2000-04-29) [umoeller]
- */
-
-APIRET doshResolveImports(PSZ pszModuleName,    // in: DLL to load
-                          HMODULE *phmod,       // out: module handle
-                          PRESOLVEFUNCTION paResolves, // in/out: function resolves
-                          ULONG cResolves)      // in: array item count (not array size!)
-{
-    CHAR    szName[CCHMAXPATH];
-    APIRET arc = DosLoadModule(szName,
-                               sizeof(szName),
-                               pszModuleName,
-                               phmod);
-    if (arc == NO_ERROR)
-    {
-        ULONG  ul;
-        for (ul = 0;
-             ul < cResolves;
-             ul++)
-        {
-            arc = DosQueryProcAddr(*phmod,
-                                   0,               // ordinal, ignored
-                                   (PSZ)paResolves[ul].pcszFunctionName,
-                                   paResolves[ul].ppFuncAddress);
-
-            /* _Pmpf(("Resolved %s to 0x%lX, rc: %d",
-                    paResolves[ul].pcszFunctionName,
-                    *paResolves[ul].ppFuncAddress,
-                    arc)); */
-            if (arc != NO_ERROR)
-                break;
         }
     }
Index: /trunk/src/helpers/linklist.c
===================================================================
--- /trunk/src/helpers/linklist.c	(revision 16)
+++ /trunk/src/helpers/linklist.c	(revision 17)
@@ -353,4 +353,5 @@
  *      The item data can be queried from the node
  *      as follows:
+ *
  +          PLINKLIST pll = lstCreate();
  +          ...  // add items here
@@ -359,4 +360,5 @@
  *
  *      You can iterate over the whole list like this:
+ *
  +          PLISTNODE pNode = lstQueryFirstNode(pll);
  +          while (pNode)
@@ -425,5 +427,6 @@
  */
 
-PLISTNODE lstNodeFromItem(PLINKLIST pList, void* pItemData)
+PLISTNODE lstNodeFromItem(PLINKLIST pList,
+                          void* pItemData)
 {
     PLISTNODE pNode = 0,
@@ -465,5 +468,6 @@
  */
 
-void* lstItemFromIndex(PLINKLIST pList, unsigned long ulIndex)
+void* lstItemFromIndex(PLINKLIST pList,
+                       unsigned long ulIndex)
 {
     PLISTNODE pNode = lstNodeFromIndex(pList, ulIndex);
@@ -472,4 +476,38 @@
     else
         return (0);
+}
+
+/*
+ *@@ lstIndexFromItem:
+ *      returns the index of the list node with
+ *      the specified item pointer. The first
+ *      node returns 0, the second 1, and so on.
+ *
+ *      Returns -1 if not found.
+ *
+ *      In the worst case, this function traverses
+ *      the whole list.
+ *
+ *@@added V0.9.7 (2000-12-13) [umoeller]
+ */
+
+unsigned long lstIndexFromItem(PLINKLIST pList, void *pItemData)
+{
+    ULONG ulrc = -1,
+          ulIndex = 0;
+    PLISTNODE pNode = lstQueryFirstNode(pList);
+    while (pNode)
+    {
+        if (pNode->pItemData == pItemData)
+        {
+            ulrc = ulIndex;
+            break;
+        }
+
+        pNode = pNode->pNext;
+        ulIndex++;
+    }
+
+    return (ulrc);
 }
 
Index: /trunk/src/helpers/timer.c
===================================================================
--- /trunk/src/helpers/timer.c	(revision 16)
+++ /trunk/src/helpers/timer.c	(revision 17)
@@ -73,4 +73,6 @@
 #define INCL_DOSMISC
 #define INCL_DOSERRORS
+
+#define INCL_WINMESSAGEMGR
 #include <os2.h>
 
@@ -151,5 +153,5 @@
     }
     else
-        brc = (DosRequestMutexSem(G_hmtxTimers, SEM_INDEFINITE_WAIT)
+        brc = (WinRequestMutexSem(G_hmtxTimers, SEM_INDEFINITE_WAIT)
                     == NO_ERROR);
     return (brc);
@@ -164,17 +166,4 @@
 {
     DosReleaseMutexSem(G_hmtxTimers);
-}
-
-/*
- *@@ tmrOnKill:
- *      on-kill proc for exception handlers.
- *
- *@@added V0.9.7 (2000-12-09) [umoeller]
- */
-
-VOID APIENTRY tmrOnKill(PEXCEPTIONREGISTRATIONRECORD2 pRegRec2)
-{
-    DosBeep(500, 500);
-    UnlockTimers();
 }
 
@@ -217,4 +206,6 @@
         ULONG ulNesting = 0;
 
+        ULONG ulTimeNow;
+
         DosSleep(ulInterval);
 
@@ -225,8 +216,8 @@
         ulInterval = 100;
 
+        DosEnterMustComplete(&ulNesting);
+
         TRY_LOUD(excpt1)
         {
-            DosEnterMustComplete(&ulNesting);
-
             fLocked = LockTimers();
             if (fLocked)
@@ -244,10 +235,12 @@
                     // we have timers:
                     BOOL      fFoundInvalid = FALSE;
+
+                    // get current time
+                    DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT,
+                                    &ulTimeNow, sizeof(ulTimeNow));
+
                     while (pTimerNode)
                     {
                         PXTIMER pTimer = (PXTIMER)pTimerNode->pItemData;
-                        ULONG ulTimeNow;
-                        DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT,
-                                        &ulTimeNow, sizeof(ulTimeNow));
 
                         if (pTimer->ulNextFire < ulTimeNow)
Index: /trunk/src/helpers/winh.c
===================================================================
--- /trunk/src/helpers/winh.c	(revision 16)
+++ /trunk/src/helpers/winh.c	(revision 17)
@@ -3251,4 +3251,6 @@
  *      If this is passed as HWND_DESKTOP, the
  *      whole screen is repainted.
+ *
+ *@@changed V0.9.7 (2000-12-13) [umoeller]: hwndParent was never respected, fixed
  */
 
@@ -3256,5 +3258,5 @@
 {
     HWND    hwndTop;
-    HENUM   henum = WinBeginEnumWindows(HWND_DESKTOP);
+    HENUM   henum = WinBeginEnumWindows(hwndParent);
     while ((hwndTop = WinGetNextWindow(henum)))
         if (WinIsWindowShowing(hwndTop))
