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.
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.
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.
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.
26 #define DBGC_CLASS DBGC_RPC_SRV
30 pstring logname
; /* rather than alloc on the fly what we need... (memory is cheap now) */
32 TDB_CONTEXT
*log_tdb
; /* the pointer to the TDB_CONTEXT */
36 static EventlogTDBInfo
*ttdb
= NULL
;
37 static TALLOC_CTX
*mem_ctx
= NULL
;
50 /********************************************************************
51 ********************************************************************/
53 void test_eventlog_tdb( TDB_CONTEXT
* the_tdb
)
59 memset( &ee
, 0, sizeof( Eventlog_entry
) );
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;
83 rpcstr_push( ( void * ) ( ee
.data_record
.source_name
),
85 sizeof( ee
.data_record
.source_name
),
87 ee
.data_record
.source_name_len
=
88 ( strlen_w( ee
.data_record
.source_name
) * 2 ) + 2;
90 rpcstr_push( ( void * ) ( ee
.data_record
.computer_name
),
92 sizeof( ee
.data_record
.computer_name
),
95 ee
.data_record
.computer_name_len
=
96 ( strlen_w( ee
.data_record
.computer_name
) * 2 ) + 2;
98 write_eventlog_tdb( the_tdb
, &ee
);
103 /********************************************************************
104 ********************************************************************/
106 static void refresh_eventlog_tdb_table( void )
108 const char **elogs
= lp_eventlog_list( );
115 mem_ctx
= talloc_init( "refresh_eventlog_tdb_table" );
119 DEBUG( 1, ( "Can't allocate memory\n" ) );
124 for ( i
= 0; elogs
[i
]; i
++ ) {
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 */
130 if ( ( ttdb
!= NULL
) ) {
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
);
139 } else { /* i == nlogs */
141 for ( j
= 0; j
< nlogs
; j
++ ) {
142 if ( StrCaseCmp( ttdb
[j
].logname
, elogs
[i
] ) ) {
143 /* something changed, have to discard */
145 ( "Closing existing table \n" ) );
146 for ( j
= 0; j
< nlogs
; j
++ ) {
147 tdb_close( ttdb
[j
].log_tdb
);
157 /* note that this might happen because of above */
158 if ( ( i
> 0 ) && ( ttdb
== NULL
) ) {
160 DEBUG( 10, ( "Creating the table\n" ) );
161 ttdb
= TALLOC( mem_ctx
, sizeof( EventlogTDBInfo
) * i
);
164 ( "Can't allocate table for tdb handles \n" ) );
167 for ( j
= 0; j
< i
; j
++ ) {
168 pstrcpy( ttdb
[j
].tdbfname
,
169 lock_path( mk_tdbfilename
172 sizeof( pstring
) ) ) );
173 pstrcpy( ttdb
[j
].logname
, elogs
[j
] );
174 DEBUG( 10, ( "Opening tdb for %s\n", elogs
[j
] ) );
176 open_eventlog_tdb( ttdb
[j
].tdbfname
);
182 /********************************************************************
183 ********************************************************************/
185 TDB_CONTEXT
*tdb_of( char *eventlog_name
)
189 if ( !eventlog_name
)
193 DEBUG( 10, ( "Refreshing list of eventlogs\n" ) );
194 refresh_eventlog_tdb_table( );
198 ( "eventlog tdb table is NULL after a refresh!\n" ) );
203 DEBUG( 10, ( "Number of eventlogs %d\n", nlogs
) );
205 for ( i
= 0; i
< nlogs
; i
++ ) {
206 if ( strequal( eventlog_name
, ttdb
[i
].logname
) )
207 return ttdb
[i
].log_tdb
;
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 ********************************************************************/
219 Eventlog_entry
*get_eventlog_record( prs_struct
* ps
, TDB_CONTEXT
* tdb
,
220 int recno
, Eventlog_entry
* ee
)
229 pstring
*wpsource
, *wpcomputer
, *wpsid
, *wpstrs
, *puserdata
;
231 key
.dsize
= sizeof( int32
);
235 key
.dptr
= ( char * ) &srecno
;
237 ret
= tdb_fetch( tdb
, key
);
239 if ( ret
.dsize
== 0 ) {
241 ( "Can't find a record for the key, record %d\n",
246 len
= tdb_unpack( ret
.dptr
, ret
.dsize
, "d", &reclen
);
248 DEBUG( 10, ( "Unpacking record %d, size is %d\n", srecno
, len
) );
253 /* ee = PRS_ALLOC_MEM(ps, Eventlog_entry, 1); */
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
);
278 ( "Read record %d, len in tdb was %d\n",
279 ee
->record
.record_number
, len
) );
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' */
285 memcpy( ee
->data_record
.computer_name
, wpcomputer
,
286 ee
->data_record
.computer_name_len
);
288 memcpy( ee
->data_record
.source_name
, wpsource
,
289 ee
->data_record
.source_name_len
);
292 memcpy( ee
->data_record
.sid
, wpsid
,
293 ee
->record
.user_sid_length
);
295 memcpy( ee
->data_record
.strings
, wpstrs
,
296 ee
->data_record
.strings_len
);
298 /* note that userdata is a pstring */
300 memcpy( ee
->data_record
.user_data
, puserdata
,
301 ee
->data_record
.user_data_len
);
303 SAFE_FREE( wpcomputer
);
304 SAFE_FREE( wpsource
);
307 SAFE_FREE( puserdata
);
309 DEBUG( 10, ( "get_eventlog_record: read back %d\n", len
) );
311 ( "get_eventlog_record: computer_name %d is ",
312 ee
->data_record
.computer_name_len
) );
313 SAFE_FREE( ret
.dptr
);
317 /********************************************************************
318 ********************************************************************/
320 static void free_eventlog_info( void *ptr
)
325 /********************************************************************
326 ********************************************************************/
328 static EventlogInfo
*find_eventlog_info_by_hnd( pipes_struct
* p
,
329 POLICY_HND
* handle
)
333 if ( !find_policy_by_hnd( p
, handle
, ( void ** ) &info
) ) {
335 ( "find_eventlog_info_by_hnd: eventlog not found.\n" ) );
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 ********************************************************************/
347 static BOOL
sync_eventlog_params( const char *elogname
)
352 REGISTRY_KEY
*keyinfo
;
356 TDB_CONTEXT
*the_tdb
;
358 the_tdb
= tdb_of( ( char * ) elogname
);
360 DEBUG( 4, ( "sync_eventlog_params with %s\n", elogname
) );
363 DEBUG( 4, ( "Can't open tdb for %s\n", elogname
) );
366 /* set resonable defaults. 512Kb on size and 1 week on time */
369 uiRetention
= 604800;
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
376 pstr_sprintf( path
, "%s/%s", KEY_EVENTLOG
, elogname
);
379 regkey_open_internal( &keyinfo
, path
, get_root_nt_token( ),
382 if ( !W_ERROR_IS_OK( wresult
) ) {
384 ( "sync_eventlog_params: Failed to open key [%s] (%s)\n",
385 path
, dos_errstr( wresult
) ) );
389 if ( !( values
= TALLOC_ZERO_P( keyinfo
, REGVAL_CTR
) ) ) {
390 TALLOC_FREE( keyinfo
);
391 DEBUG( 0, ( "control_eventlog_hook: talloc() failed!\n" ) );
395 fetch_reg_values( keyinfo
, values
);
397 if ( ( val
= regval_ctr_getvalue( values
, "Retention" ) ) != NULL
)
398 uiRetention
= IVAL( regval_data_p( val
), 0 );
400 if ( ( val
= regval_ctr_getvalue( values
, "MaxSize" ) ) != NULL
)
401 uiMaxSize
= IVAL( regval_data_p( val
), 0 );
403 regkey_close_internal( keyinfo
);
405 tdb_store_int32( the_tdb
, VN_maxsize
, uiMaxSize
);
406 tdb_store_int32( the_tdb
, VN_retention
, uiRetention
);
411 /********************************************************************
412 ********************************************************************/
414 static BOOL
open_eventlog_hook( EventlogInfo
* info
)
419 /********************************************************************
420 ********************************************************************/
423 * Callout to get the number of records in the specified event log
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.
432 static BOOL
get_num_records_hook( EventlogInfo
* info
)
435 TDB_CONTEXT
*the_tdb
= NULL
;
440 the_tdb
= tdb_of( info
->logname
);
443 DEBUG( 10, ( "Can't find tdb for %s\n", info
->logname
) );
444 info
->num_records
= 0;
449 tdb_lock_bystring( the_tdb
, VN_next_record
, 1 );
453 next_record
= tdb_fetch_int32( the_tdb
, VN_next_record
);
454 oldest_record
= tdb_fetch_int32( the_tdb
, VN_oldest_entry
);
459 ( "Oldest Record %d Next Record %d\n", oldest_record
,
462 info
->num_records
= ( next_record
- oldest_record
);
463 info
->oldest_entry
= oldest_record
;
464 tdb_unlock_bystring( the_tdb
, VN_next_record
);
472 /********************************************************************
473 ********************************************************************/
476 * Callout to find the oldest record in the log
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
485 static BOOL
get_oldest_entry_hook( EventlogInfo
* info
)
488 /* it's the same thing */
489 return get_num_records_hook( info
);
493 /********************************************************************
494 ********************************************************************/
497 * Callout to close the specified event log
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.
505 static BOOL
close_eventlog_hook( EventlogInfo
* info
)
511 /********************************************************************
512 ********************************************************************/
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
)
520 Eventlog_entry
*ee_new
= NULL
;
522 ee_new
= PRS_ALLOC_MEM( ps
, Eventlog_entry
, 1 );
523 if ( ee_new
== NULL
) {
527 entry
->data_record
.sid_padding
=
529 ( ( entry
->data_record
.source_name_len
+
530 entry
->data_record
.computer_name_len
) % 4 ) ) % 4 );
531 entry
->data_record
.data_padding
=
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;
546 ( "sid_padding is [%d].\n", entry
->data_record
.sid_padding
) );
548 ( "data_padding is [%d].\n",
549 entry
->data_record
.data_padding
) );
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
);
559 ( "entry->record.length is [%d].\n", entry
->record
.length
) );
561 PRS_ALLOC_MEM( ps
, uint8
,
562 entry
->record
.length
-
563 sizeof( Eventlog_record
) -
564 sizeof( entry
->record
.length
) );
565 if ( entry
->data
== NULL
) {
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
;
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
;
605 /********************************************************************
606 ********************************************************************/
608 static BOOL
add_record_to_resp( EVENTLOG_R_READ_EVENTLOG
* r_u
,
609 Eventlog_entry
* ee_new
)
611 Eventlog_entry
*insert_point
;
613 insert_point
= r_u
->entry
;
615 if ( NULL
== insert_point
) {
619 while ( ( NULL
!= insert_point
->next
) ) {
620 insert_point
= insert_point
->next
;
623 insert_point
->next
= ee_new
;
626 r_u
->num_bytes_in_resp
+= ee_new
->record
.length
;
631 /********************************************************************
632 ********************************************************************/
635 * Callout to clear (and optionally backup) a specified event log
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
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
648 static BOOL
clear_eventlog_hook( EventlogInfo
* info
,
649 pstring backup_file_name
)
657 DEBUG( 3, ( "There are %d event logs\n", nlogs
) );
658 for ( i
= 0; i
< nlogs
; i
++ ) {
660 ( "Comparing Eventlog %s, %s\n", info
->logname
,
662 if ( !StrCaseCmp( info
->logname
, ttdb
[i
].logname
) ) {
663 /* close the current one, reinit */
664 tdb_close( ttdb
[i
].log_tdb
);
666 ( "Closing Eventlog %s, file-on-disk %s\n",
667 info
->logname
, ttdb
[i
].tdbfname
) );
669 init_eventlog_tdb( ttdb
[i
].tdbfname
);
674 return False
; /* not found */
675 /* TODO- do something with the backup file name */
679 /*******************************************************************
680 *******************************************************************/
682 static int eventlog_size( char *eventlog_name
)
686 if ( !eventlog_name
)
688 tdb
= tdb_of( eventlog_name
);
691 return eventlog_tdb_size( tdb
, NULL
, NULL
);
694 /********************************************************************
695 ********************************************************************/
697 WERROR
_eventlog_open_eventlog( pipes_struct
* p
,
698 EVENTLOG_Q_OPEN_EVENTLOG
* q_u
,
699 EVENTLOG_R_OPEN_EVENTLOG
* r_u
)
701 EventlogInfo
*info
= NULL
;
704 if ( !( info
= TALLOC_ZERO_P( NULL
, EventlogInfo
) ) )
707 fstrcpy( str
, global_myname( ) );
708 if ( q_u
->servername
.string
) {
709 rpcstr_pull( str
, q_u
->servername
.string
->buffer
,
711 q_u
->servername
.string
->uni_str_len
* 2, 0 );
714 info
->servername
= talloc_strdup( info
, str
);
716 fstrcpy( str
, "Application" );
717 if ( q_u
->logname
.string
) {
718 rpcstr_pull( str
, q_u
->logname
.string
->buffer
,
720 q_u
->logname
.string
->uni_str_len
* 2, 0 );
723 info
->logname
= talloc_strdup( info
, str
);
726 ( "Size of %s is %d\n", info
->logname
,
727 eventlog_size( info
->logname
) ) );
732 ( "_eventlog_open_eventlog: Using [%s] as the server name.\n",
733 info
->servername
) );
735 ( "_eventlog_open_eventlog: Using [%s] as the source log file.\n",
739 if ( !create_policy_hnd
740 ( p
, &r_u
->handle
, free_eventlog_info
, ( void * ) info
) ) {
741 free_eventlog_info( info
);
745 if ( !open_eventlog_hook( info
) ) {
746 close_policy_hnd( p
, &r_u
->handle
);
750 sync_eventlog_params( info
->logname
);
751 prune_eventlog( tdb_of( info
->logname
) );
756 /********************************************************************
757 ********************************************************************/
759 WERROR
_eventlog_clear_eventlog( pipes_struct
* p
,
760 EVENTLOG_Q_CLEAR_EVENTLOG
* q_u
,
761 EVENTLOG_R_CLEAR_EVENTLOG
* r_u
)
763 EventlogInfo
*info
= find_eventlog_info_by_hnd( p
, &q_u
->handle
);
764 pstring backup_file_name
;
766 pstrcpy( backup_file_name
, "" );
768 if ( q_u
->backupfile
.string
)
769 unistr2_to_ascii( backup_file_name
, q_u
->backupfile
.string
,
770 sizeof( backup_file_name
) );
773 ( "_eventlog_clear_eventlog: Using [%s] as the backup file name for log [%s].",
774 backup_file_name
, info
->logname
) );
776 if ( !( clear_eventlog_hook( info
, backup_file_name
) ) )
782 /********************************************************************
783 ********************************************************************/
785 WERROR
_eventlog_close_eventlog( pipes_struct
* p
,
786 EVENTLOG_Q_CLOSE_EVENTLOG
* q_u
,
787 EVENTLOG_R_CLOSE_EVENTLOG
* r_u
)
789 EventlogInfo
*info
= find_eventlog_info_by_hnd( p
, &q_u
->handle
);
791 if ( !( close_eventlog_hook( info
) ) )
794 if ( !( close_policy_hnd( p
, &q_u
->handle
) ) ) {
801 /********************************************************************
802 ********************************************************************/
804 WERROR
_eventlog_read_eventlog( pipes_struct
* p
,
805 EVENTLOG_Q_READ_EVENTLOG
* q_u
,
806 EVENTLOG_R_READ_EVENTLOG
* r_u
)
808 EventlogInfo
*info
= find_eventlog_info_by_hnd( p
, &q_u
->handle
);
809 Eventlog_entry entry
, *ee_new
;
811 uint32 num_records_read
= 0;
813 int bytes_left
, record_number
;
814 TDB_CONTEXT
*the_tdb
;
817 info
->flags
= q_u
->flags
;
818 ps
= &p
->out_data
.rdata
;
821 bytes_left
= q_u
->max_read_size
;
822 the_tdb
= tdb_of( info
->logname
);
824 /* todo handle the error */
827 /* DEBUG(8,("Bytes left is %d\n",bytes_left)); */
830 record_number
= q_u
->offset
;
832 while ( bytes_left
> 0 ) {
833 if ( get_eventlog_record
834 ( ps
, the_tdb
, record_number
, &entry
) ) {
836 ( "Retrieved record %d\n", record_number
) );
837 /* Now see if there is enough room to add */
839 read_package_entry( ps
, q_u
, r_u
,
840 &entry
) ) == NULL
) {
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 */
853 add_record_to_resp( r_u
, ee_new
);
854 bytes_left
-= ee_new
->record
.length
;
855 ZERO_STRUCT( entry
);
857 r_u
->num_records
- num_records_read
;
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
) );
864 DEBUG( 8, ( "get_eventlog_record returned NULL\n" ) );
865 return WERR_NOMEM
; /* wrong error - but return one anyway */
869 if ( info
->flags
& EVENTLOG_FORWARDS_READ
) {
879 /********************************************************************
880 ********************************************************************/
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
)
886 EventlogInfo
*info
= find_eventlog_info_by_hnd( p
, &q_u
->handle
);
888 if ( !( get_oldest_entry_hook( info
) ) )
891 r_u
->oldest_entry
= info
->oldest_entry
;
896 /********************************************************************
897 ********************************************************************/
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
)
903 EventlogInfo
*info
= find_eventlog_info_by_hnd( p
, &q_u
->handle
);
905 if ( !( get_num_records_hook( info
) ) )
908 r_u
->num_records
= info
->num_records
;