En principio es tan sencillo o tan complicado como usar la función de la API de Windows “NetShareAdd”. La preguntas es: ¿dónde está esta función? Pues bien, esta función se puede encontrar en la DLL “SrvApi.dll” en los sistemas Win9x y WinMe, o en la DLL “NetApi32.dll” en los sistemas Windows NT y 2000 (y supongo que XP).
Borland, ante este problema de que dicha función dependa del sistema operativo lo que ha hecho es pasar de todo y no incluir esta función (ni muchas otras de redes locales) en sus archivos de sistema de la VCL, por lo que para poder usar tendremos que declarar nosotros mismos esta función.
Aquí surge una duda de como cargar la DLL que vayamos a usar: estática o dinámicamente.
Si declaramos la función estáticamente, es decir, con un “external XXXXX” después de la declaración, nuestro ejecutable dependerá de dicha DLL y no nos funcionará en el otro tipo de plataforma. Si por ejemplo cargamos estáticamente NetApi32.dll porque estamos en NT ó 2000 no podremos ejecutar nuestra aplicación en Win9x ó Me.
Esto nos lleva a que la mejor forma de hacerlo es cargando la función dinámicamente (LoadLibrary, GetProcAddress, …) y evitar la dependencia del sistema operativo.
Por otra parte está el hecho de que esta función utiliza unas estructuras (records en Delphi) que tampoco están declaradas y tendremos que declararlas a mano. Estas son: “share_info_50” para sistemas 9x y Me y “share_info_2” para sistemas NT/2000.
Para declarar estas estructuras y otras constantes necesarias he creado el fichero NetShare.pas que es como sigue:
unit NetShare;
interface uses Windows; const LM20_NNLEN = 12; SHPWLEN = 8; SHI50F_RDONLY = 1; SHI50F_FULL = 2; SHI50F_DEPENDSON = (SHI50F_RDONLY or SHI50F_FULL); SHI50F_ACCESSMASK = (SHI50F_RDONLY or SHI50F_FULL); SHI50F_PERSIST = 256; SHI50F_SYSTEM = 512; STYPE_DISKTREE = 0; ACCESS_NONE = 0; ACCESS_READ = $01; ACCESS_WRITE = $02; ACCESS_CREATE = $04; ACCESS_EXEC = $08; ACCESS_DELETE = $10; ACCESS_ATRIB = $20; ACCESS_PERM = $40; ACCESS_GROUP = $8000; ACCESS_ALL = (ACCESS_READ or ACCESS_WRITE or ACCESS_CREATE or ACCESS_EXEC or ACCESS_DELETE or ACCESS_ATRIB or ACCESS_PERM); 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; share_info_50 = packed record shi50_netname : array [0..LM20_NNLEN] of Char; shi50_type : Byte; shi50_flags : Short; shi50_remark : PChar; shi50_path : PChar; shi50_rw_password: array [0..SHPWLEN] of Char; shi50_ro_password: array [0..SHPWLEN] of Char; end; implementation end.
La llamada a la función para compartir una carpeta sería algo así:
procedure TForm1.Button1Click(Sender: TObject);
var hDll : THandle; NetShareAddWin9x : function(pszServer : PChar; sLevel : Short; pbBuffer : Pointer; cbBuffer : Short):DWORD;stdcall; NetShareAddWinNT : function(servername : PWideChar; level : DWORD; buf : Pointer; var parm_Err : DWORD):DWORD;stdcall; si50 : share_info_50; si2 : share_info_2; tamano : Short; res, err : DWORD; begin // Habría que comprobar la versión de windows // con la función EsNT que tiene que devolver // true si estamos en NT ó 2000 y si no false. if (not EsNT) then begin // Probamos con la librería de Win 95/98/Me hDll := LoadLibrary('SvrApi.dll'); if hDll > 32 then begin NetShareAddWin9x := GetProcAddress(hDll, 'NetShareAdd'); tamano := sizeof(si50); FillChar(si50, tamano, 0); StrCopy(si50.shi50_netname, 'PRUEBA'); si50.shi50_type := STYPE_DISKTREE; si50.shi50_flags := SHI50F_RDONLY; si50.shi50_path := 'D:\TEMP'; res := NetShareAddWin9x(nil, 50, @si50, tamano); FreeLibrary(hDll); end; end else begin // Probamos con la librería de Win NT/2000 hDll := LoadLibrary('NetApi32.dll'); if hDll > 32 then begin NetShareAddWinNT := GetProcAddress(hDll, 'NetShareAdd'); tamano := sizeof(si2); FillChar(si2, tamano, 0); si2.shi2_netname := 'PRUEBA'; si2.shi2_type := STYPE_DISKTREE; si2.shi2_permissions := ACCESS_READ; si2.shi2_max_uses := 1; si2.shi2_current_uses := 1; si2.shi2_path := 'C:\WINNT'; res := NetShareAddWinNT(nil, 2, @si2, err); FreeLibrary(hDll); end; end; end;
NOTA: en Win9x/ME hay que poner el parámetro “shi50_path” en mayúsculas para que funcione.
Ważne artykuły