| « Поставить закладку » « Сделать стартовой » | |||
|
|||
|
SVR API для непродвинутых
Автор: Александр
Терехов Вступление... Для тех, кто считает мои примеры и статьи "плагиатом без зазрения совести" ( были прецеденты от анонимных авторов), оговорюсь сразу: не я придумал систему Windows и API-функции к ней, а также не я писал хелп по этому поводу. Но это не значит, что использование полученной оттуда информации - есть плагиат, так как вся информация заранее застолблена авторским правом Б.Гейтса & сотоварищи. А раз она принадлежит им и только им, то какое-либо ее использование ни как не может подпадать под понятие "плагиат".Иное дело алгоритмы... Итак хелп. Предыстория Как-то потребовалось программным способом открыть доступ к сетевому ресурсу. После прочтения (в очередной раз) хелпа от Дельфи стало ясно, что сетевым администрированием занимаются функции семейства Net*. А в частности для открытия, закрытия доступа к сетевому ресурсу, а также получения или изменения информации о нем применяются функции подсемейства NetShare*. Однако, как написано в хелпе, все эти функции работают только под WinNT. К сожалению... Но раз Win'9x открывает (закрывает) доступ, значит, можно сделать то же самое и программно. И тут начались поиски. В хелпе сказано, что для Си++ надо применять заголовочный модуль LmShare.h, в котором даны прототипы функций библиотеки netapi32.dll. Посмотрев эту библиотеку утилитой tdump.exe (лежит в директории Delphi_XBin), я увидел, что библиотека netapi32.dll (для Win'9x) кроме одной экспортируемой функции netbios более ничего не содержит. Далее включаю обычный поиск текста "NetShareAdd" в файлах *.dll. Поиск выдал результат - среди нескольких библиотек эту строку содержит и библиотека svrapi.dll. Следуя проторенным путем, т.е. через tdump.exe, увидел, что эта библиотека содержит почти все экспортируемые функции с названиями Net*. Ура! Место, где "собака порылась" найдено! Осталось только эту собаку откопать. Ясно, что без знания прототипов этих функций, сами по себе их названия - пустой хлам. Включаю поиск в Интернет строки "svrapi". И вот он, заветный заголовочный модуль! SvrApi.pas. Лежит, голубчик на JEDI! Написал его Petr Vones, за что ему большое спасибо! В этом модуле даны прототипы следующих классов Net-функций:
Функция NetShareAdd Все семейство NetShare*, а это:
Вот ее прототип: function NetShareAdd(const pszServer: PChar; sLevel: SmallInt; pbBuffer: Pointer; cbBuffer: Word): NET_API_STATUS; stdcall;Описание аргументов функции будут даны ниже. Сейчас рассмотрим, как следует подключать эту функцию. Подключение внешней функции Если не вдаваться в подробности, то в подключении внешних функций оказывается нет ничего сложного. В Unit.pas после описания класса TForm и до клаузы implementation следует написать:Function NetShareAdd(ServerName : PChar; Level : Integer; pbBuffer : Pointer; BufferSize : Integer) : Integer; stdcall; external 'svrapi.dll';На что следует обратить внимание. Во-первых, я вольно заменил типы некоторых переменных на более привычный Integer (хотя по большому счету этого делать не следует). Во-вторых, stdcall - это способ передачи данных через стек, применяемый для Паскаля. И, в-третьих, external 'svrapi.dll' - означает, что функция находится во внешней библиотеке с названием svrapi.dll. Теперь к аргументам. Аргументы функции ServerName - сетевое имя компьютера, для локального можно писать Nill.Что можно сказать об этом аргументе. Для работы с локальной машиной проблем не возникает. Например, если сетевое имя машины Toshiba, то в этот параметр надо писать '\Toshiba' или указать Nill. А вот для сетевой машины возникают проблемы. Испытывая NetShareAdd в сети, я постоянно результатом работы функции получал значение 65, что означает - "Нет доступа к сети". Оказалось, чтобы открыть доступ к сети для NetShare-функций, надо "Разрешить удаленное управление этим сервером" (делается в "Пароли" из "Панели управления"). Тогда директории Windows присваивается сетевое имя ADMIN$ и после подключения этого имени в качестве сетевого диска, "сезам" открывается. Все это можно сделать программно: с помощью описываемой функции открыть доступ с именем ADMIN$ к любой директории, в том числе несуществующей (см. ниже) и с помощью одной из трех WNetAddConnection подключить сетевой диск для этого имени. Тогда все сработает на ура. Level - уровень администрирования. Для WinNT применяют три уровня 1,2 и 502, для Win'9x следует применять уровень 50. pbBuffer - указатель на структуру, в которую будем заносить все данные, необходимые для открытия доступа к ресурсу. На этой структуре следует остановиться более подробно. Вот она сама: Type
TShareInfo50 = packet 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;
shi50_netname - сетевое имя, по обращению к которому, будет доступен
сетевой ресурс. Сетевое имя должно быть уникальным. Константа LM20_NNLEN имеет
значение 12, т.е. сетевое имя не должно быть более 12-ти символов.
shi50_type - тип ресурса, может иметь следующие значения:
shi50_ro_password - пароль "только чтение", где SHPWLEN = 8, т.е. максимальное количество символов в пароле с учетом символа под номером 0 составляет 9 штук. И наконец, последний аргумент BufferSize - размер буфера, в котором находятся необходимые для открытия доступа данные. Теперь перейдем к значению, возвращаемому функцией NetShareAdd. Результат функции В случае успешного выполнения функции возвращается 0. В случае неудачи возвращается числовое значение. Обработка этого значения в большинстве случаев позволяет локализировать причину неудачи.Для функции NetShareAdd предлагаются следующие виды ошибок (в моем вольном переводе): NO_ERROR = 0; 'Все в порядке' (из LmErr.pas): NERR_BASE = 2100; базовая ошибка для NERR_; NERR_NetNotStarted = NERR_BASE+2 'Сеть недоступна'; NERR_UnknownServer = NERR_BASE+3 'Неизвестный сервер'; NERR_ServerNotStarted = NERR_BASE+14 'Сервер не работает'; NERR_UnknownDevDir = NERR_BASE+16 'Сетевое устройство отсутствует'; NERR_RedirectedPath = NERR_BASE+17 'Переназначенное устройство'; NERR_DuplicateShare = NERR_BASE+18 'Сетевое имя уже существует'; NERR_BufTooSmall = NERR_BASE+23 'Слишком маленький буфер для данных!'; NERR_NetNameNotFound = NERR_BASE+210 'Сетевое имя не существует'; NERR_InvalidComputer = NERR_BASE+251 'Неверное имя компьютера'; NERR_ShareNotFound = NERR_BASE+292 'Сетевое устройство не обнаружено'.Однако бывают и другие ошибки. Почему-то функции SysErrorMessage(GetLastError) и WNetGetLastError при работе с NetShare* (по крайней мере у меня) не срабатывают, поэтому значения ошибок, коды которых менее 2100, я взял из ошибок, общих для всей операционной системы. (из Windows.pas:) ERROR_NOT_ENOUGH_MEMORY = 8 'Недостаточно памяти'; ERROR_BAD_NETPATH = 53 'Неверное сетевое имя'; ERROR_NETNAME_DELETED = 64 'Сетевой ресурс более недоступен'; ERROR_NETWORK_ACCESS_DENIED = 65 'Отсутствует доступ к сети'; ERROR_BAD_DEV_TYPE = 66 'Неверный тип сетевого ресурса'; ERROR_BAD_NET_NAME = 67 'Не найдено сетевое имя'; ERROR_INVALID_PARAMETER = 87 'Неверный параметр'; ERROR_INVALID_LEVEL = 124 'Неверный уровень администрирования';Т.е. если результатом функции возвращается число больше, чем 2100, то смотри модуль LmErr.pas, если меньше - то модуль Windows.pas. На этом вроде все. Но, лучше один раз увидеть, чем... Поэтому посмотрим, как все работает на практике. Пример работы NetShareAdd Для директории C:Temp локальной машины откроем доступ с именем "TEST", паролем для чтения "QWE", для полного доступа "ASDF", комментарием "This is a network machine's commentary", с автоматическим открытием доступа при перезагрузке компьютера. И заодно закроем доступ. На новую форму следует положить две кнопочки и привести вид Unit1.pas в соответствие с ниже приведенным кодом.unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls ;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
//подключаем две функции из библиотеки svrapi.dll
Function NetShareAdd(Servername : PChar; Level : Integer; Buffer : Pointer;
BufferSize : Integer) : Integer; stdcall; external 'svrapi.dll';
Function NetShareDel(Servername : PChar; NetName : PChar; Reserved:DWORD): DWORD;
stdcall; external 'svrapi.dll';
//необходимые константы
const
{см. LmCons.pas}
LM20_NNLEN = 12;
SHPWLEN = 8;
SHI50F_RDONLY = 1;
SHI50F_FULL = 2;
STYPE_DISKTREE = 0;
SHI50F_PERSIST = $0100;
SHI50F_SYSTEM = $0200;
{см. LmErr.pas}
NERR_BASE = 2100;
NERR_NetNotStarted = NERR_BASE+2;
NERR_UnknownServer = NERR_BASE+3;
NERR_ServerNotStarted = NERR_BASE+14;
NERR_UnknownDevDir = NERR_BASE+16;
NERR_RedirectedPath = NERR_BASE+17;
NERR_DuplicateShare = NERR_BASE+18;
NERR_BufTooSmall = NERR_BASE+23;
NERR_NetNameNotFound = NERR_BASE+210;
NERR_InvalidComputer = NERR_BASE+251;
NERR_ShareNotFound = NERR_BASE+292;
//формируем тип для записи с необходимыми параметрами
Type
TShareInfo50 = 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; {Record}
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
Var
info50: TShareInfo50;
rc, cb: Integer;
ServerName, Path, NetName, ErrMes, ErrCap, Comment:String;
MessIconBtn:Byte;
begin
//установим необходимые параметры
ServerName:='';
Path:='C:TEMP';
NetName:='TEST';
Comment:='This is a network machine''s commentary';
//заполним буфер
FillChar(info50, sizeof(info50), 0);
With info50 Do
Begin{With}
StrCopy(shi50_netname, PChar(NetName)); //сетевое имя
shi50_type := STYPE_DISKTREE; //подключать будем диск
shi50_remark:=PChar(Comment); //комментарий
shi50_flags:= SHI50F_RDONLY OR SHI50F_FULL //доступ определяется паролем
OR SHI50F_PERSIST;//и пишется в Registry
shi50_path:=PChar(Path); //путь
StrPCopy(shi50_rw_password,'ASDF'); //пароль для полного доступа
StrPCopy(shi50_ro_password,'QWE'); // пароль для "только чтение"
End;{With}
//установим размер буфера
cb := sizeof(info50);
//основная функция
rc := NetShareAdd(PChar(ServerName), 50, @info50, cb);
//сформируем текст сообщений об успехе или ошибках
ErrMes:='Доступ к устройству "'+NetName+'" открыт!';
ErrCap:='Все в порядке!';
MessIconBtn:=MB_OK OR MB_ICONINFORMATION;
//проверка ошибок
If rc <> 0 Then
Begin {ошибка}
ErrCap:='Ошибка!';
MessIconBtn:=MB_OK OR MB_ICONERROR;
Case rc Of
//расшифровка ошибок
ERROR_NOT_ENOUGH_MEMORY : ErrMes:='Недостаточно памяти';
ERROR_BAD_NETPATH : ErrMes:='"'+Servername+ '" - неверное сетевое имя!';
ERROR_NETNAME_DELETED : ErrMes:='Сетевой ресурс более недоступен';
ERROR_NETWORK_ACCESS_DENIED: ErrMes:='Отсутствует доступ к сети';
ERROR_BAD_DEV_TYPE : ErrMes:='Неверный тип сетевого ресурса';
ERROR_BAD_NET_NAME : ErrMes:='Не найдено сетевое имя';
ERROR_INVALID_PARAMETER : ErrMes:='Неверный параметр';
ERROR_INVALID_LEVEL : ErrMes:='Неверный уровень администрирования';
NERR_InvalidComputer:ErrMes:='Неверное имя компьютера!';
NERR_UnknownServer:ErrMes:='Неизвестный сервер!';
NERR_UnknownDevDir:ErrMes:='Устройство "'+Path+'" отсутствует!';
NERR_ServerNotStarted:ErrMes:='Сервер не работает!';
NERR_RedirectedPath:ErrMes:='Переназначенный путь!';
NERR_DuplicateShare:ErrMes:='Сетевое имя "'+NetName+'" уже существует!';
NERR_BufTooSmall:ErrMes:='Слишком маленький буфер для данных!';
Else
End; {Case}
End; {ошибка}
//выдадим сообщение
MessageBox(Application.Handle,PChar(ErrMes),PChar(ErrCap),MessIconBtn);
end;
procedure TForm1.Button2Click(Sender: TObject);
Var
rc:DWord;
Servername,NetName, ErrMes, ErrCap:String;
MessIconBtn:Byte;
begin
ServerName:='';
NetName:='TEST';
rc:=NetShareDel(PChar(ServerName),PChar(NetName),0);
ErrMes:='Доступ к устройству "'+NetName+'" закрыт!';
ErrCap:='Все в порядке!';
MessIconBtn:=MB_OK OR MB_ICONINFORMATION;
If rc <> 0 Then
Begin {ошибка}
//ошибка
ErrCap:='Ошибка!';
MessIconBtn:=MB_OK OR MB_ICONERROR;
Case rc Of
//расшифровка ошибок
ERROR_BAD_NETPATH:ErrMes:='"'+Servername+ '" - неверное сетевое имя!';
ERROR_INVALID_PARAMETER:ErrMes:='Неверный параметр!';
NERR_NetNotStarted:ErrMes:='Сеть недоступна!';
NERR_ServerNotStarted:ErrMes:='Сервер не работает!';
NERR_NetNameNotFound:ErrMes:='Устройство не существует!';
NERR_ShareNotFound:ErrMes:='Сетевое имя "'+NetName+'" не найдено!';
Else
//смотри ошибки для NetShareAdd или
ErrMes:='Неизвестная сетевая ошибка!';
End; {Case}
End;{ошибка}
MessageBox(Application.Handle,PChar(ErrMes),PChar(ErrCap),MessIconBtn);
end;
end.
Прилагаемые модули Скачать SvrAPI.zip (28K)
Да и каждый раз расшаркиваться перед правообладателем не надо! :) Не забываем, что все, о чем говорилось в этой статье, относится к Win'9x! SvrAPI для непродвинутых II Рубрика: Интернет и Сети
Подгрузка через AJAX HTML-кода, содержащег....
При разработке CMS S.Builder наша команда активно использовала AJAX. Теперь вот решили поделиться накопленным опытом. Начнем с этого хабратопика. Не буду здесь затрагивать различные фреймворки и библиотеки. Свой код всегда роднее. Для работы с AJAX-ом в S.Builder написана библиотека sbAJAX. Можете качать и пользоваться :). В этом файле есть функция sbEvalJS. Для тех, кто не знает, объясню. При подгрузке через AJAX и вставке на страницу HTML-кода, содержащего JavaScript, JavaScript выполняться не будет или полезут баги. Эта функция как раз решает поставленную задачу.
Подробнее... |
Рубрика: AJAX
| Добавлено: 19.11.2008
Обзор нового релиза самой мощной Ajax библ....
Хотя наш обзор немного запоздал, оригинальный Dojo 1.2 вышел в релизной версии ещё 6-го октября, но сейчас мы наверстаем упущенное. И так, Dojo Toolkit — это самая мощная и гибкая ajax-библиотека из всех, что есть на рынке, она активно развивается и имеет большое комьюнити. Кстати, это самое комьюнити, совместно с компанией Sitepen, имеет ещё несколько проектов, среди которых и Cometd и некоторые другие, не менее интересные, о которых мы скоро вам расскажем. Сегодня же все внимание на флагманский продукт — Dojo 1.2.
Подробнее... |
Рубрика: AJAX
| Добавлено: 19.11.2008
Firebug 1.3 и 1.4 alpha — что нового и инт....
Если вы профессиональный веб-разработчик и постоянно имеете дело с разработкой и отладкой сложных AJAX приложений, то наверняка знаете и используете Firebug — плагин для браузера Firefox, предназначенный для отладки и исследования веб-приложений. Текущая его версия, 1.2х достаточно стабильная и функциональна, чтобы помочь в 99% проблем, которые могут возникнуть при разработке. Но и этот инструмент не лишён если не недостатков, то некоторых фич, которые могли бы облегчить работу. И даже идеальный инструмент можно сделать ещё более идеальным, как бы это не звучало.
Подробнее... |
Рубрика: Вебмастеру
| Добавлено: 19.11.2008
Остальные статьи: |
Цитата дня (все,добавить):
|
Realcoding.NET
© 2003-2008 |
Контакты |
Реклама на сайте
|