Status WindowsEventLoggerPlugin::emitLogRecord(
    REGHANDLE registration_handle,
    const std::string& message,
    StatusLogSeverity severity,
    const std::string& source_file_name,
    size_t line) {
  if (registration_handle == 0) {
    return Status(1, "The Windows Event Logger plugin is not initialized.");
  }

  EVENT_DATA_DESCRIPTOR data_descriptor[2] = {};
  EventDataDescCreate(&data_descriptor[0],
                      message.data(),
                      static_cast<ULONG>(message.size() + 1));

  auto location = source_file_name + ":" + std::to_string(line);
  EventDataDescCreate(&data_descriptor[1],
                      location.data(),
                      static_cast<ULONG>(location.size() + 1));

  const EVENT_DESCRIPTOR* event_descriptor = nullptr;
  switch (severity) {
  case O_WARNING: {
    event_descriptor = &WarningMessage;
    break;
  }

  case O_ERROR: {
    event_descriptor = &ErrorMessage;
    break;
  }

  case O_FATAL: {
    event_descriptor = &FatalMessage;
    break;
  }

  case O_INFO:
  default: {
    event_descriptor = &InfoMessage;
    break;
  }
  }

  auto status =
      EventWrite(registration_handle, event_descriptor, 2, data_descriptor);
  if (status != ERROR_SUCCESS) {
    auto error_message =
        std::string("Failed to publish the following log record: ") + location +
        " " + message;
    return Status(1, std::move(error_message));
  }

  return Status();
}
    virtual void Write(int level, int opcode, char * msg, va_list argptr)
    {
        //event not registered
        if (0==m_EventHandle)
        {
            return;
        }
        if (!m_bProviderEnable)
        {
            return;
        }
        if (level == DL_LOADED_LIBRARY)
        {
            return;
        }

        char msg_formated[1024];
        EVENT_DESCRIPTOR descriptor;
        EVENT_DATA_DESCRIPTOR data_descriptor;

        EventDescZero(&descriptor);
        
        descriptor.Opcode = (UCHAR)opcode; 
        descriptor.Level  = (UCHAR)level;
        
        if (m_bUseFormatter)
        {
            if (NULL != msg)
            {
#if _MSC_VER >= 1400
                vsprintf_s(msg_formated, sizeof (msg_formated) / sizeof (msg_formated[0]), msg, argptr);
#else
                vsnprintf(msg_formated, sizeof (msg_formated) / sizeof (msg_formated[0]), msg, argptr);
#endif
                EventDataDescCreate(&data_descriptor, msg_formated, (ULONG)(strlen(msg_formated) + 1));
            }else
            {
                EventDataDescCreate(&data_descriptor, NULL, 0);
            }
        }else
        {
            //TODO: non formated events supports under zbb 
        }

        EventWrite(m_EventHandle, &descriptor, 1, &data_descriptor);
    }
void ETWLogger::err(const std::string& msg) {
	EVENT_DATA_DESCRIPTOR descr;
	EventDataDescCreate(&descr, msg.c_str(), static_cast<ULONG>(msg.size()));
	auto status = EventWrite(
		m_registration_handle,
		&ErrEvent,
		1,
		&descr
		);
	if (status != 0) DebugBreak();
}
// Sends a file download event to the Vista Event Log 
void
nsParentalControlsServiceWin::LogFileDownload(bool blocked, nsIURI *aSource, nsIFile *aTarget)
{
  nsAutoCString curi;

  if (!gEventWrite)
    return;

  // Note, EventDataDescCreate is a macro defined in the headers, not a function

  aSource->GetSpec(curi);
  nsAutoString uri = NS_ConvertUTF8toUTF16(curi);

  // Get the name of the currently running process
  nsCOMPtr<nsIXULAppInfo> appInfo = do_GetService("@mozilla.org/xre/app-info;1");
  nsAutoCString asciiAppName;
  if (appInfo)
    appInfo->GetName(asciiAppName);
  nsAutoString appName = NS_ConvertUTF8toUTF16(asciiAppName);

  static const WCHAR fill[] = L"";
  
  // See wpcevent.h and msdn for event formats
  EVENT_DATA_DESCRIPTOR eventData[WPC_ARGS_FILEDOWNLOADEVENT_CARGS];
  DWORD dwBlocked = blocked;

  EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_URL], (const void*)uri.get(),
                      ((ULONG)uri.Length()+1)*sizeof(WCHAR));
  EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_APPNAME], (const void*)appName.get(),
                      ((ULONG)appName.Length()+1)*sizeof(WCHAR));
  EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_VERSION], (const void*)fill, sizeof(fill));
  EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_BLOCKED], (const void*)&dwBlocked,
                      sizeof(dwBlocked));

  nsCOMPtr<nsILocalFileWin> local(do_QueryInterface(aTarget)); // May be null
  if (local) {
    nsAutoString path;
    local->GetCanonicalPath(path);
    EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_PATH], (const void*)path.get(),
                        ((ULONG)path.Length()+1)*sizeof(WCHAR));
  }
  else {
    EventDataDescCreate(&eventData[WPC_ARGS_FILEDOWNLOADEVENT_PATH], (const void*)fill, sizeof(fill));
  }

  gEventWrite(mProvider, &WPCEVENT_WEB_FILEDOWNLOAD, ARRAYSIZE(eventData), eventData);
}