void send_channel_event(EVT_HANDLE evt, os_channel *channel)
{
    DWORD buffer_length = 0;
    PEVT_VARIANT properties_values = NULL;
    DWORD count = 0;
    EVT_HANDLE context = NULL;
    os_event event = {0};
    char final_msg[OS_MAXSTR];
    int result = 0;

    if ((context = EvtCreateRenderContext(count, NULL, EvtRenderContextSystem)) == NULL) {
        log2file(
            "%s: ERROR: Could not EvtCreateRenderContext() for (%s) which returned (%lu)",
            ARGV0,
            channel->evt_log,
            GetLastError());
        goto cleanup;
    }

    /* Make initial call to determine buffer size necessary */
    result = EvtRender(context,
                       evt,
                       EvtRenderEventValues,
                       0,
                       NULL,
                       &buffer_length,
                       &count);
    if (result != FALSE || GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
        log2file(
            "%s: ERROR: Could not EvtRender() to determine buffer size for (%s) which returned (%lu)",
            ARGV0,
            channel->evt_log,
            GetLastError());
        goto cleanup;
    }

    if ((properties_values = malloc(buffer_length)) == NULL) {
        log2file(
            "%s: ERROR: Could not malloc() memory to process event (%s) which returned [(%d)-(%s)]",
            ARGV0,
            channel->evt_log,
            errno,
            strerror(errno));
        goto cleanup;
    }

    if (!EvtRender(context,
                   evt,
                   EvtRenderEventValues,
                   buffer_length,
                   properties_values,
                   &buffer_length,
                   &count)) {
        log2file(
            "%s: ERROR: Could not EvtRender() for (%s) which returned (%lu)",
            ARGV0,
            channel->evt_log,
            GetLastError());
        goto cleanup;
    }

    event.name = get_property_value(&properties_values[EvtSystemChannel]);
    event.id = properties_values[EvtSystemEventID].UInt16Val;
    event.source = get_property_value(&properties_values[EvtSystemProviderName]);
    event.uid = properties_values[EvtSystemUserID].Type == EvtVarTypeNull ? NULL : properties_values[EvtSystemUserID].SidVal;
    event.computer = get_property_value(&properties_values[EvtSystemComputer]);
    event.time_created = properties_values[EvtSystemTimeCreated].FileTimeVal;
    event.keywords = properties_values[EvtSystemKeywords].Type == EvtVarTypeNull ? 0 : properties_values[EvtSystemKeywords].UInt64Val;
    event.level = properties_values[EvtSystemLevel].Type == EvtVarTypeNull ? -1 : properties_values[EvtSystemLevel].ByteVal;

    switch (event.level) {
        case WINEVENT_CRITICAL:
            event.category = "CRITICAL";
            break;
        case WINEVENT_ERROR:
            event.category = "ERROR";
            break;
        case WINEVENT_WARNING:
            event.category = "WARNING";
            break;
        case WINEVENT_INFORMATION:
            event.category = "INFORMATION";
            break;
        case WINEVENT_VERBOSE:
            event.category = "DEBUG";
            break;
        case WINEVENT_AUDIT:
            if (event.keywords & WINEVENT_AUDIT_FAILURE) {
                event.category = "AUDIT_FAILURE";
                break;
            } else if (event.keywords & WINEVENT_AUDIT_SUCCESS) {
                event.category = "AUDIT_SUCCESS";
                break;
            }
        default:
            event.category = "Unknown";
            break;
    }

    if ((event.timestamp = WinEvtTimeToString(event.time_created)) == NULL) {
        log2file(
            "%s: ERROR: Could not convert timestamp for (%s)",
            ARGV0,
            channel->evt_log);
        goto cleanup;
    }

    /* Determine user and domain */
    get_username_and_domain(&event);

    /* Get event log message */
    if ((event.message = get_message(evt, properties_values[EvtSystemProviderName].StringVal, EvtFormatMessageEvent)) == NULL) {
        log2file(
            "%s: ERROR: Could not get message for (%s)",
            ARGV0,
            channel->evt_log);
    } else {
        /* Format message */
        win_format_event_string(event.message);
    }

    snprintf(
        final_msg,
        sizeof(final_msg),
        "%s WinEvtLog: %s: %s(%d): %s: %s: %s: %s: %s",
        event.timestamp,
        event.name,
        event.category,
        event.id,
        event.source && strlen(event.source) ? event.source : "no source",
        event.user && strlen(event.user) ? event.user : "******",
        event.domain && strlen(event.domain) ? event.domain : "no domain",
        event.computer && strlen(event.computer) ? event.computer : "no computer",
        event.message && strlen(event.message) ? event.message : "(no message)"
    );

    if (SendMSG(logr_queue, final_msg, "WinEvtLog", LOCALFILE_MQ) < 0) {
        merror(QUEUE_SEND, ARGV0);
    }

    if (channel->bookmark_enabled) {
        update_bookmark(evt, channel);
    }

cleanup:
    free(properties_values);
    free_event(&event);

    if (context != NULL) {
        EvtClose(context);
    }

    return;
}
/* Reads the event log */
void readel(os_el *el, int printit)
{
    DWORD _evtid = 65535;
    DWORD nstr;
    DWORD user_size;
    DWORD domain_size;
    DWORD read, needed;
    int size_left;
    int str_size;
    int id;

    char mbuffer[BUFFER_SIZE + 1];
    LPSTR sstr = NULL;

    char *tmp_str = NULL;
    char *category;
    char *source;
    char *computer_name;
    char *descriptive_msg;

    char el_user[OS_FLSIZE + 1];
    char el_domain[OS_FLSIZE + 1];
    char el_string[OS_MAXSTR + 1];
    char final_msg[OS_MAXSTR + 1];
    LPSTR el_sstring[OS_FLSIZE + 1];

    /* er must point to the mbuffer */
    el->er = (EVENTLOGRECORD *) &mbuffer;

    /* Zero the values */
    el_string[OS_MAXSTR] = '\0';
    el_user[OS_FLSIZE] = '\0';
    el_domain[OS_FLSIZE] = '\0';
    final_msg[OS_MAXSTR] = '\0';
    el_sstring[0] = NULL;
    el_sstring[OS_FLSIZE] = NULL;

    /* Event log is not open */
    if (!el->h) {
        return;
    }

    /* Read the event log */
    while (ReadEventLog(el->h,
                        EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ,
                        0,
                        el->er, BUFFER_SIZE - 1, &read, &needed)) {
        if (!printit) {
            /* Set er to the beginning of the buffer */
            el->er = (EVENTLOGRECORD *)&mbuffer;
            continue;
        }


        while (read > 0) {
            /* We need to initialize every variable before the loop */
            category = el_getCategory(el->er->EventType);
            source = (LPSTR) ((LPBYTE) el->er + sizeof(EVENTLOGRECORD));
            computer_name = source + strlen(source) + 1;
            descriptive_msg = NULL;

            /* Get event id */
            id = (int)el->er->EventID & _evtid;

            /* Initialize domain/user size */
            user_size = 255;
            domain_size = 255;
            el_domain[0] = '\0';
            el_user[0] = '\0';

            /* We must have some description */
            if (el->er->NumStrings) {
                size_left = OS_MAXSTR - OS_SIZE_1024;

                sstr = (LPSTR)((LPBYTE)el->er + el->er->StringOffset);
                el_string[0] = '\0';

                for (nstr = 0; nstr < el->er->NumStrings; nstr++) {
                    str_size = strlen(sstr);
                    if (size_left > 1) {
                        strncat(el_string, sstr, size_left);
                    }

                    tmp_str = strchr(el_string, '\0');
                    if (tmp_str) {
                        *tmp_str = ' ';
                        tmp_str++;
                        *tmp_str = '\0';
                    } else {
                        merror("%s: Invalid application string (size+)",
                               ARGV0);
                    }
                    size_left -= str_size + 2;

                    if (nstr <= 92) {
                        el_sstring[nstr] = (LPSTR)sstr;
                        el_sstring[nstr + 1] = NULL;
                    }

                    sstr = strchr( (LPSTR)sstr, '\0');
                    if (sstr) {
                        sstr++;
                    } else {
                        break;
                    }
                }

                /* Get a more descriptive message (if available) */
                if (isVista && strcmp(el->name, "Security") == 0) {
                    descriptive_msg = el_vista_getMessage(id, el_sstring);
                }

                else {
                    descriptive_msg = el_getMessage(el->er,
                                                    el->name,
                                                    source,
                                                    el_sstring);
                }

                if (descriptive_msg != NULL) {
                    /* format message */
                    win_format_event_string(descriptive_msg);
                }
            } else {
                strncpy(el_string, "(no message)", 128);
            }

            /* Get username */
            if (el->er->UserSidLength) {
                SID_NAME_USE account_type;
                if (!LookupAccountSid(NULL,
                                      (SID *)((LPSTR)el->er +
                                              el->er->UserSidOffset),
                                      el_user,
                                      &user_size,
                                      el_domain,
                                      &domain_size,
                                      &account_type)) {
                    strncpy(el_user, "(no user)", 255);
                    strncpy(el_domain, "no domain", 255);
                }
            }

            else if (isVista && strcmp(el->name, "Security") == 0) {
                int uid_array_id = -1;

                switch (id) {
                    case 4624:
                        uid_array_id = 5;
                        break;
                    case 4634:
                        uid_array_id = 1;
                        break;
                    case 4647:
                        uid_array_id = 1;
                        break;
                    case 4769:
                        uid_array_id = 0;
                        break;
                }

                if ((uid_array_id >= 0) &&
                        el_sstring[uid_array_id] &&
                        el_sstring[uid_array_id + 1]) {
                    strncpy(el_user, el_sstring[uid_array_id], OS_FLSIZE);
                    strncpy(el_domain, el_sstring[uid_array_id + 1], OS_FLSIZE);
                } else {
                    strncpy(el_user, "(no user)", 255);
                    strncpy(el_domain, "no domain", 255);
                }
            }

            else {
                strncpy(el_user, "(no user)", 255);
                strncpy(el_domain, "no domain", 255);
            }

            if (printit) {
                DWORD _evtid = 65535;
                int id = (int)el->er->EventID & _evtid;

                final_msg[OS_MAXSTR - OS_LOG_HEADER] = '\0';
                final_msg[OS_MAXSTR - OS_LOG_HEADER - 1] = '\0';

                snprintf(final_msg, OS_MAXSTR - OS_LOG_HEADER - 1,
                         "%s WinEvtLog: %s: %s(%d): %s: %s: %s: %s: %s",
                         epoch_to_human((int)el->er->TimeGenerated),
                         el->name,
                         category,
                         id,
                         source,
                         el_user,
                         el_domain,
                         computer_name,
                         descriptive_msg != NULL ? descriptive_msg : el_string);

                if (SendMSG(logr_queue, final_msg, "WinEvtLog",
                            LOCALFILE_MQ) < 0) {
                    merror(QUEUE_SEND, ARGV0);
                }
            }

            if (descriptive_msg != NULL) {
                LocalFree(descriptive_msg);
            }

            /* Change the point to the er */
            read -= el->er->Length;
            el->er = (EVENTLOGRECORD *)((LPBYTE) el->er + el->er->Length);
        }

        /* Set er to the beginning of the buffer */
        el->er = (EVENTLOGRECORD *)&mbuffer;
    }

    id = GetLastError();
    if (id == ERROR_HANDLE_EOF) {
        return;
    }

    /* Event log was cleared */
    else if (id == ERROR_EVENTLOG_FILE_CHANGED) {
        char msg_alert[512 + 1];
        msg_alert[512] = '\0';
        merror("%s: WARN: Event log cleared: '%s'", ARGV0, el->name);

        /* Send message about cleared */
        snprintf(msg_alert, 512, "ossec: Event log cleared: '%s'", el->name);
        SendMSG(logr_queue, msg_alert, "WinEvtLog", LOCALFILE_MQ);

        /* Close the event log and reopen */
        CloseEventLog(el->h);
        el->h = NULL;

        /* Reopen */
        if (startEL(el->name, el) < 0) {
            merror("%s: ERROR: Unable to reopen event log '%s'",
                   ARGV0, el->name);
        }
    }

    else {
        debug1("%s: WARN: Error reading event log: %d", ARGV0, id);
    }
}