Средства разработки приложений


Краткие комментарии к динамической библиотеке


Процедура libEntry является точкой входа в динамическую библиотеку, её не надо объявлять как экспортируемую, загрузчик сам определяет её местонахождение. LibEntry может вызываться в четырёх случаях:

  • при проецировании библиотеки в адресное пространство процесса (DLL_PROCESS_ATTACH);
  • при первом вызове библиотеки из потока (DLL_THREAD_ATTACH), например, с помощью функции LoadLibrary;
  • при выгрузке библиотеки потоком (DLL_THREAD_DETACH);
  • при выгрузке библиотеки из адресного пространства процесса (DLL_PROCESS_DETACH).

В нашем примере обрабатывается только первое из событий DLL_PROCESS_ATTACH. При обработке данного события библиотека запрашивает версию OS сохраняет её, а также свой handle of instance.

Библиотека содержит только одну экспортируемую функцию, которая собственно не требует пояснений. Вы, пожалуй, можете обратить внимание на то, как производится запись преобразованных значений. Интересна система адресации посредством двух регистров общего назначения: ebx + ecx, она позволяет нам использовать регистр ecx одновременно и как счётчик и как составную часть адреса.

Пример 3. Оконное приложение Файл dmenu.asm Ideal P586 Radix 16 Model flat struc WndClassEx cbSize dd 0 style dd 0 lpfnWndProc dd 0 cbClsExtra dd 0 cbWndExtra dd 0 hInstance dd 0 hIcon dd 0 hCursor dd 0 hbrBackground dd 0 lpszMenuName dd 0 lpszClassName dd 0 hIconSm dd 0 ends WndClassEx struc Point left dd 0 top dd 0 right dd 0 bottom dd 0 ends Point struc msgStruc hwnd dd 0 message dd 0 wParam dd 0 lParam dd 0 time dd 0 pt Point <> ends msgStruc MyMenu = 0065 ID_OPEN = 9C41 ID_SAVE = 9C42 ID_EXIT = 9C43 CS_VREDRAW = 0001 CS_HREDRAW = 0002 IDI_APPLICATION = 7F00 IDC_ARROW = 7F00 COLOR_WINDOW = 5 WS_EX_WINDOWEDGE = 00000100 WS_EX_CLIENTEDGE = 00000200 WS_EX_OVERLAPPEDWINDOW = WS_EX_WINDOWEDGE OR WS_EX_CLIENTEDGE WS_OVERLAPPED = 00000000 WS_CAPTION = 00C00000 WS_SYSMENU = 00080000 WS_THICKFRAME = 00040000 WS_MINIMIZEBOX = 00020000 WS_MAXIMIZEBOX = 00010000 WS_OVERLAPPEDWINDOW = WS_OVERLAPPED OR \ WS_CAPTION OR \ WS_SYSMENU OR \ WS_THICKFRAME OR \ WS_MINIMIZEBOX OR \ WS_MAXIMIZEBOX CW_USEDEFAULT = 80000000 SW_SHOW = 5 WM_COMMAND = 0111 WM_DESTROY = 0002 WM_CLOSE = 0010 MB_OK = 0 PROCTYPE ptGetModuleHandle stdcall \ lpModuleName :dword PROCTYPE ptLoadIcon stdcall \ hInstance :dword, \ lpIconName :dword PROCTYPE ptLoadCursor stdcall \ hInstance :dword, \ lpCursorName :dword PROCTYPE ptLoadMenu stdcall \ hInstance :dword, \ lpMenuName :dword PROCTYPE ptRegisterClassEx stdcall \ lpwcx :dword PROCTYPE ptCreateWindowEx stdcall \ dwExStyle :dword, \ lpClassName :dword, \ lpWindowName :dword, \ dwStyle :dword, \ x :dword, \ y :dword, \ nWidth :dword, \ nHeight :dword, \ hWndParent :dword, \ hMenu :dword, \ hInstance :dword, \ lpParam :dword PROCTYPE ptShowWindow stdcall \ hWnd :dword, \ nCmdShow :dword PROCTYPE ptUpdateWindow stdcall \ hWnd :dword PROCTYPE ptGetMessage stdcall \ pMsg :dword, \ hWnd :dword, \ wMsgFilterMin :dword, \ wMsgFilterMax :dword PROCTYPE ptTranslateMessage stdcall \ lpMsg :dword PROCTYPE ptDispatchMessage stdcall \ pmsg :dword PROCTYPE ptSetMenu stdcall \ hWnd :dword, \ hMenu :dword PROCTYPE ptPostQuitMessage stdcall \ nExitCode :dword PROCTYPE ptDefWindowProc stdcall \ hWnd :dword, \ Msg :dword, \ wParam :dword, \ lParam :dword PROCTYPE ptSendMessage stdcall \ hWnd :dword, \ Msg :dword, \ wParam :dword, \ lParam :dword PROCTYPE ptMessageBox stdcall \ hWnd :dword, \ lpText :dword, \ lpCaption :dword, \ uType :dword PROCTYPE ptExitProcess stdcall \ exitCode :dword extrn GetModuleHandleA :ptGetModuleHandle extrn LoadIconA :ptLoadIcon extrn LoadCursorA :ptLoadCursor extrn RegisterClassExA :ptRegisterClassEx extrn LoadMenuA :ptLoadMenu extrn CreateWindowExA :ptCreateWindowEx extrn ShowWindow :ptShowWindow extrn UpdateWindow :ptUpdateWindow extrn GetMessageA :ptGetMessage extrn TranslateMessage :ptTranslateMessage extrn DispatchMessageA :ptDispatchMessage extrn SetMenu :ptSetMenu extrn PostQuitMessage :ptPostQuitMessage extrn DefWindowProcA :ptDefWindowProc extrn SendMessageA :ptSendMessage extrn MessageBoxA :ptMessageBox extrn ExitProcess :ptExitProcess UDataSeg hInst dd ? hWnd dd ? IFNDEF VER1 hMenu dd ? ENDIF DataSeg msg msgStruc <> classTitle db 'Menu demo', 0 wndTitle db 'Demo program', 0 msg_open_txt db 'You selected open', 0 msg_open_tlt db 'Open box', 0 msg_save_txt db 'You selected save', 0 msg_save_tlt db 'Save box', 0 CodeSeg Start: call GetModuleHandleA, 0 ; не обязательно, но желательно mov [hInst],eax sub esp,SIZE WndClassEx ; отведём место в стеке под структуру mov [(WndClassEx esp).cbSize],SIZE WndClassEx mov [(WndClassEx esp).style],CS_HREDRAW or CS_VREDRAW mov [(WndClassEx esp).lpfnWndProc],offset WndProc mov [(WndClassEx esp).cbWndExtra],0 mov [(WndClassEx esp).cbClsExtra],0 mov [(WndClassEx esp).hInstance],eax call LoadIconA, 0, IDI_APPLICATION mov [(WndClassEx esp).hIcon],eax call LoadCursorA, 0, IDC_ARROW mov [(WndClassEx esp).hCursor],eax mov [(WndClassEx esp).hbrBackground],COLOR_WINDOW IFDEF VER1 mov [(WndClassEx esp).lpszMenuName],MyMenu ELSE mov [(WndClassEx esp).lpszMenuName],0 ENDIF mov [(WndClassEx esp).lpszClassName],offset classTitle mov [(WndClassEx esp).hIconSm],0 call RegisterClassExA, esp ; зарегистрируем класс окна add esp,SIZE WndClassEx ; восстановим стек ; и создадим окно IFNDEF VER2 call CreateWindowExA, WS_EX_OVERLAPPEDWINDOW, \ extended window style offset classTitle, \ pointer to registered class name offset wndTitle,\ pointer to window name WS_OVERLAPPEDWINDOW, \ window style CW_USEDEFAULT, \ horizontal position of window CW_USEDEFAULT, \ vertical position of window CW_USEDEFAULT, \ window width CW_USEDEFAULT, \ window height 0, \ handle to parent or owner window 0, \ handle to menu, or child-window identifier [hInst], \ handle to application instance 0 ; pointer to window-creation data ELSE call LoadMenu, hInst, MyMenu mov [hMenu],eax call CreateWindowExA, WS_EX_OVERLAPPEDWINDOW, \ extended window style offset classTitle, \ pointer to registered class name offset wndTitle, \ pointer to window name WS_OVERLAPPEDWINDOW, \ window style CW_USEDEFAULT, \ horizontal position of window CW_USEDEFAULT, \ vertical position of window CW_USEDEFAULT, \ window width CW_USEDEFAULT, \ window height 0, \ handle to parent or owner window eax, \ handle to menu, or child-window identifier [hInst], \ handle to application instance 0 ; pointer to window-creation data ENDIF mov [hWnd],eax call ShowWindow, eax, SW_SHOW ; show window call UpdateWindow, [hWnd] ; redraw window IFDEF VER3 call LoadMenuA, [hInst], MyMenu mov [hMenu],eax call SetMenu, [hWnd], eax ENDIF msg_loop: call GetMessageA, offset msg, 0, 0, 0 or ax,ax jz exit call TranslateMessage, offset msg call DispatchMessageA, offset msg jmp msg_loop exit: call ExitProcess, 0 public stdcall WndProc proc WndProc stdcall arg @@hwnd: dword, @@msg: dword, @@wPar: dword, @@lPar: dword mov eax,[@@msg] cmp eax,WM_COMMAND je @@command cmp eax,WM_DESTROY jne @@default call PostQuitMessage, 0 xor eax,eax jmp @@ret @@default: call DefWindowProcA, [@@hwnd], [@@msg], [@@wPar], [@@lPar] @@ret: ret @@command: mov eax,[@@wPar] cmp eax,ID_OPEN je @@open cmp eax,ID_SAVE je @@save call SendMessageA, [@@hwnd], WM_CLOSE, 0, 0 xor eax,eax jmp @@ret @@open: mov eax, offset msg_open_txt mov edx, offset msg_open_tlt jmp @@mess @@save: mov eax, offset msg_save_txt mov edx, offset msg_save_tlt @@mess: call MessageBoxA, 0, eax, edx, MB_OK xor eax,eax jmp @@ret endp WndProc end Start

Комментарии к программе

Здесь мне хотелось в первую очередь продемонстрировать использование прототипов функций API Win32.


Начало  Назад  Вперед