ReactOS 0.4.15-dev-7958-gcd0bb1a
eventcreate.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS EventCreate Command
4 * FILE: base/applications/cmdutils/eventcreate/eventcreate.c
5 * PURPOSE: Allows reporting custom user events in event logs,
6 * by using the old-school NT <= 2k3 logging API.
7 * PROGRAMMER: Hermes Belusca-Maito
8 *
9 * RATIONALE AND NOTE ABOUT THE IMPLEMENTATION:
10 *
11 * Contrary to what can be expected, there is no simple way of logging inside
12 * a NT event log an arbitrary string, for example a description text, that
13 * can then be viewed in a human-readable form under an event viewer. Indeed,
14 * a NT log entry is not just a simple arbitrary string, but is instead made
15 * of an identifier (ID), an event "source" and an arbitrary data chunk.
16 * To make things somewhat simpler, the data chunk is divided in two parts:
17 * an array of data strings and a raw (binary) data chunk.
18 *
19 * How then can a log entry be reconstructed? At each NT log is associated
20 * one or many event "sources", which are binary files (PE format) containing
21 * a table of predefined string templates (message table resource), indexed
22 * by identifiers. The ID and event source specified in a given log entry
23 * inside a given log allows to refer to one of the string template inside
24 * the specified event source of the log. A human-readable event description
25 * that is shown by an event viewer is obtained by associating the string
26 * template together with the array of data strings of the log entry.
27 * Each of the data strings is a parameter for the string template (formatted
28 * in a printf-like format).
29 *
30 * Thus we see that the human-readable event description of a log entry is
31 * not completely arbitrary but is dictated by both the string templates and
32 * the data strings of the log entry. Only the data strings can be arbitrary.
33 *
34 * Therefore, what can we do to be able to report arbitrary human-readable
35 * events, the description of which the user specifies at the command-line?
36 * There is actually only one possible way: store the description text as
37 * a string inside the array of data strings of the event. But we need the
38 * event to be displayed correctly. For that it needs to be associated with
39 * an event source, and its ID must point to a suitable string template, the
40 * association of which with the user-specified arbitrary data string should
41 * directly display this arbitrary string. The suitable string template is
42 * therefore the identity template: "%1" (in the format for message strings).
43 * The last problem, that may constitute a limitation of this technique, is
44 * that this string template is tied to a given event ID. What if the user
45 * wants to use a different event ID? The solution is the event source to
46 * contain as many same identity templates as different IDs the user can use.
47 * This is quite a redundant and limiting technique!
48 *
49 * On MS Windows, the EventCreate.exe command contains the identity template
50 * for all IDs from 1 to 1001 included, yet it is only possible to specify
51 * an event ID from 1 to 1000 included.
52 * The Powershell command "Write-EventLog" allows using IDs from 0 to 65535
53 * included, thus covering all of the 2-byte unsigned integer space; its
54 * corresponding event source file "EventLogMessages.dll"
55 * (inside "%SystemRoot%\Microsoft.NET\Framework\vX.Y.ZZZZZ") therefore
56 * contains the identity template for all IDs from 0 to 65535, making it a
57 * large file.
58 *
59 * For ReactOS I want to have a compromise between disk space and usage
60 * flexibility, therefore I choose to include as well the identity template
61 * for all IDs from 0 to 65535 included, as done by Powershell. If somebody
62 * wants to change these limits, one has to perform the following steps:
63 *
64 * 0- Update the "/ID EventID" description in the help string "IDS_HELP"
65 * inside the lang/xx-YY.rc resource files;
66 *
67 * 1- Change in this file the two #defines EVENT_ID_MIN and EVENT_ID_MAX
68 * to other values of one's choice (called 'ID_min' and 'ID_max');
69 *
70 * 2- Regenerate and replace the event message string templates file using
71 * the event message string templates file generator (evtmsggen tool):
72 * $ evtmsggen ID_min ID_max evtmsgstr.mc
73 *
74 * 3- Recompile the EventCreate command.
75 *
76 */
77
78#include <stdio.h>
79#include <stdlib.h> // EXIT_SUCCESS, EXIT_FAILURE
80
81#include <windef.h>
82#include <winbase.h>
83#include <winreg.h>
84
85#include <conutils.h>
86
87#include <strsafe.h>
88
89#include "resource.h"
90
91/*
92 * The minimal and maximal values of the allowed ID range.
93 * See the "NOTE ABOUT THE IMPLEMENTATION" above.
94 *
95 * Here are some examples of values:
96 * Windows' EventCreate.exe command : ID_min = 1 and ID_max = 1000
97 * Powershell "Write-EventLog" command: ID_min = 0 and ID_max = 65535
98 *
99 * ReactOS' EventCreate.exe command uses the same limits as Powershell.
100 */
101#define EVENT_ID_MIN 0
102#define EVENT_ID_MAX 65535
103
104/*
105 * The EventCreate command internal name (used for both setting the default
106 * event source name and specifying the default event source file path).
107 */
108#define APPLICATION_NAME L"EventCreate"
109
110
112{
113 if (dwError == ERROR_SUCCESS)
114 return;
115
117 NULL, dwError, LANG_USER_DEFAULT);
118 ConPuts(StdErr, L"\n");
119}
120
121
122static BOOL
124 OUT PTOKEN_USER* ppUserToken)
125{
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
163Quit:
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}
176
177static LONG
179 IN HKEY hEventLogKey,
181{
182 LONG lRet;
183 HKEY hSourceKey = NULL;
184 DWORD dwDisposition = 0;
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
252Quit:
253 if (hSourceKey)
254 RegCloseKey(hSourceKey);
255
256 return lRet;
257}
258
259static BOOL
261 IN LPCWSTR UNCServerName OPTIONAL,
262 IN LPCWSTR EventLogName,
264 IN BOOL AllowAppSources OPTIONAL)
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
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,
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,
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 */
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 */
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
639Quit:
640 if (hEventLogKey)
641 RegCloseKey(hEventLogKey);
642
643 SetLastError(lRet);
644
645 return Success;
646}
647
648
649/************************** P A R S E R A P I **************************/
650
652{
655// TYPE_U8,
656// TYPE_U16,
658};
659
660#define OPTION_ALLOWED_LIST 0x01
661#define OPTION_NOT_EMPTY 0x02
662#define OPTION_TRIM_SPACE 0x04
663#define OPTION_EXCLUSIVE 0x08
664#define OPTION_MANDATORY 0x10
665
666typedef struct _OPTION
667{
668 /* Constant data */
669 PWSTR OptionName; // Option switch name
670 ULONG Type; // Type of data stored in the 'Value' member (UNUSED) (bool, string, int, ..., or function to call)
671 ULONG Flags; // Flags (preprocess the string or not, cache the string, stop processing...)
672 ULONG MaxOfInstances; // Maximum number of times this option can be seen in the command line (or 0: do not care)
673 // PWSTR OptionHelp; // Help string, or resource ID of the (localized) string (use the MAKEINTRESOURCE macro to create this value).
674 // PVOID Callback() ??
675 PWSTR AllowedValues; // Optional list of allowed values, given as a string of values separated by a pipe symbol '|'.
676
677 /* Parsing data */
678 PWSTR OptionStr; // Pointer to the original option string
679 ULONG Instances; // Number of times this option is seen in the command line
680 ULONG ValueSize; // Size of the buffer pointed by 'Value' ??
681 PVOID Value; // A pointer to part of the command line, or an allocated buffer
683
684#define NEW_OPT(Name, Type, Flags, MaxOfInstances, ValueSize, ValueBuffer) \
685 {(Name), (Type), (Flags), (MaxOfInstances), NULL, NULL, 0, (ValueSize), (ValueBuffer)}
686
687#define NEW_OPT_EX(Name, Type, Flags, AllowedValues, MaxOfInstances, ValueSize, ValueBuffer) \
688 {(Name), (Type), (Flags), (MaxOfInstances), (AllowedValues), NULL, 0, (ValueSize), (ValueBuffer)}
689
690static PWSTR
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}
709
710typedef enum _PARSER_ERROR
711{
722
724
725BOOL
727 IN INT argc,
728 IN WCHAR* argv[],
730 IN ULONG NumOptions,
731 IN PRINT_ERROR_FUNC PrintErrorFunc OPTIONAL)
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;
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}
990
991/******************************************************************************/
992
993
994static VOID
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 {
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}
1028
1029int wmain(int argc, WCHAR* argv[])
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 */
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 */
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
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}
static int argc
Definition: ServiceArgs.c:12
Type
Definition: Type.h:7
#define __cdecl
Definition: accygwin.h:79
#define VOID
Definition: acefi.h:82
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define IDS_HELP
Definition: resource.h:3
#define IDS_USAGE
Definition: resource.h:3
#define IDS_INVALIDSWITCH
Definition: resource.h:4
#define IDS_BADSYNTAX_1
Definition: resource.h:7
#define IDS_SOURCE_NOCREATE
Definition: resource.h:16
#define IDS_BADSYNTAX_6
Definition: resource.h:12
#define IDS_SUCCESS_2
Definition: resource.h:21
#define IDS_LOG_NOT_FOUND
Definition: resource.h:15
#define IDS_BADSYNTAX_2
Definition: resource.h:8
#define IDS_SUCCESS_3
Definition: resource.h:22
#define IDS_BADSYNTAX_3
Definition: resource.h:9
#define IDS_BADSYNTAX_0
Definition: resource.h:6
#define IDS_SOURCE_NOT_CUSTOM
Definition: resource.h:18
#define IDS_SOURCE_EXISTS
Definition: resource.h:17
#define IDS_BADSYNTAX_4
Definition: resource.h:10
#define IDS_BADSYNTAX_7
Definition: resource.h:13
#define IDS_SWITCH_UNIMPLEMENTED
Definition: resource.h:24
#define IDS_SUCCESS_1
Definition: resource.h:20
#define IDS_BADSYNTAX_5
Definition: resource.h:11
void ConPuts(FILE *fp, LPCWSTR psz)
Definition: fc.c:16
#define ConInitStdStreams()
Definition: fc.c:13
void ConPrintf(FILE *fp, LPCWSTR psz,...)
Definition: fc.c:20
#define StdOut
Definition: fc.c:14
void ConResPrintf(FILE *fp, UINT nID,...)
Definition: fc.c:33
#define StdErr
Definition: fc.c:15
void ConResPuts(FILE *fp, UINT nID)
Definition: fc.c:27
static FCRET Finalize(FILECOMPARE *pFC, struct list *ptr0, struct list *ptr1, BOOL fDifferent)
Definition: text.h:515
PEVENTSOURCE EventLogSource
Definition: eventlog.c:35
BOOL Error
Definition: chkdsk.c:66
#define RegCloseKey(hKey)
Definition: registry.h:49
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static const WCHAR szDescription[]
Definition: provider.c:55
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
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:1096
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
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:2504
LONG WINAPI RegFlushKey(HKEY hKey)
Definition: reg.c:2951
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:4882
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
HANDLE WINAPI OpenEventLogW(IN LPCWSTR lpUNCServerName, IN LPCWSTR lpSourceName)
Definition: eventlog.c:985
BOOL WINAPI CloseEventLog(IN HANDLE hEventLog)
Definition: eventlog.c:427
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 WINAPI DeregisterEventSource(IN HANDLE hEventLog)
Definition: eventlog.c:473
HANDLE WINAPI RegisterEventSourceW(IN LPCWSTR lpUNCServerName, IN LPCWSTR lpSourceName)
Definition: eventlog.c:1295
BOOL WINAPI GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength, PDWORD ReturnLength)
Definition: security.c:411
BOOL WINAPI OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle)
Definition: security.c:294
#define CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
#define SetLastError(x)
Definition: compat.h:752
#define HeapAlloc
Definition: compat.h:733
#define GetCurrentProcess()
Definition: compat.h:759
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
DWORD WINAPI GetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize)
Definition: loader.c:600
UINT WINAPI GetSystemWindowsDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2397
struct _OPTION * POPTION
TYPE
Definition: eventcreate.c:652
@ TYPE_Str
Definition: eventcreate.c:654
@ TYPE_U32
Definition: eventcreate.c:657
@ TYPE_None
Definition: eventcreate.c:653
#define OPTION_NOT_EMPTY
Definition: eventcreate.c:661
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 OPTION_EXCLUSIVE
Definition: eventcreate.c:663
VOID PrintError(DWORD dwError)
Definition: eventcreate.c:111
#define MAX_KEY_LENGTH
_PARSER_ERROR
Definition: eventcreate.c:711
@ TooManySameOption
Definition: eventcreate.c:719
@ InvalidOption
Definition: eventcreate.c:714
@ MandatoryOptionAbsent
Definition: eventcreate.c:720
@ InvalidValue
Definition: eventcreate.c:717
@ ValueNotAllowed
Definition: eventcreate.c:718
@ ValueRequired
Definition: eventcreate.c:715
@ InvalidSyntax
Definition: eventcreate.c:713
@ ValueIsEmpty
Definition: eventcreate.c:716
@ Success
Definition: eventcreate.c:712
#define OPTION_ALLOWED_LIST
Definition: eventcreate.c:660
static PWSTR TrimLeftRightWhitespace(IN PWSTR String)
Definition: eventcreate.c:691
#define OPTION_TRIM_SPACE
Definition: eventcreate.c:662
#define OPT_SYSTEM
static LONG InstallEventSource(IN HKEY hEventLogKey, IN LPCWSTR EventLogSource)
Definition: eventcreate.c:178
static BOOL GetUserToken(OUT PTOKEN_USER *ppUserToken)
Definition: eventcreate.c:123
enum _PARSER_ERROR PARSER_ERROR
static VOID __cdecl PrintParserError(PARSER_ERROR Error,...)
Definition: eventcreate.c:996
#define OPT_PASSWD
struct _OPTION OPTION
static BOOL CheckLogOrSourceExistence(IN LPCWSTR UNCServerName OPTIONAL, IN LPCWSTR EventLogName, IN LPCWSTR EventLogSource, IN BOOL AllowAppSources OPTIONAL)
Definition: eventcreate.c:260
#define EVENT_ID_MIN
Definition: eventcreate.c:101
#define EVENT_ID_MAX
Definition: eventcreate.c:102
#define NEW_OPT(Name, Type, Flags, MaxOfInstances, ValueSize, ValueBuffer)
Definition: eventcreate.c:684
#define APPLICATION_NAME
Definition: eventcreate.c:108
#define OPT_EVTID
#define NEW_OPT_EX(Name, Type, Flags, AllowedValues, MaxOfInstances, ValueSize, ValueBuffer)
Definition: eventcreate.c:687
VOID(__cdecl * PRINT_ERROR_FUNC)(IN PARSER_ERROR,...)
Definition: eventcreate.c:723
#define OPTION_MANDATORY
Definition: eventcreate.c:664
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define iswspace(_c)
Definition: ctype.h:669
_Check_return_ unsigned long __cdecl wcstoul(_In_z_ const wchar_t *_Str, _Out_opt_ _Deref_post_z_ wchar_t **_EndPtr, _In_ int _Radix)
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define EXIT_FAILURE
Definition: jerror.c:33
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
static HANDLE ULONG_PTR dwData
Definition: file.c:35
#define argv
Definition: mplay32.c:18
unsigned int UINT
Definition: ndis.h:50
#define KEY_READ
Definition: nt_native.h:1023
#define KEY_CREATE_SUB_KEY
Definition: nt_native.h:1018
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define REG_CREATED_NEW_KEY
Definition: nt_native.h:1084
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
#define KEY_SET_VALUE
Definition: nt_native.h:1017
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define L(x)
Definition: ntvdm.h:50
INT ConResPrintfV(IN PCON_STREAM Stream, IN UINT uID, IN va_list args)
Definition: outstream.c:695
INT ConMsgPuts(IN PCON_STREAM Stream, IN DWORD dwFlags, IN LPCVOID lpSource OPTIONAL, IN DWORD dwMessageId, IN DWORD dwLanguageId)
Definition: outstream.c:837
long LONG
Definition: pedump.c:60
int wmain()
#define EXIT_SUCCESS
Definition: rdjpgcom.c:55
#define REG_DWORD
Definition: sdbapi.c:596
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_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)
#define args
Definition: format.c:66
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
STRSAFEAPI StringCchCatW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:325
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
ULONG MaxOfInstances
Definition: eventcreate.c:672
ULONG Instances
Definition: eventcreate.c:679
ULONG ValueSize
Definition: eventcreate.c:680
PWSTR AllowedValues
Definition: eventcreate.c:675
ULONG Flags
Definition: eventcreate.c:671
PWSTR OptionName
Definition: eventcreate.c:669
PWSTR OptionStr
Definition: eventcreate.c:678
PVOID Value
Definition: eventcreate.c:681
ULONG Type
Definition: eventcreate.c:670
SID_AND_ATTRIBUTES User
Definition: setypes.h:1010
Definition: match.c:390
#define LANG_USER_DEFAULT
Definition: tnerror.cpp:50
uint16_t * PWSTR
Definition: typedefs.h:56
unsigned char * LPBYTE
Definition: typedefs.h:53
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IN
Definition: typedefs.h:39
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
_In_ PWDFDEVICE_INIT _In_ PWDF_REMOVE_LOCK_OPTIONS Options
Definition: wdfdevice.h:3534
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2433
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
#define wprintf(...)
Definition: whoami.c:18
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:423
#define EVENTLOG_ERROR_TYPE
Definition: winnt_old.h:2834
#define EVENTLOG_INFORMATION_TYPE
Definition: winnt_old.h:2836
#define EVENTLOG_SUCCESS
Definition: winnt_old.h:2833
#define EVENTLOG_WARNING_TYPE
Definition: winnt_old.h:2835
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define TOKEN_QUERY
Definition: setypes.h:928
@ TokenUser
Definition: setypes.h:966
__wchar_t WCHAR
Definition: xmlstorage.h:180
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185