Files
kolibrios/drivers/vboxguest/services/shared_folders/shared_folders.inc
lex ab59015ded
Some checks failed
Build system / Check kernel codestyle (pull_request) Has been cancelled
Build system / Build (pull_request) Has been cancelled
Add VBoxGuest driver code
2026-03-04 21:16:17 +03:00

1120 lines
31 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
; =============================================================================
; Модуль : VBox SharedFolder Service
; Назначение : Подключение VBox shared folders как ФС в KolibriOS
; Файл : services/shared_folders/shared_folders.inc
; Протокол : HGCM (VBoxSharedFolders)
;
; Функционал:
; - Подключение к HGCM сервису VBoxSharedFolders
; - Включение UTF-8 режима (SHFL_FN_SET_UTF8)
; - Запрос и подключение всех shared folders
; - Регистрация диска через DiskAdd + ФС через FsAdd
; - Обслуживание ReadFolder/Read/GetFileInfo через SHFL
; =============================================================================
svc_shfl_name db "SHARED_FOLDERS", 0
align 4
sz_shfl_hgcm_service db 'VBoxSharedFolders', 0
; --- Data ---
align 4
sf_state SF_STATE
; Данные для диска
align 4
vboxsf_data VBOXSF_DISK
; Буферы выделяются динамически в shfl_init, указатели хранятся в sf_state
; Состояние
align 4
sf_map_count dd 0 ; Количество найденных mappings
sf_list_resume dd 0 ; Resume point для LIST пагинации
sf_list_total dd 0 ; Общее количество файлов (все страницы)
; vboxsf_add_folder Добавить папку в массив vboxsf_data
proc vboxsf_add_folder stdcall uses ebx ecx edx esi edi, root:dword, name_ptr:dword
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] add_folder: root=%d name='%s'\n", [root], [name_ptr]
; Проверить лимит
cmp dword [vboxsf_data.count], 32
jae .error
; Выделить память для SF_FOLDER
invoke KernelAlloc, 4096
test eax, eax
jz .error
; Инициализировать структуру
mov edi, eax
push edi
; Очистить
push eax
xor eax, eax
mov ecx, sizeof.SF_FOLDER / 4
rep stosd
pop eax
pop edi
; Сохранить указатель в массив
mov ecx, [vboxsf_data.count]
mov [vboxsf_data.folders + ecx*4], edi
; Установить root handle
mov edx, [root]
mov [edi + SF_FOLDER.root_handle], edx
; Установить active
mov dword [edi + SF_FOLDER.active], 1
; Скопировать имя папки (UTF-8)
mov esi, [name_ptr]
lea edi, [edi + SF_FOLDER.name]
mov ecx, 255
.copy_name:
lodsb
stosb
test al, al
jz .name_done
dec ecx
jnz .copy_name
.name_done:
mov byte [edi], 0 ; гарантировать null-terminator
; Увеличить счётчик папок
inc dword [vboxsf_data.count]
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] folder added, total count: %d\n", [vboxsf_data.count]
xor eax, eax
ret
.error:
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] add_folder: failed\n"
mov eax, -1
ret
endp
; vboxsf_register_disk Зарегистрировать виртуальный диск + ФС в системе
; Смещения в структуре DISK ядра (вычислены из kernel/trunk/blkdev/disk.inc + const.inc)
; MUTEX = LHEAD(8) + count(4) = 12 bytes
; DISKMEDIAINFO = Flags(4) + SectorSize(4) + Capacity(8) + LastSessionSector(4) = 20 bytes
; DISK layout: Next(4) + Prev(4) + Functions(4) + Name(4) + UserData(4) +
; DriverFlags(4) + RefCount(4) + MediaLock(12) +
; MediaInserted(1) + MediaUsed(1) + pad(2) + MediaRefCount(4) +
; MediaInfo(20) = 68
KDISK_OFS_NUMPARTITIONS = 68
KDISK_OFS_PARTITIONS = 72
proc vboxsf_register_disk stdcall uses ebx ecx edx esi edi
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] Registering filesystem...\n"
; Проверить что есть хотя бы одна папка
cmp dword [vboxsf_data.count], 0
je .no_folders
; --- Шаг 1: DiskAdd создать виртуальный диск ---
; НЕ используем FsAdd в ядре баг: fs_add итерирует ВСЕ диски
; включая те, у которых NumPartitions не инициализирован (CD без диска),
; что вызывает GPF. Вместо этого вручную ставим FSUserFunctions.
invoke DiskAdd, vboxsf_disk_functions, sz_vboxsf_diskname, vboxsf_data, 0
DEBUGF __DEBUG_SF__, "[DiskAdd] result eax=0x%x\n", eax
test eax, eax
jz .disk_failed
mov [vboxsf_data.disk_handle], eax
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] DiskAdd OK, handle=0x%x\n", eax
; --- Шаг 2: DiskMediaChanged ядро создаст raw-раздел ---
; vboxsf_read_sectors вернёт нули нет MBR disk_add_partition создаст
; один раздел с default_fs_functions (ни одна встроенная ФС не узнает).
invoke DiskMediaChanged, [vboxsf_data.disk_handle], 1
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] DiskMediaChanged done\n"
; --- Шаг 3: Вручную установить наши FSUserFunctions на раздел ---
mov eax, [vboxsf_data.disk_handle]
mov ecx, [eax + KDISK_OFS_NUMPARTITIONS]
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] NumPartitions=%d\n", ecx
test ecx, ecx
jz .no_partitions
mov ecx, [eax + KDISK_OFS_PARTITIONS] ; ecx = Partitions array
mov ecx, [ecx] ; ecx = first PARTITION*
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] Partition[0]=0x%x, old FSUserFuncs=0x%x\n", ecx, [ecx + KPARTITION_OFS_FSUSERFUNCTIONS]
; Заменить default_fs_functions на наши
mov dword [ecx + KPARTITION_OFS_FSUSERFUNCTIONS], vboxsf_user_functions
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] Set FSUserFunctions=0x%x\n", vboxsf_user_functions
; Верификация: прочитать обратно и показать содержимое таблицы
mov eax, [ecx + KPARTITION_OFS_FSUSERFUNCTIONS]
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] Verify readback=0x%x\n", eax
mov eax, [vboxsf_user_functions + 0]
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] Table[0] free=0x%x\n", eax
mov eax, [vboxsf_user_functions + 4]
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] Table[1] count=%d\n", eax
mov eax, [vboxsf_user_functions + 8]
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] Table[2] subfn0_Read=0x%x\n", eax
mov eax, [vboxsf_user_functions + 12]
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] Table[3] subfn1_ReadFolder=0x%x\n", eax
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] Disk + FS registered, accessible via /vbox/1/\n"
mov eax, [vboxsf_data.disk_handle]
ret
.no_folders:
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] No folders to register\n"
xor eax, eax
ret
.no_partitions:
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] ERROR: DiskMediaChanged created 0 partitions\n"
xor eax, eax
ret
.disk_failed:
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] DiskAdd failed\n"
xor eax, eax
ret
endp
; shfl_init Инициализация SharedFolder сервиса
proc shfl_init uses ebx ecx edx esi edi
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] Initializing SharedFolders...\n"
; Проверка что HGCM готов
mov eax, [vbox_device.hgcm_connect_virt]
test eax, eax
jz .hgcm_not_ready
; Уже подключены?
cmp dword [sf_state.connected], 1
je .already_connected
; --- Выделить init-буферы ---
invoke KernelAlloc, 4096 ; sf_packet
test eax, eax
jz .alloc_fail
mov [sf_state.packet_ptr], eax
invoke KernelAlloc, 4096 ; sf_listbuf
test eax, eax
jz .alloc_fail_free1
mov [sf_state.listbuf_ptr], eax
invoke KernelAlloc, 4096 ; small_bufs: mappings+namebuf+cp866+dir_path+createparms
test eax, eax
jz .alloc_fail_free2
mov [sf_state.small_bufs_ptr], eax
; Вычислить указатели внутри small_bufs
lea ecx, [eax + 0]
mov [sf_state.mappings_ptr], ecx ; +0: 512 байт
lea ecx, [eax + 512]
mov [sf_state.namebuf_ptr], ecx ; +512: 512 байт
lea ecx, [eax + 1024]
mov [sf_state.cp866_buf_ptr], ecx ; +1024: 512 байт
lea ecx, [eax + 1536]
mov [sf_state.dir_path_ptr], ecx ; +1536: 32 байт
lea ecx, [eax + 1568]
mov [sf_state.createparms_ptr], ecx ; +1568: 128 байт
DEBUGF 2, "[VBoxGuest] [SF] Init buffers allocated\n"
; Подключение к HGCM сервису
DEBUGF 2, "[VBoxGuest] [SF] Connecting to '%s'...\n", sz_shfl_hgcm_service
stdcall hgcm_connect, sz_shfl_hgcm_service
test eax, eax
jz .connect_failed
mov [sf_state.client_id], eax
mov dword [sf_state.connected], 1
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] Connected! client_id=%d\n", eax
; --- Выделить FS-буферы ---
invoke KernelAlloc, 4096 ; fs_packet
test eax, eax
jz .fs_alloc_fail
mov [sf_state.fs_packet_ptr], eax
invoke KernelAlloc, 4096 ; fs_listbuf
test eax, eax
jz .fs_alloc_fail_f1
mov [sf_state.fs_listbuf_ptr], eax
invoke KernelAlloc, 65536 ; fs_iobuf (64KB bounce buffer)
test eax, eax
jz .fs_alloc_fail_f2
mov [sf_state.fs_iobuf_ptr], eax
invoke KernelAlloc, 4096 ; fs_cparms (page-aligned for PageList)
test eax, eax
jz .fs_alloc_fail_f3
mov [sf_state.fs_cparms_ptr], eax
invoke KernelAlloc, 4096 ; fs_small_bufs: pathbuf+pathbuf2
test eax, eax
jz .fs_alloc_fail_f4
mov [sf_state.fs_small_bufs_ptr], eax
; Вычислить указатели внутри fs_small_bufs
lea ecx, [eax + 0]
mov [sf_state.fs_pathbuf_ptr], ecx ; +0: 1024 байт
lea ecx, [eax + 1024]
mov [sf_state.fs_pathbuf2_ptr], ecx ; +1024: 1024 байт
DEBUGF 2, "[VBoxGuest] [SF] FS buffers allocated\n"
; Перечислить папки, подключить, зарегистрировать диск+ФС
stdcall shfl_list_all
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] Initialized OK\n"
xor eax, eax
ret
.connect_failed:
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] HGCM connect failed\n"
; Init-буферы уже выделены освободить
call shfl_free_init_bufs
mov eax, VERR_HGCM_SERVICE_NOT_FOUND
ret
; FS buffer allocation failure cascade
.fs_alloc_fail_f4:
invoke KernelFree, [sf_state.fs_cparms_ptr]
mov dword [sf_state.fs_cparms_ptr], 0
.fs_alloc_fail_f3:
invoke KernelFree, [sf_state.fs_iobuf_ptr]
mov dword [sf_state.fs_iobuf_ptr], 0
.fs_alloc_fail_f2:
invoke KernelFree, [sf_state.fs_listbuf_ptr]
mov dword [sf_state.fs_listbuf_ptr], 0
.fs_alloc_fail_f1:
invoke KernelFree, [sf_state.fs_packet_ptr]
mov dword [sf_state.fs_packet_ptr], 0
.fs_alloc_fail:
DEBUGF 2, "[VBoxGuest] [SF] KernelAlloc failed for FS buffers\n"
; HGCM уже подключен отключить
stdcall hgcm_disconnect, [sf_state.client_id]
mov dword [sf_state.connected], 0
mov dword [sf_state.client_id], 0
call shfl_free_init_bufs
mov eax, VERR_NO_MEMORY
ret
; Init buffer allocation failure cascade
.alloc_fail_free2:
invoke KernelFree, [sf_state.listbuf_ptr]
mov dword [sf_state.listbuf_ptr], 0
.alloc_fail_free1:
invoke KernelFree, [sf_state.packet_ptr]
mov dword [sf_state.packet_ptr], 0
.alloc_fail:
DEBUGF 2, "[VBoxGuest] [SF] KernelAlloc failed for init buffers\n"
mov eax, VERR_NO_MEMORY
ret
.hgcm_not_ready:
DEBUGF __DEBUG_SF__, "[VBoxGuest] [SF] HGCM not ready\n"
mov eax, VERR_NOT_READY
ret
.already_connected:
DEBUGF 2, "[VBoxGuest] [SF] Already connected\n"
xor eax, eax
ret
endp
; shfl_list_all Перечислить все shared folders, подключить, зарегистрировать
proc shfl_list_all uses ebx ecx edx esi edi
locals
map_idx dd ?
map_root dd ?
endl
cmp dword [sf_state.connected], 1
jne .not_connected
; ================================================================
; Шаг 1: SET_UTF8 (fn=16, 0 параметров)
; ================================================================
mov edi, [sf_state.packet_ptr]
xor eax, eax
mov ecx, 256/4
rep stosd
mov edi, [sf_state.packet_ptr]
mov dword [edi + 0], 44 ; size (header only)
mov dword [edi + 4], 0x00010001 ; version
mov dword [edi + 8], 62 ; HGCM_CALL32
mov dword [edi + 12], VERR_GENERAL_FAILURE ; rc
mov dword [edi + 16], 0 ; reserved1
mov dword [edi + 20], 0x00000081 ; f_requestor
mov dword [edi + 24], 0 ; fu32Flags
mov dword [edi + 28], 0 ; result
mov eax, [sf_state.client_id]
mov dword [edi + 32], eax ; client_id
mov dword [edi + 36], 16 ; SHFL_FN_SET_UTF8
mov dword [edi + 40], 0 ; param_count = 0
stdcall hgcm_send_request, edi
mov eax, dword [edi +28]
DEBUGF __DEBUG_SF__, "[SF] SET_UTF8 result: %d\n", eax
; ================================================================
; Шаг 2: QUERY_MAPPINGS (fn=1, 3 параметра)
; ================================================================
mov edi, [sf_state.packet_ptr]
xor eax, eax
mov ecx, 1024/4
rep stosd
mov edi, [sf_state.mappings_ptr]
xor eax, eax
mov ecx, 512/4
rep stosd
mov edi, [sf_state.packet_ptr]
mov dword [edi + 0], 96
mov dword [edi + 4], 0x00010001
mov dword [edi + 8], 62
mov dword [edi + 12], 0xFFFFFFFF
mov dword [edi + 16], 0
mov dword [edi + 20], 0x00000081
mov dword [edi + 24], 0
mov dword [edi + 28], 0
mov eax, [sf_state.client_id]
mov dword [edi + 32], eax
mov dword [edi + 36], 1 ; SHFL_FN_QUERY_MAPPINGS
mov dword [edi + 40], 3 ; 3 params
; parm[0] @ +44: flags = SHFL_MF_UTF8 (1)
mov dword [edi + 44], 1
mov dword [edi + 48], 1
mov dword [edi + 52], 0
; parm[1] @ +56: numberOfMappings = SHFL_MAX_FOLDERS
mov dword [edi + 56], 1
mov dword [edi + 60], SHFL_MAX_FOLDERS
mov dword [edi + 64], 0
; parm[2] @ +68: PageList OUT, cbData = SHFL_MAX_FOLDERS * 8
mov dword [edi + 68], 10 ; type = PAGELIST
mov dword [edi + 72], SHFL_MAX_FOLDERS * 8
mov dword [edi + 76], SHFL_MAX_FOLDERS * 8
; PageListInfo @ +80
push edi
mov eax, [sf_state.mappings_ptr]
and eax, PAGE_BASE_MASK
invoke GetPhysAddr
mov ebx, eax
pop edi
mov dword [edi + 80], 2
mov eax, [sf_state.mappings_ptr]
and eax, PAGE_OFFSET_MASK
mov word [edi + 84], ax
mov word [edi + 86], 1
mov dword [edi + 88], ebx
mov dword [edi + 92], 0
stdcall hgcm_send_request, edi
mov eax, dword [edi +12]
mov ebx, dword [edi +28]
DEBUGF __DEBUG_SF__, "[SF] QUERY_MAPPINGS: rc=0x%x result=%d\n", eax, ebx
test ebx, ebx
jnz .qm_failed
mov ecx, dword [edi +60]
DEBUGF __DEBUG_SF__, "[SF] Found %d shared folders\n", ecx
test ecx, ecx
jz .no_folders
cmp ecx, SHFL_MAX_FOLDERS
jbe @f
mov ecx, SHFL_MAX_FOLDERS
@@:
mov [sf_map_count], ecx
; ================================================================
; Шаг 3: Для каждого mapping получить имя, подключить, добавить
; ================================================================
mov dword [map_idx], 0
mov esi, [sf_state.mappings_ptr]
.folder_loop:
mov eax, [map_idx]
cmp eax, [sf_map_count]
jae .all_done
push esi
; Получить root index из SHFLMAPPING
mov eax, [esi + 4]
; --- 3a: QUERY_MAP_NAME ---
mov edi, [sf_state.namebuf_ptr]
push eax
xor eax, eax
mov ecx, 512/4
rep stosd
pop eax
mov edi, [sf_state.namebuf_ptr]
mov word [edi + 0], 508
mov word [edi + 2], 0
push eax
mov edi, [sf_state.packet_ptr]
xor eax, eax
mov ecx, 256/4
rep stosd
pop eax
mov edi, [sf_state.packet_ptr]
mov dword [edi + 0], 92
mov dword [edi + 4], 0x00010001
mov dword [edi + 8], 62
mov dword [edi + 12], 0xFFFFFFFF
mov dword [edi + 16], 0
mov dword [edi + 20], 0x00000081
mov dword [edi + 24], 0
mov dword [edi + 28], 0
push eax
mov eax, [sf_state.client_id]
mov dword [edi + 32], eax
pop eax
mov dword [edi + 36], 2
mov dword [edi + 40], 2
mov dword [edi + 44], 1
mov dword [edi + 48], eax
mov dword [edi + 52], 0
mov dword [edi + 56], 10
mov dword [edi + 60], 512
mov dword [edi + 64], 68
push edi
mov eax, [sf_state.namebuf_ptr]
and eax, PAGE_BASE_MASK
invoke GetPhysAddr
mov ebx, eax
pop edi
mov dword [edi + 68], 3
mov eax, [sf_state.namebuf_ptr]
and eax, PAGE_OFFSET_MASK
mov word [edi + 72], ax
mov word [edi + 74], 1
mov dword [edi + 76], ebx
mov dword [edi + 80], 0
stdcall hgcm_send_request, edi
mov eax, dword [edi +28]
test eax, eax
jnz .name_failed
mov edi, [sf_state.namebuf_ptr]
movzx eax, word [edi + 2]
test eax, eax
jz .name_failed
; Null-terminate имя
lea edi, [edi + 4]
mov byte [edi + eax], 0
; Конвертировать UTF-8 -> CP866 для отладочного вывода
push eax
stdcall sf_utf8_to_cp866, edi, [sf_state.cp866_buf_ptr], eax
pop eax
DEBUGF __DEBUG_SF__, "[SF] Folder[%d]: '%s'\n", [map_idx], [sf_state.cp866_buf_ptr]
; --- 3b: MAP_FOLDER ---
mov edi, [sf_state.namebuf_ptr]
movzx eax, word [edi + 2]
inc eax
mov word [edi + 0], ax
mov edi, [sf_state.packet_ptr]
xor eax, eax
mov ecx, 256/4
rep stosd
mov edi, [sf_state.packet_ptr]
mov dword [edi + 0], 108
mov dword [edi + 4], 0x00010001
mov dword [edi + 8], 62
mov dword [edi + 12], 0xFFFFFFFF
mov dword [edi + 16], 0
mov dword [edi + 20], 0x00000081
mov dword [edi + 24], 0
mov dword [edi + 28], 0
mov eax, [sf_state.client_id]
mov dword [edi + 32], eax
mov dword [edi + 36], 17
mov dword [edi + 40], 4
mov dword [edi + 44], 10
push ecx
mov ecx, [sf_state.namebuf_ptr]
movzx eax, word [ecx + 0]
pop ecx
add eax, 4
mov dword [edi + 48], eax
mov dword [edi + 52], 92
mov dword [edi + 56], 1
mov dword [edi + 60], 0
mov dword [edi + 64], 0
mov dword [edi + 68], 1
mov dword [edi + 72], '/'
mov dword [edi + 76], 0
mov dword [edi + 80], 1
mov dword [edi + 84], 1
mov dword [edi + 88], 0
push edi
mov eax, [sf_state.namebuf_ptr]
and eax, PAGE_BASE_MASK
invoke GetPhysAddr
mov ebx, eax
pop edi
mov dword [edi + 92], 1
mov eax, [sf_state.namebuf_ptr]
and eax, PAGE_OFFSET_MASK
mov word [edi + 96], ax
mov word [edi + 98], 1
mov dword [edi + 100], ebx
mov dword [edi + 104], 0
stdcall hgcm_send_request, edi
mov ebx, dword [edi +28]
test ebx, ebx
jnz .map_failed
; Получить root handle
mov eax, dword [edi +60]
mov [map_root], eax
DEBUGF __DEBUG_SF__, "[SF] Mapped, root=%d\n", eax
; --- 3c: Добавить папку в массив для диска ---
mov edi, [sf_state.namebuf_ptr]
lea edi, [edi + 4] ; UTF-8 имя
stdcall vboxsf_add_folder, eax, edi
; --- 3d: Листинг корневой директории (debug) ---
stdcall shfl_list_root, [map_root]
jmp .next_folder
.name_failed:
DEBUGF __DEBUG_SF__, "[SF] Folder[%d]: <name query failed>\n", [map_idx]
jmp .next_folder
.map_failed:
DEBUGF __DEBUG_SF__, "[SF] Folder[%d]: <map failed, result=%d>\n", [map_idx], ebx
.next_folder:
pop esi
add esi, 8
inc dword [map_idx]
jmp .folder_loop
.all_done:
DEBUGF __DEBUG_SF__, "[SF] All %d folders enumerated\n", [sf_map_count]
; --- Шаг 4: Зарегистрировать диск + ФС ---
stdcall vboxsf_register_disk
test eax, eax
jz .disk_failed
DEBUGF __DEBUG_SF__, "[SF] Virtual disk registered OK\n"
xor eax, eax
ret
.disk_failed:
DEBUGF __DEBUG_SF__, "[SF] Failed to register virtual disk\n"
xor eax, eax
ret
.qm_failed:
DEBUGF __DEBUG_SF__, "[SF] QUERY_MAPPINGS failed: result=%d\n", ebx
ret
.no_folders:
DEBUGF __DEBUG_SF__, "[SF] No shared folders found\n"
xor eax, eax
ret
.not_connected:
DEBUGF __DEBUG_SF__, "[SF] Not connected\n"
mov eax, -1
ret
endp
; shfl_list_root Листинг корневой директории mapped папки (debug)
proc shfl_list_root uses ebx ecx edx esi edi, root_handle:dword
locals
dir_handle_lo dd ?
dir_handle_hi dd ?
list_bytes dd ?
list_files dd ?
endl
; Подготовить SHFLSTRING path = "/"
mov edi, [sf_state.dir_path_ptr]
xor eax, eax
mov ecx, 4
rep stosd
mov edi, [sf_state.dir_path_ptr]
mov word [edi + 0], 2
mov word [edi + 2], 1
mov byte [edi + 4], '/'
mov byte [edi + 5], 0
; Подготовить SHFLCREATEPARMS
mov edi, [sf_state.createparms_ptr]
xor eax, eax
mov ecx, 128/4
rep stosd
mov edi, [sf_state.createparms_ptr]
mov dword [edi + 12], 0x00001104
; CREATE "/"
mov edi, [sf_state.packet_ptr]
xor eax, eax
mov ecx, 512/4
rep stosd
mov edi, [sf_state.packet_ptr]
mov dword [edi + 0], 112
mov dword [edi + 4], 0x00010001
mov dword [edi + 8], 62
mov dword [edi + 12], 0xFFFFFFFF
mov dword [edi + 16], 0
mov dword [edi + 20], 0x00000081
mov dword [edi + 24], 0
mov dword [edi + 28], 0
mov eax, [sf_state.client_id]
mov dword [edi + 32], eax
mov dword [edi + 36], 3
mov dword [edi + 40], 3
mov dword [edi + 44], 1
mov eax, [root_handle]
mov dword [edi + 48], eax
mov dword [edi + 52], 0
mov dword [edi + 56], 10
mov dword [edi + 60], 6
mov dword [edi + 64], 80
mov dword [edi + 68], 10
mov dword [edi + 72], 108
mov dword [edi + 76], 96
push edi
mov eax, [sf_state.dir_path_ptr]
and eax, PAGE_BASE_MASK
invoke GetPhysAddr
mov ebx, eax
pop edi
mov dword [edi + 80], 3
mov eax, [sf_state.dir_path_ptr]
and eax, PAGE_OFFSET_MASK
mov word [edi + 84], ax
mov word [edi + 86], 1
mov dword [edi + 88], ebx
mov dword [edi + 92], 0
push edi
mov eax, [sf_state.createparms_ptr]
and eax, PAGE_BASE_MASK
invoke GetPhysAddr
mov ebx, eax
pop edi
mov dword [edi + 96], 3
mov eax, [sf_state.createparms_ptr]
and eax, PAGE_OFFSET_MASK
mov word [edi + 100], ax
mov word [edi + 102], 1
mov dword [edi + 104], ebx
mov dword [edi + 108], 0
stdcall hgcm_send_request, edi
mov ebx, dword [edi +28]
test ebx, ebx
jnz .create_failed
mov ecx, [sf_state.createparms_ptr]
mov eax, dword [ecx + 0]
mov ebx, dword [ecx + 4]
mov [dir_handle_lo], eax
mov [dir_handle_hi], ebx
; LIST с пагинацией
mov dword [sf_list_resume], 0
mov dword [sf_list_total], 0
mov edi, [sf_state.packet_ptr]
xor eax, eax
mov ecx, 512/4
rep stosd
mov edi, [sf_state.packet_ptr]
mov dword [edi + 0], 172
mov dword [edi + 4], 0x00010001
mov dword [edi + 8], 62
mov dword [edi + 12], 0xFFFFFFFF
mov dword [edi + 16], 0
mov dword [edi + 20], 0x00000081
mov dword [edi + 24], 0
mov dword [edi + 28], 0
mov eax, [sf_state.client_id]
mov dword [edi + 32], eax
mov dword [edi + 36], 8
mov dword [edi + 40], 8
mov dword [edi + 44], 1
mov eax, [root_handle]
mov dword [edi + 48], eax
mov dword [edi + 52], 0
mov dword [edi + 56], 2
mov eax, [dir_handle_lo]
mov dword [edi + 60], eax
mov eax, [dir_handle_hi]
mov dword [edi + 64], eax
mov dword [edi + 68], 1
mov dword [edi + 72], 0
mov dword [edi + 76], 0
mov dword [edi + 80], 1
mov dword [edi + 84], 4096
mov dword [edi + 88], 0
mov dword [edi + 92], 10
mov dword [edi + 96], 0
mov dword [edi + 100], 140
mov dword [edi + 104], 10
mov dword [edi + 108], 4096
mov dword [edi + 112], 156
mov dword [edi + 116], 1
mov dword [edi + 120], 0
mov dword [edi + 124], 0
mov dword [edi + 128], 1
mov dword [edi + 132], 0
mov dword [edi + 136], 0
mov dword [edi + 140], 1
mov word [edi + 144], 0
mov word [edi + 146], 1
mov dword [edi + 148], 0
mov dword [edi + 152], 0
push edi
mov eax, [sf_state.listbuf_ptr]
and eax, PAGE_BASE_MASK
invoke GetPhysAddr
mov ebx, eax
pop edi
mov dword [edi + 156], 2
mov eax, [sf_state.listbuf_ptr]
and eax, PAGE_OFFSET_MASK
mov word [edi + 160], ax
mov word [edi + 162], 1
mov dword [edi + 164], ebx
mov dword [edi + 168], 0
.list_page:
push edi
mov edi, [sf_state.listbuf_ptr]
xor eax, eax
mov ecx, 4096/4
rep stosd
pop edi
mov edi, [sf_state.packet_ptr]
mov dword [edi + 12], 0xFFFFFFFF
mov dword [edi + 24], 0
mov dword [edi + 28], 0
mov dword [edi + 84], 4096
mov eax, [sf_list_resume]
mov dword [edi + 120], eax
mov dword [edi + 132], 0
stdcall hgcm_send_request, edi
mov ebx, dword [edi +28]
cmp ebx, -201
je .list_done
cmp ebx, -18
je .list_done
test ebx, ebx
js .list_failed
mov eax, dword [edi +84]
mov [list_bytes], eax
mov eax, dword [edi +132]
mov [list_files], eax
test eax, eax
jz .list_done
mov esi, [sf_state.listbuf_ptr]
xor ebx, ebx
.parse_entry:
cmp ebx, [list_files]
jae .page_done
mov eax, esi
sub eax, [sf_state.listbuf_ptr]
cmp eax, [list_bytes]
jae .page_done
mov eax, dword [esi + SHFLDIRINFO_OFS_SIZE_LO]
mov ecx, dword [esi + SHFLDIRINFO_OFS_FMODE]
movzx edx, word [esi + SHFLDIRINFO_OFS_NAME_LENGTH]
push eax ecx esi
lea eax, [esi + SHFLDIRINFO_OFS_NAME_STRING]
stdcall sf_utf8_to_cp866, eax, [sf_state.cp866_buf_ptr], edx
pop esi ecx eax
push esi ebx eax
mov edx, [sf_list_total]
add edx, ebx
test ecx, 0x4000
jnz .is_dir
DEBUGF __DEBUG_SF__, "[SF] [%d] F '%s' size=%d\n", edx, [sf_state.cp866_buf_ptr], eax
jmp .printed
.is_dir:
DEBUGF __DEBUG_SF__, "[SF] [%d] D '%s'\n", edx, [sf_state.cp866_buf_ptr]
.printed:
pop eax ebx esi
movzx eax, word [esi + SHFLDIRINFO_OFS_NAME_SIZE]
add eax, SHFLDIRINFO_OFS_NAME_STRING
add esi, eax
inc ebx
jmp .parse_entry
.page_done:
mov eax, [list_files]
add [sf_list_total], eax
mov eax, dword [edi +120]
mov [sf_list_resume], eax
mov eax, dword [edi +28]
test eax, eax
jg .list_page
mov eax, [list_files]
test eax, eax
jnz .list_page
.list_done:
DEBUGF __DEBUG_SF__, "[SF] Total: %d entries\n", [sf_list_total]
.close_dir:
mov edi, [sf_state.packet_ptr]
xor eax, eax
mov ecx, 256/4
rep stosd
mov edi, [sf_state.packet_ptr]
mov dword [edi + 0], 68
mov dword [edi + 4], 0x00010001
mov dword [edi + 8], 62
mov dword [edi + 12], 0xFFFFFFFF
mov dword [edi + 16], 0
mov dword [edi + 20], 0x00000081
mov dword [edi + 24], 0
mov dword [edi + 28], 0
mov eax, [sf_state.client_id]
mov dword [edi + 32], eax
mov dword [edi + 36], 4
mov dword [edi + 40], 2
mov dword [edi + 44], 1
mov eax, [root_handle]
mov dword [edi + 48], eax
mov dword [edi + 52], 0
mov dword [edi + 56], 2
mov eax, [dir_handle_lo]
mov dword [edi + 60], eax
mov eax, [dir_handle_hi]
mov dword [edi + 64], eax
stdcall hgcm_send_request, edi
xor eax, eax
ret
.create_failed:
DEBUGF __DEBUG_SF__, "[SF] CREATE '/' failed: result=%d\n", ebx
ret
.list_failed:
DEBUGF __DEBUG_SF__, "[SF] LIST failed: result=%d\n", ebx
jmp .close_dir
endp
; shfl_disable Отключить SharedFolder сервис
proc shfl_disable uses ebx ecx edx esi edi
DEBUGF 2, "[VBoxGuest] [SF] Disabling (removing disk)...\n"
; 1. Заблокировать FS callbacks (guard в vboxsf.inc)
mov dword [sf_state.connected], 0
; 2. Удалить диск из системы
; DiskDel вызывает disk_media_changed(0) внутри
; освобождает разделы (вызывает vboxsf_fs_free)
; удаляет диск из глобального списка
cmp dword [vboxsf_data.disk_handle], 0
je .no_disk
invoke DiskDel, [vboxsf_data.disk_handle]
mov dword [vboxsf_data.disk_handle], 0
DEBUGF 2, "[VBoxGuest] [SF] DiskDel done\n"
.no_disk:
; 3. Отключить HGCM
cmp dword [sf_state.client_id], 0
je .no_hgcm
stdcall hgcm_disconnect, [sf_state.client_id]
mov dword [sf_state.client_id], 0
.no_hgcm:
; 4. Освободить буферы
call shfl_free_fs_bufs
call shfl_free_init_bufs
; 5. Освободить SF_FOLDER структуры и сбросить счётчик
call shfl_free_folders
DEBUGF 2, "[VBoxGuest] [SF] Disabled, disk removed\n"
xor eax, eax
ret
endp
; shfl_free_init_bufs Освободить init-буферы SharedFolders
proc shfl_free_init_bufs
cmp dword [sf_state.packet_ptr], 0
je @f
invoke KernelFree, [sf_state.packet_ptr]
mov dword [sf_state.packet_ptr], 0
@@:
cmp dword [sf_state.listbuf_ptr], 0
je @f
invoke KernelFree, [sf_state.listbuf_ptr]
mov dword [sf_state.listbuf_ptr], 0
@@:
cmp dword [sf_state.small_bufs_ptr], 0
je @f
invoke KernelFree, [sf_state.small_bufs_ptr]
mov dword [sf_state.small_bufs_ptr], 0
; Обнулить указатели-потомки
mov dword [sf_state.mappings_ptr], 0
mov dword [sf_state.namebuf_ptr], 0
mov dword [sf_state.cp866_buf_ptr], 0
mov dword [sf_state.dir_path_ptr], 0
mov dword [sf_state.createparms_ptr], 0
@@:
ret
endp
; shfl_free_fs_bufs Освободить FS-буферы SharedFolders
proc shfl_free_fs_bufs
cmp dword [sf_state.fs_packet_ptr], 0
je @f
invoke KernelFree, [sf_state.fs_packet_ptr]
mov dword [sf_state.fs_packet_ptr], 0
@@:
cmp dword [sf_state.fs_listbuf_ptr], 0
je @f
invoke KernelFree, [sf_state.fs_listbuf_ptr]
mov dword [sf_state.fs_listbuf_ptr], 0
@@:
cmp dword [sf_state.fs_iobuf_ptr], 0
je @f
invoke KernelFree, [sf_state.fs_iobuf_ptr]
mov dword [sf_state.fs_iobuf_ptr], 0
@@:
cmp dword [sf_state.fs_cparms_ptr], 0
je @f
invoke KernelFree, [sf_state.fs_cparms_ptr]
mov dword [sf_state.fs_cparms_ptr], 0
@@:
cmp dword [sf_state.fs_small_bufs_ptr], 0
je @f
invoke KernelFree, [sf_state.fs_small_bufs_ptr]
mov dword [sf_state.fs_small_bufs_ptr], 0
; Обнулить указатели-потомки
mov dword [sf_state.fs_pathbuf_ptr], 0
mov dword [sf_state.fs_pathbuf2_ptr], 0
@@:
ret
endp
; shfl_free_folders Освободить SF_FOLDER структуры и сбросить счётчик
proc shfl_free_folders uses ebx esi
mov ebx, [vboxsf_data.count]
test ebx, ebx
jz .done
xor esi, esi
.loop:
cmp dword [vboxsf_data.folders + esi*4], 0
je .next
invoke KernelFree, [vboxsf_data.folders + esi*4]
mov dword [vboxsf_data.folders + esi*4], 0
.next:
inc esi
dec ebx
jnz .loop
.done:
mov dword [vboxsf_data.count], 0
ret
endp
include 'vboxsf.inc'
REGISTER_SERVICE svc_shfl_name, 0, VMMDEV_GUEST_SUPPORTS_SHARED_FOLDERS, \
shfl_init, shfl_init, shfl_disable, 0, 0, AUTOSTART_SHARED_FOLDERS