Changeset 1891 for trunk/dll/filldir.c


Ignore:
Timestamp:
Jan 31, 2020, 3:47:37 AM (6 years ago)
Author:
Steven Levine
Message:

Rework FreeCnrItem to ensure all CNRITEMs deleted.
Use WinSendMsg CMA_NEXT.
Was using preccNextRecord which is not recommended because control does
not maintain linkage after inserts and deletes.
Note: arccnrs.c still needs to be reworked to use common functions from filldir.c.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/dll/filldir.c

    r1890 r1891  
    66  Fill Directory Tree Containers
    77
    8   Copyright (c) 1993-98 M. Kimes
    9   Copyright (c) 2001, 2015 Steven H. Levine
     8  Copyright (c) 1993-1998 M. Kimes
     9  Copyright (c) 2001-2020 Steven H. Levine
    1010
    1111  10 Jan 04 SHL ProcessDirectory: avoid most large drive failures
     
    121121  24 Aug 15 GKY Remove fDummy code
    122122  20 Sep 15 GKY Add code for Flesh to skip the directory entry added by Stubby (eliminate
    123                 use of NULL/Nullstr pszFileNames by Stubby). Add code to relink pci chain
    124                 following rename, delete, etc. Add "Expanding" window text.
     123                use of NULL/Nullstr pszFileNames by Stubby). Add code to relink pci chain
     124                following rename, delete, etc. Add "Expanding" window text.
    125125  26 Sep 15 GKY Remove fInitialDriveScan code
     126  28 Jan 20 SHL EmptyCnr: report more errors
     127  29 Jan 20 SHL RemoveCnrItems: rework removal from prev/next chain
    126128
    127129***********************************************************************/
     
    168170#include "pathutil.h"                   // AddBackslashToPath
    169171#include "tmrsvcs.h"                    // ITIMER_DESC
    170 
    171 #ifdef PMPRINTF
    172 #define  _PMPRINTF_                     // Enable debug macros
    173 #include "PMPRINTF.H"
    174 #endif
    175172
    176173// Data definitions
     
    370367  ULONG flags = driveflags[toupper(*pci->pszFileName) - 'A'];
    371368  BOOL fLoadSubjectForDrive = fLoadSubject && ~flags & DRIVE_NOLOADSUBJS;
    372   BOOL fLoadLongNameForDrive = fLoadLongnames &&  //~flags & DRIVE_NOLONGNAMES &&
     369  BOOL fLoadLongNameForDrive = fLoadLongnames &&        // ~flags & DRIVE_NOLONGNAMES &&
    373370                               ~flags & DRIVE_NOLOADLONGS;
    374371  if (fLoadSubjectForDrive || fLoadLongNameForDrive) {
     
    626623  pci->rc.hptrIcon = hptr;
    627624
    628 
    629625  // check to see if record should be visible
    630626  DosRequestMutexSem(hmtxFiltering, SEM_INDEFINITE_WAIT);
     
    821817                      const BOOL recurse,
    822818                      const BOOL partial,
    823                       CHAR *stopflag,
     819                      CHAR *stopflag,
    824820                      DIRCNRDATA *dcd,                  // Optional
    825821                      ULONG *pulTotalFiles,             // Optional
    826                       PULONGLONG pullTotalBytes,        // Optional
    827                       CHAR *LoadedFirstChild)           // Optional
     822                      PULONGLONG pullTotalBytes,        // Optional
     823                      CHAR *LoadedFirstChild)           // Optional
    828824{
    829825  /**
     
    899895      do {
    900896        /**
    901         * remove . and .. and directories already added
    902         * by Stubby from list if present
     897        * remove . and .. and directories already added
     898        * by Stubby from list if present
    903899         * also counter file system bugs that sometimes
    904900         * allows normal files to slip through when
     
    911907        pffbFile = paffbFound;
    912908        ulSelCnt = 0;
    913         for (;;) {
     909        for (;;) {
    914910          if (!*pffbFile->achName ||
    915911              (!filestoo && ~pffbFile->attrFile & FILE_DIRECTORY) ||
     
    917913               !pffbFile->achName[0] || pffbFile->achName[0] == '.' &&
    918914               (!pffbFile->achName[1] ||
    919                 (pffbFile->achName[1] == '.' && !pffbFile->achName[2])) ||
    920                (LoadedFirstChild && !stricmp(LoadedFirstChild, pffbFile->achName)))) {
    921                         // Got . or .. or file to be skipped
     915                (pffbFile->achName[1] == '.' && !pffbFile->achName[2])) ||
     916               (LoadedFirstChild && !stricmp(LoadedFirstChild, pffbFile->achName)))) {
     917                        // Got . or .. or file to be skipped
    922918          }
    923919          else
     
    957953                ullBytes = FillInRecordFromFFB(hwndCnr, pci, pszFileSpec,
    958954                                               pffbFile, partial, dcd);
    959                 pciNext = pci;
    960                 pci = (PCNRITEM) pci->rc.preccNextRecord;
    961                 if (pci && (INT) pci != -1)
    962                   pci->pciPrevious = pciNext;
     955                pciNext = pci;
     956                pci = (PCNRITEM) pci->rc.preccNextRecord;
    963957                ullTotalBytes += ullBytes;
    964958              } // for
     
    10581052              break;
    10591053            }
    1060             ulRecsToInsert = cAffbTotal - x <  USHRT_MAX ? cAffbTotal - x : USHRT_MAX;
     1054            ulRecsToInsert = cAffbTotal - x < USHRT_MAX ? cAffbTotal - x : USHRT_MAX;
    10611055            pciFirst = WinSendMsg(hwndCnr, CM_ALLOCRECORD,
    10621056                                  MPFROMLONG(EXTRA_RECORD_BYTES), MPFROMLONG(ulRecsToInsert));
     
    10711065            else {
    10721066              // 04 Jan 08 SHL FIXME like comp.c to handle less than ulSelCnt records
    1073               if (hwndStatus && dcd && dcd->hwndFrame ==
    1074                   WinQueryActiveWindow(dcd->hwndParent)) {
    1075                 WinSetWindowText(hwndStatus, (CHAR *) GetPString(LoadedFirstChild ?
    1076                                                                 IDS_PLEASEWAITEXPANDINGTEXT :
    1077                                                                 IDS_PLEASEWAITCOUNTINGTEXT));
     1067              if (hwndStatus && dcd && dcd->hwndFrame ==
     1068                  WinQueryActiveWindow(dcd->hwndParent)) {
     1069                WinSetWindowText(hwndStatus, (CHAR *) GetPString(LoadedFirstChild ?
     1070                                                                IDS_PLEASEWAITEXPANDINGTEXT :
     1071                                                                IDS_PLEASEWAITCOUNTINGTEXT));
    10781072              }
    10791073              pci = pciFirst;
     
    10811075          }
    10821076          ullBytes = FillInRecordFromFFB(hwndCnr, pci, pszFileSpec,
    1083                                          pffbFile, partial, dcd);
    1084           pciNext = pci;
    1085           pci = (PCNRITEM) pci->rc.preccNextRecord;
    1086           if (pci && (INT) pci != -1)
    1087             pci->pciPrevious = pciNext;
     1077                                         pffbFile, partial, dcd);
     1078          pciNext = pci;
     1079          pci = (PCNRITEM)pci->rc.preccNextRecord;
    10881080          ullTotalBytes += ullBytes;
    10891081          // 15 Sep 09 SHL allow timed updates to see
     
    11961188      }
    11971189      if ((pci->attrFile & FILE_DIRECTORY))
    1198         AddFleshWorkRequest(hwndCnr, pci, eStubby);
     1190        AddFleshWorkRequest(hwndCnr, pci, eStubby);
    11991191      pci = WinSendMsg(hwndCnr, CM_QUERYRECORD, MPFROMP(pci),
    12001192                       MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
     
    12251217                   dcd,
    12261218                   NULL,                // total files
    1227                    pullTotalBytes,
    1228                    0);
     1219                   pullTotalBytes,
     1220                   0);
    12291221  DosPostEventSem(CompactSem);
    12301222
     
    12531245  ULONG ulDriveType;
    12541246  PCNRITEM pci, pciFirst = NULL;
    1255   PCNRITEM  pciNext;
    1256   PCNRITEM  pciParent = NULL;
     1247  PCNRITEM pciNext;
     1248  PCNRITEM pciParent = NULL;
    12571249  UINT iDrvNum;
    12581250  ULONG ulDriveMapMask;
     
    17491741} // FillTreeCnr
    17501742
    1751 
    17521743/**
    17531744 * Empty all records from a container and free associated storage and
     
    17591750  PFIELDINFO pfi;
    17601751
    1761 #if 0 // fixme to be gone or to be configurable
     1752#if 0 // FIXME to be gone or to be configurable
    17621753  {
    17631754    int state = _heapchk();
     
    17681759
    17691760  // Remove all records
    1770   RemoveCnrItems(hwnd, NULL, 0, CMA_FREE);
     1761  if (RemoveCnrItems(hwnd, NULL, 0, CMA_FREE))
     1762    Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"RemoveCnrItems");
    17711763
    17721764  // Remove field info descriptors
     
    17861778VOID FreeCnrItemData(PCNRITEM pci)
    17871779{
    1788 
    17891780  // 2015-08-23 SHL FIXME debug
    17901781  if ((pci->pszSubject && (ULONG)pci->pszSubject < 0x10000) ||
     
    17981789  }
    17991790
     1791# ifdef PMPRINTF
     1792  {
     1793    PSZ psz = pci->pszFileName;
     1794    if (!psz)
     1795      psz = "(NULL)";
     1796    else if (psz == NullStr)
     1797      psz = "NullStr";
     1798    PmPrintf_Report(pszSrcFile, __LINE__, "FreeCnrItemData freeing pci %p data for fileName \"%.260s\"",
     1799                    pci, psz);
     1800  }
     1801# endif
     1802
    18001803  if (pci->pszSubject) {
    18011804    if (pci->pszSubject != NullStr)
     
    18231826  }
    18241827
    1825 #if 1 // 2009-09-26 SHL FIXME debug dup free complaints
     1828#if 0 // 2009-09-26 SHL FIXME debug dup free complaints
    18261829  if (!pci->pszFileName)
    18271830    Runtime_Error(pszSrcFile, __LINE__, "FreeCnrItemData attempting to free %p data twice", pci);
     
    18321835  }
    18331836#else
     1837# if 0                  // FIXME to be gone
    18341838  {
    1835     // 2015-08-23 SHL FIXME to work again now that Flesh/Stubby on thread
    1836     #define HIST_COUNT 50
     1839    static BOOL first;
     1840    if (!first) {
     1841      first=1;
     1842      DebugHereIAm();
     1843    }
     1844  }
     1845# endif
     1846  {
     1847    // Add CNRITEM to history list
     1848    // 2015-08-23 SHL FIXME to verify OK now that Flesh/Stubby on thread
     1849    #define HIST_CNT 5000
     1850    static INT volatile iHistLock;              // Cheap spin lock
    18371851    static struct {
    18381852      PCNRITEM pci;
    18391853      PSZ pszFileName;
    1840     } history[HIST_COUNT];
    1841     static volatile UINT iHistNdx;
    1842     UINT i;
     1854    } histList[HIST_CNT];
     1855    static volatile UINT iHistNdx;              // Last used
     1856    UINT iCurNdx;
    18431857
    18441858    if (!pci->pszFileName) {
    18451859      // Looks like pci was already freed
    1846       // Try to locate original file name in history buffer
    1847       for (i = 0; i < HIST_COUNT && pci != history[i].pci; i++) { }     // Scan
    1848       if (i < HIST_COUNT) {
    1849         Runtime_Error(pszSrcFile, __LINE__, "FreeCnrItemData attempting to free %p data twice, fileName was %.260s",
    1850                       pci, history[i].pszFileName);
     1860      // Try to locate original file name in history list
     1861      for (iCurNdx = 0; iCurNdx < HIST_CNT && pci != histList[iCurNdx].pci; iCurNdx++) { }      // Scan
     1862      if (iCurNdx < HIST_CNT) {
     1863        PSZ psz = histList[iCurNdx].pszFileName;
     1864#       ifdef PMPRINTF
     1865        PmPrintf_Report(pszSrcFile, __LINE__, "FreeCnrItemData attempting to free %p data twice, fileName was \"%.260s\"",
     1866                       pci, psz == NullStr ? "NullStr" : psz);
     1867#       endif
     1868        Runtime_Error(pszSrcFile, __LINE__, "FreeCnrItemData attempting to free %p data twice, fileName was \"%.260s\"",
     1869                      pci, psz == NullStr ? "NullStr" : psz);
    18511870      } else {
     1871
     1872#       ifdef PMPRINTF
     1873        PmPrintf_Report(pszSrcFile, __LINE__, "FreeCnrItemData attempting to free %p data twice", pci);
     1874#       endif
    18521875        Runtime_Error(pszSrcFile, __LINE__, "FreeCnrItemData attempting to free %p data twice", pci);
    18531876      }
    18541877    }
    18551878    else {
     1879      // Add to history list
    18561880      PSZ psz;
    18571881      PSZ *ppsz;
    1858       // Grab a history slot
     1882      static PSZ pszNull = "(NULL)";
    18591883      // This should work well enoungh to prevent MT/SMP conflicts
    1860       for (;;) {
    1861         i = iHistNdx;
    1862         if (++i >= HIST_COUNT)
    1863           i = 0;
    1864         if (++iHistNdx >= HIST_COUNT)
    1865           iHistNdx = 0;
    1866         if (i == iHistNdx) break;
    1867       }
    1868       ppsz = &history[iHistNdx].pszFileName;
     1884      for (; ++iHistLock > 1; iHistLock--)
     1885        DosSleep(0);                    // Spin if list locked
     1886      if (++iHistNdx >= HIST_CNT)
     1887        iHistNdx = 0;
     1888      ppsz = &histList[iHistNdx].pszFileName;
    18691889      psz = *ppsz;
    1870       if (psz)
     1890      if (psz && psz != NullStr && psz != pszNull)
    18711891        free(psz);
    1872       if (pci->pszFileName && pci->pszFileName != NullStr)
    1873         *ppsz = strdup(pci->pszFileName);
     1892      if (pci->pszFileName) {
     1893         if (pci->pszFileName != NullStr)
     1894           *ppsz = strdup(pci->pszFileName);
     1895        else
     1896           *ppsz = NullStr;
     1897      }
    18741898      else
    1875         *ppsz = NULL;
    1876       history[iHistNdx].pci = pci;
     1899        *ppsz = pszNull;
     1900      histList[iHistNdx].pci = pci;
     1901      iHistLock--;
     1902
    18771903      if (pci->pszFileName != NullStr)
    18781904        free(pci->pszFileName);
     
    19021928VOID FreeCnrItem(HWND hwnd, PCNRITEM pci)
    19031929{
     1930# ifdef PMPRINTF
     1931  PmPrintf_Report(pszSrcFile, __LINE__, "FreeCnrItem freeing pci %p");
     1932# endif
     1933
    19041934  FreeCnrItemData(pci);
    19051935
     
    19491979 * Remove item(s) from container and free associated storage if requested
    19501980 * @param pciFirst points to first item to remove or NULL to remove all
    1951  * @param usCnt is remove count or 0 to remove all
    1952  * @returns count of items remaining in container or -1 if error
     1981 * @param usCnt is 0 to remove all or 1 to remove specific record
     1982 * @param usFlags for CM_REMOVERECORD
     1983 * @returns count of items remaining to delete or -1 if error
    19531984 */
    19541985
     
    19571988  INT remaining = usCnt;
    19581989  BOOL bIdlePrioritySet = FALSE;
    1959   // #define RCI_ITEMS_PER_TIMER_CHECK (10)
    1960   // 10 seems a very conservative number
    1961   //  USHORT usTimerCheckCountdown      = RCI_ITEMS_PER_TIMER_CHECK;
    19621990  PCNRITEM pci;
    1963   PCNRITEM pciPrevious;
    19641991  ITIMER_DESC itdSleep = { 0 };         // 30 May 11 GKY
    19651992
    1966   if ((usCnt && !pciFirst) || (!usCnt && pciFirst)) {
    1967       Runtime_Error(pszSrcFile, __LINE__, "pciFirst %p usCnt %u mismatch", pciFirst, usCnt);
     1993  // Counted remove requires pciFirst and can only remove 1 record
     1994  // Remove all does not allow pciFirst
     1995  if ((usCnt && !pciFirst) || (usCnt != 1 && pciFirst)) {
     1996    Runtime_Error(pszSrcFile, __LINE__, "pciFirst %p usCnt %u mismatch", pciFirst, usCnt);
     1997    remaining = -1;
     1998  }
     1999  else if (!usFlags & CMA_FREE) {
     2000    Runtime_Error(pszSrcFile, __LINE__, "usFlags must have CMA_FREE set");
     2001    remaining = -1;
     2002  }
     2003  else if (!pciFirst) {
     2004    // Removing all - query first
     2005    pciFirst = (PCNRITEM)WinSendMsg(hwnd, CM_QUERYRECORD, MPVOID,
     2006                                    MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
     2007    if ((INT)pciFirst == -1) {
     2008      Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_QUERYRECORD");
    19682009      remaining = -1;
    1969   }
    1970   else {
    1971     // Free our buffers if free requested
    1972     if (usFlags & CMA_FREE) {
    1973       if (pciFirst)
    1974         pci = pciFirst;
    1975       else {
    1976         pci = (PCNRITEM)WinSendMsg(hwnd, CM_QUERYRECORD, MPVOID,
    1977                                    MPFROM2SHORT(CMA_FIRST, CMA_ITEMORDER));
    1978         if ((INT)pci == -1) {
    1979           Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_QUERYRECORD");
    1980           remaining = -1;
    1981           pci = NULL;
    1982         }
    1983       }
    1984       InitITimer(&itdSleep, 500);
    1985       while (pci) {
    1986         FreeCnrItemData(pci);
    1987         if (usCnt > 0)
    1988           pciPrevious = pci;
    1989         pci = (PCNRITEM)pci->rc.preccNextRecord;
    1990         if (!pci)
    1991           break;
    1992         if (usCnt > 0 && pciPrevious && pciPrevious->pciPrevious) {
    1993           pciPrevious->pciPrevious->rc.preccNextRecord = (MINIRECORDCORE *) pci;
    1994           pci->pciPrevious = pciPrevious->pciPrevious;
    1995           pciPrevious->pciPrevious = NULL;
    1996           pciPrevious->rc.preccNextRecord = NULL;
    1997         }
    1998         if (remaining && --remaining == 0)
    1999           break;
    2000         if (!bIdlePrioritySet) {
    2001           bIdlePrioritySet = !IdleIfNeeded(&itdSleep, 30);
    2002         }
    2003       } // while
    2004       if (bIdlePrioritySet)
    2005         priority_normal();
    2006 
    2007       DosPostEventSem(CompactSem);
    2008     }
    2009   }
    2010   if (remaining != - 1) {
     2010    }
     2011  }
     2012
     2013  InitITimer(&itdSleep, 500);
     2014
     2015# ifdef PMPRINTF
     2016  PmPrintf_Report(pszSrcFile, __LINE__, "RemoveCnrItems freeing data pciFirst %p usCnt %d remaining %d",
     2017                  pciFirst, usCnt, remaining);
     2018# endif
     2019
     2020  // Free data
     2021  // 2020-01-28 SHL Rework to use CMA_NEXT - preccNextRecord method was never reliable
     2022  pci = pciFirst;
     2023  while (pci && (INT)pci != -1) {
     2024    FreeCnrItemData(pci);
     2025    if (remaining && --remaining == 0)
     2026      break;                    // pci point to last CNRITEM to be deleted
     2027    pci = WinSendMsg(hwnd, CM_QUERYRECORD, MPFROMP(pci),
     2028                     MPFROM2SHORT(CMA_NEXT, CMA_ITEMORDER));
     2029    if (!bIdlePrioritySet)
     2030      bIdlePrioritySet = !IdleIfNeeded(&itdSleep, 30);
     2031  } // while
     2032
     2033  if (bIdlePrioritySet)
     2034    priority_normal();
     2035
     2036  DosPostEventSem(CompactSem);
     2037
     2038  // Free CNRITEM record(s) if OK so far
     2039  if (remaining != -1 && pciFirst && (INT)pciFirst != -1) {
     2040#   ifdef PMPRINTF
     2041    PmPrintf_Report(pszSrcFile, __LINE__, "RemoveCnrItems CM_REMOVERECORD pciFirst %p usCnt %d", pciFirst, usCnt);
     2042#   endif
    20112043    remaining = (INT)WinSendMsg(hwnd, CM_REMOVERECORD, MPFROMP(&pciFirst), MPFROM2SHORT(usCnt, usFlags));
    2012     if (remaining == -1) {
     2044    if (remaining == -1)
    20132045      Win_Error(hwnd, HWND_DESKTOP, pszSrcFile, __LINE__,"CM_REMOVERECORD hwnd %x pci %p cnt %u", hwnd, pciFirst, usCnt);
    2014     }
     2046    else if (usCnt == 0 && remaining != 0)
     2047      Runtime_Error(pszSrcFile, __LINE__, "%u records remain after CM_REMOVERECORD", remaining);
    20152048  }
    20162049
Note: See TracChangeset for help on using the changeset viewer.