ReactOS  0.4.12-dev-36-g472787f
eventcreate.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <windef.h>
#include <winbase.h>
#include <winreg.h>
#include <conutils.h>
#include <strsafe.h>
#include "resource.h"
Include dependency graph for eventcreate.c:

Go to the source code of this file.

Classes

struct  _OPTION
 

Macros

#define EVENT_ID_MIN   0
 
#define EVENT_ID_MAX   65535
 
#define APPLICATION_NAME   L"EventCreate"
 
#define MAX_KEY_LENGTH   255
 
#define OPTION_ALLOWED_LIST   0x01
 
#define OPTION_NOT_EMPTY   0x02
 
#define OPTION_TRIM_SPACE   0x04
 
#define OPTION_EXCLUSIVE   0x08
 
#define OPTION_MANDATORY   0x10
 
#define NEW_OPT(Name, Type, Flags, MaxOfInstances, ValueSize, ValueBuffer)   {(Name), (Type), (Flags), (MaxOfInstances), NULL, NULL, 0, (ValueSize), (ValueBuffer)}
 
#define NEW_OPT_EX(Name, Type, Flags, AllowedValues, MaxOfInstances, ValueSize, ValueBuffer)   {(Name), (Type), (Flags), (MaxOfInstances), (AllowedValues), NULL, 0, (ValueSize), (ValueBuffer)}
 
#define OPT_SYSTEM   (Options[1])
 
#define OPT_USER   (Options[2])
 
#define OPT_PASSWD   (Options[3])
 
#define OPT_EVTID   (Options[8])
 

Typedefs

typedef struct _OPTION OPTION
 
typedef struct _OPTIONPOPTION
 
typedef enum _PARSER_ERROR PARSER_ERROR
 
typedef VOID(__cdeclPRINT_ERROR_FUNC) (IN PARSER_ERROR,...)
 

Enumerations

enum  TYPE { TYPE_None = 0, TYPE_Str, TYPE_U32 }
 
enum  _PARSER_ERROR {
  Success = 0, InvalidSyntax, InvalidOption, ValueRequired,
  ValueIsEmpty, InvalidValue, ValueNotAllowed, TooManySameOption,
  MandatoryOptionAbsent
}
 

Functions

VOID PrintError (DWORD dwError)
 
static BOOL GetUserToken (OUT PTOKEN_USER *ppUserToken)
 
static LONG InstallEventSource (IN HKEY hEventLogKey, IN LPCWSTR EventLogSource)
 
static BOOL CheckLogOrSourceExistence (IN LPCWSTR UNCServerName OPTIONAL, IN LPCWSTR EventLogName, IN LPCWSTR EventLogSource, IN BOOL AllowAppSources OPTIONAL)
 
static PWSTR TrimLeftRightWhitespace (IN PWSTR String)
 
BOOL DoParse (IN INT argc, IN WCHAR *argv[], IN OUT POPTION Options, IN ULONG NumOptions, IN PRINT_ERROR_FUNC PrintErrorFunc OPTIONAL)
 
static VOID __cdecl PrintParserError (PARSER_ERROR Error,...)
 
int wmain (int argc, WCHAR *argv[])
 

Macro Definition Documentation

◆ APPLICATION_NAME

#define APPLICATION_NAME   L"EventCreate"

Definition at line 108 of file eventcreate.c.

Referenced by InstallEventSource(), and wmain().

◆ EVENT_ID_MAX

#define EVENT_ID_MAX   65535

Definition at line 102 of file eventcreate.c.

Referenced by wmain().

◆ EVENT_ID_MIN

#define EVENT_ID_MIN   0

Definition at line 101 of file eventcreate.c.

Referenced by wmain().

◆ MAX_KEY_LENGTH

◆ NEW_OPT

#define NEW_OPT (   Name,
  Type,
  Flags,
  MaxOfInstances,
  ValueSize,
  ValueBuffer 
)    {(Name), (Type), (Flags), (MaxOfInstances), NULL, NULL, 0, (ValueSize), (ValueBuffer)}

Definition at line 684 of file eventcreate.c.

Referenced by wmain().

◆ NEW_OPT_EX

#define NEW_OPT_EX (   Name,
  Type,
  Flags,
  AllowedValues,
  MaxOfInstances,
  ValueSize,
  ValueBuffer 
)    {(Name), (Type), (Flags), (MaxOfInstances), (AllowedValues), NULL, 0, (ValueSize), (ValueBuffer)}

Definition at line 687 of file eventcreate.c.

Referenced by wmain().

◆ OPT_EVTID

#define OPT_EVTID   (Options[8])

Referenced by wmain().

◆ OPT_PASSWD

#define OPT_PASSWD   (Options[3])

Referenced by wmain().

◆ OPT_SYSTEM

#define OPT_SYSTEM   (Options[1])

Referenced by wmain().

◆ OPT_USER

#define OPT_USER   (Options[2])

Referenced by wmain().

◆ OPTION_ALLOWED_LIST

#define OPTION_ALLOWED_LIST   0x01

Definition at line 660 of file eventcreate.c.

Referenced by DoParse(), and wmain().

◆ OPTION_EXCLUSIVE

#define OPTION_EXCLUSIVE   0x08

Definition at line 663 of file eventcreate.c.

Referenced by DoParse(), and wmain().

◆ OPTION_MANDATORY

#define OPTION_MANDATORY   0x10

Definition at line 664 of file eventcreate.c.

Referenced by DoParse(), and wmain().

◆ OPTION_NOT_EMPTY

#define OPTION_NOT_EMPTY   0x02

Definition at line 661 of file eventcreate.c.

Referenced by DoParse(), and wmain().

◆ OPTION_TRIM_SPACE

#define OPTION_TRIM_SPACE   0x04

Definition at line 662 of file eventcreate.c.

Referenced by DoParse(), and wmain().

Typedef Documentation

◆ OPTION

◆ PARSER_ERROR

◆ POPTION

typedef struct _OPTION * POPTION

◆ PRINT_ERROR_FUNC

typedef VOID(__cdecl * PRINT_ERROR_FUNC) (IN PARSER_ERROR,...)

Definition at line 723 of file eventcreate.c.

Enumeration Type Documentation

◆ _PARSER_ERROR

Enumerator
Success 
InvalidSyntax 
InvalidOption 
ValueRequired 
ValueIsEmpty 
InvalidValue 
ValueNotAllowed 
TooManySameOption 
MandatoryOptionAbsent 

Definition at line 710 of file eventcreate.c.

◆ TYPE

Enumerator
TYPE_None 
TYPE_Str 
TYPE_U32 

Definition at line 651 of file eventcreate.c.

652 {
653  TYPE_None = 0,
654  TYPE_Str,
655 // TYPE_U8,
656 // TYPE_U16,
657  TYPE_U32,
658 };

Function Documentation

◆ CheckLogOrSourceExistence()

static BOOL CheckLogOrSourceExistence ( IN LPCWSTR UNCServerName  OPTIONAL,
IN LPCWSTR  EventLogName,
IN LPCWSTR  EventLogSource,
IN BOOL AllowAppSources  OPTIONAL 
)
static

Definition at line 260 of file eventcreate.c.

Referenced by wmain().

265 {
266  /*
267  * The 'AllowAppSources' parameter allows the usage of
268  * application (non-custom) sources, when set to TRUE.
269  * Its default value is FALSE.
270  */
271 
272 #define MAX_KEY_LENGTH 255 // or 256 ??
273 
274  BOOL Success = FALSE;
275  LONG lRet;
276  HKEY hEventLogKey = NULL, hLogKey = NULL;
277  DWORD NameLen;
278  DWORD dwIndex;
279 
280  BOOL LogNameValid, LogSourceValid;
281  BOOL FoundLog = FALSE, FoundSource = FALSE;
282  BOOL SourceAlreadyExists = FALSE, SourceCreated = FALSE, IsCustomSource = FALSE;
283 
284  WCHAR LogName[MAX_KEY_LENGTH]; // Current event log being tested for.
285  WCHAR LogNameErr[MAX_KEY_LENGTH]; // Event log in which the source already exists.
286 
287  UNREFERENCED_PARAMETER(UNCServerName); // FIXME: Use remote server if needed!
288 
289  LogNameValid = (EventLogName && *EventLogName);
290  LogSourceValid = (EventLogSource && *EventLogSource);
291 
292  /*
293  * If neither the log name nor the log source are specified,
294  * there is no need to continue. Just fail.
295  */
296  if (!LogNameValid && !LogSourceValid)
297  return FALSE;
298 
299  lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, // FIXME: Use remote server if needed!
300  L"SYSTEM\\CurrentControlSet\\Services\\EventLog",
302  &hEventLogKey);
303  if (lRet != ERROR_SUCCESS)
304  goto Quit;
305 
306  /*
307  * If we just have a valid log name but no specified source, check whether
308  * the log key exist by atttempting to open it. If we fail: no log.
309  * In all cases we do not perform other tests nor create any source.
310  */
311  if (LogNameValid && !LogSourceValid)
312  {
313  lRet = RegOpenKeyExW(hEventLogKey,
314  EventLogName,
315  0, KEY_QUERY_VALUE,
316  &hLogKey);
317  RegCloseKey(hLogKey);
318  FoundLog = (lRet == ERROR_SUCCESS);
319 
320  if (FoundLog)
321  {
322  /* Set the flags to consistent values */
323  SourceCreated = TRUE;
324  IsCustomSource = TRUE;
325  }
326  goto Finalize;
327  }
328 
329  /* Here, LogSourceValid is always TRUE */
330 
331  /*
332  * We now have a valid source and either an event log name or none.
333  * Search for the source existence over all the existing logs:
334  * we loop through the event logs and we will:
335  * - localize whether the specified source exists and in which log it does;
336  * - and at the same time, check whether the specified log does exist.
337  */
338  dwIndex = 0;
339  while (TRUE)
340  {
341  NameLen = ARRAYSIZE(LogName);
342  LogName[0] = L'\0';
343 
344  lRet = RegEnumKeyExW(hEventLogKey, dwIndex, LogName, &NameLen,
345  NULL, NULL, NULL, NULL);
346  if (dwIndex > 0)
347  {
348  if (lRet == ERROR_NO_MORE_ITEMS)
349  {
350  /*
351  * We may/may not have found our log and may/may not have found
352  * our source. Quit the loop, we will check those details after.
353  */
354  break; // goto Finalize;
355  }
356  }
357  if (lRet != ERROR_SUCCESS)
358  {
359  /* A registry error happened, just fail */
360  goto Quit;
361  }
362 
363  /* We will then continue with the next log */
364  ++dwIndex;
365 
366  /* If we have specified a log, check whether we have found it */
367  if (LogNameValid && _wcsicmp(LogName, EventLogName) == 0)
368  {
369  /*
370  * We have found the specified log, but do not break yet: if we have
371  * a specified source, we want to be sure it does not exist elsewhere.
372  */
373  FoundLog = TRUE;
374  }
375 
376  /*
377  * The following case: if (LogNameValid && !LogSourceValid) {...}
378  * was already dealt with before. Here, LogSourceValid is always TRUE.
379  */
380 
381  /* Now determine whether we need to continue */
382  if (/* LogNameValid && */ FoundLog)
383  {
384 #if 0
385  if (!LogSourceValid)
386  {
387  /*
388  * We have found our log and we do not use any source,
389  * we can stop scanning now.
390  */
391  /* Set the flags to consistent values */
392  SourceCreated = TRUE;
393  IsCustomSource = TRUE;
394  break; // goto Finalize;
395  }
396 #endif
397  if (SourceAlreadyExists)
398  {
399  /*
400  * We have finally found our log but the source existed elsewhere,
401  * stop scanning and we will error that the source is not in the
402  * expected log. On the contrary, if our log was not found yet,
403  * continue scanning to attempt to find it and, if the log is not
404  * found at the end we will error that the log does not exist.
405  */
406  break; // goto Finalize;
407  }
408  }
409 
410  /*
411  * If we have specified a source and have not found it so far,
412  * check for its presence in this log.
413  * NOTE: Here, LogSourceValid is always TRUE.
414  */
415  if (LogSourceValid && !FoundSource)
416  {
417  HKEY hKeySource = NULL;
418 
419  /* Check the sources inside this log */
420  lRet = RegOpenKeyExW(hEventLogKey, LogName, 0, KEY_READ, &hLogKey);
421  if (lRet != ERROR_SUCCESS)
422  {
423  /* A registry error happened, just fail */
424  goto Quit;
425  }
426 
427  /*
428  * Attempt to open the source key.
429  *
430  * NOTE: Alternatively we could have scanned each source key
431  * in this log by using RegEnumKeyExW.
432  */
433  lRet = RegOpenKeyExW(hLogKey, EventLogSource,
434  0, KEY_QUERY_VALUE,
435  &hKeySource);
436 
437  /* Get rid of the log key handle */
438  RegCloseKey(hLogKey);
439  hLogKey = NULL;
440 
441  if (lRet == ERROR_SUCCESS) // || lRet == ERROR_ACCESS_DENIED
442  {
443  /*
444  * We have found our source in this log (it can be
445  * in a different log than the one specified).
446  */
447  FoundSource = TRUE;
448  // lRet = ERROR_SUCCESS;
449  }
450  else if (lRet == ERROR_FILE_NOT_FOUND)
451  {
452  /* Our source was not found there */
453  lRet = ERROR_SUCCESS;
454  hKeySource = NULL;
455  }
456  else // if (lRet != ERROR_SUCCESS && lRet != ERROR_FILE_NOT_FOUND)
457  {
458  /* A registry error happened, but we continue scanning the other logs... */
459  hKeySource = NULL;
460  }
461 
462  /* If we have not found our source, continue scanning the other logs */
463  if (!FoundSource)
464  continue;
465 
466  /*
467  * We have found our source, but is it in the correct log?
468  *
469  * NOTE: We check only in the case we have specified a log,
470  * otherwise we just care about the existence of the source
471  * and we do not check for its presence in the other logs.
472  */
473  if (LogNameValid && !(FoundLog && _wcsicmp(LogName, EventLogName) == 0))
474  {
475  /* Now get rid of the source key handle */
476  RegCloseKey(hKeySource);
477  hKeySource = NULL;
478 
479  /* The source is in another log than the specified one */
480  SourceAlreadyExists = TRUE;
481 
482  /* Save the log name in which the source already exists */
483  RtlCopyMemory(LogNameErr, LogName, sizeof(LogName));
484 
485  /*
486  * We continue because we want to also know whether we can
487  * still find our specified log (and we will error that the
488  * source exists elsewhere), or whether the log does not exist
489  * (and we will error accordingly).
490  */
491  continue;
492  }
493 
494  /*
495  * We have found our source, and if we have specified a log,
496  * the source is in the correct log.
497  */
498  SourceCreated = TRUE;
499 
500  /*
501  * Check whether this is one of our custom sources
502  * (application sources do not have this value present).
503  */
504  IsCustomSource = FALSE;
505 
506  lRet = RegQueryValueExW(hKeySource, L"CustomSource", NULL, NULL, NULL, NULL);
507 
508  /* Now get rid of the source key handle */
509  RegCloseKey(hKeySource);
510  hKeySource = NULL;
511 
512  if (lRet == ERROR_SUCCESS)
513  {
514  IsCustomSource = TRUE;
515  }
516  else if (lRet == ERROR_FILE_NOT_FOUND)
517  {
518  // IsCustomSource = FALSE;
519  }
520  else // if (lRet != ERROR_SUCCESS && lRet != ERROR_FILE_NOT_FOUND)
521  {
522  /* A registry error happened, just fail */
523  goto Quit;
524  }
525 
526  /*
527  * We have found our source and it may be (or not) a custom source,
528  * and it is in the correct event log (if we have specified one).
529  * Break the search loop.
530  */
531  break; // goto Finalize;
532  }
533  }
534 
535  /*
536  * No errors happened so far.
537  * Perform last validity checks (the flags are all valid and 'LogName'
538  * contains the name of the last log having been tested for).
539  */
540 Finalize:
541  lRet = ERROR_SUCCESS; // but do not set Success to TRUE yet.
542 
543  // FIXME: Shut up a GCC warning/error about 'SourceCreated' being unused.
544  // We will use it later on.
545  UNREFERENCED_PARAMETER(SourceCreated);
546 
547  /*
548  * The source does not exist (SourceCreated == FALSE), create it.
549  * Note that we then must have a specified log that exists on the system.
550  */
551  // NOTE: IsCustomSource always FALSE here.
552 
553  if (LogNameValid && !FoundLog)
554  {
555  /* We have specified a log but it does not exist! */
556  ConResPrintf(StdErr, IDS_LOG_NOT_FOUND, EventLogName);
557  goto Quit;
558  }
559 
560  //
561  // Here, LogNameValid == TRUE && FoundLog == TRUE, or
562  // LogNameValid == FALSE && FoundLog == FALSE.
563  //
564 
565  if (LogNameValid /* && FoundLog */ && !LogSourceValid /* && !FoundSource && !SourceAlreadyExists */)
566  {
567  /* No source, just use the log */
568  // NOTE: For this case, SourceCreated and IsCustomSource were both set to TRUE.
569  Success = TRUE;
570  goto Quit;
571  }
572 
573  if (/* LogSourceValid && */ FoundSource && SourceAlreadyExists)
574  {
575  /* The source is in another log than the specified one */
576  ConResPrintf(StdErr, IDS_SOURCE_EXISTS, LogNameErr);
577  goto Quit;
578  }
579 
580  if (/* LogSourceValid && */ FoundSource && !SourceAlreadyExists)
581  {
582  /* We can directly use the source */
583 
584  // if (SourceCreated)
585  {
586  /* The source already exists, check whether this is a custom one */
587  if (IsCustomSource || AllowAppSources)
588  {
589  /* This is a custom source, fine! */
590  Success = TRUE;
591  goto Quit;
592  }
593  else
594  {
595  /* This is NOT a custom source, we must return an error! */
597  goto Quit;
598  }
599  }
600  }
601 
602  if (LogSourceValid && !FoundSource)
603  {
604  if (!LogNameValid /* && !FoundLog */)
605  {
606  /* The log name is not specified, we cannot create the source */
608  goto Quit;
609  }
610  else // LogNameValid && FoundLog
611  {
612  /* Create a new source in the specified log */
613 
614  lRet = RegOpenKeyExW(hEventLogKey,
615  EventLogName,
616  0, KEY_CREATE_SUB_KEY, // KEY_WRITE
617  &hLogKey);
618  if (lRet != ERROR_SUCCESS)
619  goto Quit;
620 
621  /* Register the new event source */
622  lRet = InstallEventSource(hLogKey, EventLogSource);
623 
624  RegCloseKey(hLogKey);
625 
626  if (lRet != ERROR_SUCCESS)
627  {
628  PrintError(lRet);
629  ConPrintf(StdErr, L"Impossible to create the source `%s' for log `%s'!\n",
630  EventLogSource, EventLogName);
631  goto Quit;
632  }
633 
634  SourceCreated = TRUE;
635  Success = TRUE;
636  }
637  }
638 
639 Quit:
640  if (hEventLogKey)
641  RegCloseKey(hEventLogKey);
642 
643  SetLastError(lRet);
644 
645  return Success;
646 }
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define ERROR_SUCCESS
Definition: deptool.c:10
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:95
#define KEY_READ
Definition: nt_native.h:1023
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define IDS_LOG_NOT_FOUND
Definition: resource.h:15
#define IDS_SOURCE_EXISTS
Definition: resource.h:17
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define MAX_KEY_LENGTH
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
long LONG
Definition: pedump.c:60
INT __cdecl ConPrintf(IN PCON_STREAM Stream, IN LPWSTR szStr,...)
Definition: outstream.c:520
smooth NULL
Definition: ftsmooth.c:416
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
INT __cdecl ConResPrintf(IN PCON_STREAM Stream, IN UINT uID,...)
Definition: outstream.c:781
unsigned int BOOL
Definition: ntddk_ex.h:94
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4134
PEVENTSOURCE EventLogSource
Definition: eventlog.c:35
unsigned long DWORD
Definition: ntddk_ex.h:95
#define SetLastError(x)
Definition: compat.h:409
#define StdErr
Definition: stream.h:77
INT ConResPuts(IN PCON_STREAM Stream, IN UINT uID)
Definition: outstream.c:610
static const WCHAR L[]
Definition: oid.c:1087
VOID PrintError(DWORD dwError)
Definition: eventcreate.c:111
#define IDS_SOURCE_NOT_CUSTOM
Definition: resource.h:18
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
static LONG InstallEventSource(IN HKEY hEventLogKey, IN LPCWSTR EventLogSource)
Definition: eventcreate.c:178
#define IDS_SOURCE_NOCREATE
Definition: resource.h:16
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3381
LONG WINAPI RegEnumKeyExW(_In_ HKEY hKey, _In_ DWORD dwIndex, _Out_ LPWSTR lpName, _Inout_ LPDWORD lpcbName, _Reserved_ LPDWORD lpReserved, _Out_opt_ LPWSTR lpClass, _Inout_opt_ LPDWORD lpcbClass, _Out_opt_ PFILETIME lpftLastWriteTime)
Definition: reg.c:2541
#define KEY_CREATE_SUB_KEY
Definition: nt_native.h:1018
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019

◆ DoParse()

BOOL DoParse ( IN INT  argc,
IN WCHAR argv[],
IN OUT POPTION  Options,
IN ULONG  NumOptions,
IN PRINT_ERROR_FUNC PrintErrorFunc  OPTIONAL 
)

FIXME: This test is problematic if this concerns the last option in the command-line! A hack-fix is to repeat this check after the 'for'-loop.

HACK-fix for the check done inside the 'for'-loop.

Definition at line 726 of file eventcreate.c.

Referenced by wmain().

732 {
733  BOOL ExclusiveOptionPresent = FALSE;
734  PWSTR OptionStr = NULL;
735  UINT i;
736 
737  /*
738  * The 'Option' index is reset to 'NumOptions' (total number of elements in
739  * the 'Options' list) before retrieving a new option. This is done so that
740  * we know it cannot index a valid option at that moment.
741  */
742  UINT Option = NumOptions;
743 
744  /* Parse command line for options */
745  for (i = 1; i < argc; ++i)
746  {
747  /* Check for new options */
748 
749  if (argv[i][0] == L'-' || argv[i][0] == L'/')
750  {
753  if (Option != NumOptions)
754  {
755  if (PrintErrorFunc)
756  PrintErrorFunc(ValueRequired, OptionStr);
757  return FALSE;
758  }
759 
760  /*
761  * If we have already encountered an (unique) exclusive option,
762  * just break now.
763  */
764  if (ExclusiveOptionPresent)
765  break;
766 
767  OptionStr = argv[i];
768 
769  /* Lookup for the option in the list of options */
770  for (Option = 0; Option < NumOptions; ++Option)
771  {
772  if (_wcsicmp(OptionStr + 1, Options[Option].OptionName) == 0)
773  break;
774  }
775 
776  if (Option >= NumOptions)
777  {
778  if (PrintErrorFunc)
779  PrintErrorFunc(InvalidOption, OptionStr);
780  return FALSE;
781  }
782 
783 
784  /* An option is being set */
785 
786  if (Options[Option].MaxOfInstances != 0 &&
787  Options[Option].Instances >= Options[Option].MaxOfInstances)
788  {
789  if (PrintErrorFunc)
790  PrintErrorFunc(TooManySameOption, OptionStr, Options[Option].MaxOfInstances);
791  return FALSE;
792  }
793  ++Options[Option].Instances;
794 
795  Options[Option].OptionStr = OptionStr;
796 
797  /*
798  * If this option is exclusive, remember it for later.
799  * We will then short-circuit the regular validity checks
800  * and instead check whether this is the only option specified
801  * on the command-line.
802  */
803  if (Options[Option].Flags & OPTION_EXCLUSIVE)
804  ExclusiveOptionPresent = TRUE;
805 
806  /* Preprocess the option before setting its value */
807  switch (Options[Option].Type)
808  {
809  case TYPE_None: // ~= TYPE_Bool
810  {
811  /* Set the associated boolean */
812  BOOL* pBool = (BOOL*)Options[Option].Value;
813  *pBool = TRUE;
814 
815  /* No associated value, so reset the index */
816  Option = NumOptions;
817  }
818 
819  /* Fall-back */
820 
821  case TYPE_Str:
822 
823  // case TYPE_U8:
824  // case TYPE_U16:
825  case TYPE_U32:
826  break;
827 
828  default:
829  {
830  wprintf(L"PARSER: Unsupported option type %lu\n", Options[Option].Type);
831  break;
832  }
833  }
834  }
835  else
836  {
837  /* A value for an option is being set */
838  switch (Options[Option].Type)
839  {
840  case TYPE_None:
841  {
842  /* There must be no associated value */
843  if (PrintErrorFunc)
844  PrintErrorFunc(ValueNotAllowed, OptionStr);
845  return FALSE;
846  }
847 
848  case TYPE_Str:
849  {
850  /* Retrieve the string */
851  PWSTR* pStr = (PWSTR*)Options[Option].Value;
852  *pStr = argv[i];
853 
854  /* Trim whitespace if needed */
855  if (Options[Option].Flags & OPTION_TRIM_SPACE)
856  *pStr = TrimLeftRightWhitespace(*pStr);
857 
858  /* Check whether or not the value can be empty */
859  if ((Options[Option].Flags & OPTION_NOT_EMPTY) && !**pStr)
860  {
861  /* Value cannot be empty */
862  if (PrintErrorFunc)
863  PrintErrorFunc(ValueIsEmpty, OptionStr);
864  return FALSE;
865  }
866 
867  /* Check whether the value is part of the allowed list of values */
868  if (Options[Option].Flags & OPTION_ALLOWED_LIST)
869  {
870  PWSTR AllowedValues, Scan;
871  SIZE_T Length;
872 
873  AllowedValues = Options[Option].AllowedValues;
874  if (!AllowedValues)
875  {
876  /* The array is empty, no allowed values */
877  if (PrintErrorFunc)
878  PrintErrorFunc(InvalidValue, *pStr, OptionStr);
879  return FALSE;
880  }
881 
882  Scan = AllowedValues;
883  while (*Scan)
884  {
885  /* Find the values separator */
886  Length = wcscspn(Scan, L"|");
887 
888  /* Check whether this is an allowed value */
889  if ((wcslen(*pStr) == Length) &&
890  (_wcsnicmp(*pStr, Scan, Length) == 0))
891  {
892  /* Found it! */
893  break;
894  }
895 
896  /* Go to the next test value */
897  Scan += Length;
898  if (*Scan) ++Scan; // Skip the separator
899  }
900 
901  if (!*Scan)
902  {
903  /* The value is not allowed */
904  if (PrintErrorFunc)
905  PrintErrorFunc(InvalidValue, *pStr, OptionStr);
906  return FALSE;
907  }
908  }
909 
910  break;
911  }
912 
913  // case TYPE_U8:
914  // case TYPE_U16:
915  case TYPE_U32:
916  {
917  PWCHAR pszNext = NULL;
918 
919  /* The number is specified in base 10 */
920  // NOTE: We might use '0' so that the base is automatically determined.
921  *(ULONG*)Options[Option].Value = wcstoul(argv[i], &pszNext, 10);
922  if (*pszNext)
923  {
924  /* The value is not a valid numeric value and is not allowed */
925  if (PrintErrorFunc)
926  PrintErrorFunc(InvalidValue, argv[i], OptionStr);
927  return FALSE;
928  }
929  break;
930  }
931 
932  default:
933  {
934  wprintf(L"PARSER: Unsupported option type %lu\n", Options[Option].Type);
935  break;
936  }
937  }
938 
939  /* Reset the index */
940  Option = NumOptions;
941  }
942  }
943 
945  if (Option != NumOptions)
946  {
947  if (PrintErrorFunc)
948  PrintErrorFunc(ValueRequired, OptionStr);
949  return FALSE;
950  }
951 
952  /* Finalize options validity checks */
953 
954  if (ExclusiveOptionPresent)
955  {
956  /*
957  * An exclusive option present on the command-line:
958  * check whether this is the only option specified.
959  */
960  for (i = 0; i < NumOptions; ++i)
961  {
962  if (!(Options[i].Flags & OPTION_EXCLUSIVE) && (Options[i].Instances != 0))
963  {
964  /* A non-exclusive option is present on the command-line, fail */
965  if (PrintErrorFunc)
966  PrintErrorFunc(InvalidSyntax);
967  return FALSE;
968  }
969  }
970 
971  /* No other checks needed, we are done */
972  return TRUE;
973  }
974 
975  /* Check whether the required options were specified */
976  for (i = 0; i < NumOptions; ++i)
977  {
978  /* Regular validity checks */
979  if ((Options[i].Flags & OPTION_MANDATORY) && (Options[i].Instances == 0))
980  {
981  if (PrintErrorFunc)
982  PrintErrorFunc(MandatoryOptionAbsent, Options[i].OptionName);
983  return FALSE;
984  }
985  }
986 
987  /* All checks are done */
988  return TRUE;
989 }
_In_opt_ ULONG _Out_ PULONG Value
Definition: rtlfuncs.h:2327
static int argc
Definition: ServiceArgs.c:12
#define TRUE
Definition: types.h:120
Type
Definition: Type.h:6
#define OPTION_EXCLUSIVE
Definition: eventcreate.c:663
uint16_t * PWSTR
Definition: typedefs.h:54
#define OPTION_NOT_EMPTY
Definition: eventcreate.c:661
#define OPTION_MANDATORY
Definition: eventcreate.c:664
_Check_return_ _CRTIMP size_t __cdecl wcscspn(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_Control)
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
uint16_t * PWCHAR
Definition: typedefs.h:54
_Check_return_ unsigned long __cdecl wcstoul(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
#define wprintf(...)
Definition: whoami.c:18
enum OPTION_FLAGS Options
Definition: stats.c:44
static char ** argv
Definition: ServiceArgs.c:11
#define OPTION_TRIM_SPACE
Definition: eventcreate.c:662
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
GLenum GLclampf GLint i
Definition: glfuncs.h:14
smooth NULL
Definition: ftsmooth.c:416
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned int UINT
Definition: ndis.h:50
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
static const WCHAR L[]
Definition: oid.c:1087
static PWSTR TrimLeftRightWhitespace(IN PWSTR String)
Definition: eventcreate.c:691
ULONG_PTR SIZE_T
Definition: typedefs.h:78
#define OPTION_ALLOWED_LIST
Definition: eventcreate.c:660
unsigned int ULONG
Definition: retypes.h:1
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)

◆ GetUserToken()

static BOOL GetUserToken ( OUT PTOKEN_USER ppUserToken)
static

Definition at line 123 of file eventcreate.c.

Referenced by wmain().

125 {
126  BOOL Success = FALSE;
127  DWORD dwError;
128  HANDLE hToken;
129  DWORD cbTokenBuffer = 0;
130  PTOKEN_USER pUserToken = NULL;
131 
132  *ppUserToken = NULL;
133 
134  /* Get the process token */
136  return FALSE;
137 
138  /* Retrieve token's information */
139  if (!GetTokenInformation(hToken, TokenUser, NULL, 0, &cbTokenBuffer))
140  {
141  dwError = GetLastError();
142  if (dwError != ERROR_INSUFFICIENT_BUFFER)
143  goto Quit;
144  }
145 
146  pUserToken = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbTokenBuffer);
147  if (!pUserToken)
148  {
149  dwError = ERROR_NOT_ENOUGH_MEMORY;
150  goto Quit;
151  }
152 
153  if (!GetTokenInformation(hToken, TokenUser, pUserToken, cbTokenBuffer, &cbTokenBuffer))
154  {
155  dwError = GetLastError();
156  goto Quit;
157  }
158 
159  Success = TRUE;
160  dwError = ERROR_SUCCESS;
161  *ppUserToken = pUserToken;
162 
163 Quit:
164  if (Success == FALSE)
165  {
166  if (pUserToken)
167  HeapFree(GetProcessHeap(), 0, pUserToken);
168  }
169 
170  CloseHandle(hToken);
171 
172  SetLastError(dwError);
173 
174  return Success;
175 }
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
#define ERROR_SUCCESS
Definition: deptool.c:10
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
smooth NULL
Definition: ftsmooth.c:416
unsigned int BOOL
Definition: ntddk_ex.h:94
#define GetProcessHeap()
Definition: compat.h:395
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
#define TOKEN_QUERY
Definition: setypes.h:874
HANDLE WINAPI GetCurrentProcess(VOID)
Definition: proc.c:1168
unsigned long DWORD
Definition: ntddk_ex.h:95
#define SetLastError(x)
Definition: compat.h:409
BOOL WINAPI OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle)
Definition: security.c:292
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
BOOL WINAPI GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength, PDWORD ReturnLength)
Definition: security.c:409
#define HeapFree(x, y, z)
Definition: compat.h:394
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10

◆ InstallEventSource()

static LONG InstallEventSource ( IN HKEY  hEventLogKey,
IN LPCWSTR  EventLogSource 
)
static

Definition at line 178 of file eventcreate.c.

Referenced by CheckLogOrSourceExistence().

181 {
182  LONG lRet;
183  HKEY hSourceKey = NULL;
184  DWORD dwDisposition = 0;
185  DWORD dwData;
186 
187  LPCWSTR EventMessageFile;
188  DWORD PathSize;
189  WCHAR ExePath[MAX_PATH];
190 
191  lRet = RegCreateKeyExW(hEventLogKey,
195  &hSourceKey, &dwDisposition);
196  if (lRet != ERROR_SUCCESS)
197  goto Quit;
198  if (dwDisposition != REG_CREATED_NEW_KEY)
199  {
200  /* The source key already exists, just quit */
201  goto Quit;
202  }
203 
204  /* We just have created the new source. Add the values. */
205 
206  /*
207  * Retrieve the full path of the current running executable.
208  * We need it to install our custom event source.
209  * - In case of success, try to replace the ReactOS installation path
210  * (if present in the executable path) by %SystemRoot%.
211  * - In case of failure, use a default path.
212  */
213  PathSize = GetModuleFileNameW(NULL, ExePath, ARRAYSIZE(ExePath));
214  if ((PathSize == 0) || (GetLastError() == ERROR_INSUFFICIENT_BUFFER))
215  {
216  /* We failed, copy the default value */
217  StringCchCopyW(ExePath, ARRAYSIZE(ExePath),
218  L"%SystemRoot%\\System32\\" APPLICATION_NAME L".exe");
219  }
220  else
221  {
222  /* Alternatively one can use SharedUserData->NtSystemRoot */
223  WCHAR TmpDir[ARRAYSIZE(ExePath)];
224  PathSize = GetSystemWindowsDirectoryW(TmpDir, ARRAYSIZE(TmpDir));
225  if ((PathSize > 0) && (_wcsnicmp(ExePath, TmpDir, PathSize) == 0))
226  {
227  StringCchCopyW(TmpDir, ARRAYSIZE(TmpDir), L"%SystemRoot%");
228  StringCchCatW(TmpDir, ARRAYSIZE(TmpDir), ExePath + PathSize);
229  StringCchCopyW(ExePath, ARRAYSIZE(ExePath), TmpDir);
230  }
231  }
232  EventMessageFile = ExePath;
233 
234  lRet = ERROR_SUCCESS;
235 
236  dwData = 1;
237  RegSetValueExW(hSourceKey, L"CustomSource", 0, REG_DWORD,
238  (LPBYTE)&dwData, sizeof(dwData));
239 
240  // FIXME: Set those flags according to caller's rights?
241  // Or, if we are using the Security log?
243  /* | EVENTLOG_AUDIT_SUCCESS | EVENTLOG_AUDIT_FAILURE */ ;
244  RegSetValueExW(hSourceKey, L"TypesSupported", 0, REG_DWORD,
245  (LPBYTE)&dwData, sizeof(dwData));
246 
247  RegSetValueExW(hSourceKey, L"EventMessageFile", 0, REG_EXPAND_SZ,
248  (LPBYTE)EventMessageFile, (wcslen(EventMessageFile) + 1) * sizeof(WCHAR));
249 
250  RegFlushKey(hSourceKey);
251 
252 Quit:
253  if (hSourceKey)
254  RegCloseKey(hSourceKey);
255 
256  return lRet;
257 }
DWORD WINAPI GetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize)
Definition: loader.c:607
#define APPLICATION_NAME
Definition: eventcreate.c:108
UINT WINAPI GetSystemWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2396
#define ERROR_SUCCESS
Definition: deptool.c:10
#define KEY_SET_VALUE
Definition: nt_native.h:1017
__wchar_t WCHAR
Definition: xmlstorage.h:180
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
static HANDLE ULONG_PTR dwData
Definition: file.c:35
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
LONG WINAPI RegFlushKey(HKEY hKey)
Definition: reg.c:2988
LONG WINAPI RegCreateKeyExW(_In_ HKEY hKey, _In_ LPCWSTR lpSubKey, _In_ DWORD Reserved, _In_opt_ LPWSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_opt_ LPDWORD lpdwDisposition)
Definition: reg.c:1094
STRSAFEAPI StringCchCatW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:325
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
unsigned char * LPBYTE
Definition: typedefs.h:52
#define EVENTLOG_ERROR_TYPE
Definition: winnt_old.h:2630
long LONG
Definition: pedump.c:60
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
smooth NULL
Definition: ftsmooth.c:416
#define REG_CREATED_NEW_KEY
Definition: nt_native.h:1084
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4917
#define EVENTLOG_SUCCESS
Definition: winnt_old.h:2629
#define EVENTLOG_INFORMATION_TYPE
Definition: winnt_old.h:2632
#define EVENTLOG_WARNING_TYPE
Definition: winnt_old.h:2631
PEVENTSOURCE EventLogSource
Definition: eventlog.c:35
#define MAX_PATH
Definition: compat.h:26
unsigned long DWORD
Definition: ntddk_ex.h:95
static const WCHAR L[]
Definition: oid.c:1087
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
#define REG_DWORD
Definition: sdbapi.c:539
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10

◆ PrintError()

VOID PrintError ( DWORD  dwError)

Definition at line 111 of file eventcreate.c.

Referenced by CheckLogOrSourceExistence(), and wmain().

112 {
113  if (dwError == ERROR_SUCCESS)
114  return;
115 
117  NULL, dwError, LANG_USER_DEFAULT);
118  ConPuts(StdErr, L"\n");
119 }
#define ERROR_SUCCESS
Definition: deptool.c:10
smooth NULL
Definition: ftsmooth.c:416
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:404
INT ConMsgPuts(IN PCON_STREAM Stream, IN DWORD dwFlags, IN LPCVOID lpSource OPTIONAL, IN DWORD dwMessageId, IN DWORD dwLanguageId)
Definition: outstream.c:837
#define StdErr
Definition: stream.h:77
static const WCHAR L[]
Definition: oid.c:1087
INT ConPuts(IN PCON_STREAM Stream, IN LPWSTR szStr)
Definition: outstream.c:427
#define LANG_USER_DEFAULT
Definition: tnerror.cpp:50

◆ PrintParserError()

static VOID __cdecl PrintParserError ( PARSER_ERROR  Error,
  ... 
)
static

Definition at line 996 of file eventcreate.c.

Referenced by wmain().

997 {
998  /* WARNING: Please keep this lookup table in sync with the resources! */
999  static UINT ErrorIDs[] =
1000  {
1001  0, /* Success */
1002  IDS_BADSYNTAX_0, /* InvalidSyntax */
1003  IDS_INVALIDSWITCH, /* InvalidOption */
1004  IDS_BADSYNTAX_1, /* ValueRequired */
1005  IDS_BADSYNTAX_2, /* ValueIsEmpty */
1006  IDS_BADSYNTAX_3, /* InvalidValue */
1007  IDS_BADSYNTAX_4, /* ValueNotAllowed */
1008  IDS_BADSYNTAX_5, /* TooManySameOption */
1009  IDS_BADSYNTAX_6, /* MandatoryOptionAbsent */
1010  };
1011 
1012  va_list args;
1013 
1014  if (Error < ARRAYSIZE(ErrorIDs))
1015  {
1016  va_start(args, Error);
1017  ConResPrintfV(StdErr, ErrorIDs[Error], args);
1018  va_end(args);
1019 
1020  if (Error != Success)
1022  }
1023  else
1024  {
1025  ConPrintf(StdErr, L"PARSER: Unknown error %d\n", Error);
1026  }
1027 }
INT ConResPrintfV(IN PCON_STREAM Stream, IN UINT uID, IN va_list args)
Definition: outstream.c:695
#define IDS_BADSYNTAX_4
Definition: resource.h:10
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define IDS_USAGE
Definition: resource.h:3
#define IDS_BADSYNTAX_2
Definition: resource.h:8
#define IDS_BADSYNTAX_1
Definition: resource.h:7
#define va_end(ap)
Definition: acmsvcex.h:90
#define IDS_BADSYNTAX_0
Definition: resource.h:6
INT __cdecl ConPrintf(IN PCON_STREAM Stream, IN LPWSTR szStr,...)
Definition: outstream.c:520
#define IDS_BADSYNTAX_6
Definition: resource.h:12
char * va_list
Definition: acmsvcex.h:78
unsigned int UINT
Definition: ndis.h:50
BOOL Error
Definition: chkdsk.c:66
#define StdErr
Definition: stream.h:77
INT ConResPuts(IN PCON_STREAM Stream, IN UINT uID)
Definition: outstream.c:610
static const WCHAR L[]
Definition: oid.c:1087
#define IDS_BADSYNTAX_3
Definition: resource.h:9
#define IDS_BADSYNTAX_5
Definition: resource.h:11
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define IDS_INVALIDSWITCH
Definition: resource.h:4
#define args
Definition: format.c:66

◆ TrimLeftRightWhitespace()

static PWSTR TrimLeftRightWhitespace ( IN PWSTR  String)
static

Definition at line 691 of file eventcreate.c.

Referenced by DoParse().

693 {
694  PWSTR pStr;
695 
696  /* Trim whitespace on left (just advance the pointer) */
697  while (*String && iswspace(*String))
698  ++String;
699 
700  /* Trim whitespace on right (NULL-terminate) */
701  pStr = String + wcslen(String) - 1;
702  while (pStr >= String && iswspace(*pStr))
703  --pStr;
704  *++pStr = L'\0';
705 
706  /* Return the modified pointer */
707  return String;
708 }
uint16_t * PWSTR
Definition: typedefs.h:54
static WCHAR String[]
Definition: stringtable.c:55
#define iswspace(_c)
Definition: ctype.h:669
static const WCHAR L[]
Definition: oid.c:1087
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)

◆ wmain()

int wmain ( int  argc,
WCHAR argv[] 
)

Definition at line 1029 of file eventcreate.c.

1030 {
1031  BOOL Success = FALSE;
1032  HANDLE hEventLog;
1033  PTOKEN_USER pUserToken;
1034 
1035  /* Default option values */
1036  BOOL bDisplayHelp = FALSE;
1037  PWSTR szSystem = NULL;
1038  PWSTR szDomainUser = NULL;
1039  PWSTR szPassword = NULL;
1040  PWSTR szLogName = NULL;
1041  PWSTR szEventSource = NULL;
1042  PWSTR szEventType = NULL;
1044  ULONG ulEventType = EVENTLOG_INFORMATION_TYPE;
1045  ULONG ulEventCategory = 0;
1046  ULONG ulEventIdentifier = 0;
1047 
1048  OPTION Options[] =
1049  {
1050  /* Help */
1051  NEW_OPT(L"?", TYPE_None, // ~= TYPE_Bool,
1053  1,
1054  sizeof(bDisplayHelp), &bDisplayHelp),
1055 
1056  /* System */
1057  NEW_OPT(L"S", TYPE_Str,
1059  1,
1060  sizeof(szSystem), &szSystem),
1061 
1062  /* Domain & User */
1063  NEW_OPT(L"U", TYPE_Str,
1065  1,
1066  sizeof(szDomainUser), &szDomainUser),
1067 
1068  /* Password */
1069  NEW_OPT(L"P", TYPE_Str,
1070  0,
1071  1,
1072  sizeof(szPassword), &szPassword),
1073 
1074  /* Log name */
1075  NEW_OPT(L"L", TYPE_Str,
1077  1,
1078  sizeof(szLogName), &szLogName),
1079 
1080  /* Event source */
1081  NEW_OPT(L"SO", TYPE_Str,
1083  1,
1084  sizeof(szEventSource), &szEventSource),
1085 
1086  /* Event type */
1087  NEW_OPT_EX(L"T", TYPE_Str,
1089  L"SUCCESS|ERROR|WARNING|INFORMATION",
1090  1,
1091  sizeof(szEventType), &szEventType),
1092 
1093  /* Event category (ReactOS additional option) */
1094  NEW_OPT(L"C", TYPE_U32,
1095  0,
1096  1,
1097  sizeof(ulEventCategory), &ulEventCategory),
1098 
1099  /* Event ID */
1100  NEW_OPT(L"ID", TYPE_U32,
1102  1,
1103  sizeof(ulEventIdentifier), &ulEventIdentifier),
1104 
1105  /* Event description */
1106  NEW_OPT(L"D", TYPE_Str,
1108  1,
1109  sizeof(szDescription), &szDescription),
1110  };
1111 #define OPT_SYSTEM (Options[1])
1112 #define OPT_USER (Options[2])
1113 #define OPT_PASSWD (Options[3])
1114 #define OPT_EVTID (Options[8])
1115 
1116  /* Initialize the Console Standard Streams */
1118 
1119  /* Parse command line for options */
1120  if (!DoParse(argc, argv, Options, ARRAYSIZE(Options), PrintParserError))
1121  return EXIT_FAILURE;
1122 
1123  /* Finalize options validity checks */
1124 
1125  if (bDisplayHelp)
1126  {
1127  if (argc > 2)
1128  {
1129  /* Invalid syntax */
1131  return EXIT_FAILURE;
1132  }
1133 
1135  return EXIT_SUCCESS;
1136  }
1137 
1138  if (szSystem || szDomainUser || szPassword)
1139  {
1140  // TODO: Implement!
1141  if (szSystem)
1143  if (szDomainUser)
1145  if (szPassword)
1147  return EXIT_FAILURE;
1148  }
1149 
1150  if (ulEventIdentifier < EVENT_ID_MIN || ulEventIdentifier > EVENT_ID_MAX)
1151  {
1152  /* Invalid event identifier */
1153  ConResPrintf(StdErr, IDS_BADSYNTAX_7, OPT_EVTID.OptionStr, EVENT_ID_MIN, EVENT_ID_MAX);
1155  return EXIT_FAILURE;
1156  }
1157 
1158  /*
1159  * Set the event type. Note that we forbid the user
1160  * to use security auditing types.
1161  */
1162  if (_wcsicmp(szEventType, L"SUCCESS") == 0)
1163  ulEventType = EVENTLOG_SUCCESS;
1164  else
1165  if (_wcsicmp(szEventType, L"ERROR") == 0)
1166  ulEventType = EVENTLOG_ERROR_TYPE;
1167  else
1168  if (_wcsicmp(szEventType, L"WARNING") == 0)
1169  ulEventType = EVENTLOG_WARNING_TYPE;
1170  else
1171  if (_wcsicmp(szEventType, L"INFORMATION") == 0)
1172  ulEventType = EVENTLOG_INFORMATION_TYPE;
1173  else
1174  {
1175  /* Use a default event type */
1176  ulEventType = EVENTLOG_SUCCESS;
1177  }
1178 
1179  /*
1180  * If we have a source, do not care about the log (as long as we will be
1181  * able to find the source later).
1182  * But if we do not have a source, then two cases:
1183  * - either we have a log name so that we will use OpenEventLog (and use
1184  * default log's source), unless this is the Application log in which case
1185  * we use the default source;
1186  * - or we do not have a log name so that we use default log and source names.
1187  */
1188  if (!szEventSource)
1189  {
1190  if (!szLogName)
1191  szLogName = L"Application";
1192 
1193  if (_wcsicmp(szLogName, L"Application") == 0)
1194  szEventSource = APPLICATION_NAME;
1195  }
1196 
1197  // FIXME: Check whether szLogName == L"Security" !!
1198 
1199  /*
1200  * The event APIs OpenEventLog and RegisterEventSource fall back to using
1201  * the 'Application' log when the specified log name or event source do not
1202  * exist on the system.
1203  * To prevent that and be able to error the user that the specified log name
1204  * or event source do not exist, we need to manually perform the existence
1205  * checks by ourselves.
1206  *
1207  * Check whether either the specified event log OR event source exist on
1208  * the system. If the event log does not exist, return an error. Otherwise
1209  * check whether a specified source already exists (everywhere). If found
1210  * in a different log, return an error. If not found, create the source
1211  * in the specified event log.
1212  *
1213  * NOTE: By default we forbid the usage of application (non-custom) sources.
1214  * An optional switch can be added to EventCreate to allow such sources
1215  * to be used.
1216  */
1217  if (!CheckLogOrSourceExistence(szSystem, szLogName, szEventSource, FALSE))
1218  {
1220  return EXIT_FAILURE;
1221  }
1222 
1223  /* Open the event log, by source or by log name */
1224  if (szEventSource) // && *szEventSource
1225  hEventLog = RegisterEventSourceW(szSystem, szEventSource);
1226  else
1227  hEventLog = OpenEventLogW(szSystem, szLogName);
1228 
1229  if (!hEventLog)
1230  {
1232  return EXIT_FAILURE;
1233  }
1234 
1235  /* Retrieve the current user token and report the event */
1236  if (GetUserToken(&pUserToken))
1237  {
1238  Success = ReportEventW(hEventLog,
1239  ulEventType,
1240  ulEventCategory,
1241  ulEventIdentifier,
1242  pUserToken->User.Sid,
1243  1, // One string
1244  0, // No raw data
1245  (LPCWSTR*)&szDescription,
1246  NULL // No raw data
1247  );
1248  if (!Success)
1249  {
1251  ConPuts(StdErr, L"Failed to report event!\n");
1252  }
1253  else
1254  {
1255  /* Show success */
1256  ConPuts(StdOut, L"\n");
1257  if (!szEventSource)
1258  ConResPrintf(StdOut, IDS_SUCCESS_1, szEventType, szLogName);
1259  else if (!szLogName)
1260  ConResPrintf(StdOut, IDS_SUCCESS_2, szEventType, szEventSource);
1261  else
1262  ConResPrintf(StdOut, IDS_SUCCESS_3, szEventType, szLogName, szEventSource);
1263  }
1264 
1265  HeapFree(GetProcessHeap(), 0, pUserToken);
1266  }
1267  else
1268  {
1270  ConPuts(StdErr, L"GetUserToken() failed!\n");
1271  }
1272 
1273  /* Close the event log */
1274  if (szEventSource && *szEventSource)
1275  DeregisterEventSource(hEventLog);
1276  else
1277  CloseEventLog(hEventLog);
1278 
1279  return (Success ? EXIT_SUCCESS : EXIT_FAILURE);
1280 }
HANDLE WINAPI OpenEventLogW(IN LPCWSTR lpUNCServerName, IN LPCWSTR lpSourceName)
Definition: eventlog.c:985
static int argc
Definition: ServiceArgs.c:12
#define APPLICATION_NAME
Definition: eventcreate.c:108
#define OPTION_EXCLUSIVE
Definition: eventcreate.c:663
#define IDS_SUCCESS_3
Definition: resource.h:22
uint16_t * PWSTR
Definition: typedefs.h:54
#define OPTION_NOT_EMPTY
Definition: eventcreate.c:661
#define OPTION_MANDATORY
Definition: eventcreate.c:664
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
static VOID __cdecl PrintParserError(PARSER_ERROR Error,...)
Definition: eventcreate.c:996
static BOOL GetUserToken(OUT PTOKEN_USER *ppUserToken)
Definition: eventcreate.c:123
#define IDS_USAGE
Definition: resource.h:3
enum OPTION_FLAGS Options
Definition: stats.c:44
static char ** argv
Definition: ServiceArgs.c:11
#define OPTION_TRIM_SPACE
Definition: eventcreate.c:662
#define IDS_SWITCH_UNIMPLEMENTED
Definition: resource.h:24
#define EXIT_SUCCESS
Definition: rdjpgcom.c:55
static BOOL CheckLogOrSourceExistence(IN LPCWSTR UNCServerName OPTIONAL, IN LPCWSTR EventLogName, IN LPCWSTR EventLogSource, IN BOOL AllowAppSources OPTIONAL)
Definition: eventcreate.c:260
#define EVENT_ID_MAX
Definition: eventcreate.c:102
#define ConInitStdStreams()
Definition: stream.h:122
#define EVENTLOG_ERROR_TYPE
Definition: winnt_old.h:2630
#define IDS_SUCCESS_2
Definition: resource.h:21
smooth NULL
Definition: ftsmooth.c:416
INT __cdecl ConResPrintf(IN PCON_STREAM Stream, IN UINT uID,...)
Definition: outstream.c:781
#define EVENTLOG_SUCCESS
Definition: winnt_old.h:2629
unsigned int BOOL
Definition: ntddk_ex.h:94
#define GetProcessHeap()
Definition: compat.h:395
#define EVENTLOG_INFORMATION_TYPE
Definition: winnt_old.h:2632
#define EVENTLOG_WARNING_TYPE
Definition: winnt_old.h:2631
#define EXIT_FAILURE
Definition: jerror.c:33
#define StdErr
Definition: stream.h:77
INT ConResPuts(IN PCON_STREAM Stream, IN UINT uID)
Definition: outstream.c:610
static const WCHAR L[]
Definition: oid.c:1087
VOID PrintError(DWORD dwError)
Definition: eventcreate.c:111
BOOL WINAPI CloseEventLog(IN HANDLE hEventLog)
Definition: eventlog.c:427
#define NEW_OPT_EX(Name, Type, Flags, AllowedValues, MaxOfInstances, ValueSize, ValueBuffer)
Definition: eventcreate.c:687
BOOL WINAPI ReportEventW(IN HANDLE hEventLog, IN WORD wType, IN WORD wCategory, IN DWORD dwEventID, IN PSID lpUserSid, IN WORD wNumStrings, IN DWORD dwDataSize, IN LPCWSTR *lpStrings, IN LPVOID lpRawData)
Definition: eventlog.c:1516
BOOL DoParse(IN INT argc, IN WCHAR *argv[], IN OUT POPTION Options, IN ULONG NumOptions, IN PRINT_ERROR_FUNC PrintErrorFunc OPTIONAL)
Definition: eventcreate.c:726
#define OPT_USER
#define OPT_PASSWD
#define NEW_OPT(Name, Type, Flags, MaxOfInstances, ValueSize, ValueBuffer)
Definition: eventcreate.c:684
#define IDS_HELP
Definition: resource.h:3
BOOL WINAPI DeregisterEventSource(IN HANDLE hEventLog)
Definition: eventlog.c:473
INT ConPuts(IN PCON_STREAM Stream, IN LPWSTR szStr)
Definition: outstream.c:427
#define OPTION_ALLOWED_LIST
Definition: eventcreate.c:660
#define StdOut
Definition: stream.h:76
unsigned int ULONG
Definition: retypes.h:1
SID_AND_ATTRIBUTES User
Definition: setypes.h:956
#define IDS_BADSYNTAX_7
Definition: resource.h:13
#define OPT_EVTID
#define OPT_SYSTEM
HANDLE WINAPI RegisterEventSourceW(IN LPCWSTR lpUNCServerName, IN LPCWSTR lpSourceName)
Definition: eventlog.c:1295
#define IDS_SUCCESS_1
Definition: resource.h:20
#define HeapFree(x, y, z)
Definition: compat.h:394
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
static const WCHAR szDescription[]
Definition: provider.c:52
#define EVENT_ID_MIN
Definition: eventcreate.c:101