• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1274
  • Last Modified:

NetShareAdd: Error handling

Hi,

Running to code below gives me error = 8.
Can anybody tell me what this error means and how it might be solved?
In fact other errors should be handled as well, so at least an informative message can be presented to the user.

I already found some information but it doesn't mention any errorcode.
http://msdn.microsoft.com/en-us/library/bb525384(VS.85).aspx
0
Stef Merlijn
Asked:
Stef Merlijn
  • 16
  • 11
  • 7
  • +1
2 Solutions
 
Stef MerlijnDeveloperAuthor Commented:
And the code of course:
function ShareFolder(vFolder : String) : Boolean;
var Buffer        : TShareInfo;
    Err           : Integer;
    NetName, Path : WideString;
Begin
  NetName                  := 'MyApp';
  Buffer.shi2_NetName      := PWideChar(NetName);
  Buffer.shi2_Type         := STYPE_DISKTREE;
  Buffer.shi2_Remark       := nil;
  Buffer.shi2_Permissions  := ACCESS_ALL; // Alle gebruikers
  Buffer.shi2_MaxUsers     := DWORD(-1);
  Buffer.shi2_Current_Uses := DWORD(-1);
  Path                     := vFolder;
  Buffer.shi2_Path         := PWideChar(Path);
  Buffer.shi2_PassWord     := nil;
    if NetShareAdd(nil, 2, @Buffer, Err) <> 0 then
    begin
      Result := False;
      ShowMessage( 'Error ' + IntToStr(Err) );
    end else
      Result := False;
end;

Open in new window

0
 
aflarinCommented:
here is improved function. run it and let me know about error codes:

function ShareFolder(vFolder : String) : Boolean;
var
  Buffer : TShareInfo;
  Err, ErrField : Integer;
  NetName, Path: WideString;
Begin

  NetName:= 'NetName';
  Buffer.shi2_NetName := PWideChar(NetName);
  Buffer.shi2_Type:= STYPE_DISKTREE;
  Buffer.shi2_Remark:= nil;
  Buffer.shi2_Permissions:= ACCESS_ALL;
  Buffer.shi2_MaxUsers:= DWORD(-1);
  Buffer.shi2_Current_Uses:= DWORD(-1);
  Path:= vFolder;
  Buffer.shi2_Path:= PWideChar(Path);
  Buffer.shi2_PassWord:= nil;

  Err:= NetShareAdd(nil,2,@Buffer, ErrField);
  Result:= Err = 0;
  if not Result then
    ShowMessage( Format('Error %d %d', [Err, ErrField]) );
end;
0
 
epasquierCommented:
Error Code 8
System error code 8 means "Not enough storage is available to process this command."
This error code may also display as "ERROR_NOT_ENOUGH_MEMORY" or as the value 0x8.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
epasquierCommented:
oh, but when you say you get an error = 8 , you might be talking about the last parameter, not the function result (as Aflarin has modified the code to display it).

If that is the case, you are mistaken about the signification of this last parameter :


parm_err [out] :
Pointer to a value that receives the index of the first member of the share information structure that causes the ERROR_INVALID_PARAMETER error. If this parameter is NULL, the index is not returned on error. For more information, see the NetShareSetInfo function.

=> I am not sure about the index thing, but it might be the password that is not correct. Have you tried with and empty string instead of nil ?

Buffer.shi2_PassWord:= '';
0
 
aflarinCommented:
> Error Code 8

No, it isn't the error code.
In the initial function the error code indicates the field of structure where the error happens.

It seems the error code is ERROR_INVALID_PARAMETER and the problem parameter is shi2_PassWord
0
 
Stef MerlijnDeveloperAuthor Commented:
Your improved version gives error: 123 8
Which is not much better... :-)
Getting this error seems a bit strange as there is more then plenty storage and memory on my computer.
Bye the way I try to share folder:
C:\Documents and Settings\All Users\Documenten\MyAppName

0
 
epasquierCommented:
ok, no,  8 is this parameter :
#define SHARE_PATH_PARMNUM 8

your path is incorrect
0
 
Stef MerlijnDeveloperAuthor Commented:
When I try to share the same folder from within Windows Explorer, I get the message that there is already a share available with the same ShareName (NetName). In my case "MyApp"
So I need to remove the old share first.
0
 
epasquierCommented:
that confirms it :
Windows Error Message 123: 'ERROR_INVALID_NAME'
0
 
Stef MerlijnDeveloperAuthor Commented:
So I need some function that will remove a share by it's name (if it exists).
My Application will then have one share assigned to it (to it's base-folder).
Moving the base-folder will delete the share of the old base-folder and create a new share for the newly assigned base-folder.
0
 
aflarinCommented:
Epasquier is right, it means you already have a share with the same name
0
 
aflarinCommented:
I've improved the function:
  - it shows the text error message now
  - it takes ShareName as param
  - changed params to const to improve perfomance

function GetWin32ErrorString(ErrorCode: Integer): string;
var
  Len: Integer;
  Buffer: array[0..255] of Char;
begin
  Len := FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM or
    FORMAT_MESSAGE_ARGUMENT_ARRAY, nil, ErrorCode, 0, Buffer,
    SizeOf(Buffer), nil);
  while (Len > 0) and (Buffer[Len - 1] in [#0..#32, '.']) do Dec(Len);
  SetString(Result, Buffer, Len);
end;


function ShareFolder(const AFolder, AShareName: String) : Boolean;
var
  Buffer : TShareInfo;
  Err, ErrField : Integer;
  NetName, Path: WideString;
Begin
  NetName:= AShareName;
  Buffer.shi2_NetName := PWideChar(NetName);
  Buffer.shi2_Type:= STYPE_DISKTREE;
  Buffer.shi2_Remark:= nil;
  Buffer.shi2_Permissions:= ACCESS_ALL;
  Buffer.shi2_MaxUsers:= DWORD(-1);
  Buffer.shi2_Current_Uses:= DWORD(-1);
  Path:= AFolder;
  Buffer.shi2_Path:= PWideChar(Path);
  Buffer.shi2_PassWord:= nil;

  Err:= NetShareAdd(nil,2,@Buffer, ErrField);
  Result:= Err = 0;
  if not Result then
    ShowMessage( Format('Error %d: %s'#13#10'Param index - %d', [Err, GetWin32ErrorString(Err), ErrField]) );
end;

Using

procedure TForm1.Button1Click(Sender: TObject);
Begin
  ShareFolder( 'C:\Documents and Settings\All Users\Documents\Test', 'MyShareName' );
end;
0
 
Stef MerlijnDeveloperAuthor Commented:
Yes.
Asuming that my application generates some unique sharename, It should never be created twice. So if it already exists as a sharename, then the old share can be removed and the new share can be created/added.
Do you agree with this?

Then there is the issue about how to remove the old share?
If a sharename is already present and it's NOT covering the sharing of the new base-Folder, then it must be removed so a new share can be created with the same name.
This also elliminates the problem of having multiple shares that aren't used anymore, but still give full access to all users.
0
 
epasquierCommented:
this code works for me.
I added a parameter for the Share Name, and the display of a text message corresponding to the error you get if it fails.
but otherwise it is quite the same.

If you still have errors, then you have a problem that is not from the code. I hope the clear message will help you.
Type
  TShareInfo = record
     shi2_netname: LPWSTR;
     shi2_type: DWORD;
     shi2_remark: LPWSTR;
     shi2_permissions: DWORD;
     shi2_MaxUsers: DWORD;
     shi2_current_uses: DWORD;
     shi2_path: LPWSTR;
     shi2_PassWord: LPWSTR;
  end;
  pShareInfo=^TShareInfo;

const
 STYPE_DISKTREE = 0;
 STYPE_PRINTQ = 1;
 STYPE_DEVICE = 2;
 STYPE_IPC = 3;
 STYPE_DFS = 100;
 STYPE_SPECIAL = $80000000;
 
 ACCESS_NONE = 0;
 ACCESS_READ  = 1;
 ACCESS_WRITE = 2;
 ACCESS_CREATE = 4;
 ACCESS_EXEC = 8;
 ACCESS_DELETE = 16;
 ACCESS_ATRIB = 32;
 ACCESS_PERM = 64;
 ACCESS_ALL = (ACCESS_READ+ACCESS_WRITE+ACCESS_CREATE+ACCESS_EXEC+ACCESS_DELETE+ACCESS_ATRIB+ACCESS_PERM);

function NetShareAdd(servername: LPWSTR;
    level: DWORD;
    buf: pShareInfo;
    parm_err: LPDWORD):LongWord; stdcall; external 'netapi32.dll';
 
function ShareFolder(vFolder : String; ShareName:String) : Boolean;
var Buffer        : TShareInfo;
    Err           : Integer;
    NetName, Path : WideString;
Begin
  NetName                  := ShareName;
  Buffer.shi2_NetName      := PWideChar(NetName);
  Buffer.shi2_Type         := STYPE_DISKTREE;
  Buffer.shi2_Remark       := nil;
  Buffer.shi2_Permissions  := ACCESS_ALL;
  Buffer.shi2_MaxUsers     := DWORD(-1);
  Buffer.shi2_Current_Uses := DWORD(-1);
  Path                     := vFolder;
  Buffer.shi2_Path         := PWideChar(Path);
  Buffer.shi2_PassWord     := nil;
  if NetShareAdd(nil, 2, @Buffer, @Err) <> 0 then
   begin
    Result := False;
    ShowMessage(SysErrorMessage(GetLastError));
   end else Result := True;
end;

Open in new window

0
 
epasquierCommented:
If the path is already shared with a different name, the old one is replaced by the new one with this function, not even generating an error. At least in my system, Vista 64
0
 
Stef MerlijnDeveloperAuthor Commented:
I changed some code I got from aflarin in a previous post.
I just need to have some code to delete the old share.
function IsFolderShared(vServer, vFolder, vUniqueSharename : String) : Boolean;
var  p                      : PShareInfo502Array;
     res, er, tr, resume, i : DWORD;
     szServer, line         :      String;
     lpwszServer            : Array [0..255] of WideChar;
     pwszServer             : PWideChar;
begin
  Result := False;
  er:=0;
  tr:=0;
  resume:=0;
  szServer:= vServer;  // ComputerName
  // 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;
  // 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;
      for i := 1 to Pred(er) do
      begin
        // Check is sharename is used already
        // and if so: Does is cover sharing of vFolder
        if (AnsiCompareText(WideCharToString(p^[i].shi502_netname), vUniqueSharename) = 0) then
        begin
          if NOT (AnsiPos(WideCharToString(p^[i].shi502_path), vFolder) > 0) then
          begin
            // Sharename exists and must be removed first
            showMessage('Sharename already exists');

            DeleteShareByName; // HOW TO DO THIS???

          end;
        end;
        if (AnsiPos(WideCharToString(p^[i].shi502_path), vFolder) > 0) AND
           NOT (AnsiPos('$', WideCharToString(p^[i].shi502_netname)) > 0)  then
        begin
          // Folder is shared already (by any available share)
          Result := True;
        end;
      end;
      // Free the allocated buffer.
      NetApiBufferFree(p);
    end;
  until (res <> ERROR_MORE_DATA); // Continue to call NetShareEnum while there are more entries.
end;

Open in new window

0
 
aflarinCommented:
>> Do you agree with this?

You can just enumerate all shares (NetShareEnum function from your previous question) and find if the share with the same Local Path already exist

>> Then there is the issue about how to remove the old share?

It's NetShareDel, I already posted this link and you already checked it :)
http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_23470466.html
0
 
Stef MerlijnDeveloperAuthor Commented:
Removing the old share was already present indeed. I got too many lines of code in my project and sometimes forget what I have already.... :-)
0
 
Stef MerlijnDeveloperAuthor Commented:
The code works fine except when I try sharing the following folder (which I actually want to share): C:\Documents and Settings\All Users\Documenten\MyAppName

Here I get error:

using: ShowMessage(SysErrorMessage(GetLastError));
=> Overlapping I/O is executed
using: ShowMessage( Format('Error %d: %s'#13#10'Param index - %d', [Err, GetWin32ErrorString(Err), ErrField]) );
Error 123: Syntaxt of filename, foldername ot volumename is incorrect. Param index - 8
0
 
aflarinCommented:
>> using: ShowMessage(SysErrorMessage(GetLastError));
>> => Overlapping I/O is executed

It seems it's not a correct message. I think GetLastError returns error from other function, not NetShareAdd.

>> Error 123: Syntaxt of filename, foldername ot volumename is incorrect. Param index - 8

It's the same error as in your first post - 123 8
Try to create share in Explorer, it seems you already have the same share name
0
 
systanCommented:
Why not do like this;
function ReShareFolder(const AFolder, AShareName: String) : Boolean;
var
  Buffer : TShareInfo;
  Err, ErrField : Integer;
  NetName, Path: WideString;
  NameNT : PWChar;
  Size : Integer;
Begin
  NetName:= AShareName;
  Buffer.shi2_NetName := PWideChar(NetName);
  Buffer.shi2_Type:= STYPE_DISKTREE;
  Buffer.shi2_Remark:= nil;
  Buffer.shi2_Permissions:= ACCESS_ALL;
  Buffer.shi2_MaxUsers:= DWORD(-1);
  Buffer.shi2_Current_Uses:= DWORD(-1);
  Path:= AFolder;
  Buffer.shi2_Path:= PWideChar(Path);
  Buffer.shi2_PassWord:= nil;

  Err:= NetShareAdd(nil,2,@Buffer, ErrField);
  Result:= Err = 0;
  if not Result then
    begin
    Size := SizeOf(WideChar)*256;
    GetMem(NameNT,Size);
    StringToWideChar(AShareName,NameNT,Size);
    NetShareDel(nil,NameNT,0);
    ReShareFolder(AFolder, AShareName);
  end;
end;

procedure TForm1.ButtonXClick(Sender: TObject);
begin
  ReShareFolder('C:\Documents and Settings\All Users\Documenten\MyAppName', 'TestX' );
end;

Open in new window

0
 
aflarinCommented:
Hm. when I try to create share with existing share name, it returns
2118: The name has already been shared. Param index - 0
0
 
epasquierCommented:
Really, that is not a problem with sharing a folder that is already shared, as in this case IT IS JUST REPLACED.

Are you sure you can share the folder you want using windows explorer ?
0
 
Stef MerlijnDeveloperAuthor Commented:
epasquier:
Yes I can share the folder in Windows Explorer.
The folder nor the drivepath are shared. Only the default admninistrative share "C$" is available. When I select the same folder in my aplication, then it gives the mentioned error (even with a completely unique sharename).
systan:
I believe your code could result in an endless loop. If for some other reason, than a duplicate sharename, the share can't be created.
0
 
aflarinCommented:
are you still sharing a folder on a local machine?

My function from http:#33556764 creates a share fine. did you still use it?

If you modified it, please show the code. There may be a problem there.


0
 
systanCommented:
>>I believe your code could result in an endless loop. If for some other reason, than a duplicate sharename, the share can't be created.

huh, I tested it many times.  Even I clicked the button for many times it wont error.
0
 
Stef MerlijnDeveloperAuthor Commented:
aflarin:
Yes I still use that function

systan:
I believe it won't error because the only error you trap is an existing share. But if in any case a different error occurs then it would loop (in my homble opinion)
0
 
aflarinCommented:
Could you show how you are using it?

1. Delphi version. Don't think it may be cause, because I checked on D7 and D2009
2. OS version
3. ShareName and Folder params. Maybe there is a typo there



0
 
Stef MerlijnDeveloperAuthor Commented:
vFolder:
\\COMPUTERNAME\C$\Documents and Settings\All Users\Documenten\MyAppName
vSharename:
"MyApp"

function DelenMapStarten(vFolder, vShareName : String) : Boolean;
var Buffer        : TShareInfo;
    Err, ErrField : Integer;
    NetName, Path : WideString;
Begin
  NetName                  := vShareName;
  Buffer.shi2_NetName      := PWideChar(NetName);
  Buffer.shi2_Type         := STYPE_DISKTREE;
  Buffer.shi2_Remark       := nil;
  Buffer.shi2_Permissions  := ACCESS_ALL; // Alle gebruikers
  Buffer.shi2_MaxUsers     := DWORD(-1);
  Buffer.shi2_Current_Uses := DWORD(-1);
  Path                     := vFolder;
  Buffer.shi2_Path         := PWideChar(Path);
  Buffer.shi2_PassWord     := nil;
  Err:= NetShareAdd(nil, 2, @Buffer, ErrField);
  Result:= (Err = 0);
  if NOT Result then
  begin
    ShowMessage( Format('Error %d: %s'#13#10'Param index - %d', [Err, GetWin32ErrorString(Err), ErrField]) );
  end;
end;

Open in new window

0
 
aflarinCommented:
>> vFolder:
>> \\COMPUTERNAME\C$\Documents and Settings\All Users\Documenten\MyAppName

That's it. You have to use only local path!

C:\Documents and Settings\All Users\Documenten\MyAppName

If you are trying to create share on other PC, you have to use the first param of NetShareAdd
0
 
Stef MerlijnDeveloperAuthor Commented:
Can I use the first param of NetShareAdd even when I'm on a local computer?
That would make things a lot easier for me, as I store the UNC-path in the database (because an other user in the network needs to be pointed to the same folder on the server)..
0
 
aflarinCommented:
>> Can I use the first param of NetShareAdd even when I'm on a local computer?

I think you can, but it isn't a good idea. Why?

1. At the first you have to extract Server name and Local Path from UNC in any event. (Because server name is the first param on NetShareAdd and the local path is the shi2_Path of structure.

2. At the second... I'm not sure how Windows handles if you are using server name param on local machine. It should be ok, but... I don't like a risk in such cases
0
 
Stef MerlijnDeveloperAuthor Commented:
In my database I store two paths:
  1. Base-folder
  2. Templates-folder
Both are always located on the server.
Currently these paths are stored as UNCpath.
So I need to translate the UNC-path back to a local path in order to check for shares.
Can this be done easily?
Or else I need to do a reset of these paths, so the user can select them again. And then store it as local filepaths in the database?
 
0
 
Stef MerlijnDeveloperAuthor Commented:
You can forget the last conversion question of the UNC-path.
Got that covered.
0
 
Stef MerlijnDeveloperAuthor Commented:
Thank you all.
aflarin has posted the first solution that supplies a informative errormessage and also came up with the cause of the error while sharing a folder (=> don't use a UNCpath locally)
0
 
systanCommented:
I know it is already closed, but this can help you.

Here's the code to correct the  <vFolder>  even if includes the UNC path and even if it is already shared AND even if you don't issue a  <vSharename>.

What do you think?
function ReShareFolder(AFolder:String) : Boolean;
var
  Buffer : TShareInfo;
  Err, ErrField : Integer;
  NetName, Path: WideString;
  NameNT : PWChar;
  Size : Integer;
  AShareName: String;
Begin
  AShareName := AFolder;
  size := pos('$',Afolder);
  if size>0 then
  begin
  AFolder := copy(AFolder,size-1, length(AFolder)-(size-2));
  AFolder := StringReplace(AFolder, '$', ':',[rfReplaceAll, rfIgnoreCase]);
  end;

  repeat
  size := pos('\',AShareName);
  AShareName := copy(AShareName,size+1,length(AShareName)-size);
  until size=0;

  NetName:= AShareName;
  Buffer.shi2_NetName := PWideChar(NetName);
  Buffer.shi2_Type:= STYPE_DISKTREE;
  Buffer.shi2_Remark:= nil;
  Buffer.shi2_Permissions:= ACCESS_ALL;
  Buffer.shi2_MaxUsers:= DWORD(-1);
  Buffer.shi2_Current_Uses:= DWORD(-1);
  Path:= AFolder;
  Buffer.shi2_Path:= PWideChar(Path);
  Buffer.shi2_PassWord:= nil;

  Err:= NetShareAdd(nil,2,@Buffer, ErrField);
  Result:= Err = 0;
  if not Result then
    begin
    Size := SizeOf(WideChar)*256;
    GetMem(NameNT,Size);
    StringToWideChar(AShareName,NameNT,Size);
    NetShareDel(nil,NameNT,0);
    ReShareFolder(AFolder);
  end;
end;

Open in new window

0
 
systanCommented:
>>So I need to translate the UNC-path back to a local path in order to check for shares.
Thats the answer of your need, what do you think?
0
 
Stef MerlijnDeveloperAuthor Commented:
It's worth testing, but for now I got all the basics covered.
The thing you do with AFolder to get the local path is something I do, but then before I go into this functies.
For the rest your function look good.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 16
  • 11
  • 7
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now