|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.