Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to Implement an API procedure in the Windows.pas

131 views
Skip to first unread message

Diego

unread,
Aug 30, 2004, 8:11:06 AM8/30/04
to
Hello guys,
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 !

Can someone help me to implement that ?

Thank a lote,
Diego.


Kurt Barthelmess [TeamB]

unread,
Aug 30, 2004, 9:50:28 AM8/30/04
to
"Diego" <di...@terti.dot.com.br> wrote:

>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

Diego

unread,
Aug 30, 2004, 10:12:12 AM8/30/04
to
Yap .. I was adding my code to the windows that cames with delphi.
But I dont know why it didnt works ...

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.


Jens Geyer

unread,
Aug 30, 2004, 12:07:57 PM8/30/04
to
> NetShareAdd( LPWSTR servername, DWORD level, LPBYTE buf, LPDWORD
> parm_err);

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


Jens Geyer

unread,
Aug 30, 2004, 12:11:09 PM8/30/04
to
> function NetShareAdd ....
> external 'netapi32.dll' name 'NetShareAddA';

Should be

external 'netapi32.dll' name 'NetShareAdd';

without the "A"
JensG


Diego

unread,
Aug 30, 2004, 12:46:36 PM8/30/04
to
Another thing,
I'm trying to do the example that is in msdn
but it is writed in c so the code is that one
------ C

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;


Diego

unread,
Aug 30, 2004, 1:18:51 PM8/30/04
to
Jens I've maded some changes know it compiles but I got an error ..

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.

walt

unread,
Aug 30, 2004, 1:18:16 PM8/30/04
to


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 Geyer

unread,
Aug 31, 2004, 4:11:14 AM8/31/04
to
Hello,

> 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


Diego

unread,
Aug 31, 2004, 8:17:43 AM8/31/04
to
Thanks Jens,

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.


Jens Geyer

unread,
Aug 31, 2004, 9:25:10 AM8/31/04
to
Hello 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


Diego

unread,
Aug 31, 2004, 11:58:16 AM8/31/04
to
Yap Jens it helps me a lote,
I 've not seen that the constants had this numbers that you gave me so
now I can get back to work !
I will try to made the changes to work on W9x then I post the answear here
later.

Thanks a lote Jens,
Regards,
Diego.


Diego

unread,
Aug 31, 2004, 1:01:22 PM8/31/04
to
Ok Jens
Its Done and Working very nice
here is the full code:

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.


Jens Geyer

unread,
Sep 1, 2004, 4:06:12 AM9/1/04
to
Hello Diego,

> Its Done and Working very nice

> here is the full code: [snipped]
> Works Perfect now :)

Cool!

Have a nice day,
JensG


Jens Geyer

unread,
Sep 1, 2004, 4:05:18 AM9/1/04
to

> I 've not seen that the constants had this numbers that you gave me
> so now I can get back to work !

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


0 new messages