; ============================================================================= ; 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