I already tryed to put the procedure and declared like external and
everthing but my other unit doesnt see my new procedure !
Can someone help me to implement that ?
Thank a lote,
Diego.
>I need to implement the NetShareAdd procedure from the windows api into my
>unit windows,
>but it doesnt work ...
>
>I already tryed to put the procedure and declared like external and
>everthing but my other unit doesnt see my new procedure !
Did you add the unit in which you put the external declaration to the
"uses" clause where you reference it?
Good luck.
Kurt
So I change it to another unit but know I'm getting some other probs cuz I
dont understand so much how to work with packed records to implement the
functions !
Can you give me a hand ?
I need to implement this api function
NetShareAdd( LPWSTR servername, DWORD level, LPBYTE buf, LPDWORD
parm_err);
Can you give me some tips ?
Thanks a lote,
Diego.
Without return type, the declaration is obviously incomplete.
NET_API_STATUS NetShareAdd(
LPWSTR servername,
DWORD level,
LPBYTE buf,
LPDWORD parm_err
);
Translated to Delphi, you got something like this:
// Declaration
function NetShareAdd( servername : PWideChar; // LPWSTR
level : DWORD; pShareInfo : Pointer; var parm_err : DWORD
) : NET_API_STATUS; stdcall;
// Implementation
function NetShareAdd; external 'netapi32.dll' name 'NetShareAddA';
NET_API_STATUS is simply a DWORD type. You will need SHARE_INFO_2 and/or
SHARE_INFO_502 in order to use this API:
type SHARE_INFO_2 = record
shi2_netname : PWideChar; // LPWSTR
shi2_type : DWORD;
shi2_remark : PWideChar; // LPWSTR
shi2_permissions : DWORD;
shi2_max_uses : DWORD;
shi2_current_uses : DWORD;
shi2_path : PWideChar; // LPWSTR
shi2_passwd : PWideChar; // LPWSTR
end;
SHARE_INFO_502 can be translated analogously.
HTH
JensG
JensG
Should be
external 'netapi32.dll' name 'NetShareAdd';
without the "A"
JensG
NET_API_STATUS res;
SHARE_INFO_2 p;
DWORD parm_err = 0;
//
// Fill in the SHARE_INFO_2 structure.
//
p.shi2_netname = TEXT("TESTSHARE");
p.shi2_type = STYPE_DISKTREE; // disk drive
p.shi2_remark = TEXT("TESTSHARE to test NetShareAdd");
p.shi2_permissions = 0;
p.shi2_max_uses = 4;
p.shi2_current_uses = 0;
p.shi2_path = TEXT("C:\\");
p.shi2_passwd = NULL; // no password
//
// Call the NetShareAdd function,
// specifying level 2.
//
res=NetShareAdd(null, 2, (LPBYTE) &p, &parm_err);
//
// If the call succeeds, inform the user.
//
if(res==0)
printf("Share created.\n");
// Otherwise, print an error,
// and identify the parameter in error.
//
else
printf("Error: %u\tparmerr=%u\n", res, parm_err);
return;
in Delphi it should be like that
var
res : NET_API_STATUS;
p: SHARE_INFO_2;
parm_err :DWORD;
parm_err := 0;
p.shi2_netname := 'TESTSHARE';
p.shi2_type := STYPE_DISKTREE; // What is this ? should I made some
constants in my unit ? whit the types ?
p.shi2_remark := 'TESTSHARE to test NetShareAdd';
p.shi2_permissions := 0;
p.shi2_max_uses := 4;
p.shi2_current_uses := 0;
p.shi2_path := TEXT('C:\\');
p.shi2_passwd := NIL;
// How should I translate this line ?
res=NetShareAdd(nil 2, (LPBYTE) &p, &parm_err);
if res=0 then
showmessage('Share created')
else
begin
Showmessage('Error: ');
Exit;
end;
result := true;
can you give me a hand ?
Thanks a lote,
Diego.
This is my code.
onClick
var
v_p : SHARE_INFO_2;
v_parm :DWORD;
begin
CreateDirectory('C:\testess',nil);
v_p.shi2_netname := 'testess';
v_p.shi2_type := STYPE_DISKTREE;
v_p.shi2_remark := 'TESTSHARE to test NetSha';
v_p.shi2_permissions := 0;
v_p.shi2_max_uses := 4;
v_p.shi2_current_uses:= 0;
v_p.shi2_path := 'C:\testes';
v_p.shi2_passwd := nil;
v_parm := 0;
NetShareAdd(nil,2,v_p,v_parm);
End button click
Begin unit u_apifunctions
unit u_apifunctions;
interface
uses Windows;
const
STYPE_DISKTREE = 1;
STYPE_PRINTQ = 2;
STYPE_DEVICE = 3;
STYPE_IPC = 4;
STYPE_SPECIAL = 5;
STYPE_TEMPORARY= 6;
type
SHARE_INFO_2 = record
shi2_netname:PWideChar;
shi2_type:DWORD;
shi2_remark:PWideChar;
shi2_permissions:DWORD;
shi2_max_uses:DWORD;
shi2_current_uses:DWORD;
shi2_path:PWideChar;
shi2_passwd:PWideChar;
end;
TSHARE_INFO_2 = SHARE_INFO_2;
{$EXTERNALSYM SHARE_INFO_2}
NET_API_STATUS = DWORD;
function NetShareAdd( servername : PWideChar; level : DWORD; pShareInfo
: SHARE_INFO_2; var parm_err : DWORD): NET_API_STATUS; stdcall;
{$EXTERNALSYM NetShareAdd}
implementation
function NetShareAdd; external 'netapi32.dll' name 'NetShareAdd';
end.
I suggest that...
The JEDI -> JCL library (Lm.pas) already has the 'Netshare*' routines
implemented. As the source is provided, it is an incredibly useful resource
of working delphi code.
> Jens I've maded some changes know it compiles but I got an error ..
The changes caused the error ;-)
And also there were wrong constant values.
const
// these are wrong values, do not use! see below
STYPE_DISKTREE = 1;
STYPE_PRINTQ = 2;
STYPE_DEVICE = 3;
STYPE_IPC = 4;
STYPE_SPECIAL = 5;
STYPE_TEMPORARY= 6;
I made a short sample program from it, renamed some vars, added some
constants from the PSDK header files and on my win2000 it runs now
perfectly.
<code>
program sample;
uses Windows, sysutils;
type
SHARE_INFO_2 = record
shi2_netname : PWideChar;
shi2_type : DWORD;
shi2_remark : PWideChar;
shi2_permissions : DWORD;
shi2_max_uses : DWORD;
shi2_current_uses : DWORD;
shi2_path : PWideChar;
shi2_passwd : PWideChar;
end;
TSHARE_INFO_2 = SHARE_INFO_2;
{$EXTERNALSYM SHARE_INFO_2}
NET_API_STATUS = DWORD;
const
NERR_BASE = 2100;
NERR_RedirectedPath = NERR_BASE+17; //* The operation is invalid on a
redirected resource. */
NERR_DuplicateShare = NERR_BASE+18; //* The name has already been
shared. */
NERR_UnknownDevDir = NERR_BASE+16; //* The device or directory does
not exist. */
ACCESS_READ = $01;
ACCESS_WRITE = $02;
ACCESS_CREATE = $04;
ACCESS_EXEC = $08;
ACCESS_DELETE = $10;
ACCESS_ATRIB = $20;
ACCESS_PERM = $40;
// Share types (shi1_type and shi2_type fields).
STYPE_DISKTREE = 0;
STYPE_PRINTQ = 1;
STYPE_DEVICE = 2;
STYPE_IPC = 3;
//
STYPE_TEMPORARY = $40000000;
STYPE_SPECIAL = $80000000;
//
SHI_USES_UNLIMITED = DWORD(-1);
function NetShareAdd( servername : PWideChar;
level : DWORD;
pShareInfo : Pointer; // not SHARE_INFO_2;
var parm_err : DWORD): NET_API_STATUS; stdcall;
external 'netapi32.dll' name 'NetShareAdd';
{$EXTERNALSYM NetShareAdd}
var
share2 : SHARE_INFO_2;
dwErr :DWORD;
status : NET_API_STATUS;
sMsg : string;
begin
with share2 do begin
shi2_netname := 'testess';
shi2_type := STYPE_DISKTREE;
shi2_remark := 'TESTSHARE to test NetSha';
shi2_permissions := ACCESS_READ;
shi2_max_uses := 4;
shi2_current_uses:= 0;
shi2_path := 'C:\temp';
shi2_passwd := nil;
end;
dwErr := 0;
{ Security Requirements
Only members of the Administrators or Account Operators local group or
those with Communication, Print, or Server operator group membership
can
successfully execute NetShareAdd. The Print operator can add only
Printer
queues. The Communication operator can add only communication-device
queues.
}
status := NetShareAdd( nil,2, @share2, dwErr);
case status of
ERROR_SUCCESS : sMsg := 'Successful';
ERROR_ACCESS_DENIED : sMsg := 'The user does not have access to the
requested information.';
ERROR_INVALID_LEVEL : sMsg := 'The value specified for the Level
parameter is invalid.';
ERROR_INVALID_NAME : sMsg := 'The character or file system name is
invalid.';
ERROR_INVALID_PARAMETER : sMsg := 'The specified parameter number
'+IntToStr(Integer(dwErr))+' is invalid.';
NERR_DuplicateShare : sMsg := 'The sharename is already in use on this
server.';
NERR_RedirectedPath : sMsg := 'The operation is invalid for a
redirected resource. The specified device name is assigned to a shared
resource.';
NERR_UnknownDevDir : sMsg := 'The device or directory does not exist.';
else
sMsg := 'NET_API_STATUS code
'+IntToStr(Integer(status))+#10+SysErrorMessage(status);
end;
if sMsg <> '' then MessageBox(0,PChar(sMsg),'NetShareAdd',0);
end.
</code>
JensG
I was searching for that values but I couldnt find so I was trying to put
some values that came on my mind :)
So I was testing on Windows Xp works nice and on 2000 to so I've read some
of microsoft documentation about how to run it on w98 and it says that you
should use the NetShareAdd from the svrapi.dll and should use the level 50
instead 2 and should use the SHARE_INFO_50 instead SHARE_INFO_2 so I've
Created another function that is called
NetShareAddW9x( servername : PWideChar; level : DWORD; pShareInfo :
Pointer; var parm_err : DWORD): NET_API_STATUS; stdcall;
so created the type SHARE_INFO_50, but I dont know if the types are write
since some of those I dont know so much !
so here is my code:
unit u_apifunctions;
interface
uses Windows;
const
NERR_BASE = 2100;
NERR_RedirectedPath = NERR_BASE+17;
NERR_DuplicateShare = NERR_BASE+18;
NERR_UnknownDevDir = NERR_BASE+16;
ACCESS_READ = $01;
ACCESS_WRITE = $02;
ACCESS_CREATE = $04;
ACCESS_EXEC = $08;
ACCESS_DELETE = $10;
ACCESS_ATRIB = $20;
ACCESS_PERM = $40;
STYPE_DISKTREE = 0;
STYPE_PRINTQ = 1;
STYPE_DEVICE = 2;
STYPE_IPC = 3;
STYPE_TEMPORARY = $40000000;
STYPE_SPECIAL = $80000000;
SHI_USES_UNLIMITED = DWORD(-1);
SHI50F_RDONLY = $01; SHI50F_FULL = $02;
SHI50F_ACCESSMASK = SHI50F_RDONLY+SHI50F_FULL;
SHI50F_PERSIST = $100; SHI50F_SYSTEM = $200;
type
SHARE_INFO_2 = record
shi2_netname:PWideChar;
shi2_type:DWORD;
shi2_remark:PWideChar;
shi2_permissions:DWORD;
shi2_max_uses:DWORD;
shi2_current_uses:DWORD;
shi2_path:PWideChar;
shi2_passwd:PWideChar;
end;
TSHARE_INFO_2 = SHARE_INFO_2;
{$EXTERNALSYM SHARE_INFO_2}
NET_API_STATUS = DWORD;
type
SHARE_INFO_50 = record
shi50_netname : PWChar;
shi50_type: DWORD;
shi50_flags: SHORT;
shi50_remark: PWChar;
shi50_path: PWChar;
shi50_rw_password: PWChar;
shi50_ro_password: PWChar;
end;
TSHARE_INFO_50 = SHARE_INFO_50;
{$EXTERNALSYM SHARE_INFO_50}
function NetShareAdd( servername : PWideChar; level : DWORD; pShareInfo
: Pointer; var parm_err : DWORD): NET_API_STATUS; stdcall;
function NetShareAddW9x( servername : PWideChar; level : DWORD;
pShareInfo : Pointer; var parm_err : DWORD): NET_API_STATUS; stdcall;
{$EXTERNALSYM NetShareAdd}
implementation
function NetShareAdd; external 'netapi32.dll' name 'NetShareAdd';
function NetShareAddW9x; external 'svrapi.dll' name 'NetShareAdd';
end.
So it doesnt gives me error but it doesnt share the folder on w98.
Can you just take a look for me Jens ?
Thanks for the big help !
Regards,
Diego.
I had another look at the PSDK documentation (Platform SDK, downloadable at
microsoft.com), which has some answers for us:
type _share_info_50 = record
shi50_netname : array[0..LM20_NNLEN] of Char;
shi50_type : Byte; // unsigned char;
shi50_flags : Byte; // unsigned short ;
shi50_remark : PChar; // char FAR*
shi50_path : PChar; // char FAR*
shi50_rw_password : array[0..SHPWLEN] of Char;
shi50_ro_password : array[0..SHPWLEN] of Char;
end;
Remarks
a) types [unsigned] char and [unsigned] short both are 8 bits in length, at
least for Win32.
b) All strings are Ansi here, probably because this is for Win9x only
Note that the string you specify in the shi50_path member MUST CONTAIN ONLY
uppercase characters. If the path contains lowercase characters, calls to
NetShareAdd can fail with NERR_UnknownDevDir or ERROR_BAD_NET_NAME.
The call for Win9x is somewhat different than the call for the NT platforms.
You must specify the size of the information buffer, in bytes, using the
cbBuffer parameter. The parm_err parameter is not available on this
platform. Therefore, the parameter list is as follows.
extern API_FUNCTION
NetShareAdd ( const char FAR * pszServer,
short sLevel,
const char FAR * pbBuffer,
unsigned short cbBuffer );
which translates to Delphi as follows:
function NetShareAddW95( pszServer : PChar; sLevel : Byte;
pBuffer : ^_share_info_50; cbBuffer : byte) : DWORD;
external 'svrapi.dll' name 'NetShareAdd';
The parameters:
The shi50_flags can be as follows:
shi50_flags
This member can be one or more of the following values.
SHI50F_RDONLY The share can be opened with read-only access.
SHI50F_FULL The share can be opened with read/write access.
SHI50F_ACCESSMASK The share can be opened with read/write access.
SHI50F_PERSIST The share is restored at system startup.
SHI50F_SYSTEM The share is a hidden share, and normally is not
visible.
and they have these values:
const
SHI50F_RDONLY = $0001;
SHI50F_FULL = $0002;
SHI50F_DEPENDSON = (SHI50F_RDONLY or SHI50F_FULL);
SHI50F_ACCESSMASK = (SHI50F_RDONLY or SHI50F_FULL);
SHI50F_PERSIST = $0100;
SHI50F_SYSTEM = $0200;
In a user-level security environment, specify the value SHI50F_FULL. When
the server is running with user-level security the network management access
functions (those that begin with NetAccess) determine the access rights.
For the cbBuffer value always pass
SizeOf(_share_info_50);
> So it doesnt gives me error but it doesnt share the folder on w98.
> Can you just take a look for me Jens ?
Unfortunately I have no access to a Win9x at this time due to some reasons,
so I can't made a test there today. Does this help you anyway?
JensG
Thanks a lote Jens,
Regards,
Diego.
unit u_apifunctions;
interface
uses Windows;
const
NERR_BASE = 2100;
NERR_RedirectedPath = NERR_BASE+17; //Operação invalida ao
redirecionar o path
NERR_DuplicateShare = NERR_BASE+18; //Nome compartilhado ja esta sendo
usado
NERR_UnknownDevDir = NERR_BASE+16; //Erro Diretorio não existe
ACCESS_READ = $01;
ACCESS_WRITE = $02;
ACCESS_CREATE = $04;
ACCESS_EXEC = $08;
ACCESS_DELETE = $10;
ACCESS_ATRIB = $20;
ACCESS_PERM = $40;
//Tipos de compartilhamentos
STYPE_DISKTREE = 0;
STYPE_PRINTQ = 1;
STYPE_DEVICE = 2;
STYPE_IPC = 3;
STYPE_TEMPORARY = $40000000;
STYPE_SPECIAL = $80000000;
SHI_USES_UNLIMITED = DWORD(-1);
//Tipos de acesso do Windows 95 e Windows 98
SHI50F_RDONLY = $0001; //Compartilhamento somente leitura.
SHI50F_FULL = $0002; //Compartilhamento escrita e leitura.
SHI50F_DEPENDSON = (SHI50F_RDONLY or SHI50F_FULL); //Compartilhamento
escrita e leitura determinado por mascara.
SHI50F_ACCESSMASK = (SHI50F_RDONLY or SHI50F_FULL); //Compartilhamento
escrita e leitura determinado por mascara.
SHI50F_PERSIST = $0100; //Compartilhamento é restaurado na
inicializaçao .
SHI50F_SYSTEM = $0200; //Compartilhamento oculto.
LM20_NNLEN = 12;
SHPWLEN = 8;
//Define estrutura do SHARE_INFO_2
type
SHARE_INFO_2 = record
shi2_netname:PWideChar;
shi2_type:DWORD;
shi2_remark:PWideChar;
shi2_permissions:DWORD;
shi2_max_uses:DWORD;
shi2_current_uses:DWORD;
shi2_path:PWideChar;
shi2_passwd:PWideChar;
end;
TSHARE_INFO_2 = SHARE_INFO_2;
{$EXTERNALSYM SHARE_INFO_2}
NET_API_STATUS = DWORD;
//Define estrutura do SHARE_INFO_50
type
SHARE_INFO_50 = record
shi50_netname : array [0..LM20_NNLEN] of char;
shi50_type: Byte;
shi50_flags: Byte;
shi50_remark: PChar;
shi50_path: PChar;
shi50_rw_password: array [0..SHPWLEN] of char;
shi50_ro_password: array [0..SHPWLEN] of char;
end;
TSHARE_INFO_50 = SHARE_INFO_50;
{$EXTERNALSYM SHARE_INFO_50}
function NetShareAdd( servername : PWideChar; level : DWORD; pShareInfo
: Pointer; var parm_err : DWORD): NET_API_STATUS; stdcall;
function NetShareAddW9x( pszServer : PChar; sLevel : Byte; pBuffer :
Pointer; cbBuffer : byte) : DWORD; stdcall;
{$EXTERNALSYM NetShareAdd}
implementation
function NetShareAdd; external 'netapi32.dll' name 'NetShareAdd';
function NetShareAddW9x; external 'svrapi.dll' name 'NetShareAdd';
end.
And here is an example on how to use it !
var
//Windows 2000 & Windows XP
v_p : SHARE_INFO_2;
v_parm :DWORD;
v_result :NET_API_STATUS;
//Windows 95 & Windows 98
v_p : SHARE_INFO_50;
v_buff : byte;
v_result :DWORD;
begin
trv_admpcs.FullExpand;
trv_admpcs.Selected := trv_admpcs.Items[0];
CreateDirectory('C:\testa',nil);
//Windows 2000 & Windows XP { Concluido }
v_p.shi2_netname := 'testess';
v_p.shi2_type := STYPE_DISKTREE;
v_p.shi2_remark := 'Teste de Compartilhamento de Arquivo';
v_p.shi2_permissions := 0;
v_p.shi2_max_uses := 4;
v_p.shi2_current_uses:= 0;
v_p.shi2_path := 'C:\testa';
v_p.shi2_passwd := nil;
v_parm := 0;
NetShareAdd(nil,2,@v_p,v_parm);
//Windows 95 & Windows 98 { Em fase de teste - Retorna erro nr 87 }
v_p.shi50_netname := 'testa';
v_p.shi50_type := STYPE_DISKTREE;
v_p.shi50_flags := SHI50F_FULL;
v_p.shi50_remark := 'Teste de Compartilhamento';
v_p.shi50_path := 'C:\TESTA';
v_p.shi50_rw_password := '';
v_p.shi50_ro_password := '';
v_buff := SIZEOF(SHARE_INFO_50);
NetShareAddW9x(nil,50,@v_p,v_buff);
end;
Works Perfect now :)
Regards,
Diego.
> Its Done and Working very nice
> here is the full code: [snipped]
> Works Perfect now :)
Cool!
Have a nice day,
JensG
As I said: The PSDK is very useful, even for Delphi programmers. You got all
the header files and samples, so one can easily find the things one needd
and translate it to Delphi.
The JEDI library has been already recommended. I know they have ported a lot
of code and Windows SDK headers, but until now I never used their stuff. But
it may be helpful to you and save a lot of time.
JensG