a verma
a verma

Reputation: 35

how to write in windows event logs using Ada language?

an Ada application which will write in to windows event logs? i have tried to use system call in Ada but its not working this is main.adb

with System;

with Interfaces.C;
use Interfaces.C;

with Ada.Text_IO;
use Ada.Text_IO;

with Ada.Integer_Text_IO;
use Ada.Integer_Text_IO;

with c_interface;
use c_interface;



with Interfaces.C.Strings;
use Interfaces.C.Strings;

with Ada.Strings.Unbounded; 
use Ada.Strings.Unbounded;

with Ada.Strings.Unbounded.Text_IO; 
use Ada.Strings.Unbounded.Text_IO;


procedure main is

begin

   System_even("error",888,"Demo","this is serious");
   --Put_Line("hello");
   delay 2.0;

end main;

and it's using package c_interface.ads

with Interfaces.C;
use Interfaces.C;

with Interfaces.C.Strings;
use Interfaces.C.Strings;

package c_interface is use Interfaces;

   procedure System_even (EventCreate : String;
                          ID          : Integer;
                          Application : String;
                          Source : String);

private
   pragma Import (C, System_even,"system");

end c_interface;

Upvotes: 0

Views: 176

Answers (2)

Jere
Jere

Reputation: 3641

Jacob already covered the discussion, but I ended up generating a quick binding on top of the system call. I was able to generate application events in Windows 10 using GPS to compile and run it:

Windows_Event_Log.ads

package Windows_Event_Log is

   type Event_Type is
      (Error,
       Warning,
       Information,
       Success_Audit,
       Failure_Audit);

   type Event_Category is
      (Application,
       System);

   -- Calls command
   procedure Event_Create
      (Type_Of_Event : Event_Type;
       ID            : Positive;
       Category      : Event_Category;
       Source        : String;
       Message       : String);

   -- For Debug
   function Make_Event_String
      (Type_Of_Event : Event_Type;
       ID            : Positive;
       Category      : Event_Category;
       Source        : String;
       Message       : String)
       return String;

end Windows_Event_Log;

Windows_Event_Log.adb

with Interfaces.C.Strings;
with Ada.Characters.Latin_1;
with Ada.Containers.Indefinite_Holders;

package body Windows_Event_Log is

   package String_Holders is new Ada.Containers.Indefinite_Holders(String);

   -- Conversion arrays
   Type_String : constant array(Event_Type) of String_Holders.Holder :=
      (Error         => String_Holders.To_Holder("ERROR"),
       Warning       => String_Holders.To_Holder("WARNING"),
       Information   => String_Holders.To_Holder("INFORMATION"),
       Success_Audit => String_Holders.To_Holder("SUCCESSAUDIT"),
       Failure_Audit => String_Holders.To_Holder("FAILUREAUDIT"));

   Category_String : constant array(Event_Category) of String_Holders.Holder :=
      (Application => String_Holders.To_Holder("APPLICATION"),
       System      => String_Holders.To_Holder("SYSTEM"));

   function Make_Event_String
      (Type_Of_Event : Event_Type;
       ID            : Positive;
       Category      : Event_Category;
       Source        : String;
       Message       : String)
       return String
   is begin
      return
         "EventCreate /t "
         & Type_String(Type_Of_Event).Element
         & " /id "
         & Positive'Image(ID)
         & " /l "
         & Category_String(Category).Element
         & " /so "
         & Source
         & " /d """
         & Message
         & """ >nul 2>&1";              -- Suppress output and error
   end Make_Event_String;

   -- Thin binding to the system call
   function System(Str : Interfaces.C.Strings.chars_ptr) return Interfaces.C.int
      with
         Import,
         Convention => C,
         External_Name => "system";

   procedure Event_Create
      (Type_Of_Event : Event_Type;
       ID            : Positive;
       Category      : Event_Category;
       Source        : String;
       Message       : String)
   is
      Event_String : String := Make_Event_String
         (Type_Of_Event => Type_Of_Event,
          ID            => ID,
          Category      => Category,
          Source        => Source,
          Message       => Message)
         & Ada.Characters.Latin_1.NUL; -- needed for C strings

      Event_Chars_Ptr : Interfaces.C.Strings.chars_ptr :=
         Interfaces.C.Strings.New_String(Event_String);  --allocates memory

      -- This line actually makes the system call
      Result : Interfaces.C.int := System(Event_Chars_Ptr);
   begin

      -- Free the allocated memory from New_String
      Interfaces.C.Strings.Free(Event_Chars_Ptr);
   end;

end Windows_Event_Log;

main.adb

with Windows_Event_Log;
with Ada.Text_IO; use Ada.Text_IO;

procedure Main is

   Event_Type : Windows_Event_Log.Event_Type := Windows_Event_Log.Warning;
   ID         : Positive := 458;
   Category   : Windows_Event_Log.Event_Category := Windows_Event_Log.Application;
   Source     : String   := "SomeString";
   Message    : String   := "This is another joke";

begin
   -- Debug print
   Put_Line
      ("Generated Command => "
       & Windows_Event_Log.Make_Event_String
          (Type_Of_Event => Event_Type,
           ID            => ID,
           Category      => Category,
           Source        => Source,
           Message       => Message));

   -- Actual Command Sent
   Windows_Event_Log.Event_Create
      (Type_Of_Event => Event_Type,
       ID            => ID,
       Category      => Category,
       Source        => Source,
       Message       => Message);
end Main;

I only tested a few of the input cases, so it is far from fully tested, but I wanted to give you an example of making a quick binding for it. It was compiled and tested using GNAT GPL 2017 for windows

References

system() api for Windows

EventCreate api for Windows

Rosetta Code Example in C for how to do it

Upvotes: 0

Jacob Sparre Andersen
Jacob Sparre Andersen

Reputation: 6611

I'm not a Microsoft expert, but on other operating systems system() is usually declared as:

int system(const char *command);

That is in no way whatsoever the same as:

procedure System_even (EventCreate : String;
                       ID          : Integer;
                       Application : String;
                       Source      : String);

Change your import so the profiles match. - Or even better, use gcc -fdump-ada-spec to have your compiler generate the correct Ada specification for you.

Upvotes: 2

Related Questions