Files
VBoxGuest/services/shared_folder.inc
Alexey Mikhailov 0f400bc0e0 #1 init в репу
2026-01-06 15:43:37 +03:00

341 lines
13 KiB
HTML
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.
; =============================================================================
; SharedFolder Service - FIXED VERSION
; =============================================================================
VBOX_SHAREDFOLDER_SERVICE db 'VBoxSharedFolders', 0
align 4
sf_state SF_STATE
; =============================================================================
; ПРОЦЕДУРА: sf_init
; =============================================================================
proc sf_init uses ebx ecx edx esi edi
DEBUGF 1, "=================================================\n"
DEBUGF 1, "[SF] >>> SharedFolder initialization STARTED\n"
DEBUGF 1, "=================================================\n"
mov ax, [vbox_device.port]
test ax, ax
jz .vmmdev_not_ready
mov eax, [vbox_device.mmio]
test eax, eax
jz .vmmdev_not_ready
DEBUGF 1, "[SF] VMMDev ready: port=0x%x, mmio=0x%x\n", \
[vbox_device.port], [vbox_device.mmio]
DEBUGF 1, "[SF] Connecting to SharedFolders HGCM service...\n"
stdcall hgcm_connect, VBOX_SHAREDFOLDER_SERVICE
test eax, eax
jz .connect_failed
mov [sf_state.client_id], eax
mov dword [sf_state.connected], 1
DEBUGF 1, "[SF] *** HGCM CONNECTED *** client_id=0x%x\n", eax
DEBUGF 1, "[SF] Querying available shared folders...\n"
call sf_query_mappings
DEBUGF 1, "[SF] After sf_query_mappings, eax=0x%x\n", eax
test eax, eax
jnz .query_failed
DEBUGF 1, "=================================================\n"
DEBUGF 1, "[SF] *** SHAREDFOLDER INITIALIZED SUCCESSFULLY ***\n"
DEBUGF 1, "[SF] client_id : 0x%x\n", [sf_state.client_id]
DEBUGF 1, "[SF] folder_count : %d\n", [sf_state.folder_count]
DEBUGF 1, "=================================================\n"
xor eax, eax
ret
.vmmdev_not_ready:
DEBUGF 1, "[SF] ERROR: VMMDev not initialized!\n"
mov eax, -1
ret
.connect_failed:
DEBUGF 1, "[SF] *** CRITICAL: HGCM connect failed ***\n"
mov eax, -1
ret
.query_failed:
DEBUGF 1, "[SF] WARNING: Query mappings failed (non-fatal)\n"
xor eax, eax
ret
endp
; =============================================================================
; ПРОЦЕДУРА: sf_query_mappings
; ПОЛНОСТЬЮ ИСПРАВЛЕННАЯ ВЕРСИЯ
; =============================================================================
proc sf_query_mappings uses ebx esi edi
DEBUGF 1, "[SF] ========================================\n"
DEBUGF 1, "[SF] >>> sf_query_mappings STARTED\n"
DEBUGF 1, "[SF] ========================================\n"
; =========================================================================
; ШАГ 1: Получить физические адреса
; =========================================================================
DEBUGF 1, "[SF] STEP 1: Buffer preparation\n"
; Получить физический адрес буфера
mov eax, sf_mappings_buffer
invoke GetPhysAddr
mov ebx, eax ; ebx = buffer_phys
DEBUGF 1, "[SF] buffer_virt = 0x%x\n", sf_mappings_buffer
DEBUGF 1, "[SF] buffer_phys = 0x%x\n", ebx
; Вычислить PFN (Page Frame Number)
mov eax, ebx
shr eax, PAGE_SHIFT
mov [sf_pagelist_pfn], eax
DEBUGF 1, "[SF] buffer_pfn = 0x%x\n", eax
; Получить физический адрес pagelist структуры
mov eax, sf_pagelist
invoke GetPhysAddr
mov esi, eax ; esi = pagelist_phys
DEBUGF 1, "[SF] pagelist_phys = 0x%x\n", esi
; =========================================================================
; ШАГ 2: Формирование HGCM пакета (56 байт как в Clipboard!)
; =========================================================================
DEBUGF 1, "[SF] STEP 2: Building HGCM packet (56 bytes)\n"
; Используем пакет на 56 байт (как в работающем Clipboard запросе)
mov edi, sf_query_mappings_pkt
; Очистка пакета (56 байт)
push edi
mov ecx, 56/4
xor eax, eax
rep stosd
pop edi
; =========================================================================
; ВАЖНО: Сравниваем с работающим Clipboard запросом!
; Clipboard пакет (56 байт):
; 0x38 0x00 0x00 0x00 0x01 0x00 0x01 0x00 0x3E 0x00 0x00 0x00 0x1F 0xFF 0xFF 0xFF
; 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x1F 0xFF 0xFF 0xFF
; 0x03 0x00 0x00 0x00 0x02 0x00 0x00 0x00 0x01 0x00 0x00 0x00 0x01 0x00 0x00 0x00
; =========================================================================
; Заполняем пакет ТОЧНО как в Clipboard запросе, но с нашими параметрами
; VMMDev Request Header (первые 24 байта)
mov dword [edi + 0], 56 ; size = 56 байт (0x38) как в Clipboard!
mov dword [edi + 4], VMMDEV_REQUEST_HEADER_VERSION
mov dword [edi + 8], VMMDEV_HGCM_CALL32
; КРИТИЧНО: rc должен быть 0x1FFFFFFF (как в работающем запросе)!
mov dword [edi + 12], 0x1FFFFFFF ; rc = VERR_HGCM_ASYNC_EXECUTE
; mov dword [edi + 12], 0
mov dword [edi + 16], 0 ; reserved1
mov dword [edi + 20], 0 ; reserved2
; HGCM Call Header (смещение 24)
mov eax, [sf_state.client_id]
mov dword [edi + 24], eax ; clientID
mov dword [edi + 28], SHFL_FN_QUERY_MAPPINGS ; function
mov dword [edi + 32], 3 ; cParms = 3 параметра
; КРИТИЧНО: Еще одно поле rc в HGCM header (смещение 36)!
mov dword [edi + 36], 0x1FFFFFFF ; Еще один rc (как в Clipboard)
; =========================================================================
; Параметры (начинаются с 40 байта)
; В 56-байтовом пакете у нас есть место для 3 параметров по 4+4 байта каждый
; =========================================================================
; Параметр 0: flags (U32, IN) - смещение 40
mov dword [edi + 40], HGCM_PARM_TYPE_32BIT ; type = 1
mov dword [edi + 44], 0 ; flags = 0
; Параметр 1: count (U32, OUT) - смещение 44+4=48
mov dword [edi + 48], HGCM_PARM_TYPE_32BIT ; type = 1
mov dword [edi + 52], 0 ; начальное значение = 0
; Параметр 2: buffer (PAGELIST, OUT) - смещение 48+8=56
; Но у нас пакет всего 56 байт! Значит, параметры идут последовательно.
; Исправляем: параметр 2 начинается с 52+4=56, но это уже за пределами 56 байт!
; ВНИМАНИЕ: В пакете Clipboard параметры идут последовательно без пропусков:
; offset 40: param0.type
; offset 44: param0.value
; offset 48: param1.type
; offset 52: param1.value
; offset 56: param2.type - но это уже за пределами 56 байт!
; Значит, пакет должен быть больше 56 байт!
; Попробуем 80 байт, как было раньше, но с правильными смещениями
; =========================================================================
; ВЕРСИЯ 2: Пакет на 80 байт с правильными смещениями
; =========================================================================
DEBUGF 1, "[SF] STEP 2a: Rebuilding packet (80 bytes with correct offsets)\n"
; Переопределяем пакет на 80 байт
mov dword [edi + 0], 80 ; size = 80 байт
; Очищаем оставшуюся часть пакета
push edi
add edi, 56
mov ecx, (80-56)/4
xor eax, eax
rep stosd
pop edi
; Теперь параметр 2 должен начинаться с 56 байта
mov dword [edi + 56], HGCM_PARM_TYPE_PAGELIST ; type = 8
mov dword [edi + 60], 1 ; cPages = 1
mov dword [edi + 64], esi ; paPages = физический адрес pagelist
; Padding для 80-байтового пакета
mov dword [edi + 68], 0
mov dword [edi + 72], 0
mov dword [edi + 76], 0
DEBUGF 1, "[SF] Packet structure (80 bytes):\n"
DEBUGF 1, "[SF] size: 80 (0x50)\n"
DEBUGF 1, "[SF] rc: 0x%x\n", [edi + 12]
DEBUGF 1, "[SF] clientID: 0x%x\n", [sf_state.client_id]
DEBUGF 1, "[SF] function: %d\n", SHFL_FN_QUERY_MAPPINGS
DEBUGF 1, "[SF] cParms: ?\n"
DEBUGF 1, "[SF] param0: type=1, value=0\n"
DEBUGF 1, "[SF] param1: type=1, value=0\n"
DEBUGF 1, "[SF] param2: type=8, cPages=?, paPages=0x%x\n", esi
; Дамп пакета для проверки
LOG_DUMP_MEMORY edi, 80
; =========================================================================
; ШАГ 3: Отправка запроса
; =========================================================================
DEBUGF 1, "[SF] STEP 3: Sending HGCM request...\n"
stdcall hgcm_send_request, edi
DEBUGF 1, "[SF] hgcm_send_request returned: 0x%x\n", eax
test eax, eax
jnz .request_failed
; =========================================================================
; ШАГ 4: Анализ результата
; =========================================================================
DEBUGF 1, "[SF] STEP 4: Analyzing response\n"
; Проверка кода возврата VMMDev
mov eax, [edi + 12]
DEBUGF 1, "[SF] VMMDev RC = 0x%x\n", eax
; Проверка результата HGCM
mov eax, [edi + 36] ; HGCM result code (смещение 36 в 80-байтовом пакете)
DEBUGF 1, "[SF] HGCM result = 0x%x\n", eax
; Проверяем оба кода
cmp dword [edi + 12], 0x8000B57 ; VERR_HGCM_ASYNC_EXECUTE
je .async_ok
cmp dword [edi + 12], 0
je .check_hgcm
; Ошибка VMMDev
DEBUGF 1, "[SF] VMMDev error: 0x%x\n", [edi + 12]
mov eax, -1
ret
.check_hgcm:
cmp dword [edi + 36], 0
je .success
; Ошибка HGCM
DEBUGF 1, "[SF] HGCM error: 0x%x\n", [edi + 36]
mov eax, -1
ret
.async_ok:
; Асинхронное выполнение - проверяем HGCM результат
cmp dword [edi + 36], 0
je .success
DEBUGF 1, "[SF] HGCM async error: 0x%x\n", [edi + 36]
mov eax, -1
ret
.success:
; Успех - получаем количество папок из param1.value
mov eax, [edi + 52] ; param1.value (count) - смещение 52
mov [sf_state.folder_count], eax
DEBUGF 1, "[SF] ========================================\n"
DEBUGF 1, "[SF] SUCCESS: Found %d shared folder(s)\n", eax
DEBUGF 1, "[SF] ========================================\n"
xor eax, eax
ret
.request_failed:
DEBUGF 1, "[SF] ERROR: hgcm_send_request failed (rc=0x%x)\n", eax
DEBUGF 1, "[SF] Check packet structure and sizes\n"
mov eax, -1
ret
endp
; =============================================================================
; ПРОЦЕДУРА: sf_shutdown
; =============================================================================
proc sf_shutdown uses eax
DEBUGF 1, "[SF] >>> Shutting down SharedFolder\n"
cmp dword [sf_state.connected], 1
jne .not_connected
stdcall hgcm_disconnect, [sf_state.client_id]
mov dword [sf_state.connected], 0
mov dword [sf_state.client_id], 0
DEBUGF 1, "[SF] Shutdown complete\n"
.not_connected:
ret
endp
; =============================================================================
; ДАННЫЕ
; =============================================================================
; Page-aligned буфер для данных (16384 байт)
align 4096
sf_mappings_buffer: rb 16384
; PageList структура
align 16
sf_pagelist:
dd 1 ; cPages
sf_pagelist_pfn:
dd 0 ; pfn[0]
; Структуры пакетов (в постоянной памяти)
align 16
sf_query_mappings_pkt: rb 80 ; Пакет для QUERY_MAPPINGS
sf_query_map_name_pkt: rb 80 ; Пакет для QUERY_MAP_NAME
sf_map_folder_pkt: rb 80 ; Пакет для MAP_FOLDER
; SharedFolder packets (must be in permanent memory!)
align 4
; sf_query_mappings_pkt: rb sizeof.SHFL_QUERY_MAPPINGS
; sf_query_map_name_pkt: rb sizeof.SHFL_QUERY_MAP_NAME
; sf_map_folder_pkt: rb sizeof.SHFL_MAP_FOLDER
sf_create_pkt: rb sizeof.SHFL_CREATE
sf_read_pkt: rb sizeof.SHFL_READ
sf_write_pkt: rb sizeof.SHFL_WRITE
sf_close_pkt: rb sizeof.SHFL_CLOSE
sf_list_pkt: rb sizeof.SHFL_LIST