346 lines
7.6 KiB
HTML
346 lines
7.6 KiB
HTML
; =============================================================================
|
||
; Модуль : Service Dispatcher
|
||
; Файл : core/dispatcher.inc
|
||
; Назначение : Функции диспетчера сервисов
|
||
; =============================================================================
|
||
|
||
include 'dispatcher_macros.inc'
|
||
|
||
; =============================================================================
|
||
; Данные диспетчера
|
||
; =============================================================================
|
||
align 4
|
||
dispatcher_active_events dd 0 ; OR всех event_mask включенных сервисов
|
||
dispatcher_active_caps dd 0 ; OR всех caps_mask включенных сервисов
|
||
|
||
|
||
; dispatcher_find_by_id — Найти сервис по ID
|
||
;
|
||
; Вход : svc_id — числовой идентификатор сервиса
|
||
; Выход: eax = SERVICE_ENTRY* или 0 если не найден
|
||
proc dispatcher_find_by_id stdcall uses ecx esi, svc_id:dword
|
||
mov ecx, [services_count]
|
||
test ecx, ecx
|
||
jz .not_found
|
||
|
||
mov esi, services_table
|
||
mov eax, [svc_id]
|
||
|
||
.loop:
|
||
cmp [esi + SERVICE_ENTRY.id], eax
|
||
je .found
|
||
|
||
add esi, sizeof.SERVICE_ENTRY
|
||
dec ecx
|
||
jnz .loop
|
||
|
||
.not_found:
|
||
xor eax, eax
|
||
ret
|
||
|
||
.found:
|
||
mov eax, esi
|
||
ret
|
||
endp
|
||
|
||
; Включить сервис по ID
|
||
proc dispatcher_enable_by_id stdcall, svc_id:dword
|
||
stdcall dispatcher_find_by_id, [svc_id]
|
||
test eax, eax
|
||
jz .not_found
|
||
|
||
stdcall dispatcher_enable_entry, eax
|
||
ret
|
||
|
||
.not_found:
|
||
mov eax, -1
|
||
ret
|
||
endp
|
||
|
||
; Выключить сервис по ID
|
||
proc dispatcher_disable_by_id stdcall, svc_id:dword
|
||
stdcall dispatcher_find_by_id, [svc_id]
|
||
test eax, eax
|
||
jz .not_found
|
||
|
||
stdcall dispatcher_disable_entry, eax
|
||
ret
|
||
|
||
.not_found:
|
||
mov eax, -1
|
||
ret
|
||
endp
|
||
|
||
; Включить сервис по указателю на SERVICE_ENTRY
|
||
proc dispatcher_enable_entry stdcall uses ebx esi, entry_ptr:dword
|
||
mov esi, [entry_ptr]
|
||
|
||
; Уже включен?
|
||
cmp dword [esi + SERVICE_ENTRY.enabled], 1
|
||
je .already_enabled
|
||
|
||
; Вызвать fn_enable если есть
|
||
mov eax, [esi + SERVICE_ENTRY.fn_enable]
|
||
test eax, eax
|
||
jz .no_enable_fn
|
||
|
||
push esi
|
||
call eax
|
||
pop esi
|
||
|
||
test eax, eax
|
||
jnz .enable_failed
|
||
|
||
.no_enable_fn:
|
||
; Включить
|
||
mov dword [esi + SERVICE_ENTRY.enabled], 1
|
||
|
||
; Добавить маски
|
||
mov eax, [esi + SERVICE_ENTRY.event_mask]
|
||
or [dispatcher_active_events], eax
|
||
|
||
mov eax, [esi + SERVICE_ENTRY.caps_mask]
|
||
or [dispatcher_active_caps], eax
|
||
|
||
DEBUGF 2, "[VBoxGuest] [Dispatcher] Enabled service ID=%d\n", [esi + SERVICE_ENTRY.id]
|
||
|
||
.already_enabled:
|
||
xor eax, eax
|
||
ret
|
||
|
||
.enable_failed:
|
||
DEBUGF 2, "[VBoxGuest] [Dispatcher] Enable failed: 0x%x\n", eax
|
||
ret
|
||
endp
|
||
|
||
; Выключить сервис по указателю
|
||
proc dispatcher_disable_entry stdcall uses ebx esi, entry_ptr:dword
|
||
mov esi, [entry_ptr]
|
||
|
||
; Уже выключен?
|
||
cmp dword [esi + SERVICE_ENTRY.enabled], 0
|
||
je .already_disabled
|
||
|
||
; Вызвать fn_disable если есть
|
||
mov eax, [esi + SERVICE_ENTRY.fn_disable]
|
||
test eax, eax
|
||
jz .no_disable_fn
|
||
|
||
push esi
|
||
call eax
|
||
pop esi
|
||
|
||
.no_disable_fn:
|
||
; Выключить
|
||
mov dword [esi + SERVICE_ENTRY.enabled], 0
|
||
|
||
; Пересчитать активные маски
|
||
call dispatcher_recalc_masks
|
||
|
||
DEBUGF 2, "[VBoxGuest] [Dispatcher] Disabled service ID=%d\n", [esi + SERVICE_ENTRY.id]
|
||
|
||
.already_disabled:
|
||
xor eax, eax
|
||
ret
|
||
endp
|
||
|
||
; dispatcher_disable_all — Выключить все сервисы
|
||
proc dispatcher_disable_all uses ecx esi
|
||
DEBUGF 2, "[VBoxGuest] [Dispatcher] Disabling all services\n"
|
||
|
||
mov ecx, [services_count]
|
||
test ecx, ecx
|
||
jz .done
|
||
|
||
mov esi, services_table
|
||
|
||
.loop:
|
||
stdcall dispatcher_disable_entry, esi
|
||
add esi, sizeof.SERVICE_ENTRY
|
||
dec ecx
|
||
jnz .loop
|
||
|
||
.done:
|
||
ret
|
||
endp
|
||
|
||
; Инициализация всех сервисов
|
||
proc dispatcher_init_all uses ebx ecx esi
|
||
DEBUGF 2, "[VBoxGuest] [Dispatcher] Initializing %d services...\n", [services_count]
|
||
|
||
mov ecx, [services_count]
|
||
test ecx, ecx
|
||
jz .done
|
||
|
||
mov esi, services_table
|
||
|
||
.loop:
|
||
mov eax, [esi + SERVICE_ENTRY.fn_init]
|
||
test eax, eax
|
||
jz .next
|
||
|
||
DEBUGF 2, "[VBoxGuest] [Dispatcher] Init service ID=%d, name=%s\n", [esi + SERVICE_ENTRY.id], [esi + SERVICE_ENTRY.name_ptr]
|
||
push ecx esi
|
||
call eax
|
||
pop esi ecx
|
||
|
||
test eax, eax
|
||
jnz .init_failed
|
||
|
||
.next:
|
||
add esi, sizeof.SERVICE_ENTRY
|
||
dec ecx
|
||
jnz .loop
|
||
|
||
.done:
|
||
DEBUGF 2, "[VBoxGuest] [Dispatcher] All services initialized\n"
|
||
xor eax, eax
|
||
ret
|
||
|
||
.init_failed:
|
||
DEBUGF 2, "[VBoxGuest] [Dispatcher] Service ID=%d init failed: 0x%x\n", [esi + SERVICE_ENTRY.id], eax
|
||
jmp .next
|
||
endp
|
||
|
||
; Включить сервисы с autostart=1
|
||
proc dispatcher_enable_autostart uses ecx esi
|
||
DEBUGF 2, "[VBoxGuest] [Dispatcher] Enabling autostart services...\n"
|
||
|
||
mov ecx, [services_count]
|
||
test ecx, ecx
|
||
jz .done
|
||
|
||
mov esi, services_table
|
||
|
||
.loop:
|
||
cmp dword [esi + SERVICE_ENTRY.autostart], 1
|
||
jne .next
|
||
|
||
push ecx esi
|
||
stdcall dispatcher_enable_entry, esi
|
||
pop esi ecx
|
||
|
||
.next:
|
||
add esi, sizeof.SERVICE_ENTRY
|
||
dec ecx
|
||
jnz .loop
|
||
|
||
.done:
|
||
DEBUGF 2, "[VBoxGuest] [Dispatcher] Autostart done, events=0x%x, caps=0x%x\n", \
|
||
[dispatcher_active_events], [dispatcher_active_caps]
|
||
ret
|
||
endp
|
||
|
||
; Пересчитать активные маски
|
||
proc dispatcher_recalc_masks uses ebx ecx edx esi
|
||
xor edx, edx ; events
|
||
xor ebx, ebx ; caps
|
||
|
||
mov ecx, [services_count]
|
||
test ecx, ecx
|
||
jz .done
|
||
|
||
mov esi, services_table
|
||
|
||
.loop:
|
||
cmp dword [esi + SERVICE_ENTRY.enabled], 1
|
||
jne .next
|
||
|
||
or edx, [esi + SERVICE_ENTRY.event_mask]
|
||
or ebx, [esi + SERVICE_ENTRY.caps_mask]
|
||
|
||
.next:
|
||
add esi, sizeof.SERVICE_ENTRY
|
||
dec ecx
|
||
jnz .loop
|
||
|
||
.done:
|
||
mov [dispatcher_active_events], edx
|
||
mov [dispatcher_active_caps], ebx
|
||
ret
|
||
endp
|
||
|
||
; Разослать события включенным сервисам
|
||
proc dispatcher_dispatch stdcall uses ebx ecx edx esi, event_mask:dword
|
||
mov edx, [event_mask]
|
||
test edx, edx
|
||
jz .done
|
||
|
||
mov ecx, [services_count]
|
||
test ecx, ecx
|
||
jz .done
|
||
|
||
mov esi, services_table
|
||
|
||
.loop:
|
||
; Включен?
|
||
cmp dword [esi + SERVICE_ENTRY.enabled], 0
|
||
je .next
|
||
|
||
; Есть совпадение событий?
|
||
mov eax, [esi + SERVICE_ENTRY.event_mask]
|
||
test eax, edx
|
||
jz .next
|
||
|
||
; Есть обработчик?
|
||
mov eax, [esi + SERVICE_ENTRY.fn_on_event]
|
||
test eax, eax
|
||
jz .next
|
||
|
||
; Вызвать fn_on_event(event_mask)
|
||
push ecx edx esi
|
||
mov eax, edx
|
||
call [esi + SERVICE_ENTRY.fn_on_event]
|
||
pop esi edx ecx
|
||
|
||
.next:
|
||
add esi, sizeof.SERVICE_ENTRY
|
||
dec ecx
|
||
jnz .loop
|
||
|
||
.done:
|
||
ret
|
||
endp
|
||
|
||
; Вызвать fn_on_tick у включенных сервисов
|
||
proc dispatcher_tick_all uses eax ecx esi
|
||
mov ecx, [services_count]
|
||
test ecx, ecx
|
||
jz .done
|
||
|
||
mov esi, services_table
|
||
|
||
.loop:
|
||
cmp dword [esi + SERVICE_ENTRY.enabled], 0
|
||
je .next
|
||
|
||
mov eax, [esi + SERVICE_ENTRY.fn_on_tick]
|
||
test eax, eax
|
||
jz .next
|
||
|
||
push ecx esi
|
||
call eax
|
||
pop esi ecx
|
||
|
||
.next:
|
||
add esi, sizeof.SERVICE_ENTRY
|
||
dec ecx
|
||
jnz .loop
|
||
|
||
.done:
|
||
ret
|
||
endp
|
||
|
||
|
||
; Получить активную маску событий
|
||
proc dispatcher_get_active_events
|
||
mov eax, [dispatcher_active_events]
|
||
ret
|
||
endp
|
||
|
||
; Получить активную маску capabilities
|
||
proc dispatcher_get_active_caps
|
||
mov eax, [dispatcher_active_caps]
|
||
ret
|
||
endp
|