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