home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winbase / security / crypto / cfiler / expdir.c < prev    next >
C/C++ Source or Header  |  1997-10-08  |  20KB  |  618 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright 1996-1997 Microsoft Corporation.
  5. *       All rights reserved. 
  6. *       This source code is only intended as a supplement to 
  7. *       Microsoft Development Tools and/or WinHelp documentation.
  8. *       See these sources for detailed information regarding the 
  9. *       Microsoft samples programs.
  10. \******************************************************************************/
  11.  
  12. //    PROGRAM: EXPDIR.C
  13. //
  14. //    PURPOSE: Directory Listbox expansion/collapse functions
  15.  
  16. #define  STRICT
  17.  
  18. #include "cfiler.h"
  19.  
  20. extern HANDLE ghModule;
  21.  
  22. /**********************************************************************************\
  23. * ExpDir()
  24. *
  25. * Thread Function
  26. * Called when directory is selected (Enter or Double-click).  Expands subdirs
  27. *  of selected directory if not expanded, indenting subdirs.  If
  28. *  already expanded, deletes all subdirs from listbox
  29. *
  30. * Returns:  TRUE if successful, FALSE if error.
  31. \***********************************************************************************/
  32.  
  33. BOOL ExpDir(LPCINFO lpCInfo)
  34. {
  35.     HANDLE          hFile = NULL;   //  Find file handle
  36.     WIN32_FIND_DATA FileData;       //  Find file info structure
  37.  
  38.     TCHAR           szFileName[BUF_SIZE];
  39.     TCHAR            szFileName2[BUF_SIZE];
  40.     TCHAR            szInsertString[DIRECTORY_STRING_SIZE << 1];
  41.     TCHAR            szBuf[BUF_SIZE];
  42.  
  43.     PTCHAR          lpszHold;      //  Points to actual name in LB string
  44.  
  45.     BOOL            fDone = FALSE;  //  Loop flag for finding files in dir
  46.  
  47.     DWORD           dwAttrib;       //  Holds file attribute flags
  48.  
  49.     LONG            lIndex,         //  Index of selected listbox member
  50.                     lDirDepth;
  51.     
  52.     INT i;
  53.     
  54.        if (!lpCInfo) {
  55.            ErrorMsg(TEXT("ExpDir: lpCInfo is NULL."));
  56.            return FALSE;
  57.        }
  58.        
  59.        for (i = 0; i < BUF_SIZE; i++) {
  60.         szFileName[i] = TEXT('\0');
  61.         szFileName2[i] = TEXT('\0');
  62.     }
  63.     
  64.     if( WaitForSingleObject( lpCInfo->hDirMutex, MUTEX_TIMEOUT)
  65.             == WAIT_TIMEOUT ){
  66.         ErrorMsg(TEXT("ExpDir: Dir LB Mutex Timeout."));
  67.         return(0);
  68.     }
  69.  
  70.     //
  71.     // If the LB is empty, we insert the root, unexpanded
  72.     //
  73.     if( !SendMessage( lpCInfo->hDirLB, LB_GETCOUNT, 0, 0) ){
  74.  
  75.         TCHAR   szHold[DIRECTORY_STRING_SIZE << 1];
  76.  
  77.         szHold[0] = TEXT('+');
  78.         lstrcpy( &(szHold[1]), lpCInfo->lpDriveInfo->DriveName );
  79.  
  80.         //
  81.         // Also copy the DriveName to the Caption Bar.
  82.         //
  83.         lstrcpy(lpCInfo->CaptionBarText, lpCInfo->lpDriveInfo->DriveName );
  84.  
  85.         SendMessage(lpCInfo->hDirLB, LB_ADDSTRING, 0,
  86.                     (LPARAM)szHold );
  87.  
  88.         if (!TableAdd(lpCInfo->DirTable, lpCInfo->lpDriveInfo->DriveName, szHold)) {
  89.             ErrorMsg(TEXT("ExpDir: TableAdd failed."));
  90.             return FALSE;
  91.         }
  92.         
  93.         ReleaseMutex( lpCInfo->hDirMutex );
  94.         return(1);
  95.     }
  96.  
  97.     //
  98.     // Retrieve index of selected (careted) directory.
  99.     //
  100.     lIndex = SendMessage( lpCInfo->hDirLB, LB_GETCARETINDEX,
  101.                           (WPARAM)NULL, (LPARAM)NULL );
  102.  
  103.     if( SendMessage( lpCInfo->hDirLB, LB_GETTEXT, (WPARAM)lIndex,
  104.                         (LPARAM)szFileName ) < 0 ){
  105.         ErrorMsg(TEXT("Expand Directory:  Get listbox text failure"));
  106.         ExpDirExit(lpCInfo, hFile);
  107.         return(0);
  108.     }
  109.  
  110.     lDirDepth = GetDirDepth( szFileName, &lpszHold );
  111.  
  112.     if( lDirDepth == -1 ){
  113.         ErrorMsg(TEXT(" Expand Directory:  GetDirDepth failure"));
  114.         ExpDirExit(lpCInfo, hFile);
  115.         return(0);
  116.     }
  117.  
  118.     //
  119.     // If Directory is already expanded, collapse it, and vice versa.
  120.     //  First, change the symbol.
  121.     //
  122.     if( *lpszHold == TEXT('-'))
  123.         *lpszHold = TEXT('+');
  124.     else
  125.         *lpszHold = TEXT('-');
  126.  
  127.     //
  128.     // Clear WM_SETREDRAW flag, so changes will not be seen until entire
  129.     //  expansion/collapse is complete.  Reset flag at end of function
  130.     //
  131.     if( SendMessage(lpCInfo->hDirLB, WM_SETREDRAW, (WPARAM)FALSE,
  132.                 (LPARAM)0 ) < 0){
  133.         ErrorMsg(TEXT("Expand Directory:  Clear redraw flag failure"));
  134.         ExpDirExit(lpCInfo, hFile);
  135.         return(0);
  136.     }
  137.  
  138.     //
  139.     // Delete old dir string, insert new, and reset the selection
  140.     //
  141.     if( SendMessage(lpCInfo->hDirLB, LB_DELETESTRING, (WPARAM)lIndex,
  142.                 (LPARAM)0 ) < 0){
  143.         ErrorMsg(TEXT("Expand Directory:  Delete dir string failure"));
  144.         ExpDirExit(lpCInfo, hFile);
  145.         return(0);
  146.     }
  147.     else {
  148.         if (!TableGetHidden(lpCInfo->DirTable, lIndex, szBuf)) {
  149.             ErrorMsg(TEXT("ExpDir: TableGetHidden failed."));
  150.             return 0;
  151.         }
  152.         lstrcpy(szInsertString, szBuf);
  153.         TableRemove(lpCInfo->DirTable, lIndex);
  154.     }
  155.  
  156.     if( SendMessage(lpCInfo->hDirLB, LB_INSERTSTRING, (WPARAM)lIndex,
  157.                (LPARAM)szFileName ) < 0){
  158.         ErrorMsg(TEXT("Expand Directory:  Insert dir string failure"));
  159.         ExpDirExit(lpCInfo, hFile);
  160.         return(0);
  161.     }
  162.     else {
  163.         if (!TableInsert(lpCInfo->DirTable, szInsertString, szFileName, lIndex)) {
  164.             ErrorMsg(TEXT("ExpDir: TableInsert failed."));
  165.             return 0;
  166.         }    
  167.     }
  168.     
  169.     if( SendMessage(lpCInfo->hDirLB, LB_SETCURSEL, (WPARAM)lIndex,
  170.                (LPARAM)0 ) < 0){
  171.         ErrorMsg(TEXT("Expand Directory:  Insert dir string failure"));
  172.         ExpDirExit(lpCInfo, hFile);
  173.         return(0);
  174.     }
  175.  
  176.     //
  177.     // The symbol has been changed, now collapse if needed, then reset
  178.     //  redraw flag, leave critical section, and exit.
  179.     //
  180.     if( *lpszHold == TEXT('+') ){
  181.         CollapseDir( lpCInfo, lIndex, lDirDepth);
  182.         ExpDirExit(lpCInfo, hFile);
  183.         return(1);
  184.     }
  185.  
  186.     //
  187.     // If we're here, directory needs to be expanded.
  188.     //  Enumerate subdirectories beneath the dir entry in the listbox.
  189.     //
  190.     // First, Get the full path of the directory (in szFileName)
  191.     //
  192.     if (!TableGetHidden(lpCInfo->DirTable, lIndex, szBuf)) {
  193.         ErrorMsg(TEXT("ExpDir: TableGetHidden failed."));
  194.         return FALSE;
  195.     }
  196.     
  197.     lstrcpy(szFileName, szBuf);
  198.         
  199.     //
  200.     // Check to see if there is a terminating backslash
  201.     //  Then append a '*' as a wildcard for FindFirstFile.
  202.     //
  203.     lpszHold = &szFileName[lstrlen(szFileName)];
  204.  
  205.     lpszHold--;
  206.     if( *lpszHold != TEXT('\\') ){
  207.         lpszHold++;
  208.         *lpszHold = TEXT('\\');
  209.     }
  210.  
  211.     lstrcpy(szFileName2, szFileName);
  212.     
  213.     lpszHold++;
  214.     lstrcpy( lpszHold, TEXT("*"));
  215.  
  216.     //
  217.     // Start a search on all the files within the directory
  218.     //
  219.     hFile = FindFirstFile( szFileName, &FileData );
  220.     if( hFile == INVALID_HANDLE_VALUE ){
  221.         ErrorMsg(TEXT("Expand Directory: FindFirstFile failure."));
  222.         ExpDirExit(lpCInfo, hFile);
  223.         return(0);
  224.     }
  225.  
  226.     //
  227.     // Walk all the files in the directory.
  228.     //
  229.     while( !fDone ){
  230.  
  231.         //
  232.         // Check to see if the thread has been requested to kill itself.
  233.         //  This code does not clear the suicide flag for synchronization
  234.         //  reasons - it is left to the calling code.
  235.         //
  236.         if( lpCInfo->fSuicide ){
  237.             ErrorMsg(TEXT("Expand Directory: killing thread per request."));
  238.             ExpDirExit(lpCInfo, hFile);
  239.  
  240.             //
  241.             // Post an MM_REFRESH Message if the user has re-collapsed the
  242.             //  Dir LB.
  243.             //
  244.             if( !lpCInfo->fDirExpand )
  245.                 if( !PostMessage(lpCInfo->hwnd, WM_COMMAND, MM_REFRESH,
  246.                                  (LPARAM)0) )
  247.                     ErrorMsg(TEXT("ExpDir: MM_REFRESH call failure."));
  248.  
  249.             //
  250.             // We must return failure (0) here, so if FullExpand is calling,
  251.             //  it will terminate.
  252.             //
  253.             return(0);
  254.         }
  255.  
  256.         //
  257.         // Append filename to path, and get attributes
  258.         //
  259.         lstrcpy(lpszHold, FileData.cFileName);
  260.         dwAttrib = GetFileAttributes( szFileName );
  261.  
  262.         //
  263.         // Check if file is a directory.  If not, or if '.' or '..', fall
  264.         //  through.  If so, add it to the directory listbox.
  265.         //
  266.         if( dwAttrib & FILE_ATTRIBUTE_DIRECTORY )
  267.             if( lstrcmp( FileData.cFileName,TEXT(".") ) )
  268.                 if( lstrcmp( FileData.cFileName,TEXT("..") ) ){
  269.                     TCHAR   szLBEntry[DIRECTORY_STRING_SIZE << 1];
  270.                     TCHAR    szHidden[DIRECTORY_STRING_SIZE << 1];
  271.                     
  272.                     lstrcpy(szHidden, szFileName2);
  273.                     lstrcat(szHidden, FileData.cFileName);
  274.  
  275.                     if (IsEncrypted(szHidden)) {
  276.                         TCHAR    szDecryptedName[BUF_SIZE];
  277.                         HANDLE    hFileRead;
  278.                             
  279.                         GetDecryptedDirName(lpCInfo->hDirLB, 
  280.                                             szHidden, 
  281.                                             szDecryptedName, 
  282.                                             0, 
  283.                                             &hFileRead);    
  284.                         CloseHandle(hFileRead);
  285.                         
  286.                         if (!SimplifyFileName(szDecryptedName, szBuf)) {
  287.                             ErrorMsg(TEXT("ExpDir: SimplifyFileName failed."));
  288.                             return FALSE;
  289.                         }
  290.                                                 
  291.                         lstrcpy(szDecryptedName, szBuf);
  292.  
  293.                         ConstructLBEntry(lDirDepth, szDecryptedName, szLBEntry);
  294.                     }
  295.                     else
  296.                         ConstructLBEntry(lDirDepth, FileData.cFileName, szLBEntry);
  297.                     
  298.                     //
  299.                     //  Increment index in order to add subdir after
  300.                     //  dirs just inserted.
  301.                     //
  302.                     lIndex++;
  303.                     
  304.                     if( SendMessage(lpCInfo->hDirLB, LB_INSERTSTRING,
  305.                                        (WPARAM)lIndex,
  306.                                        (LPARAM)szLBEntry) < 0){
  307.                         ErrorMsg(TEXT("Expand Directory: error inserting string."));
  308.                         ExpDirExit(lpCInfo, hFile);
  309.                         return(0);
  310.                     }
  311.                     
  312.                     if (!TableInsert(lpCInfo->DirTable, szHidden, szLBEntry, lIndex)) {
  313.                         ErrorMsg(TEXT("ExpDir: TableInsert failed."));
  314.                         return FALSE;
  315.                     }
  316.                  }
  317.  
  318.         fDone = !FindNextFile( hFile, &FileData );
  319.     }
  320.  
  321.     ExpDirExit(lpCInfo, hFile);
  322.     return(1);
  323. }
  324.  
  325. /***********************************************************************************\
  326. * ExpDirExit()
  327. *
  328. * Performs clean-up operations for ExpDir, closing handles, etc.
  329. \***********************************************************************************/
  330.  
  331. void ExpDirExit(LPCINFO lpCInfo, HANDLE hFile)
  332. {
  333.     if (!lpCInfo) {
  334.         ErrorMsg(TEXT("ExpDirExit: lpCInfo is NULL."));
  335.         return;
  336.     }
  337.     
  338.     // Reset redraw flag. Post this message, to avoid synchro problems
  339.   
  340.     if( PostMessage(lpCInfo->hDirLB, WM_SETREDRAW, (WPARAM)TRUE,
  341.                 (LPARAM)0 ) < 0)
  342.         ErrorMsg(TEXT("Expand Directory:  Clear redraw flag failure"));
  343.  
  344.     //
  345.     // Close FindFirstFile session
  346.     //
  347.     if( hFile != NULL)
  348.         FindClose(hFile);
  349.  
  350.     //
  351.     // Release Dir LB Mutex
  352.     //
  353.     ReleaseMutex( lpCInfo->hDirMutex);
  354. }
  355.  
  356. /***********************************************************************************\
  357. * ConstructDirName()
  358. *
  359. * Builds the fully qualified path of the current directory, by walking back
  360. *  through the Dir LB tree.
  361. *
  362. * Returns:  TRUE if successful, FALSE if error.
  363. *           Returns the full directory path of given directory name in
  364. *             lpszDirName.
  365. \***********************************************************************************/
  366.  
  367. BOOL ConstructDirName(LPCINFO lpCInfo, LONG lIndex, LPTSTR lpszDirName)
  368. {
  369.     LONG    lDirDepth,      //  Depth of selected directory
  370.             lSeekDepth = LONG_MAX;
  371.  
  372.     TCHAR   szFileName[DIRECTORY_STRING_SIZE << 1];   // file buffer
  373.     LPTSTR  lpszInfoPtr,
  374.             lpszHold;
  375.  
  376.     if (!lpCInfo) {
  377.         ErrorMsg(TEXT("ConstructDirName: lpCInfo is NULL."));
  378.         return FALSE;
  379.     }
  380.     
  381.     //
  382.     // Clear the directory name buffer
  383.     //
  384.     *lpszDirName = TEXT('\0');
  385.  
  386.     //
  387.     // Walk up the entries in the listbox, constructing the full path from
  388.     //   the bottom up.
  389.     //
  390.     while( lIndex >= 0 ){
  391.  
  392.         //
  393.         // Get listbox text, and compute the depth of the directory
  394.         //
  395.         if( SendMessage( lpCInfo->hDirLB, LB_GETTEXT, (WPARAM)lIndex,
  396.                             (LPARAM)szFileName ) < 0 ){
  397.             ErrorMsg(TEXT(" Expand Directory:  Get listbox text failure"));
  398.             return(0);
  399.         }
  400.  
  401.         lDirDepth = GetDirDepth(szFileName, &lpszInfoPtr);
  402.         if( lDirDepth == -1){
  403.             ErrorMsg(TEXT("ConstructDirName: GetDirDepth failed"));
  404.             return(0);
  405.         }
  406.  
  407.         //
  408.         // If we've reached the next level up, add to the directory name
  409.         //
  410.         if( lDirDepth < lSeekDepth ){
  411.             lSeekDepth = lDirDepth;
  412.  
  413.             // check if we will exceed the size of our buffer
  414.             if( lstrlen(lpszInfoPtr) + lstrlen(lpszDirName) >
  415.                     (DIRECTORY_STRING_SIZE << 1) ){
  416.                 ErrorMsg(TEXT("ConstructDirName:  Exceeded Directory Size limit"));
  417.                 return(0);
  418.             }
  419.  
  420.             // Find the end of the directory name
  421.             lpszHold = &lpszInfoPtr[lstrlen(lpszInfoPtr)];
  422.            
  423.             // If we're not at the root, add a '\'
  424.             if( lIndex && (*lpszDirName != TEXT('\0')) )
  425.                 *lpszHold++ = TEXT('\\');
  426.  
  427.             // Append the heretofore computed path to the end of the dir name
  428.             lstrcpy( lpszHold, lpszDirName);
  429.             // Copy the whole path so far back into the final buffer
  430.             lstrcpy( lpszDirName, ++lpszInfoPtr);
  431.         }
  432.  
  433.         // If the first level dir has been added, jump to the root,
  434.         //   else go up to the previous entry in the listbox.
  435.         if( lDirDepth == 1 )
  436.             lIndex = 0;
  437.         else
  438.             lIndex--;
  439.     }
  440.  
  441.     return(TRUE);
  442. }
  443.  
  444. /***********************************************************************************\
  445. * GetDirDepth()
  446. *
  447. * Returns:  -1 if error
  448. *           otherwise, the depth of the directory (i.e. root is depth 0,
  449. *           c:\foo is depth 1, etc.  This is computed in perhaps not the
  450. *           most efficient way, by counting the ' 's proceeding the name.
  451. *
  452. *           This function also returns in lpszDirName a pointer to the
  453. *           end of the preceeding ' ' characters within the given listbox str.
  454. *           If the function fails, this pointer value is undefined.
  455. *
  456. * The left shifted index is to skip the tab characters. See ConstructLBEntry().
  457. \***********************************************************************************/
  458.  
  459. LONG GetDirDepth(LPTSTR lpszLBString, LPTSTR *lpszDirName)
  460. {
  461.     TCHAR cBar;
  462.     LONG  lCount = 0;
  463.  
  464.     do{
  465.  
  466.         cBar = lpszLBString[lCount << 1];
  467.  
  468.         if( cBar == TEXT(' ') )
  469.             lCount++;
  470.         else
  471.             if( cBar != TEXT('+') && cBar != TEXT('-') ){
  472.                 ErrorMsg(TEXT("GetDirDepth: string parse error"));
  473.                 return(-1);
  474.             }
  475.  
  476.     }while( cBar != TEXT('+') && cBar != TEXT('-') );
  477.  
  478.     *lpszDirName = &(lpszLBString[lCount << 1]);
  479.  
  480.     return( lCount );
  481. }
  482.  
  483. /***********************************************************************************\
  484. * CollapseDir()
  485. *
  486. * If directory is expanded, collapses it, by deleteing any subdirectory
  487. *  entries below it.
  488. *
  489. * Returns:  TRUE if successful, FALSE if error
  490. \***********************************************************************************/
  491.  
  492. BOOL CollapseDir(LPCINFO lpCInfo, LONG lIndex, LONG lDirDepth)
  493. {
  494.     TCHAR   szFileName[DIRECTORY_STRING_SIZE << 1];   // file name buffer
  495.     LPTSTR  lpszNamePtr;
  496.  
  497.     LONG    lDepthHold;
  498.         
  499.     if (!lpCInfo) {
  500.         ErrorMsg(TEXT("CollapseDir: lpCInfo is NULL."));
  501.         return FALSE;
  502.     }
  503.     
  504.     //
  505.     // Remove any following LB entries until we return to same depth
  506.     //
  507.     do{
  508.         if (lpCInfo->DirTable->iNumElems == 1)
  509.             return 1;
  510.         
  511.         if( SendMessage( lpCInfo->hDirLB, LB_GETTEXT, (WPARAM)lIndex + 1,
  512.                             (LPARAM)szFileName ) < 0 ){
  513.             ErrorMsg(TEXT(" Expand Directory:  Get listbox text failure"));
  514.             return(0);
  515.         }
  516.  
  517.         lDepthHold = GetDirDepth( szFileName, &lpszNamePtr);
  518.         if( lDirDepth == -1 ){
  519.             ErrorMsg(TEXT(" Expand Directory:  GetDirDepth failure"));
  520.             return(0);
  521.         }
  522.  
  523.         if( lDirDepth < lDepthHold ) {
  524.             if( SendMessage( lpCInfo->hDirLB, LB_DELETESTRING, (WPARAM)lIndex + 1,
  525.                                 (LPARAM)0 ) < 0 ){
  526.                 ErrorMsg(TEXT(" Expand Directory:  Delete String failure"));
  527.                 return(0);
  528.             }
  529.             if (!TableRemove(lpCInfo->DirTable, lIndex + 1)) {
  530.                 ErrorMsg(TEXT("CollapseDir: TableRemove failed."));
  531.                 return 0;
  532.             }
  533.         }
  534.     }while( lDirDepth < lDepthHold );
  535.  
  536.     return(1);
  537. }
  538.  
  539. /***********************************************************************************\
  540. * ConstructLBEntry()
  541. *
  542. * Given the parent's directory depth, and the subdirectory name, inserts
  543. * ' 's equal to the depth+1 of the parent (plus tab character), and an
  544. * unexpanded '+' directory marker, then the name of the subdirectory.
  545. *
  546. * The left shifted index is to skip the tab characters.
  547. *
  548. * Returns:  void.  the completed listbox entry is returned in szLBEntry.
  549. \***********************************************************************************/
  550.  
  551. void ConstructLBEntry(LONG lDirDepth, LPTSTR szFileName, LPTSTR szLBEntry)
  552. {
  553.     int i;
  554.  
  555.     for(i = 0; i <= lDirDepth; i++){
  556.         szLBEntry[i << 1] = TEXT(' ');
  557.         szLBEntry[(i << 1) + 1] = 9;
  558.     }
  559.  
  560.     szLBEntry[i << 1] = TEXT('+');
  561.     szLBEntry[(i << 1) + 1] = TEXT('\0');
  562.  
  563.     lstrcat(szLBEntry, szFileName);
  564. }
  565.  
  566. /***********************************************************************************\
  567. * FullExpand()
  568. *
  569. * From the unexpanded root, walks down directory LB, expanding each directory
  570. *  until it reaches the end of the tree.
  571. \***********************************************************************************/
  572.  
  573. BOOL FullExpand(LPCINFO lpCInfo)
  574. {
  575.     LONG lIndex = 0;
  576.  
  577.     if (!lpCInfo) {
  578.         ErrorMsg(TEXT("FullExpand: lpCInfo is NULL."));
  579.         return FALSE;
  580.     }
  581.     
  582.     if( WaitForSingleObject( lpCInfo->hDirMutex, MUTEX_TIMEOUT)
  583.             == WAIT_TIMEOUT ){
  584.         ErrorMsg(TEXT("FullExpand: Dir LB Mutex Timeout."));
  585.         return(0);
  586.     }
  587.  
  588.     while( SendMessage(lpCInfo->hDirLB, LB_SETCURSEL,
  589.                         (WPARAM)lIndex,
  590.                         (LPARAM)0) != LB_ERR ){
  591.         if( !ExpDir( lpCInfo ) ){
  592.             ErrorMsg(TEXT("Full Expand: ExpDir failure."));
  593.             ReleaseMutex( lpCInfo->hDirMutex );
  594.  
  595.             // This is in case the ExpDir failed because a change drive
  596.             //  command caused a kill.
  597.             if( !PostMessage(lpCInfo->hwnd, WM_COMMAND, MM_REFRESH,
  598.                             (LPARAM)0) )
  599.                 ErrorMsg(TEXT("ExpDir: MM_REFRESH call failure."));
  600.             return(0);
  601.         }
  602.  
  603.         lIndex++;
  604.     }
  605.  
  606.     //  Set selection in listboxes to first item.
  607.     if( SendMessage(lpCInfo->hDirLB, LB_SETCURSEL,
  608.                         (WPARAM)0,
  609.                         (LPARAM)0) == LB_ERR ){
  610.         ErrorMsg(TEXT("Full Expand: Dir LB Set Selection Error"));
  611.         ReleaseMutex( lpCInfo->hDirMutex );
  612.         return(0);
  613.     }
  614.  
  615.     ReleaseMutex( lpCInfo->hDirMutex );
  616.     return(1);
  617. }
  618.