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