February 2012
    Get Version

January 2007
    Bezier Text

December 2005
    Rotated Ellipses

December 2004
    PDF Page Count

January 2003
    Boolean Blues

March 2002
» Networked Drives

January 2002
    Treeview Troubles
    Appending to Exe's



Freeware Components
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;

Copyright © 2002-2006 Angus Johnson