How do I recurse through a directory tree?

This code is taken from a utility for counting lines in all files matching a given spec, in or below a certain folder. It illustrates the technique for recursing into folders quite well. It's pretty obvious, you just have to watch out for the special case items . (this folder) and .. (up one).

UINT CCountlinesDlg::GetLineCountForFiles (CString& csStartFolder,
                                           CString& csFileSpec,
                                           BOOL bRecurse)
{
   UINT uRetVal = 0;
   HANDLE hFF = 0;
   WIN32_FIND_DATA wfd;

   int iDotIndex=0;
   CString csPath;
   CString csFile;
   CString csSubPath;
   CString csTgt;
   CString csExtension;
   CString csUpperFileSpec = csFileSpec;

   csUpperFileSpec.MakeUpper();
   m_csOutputDir = csStartFolder;
   UpdateData (FALSE);

   csTgt = csStartFolder + "\\*.*";

   hFF = FindFirstFile (csTgt,&wfd);
   if (hFF != INVALID_HANDLE_VALUE)
   {
      if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
      {
         if (strcmp (wfd.cFileName, ".") && 
             strcmp (wfd.cFileName, "..") &&
             bRecurse)
         {
            // recurse into the subdir:
            csSubPath = csStartFolder + "\\" + wfd.cFileName;
            uRetVal += GetLineCountForFiles (csSubPath,csFileSpec,bRecurse);
         }
      }
      else
      {
         // Is this one of the target files ?
         csFile = wfd.cFileName;
         iDotIndex = csFile.ReverseFind ('.');

         csExtension = csFile.Right (csFile.GetLength() - (iDotIndex+1));
         csExtension.MakeUpper ();

         if (csExtension == csUpperFileSpec)
         {
           csFile = csStartFolder + "\\" + wfd.cFileName;
           uRetVal += CountLinesIn (csFile);
           m_csOutputFile.Format ("%s : %u", wfd.cFileName, uRetVal);
           UpdateData (FALSE);
        }
      }

      while (FindNextFile (hFF, &wfd))
      {
         if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
         {
            if (strcmp (wfd.cFileName, ".") && 
                strcmp (wfd.cFileName, "..") &&
                bRecurse)
            {
               // recurse into the subdir:
               csSubPath = csStartFolder + "\\" + wfd.cFileName;
               uRetVal += GetLineCountForFiles (csSubPath,csFileSpec,bRecurse);
            }
         }
         else
         {
            // Is this one of the target files?

            csFile = wfd.cFileName;
            iDotIndex = csFile.ReverseFind ('.');
            csExtension = csFile.Right (csFile.GetLength() - (iDotIndex+1));
            csExtension.MakeUpper();
            if (csExtension == csUpperFileSpec)
            {
               csFile = csStartFolder + "\\" + wfd.cFileName;
               uRetVal += CountLinesIn (csFile);
               m_csOutputFile.Format ("%s : %u", wfd.cFileName, uRetVal);
               UpdateData (FALSE);
            }
         }
      }
   }
   return uRetVal;
}

Download