home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winbase / io / filer / enumdrv.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  9KB  |  274 lines

  1.  
  2. /******************************************************************************\
  3. *       This is a part of the Microsoft Source Code Samples. 
  4. *       Copyright (C) 1993-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. /****************************************************************************
  13. *
  14. *    PROGRAM: Enumdrv.C
  15. *
  16. *    PURPOSE: Determines all drives in the system, both local and remote,
  17. *             and their file system type
  18. *
  19. ****************************************************************************/
  20. #define  STRICT
  21. #include <windows.h>
  22. #include "globals.h"
  23. #include "filer.h"
  24. #include "enumdrv.h"
  25.  
  26. extern HANDLE           ghHeap;          // Handle to global heap, declared in FILER.C
  27. extern CRITICAL_SECTION gHeapCS;      // Global heap critical section var.
  28. extern CRITICAL_SECTION gDrvCS;          // Drive list critical section var.
  29. extern LPDINFO          glpDrives;
  30. extern HANDLE            ghModule;      // Global Instance handle, declared in FILER.C    
  31.  
  32. /****************************************************************************
  33. *
  34. *    FUNCTION: CheckRM(LPTSTR)
  35. *
  36. *    PURPOSE: Verifies that a removeable media drive contains a disk
  37. *
  38. *    COMMENTS:
  39. *
  40. *        This function is called each time a drive type is determined to be
  41. *        removeable (DRIVE_REMOVEABLE).  An attempt is made to open a
  42. *        file in the root directory of the drive.  If the attempt succeeds,
  43. *        then media is present in the drive and subsequent calls to the
  44. *        drive can be safely made.  If the call fails, then there is no media
  45. *        present in the drive and no attempts should be made to access this
  46. *        drive.  The Error Mode is temporarily set to 1 to allow failures
  47. *        to immediately return to the calling program.  This eliminates
  48. *        unwanted dialog boxes that prompt for disks to be placed in the
  49. *        drive.
  50. *
  51. *    INPUT: szDriveName - removeable media drive name (ex - "a:")
  52. *
  53. *    OUTPUT: Returns TRUE if media present
  54. *                    FALSE if media is not present
  55. *
  56. ****************************************************************************/
  57.  
  58. BOOL CheckRM( LPTSTR lpszDriveName )
  59. {
  60.     TCHAR    szFileName[DIRECTORY_STRING_SIZE];
  61.     DWORD    dwHold;
  62.  
  63.     SetErrorMode( SEM_FAILCRITICALERRORS );
  64.  
  65.     lstrcpy( szFileName, lpszDriveName );
  66.     lstrcat( szFileName, TEXT(".") );
  67.  
  68.     dwHold = GetFileAttributes( szFileName );
  69.  
  70.     SetErrorMode( 0 );
  71.  
  72.     //  If no error, media must be in drive.
  73.     if( dwHold != 0xFFFFFFFF ){
  74.         return(TRUE);
  75.     }
  76.     else{
  77.         dwHold = GetLastError();
  78.         if( dwHold != ERROR_NOT_READY )
  79.             ErrorMsg(TEXT("CheckRM: Get Removable Media Info Failure."));
  80.  
  81.         return(FALSE);
  82.     }
  83.  
  84. }
  85.  
  86.  
  87. /****************************************************************************
  88. *
  89. *    FUNCTION: DWORD EnumDrives(*LPDINFO)
  90. *
  91. *    PURPOSE: Enumerates available drives, and information on them. If the
  92. *               DINFO structure passed in is NULL, it creates a linked list
  93. *               of DINFO structures, reporting information on each available
  94. *               drive.  If DINFO points to an existing structure, the list
  95. *               is updated.
  96. *
  97. *    COMMENTS:
  98. *        The number of available drives is first determined by a call to
  99. *        GetLogicalDrives.  This provides a bit mask of all logical drives.
  100. *
  101. *        For each logical drive, a call is made to GetDriveType to determine
  102. *        the drive type.  If the logical drive is not in the bit mask that
  103. *        was created with the GetLogicalDrives call, then this drive is
  104. *        bypassed.
  105. *
  106. *        GetVolumeInformation is used to determine the file syste for the
  107. *        logical drive. If the drive type is removable, a check must be made
  108. *        to see if the drive contains a disk. If the remote drive contains a
  109. *        disk, then it is safe to proceed with the GetVolumeInformation call.
  110. *
  111. *    INPUT:  LPDINFO dINfo: A pointer to a DRVINFO Structure.
  112. *
  113. *    OUTPUT: Returns the number of DINFO structures in the linked
  114. *            list pointed to by dInfo.  Value is negative if error.
  115. *
  116. \****************************************************************************/
  117.  
  118. void EnumDrives(LPDINFO *lplpRoot)
  119. {
  120.   DWORD         dwDriveMask;
  121.   DWORD         dwCount;
  122.   LPTSTR        lpszRootPathName=TEXT("?:\\");
  123.   TCHAR            lpBuffer[128];
  124.  
  125.   static LPTSTR lpDriveStrings = NULL;
  126.   LPTSTR        lpParse;
  127.  
  128.   LPDINFO       lpDInfo,                // new node ptr
  129.                 lpHold,                 // list walking ptrs
  130.                 lpBack,
  131.                 lpRoot = *lplpRoot;     // root ptr
  132.  
  133.  
  134.   EnterCriticalSection(&gDrvCS);
  135.  
  136.   //
  137.   // Free old drive strings;
  138.   // With a buffer size of 0, the first call returns the size of buffer needed.
  139.   //
  140.   if(lpDriveStrings != NULL){
  141.     EnterCriticalSection(&gHeapCS);
  142.     HeapFree( ghHeap, 0, lpDriveStrings);
  143.     LeaveCriticalSection(&gHeapCS);
  144.   }
  145.  
  146.   dwCount=GetLogicalDriveStrings( 0, lpDriveStrings);
  147.   if( !dwCount ){
  148.     LoadString(ghModule, IDS_ENUMDRVERR, lpBuffer, sizeof(lpBuffer));
  149.     LeaveCriticalSection(&gDrvCS);
  150.     ErrorMsg(lpBuffer);
  151.     ExitThread((DWORD)-1);
  152.   }
  153.  
  154.   EnterCriticalSection(&gHeapCS);
  155.   // allocate memory, +1 for trailing NULL
  156.   lpDriveStrings = (LPTSTR)HeapAlloc( ghHeap, 0, (dwCount + 1) * sizeof(TCHAR) );
  157.   LeaveCriticalSection(&gHeapCS);
  158.  
  159.   if( lpDriveStrings == NULL){
  160.       LeaveCriticalSection(&gDrvCS);
  161.       LoadString(ghModule, IDS_ENUMALOCERR, lpBuffer, sizeof(lpBuffer));
  162.       ErrorMsg(lpBuffer);
  163.       ExitThread((DWORD)-2);
  164.   }
  165.  
  166.   if(dwCount < GetLogicalDriveStrings( dwCount, lpDriveStrings) ){
  167.       LeaveCriticalSection(&gDrvCS);
  168.       LoadString(ghModule, IDS_ENUMSTRERR, lpBuffer, sizeof(lpBuffer));
  169.       ErrorMsg(lpBuffer);
  170.       ExitThread((DWORD)-3);
  171.   }
  172.   lpParse = lpDriveStrings;
  173.  
  174.   dwDriveMask=GetLogicalDrives();
  175.  
  176.   //
  177.   // walk list, inserting, deleting, & updating nodes as necessary
  178.   //
  179.   dwCount = 0;
  180.   lpHold = lpBack = lpRoot;
  181.  
  182.   for (*lpszRootPathName=TEXT('a');*lpszRootPathName<=TEXT('z');(*lpszRootPathName)++){
  183.     if (dwDriveMask & 1){   // drive exists. Insert or update.
  184.  
  185.       dwCount++;
  186.  
  187.       //
  188.       // if lpHold (the list walking ptr) is NULL, or the drive that exists
  189.       //  does not already have a node in the list, allocate a node.
  190.       //
  191.       if( !lpHold || lpHold->DriveLetter > *lpszRootPathName ){
  192.         //
  193.         // Allocating memory for DRVINFO node
  194.         //
  195.         EnterCriticalSection(&gHeapCS);
  196.         lpDInfo = (LPDINFO) HeapAlloc( ghHeap, 0, (DWORD)sizeof(DRVINFO) );
  197.         LeaveCriticalSection(&gHeapCS);
  198.         if( lpDInfo == NULL){
  199.           LeaveCriticalSection(&gDrvCS);
  200.           LoadString(ghModule, IDS_DRVALOCERR, lpBuffer, sizeof(lpBuffer));
  201.           ErrorMsg(lpBuffer);
  202.           ExitThread((DWORD)-4);
  203.         }
  204.  
  205.         //
  206.         // insert new node into list
  207.         //
  208.         if( lpHold == lpRoot ){
  209.           lpDInfo->next = lpRoot;
  210.           lpRoot = lpDInfo;
  211.         }
  212.         else{
  213.           lpDInfo->next = lpBack->next;
  214.           lpBack->next = lpDInfo;
  215.         }
  216.  
  217.         lpBack = lpDInfo;
  218.         lpHold = lpDInfo->next;
  219.  
  220.         lpDInfo->DriveLetter = *lpszRootPathName;
  221.       }
  222.       else{
  223.         if( lpBack != lpHold )
  224.           lpBack = lpBack->next;
  225.         lpHold = lpHold->next;
  226.       }
  227.  
  228.       lpBack->DriveType = GetDriveType(lpszRootPathName);
  229.       if( lpBack->DriveType == DRIVE_REMOVABLE ||
  230.           lpBack->DriveType == DRIVE_CDROM )
  231.         if( CheckRM(lpszRootPathName ) )
  232.           if( !GetVolumeInformation(lpszRootPathName,NULL,0,NULL,NULL,NULL,
  233.                                    (LPTSTR)lpBack->FileSystem,
  234.                                    (DWORD)FILE_SYSTEM_STRING_SIZE) )
  235.             lstrcpy(lpBack->FileSystem, TEXT("UNKNOWN"));
  236.           else;
  237.         else      // no removable media
  238.           lstrcpy(lpBack->FileSystem, TEXT("UNKNOWN"));
  239.       else        // not removable
  240.         if( !GetVolumeInformation(lpszRootPathName,NULL,0,NULL,NULL,NULL,
  241.                                   (LPTSTR)lpBack->FileSystem,
  242.                                   (DWORD)FILE_SYSTEM_STRING_SIZE) )
  243.           lstrcpy(lpBack->FileSystem, TEXT("UNKNOWN"));
  244.         else;
  245.  
  246.       lpBack->DriveName = lpParse;
  247.       lpParse += lstrlen(lpParse)+1;
  248.     }
  249.     else{               // drive does not exist.
  250.       if( lpHold )      //   if node exists, delete it.
  251.         if( lpHold->DriveLetter == *lpszRootPathName ){
  252.           if( lpHold == lpRoot )
  253.             lpRoot = lpBack = lpHold->next;
  254.           else
  255.             lpBack->next = lpHold->next;
  256.  
  257.           EnterCriticalSection(&gHeapCS);
  258.           HeapFree(ghHeap, 0, (LPVOID)lpHold);
  259.           LeaveCriticalSection(&gHeapCS);
  260.  
  261.           lpHold = lpBack->next;
  262.         }
  263.     }
  264.     dwDriveMask >>= 1;
  265.  
  266.   } // end for
  267.  
  268.   *lplpRoot = lpRoot;
  269.  
  270.   LeaveCriticalSection(&gDrvCS);
  271.  
  272.   ExitThread(dwCount);
  273. }
  274.