de3439eb930076e6772b131f4b3fcac50834cfe5
[samba.git] / source3 / rpc_server / srv_eventlog_nt.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Marcin Krzysztof Porwit    2005,
5  *  Copyright (C) Brian Moran                2005,
6  *  Copyright (C) Gerald (Jerry) Carter      2005.
7  *  Copyright (C) Guenther Deschner          2009.
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 3 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
21  */
22
23 #include "includes.h"
24 #include "../librpc/gen_ndr/srv_eventlog.h"
25 #include "lib/eventlog/eventlog.h"
26 #include "registry.h"
27 #include "registry/reg_api_util.h"
28
29 #undef  DBGC_CLASS
30 #define DBGC_CLASS DBGC_RPC_SRV
31
32 typedef struct {
33         char *logname;
34         ELOG_TDB *etdb;
35         uint32 current_record;
36         uint32 num_records;
37         uint32 oldest_entry;
38         uint32 flags;
39         uint32 access_granted;
40 } EVENTLOG_INFO;
41
42 /********************************************************************
43  ********************************************************************/
44
45 static int eventlog_info_destructor(EVENTLOG_INFO *elog)
46 {
47         if (elog->etdb) {
48                 elog_close_tdb(elog->etdb, false);
49         }
50         return 0;
51 }
52
53 /********************************************************************
54  ********************************************************************/
55
56 static EVENTLOG_INFO *find_eventlog_info_by_hnd( struct pipes_struct * p,
57                                                 struct policy_handle * handle )
58 {
59         EVENTLOG_INFO *info;
60
61         if ( !find_policy_by_hnd( p, handle, (void **)(void *)&info ) ) {
62                 DEBUG( 2,
63                        ( "find_eventlog_info_by_hnd: eventlog not found.\n" ) );
64                 return NULL;
65         }
66
67         return info;
68 }
69
70 /********************************************************************
71 ********************************************************************/
72
73 static bool elog_check_access( EVENTLOG_INFO *info, const struct security_token *token )
74 {
75         char *tdbname = elog_tdbname(talloc_tos(), info->logname );
76         struct security_descriptor *sec_desc;
77         struct security_ace *ace;
78         NTSTATUS status;
79
80         if ( !tdbname )
81                 return False;
82
83         /* get the security descriptor for the file */
84
85         sec_desc = get_nt_acl_no_snum( info, tdbname );
86         TALLOC_FREE( tdbname );
87
88         if ( !sec_desc ) {
89                 DEBUG(5,("elog_check_access: Unable to get NT ACL for %s\n",
90                         tdbname));
91                 return False;
92         }
93
94         ace = talloc_zero(sec_desc, struct security_ace);
95         if (ace == NULL) {
96                 TALLOC_FREE(sec_desc);
97                 return false;
98         }
99
100         ace->type               = SEC_ACE_TYPE_ACCESS_ALLOWED;
101         ace->flags              = 0;
102         ace->access_mask        = REG_KEY_ALL;
103         ace->trustee            = global_sid_System;
104
105         status = security_descriptor_dacl_add(sec_desc, ace);
106         if (!NT_STATUS_IS_OK(status)) {
107                 TALLOC_FREE(sec_desc);
108                 return false;
109         }
110
111         /* root free pass */
112
113         if ( geteuid() == sec_initial_uid() ) {
114                 DEBUG(5,("elog_check_access: running as root, using system token\n"));
115                 token = get_system_token();
116         }
117
118         /* run the check, try for the max allowed */
119
120         status = se_access_check( sec_desc, token, MAXIMUM_ALLOWED_ACCESS,
121                 &info->access_granted);
122
123         TALLOC_FREE(sec_desc);
124
125         if (!NT_STATUS_IS_OK(status)) {
126                 DEBUG(8,("elog_check_access: se_access_check() return %s\n",
127                         nt_errstr(status)));
128                 return False;
129         }
130
131         /* we have to have READ permission for a successful open */
132
133         return ( info->access_granted & SEC_FILE_READ_DATA );
134 }
135
136 /********************************************************************
137  ********************************************************************/
138
139 static bool elog_validate_logname( const char *name )
140 {
141         int i;
142         const char **elogs = lp_eventlog_list();
143
144         if (!elogs) {
145                 return False;
146         }
147
148         for ( i=0; elogs[i]; i++ ) {
149                 if ( strequal( name, elogs[i] ) )
150                         return True;
151         }
152
153         return False;
154 }
155
156 /********************************************************************
157 ********************************************************************/
158
159 static bool get_num_records_hook( EVENTLOG_INFO * info )
160 {
161         int next_record;
162         int oldest_record;
163
164         if ( !info->etdb ) {
165                 DEBUG( 10, ( "No open tdb for %s\n", info->logname ) );
166                 return False;
167         }
168
169         /* lock the tdb since we have to get 2 records */
170
171         tdb_lock_bystring_with_timeout( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD, 1 );
172         next_record = tdb_fetch_int32( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD);
173         oldest_record = tdb_fetch_int32( ELOG_TDB_CTX(info->etdb), EVT_OLDEST_ENTRY);
174         tdb_unlock_bystring( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD);
175
176         DEBUG( 8,
177                ( "Oldest Record %d; Next Record %d\n", oldest_record,
178                  next_record ) );
179
180         info->num_records = ( next_record - oldest_record );
181         info->oldest_entry = oldest_record;
182
183         return True;
184 }
185
186 /********************************************************************
187  ********************************************************************/
188
189 static bool get_oldest_entry_hook( EVENTLOG_INFO * info )
190 {
191         /* it's the same thing */
192         return get_num_records_hook( info );
193 }
194
195 /********************************************************************
196  ********************************************************************/
197
198 static NTSTATUS elog_open( struct pipes_struct * p, const char *logname, struct policy_handle *hnd )
199 {
200         EVENTLOG_INFO *elog;
201
202         /* first thing is to validate the eventlog name */
203
204         if ( !elog_validate_logname( logname ) )
205                 return NT_STATUS_OBJECT_PATH_INVALID;
206
207         if ( !(elog = TALLOC_ZERO_P( NULL, EVENTLOG_INFO )) )
208                 return NT_STATUS_NO_MEMORY;
209         talloc_set_destructor(elog, eventlog_info_destructor);
210
211         elog->logname = talloc_strdup( elog, logname );
212
213         /* Open the tdb first (so that we can create any new tdbs if necessary).
214            We have to do this as root and then use an internal access check
215            on the file permissions since you can only have a tdb open once
216            in a single process */
217
218         become_root();
219         elog->etdb = elog_open_tdb( elog->logname, False, False );
220         unbecome_root();
221
222         if ( !elog->etdb ) {
223                 /* according to MSDN, if the logfile cannot be found, we should
224                   default to the "Application" log */
225
226                 if ( !strequal( logname, ELOG_APPL ) ) {
227
228                         TALLOC_FREE( elog->logname );
229
230                         elog->logname = talloc_strdup( elog, ELOG_APPL );
231
232                         /* do the access check */
233                         if ( !elog_check_access( elog, p->server_info->ptok ) ) {
234                                 TALLOC_FREE( elog );
235                                 return NT_STATUS_ACCESS_DENIED;
236                         }
237
238                         become_root();
239                         elog->etdb = elog_open_tdb( elog->logname, False, False );
240                         unbecome_root();
241                 }
242
243                 if ( !elog->etdb ) {
244                         TALLOC_FREE( elog );
245                         return NT_STATUS_ACCESS_DENIED; /* ??? */
246                 }
247         }
248
249         /* now do the access check.  Close the tdb if we fail here */
250
251         if ( !elog_check_access( elog, p->server_info->ptok ) ) {
252                 TALLOC_FREE( elog );
253                 return NT_STATUS_ACCESS_DENIED;
254         }
255
256         /* create the policy handle */
257
258         if ( !create_policy_hnd( p, hnd, elog ) ) {
259                 TALLOC_FREE(elog);
260                 return NT_STATUS_NO_MEMORY;
261         }
262
263         /* set the initial current_record pointer */
264
265         if ( !get_oldest_entry_hook( elog ) ) {
266                 DEBUG(3,("elog_open: Successfully opened eventlog but can't "
267                         "get any information on internal records!\n"));
268         }
269
270         elog->current_record = elog->oldest_entry;
271
272         return NT_STATUS_OK;
273 }
274
275 /********************************************************************
276  ********************************************************************/
277
278 static NTSTATUS elog_close( struct pipes_struct *p, struct policy_handle *hnd )
279 {
280         if ( !( close_policy_hnd( p, hnd ) ) ) {
281                 return NT_STATUS_INVALID_HANDLE;
282         }
283
284         return NT_STATUS_OK;
285 }
286
287 /*******************************************************************
288  *******************************************************************/
289
290 static int elog_size( EVENTLOG_INFO *info )
291 {
292         if ( !info || !info->etdb ) {
293                 DEBUG(0,("elog_size: Invalid info* structure!\n"));
294                 return 0;
295         }
296
297         return elog_tdb_size( ELOG_TDB_CTX(info->etdb), NULL, NULL );
298 }
299
300 /********************************************************************
301  note that this can only be called AFTER the table is constructed,
302  since it uses the table to find the tdb handle
303  ********************************************************************/
304
305 static bool sync_eventlog_params( EVENTLOG_INFO *info )
306 {
307         char *path = NULL;
308         uint32_t uiMaxSize = 0;
309         uint32_t uiRetention = 0;
310         struct registry_key *key;
311         struct registry_value *value;
312         WERROR wresult;
313         char *elogname = info->logname;
314         TALLOC_CTX *ctx = talloc_stackframe();
315         bool ret = false;
316
317         DEBUG( 4, ( "sync_eventlog_params with %s\n", elogname ) );
318
319         if ( !info->etdb ) {
320                 DEBUG( 4, ( "No open tdb! (%s)\n", info->logname ) );
321                 goto done;
322         }
323         /* set resonable defaults.  512Kb on size and 1 week on time */
324
325         uiMaxSize = 0x80000;
326         uiRetention = 604800;
327
328         /* the general idea is to internally open the registry
329            key and retrieve the values.  That way we can continue
330            to use the same fetch/store api that we use in
331            srv_reg_nt.c */
332
333         path = talloc_asprintf(ctx, "%s\\%s", KEY_EVENTLOG, elogname);
334         if (!path) {
335                 goto done;
336         }
337
338         wresult = reg_open_path(ctx, path, REG_KEY_READ, get_system_token(),
339                                 &key);
340
341         if ( !W_ERROR_IS_OK( wresult ) ) {
342                 DEBUG( 4,
343                        ( "sync_eventlog_params: Failed to open key [%s] (%s)\n",
344                          path, win_errstr( wresult ) ) );
345                 goto done;
346         }
347
348         wresult = reg_queryvalue(key, key, "Retention", &value);
349         if (!W_ERROR_IS_OK(wresult)) {
350                 DEBUG(4, ("Failed to query value \"Retention\": %s\n",
351                           win_errstr(wresult)));
352                 goto done;
353         }
354
355         if (value->data.length >= 4) {
356                 uiRetention = IVAL(value->data.data, 0);
357         }
358
359         wresult = reg_queryvalue(key, key, "MaxSize", &value);
360         if (!W_ERROR_IS_OK(wresult)) {
361                 DEBUG(4, ("Failed to query value \"MaxSize\": %s\n",
362                           win_errstr(wresult)));
363                 goto done;
364         }
365         if (value->data.length >= 4) {
366                 uiMaxSize = IVAL(value->data.data, 0);
367         }
368
369         tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_MAXSIZE, uiMaxSize );
370         tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_RETENTION, uiRetention );
371
372         ret = true;
373
374 done:
375         TALLOC_FREE(ctx);
376         return ret;
377 }
378
379 /********************************************************************
380  _eventlog_OpenEventLogW
381  ********************************************************************/
382
383 NTSTATUS _eventlog_OpenEventLogW(struct pipes_struct *p,
384                                  struct eventlog_OpenEventLogW *r)
385 {
386         EVENTLOG_INFO *info;
387         NTSTATUS result;
388
389         DEBUG( 10,("_eventlog_OpenEventLogW: Server [%s], Log [%s]\n",
390                 r->in.servername->string, r->in.logname->string ));
391
392         /* according to MSDN, if the logfile cannot be found, we should
393           default to the "Application" log */
394
395         if ( !NT_STATUS_IS_OK( result = elog_open( p, r->in.logname->string, r->out.handle )) )
396                 return result;
397
398         if ( !(info = find_eventlog_info_by_hnd( p, r->out.handle )) ) {
399                 DEBUG(0,("_eventlog_OpenEventLogW: eventlog (%s) opened but unable to find handle!\n",
400                         r->in.logname->string ));
401                 elog_close( p, r->out.handle );
402                 return NT_STATUS_INVALID_HANDLE;
403         }
404
405         DEBUG(10,("_eventlog_OpenEventLogW: Size [%d]\n", elog_size( info )));
406
407         if (!sync_eventlog_params(info)) {
408                 elog_close(p, r->out.handle);
409                 return NT_STATUS_EVENTLOG_FILE_CORRUPT;
410         }
411         prune_eventlog( ELOG_TDB_CTX(info->etdb) );
412
413         return NT_STATUS_OK;
414 }
415
416 /********************************************************************
417  _eventlog_ClearEventLogW
418  This call still needs some work
419  ********************************************************************/
420 /** The windows client seems to be doing something funny with the file name
421    A call like
422       ClearEventLog(handle, "backup_file")
423    on the client side will result in the backup file name looking like this on the
424    server side:
425       \??\${CWD of client}\backup_file
426    If an absolute path gets specified, such as
427       ClearEventLog(handle, "C:\\temp\\backup_file")
428    then it is still mangled by the client into this:
429       \??\C:\temp\backup_file
430    when it is on the wire.
431    I'm not sure where the \?? is coming from, or why the ${CWD} of the client process
432    would be added in given that the backup file gets written on the server side. */
433
434 NTSTATUS _eventlog_ClearEventLogW(struct pipes_struct *p,
435                                   struct eventlog_ClearEventLogW *r)
436 {
437         EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
438
439         if ( !info )
440                 return NT_STATUS_INVALID_HANDLE;
441
442         if (r->in.backupfile && r->in.backupfile->string) {
443
444                 DEBUG(8,( "_eventlog_ClearEventLogW: Using [%s] as the backup "
445                         "file name for log [%s].",
446                          r->in.backupfile->string, info->logname ) );
447         }
448
449         /* check for WRITE access to the file */
450
451         if ( !(info->access_granted & SEC_FILE_WRITE_DATA) )
452                 return NT_STATUS_ACCESS_DENIED;
453
454         /* Force a close and reopen */
455
456         elog_close_tdb( info->etdb, True );
457         become_root();
458         info->etdb = elog_open_tdb( info->logname, True, False );
459         unbecome_root();
460
461         if ( !info->etdb )
462                 return NT_STATUS_ACCESS_DENIED;
463
464         return NT_STATUS_OK;
465 }
466
467 /********************************************************************
468  _eventlog_CloseEventLog
469  ********************************************************************/
470
471 NTSTATUS _eventlog_CloseEventLog(struct pipes_struct * p,
472                                  struct eventlog_CloseEventLog *r)
473 {
474         NTSTATUS status;
475
476         status = elog_close( p, r->in.handle );
477         if (!NT_STATUS_IS_OK(status)) {
478                 return status;
479         }
480
481         ZERO_STRUCTP(r->out.handle);
482
483         return NT_STATUS_OK;
484 }
485
486 /********************************************************************
487  _eventlog_ReadEventLogW
488  ********************************************************************/
489
490 NTSTATUS _eventlog_ReadEventLogW(struct pipes_struct *p,
491                                  struct eventlog_ReadEventLogW *r)
492 {
493         EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
494         uint32_t num_records_read = 0;
495         int bytes_left, record_number;
496         uint32_t elog_read_type, elog_read_dir;
497
498         if (!info) {
499                 return NT_STATUS_INVALID_HANDLE;
500         }
501
502         info->flags     = r->in.flags;
503         bytes_left      = r->in.number_of_bytes;
504
505         if (!info->etdb) {
506                 return NT_STATUS_ACCESS_DENIED;
507         }
508
509         /* check for valid flags.  Can't use the sequential and seek flags together */
510
511         elog_read_type = r->in.flags & (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ);
512         elog_read_dir  = r->in.flags & (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ);
513
514         if (r->in.flags == 0 ||
515             elog_read_type == (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ) ||
516             elog_read_dir == (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ))
517         {
518                 DEBUG(3,("_eventlog_ReadEventLogW: "
519                         "Invalid flags [0x%08x] for ReadEventLog\n",
520                         r->in.flags));
521                 return NT_STATUS_INVALID_PARAMETER;
522         }
523
524         /* a sequential read should ignore the offset */
525
526         if (elog_read_type & EVENTLOG_SEQUENTIAL_READ) {
527                 record_number = info->current_record;
528         } else {
529                 record_number = r->in.offset;
530         }
531
532         if (r->in.number_of_bytes == 0) {
533                 struct EVENTLOGRECORD *e;
534                 e = evlog_pull_record(p->mem_ctx, ELOG_TDB_CTX(info->etdb),
535                                       record_number);
536                 if (!e) {
537                         return NT_STATUS_END_OF_FILE;
538                 }
539                 *r->out.real_size = e->Length;
540                 return NT_STATUS_BUFFER_TOO_SMALL;
541         }
542
543         while (bytes_left > 0) {
544
545                 DATA_BLOB blob;
546                 enum ndr_err_code ndr_err;
547                 struct EVENTLOGRECORD *e;
548
549                 e = evlog_pull_record(p->mem_ctx, ELOG_TDB_CTX(info->etdb),
550                                       record_number);
551                 if (!e) {
552                         break;
553                 }
554
555                 ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, e,
556                               (ndr_push_flags_fn_t)ndr_push_EVENTLOGRECORD);
557                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
558                         return ndr_map_error2ntstatus(ndr_err);
559                 }
560
561                 if (DEBUGLEVEL >= 10) {
562                         NDR_PRINT_DEBUG(EVENTLOGRECORD, e);
563                 }
564
565                 if (blob.length > r->in.number_of_bytes) {
566                         *r->out.real_size = blob.length;
567                         return NT_STATUS_BUFFER_TOO_SMALL;
568                 }
569
570                 if (*r->out.sent_size + blob.length > r->in.number_of_bytes) {
571                         break;
572                 }
573
574                 bytes_left -= blob.length;
575
576                 if (info->flags & EVENTLOG_FORWARDS_READ) {
577                         record_number++;
578                 } else {
579                         record_number--;
580                 }
581
582                 /* update the eventlog record pointer */
583
584                 info->current_record = record_number;
585
586                 memcpy(&r->out.data[*(r->out.sent_size)],
587                        blob.data, blob.length);
588                 *(r->out.sent_size) += blob.length;
589
590                 num_records_read++;
591         }
592
593         if (r->in.offset == 0 && record_number == 0 && *r->out.sent_size == 0) {
594                 return NT_STATUS_END_OF_FILE;
595         }
596
597         return NT_STATUS_OK;
598 }
599
600 /********************************************************************
601  _eventlog_GetOldestRecord
602  ********************************************************************/
603
604 NTSTATUS _eventlog_GetOldestRecord(struct pipes_struct *p,
605                                    struct eventlog_GetOldestRecord *r)
606 {
607         EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
608
609         if (info == NULL) {
610                 return NT_STATUS_INVALID_HANDLE;
611         }
612
613         if ( !( get_oldest_entry_hook( info ) ) )
614                 return NT_STATUS_ACCESS_DENIED;
615
616         *r->out.oldest_entry = info->oldest_entry;
617
618         return NT_STATUS_OK;
619 }
620
621 /********************************************************************
622 _eventlog_GetNumRecords
623  ********************************************************************/
624
625 NTSTATUS _eventlog_GetNumRecords(struct pipes_struct *p,
626                                  struct eventlog_GetNumRecords *r)
627 {
628         EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
629
630         if (info == NULL) {
631                 return NT_STATUS_INVALID_HANDLE;
632         }
633
634         if ( !( get_num_records_hook( info ) ) )
635                 return NT_STATUS_ACCESS_DENIED;
636
637         *r->out.number = info->num_records;
638
639         return NT_STATUS_OK;
640 }
641
642 NTSTATUS _eventlog_BackupEventLogW(struct pipes_struct *p, struct eventlog_BackupEventLogW *r)
643 {
644         p->rng_fault_state = True;
645         return NT_STATUS_NOT_IMPLEMENTED;
646 }
647
648 /********************************************************************
649 _eventlog_GetLogInformation
650  ********************************************************************/
651
652 NTSTATUS _eventlog_GetLogInformation(struct pipes_struct *p,
653                                      struct eventlog_GetLogInformation *r)
654 {
655         EVENTLOG_INFO *info = find_eventlog_info_by_hnd(p, r->in.handle);
656         struct EVENTLOG_FULL_INFORMATION f;
657         enum ndr_err_code ndr_err;
658         DATA_BLOB blob;
659
660         if (!info) {
661                 return NT_STATUS_INVALID_HANDLE;
662         }
663
664         if (r->in.level != 0) {
665                 return NT_STATUS_INVALID_LEVEL;
666         }
667
668         *r->out.bytes_needed = 4;
669
670         if (r->in.buf_size < 4) {
671                 return NT_STATUS_BUFFER_TOO_SMALL;
672         }
673
674         /* FIXME: this should be retrieved from the handle */
675         f.full = false;
676
677         ndr_err = ndr_push_struct_blob(&blob, p->mem_ctx, &f,
678                       (ndr_push_flags_fn_t)ndr_push_EVENTLOG_FULL_INFORMATION);
679         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
680                 return ndr_map_error2ntstatus(ndr_err);
681         }
682
683         if (DEBUGLEVEL >= 10) {
684                 NDR_PRINT_DEBUG(EVENTLOG_FULL_INFORMATION, &f);
685         }
686
687         memcpy(r->out.buffer, blob.data, 4);
688
689         return NT_STATUS_OK;
690 }
691
692 /********************************************************************
693 _eventlog_FlushEventLog
694  ********************************************************************/
695
696 NTSTATUS _eventlog_FlushEventLog(struct pipes_struct *p,
697                                  struct eventlog_FlushEventLog *r)
698 {
699         EVENTLOG_INFO *info = find_eventlog_info_by_hnd(p, r->in.handle);
700         if (!info) {
701                 return NT_STATUS_INVALID_HANDLE;
702         }
703
704         return NT_STATUS_ACCESS_DENIED;
705 }
706
707 /********************************************************************
708  ********************************************************************/
709
710 static NTSTATUS evlog_report_to_record(TALLOC_CTX *mem_ctx,
711                                        const struct eventlog_ReportEventW *r,
712                                        const char *logname,
713                                        struct EVENTLOGRECORD *e)
714 {
715         uint32_t i;
716         ZERO_STRUCTP(e);
717
718         e->TimeGenerated        = r->in.timestamp;
719         e->TimeWritten          = time(NULL);
720         e->EventID              = r->in.event_id;
721         e->EventType            = r->in.event_type;
722         e->NumStrings           = r->in.num_of_strings;
723         e->EventCategory        = r->in.event_category;
724         e->ReservedFlags        = r->in.flags;
725         e->DataLength           = r->in.data_size;
726         e->SourceName           = talloc_strdup(mem_ctx, logname);
727         NT_STATUS_HAVE_NO_MEMORY(e->SourceName);
728         if (r->in.servername->string) {
729                 e->Computername = r->in.servername->string;
730         } else {
731                 e->Computername = talloc_strdup(mem_ctx, "");
732                 NT_STATUS_HAVE_NO_MEMORY(e->Computername);
733         }
734         if (r->in.user_sid) {
735                 e->UserSid      = *r->in.user_sid;
736         }
737         e->Strings              = talloc_array(mem_ctx, const char *, e->NumStrings);
738         NT_STATUS_HAVE_NO_MEMORY(e->Strings);
739
740         for (i=0; i < e->NumStrings; i++) {
741                 e->Strings[i] = talloc_strdup(e->Strings,
742                                               r->in.strings[i]->string);
743                 NT_STATUS_HAVE_NO_MEMORY(e->Strings[i]);
744         }
745         e->Data                 = r->in.data;
746
747         return NT_STATUS_OK;
748 }
749
750 /********************************************************************
751 _eventlog_ReportEventW
752  ********************************************************************/
753
754 NTSTATUS _eventlog_ReportEventW(struct pipes_struct *p,
755                                 struct eventlog_ReportEventW *r)
756 {
757         NTSTATUS status;
758         struct EVENTLOGRECORD record;
759
760         EVENTLOG_INFO *info = find_eventlog_info_by_hnd(p, r->in.handle);
761         if (!info) {
762                 return NT_STATUS_INVALID_HANDLE;
763         }
764
765         status = evlog_report_to_record(p->mem_ctx, r, info->logname, &record);
766         if (!NT_STATUS_IS_OK(status)) {
767                 return status;
768         }
769
770         status = evlog_push_record(p->mem_ctx,
771                                    ELOG_TDB_CTX(info->etdb),
772                                    &record,
773                                    r->out.record_number);
774         if (!NT_STATUS_IS_OK(status)) {
775                 return status;
776         }
777
778         return NT_STATUS_OK;
779 }
780
781 /********************************************************************
782  ********************************************************************/
783
784 NTSTATUS _eventlog_DeregisterEventSource(struct pipes_struct *p,
785                                          struct eventlog_DeregisterEventSource *r)
786 {
787         p->rng_fault_state = True;
788         return NT_STATUS_NOT_IMPLEMENTED;
789 }
790
791 NTSTATUS _eventlog_ChangeNotify(struct pipes_struct *p,
792                                 struct eventlog_ChangeNotify *r)
793 {
794         p->rng_fault_state = True;
795         return NT_STATUS_NOT_IMPLEMENTED;
796 }
797
798 NTSTATUS _eventlog_RegisterEventSourceW(struct pipes_struct *p,
799                                         struct eventlog_RegisterEventSourceW *r)
800 {
801         p->rng_fault_state = True;
802         return NT_STATUS_NOT_IMPLEMENTED;
803 }
804
805 NTSTATUS _eventlog_OpenBackupEventLogW(struct pipes_struct *p,
806                                        struct eventlog_OpenBackupEventLogW *r)
807 {
808         p->rng_fault_state = True;
809         return NT_STATUS_NOT_IMPLEMENTED;
810 }
811
812 NTSTATUS _eventlog_ClearEventLogA(struct pipes_struct *p,
813                                   struct eventlog_ClearEventLogA *r)
814 {
815         p->rng_fault_state = True;
816         return NT_STATUS_NOT_IMPLEMENTED;
817 }
818
819 NTSTATUS _eventlog_BackupEventLogA(struct pipes_struct *p,
820                                    struct eventlog_BackupEventLogA *r)
821 {
822         p->rng_fault_state = True;
823         return NT_STATUS_NOT_IMPLEMENTED;
824 }
825
826 NTSTATUS _eventlog_OpenEventLogA(struct pipes_struct *p,
827                                  struct eventlog_OpenEventLogA *r)
828 {
829         p->rng_fault_state = True;
830         return NT_STATUS_NOT_IMPLEMENTED;
831 }
832
833 NTSTATUS _eventlog_RegisterEventSourceA(struct pipes_struct *p,
834                                         struct eventlog_RegisterEventSourceA *r)
835 {
836         p->rng_fault_state = True;
837         return NT_STATUS_NOT_IMPLEMENTED;
838 }
839
840 NTSTATUS _eventlog_OpenBackupEventLogA(struct pipes_struct *p,
841                                        struct eventlog_OpenBackupEventLogA *r)
842 {
843         p->rng_fault_state = True;
844         return NT_STATUS_NOT_IMPLEMENTED;
845 }
846
847 NTSTATUS _eventlog_ReadEventLogA(struct pipes_struct *p,
848                                  struct eventlog_ReadEventLogA *r)
849 {
850         p->rng_fault_state = True;
851         return NT_STATUS_NOT_IMPLEMENTED;
852 }
853
854 NTSTATUS _eventlog_ReportEventA(struct pipes_struct *p,
855                                 struct eventlog_ReportEventA *r)
856 {
857         p->rng_fault_state = True;
858         return NT_STATUS_NOT_IMPLEMENTED;
859 }
860
861 NTSTATUS _eventlog_RegisterClusterSvc(struct pipes_struct *p,
862                                       struct eventlog_RegisterClusterSvc *r)
863 {
864         p->rng_fault_state = True;
865         return NT_STATUS_NOT_IMPLEMENTED;
866 }
867
868 NTSTATUS _eventlog_DeregisterClusterSvc(struct pipes_struct *p,
869                                         struct eventlog_DeregisterClusterSvc *r)
870 {
871         p->rng_fault_state = True;
872         return NT_STATUS_NOT_IMPLEMENTED;
873 }
874
875 NTSTATUS _eventlog_WriteClusterEvents(struct pipes_struct *p,
876                                       struct eventlog_WriteClusterEvents *r)
877 {
878         p->rng_fault_state = True;
879         return NT_STATUS_NOT_IMPLEMENTED;
880 }
881
882 NTSTATUS _eventlog_ReportEventAndSourceW(struct pipes_struct *p,
883                                          struct eventlog_ReportEventAndSourceW *r)
884 {
885         p->rng_fault_state = True;
886         return NT_STATUS_NOT_IMPLEMENTED;
887 }