Solved

NetShareEnum in delphi

Posted on 2004-10-27
1,612 Views
Last Modified: 2008-01-09
Im trying to list all shares on a REMOTE machine (this includes hidden shares such as c$), can someone please advise me on how to do this in full-working code?
0
Question by:robbiegrove
    6 Comments
     
    LVL 12

    Expert Comment

    by:Ivanov_G
    I think NetShareEnum is wrong starting point. You need WNetEnumResource for network shares

    http://www.delphiworld.narod.ru/base/enum_net_connections.html
    0
     

    Author Comment

    by:robbiegrove
    im 90% sure WNetEnumResource is for LOCAL shares..
    I have used NetShareEnum in C before and it IS what iam after, however i had alot of trouble trying to port it to delphi.
    0
     
    LVL 26

    Accepted Solution

    by:
    Just to clarify:

    1.) NetShareEnum is not the wrong starting point; it can return hidden shares where WNetEnumResource cant.
    2.) WNetEnumResource CAN be used to get remote resource location; it just can't get the hidden shares.

    Here is an msdn example translated to delphi, just compile it as a console app, run it, and enter the server name. note: PLEASE make sure you have permissions to the server before saying it does not work.

    Regards,
    Russell

    ----

    program netenum;
    {$APPTYPE CONSOLE}

    uses
      Windows,
      SysUtils,
      Classes;

    type
      _SHARE_INFO_502         =  packed record
         shi502_netname:      PWideChar;
         shi502_type:         DWORD;
         shi502_remark:       PWideChar;
         shi502_permissions:  DWORD;
         shi502_max_uses:     DWORD;
         shi502_current_uses: DWORD;
         shi502_path:         LPWSTR;
         shi502_passwd:       LPWSTR;
         shi502_reserved:     DWORD;
         shi502_security_dsc: PSECURITY_DESCRIPTOR;
      end;
      SHARE_INFO_502          =  _SHARE_INFO_502;
      PSHARE_INFO_502         =  ^SHARE_INFO_502;
      LPSHARE_INFO_502        =  PSHARE_INFO_502;
      TShareInfo502           =  SHARE_INFO_502;
      PShareInfo502           =  PSHARE_INFO_502;

    type
      TShareInfo502Array      =  Array [0..MaxWord] of TShareInfo502;
      PShareInfo502Array      =  ^TShareInfo502Array;

    function   NetApiBufferFree(buffer: Pointer): DWORD; stdcall; external 'netapi32.dll';
    function   NetShareEnum(servername: PWideChar;
                            level: DWORD;
                            bufptr: PByteArray;
                            prefmaxlen: DWORD;
                            entriesread: PDWORD;
                            totalentries: PDWORD;
                            resume_handle: PDWORD): DWORD; stdcall; external 'netapi32.dll';


    var
      p:             PShareInfo502Array;
      res,
      er, tr,
      resume,
      i:             DWORD;
      szServer:      String;
      lpwszServer:   Array [0..255] of WideChar;
      pwszServer:    PWideChar;

    begin

       er:=0;
       tr:=0;
       resume:=0;

       // Flush input on console
       FlushConsoleInputBuffer(GetStdhandle(STD_INPUT_HANDLE));

       // Get the server
       Write('Enter server name: ');
       ReadLn(szServer);

       // Check parameter
       if (Length(szServer) = 0) then
         pwszServer:=nil
       else
       begin
         // Make sure the server starts with a \\
         if (Pos('\\', szServer) <> 1) then szServer:='\\'+szServer;
         StringToWideChar(szServer, @lpwszServer, SizeOf(lpwszServer));
         pwszServer:=@lpwszServer;
       end;

       // Print a report header.
       WriteLn('Share:              Local Path:                   Uses:   Descriptor:');
       WriteLn('---------------------------------------------------------------------');

       // Call the NetShareEnum function; specify level 502.
       repeat
         res:=NetShareEnum(pwszServer, 502, @p, DWORD(-1), @er, @tr, @resume);
         // If the call succeeds
         if (res = ERROR_SUCCESS) or (res = ERROR_MORE_DATA) then
         begin
            // Loop through the entries;
            // print retrieved data.
            for i:=1 to Pred(er) do
            begin
               Write(Format('%-20s%-30s%-0.8d', [WideCharToString(p^[i].shi502_netname),
                       WideCharToString(p^[i].shi502_path), p^[i].shi502_current_uses]));
               //
               //  Validate the value of the
               //  shi502_security_descriptor member.
               //
               if IsValidSecurityDescriptor(p^[i].shi502_security_dsc) then
                   WriteLn('Yes')
                else
                   WriteLn('No');
            end;
            //
            // Free the allocated buffer.
            //
            NetApiBufferFree(p);
         end
         else
             WriteLn('Error: ', res);

         // Continue to call NetShareEnum while
         //  there are more entries.

       until (res <> ERROR_MORE_DATA);

       // Pause
       ReadLn;

    end.

    0
     
    LVL 17

    Expert Comment

    by:Wim ten Brink
    program WMI;

    {$APPTYPE CONSOLE}

    uses Windows, SysUtils, Classes, ActiveX, Variants, WbemScripting_TLB;

    function NextItem(var Enum: IEnumVARIANT; const riid: TGUID; out ppObject): Boolean;
    var
      OleProperty: OleVariant;
      NumProp: LongWord;
    begin
      try
        Result := Succeeded(Enum.Next(1, OleProperty, NumProp)) and (NumProp > 0) and Succeeded(IDispatch(OleProperty).QueryInterface(riid, ppObject));
      except
        Result := False;
        IUnknown(ppObject) := nil;
      end;
    end;

    procedure RunMe;
    const
      sQuery = 'select * from Win32_Share';
    var
      Enum: IEnumVariant;
      Item: SWbemObject;
      Lines: TStringList;
      Locator: SWbemLocator;
      MachineName: string;
      ObjectSet: SWbemObjectSet;
      Prop: SWbemProperty;
      PropEnum: IEnumVariant;
      Services: SWbemServices;
    begin
      Lines := TStringList.Create;
      MachineName := 'Knight'; // Name of machine that needs to be enumerated.
      try
        Locator := CoSWbemLocator.Create;
        Services := Locator.ConnectServer(MachineName, 'root\cimv2', '', '', '', '', 0, nil);
        ObjectSet := Services.ExecQuery(sQuery, 'WQL', wbemFlagBidirectional, nil);
        Enum := ObjectSet._NewEnum as IEnumVariant;
        while NextItem(Enum, SWBemObject, Item) do begin
          Lines.Add(Item.Path_.Path);
          PropEnum := Item.Properties_._NewEnum as IEnumVariant;
          while NextItem(PropEnum, SWBemProperty, Prop) do begin
            Lines.Add(Format('+ %s: %s = %s', [Prop.Name, VarTypeAsText(VarType(Prop.Get_Value)), Trim(VarToStrDef(Prop.Get_Value, '<Error>'))]));
          end;
          Lines.Add('');
        end;
      except on E: Exception do Lines.Add(E.Message);
      end;
      Write(Lines.Text);
      Lines.Free;
    end;

    begin
      if Assigned(InitProc) then TProcedure(InitProc);
      RunMe;
      Write('Press <Enter> to quit');
      ReadLn;
    end.

    See http://www.workshop-alex.org/Sources/WbemScripting_TLB/WbemScripting_TLB.html or http://www.workshop-alex.org/Sources/WbemScripting_TLB/WbemScripting_TLB.pas for the WMI unit used in above code. This version is optimized for Delphi 7.

    Yeah, well. I'm using WMI to access the share information, which is the easiest way to enumerate shares on a REMOTE system. All you need to provide is the right machine name, which in my case is "Knight".
    Since this is a console application, I needed to initialize the COM system by calling InitProc. The use of WMI can be a lot easier than the use of some obscure API functions. ;-)
    0
     

    Author Comment

    by:robbiegrove
    Thanks rllibby helped ALOT! almost exactly what i was looking for :D

    Sorry Workshop_alex, just wanted to know how to use NetShareEnum in delphi.
    Probably should have made that more clear.. Is there a way i can accept your answer aswell tho?
    0
     
    LVL 17

    Expert Comment

    by:Wim ten Brink
    Don't worry, robbie... I just added my answer to show there are some other ways to get information too. Many people are afraid to use WMI in the first place since they think it's complex... Well, they are right of course but hey, if you learn fast you'll learn to use it fast too. :-)
    0

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone. Privacy Policy Terms of Use

    Featured Post

    Highfive Gives IT Their Time Back

    Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

    Suggested Solutions

    The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
    In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
    This video Micro Tutorial is the first in a two-part series that shows how to create and use custom scanning profiles in Nuance's PaperPort 14.5 (http://www.experts-exchange.com/articles/17490/). But the ability to create custom scanning profiles al…
    This video is in connection to the article "The case of a missing mobile phone (https://www.experts-exchange.com/articles/28474/The-Case-of-a-Missing-Mobile-Phone.html)". It will help one to understand clearly the steps to track a lost android phone.

    875 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    14 Experts available now in Live!

    Get 1:1 Help Now