W czasie tworzenia aplikacji często zachodzi potrzeba zidentyfikowania poszczególnych urządzeń podłączonych do komputera. API udostępnia specjalną funkcję do tego przeznaczoną.
Jej nazwa to GetDriveTypeA .
Tworzymy program, który na podstawie litery zasobu wypisuje nam napędy optyczne. Na początku deklarujemy wszystkie stałe , funkcje i dane programu:
.586 ;typ instrukcji procesora
.MODEL
FLAT,STDCALL
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib
IDC_BTN1 EQU 101
IDC_LST2 EQU 103
IDC_LST1 EQU 102
LB_ADDSTRING EQU 180h
LB_RESETCONTENT EQU 184h
WM_INITDIALOG EQU 110h
WM_CLOSE EQU 10h
WM_COMMAND EQU 111h
EXTERN lstrcpyA@8:NEAR
EXTERN lstrcatA@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
.DATA?
HINST DD ?
.DATA
PA DB 'IDD_DLG1', 0 ;nazwa dialogu
APOS DB "?:\", 0
BUFER DB 40 DUP (0)
Ciąg znaków APOS to argument funkcji GetDriveTypeA. Funkcja zwraca odpowiednią wartość w zależności od rodzaju wykrytego urządzenia. W przypadku napędów optycznych CD-ROM/DVD-ROM jest to wartość 5. Pozostałe wartości, za pomocą których identyfikujemy odpowiednie urządzenie - można znaleźć na stronie MSDN Library. Sekcja kodu programu wygląda następująco:
.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
;parametry:
;[EBP +14H] LPARAM
;[EBP +10H] WPARAM
;[EBP +0CH] MES
;[EBP +8] HWND
WNDPROC PROC
PUSH EBP
MOV EBP,ESP
PUSH EBX
PUSH ESI
PUSH EDI
CMP DWORD PTR [EBP + 0CH],WM_CLOSE;komunikat związany ze zniszczeniem okna
JNE NIEKONCZ
PUSH 0
PUSH DWORD PTR [EBP+ 08H]
CALL EndDialog@8
JMP KONCZ
NIEKONCZ:
CMP DWORD PTR [EBP + 0CH],WM_COMMAND;komunikat związany z kontrolkami
JNE KONCZ
CMP WORD PTR [EBP + 10H],IDC_BTN1 ;czy uruchamiamy wyszukiwanie napędów ;optycznych?
JNE KONCZ
PUSH 0
PUSH 0
PUSH LB_RESETCONTENT
PUSH IDC_LST1
PUSH DWORD PTR [EBP+ 08H]
CALL SendDlgItemMessageA@20
MOV EDX,65
Na początku sekcji standardowo tworzymy okno dialogowe i definiujemy funkcję obsługi okna. Za pomocą przycisku umieszczonego w dialogu, będziemy uruchamiać sekcję kodu odpowiedzialną za wypełnianie odpowiednimi literami listy, identyfikującymi nasze napędy CD-ROM/DVD-ROM. W pierwszym kroku zawsze czyścimy listę podając jako parametr LB_RESETCONTENT funkcji SendDlgItemMessageA@20. Do rejestru EDX kopiujemy wartość 65 - kod ASCII litery A . Od niej zaczynamy przeszukiwanie, zwiększając ją w każdym przebiegu pętli i uzyskując tym samym kolejne kody ASCII dużych liter:
PETLA:
PUSH EDX
MOV APOS,DL
PUSH OFFSET APOS
CALL GetDriveTypeA@4
CMP EAX,5
JNE OMIN
PUSH OFFSET APOS
PUSH 0
PUSH LB_ADDSTRING
PUSH IDC_LST1
PUSH DWORD PTR [EBP+ 08H]
CALL SendDlgItemMessageA@20
OMIN:
POP EDX
CMP EDX,91
JE KONCZ
INC EDX
JMP PETLA
KONCZ:
FINISH:
XOR EAX,EAX
POP EDI
POP ESI
POP EBX
POP EBP
RET
WNDPROC ENDP
END Start
Przykładowe wywołanie programu przedstawione jest na rysunku poniżej:
Pełny kod programu przedstawiony jest na poniższym listingu:
.586 ;typ instrukcji procesora
.MODEL
FLAT,STDCALL
includelib c:\masm32\lib\user32.lib
includelib c:\masm32\lib\kernel32.lib
IDC_BTN1 EQU 101
IDC_LST1 EQU 102
LB_ADDSTRING EQU 180h
LB_RESETCONTENT EQU 184h
WM_INITDIALOG EQU 110h
WM_CLOSE EQU 10h
WM_COMMAND EQU 111h
EXTERN lstrcpyA@8:NEAR
EXTERN lstrcatA@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
.DATA?
HINST DD ?
.DATA
PA DB 'IDD_DLG1', 0 ;nazwa dialogu
APOS DB "?:\", 0
BUFER DB 40 DUP (0)
.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
;parametry:
;[EBP +14H] LPARAM
;[EBP +10H] WPARAM
;[EBP +0CH] MES
;[EBP +8] HWND
WNDPROC PROC
PUSH EBP
MOV EBP,ESP
PUSH EBX
PUSH ESI
PUSH EDI
CMP DWORD PTR [EBP + 0CH],WM_CLOSE;komunikat związany ze zniszczeniem okna
JNE NIEKONCZ
PUSH 0
PUSH DWORD PTR [EBP+ 08H]
CALL EndDialog@8
JMP KONCZ
NIEKONCZ:
CMP DWORD PTR [EBP + 0CH],WM_COMMAND;komunikat związany z kontrolkami
JNE KONCZ
CMP WORD PTR [EBP + 10H],IDC_BTN1 ;czy uruchamiamy wyszukiwanie napędów ;optycznych?
JNE KONCZ
PUSH 0
PUSH 0
PUSH LB_RESETCONTENT
PUSH IDC_LST1
PUSH DWORD PTR [EBP+ 08H]
CALL SendDlgItemMessageA@20
MOV EDX,65
PETLA:
PUSH EDX
MOV APOS,DL
PUSH OFFSET APOS
CALL GetDriveTypeA@4
CMP EAX,5
JNE OMIN
PUSH OFFSET APOS
PUSH 0
PUSH LB_ADDSTRING
PUSH IDC_LST1
PUSH DWORD PTR [EBP+ 08H]
CALL SendDlgItemMessageA@20
OMIN:
POP EDX
CMP EDX,91
JE KONCZ
INC EDX
JMP PETLA
KONCZ:
FINISH:
XOR EAX,EAX
POP EDI
POP ESI
POP EBX
POP EBP
RET
WNDPROC ENDP
END Start
Plik .rc programu wygląda następująco:
#include "..\include\resource.h"
#define IDC_BTN1 101
#define IDC_LST1 102
#define IDC_STC1 1001
IDD_DLG1 DIALOGEX 0,10,229,145
CAPTION "Urządzenia"
FONT 8,"MS Sans Serif", 0, 0, 0
STYLE WS_VISIBLE|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX
BEGIN
CONTROL "Wyświetl",IDC_BTN1,"Button",WS_CHILD|WS_VISIBLE|WS_TABSTOP,84,99,54,15
CONTROL "",IDC_LST1,"ListBox",WS_CHILD|WS_VISIBLE|WS_TABSTOP
|LBS_NOINTEGRALHEIGHT|LBS_HASSTRINGS|LBS_NOTIFY,85,30,54,63,WS_EX_CLIENTEDGE
CONTROL "Napędy optyczne:",IDC_STC1,"Static",WS_CHILD|WS_VISIBLE,84,12,75,9
END
Zmodyfikować kod przykładu tak, aby program dodatkowo wyświetlał także litery wszystkich dysków twardych i partycji. Przykładowe wywołanie programu z jednym dyskiem twardym podzielonym na dwie partycje: C:\ i D:\, przedstawiono na rysunku poniżej - Rys.2.