Annotation of mstools/samples/filer/enumdrv.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.