На этом шаге мы рассмотрим программу, составляющую перечень устройств.
В прикладном программировании часто возникает вопрос определения сетевых устройств. В принципе, вопрос можно поставить более широко: как определить тип того или иного устройства. Тот, кто программировал в MS-DOS, помнит, что там правильное определение типа устройства было не простой задачей. В Windows имеется очень полезная функция GetDriveType, единственным аргументом которой является строка корневого каталога искомого устройства, например "А:\" или "D:\". По возвращаемому функцией значению мы и определяем тип устройства.
Файл pr76_1.asm.
.386P ;Плоская модель. .MODEL FLAT, STDCALL include pr76_1.inc ;Директивы компоновщику для подключения библиотек. IFDEF MASM ;Для компоновщика LINK.EXE. includelib \masm32\lib\user32.lib includelib \masm32\lib\kernel32.lib ELSE ;Для компоновщика TLINK32.EXE. includelib c:\tasm32\lib\import32.lib ENDIF ;------------------------------------------------ ;Сегмент данных. _DATA SEGMENT DWORD PUBLIC USE32 'DATA' PRIZ DB 0 MSG MSGSTRUCT <?> HINST DD 0 ;Дескриптор приложения. PA DB "DIAL1",0 ROO DB "?:\",0 BUFER DB 40 DUP(0) TYP0 DB " Нет устройства",0 TYP1 DB " Нет устройства",0 TYP2 DB " Гибкий диск",0 TYP3 DB " Жесткий диск",0 TYP4 DB " Сетевой диск",0 TYP5 DB " Лазерный диск",0 TYP6 DB " Электронный диск",0 INDEX DD OFFSET TYP0 DD OFFSET TYP1 DD OFFSET TYP2 DD OFFSET TYP3 DD OFFSET TYP4 DD OFFSET TYP5 DD OFFSET TYP6 _DATA ENDS ;Сегмент кода. _TEXT SEGMENT DWORD PUBLIC USE32 'CODE' START: ;Получить дескриптор приложения. PUSH 0 CALL GetModuleHandleA@4 MOV [HINST], EAX ;------------------------------------- ;Создать диалоговое окно. PUSH 0 PUSH OFFSET WNDPROC PUSH 0 PUSH OFFSET PA PUSH [HINST] CALL DialogBoxParamA@20 CMP EAX,-1 JNE KOL ;Здесь можно разместить сообщение об ошибке. KOL: ;------------------------------------- PUSH 0 CALL ExitProcess@4 ;------------------------------------- ;------------------------------------- ;Процедура окна. ;Расположение параметров в стеке: ;[ЕВР+014Н] LPARAM ;[ЕВР+10Н] WAPARAM ;[ЕВР+0СН] MES ;[ЕВР+8] HWND WNDPROC PROC PUSH EBP MOV EBP, ESP PUSH EBX PUSH ESI PUSH EDI ;------------------------------------- ;Сообщение при закрытии окна. CMP DWORD PTR [EBP+0CH],WM_CLOSE JNE L1 PUSH 0 PUSH DWORD PTR [EBP+08H] CALL EndDialog@8 JMP FINISH L1: CMP DWORD PTR [EBP+0CH],WM_INITDIALOG JNE L2 L4: ;Здесь анализ устройств и заполнение списка. MOV ECX,65 LOO: PUSH ECX MOV ROO,CL ;Определить тип устройства. PUSH OFFSET ROO CALL GetDriveTypeA@4 ;Полный список. CMP PRIZ,0 JZ _ALL CMP EAX,2 JB L3 _ALL: ;Получить индекс. SHL EAX, 2 PUSH EAX ;Создать строку для списка. PUSH OFFSET ROO PUSH OFFSET BUFER CALL lstrcpy@8 POP EBX PUSH INDEX[EBX] PUSH OFFSET BUFER CALL lstrcat@8 ;Отправить строку в список. PUSH OFFSET BUFER PUSH 0 PUSH LB_ADDSTRING PUSH 101 PUSH DWORD PTR [EBP+08H] CALL SendDlgItemMessageA@20 L3: ;Проверить, не достигнута ли граница цикла. POP ECX INC ECX CMP ECX,91 JNE LOO JMP FINISH L2: CMP DWORD PTR [EBP+0CH],WM_LBUTTONDOWN JNE FINISH PUSH 0 PUSH 0 PUSH LB_RESETCONTENT PUSH 101 PUSH DWORD PTR [EBP+08H] CALL SendDlgItemMessageA@20 CMP PRIZ,0 JE YES_0 MOV PRIZ,0 JMP L4 YES_0: MOV PRIZ,1 JMP L4 FINISH: MOV EAX,0 POP EDI POP ESI POP EBX POP EBP RET 16 WNDPROC ENDP _TEXT ENDS END START
Файл pr76_1.inc.
;Константы. ;Значения, возвращаемые функцией GetDiveType. ;Значения 0 и 1 можно считать признаком ;отсутствия устройства. DRIVE_REMOVABLE equ 2 ; Накопитель на гибком диске. DRIVE_FIXED equ 3 ; Устройство жесткого диска. DRIVE_REMOTE equ 4 ; Сетевой диск. DRIVE_CDROM equ 5 ; Накопитель на лазерном диске. DRIVE_RAMDISK equ 6 ; Электронный диск. ;Сообщение приходит при закрытии окна. WM_CLOSE equ 10h ;Сообщение приходит при создании окна. WM_INITDIALOG equ 110h ;Сообщение приходит при событии ;с элементом на окне. WM_COMMAND equ 111h LB_ADDSTRING equ 180h LB_RESETCONTENT equ 184h WM_LBUTTONDOWN equ 201h ;Прототипы внешних процедур. IFDEF MASM EXTERN lstrcpy@8:NEAR EXTERN lstrcat@8:NEAR EXTERN GetDriveTypeA@4:NEAR EXTERN ExitProcess@4:NEAR EXTERN GetModuleHandleA@4:NEAR EXTERN DialogBoxParamA@20:NEAR EXTERN EndDialog@8:NEAR EXTERN SendDlgItemMessageA@20:NEAR ELSE EXTERN lstrcpy:NEAR EXTERN lstrcat:NEAR EXTERN GetDriveTypeA:NEAR EXTERN ExitProcess:NEAR EXTERN GetModuleHandleA:NEAR EXTERN DialogBoxParamA:NEAR EXTERN EndDialog:NEAR EXTERN SendDlgItemMessageA:NEAR lstrcpy@8 = lstrcpy lstrcat@8 = lstrcat GetDriveTypeA@4 = GetDriveTypeA ExitProcess@4 = ExitProcess GetModuleHandleA@4 = GetModuleHandleA DialogBoxParamA@20 = DialogBoxParamA EndDialog@8 = EndDialog SendDlgItemMessageA@20 = SendDlgItemMessageA ENDIF ;Структуры. ;Структура сообщения. MSGSTRUCT STRUC MSHWND DD ? ;Идентификатор окна, получающего сообщение. MSMESSAGE DD ? ;Идентификатор сообщения. MSWPARAM DD ? ;Доп. информация о сообщении. MSLPARAM DD ? ;Доп. информация о сообщении. MSTIME DD ? ;Время посылки сообщения. MSGSTRUCT ENDS
Файл pr76_1.rc.
//Определение констант. #define WS_SYSMENU 0x00080000L #define WS_MINIMIZEBOX 0x00020000L #define WS_MAXIMIZEBOX 0x00010000L //Элементы на окне должны быть изначально видимы. #define WS_VISIBLE 0x10000000L //Возможность фокусировать элемент //при помощи клавиши TAB. #define WS_TABSTOP 0x00010000L #define WS_VSCROLL 0x00200000L //Стиль - диалоговое окно Windows 95. #define DS_3DLOOK 0x0004L #define LBS_NOTIFY 0x0001L #define LBS_SORT 0x0002L #define LBS_WANTKEYBOARDINPUT 0x0400L //Идентификаторы. #define LIST1 101 //Определение диалогового окна. DIAL1 DIALOG 0, 0, 180, 110 STYLE WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | DS_3DLOOK CAPTION "Определение типов устройств" FONT 8, "Arial" { CONTROL "ListBox1", LIST1, "listbox", WS_VISIBLE | WS_TABSTOP | WS_VSCROLL | LBS_NOTIFY | LBS_WANTKEYBOARDINPUT, 16, 16, 100, 75 }
Результат работы программы представлен на рисунке 1.
Рис.1. Результат работы приложения
Трансляция программы:
ML /с /coff /DMASM pr76_1.asm rc pr76_1.rc LINK /SUBSYSTEM:WINDOWS pr76_1.obj pr76_1.res
TASM32 /ml pr76_1.asm brcc32 pr76_1.rc TLINK32 -aa pr76_1.obj,,,,,pr76_1.res
После того как вы определили, что данное устройство является сетевым, может возникнуть вторая задача: определить статус устройства. Под статусом в данном случае мы понимаем три возможных ситуации:
Можно поступить следующим образом. Для проверки статуса устройства можно использовать две функции: CreateFile и GetDiskFreeSpace. С первой функцией вы уже знакомы, с помощью второй функции можно определить объем свободного места на диске. Если данное устройство позволяет создать файл (файл лучше создавать с атрибутом "удалить после закрытия", и операционная система сама выполнит процедуру удаления) и прочесть данные об устройстве, следовательно, оно открыто для чтения и записи. Если устройство позволяет прочитать данные о нем, но не позволяет создать файл, следовательно, устройство открыто только для чтения. Наконец, если не разрешено ни то, ни другое, следовательно, устройство недоступно. Такой бесхитростный подход, однако, работает весьма эффективно.
На следующем шаге мы рассмотрим доступ к ресурсам локальной сети.