Networked Drives
4 March 2002
A recurring question found in the Delphi newsgroups is how to get a list of networked (shared) drives.
The windows functions WNetOpenEnum(), WNetEnumResource() and WNetCloseEnum() allow the programmer to access shared disk and printer resources.
The WNetOpenEnum function opens a specific networked resource (indicated by the lpNetResource parameter) and returns a handle to this resource. This handle can then be enumerated using WNetEnumResource to retrieve other networked resources 'owned' by the parent resource.
This task is most simply managed by using a recursive function (a function which calls itself) to access all the nested resources. Whenever calling recursive functions, always consider: ¹the condition which terminates the recursion; and, ²the likely amount of stack consumed by local variable allocation (including local parameters). If stack overflow is a possibility, then consider allocating variables using the heap within recursive functions.
The function GetNetworkedDrives I've coded below returns into the TStrings parameter a list of all networked (and shared) disk drives. This list is unsorted and includes all locally shared drives. (Excluding locally shared drives can be achieved by using the local computer's name ( see GetComputername() ) to filter the returned strings.)
An example of how to use the function below is: GetNetworkedDrives(Memo1.lines);
Code snippet ...
procedure GetNetworkedDrives( strings: TStrings);
procedure EnumNetworkDrives( pnr : PNetResource);
var
hEnum: THandle;
i, enumRes, count, BufferSize: DWORD;
buffer: pointer;
begin
BufferSize := $4000; //ie: use a 16kb buffer
buffer := nil; //just in case memory allocation fails
if WNetOpenEnum(RESOURCE_GLOBALNET,
RESOURCETYPE_DISK, 0, pnr, hEnum) = ERROR_SUCCESS then
try
GetMem(buffer, BufferSize);
while true do
begin
count := dword(-1); //ie: get as many items possible
enumRes := WNetEnumResource(hEnum,
count, buffer, BufferSize);
//break if either no more items found or an error occurs...
if (enumRes <> ERROR_SUCCESS) then
break;
pnr := buffer; //reuse the pnr pointer
for i := 1 to count do
begin
if (pnr.dwDisplayType =
RESOURCEDISPLAYTYPE_DOMAIN or
RESOURCEDISPLAYTYPE_SERVER) and
(pnr.dwType = RESOURCETYPE_DISK) then
strings.Add(pnr.lpRemoteName);
//recursive function call...
if (pnr.dwUsage and RESOURCEUSAGE_CONTAINER) > 0 then
EnumNetworkDrives(pnr);
inc(longint(pnr),sizeof(TNetResource));
end;
end;
finally
FreeMem(buffer);
WNetCloseEnum(hEnum);
end;
end;
begin
if strings = nil then exit;
//simply call the nested recursive function
//passing nil to starting at the network root ...
EnumNetworkDrives(nil);
end;