Трансляция программы на Рис. 3.4.1.
MASM32:
ml /c /coff /DMASM driv.asm rc driv.rc link /subsystem:windows driv.obj driv.resTASM32:
tasm32 /ml driv.asm brcc32 driv.rc tlink32 -aa driv.obj,,,,,driv.resРис. 3.4.2. Результат работы программы на Рис.3.4.1
После того как Вы определили, что данное устройство является сетевым, может возникнуть вторая задача: определить статус устройства. Под статусом в данном случае я понимаю три возможных ситуации: устройство открыто только для чтения и записи, устройство открыто только для чтения, устройство недоступно. Лично я поступаю следующим образом. Для проверки статуса использую две функции
CreateFile
иGetDiskFreeSpace
. С первой функцией Вы уже знакомы, с помощью второй функции можно определить объем свободного места на диске. Если данное устройство позволяет создать файл (файл лучше создавать с атрибутом "удалить после закрытия", и операционная система сама выполнит процедуру удаления) и прочесть данные об устройстве, следовательно, оно открыто для чтения и записи. Если устройство позволяет прочитать данные о нем, но не позволяет создать файл, следовательно, устройство открыто только для чтения. Наконец, если не разрешено ни то, ни другое, следовательно, устройство недоступно. Такой бесхитростный подход, однако, работает весьма эффективно.II
В данном разделе мы рассмотрим вопрос о доступе к ресурсам локальной сети. При этом следует выделить две проблемы: поиск ресурсов в локальной сети и подключение к ресурсам. Начну с того, что перечислю основные функции для работы с сетевыми ресурсами. Это не все функции, но их вполне достаточно, чтобы Ваша программа самостоятельно искала сетевые ресурсы и подключалась к ним. Конечно, я предполагаю, что вы умеете работать в сети, знаете, что такое сетевое устройство, сетевой компьютер и т.п.
Прежде всего рассмотрим структуру, которая используется в данных функциях.
NETRESOURCE STRUC dwScope DWORD ? dwType DWORD ? dwDisplayType DWORD ? dwUsage DWORD ? lpLocalName DWORD ? lpRemoteName DWORD ? lpComment DWORD ? lpProvider DWORD ? NETRESOURCE ENDS
dwScope
- может принимать одно из трех значений:
RESOURCE_CONNECTED
- ресурс подсоединен в настоящее время.RESOURCE_REMEMBERED
- ресурс, запоминаемый системой, чтобы при запуске автоматически подсоединяться к нему.
RESOURCE_GLOBALNET
- глобальный сетевой ресурс. Скорее всего, Вам понадобится только последнее значение.
dwType
- тип ресурса. Возможны следующие значения:
RESOURCETYPE_ANY
- любой ресурс.RESOURCETYPE_DISK
- диск.RESOURCETYPE_PRINT
- сетевой принтер.
dwDisplayType
- как данный ресурс должен быть представлен сетевым браузером. Типов довольно много. Например, для сетевого компьютера определен типRESOURCEDISPLAYTYPE_SERVER
, для группы -RESOURCEDISPLAYTYPE_GROUP
и т.д.
dwUsage
- чаще всего полагают равным 0.
lpLocalName
- локальное имя устройства, напримерЕ:
,LPT1:
и т.п.
lpRemoteName
- сетевое имя, например\\SUPER
,\\NDI\EPSON
и т.д.
lpComment
- комментарий к сетевому ресурсу.
lpProvider
- имя провайдера. В настоящее время имя может принимать одно из двух значений:Microsoft Network
иNetWare
, но возможны и другие имена.
WNetAddConnection2
- можно подсоединить к Вашему компьютеру сетевой ресурс (диск или принтер).
- 1-й параметр. Адрес структуры
NETRESOURCE
, значение полей которой было разобрано выше. Должны быть заполнены следующие поля:dwType
,lpLocalName
,lpRemoteName
,lpProvider
(обычноNULL
). Ниже будет приведен пример заполнения.- 2-й параметр. Пароль, необходимый для соединения с ресурсом. В случае пустой сроки - соединение беспарольное, в случае
NULL
- берется пароль, ассоциированный с именем (см. ниже).- 3-й параметр. Имя пользователя. Если значение
NULL
, то берется имя по умолчанию.- 4-й параметр. Данный параметр определяет, будет ли система потом автоматически подсоединяться к данному ресурсу. В случае значения
0
, такого подсоединения не происходит.При успешном завершении функция возвращает0
(NO_ERROR
). Это касается и всех остальных рассмотренных ниже функций.
WNetCancelConnection2
- отсоединить ресурс.
- 1-й параметр. Содержит указатель на строку, содержащую имя ресурса. Причем если имя локальное, то разрывается данное локальное соединение. Если это имя удаленного ресурса, то разрываются все соединения с данным ресурсом.
- 2-й параметр. Определяет, будет ли система и далее подсоединяться к данному ресурсу. Если
0
, то подсоединение (если было) будет возобновляться при следующем запуске системы.- 3-й параметр. Если значение не нулевое, то отсоединение произойдет, даже если на сетевом диске имеются открытые файлы или сетевой принтер выполняет задание с данного компьютера.
WNetOpenEnum
- открыть поиск сетевых ресурсов. Вообще говоря, сетевые ресурсы представляют собой структуру в виде дерева. Об этом мы будем говорить ниже, поэтому поиск сетевых ресурсов весьма напоминает поиск файлов по дереву каталогов.
- 1-й параметр.
dwScope
(см. структуруNETRESOURCE
) - обычно полагаютRESOURCE_GLOBALNET
.- 2-й параметр.
dwType
- для поиска всяких ресурсов следует положить равнымRESOURCETYPE_ANY
.- 3-й параметр.
dwUsage
- обычно следует положить равным нулю.- 4-й параметр. Адрес структур
NETRESOURCE
. Если адрес равен0
(NULL
), то поиск будет начинаться с самого нижнего уровня (корня), в противном случае поиск начнется с уровня, определяемого полямиlpRemoteName
иlpProvider
.- 5-й параметр. Указатель на переменную, которая должна получить дескриптор для дальнейшего поиска.
WNetCloseEnum
- закрыть поиск. Единственным параметром этой функции является дескриптор, полученный при выполнении функцииWNetOpenEnum
.
WNetEnumResource
- функция, осуществляющая непосредственный поиск сетевых ресурсов.
- 1-й параметр. Дескриптор поиска.
- 2-й параметр. Указатель на переменную, которая должна содержать: какое максимальное количество ресурсов должно быть найдено за один раз. Обычно переменную полагают равной
0FFFFFFFFH
- для поиска всех возможных ресурсов. При успешном завершении данной функции переменная будет содержать количество реально найденных ресурсов.- 3-й параметр. Указатель на массив, каждым элементом которого является структура
NETRESOURCE
. Ясно, что данный массив должен быть достаточно большим, чтобы вместить столько данных о ресурсе, сколько Вам нужно. Поскольку размер структуры составляет 32 байта, то в случае большой сети размер массива должен составлять не менее 32000 байт.- 4-й параметр. Адрес переменной, содержащей объем массива. Если объем окажется мал, то переменная будет содержать реально требуемый объем.
Лишний раз подчеркну, что данная функция осуществляет поиск не всех ресурсов, а лишь ресурсов данного иерархического уровня. Так что без рекурсии не обойтись.
WNetGetConnection
- с помощью данной функции можно получить информацию о данном соединении.
- 1-й параметр. Адрес локального имени (
A:
,C:
,LPT2
и т.п.).- 2-й параметр. Адрес буфера, куда будет помещено удаленное имя.
- 3-й параметр. Указатель на переменную, содержащую размер буфера.
Завершая краткий обзор сетевых функций и переходя к программированию, замечу, что нами описана лишь часть наиболее важных сетевых функций. Кроме того, в Windows NT имеются еще и свои функции для работы с сетевыми ресурсами, которые отсутствуют в операционной системе Windows 9x. Кстати, будьте готовы к тому, что поведение описанных функций может несколько отличаться в Windows 9x, Windows NT и Windows 2000. О некоторых таких тонкостях мы скажем ниже.
Ниже представлена программа, позволяющая подключаться к сетевым дискам. Командная строка программы:
NET \\SERVER\CC Z:
. Первый параметр - имя подключаемого устройства, включающее имя сетевого сервера. Второй параметр - локальный диск, на который будет спроецирован сетевой диск.; программа NET, осуществляющая подсоединение к ; сетевому ресурсу: NET \\SUPER\\D Z: .386P ; плоская модель .MODEL FLAT, stdcall ; константы STD_OUTPUT_HANDLE equ -11 RESOURCETYPE_DISK equ 1h ; прототипы внешних процедур IFDEF MASM EXTERN lstrcat@8:NEAR EXTERN lstrlen@4:NEAR EXTERN GetStdHandle@4:NEAR EXTERN WriteConsoleA@20:NEAR EXTERN ExitProcess@4:NEAR EXTERN GetCommandLineA@0:NEAR EXTERN WNetAddConnection2A@16:NEAR ELSE LOCALS EXTERN lstrcat:NEAR EXTERN lstrlen:NEAR EXTERN GetStdHandle:NEAR EXTERN WriteConsoleA:NEAR EXTERN ExitProcess:NEAR EXTERN GetCommandLineA:NEAR EXTERN WNetAddConnection2A:NEAR lstrcat@8 = lstrcat lstrlen@4 = lstrlen GetStdHandle@4 = GetStdHandle WriteConsoleA@20 = WriteConsoleA ExitProcess@4 = ExitProcess GetCommandLineA@0 = GetCommandLineA WNetAddConnection2A@16 = WNetAddConnection2A ENDIF ; структуры NETRESOURCE STRUC dwScope DWORD ? dwType DWORD ? dwDisplayType DWORD ? dwUsage DWORD ? lpLocalName DWORD ? lpRemoteName DWORD ? lpComment DWORD ? lpProvider DWORD ? NETRESOURCE ENDS ; директивы компоновщику для подключения библиотек IFDEF MASM includelib c:\masm32\lib\user32.lib includelib c:\masm32\lib\kernel32.lib includelib c:\masm32\lib\mpr.lib ELSE includelib c:\tasm32\lib\import32.lib ENDIF ;-------------------------------------------------- ;сегмент данных _DATA SEGMENT DWORD PUBLIC USE32 'DATA' BUF1 DB 100 dup (0) BUF2 DB 100 dup (0) LENS DWORD ? ; количество выведенных символов HANDL DWORD ? NR NETRESOURCE <0> PUSTO DB 0 ERR2 DB "Ошибка!",0 ERR1 DB "Мало параметров!",0 ST1 DB "->",0 _DATA ENDS ; сегмент кода _TEXT SEGMENT DWORD PUBLIC USE32 'CODE' START: ; получить дескриптор выхода вывода PUSH STD_OUTPUT_HANDLE CALL GetStdHandle@4 MOV HANDL,EAX ; получить количество параметров CALL NUMPAR CMP EAX,3 JNB PAR_OK LEA EBX,ERR1 CALL SETMSG JMP _END PAR_OK: ; получить параметры MOV EDI,2 LEA EBX,BUF1 CALL GETPAR MOV EDI,3 LEA EBX,BUF2 CALL GETPAR ; пытаемся произвести подсоединение ; вначале заполняем структуру NETRESOURCE ; для Windows NT NR.dwType = 0 MOV NR.dwType, RESOURCETYPE_DISK LEA EAX,BUF2 MOV NR.lpLocalName,EAX LEA EAX,BUF1 MOV NR.lpRemoteName,EAX MOV NR.lpProvider,0 ; вызов функции, осуществляющей соединение PUSH 0 PUSH OFFSET PUSTO PUSH OFFSET PUSTO PUSH OFFSET NR CALL WNetAddConnection2A@16 CMP EAX,0 JE _OK ; сообщение об ошибке LEA EBX,ERR2 CALL SETMSG JMP _END _OK: ; сообщение об успешном соединении PUSH OFFSET ST1 PUSH OFFSET BUF1 CALL lstrcat@8 PUSH OFFSET BUF2 PUSH OFFSET BUF1 CALL lstrcat@8 LEA EBX,BUF1 CALL SETMSG _END: PUSH 0 CALL ExitProcess@4 ; определить количество параметров (->EAX) NUMPAR PROC CALL GetCommandLineA@0 MOV ESI,EAX ; указатель на строку XOR ECX,ECX ; счетчик MOV EDX,1 ; признак @@L1: CMP BYTE PTR [ESI],0 JE @@L4 CMP BYTE PTR [ESI],32 JE @@L3 ADD ECX,EDX ; номер параметра MOV EDX,0 JMP @@L2 @@L3: OR EDX,1 @@L2: INC ESI JMP @@L1 @@L4 : MOV EAX,ECX RET NUMPAR ENDP ; получить параметр ; EBX - указывает на буфер, куда будет помещен параметр ; в буфер помещается строка с нулем на конце ; EDI - номер параметра GETPAR PROC CALL GetCommandLineA@0 MOV ESI,EAX ; указатель на строку XOR ECX,ECX ; счетчик MOV EDX,1 ; признак @@L1: CMP BYTE PTR [ESI],0 JE @@L4 CMP BYTE PTR [ESI],32 JE @@L3 ADD ECX,EDX ; номер параметра MOV EDX,0 JMP @@L2 @@L3: OR EDX,1 @@L2: CMP ECX,EDI JNE @@L5 MOV AL,BYTE PTR [ESI] CMP AL,32 JE @@L5 MOV BYTE PTR [EBX],AL INC EBX @@L5: INC ESI JMP @@L1 @@L4: MOV BYTE PTR [EBX],0 RET GETPAR ENDP ; вывод сообщения ; EBX -> строка SETMSG PROC PUSH EBX CALL lstrlen@4 PUSH 0 PUSH OFFSET LENS PUSH EAX PUSH EBX PUSH HANDL CALL WriteConsoleA@20 RET SETMSG ENDP _TEXT ENDS END START