r10819: merging a couple of fixes from trunk
[ira/wip.git] / source / 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  *  
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *  
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *  
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #include "includes.h"
24
25 #undef  DBGC_CLASS
26 #define DBGC_CLASS DBGC_RPC_SRV
27
28
29 typedef struct {
30         pstring logname;        /* rather than alloc on the fly what we need... (memory is cheap now) */
31         pstring tdbfname;
32         TDB_CONTEXT *log_tdb;   /* the pointer to the TDB_CONTEXT */
33 } EventlogTDBInfo;
34
35 static int nlogs;
36 static EventlogTDBInfo *ttdb = NULL;
37 static TALLOC_CTX *mem_ctx = NULL;
38
39 typedef struct {
40         char *logname;
41         char *servername;
42         uint32 num_records;
43         uint32 oldest_entry;
44         uint32 flags;
45 } EventlogInfo;
46
47
48
49 #if 0 /* UNUSED */
50 /********************************************************************
51  ********************************************************************/
52  
53 void test_eventlog_tdb( TDB_CONTEXT * the_tdb )
54 {
55         Eventlog_entry ee;
56
57         int i = 0;
58
59         memset( &ee, 0, sizeof( Eventlog_entry ) );
60
61         if ( !the_tdb )
62                 return;
63
64         for ( i = 0; i < 100; i++ ) {
65                 ee.record.length = sizeof( ee.record );
66                 memset( &ee.data_record, 0, sizeof( ee.data_record ) );
67                 ee.record.reserved1 = 0xBEEFDEAD;
68                 ee.record.record_number = 1000 - i;     /* should get substituted */
69                 ee.record.time_generated = 0;
70                 ee.record.time_written = 0;
71                 ee.record.event_id = 500;
72                 ee.record.event_type = 300;
73                 ee.record.num_strings = 0;
74                 ee.record.event_category = 0;
75                 ee.record.reserved2 = ( i << 8 ) | i;
76                 ee.record.closing_record_number = -1;
77                 ee.record.string_offset = 0;
78                 ee.record.user_sid_length = 0;
79                 ee.record.user_sid_offset = 0;
80                 ee.record.data_length = 0;
81                 ee.record.data_offset = 0;
82
83                 rpcstr_push( ( void * ) ( ee.data_record.source_name ),
84                              "SystemLog",
85                              sizeof( ee.data_record.source_name ),
86                              STR_TERMINATE );
87                 ee.data_record.source_name_len =
88                         ( strlen_w( ee.data_record.source_name ) * 2 ) + 2;
89
90                 rpcstr_push( ( void * ) ( ee.data_record.computer_name ),
91                              "DMLINUX",
92                              sizeof( ee.data_record.computer_name ),
93                              STR_TERMINATE );
94
95                 ee.data_record.computer_name_len =
96                         ( strlen_w( ee.data_record.computer_name ) * 2 ) + 2;
97
98                 write_eventlog_tdb( the_tdb, &ee );
99         }
100 }
101 #endif /* UNUSED */
102
103 /********************************************************************
104  ********************************************************************/
105
106 static void refresh_eventlog_tdb_table( void )
107 {
108         const char **elogs = lp_eventlog_list(  );
109         int i, j;
110
111         if ( !elogs )
112                 return;
113
114         if ( !mem_ctx ) {
115                 mem_ctx = talloc_init( "refresh_eventlog_tdb_table" );
116         }
117
118         if ( !mem_ctx ) {
119                 DEBUG( 1, ( "Can't allocate memory\n" ) );
120                 return;
121         }
122
123         /* count them */
124         for ( i = 0; elogs[i]; i++ ) {
125         }
126         /* number of logs in i */
127         DEBUG( 10, ( "Number of eventlogs %d\n", i ) );
128         /* check to see if we need to adjust our tables */
129
130         if ( ( ttdb != NULL ) ) {
131                 if ( i != nlogs ) {
132                         /* refresh the table, by closing and reconstructing */
133                         DEBUG( 10, ( "Closing existing table \n" ) );
134                         for ( j = 0; j < nlogs; j++ ) {
135                                 tdb_close( ttdb[j].log_tdb );
136                         }
137                         TALLOC_FREE( ttdb );
138                         ttdb = NULL;
139                 } else {        /* i == nlogs */
140
141                         for ( j = 0; j < nlogs; j++ ) {
142                                 if ( StrCaseCmp( ttdb[j].logname, elogs[i] ) ) {
143                                         /* something changed, have to discard */
144                                         DEBUG( 10,
145                                                ( "Closing existing table \n" ) );
146                                         for ( j = 0; j < nlogs; j++ ) {
147                                                 tdb_close( ttdb[j].log_tdb );
148                                         }
149                                         TALLOC_FREE( ttdb );
150                                         ttdb = NULL;
151                                         break;
152                                 }
153                         }
154                 }
155         }
156
157         /* note that this might happen because of above */
158         if ( ( i > 0 ) && ( ttdb == NULL ) ) {
159                 /* alloc the room */
160                 DEBUG( 10, ( "Creating the table\n" ) );
161                 ttdb = TALLOC( mem_ctx, sizeof( EventlogTDBInfo ) * i );
162                 if ( !ttdb ) {
163                         DEBUG( 10,
164                                ( "Can't allocate table for tdb handles \n" ) );
165                         return;
166                 }
167                 for ( j = 0; j < i; j++ ) {
168                         pstrcpy( ttdb[j].tdbfname,
169                                  lock_path( mk_tdbfilename
170                                             ( ttdb[j].tdbfname,
171                                               ( char * ) elogs[j],
172                                               sizeof( pstring ) ) ) );
173                         pstrcpy( ttdb[j].logname, elogs[j] );
174                         DEBUG( 10, ( "Opening tdb for %s\n", elogs[j] ) );
175                         ttdb[j].log_tdb =
176                                 open_eventlog_tdb( ttdb[j].tdbfname );
177                 }
178         }
179         nlogs = i;
180 }
181
182 /********************************************************************
183  ********************************************************************/
184
185 TDB_CONTEXT *tdb_of( char *eventlog_name )
186 {
187         int i;
188
189         if ( !eventlog_name )
190                 return NULL;
191
192         if ( !ttdb ) {
193                 DEBUG( 10, ( "Refreshing list of eventlogs\n" ) );
194                 refresh_eventlog_tdb_table(  );
195
196                 if ( !ttdb ) {
197                         DEBUG( 10,
198                                ( "eventlog tdb table is NULL after a refresh!\n" ) );
199                         return NULL;
200                 }
201         }
202
203         DEBUG( 10, ( "Number of eventlogs %d\n", nlogs ) );
204
205         for ( i = 0; i < nlogs; i++ ) {
206                 if ( strequal( eventlog_name, ttdb[i].logname ) ) 
207                         return ttdb[i].log_tdb;
208         }
209
210         return NULL;
211 }
212
213
214 /********************************************************************
215   For the given tdb, get the next eventlog record into the passed 
216   Eventlog_entry.  returns NULL if it can't get the record for some reason.
217  ********************************************************************/
218
219 Eventlog_entry *get_eventlog_record( prs_struct * ps, TDB_CONTEXT * tdb,
220                                      int recno, Eventlog_entry * ee )
221 {
222         TDB_DATA ret, key;
223
224         int srecno;
225         int reclen;
226         int len;
227         uint8 *rbuff;
228
229         pstring *wpsource, *wpcomputer, *wpsid, *wpstrs, *puserdata;
230
231         key.dsize = sizeof( int32 );
232         rbuff = NULL;
233
234         srecno = recno;
235         key.dptr = ( char * ) &srecno;
236
237         ret = tdb_fetch( tdb, key );
238
239         if ( ret.dsize == 0 ) {
240                 DEBUG( 8,
241                        ( "Can't find a record for the key, record %d\n",
242                          recno ) );
243                 return NULL;
244         }
245
246         len = tdb_unpack( ret.dptr, ret.dsize, "d", &reclen );
247
248         DEBUG( 10, ( "Unpacking record %d, size is %d\n", srecno, len ) );
249
250         if ( !len )
251                 return NULL;
252
253         /* ee = PRS_ALLOC_MEM(ps, Eventlog_entry, 1); */
254
255         if ( !ee )
256                 return NULL;
257
258         len = tdb_unpack( ret.dptr, ret.dsize, "ddddddwwwwddddddBBdBBBd",
259                           &ee->record.length, &ee->record.reserved1,
260                           &ee->record.record_number,
261                           &ee->record.time_generated,
262                           &ee->record.time_written, &ee->record.event_id,
263                           &ee->record.event_type, &ee->record.num_strings,
264                           &ee->record.event_category, &ee->record.reserved2,
265                           &ee->record.closing_record_number,
266                           &ee->record.string_offset,
267                           &ee->record.user_sid_length,
268                           &ee->record.user_sid_offset,
269                           &ee->record.data_length, &ee->record.data_offset,
270                           &ee->data_record.source_name_len, &wpsource,
271                           &ee->data_record.computer_name_len, &wpcomputer,
272                           &ee->data_record.sid_padding,
273                           &ee->record.user_sid_length, &wpsid,
274                           &ee->data_record.strings_len, &wpstrs,
275                           &ee->data_record.user_data_len, &puserdata,
276                           &ee->data_record.data_padding );
277         DEBUG( 10,
278                ( "Read record %d, len in tdb was %d\n",
279                  ee->record.record_number, len ) );
280
281         /* have to do the following because the tdb_unpack allocs a buff, stuffs a pointer to the buff
282            into it's 2nd argment for 'B' */
283
284         if ( wpcomputer )
285                 memcpy( ee->data_record.computer_name, wpcomputer,
286                         ee->data_record.computer_name_len );
287         if ( wpsource )
288                 memcpy( ee->data_record.source_name, wpsource,
289                         ee->data_record.source_name_len );
290
291         if ( wpsid )
292                 memcpy( ee->data_record.sid, wpsid,
293                         ee->record.user_sid_length );
294         if ( wpstrs )
295                 memcpy( ee->data_record.strings, wpstrs,
296                         ee->data_record.strings_len );
297
298         /* note that userdata is a pstring */
299         if ( puserdata )
300                 memcpy( ee->data_record.user_data, puserdata,
301                         ee->data_record.user_data_len );
302
303         SAFE_FREE( wpcomputer );
304         SAFE_FREE( wpsource );
305         SAFE_FREE( wpsid );
306         SAFE_FREE( wpstrs );
307         SAFE_FREE( puserdata );
308
309         DEBUG( 10, ( "get_eventlog_record: read back %d\n", len ) );
310         DEBUG( 10,
311                ( "get_eventlog_record: computer_name %d is ",
312                  ee->data_record.computer_name_len ) );
313         SAFE_FREE( ret.dptr );
314         return ee;
315 }
316
317 /********************************************************************
318  ********************************************************************/
319
320 static void free_eventlog_info( void *ptr )
321 {
322         TALLOC_FREE( ptr );
323 }
324
325 /********************************************************************
326  ********************************************************************/
327
328 static EventlogInfo *find_eventlog_info_by_hnd( pipes_struct * p,
329                                                 POLICY_HND * handle )
330 {
331         EventlogInfo *info;
332
333         if ( !find_policy_by_hnd( p, handle, ( void ** ) &info ) ) {
334                 DEBUG( 2,
335                        ( "find_eventlog_info_by_hnd: eventlog not found.\n" ) );
336                 return NULL;
337         }
338
339         return info;
340 }
341
342 /********************************************************************
343  note that this can only be called AFTER the table is constructed, 
344  since it uses the table to find the tdb handle
345  ********************************************************************/
346
347 static BOOL sync_eventlog_params( const char *elogname )
348 {
349         pstring path;
350         uint32 uiMaxSize;
351         uint32 uiRetention;
352         REGISTRY_KEY *keyinfo;
353         REGISTRY_VALUE *val;
354         REGVAL_CTR *values;
355         WERROR wresult;
356         TDB_CONTEXT *the_tdb;
357
358         the_tdb = tdb_of( ( char * ) elogname );
359
360         DEBUG( 4, ( "sync_eventlog_params with %s\n", elogname ) );
361
362         if ( !the_tdb ) {
363                 DEBUG( 4, ( "Can't open tdb for %s\n", elogname ) );
364                 return False;
365         }
366         /* set resonable defaults.  512Kb on size and 1 week on time */
367
368         uiMaxSize = 0x80000;
369         uiRetention = 604800;
370
371         /* the general idea is to internally open the registry 
372            key and retreive the values.  That way we can continue 
373            to use the same fetch/store api that we use in 
374            srv_reg_nt.c */
375
376         pstr_sprintf( path, "%s/%s", KEY_EVENTLOG, elogname );
377
378         wresult =
379                 regkey_open_internal( &keyinfo, path, get_root_nt_token(  ),
380                                       REG_KEY_READ );
381
382         if ( !W_ERROR_IS_OK( wresult ) ) {
383                 DEBUG( 4,
384                        ( "sync_eventlog_params: Failed to open key [%s] (%s)\n",
385                          path, dos_errstr( wresult ) ) );
386                 return False;
387         }
388
389         if ( !( values = TALLOC_ZERO_P( keyinfo, REGVAL_CTR ) ) ) {
390                 TALLOC_FREE( keyinfo );
391                 DEBUG( 0, ( "control_eventlog_hook: talloc() failed!\n" ) );
392
393                 return False;
394         }
395         fetch_reg_values( keyinfo, values );
396
397         if ( ( val = regval_ctr_getvalue( values, "Retention" ) ) != NULL )
398                 uiRetention = IVAL( regval_data_p( val ), 0 );
399
400         if ( ( val = regval_ctr_getvalue( values, "MaxSize" ) ) != NULL )
401                 uiMaxSize = IVAL( regval_data_p( val ), 0 );
402
403         regkey_close_internal( keyinfo );
404
405         tdb_store_int32( the_tdb, VN_maxsize, uiMaxSize );
406         tdb_store_int32( the_tdb, VN_retention, uiRetention );
407
408         return True;
409 }
410
411 /********************************************************************
412  ********************************************************************/
413
414 static BOOL open_eventlog_hook( EventlogInfo * info )
415 {
416         return True;
417 }
418
419 /********************************************************************
420 ********************************************************************/
421
422 /**
423  * Callout to get the number of records in the specified event log
424  * 
425  *   smbrun calling convention --
426  *     INPUT: <get_num_records_cmd> <log name> <policy handle>
427  *     OUTPUT: A single line with a single integer containing the number of
428  *             entries in the log. If there are no entries in the log, return 0.
429  */
430
431
432 static BOOL get_num_records_hook( EventlogInfo * info )
433 {
434
435         TDB_CONTEXT *the_tdb = NULL;
436         int next_record;
437         int oldest_record;
438
439
440         the_tdb = tdb_of( info->logname );
441
442         if ( !the_tdb ) {
443                 DEBUG( 10, ( "Can't find tdb for %s\n", info->logname ) );
444                 info->num_records = 0;
445                 return False;
446         }
447
448         /* lock */
449         tdb_lock_bystring( the_tdb, VN_next_record, 1 );
450
451
452         /* read */
453         next_record = tdb_fetch_int32( the_tdb, VN_next_record );
454         oldest_record = tdb_fetch_int32( the_tdb, VN_oldest_entry );
455
456
457
458         DEBUG( 8,
459                ( "Oldest Record %d Next Record %d\n", oldest_record,
460                  next_record ) );
461
462         info->num_records = ( next_record - oldest_record );
463         info->oldest_entry = oldest_record;
464         tdb_unlock_bystring( the_tdb, VN_next_record );
465
466
467         return True;
468
469
470 }
471
472 /********************************************************************
473  ********************************************************************/
474
475 /**
476  * Callout to find the oldest record in the log
477  * 
478  *   smbrun calling convention --
479  *     INPUT: <oldest_entry_cmd> <log name> <policy handle>
480  *     OUTPUT: If there are entries in the event log, the index of the
481  *             oldest entry. Must be 1 or greater.
482  *             If there are no entries in the log, returns a 0
483  */
484
485 static BOOL get_oldest_entry_hook( EventlogInfo * info )
486 {
487
488         /* it's the same thing */
489         return get_num_records_hook( info );
490 }
491
492
493 /********************************************************************
494  ********************************************************************/
495
496 /**
497  * Callout to close the specified event log
498  * 
499  *   smbrun calling convention --
500  *     INPUT: <close_cmd> <log name> <policy handle>
501  *     OUTPUT: the string "SUCCESS" if the command succeeded
502  *             no such string if there was a failure.
503  */
504
505 static BOOL close_eventlog_hook( EventlogInfo * info )
506 {
507
508         return True;
509 }
510
511 /********************************************************************
512  ********************************************************************/
513
514 static Eventlog_entry *read_package_entry( prs_struct * ps,
515                                            EVENTLOG_Q_READ_EVENTLOG * q_u,
516                                            EVENTLOG_R_READ_EVENTLOG * r_u,
517                                            Eventlog_entry * entry )
518 {
519         uint8 *offset;
520         Eventlog_entry *ee_new = NULL;
521
522         ee_new = PRS_ALLOC_MEM( ps, Eventlog_entry, 1 );
523         if ( ee_new == NULL ) {
524                 return NULL;
525         }
526
527         entry->data_record.sid_padding =
528                 ( ( 4 -
529                     ( ( entry->data_record.source_name_len +
530                         entry->data_record.computer_name_len ) % 4 ) ) % 4 );
531         entry->data_record.data_padding =
532                 ( 4 -
533                   ( ( entry->data_record.strings_len +
534                       entry->data_record.user_data_len ) % 4 ) ) % 4;
535         entry->record.length = sizeof( Eventlog_record );
536         entry->record.length += entry->data_record.source_name_len;
537         entry->record.length += entry->data_record.computer_name_len;
538         if ( entry->record.user_sid_length == 0 ) {
539                 /* Should not pad to a DWORD boundary for writing out the sid if there is
540                    no SID, so just propagate the padding to pad the data */
541                 entry->data_record.data_padding +=
542                         entry->data_record.sid_padding;
543                 entry->data_record.sid_padding = 0;
544         }
545         DEBUG( 10,
546                ( "sid_padding is [%d].\n", entry->data_record.sid_padding ) );
547         DEBUG( 10,
548                ( "data_padding is [%d].\n",
549                  entry->data_record.data_padding ) );
550
551         entry->record.length += entry->data_record.sid_padding;
552         entry->record.length += entry->record.user_sid_length;
553         entry->record.length += entry->data_record.strings_len;
554         entry->record.length += entry->data_record.user_data_len;
555         entry->record.length += entry->data_record.data_padding;
556         /* need another copy of length at the end of the data */
557         entry->record.length += sizeof( entry->record.length );
558         DEBUG( 10,
559                ( "entry->record.length is [%d].\n", entry->record.length ) );
560         entry->data =
561                 PRS_ALLOC_MEM( ps, uint8,
562                                entry->record.length -
563                                sizeof( Eventlog_record ) -
564                                sizeof( entry->record.length ) );
565         if ( entry->data == NULL ) {
566                 return NULL;
567         }
568         offset = entry->data;
569         memcpy( offset, &( entry->data_record.source_name ),
570                 entry->data_record.source_name_len );
571         offset += entry->data_record.source_name_len;
572         memcpy( offset, &( entry->data_record.computer_name ),
573                 entry->data_record.computer_name_len );
574         offset += entry->data_record.computer_name_len;
575         /* SID needs to be DWORD-aligned */
576         offset += entry->data_record.sid_padding;
577         entry->record.user_sid_offset =
578                 sizeof( Eventlog_record ) + ( offset - entry->data );
579         memcpy( offset, &( entry->data_record.sid ),
580                 entry->record.user_sid_length );
581         offset += entry->record.user_sid_length;
582         /* Now do the strings */
583         entry->record.string_offset =
584                 sizeof( Eventlog_record ) + ( offset - entry->data );
585         memcpy( offset, &( entry->data_record.strings ),
586                 entry->data_record.strings_len );
587         offset += entry->data_record.strings_len;
588         /* Now do the data */
589         entry->record.data_length = entry->data_record.user_data_len;
590         entry->record.data_offset =
591                 sizeof( Eventlog_record ) + ( offset - entry->data );
592         memcpy( offset, &( entry->data_record.user_data ),
593                 entry->data_record.user_data_len );
594         offset += entry->data_record.user_data_len;
595
596         memcpy( &( ee_new->record ), &entry->record,
597                 sizeof( Eventlog_record ) );
598         memcpy( &( ee_new->data_record ), &entry->data_record,
599                 sizeof( Eventlog_data_record ) );
600         ee_new->data = entry->data;
601
602         return ee_new;
603 }
604
605 /********************************************************************
606  ********************************************************************/
607
608 static BOOL add_record_to_resp( EVENTLOG_R_READ_EVENTLOG * r_u,
609                                 Eventlog_entry * ee_new )
610 {
611         Eventlog_entry *insert_point;
612
613         insert_point = r_u->entry;
614
615         if ( NULL == insert_point ) {
616                 r_u->entry = ee_new;
617                 ee_new->next = NULL;
618         } else {
619                 while ( ( NULL != insert_point->next ) ) {
620                         insert_point = insert_point->next;
621                 }
622                 ee_new->next = NULL;
623                 insert_point->next = ee_new;
624         }
625         r_u->num_records++;
626         r_u->num_bytes_in_resp += ee_new->record.length;
627
628         return True;
629 }
630
631 /********************************************************************
632  ********************************************************************/
633
634 /**
635  * Callout to clear (and optionally backup) a specified event log
636  *
637  *   smbrun calling convention --
638  *     INPUT:  <clear_eventlog_cmd> <log name> <policy handle>
639  *     OUTPUT: A single line with the string "SUCCESS" if the command succeeded.
640  *             Otherwise it is assumed to have failed
641  *
642  *     INPUT:  <clear_eventlog_cmd> <log name> <backup file> <policy handle>
643  *     OUTPUT: A single line with the string "SUCCESS" if the command succeeded.
644  *             Otherwise it is assumed to have failed
645  *             The given log is copied to that location on the server. See comments for
646  *               eventlog_io_q_clear_eventlog for info about odd file name behavior
647  */
648 static BOOL clear_eventlog_hook( EventlogInfo * info,
649                                  pstring backup_file_name )
650 {
651
652         int i;
653
654
655         if ( !info )
656                 return False;
657         DEBUG( 3, ( "There are %d event logs\n", nlogs ) );
658         for ( i = 0; i < nlogs; i++ ) {
659                 DEBUG( 3,
660                        ( "Comparing Eventlog %s,  %s\n", info->logname,
661                          ttdb[i].logname ) );
662                 if ( !StrCaseCmp( info->logname, ttdb[i].logname ) ) {
663                         /* close the current one, reinit */
664                         tdb_close( ttdb[i].log_tdb );
665                         DEBUG( 3,
666                                ( "Closing Eventlog %s, file-on-disk %s\n",
667                                  info->logname, ttdb[i].tdbfname ) );
668                         ttdb[i].log_tdb =
669                                 init_eventlog_tdb( ttdb[i].tdbfname );
670                         return True;
671                 }
672         }
673
674         return False;           /* not found */
675         /* TODO- do something with the backup file name */
676
677 }
678
679 /*******************************************************************
680  *******************************************************************/
681
682 static int eventlog_size( char *eventlog_name )
683 {
684         TDB_CONTEXT *tdb;
685
686         if ( !eventlog_name )
687                 return 0;
688         tdb = tdb_of( eventlog_name );
689         if ( !tdb )
690                 return 0;
691         return eventlog_tdb_size( tdb, NULL, NULL );
692 }
693
694 /********************************************************************
695  ********************************************************************/
696
697 WERROR _eventlog_open_eventlog( pipes_struct * p,
698                                 EVENTLOG_Q_OPEN_EVENTLOG * q_u,
699                                 EVENTLOG_R_OPEN_EVENTLOG * r_u )
700 {
701         EventlogInfo *info = NULL;
702         fstring str;
703
704         if ( !( info = TALLOC_ZERO_P( NULL, EventlogInfo ) ) )
705                 return WERR_NOMEM;
706
707         fstrcpy( str, global_myname(  ) );
708         if ( q_u->servername.string ) {
709                 rpcstr_pull( str, q_u->servername.string->buffer,
710                              sizeof( str ),
711                              q_u->servername.string->uni_str_len * 2, 0 );
712         }
713
714         info->servername = talloc_strdup( info, str );
715
716         fstrcpy( str, "Application" );
717         if ( q_u->logname.string ) {
718                 rpcstr_pull( str, q_u->logname.string->buffer,
719                              sizeof( str ),
720                              q_u->logname.string->uni_str_len * 2, 0 );
721         }
722
723         info->logname = talloc_strdup( info, str );
724
725         DEBUG( 1,
726                ( "Size of %s is %d\n", info->logname,
727                  eventlog_size( info->logname ) ) );
728
729
730
731         DEBUG( 10,
732                ( "_eventlog_open_eventlog: Using [%s] as the server name.\n",
733                  info->servername ) );
734         DEBUG( 10,
735                ( "_eventlog_open_eventlog: Using [%s] as the source log file.\n",
736                  info->logname ) );
737
738
739         if ( !create_policy_hnd
740              ( p, &r_u->handle, free_eventlog_info, ( void * ) info ) ) {
741                 free_eventlog_info( info );
742                 return WERR_NOMEM;
743         }
744
745         if ( !open_eventlog_hook( info ) ) {
746                 close_policy_hnd( p, &r_u->handle );
747                 return WERR_BADFILE;
748         }
749
750         sync_eventlog_params( info->logname );
751         prune_eventlog( tdb_of( info->logname ) );
752
753         return WERR_OK;
754 }
755
756 /********************************************************************
757  ********************************************************************/
758
759 WERROR _eventlog_clear_eventlog( pipes_struct * p,
760                                  EVENTLOG_Q_CLEAR_EVENTLOG * q_u,
761                                  EVENTLOG_R_CLEAR_EVENTLOG * r_u )
762 {
763         EventlogInfo *info = find_eventlog_info_by_hnd( p, &q_u->handle );
764         pstring backup_file_name;
765
766         pstrcpy( backup_file_name, "" );
767
768         if ( q_u->backupfile.string )
769                 unistr2_to_ascii( backup_file_name, q_u->backupfile.string,
770                                   sizeof( backup_file_name ) );
771
772         DEBUG( 10,
773                ( "_eventlog_clear_eventlog: Using [%s] as the backup file name for log [%s].",
774                  backup_file_name, info->logname ) );
775
776         if ( !( clear_eventlog_hook( info, backup_file_name ) ) )
777                 return WERR_BADFILE;
778
779         return WERR_OK;
780 }
781
782 /********************************************************************
783  ********************************************************************/
784
785 WERROR _eventlog_close_eventlog( pipes_struct * p,
786                                  EVENTLOG_Q_CLOSE_EVENTLOG * q_u,
787                                  EVENTLOG_R_CLOSE_EVENTLOG * r_u )
788 {
789         EventlogInfo *info = find_eventlog_info_by_hnd( p, &q_u->handle );
790
791         if ( !( close_eventlog_hook( info ) ) )
792                 return WERR_BADFILE;
793
794         if ( !( close_policy_hnd( p, &q_u->handle ) ) ) {
795                 return WERR_BADFID;
796         }
797
798         return WERR_OK;
799 }
800
801 /********************************************************************
802  ********************************************************************/
803
804 WERROR _eventlog_read_eventlog( pipes_struct * p,
805                                 EVENTLOG_Q_READ_EVENTLOG * q_u,
806                                 EVENTLOG_R_READ_EVENTLOG * r_u )
807 {
808         EventlogInfo *info = find_eventlog_info_by_hnd( p, &q_u->handle );
809         Eventlog_entry entry, *ee_new;
810
811         uint32 num_records_read = 0;
812         prs_struct *ps;
813         int bytes_left, record_number;
814         TDB_CONTEXT *the_tdb;
815
816
817         info->flags = q_u->flags;
818         ps = &p->out_data.rdata;
819
820
821         bytes_left = q_u->max_read_size;
822         the_tdb = tdb_of( info->logname );
823         if ( !the_tdb ) {
824                 /* todo handle the error */
825
826         }
827         /* DEBUG(8,("Bytes left is %d\n",bytes_left)); */
828
829
830         record_number = q_u->offset;
831
832         while ( bytes_left > 0 ) {
833                 if ( get_eventlog_record
834                      ( ps, the_tdb, record_number, &entry ) ) {
835                         DEBUG( 8,
836                                ( "Retrieved record %d\n", record_number ) );
837                         /* Now see if there is enough room to add */
838                         if ( ( ee_new =
839                                read_package_entry( ps, q_u, r_u,
840                                                    &entry ) ) == NULL ) {
841                                 return WERR_NOMEM;
842
843                         }
844
845                         if ( r_u->num_bytes_in_resp + ee_new->record.length >
846                              q_u->max_read_size ) {
847                                 r_u->bytes_in_next_record =
848                                         ee_new->record.length;
849                                 /* response would be too big to fit in client-size buffer */
850                                 bytes_left = 0;
851                                 break;
852                         }
853                         add_record_to_resp( r_u, ee_new );
854                         bytes_left -= ee_new->record.length;
855                         ZERO_STRUCT( entry );
856                         num_records_read =
857                                 r_u->num_records - num_records_read;
858                         DEBUG( 10,
859                                ( "_eventlog_read_eventlog: read [%d] records for a total of [%d] records using [%d] bytes out of a max of [%d].\n",
860                                  num_records_read, r_u->num_records,
861                                  r_u->num_bytes_in_resp,
862                                  q_u->max_read_size ) );
863                 } else {
864                         DEBUG( 8, ( "get_eventlog_record returned NULL\n" ) );
865                         return WERR_NOMEM;      /* wrong error - but return one anyway */
866                 }
867
868
869                 if ( info->flags & EVENTLOG_FORWARDS_READ ) {
870                         record_number++;
871                 } else {
872                         record_number--;
873                 }
874
875         }
876         return WERR_OK;
877 }
878
879 /********************************************************************
880  ********************************************************************/
881
882 WERROR _eventlog_get_oldest_entry( pipes_struct * p,
883                                    EVENTLOG_Q_GET_OLDEST_ENTRY * q_u,
884                                    EVENTLOG_R_GET_OLDEST_ENTRY * r_u )
885 {
886         EventlogInfo *info = find_eventlog_info_by_hnd( p, &q_u->handle );
887
888         if ( !( get_oldest_entry_hook( info ) ) )
889                 return WERR_BADFILE;
890
891         r_u->oldest_entry = info->oldest_entry;
892
893         return WERR_OK;
894 }
895
896 /********************************************************************
897  ********************************************************************/
898
899 WERROR _eventlog_get_num_records( pipes_struct * p,
900                                   EVENTLOG_Q_GET_NUM_RECORDS * q_u,
901                                   EVENTLOG_R_GET_NUM_RECORDS * r_u )
902 {
903         EventlogInfo *info = find_eventlog_info_by_hnd( p, &q_u->handle );
904
905         if ( !( get_num_records_hook( info ) ) )
906                 return WERR_BADFILE;
907
908         r_u->num_records = info->num_records;
909
910         return WERR_OK;
911 }