341 lines
13 KiB
HTML
341 lines
13 KiB
HTML
; =============================================================================
|
||
; 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 |