s3-libnet-samsync: pass back sequence number from fetch_sam_entries_keytab.
[Samba.git] / source / rpc_server / srv_eventlog_nt.c
blob89a8ebcb50ad13f767faf22fc78336731d0b167b
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 3 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, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
24 #undef DBGC_CLASS
25 #define DBGC_CLASS DBGC_RPC_SRV
27 typedef struct {
28 char *logname;
29 ELOG_TDB *etdb;
30 uint32 current_record;
31 uint32 num_records;
32 uint32 oldest_entry;
33 uint32 flags;
34 uint32 access_granted;
35 } EVENTLOG_INFO;
37 /********************************************************************
38 ********************************************************************/
40 static void free_eventlog_info( void *ptr )
42 EVENTLOG_INFO *elog = (EVENTLOG_INFO *)ptr;
44 if ( elog->etdb )
45 elog_close_tdb( elog->etdb, False );
47 TALLOC_FREE( elog );
50 /********************************************************************
51 ********************************************************************/
53 static EVENTLOG_INFO *find_eventlog_info_by_hnd( pipes_struct * p,
54 POLICY_HND * handle )
56 EVENTLOG_INFO *info;
58 if ( !find_policy_by_hnd( p, handle, (void **)(void *)&info ) ) {
59 DEBUG( 2,
60 ( "find_eventlog_info_by_hnd: eventlog not found.\n" ) );
61 return NULL;
64 return info;
67 /********************************************************************
68 ********************************************************************/
70 static bool elog_check_access( EVENTLOG_INFO *info, NT_USER_TOKEN *token )
72 char *tdbname = elog_tdbname(talloc_tos(), info->logname );
73 SEC_DESC *sec_desc;
74 NTSTATUS status;
76 if ( !tdbname )
77 return False;
79 /* get the security descriptor for the file */
81 sec_desc = get_nt_acl_no_snum( info, tdbname );
82 TALLOC_FREE( tdbname );
84 if ( !sec_desc ) {
85 DEBUG(5,("elog_check_access: Unable to get NT ACL for %s\n",
86 tdbname));
87 return False;
90 /* root free pass */
92 if ( geteuid() == sec_initial_uid() ) {
93 DEBUG(5,("elog_check_access: using root's token\n"));
94 token = get_root_nt_token();
97 /* run the check, try for the max allowed */
99 status = se_access_check( sec_desc, token, MAXIMUM_ALLOWED_ACCESS,
100 &info->access_granted);
102 if ( sec_desc )
103 TALLOC_FREE( sec_desc );
105 if (!NT_STATUS_IS_OK(status)) {
106 DEBUG(8,("elog_check_access: se_access_check() return %s\n",
107 nt_errstr(status)));
108 return False;
111 /* we have to have READ permission for a successful open */
113 return ( info->access_granted & SA_RIGHT_FILE_READ_DATA );
116 /********************************************************************
117 ********************************************************************/
119 static bool elog_validate_logname( const char *name )
121 int i;
122 const char **elogs = lp_eventlog_list();
124 if (!elogs) {
125 return False;
128 for ( i=0; elogs[i]; i++ ) {
129 if ( strequal( name, elogs[i] ) )
130 return True;
133 return False;
136 /********************************************************************
137 ********************************************************************/
139 static bool get_num_records_hook( EVENTLOG_INFO * info )
141 int next_record;
142 int oldest_record;
144 if ( !info->etdb ) {
145 DEBUG( 10, ( "No open tdb for %s\n", info->logname ) );
146 return False;
149 /* lock the tdb since we have to get 2 records */
151 tdb_lock_bystring_with_timeout( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD, 1 );
152 next_record = tdb_fetch_int32( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD);
153 oldest_record = tdb_fetch_int32( ELOG_TDB_CTX(info->etdb), EVT_OLDEST_ENTRY);
154 tdb_unlock_bystring( ELOG_TDB_CTX(info->etdb), EVT_NEXT_RECORD);
156 DEBUG( 8,
157 ( "Oldest Record %d; Next Record %d\n", oldest_record,
158 next_record ) );
160 info->num_records = ( next_record - oldest_record );
161 info->oldest_entry = oldest_record;
163 return True;
166 /********************************************************************
167 ********************************************************************/
169 static bool get_oldest_entry_hook( EVENTLOG_INFO * info )
171 /* it's the same thing */
172 return get_num_records_hook( info );
175 /********************************************************************
176 ********************************************************************/
178 static NTSTATUS elog_open( pipes_struct * p, const char *logname, POLICY_HND *hnd )
180 EVENTLOG_INFO *elog;
182 /* first thing is to validate the eventlog name */
184 if ( !elog_validate_logname( logname ) )
185 return NT_STATUS_OBJECT_PATH_INVALID;
187 if ( !(elog = TALLOC_ZERO_P( NULL, EVENTLOG_INFO )) )
188 return NT_STATUS_NO_MEMORY;
190 elog->logname = talloc_strdup( elog, logname );
192 /* Open the tdb first (so that we can create any new tdbs if necessary).
193 We have to do this as root and then use an internal access check
194 on the file permissions since you can only have a tdb open once
195 in a single process */
197 become_root();
198 elog->etdb = elog_open_tdb( elog->logname, False );
199 unbecome_root();
201 if ( !elog->etdb ) {
202 /* according to MSDN, if the logfile cannot be found, we should
203 default to the "Application" log */
205 if ( !strequal( logname, ELOG_APPL ) ) {
207 TALLOC_FREE( elog->logname );
209 elog->logname = talloc_strdup( elog, ELOG_APPL );
211 /* do the access check */
212 if ( !elog_check_access( elog, p->pipe_user.nt_user_token ) ) {
213 TALLOC_FREE( elog );
214 return NT_STATUS_ACCESS_DENIED;
217 become_root();
218 elog->etdb = elog_open_tdb( elog->logname, False );
219 unbecome_root();
222 if ( !elog->etdb ) {
223 TALLOC_FREE( elog );
224 return NT_STATUS_ACCESS_DENIED; /* ??? */
228 /* now do the access check. Close the tdb if we fail here */
230 if ( !elog_check_access( elog, p->pipe_user.nt_user_token ) ) {
231 elog_close_tdb( elog->etdb, False );
232 TALLOC_FREE( elog );
233 return NT_STATUS_ACCESS_DENIED;
236 /* create the policy handle */
238 if ( !create_policy_hnd
239 ( p, hnd, free_eventlog_info, ( void * ) elog ) ) {
240 free_eventlog_info( elog );
241 return NT_STATUS_NO_MEMORY;
244 /* set the initial current_record pointer */
246 if ( !get_oldest_entry_hook( elog ) ) {
247 DEBUG(3,("elog_open: Successfully opened eventlog but can't "
248 "get any information on internal records!\n"));
251 elog->current_record = elog->oldest_entry;
253 return NT_STATUS_OK;
256 /********************************************************************
257 ********************************************************************/
259 static NTSTATUS elog_close( pipes_struct *p, POLICY_HND *hnd )
261 if ( !( close_policy_hnd( p, hnd ) ) ) {
262 return NT_STATUS_INVALID_HANDLE;
265 return NT_STATUS_OK;
268 /*******************************************************************
269 *******************************************************************/
271 static int elog_size( EVENTLOG_INFO *info )
273 if ( !info || !info->etdb ) {
274 DEBUG(0,("elog_size: Invalid info* structure!\n"));
275 return 0;
278 return elog_tdb_size( ELOG_TDB_CTX(info->etdb), NULL, NULL );
281 /********************************************************************
282 For the given tdb, get the next eventlog record into the passed
283 Eventlog_entry. returns NULL if it can't get the record for some reason.
284 ********************************************************************/
286 static Eventlog_entry *get_eventlog_record(prs_struct *ps,
287 TDB_CONTEXT *tdb,
288 int recno)
290 Eventlog_entry *ee = NULL;
291 TDB_DATA ret, key;
293 int srecno;
294 int reclen;
295 int len;
297 char *wpsource = NULL;
298 char *wpcomputer = NULL;
299 char *wpsid = NULL;
300 char *wpstrs = NULL;
301 char *puserdata = NULL;
303 key.dsize = sizeof(int32);
305 srecno = recno;
306 key.dptr = ( uint8 * ) &srecno;
308 ret = tdb_fetch( tdb, key );
310 if ( ret.dsize == 0 ) {
311 DEBUG( 8,
312 ( "Can't find a record for the key, record %d\n",
313 recno ) );
314 return NULL;
317 len = tdb_unpack( ret.dptr, ret.dsize, "d", &reclen );
319 DEBUG( 10, ( "Unpacking record %d, size is %d\n", srecno, len ) );
321 if ( !len )
322 return NULL;
324 ee = TALLOC_ARRAY(ps->mem_ctx, Eventlog_entry, 1);
325 if (!ee) {
326 return NULL;
328 ZERO_STRUCTP(ee);
330 len = tdb_unpack( ret.dptr, ret.dsize, "ddddddwwwwddddddBBdBBBd",
331 &ee->record.length, &ee->record.reserved1,
332 &ee->record.record_number,
333 &ee->record.time_generated,
334 &ee->record.time_written, &ee->record.event_id,
335 &ee->record.event_type, &ee->record.num_strings,
336 &ee->record.event_category, &ee->record.reserved2,
337 &ee->record.closing_record_number,
338 &ee->record.string_offset,
339 &ee->record.user_sid_length,
340 &ee->record.user_sid_offset,
341 &ee->record.data_length, &ee->record.data_offset,
342 &ee->data_record.source_name_len, &wpsource,
343 &ee->data_record.computer_name_len, &wpcomputer,
344 &ee->data_record.sid_padding,
345 &ee->record.user_sid_length, &wpsid,
346 &ee->data_record.strings_len, &wpstrs,
347 &ee->data_record.user_data_len, &puserdata,
348 &ee->data_record.data_padding );
349 DEBUG( 10,
350 ( "Read record %d, len in tdb was %d\n",
351 ee->record.record_number, len ) );
353 /* have to do the following because the tdb_unpack allocs a buff, stuffs a pointer to the buff
354 into it's 2nd argment for 'B' */
356 if (wpcomputer) {
357 ee->data_record.computer_name = (smb_ucs2_t *)TALLOC_MEMDUP(
358 ee, wpcomputer, ee->data_record.computer_name_len);
359 if (!ee->data_record.computer_name) {
360 TALLOC_FREE(ee);
361 goto out;
364 if (wpsource) {
365 ee->data_record.source_name = (smb_ucs2_t *)TALLOC_MEMDUP(
366 ee, wpsource, ee->data_record.source_name_len);
367 if (!ee->data_record.source_name) {
368 TALLOC_FREE(ee);
369 goto out;
373 if (wpsid) {
374 ee->data_record.sid = (smb_ucs2_t *)TALLOC_MEMDUP(
375 ee, wpsid, ee->record.user_sid_length);
376 if (!ee->data_record.sid) {
377 TALLOC_FREE(ee);
378 goto out;
381 if (wpstrs) {
382 ee->data_record.strings = (smb_ucs2_t *)TALLOC_MEMDUP(
383 ee, wpstrs, ee->data_record.strings_len);
384 if (!ee->data_record.strings) {
385 TALLOC_FREE(ee);
386 goto out;
390 if (puserdata) {
391 ee->data_record.user_data = (char *)TALLOC_MEMDUP(
392 ee, puserdata, ee->data_record.user_data_len);
393 if (!ee->data_record.user_data) {
394 TALLOC_FREE(ee);
395 goto out;
399 out:
401 SAFE_FREE(wpcomputer);
402 SAFE_FREE(wpsource);
403 SAFE_FREE(wpsid);
404 SAFE_FREE(wpstrs);
405 SAFE_FREE(puserdata);
407 DEBUG( 10, ( "get_eventlog_record: read back %d\n", len ) );
408 DEBUG( 10,
409 ( "get_eventlog_record: computer_name %d is ",
410 ee->data_record.computer_name_len ) );
411 SAFE_FREE(ret.dptr);
412 return ee;
415 /********************************************************************
416 note that this can only be called AFTER the table is constructed,
417 since it uses the table to find the tdb handle
418 ********************************************************************/
420 static bool sync_eventlog_params( EVENTLOG_INFO *info )
422 char *path = NULL;
423 uint32 uiMaxSize;
424 uint32 uiRetention;
425 struct registry_key *key;
426 struct registry_value *value;
427 WERROR wresult;
428 char *elogname = info->logname;
429 TALLOC_CTX *ctx = talloc_tos();
430 bool ret = false;
432 DEBUG( 4, ( "sync_eventlog_params with %s\n", elogname ) );
434 if ( !info->etdb ) {
435 DEBUG( 4, ( "No open tdb! (%s)\n", info->logname ) );
436 return False;
438 /* set resonable defaults. 512Kb on size and 1 week on time */
440 uiMaxSize = 0x80000;
441 uiRetention = 604800;
443 /* the general idea is to internally open the registry
444 key and retrieve the values. That way we can continue
445 to use the same fetch/store api that we use in
446 srv_reg_nt.c */
448 path = talloc_asprintf(ctx, "%s/%s", KEY_EVENTLOG, elogname );
449 if (!path) {
450 return false;
453 wresult = reg_open_path(ctx, path, REG_KEY_READ, get_root_nt_token(),
454 &key);
456 if ( !W_ERROR_IS_OK( wresult ) ) {
457 DEBUG( 4,
458 ( "sync_eventlog_params: Failed to open key [%s] (%s)\n",
459 path, dos_errstr( wresult ) ) );
460 return false;
463 wresult = reg_queryvalue(key, key, "Retention", &value);
464 if (!W_ERROR_IS_OK(wresult)) {
465 DEBUG(4, ("Failed to query value \"Retention\": %s\n",
466 dos_errstr(wresult)));
467 ret = false;
468 goto done;
470 uiRetention = value->v.dword;
472 wresult = reg_queryvalue(key, key, "MaxSize", &value);
473 if (!W_ERROR_IS_OK(wresult)) {
474 DEBUG(4, ("Failed to query value \"MaxSize\": %s\n",
475 dos_errstr(wresult)));
476 ret = false;
477 goto done;
479 uiMaxSize = value->v.dword;
481 tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_MAXSIZE, uiMaxSize );
482 tdb_store_int32( ELOG_TDB_CTX(info->etdb), EVT_RETENTION, uiRetention );
484 ret = true;
486 done:
487 TALLOC_FREE(ctx);
488 return ret;
491 /********************************************************************
492 ********************************************************************/
494 static Eventlog_entry *read_package_entry( prs_struct * ps,
495 Eventlog_entry * entry )
497 uint8 *offset;
498 Eventlog_entry *ee_new = NULL;
500 ee_new = PRS_ALLOC_MEM( ps, Eventlog_entry, 1 );
501 if ( ee_new == NULL ) {
502 return NULL;
505 entry->data_record.sid_padding =
506 ( ( 4 -
507 ( ( entry->data_record.source_name_len +
508 entry->data_record.computer_name_len ) % 4 ) ) % 4 );
509 entry->data_record.data_padding =
510 ( 4 -
511 ( ( entry->data_record.strings_len +
512 entry->data_record.user_data_len ) % 4 ) ) % 4;
513 entry->record.length = sizeof( Eventlog_record );
514 entry->record.length += entry->data_record.source_name_len;
515 entry->record.length += entry->data_record.computer_name_len;
516 if ( entry->record.user_sid_length == 0 ) {
517 /* Should not pad to a DWORD boundary for writing out the sid if there is
518 no SID, so just propagate the padding to pad the data */
519 entry->data_record.data_padding +=
520 entry->data_record.sid_padding;
521 entry->data_record.sid_padding = 0;
523 DEBUG( 10,
524 ( "sid_padding is [%d].\n", entry->data_record.sid_padding ) );
525 DEBUG( 10,
526 ( "data_padding is [%d].\n",
527 entry->data_record.data_padding ) );
529 entry->record.length += entry->data_record.sid_padding;
530 entry->record.length += entry->record.user_sid_length;
531 entry->record.length += entry->data_record.strings_len;
532 entry->record.length += entry->data_record.user_data_len;
533 entry->record.length += entry->data_record.data_padding;
534 /* need another copy of length at the end of the data */
535 entry->record.length += sizeof( entry->record.length );
536 DEBUG( 10,
537 ( "entry->record.length is [%d].\n", entry->record.length ) );
538 entry->data =
539 PRS_ALLOC_MEM( ps, uint8,
540 entry->record.length -
541 sizeof( Eventlog_record ) -
542 sizeof( entry->record.length ) );
543 if ( entry->data == NULL ) {
544 return NULL;
546 offset = entry->data;
547 memcpy( offset, &( entry->data_record.source_name ),
548 entry->data_record.source_name_len );
549 offset += entry->data_record.source_name_len;
550 memcpy( offset, &( entry->data_record.computer_name ),
551 entry->data_record.computer_name_len );
552 offset += entry->data_record.computer_name_len;
553 /* SID needs to be DWORD-aligned */
554 offset += entry->data_record.sid_padding;
555 entry->record.user_sid_offset =
556 sizeof( Eventlog_record ) + ( offset - entry->data );
557 memcpy( offset, &( entry->data_record.sid ),
558 entry->record.user_sid_length );
559 offset += entry->record.user_sid_length;
560 /* Now do the strings */
561 entry->record.string_offset =
562 sizeof( Eventlog_record ) + ( offset - entry->data );
563 memcpy( offset, &( entry->data_record.strings ),
564 entry->data_record.strings_len );
565 offset += entry->data_record.strings_len;
566 /* Now do the data */
567 entry->record.data_length = entry->data_record.user_data_len;
568 entry->record.data_offset =
569 sizeof( Eventlog_record ) + ( offset - entry->data );
570 memcpy( offset, &( entry->data_record.user_data ),
571 entry->data_record.user_data_len );
572 offset += entry->data_record.user_data_len;
574 memcpy( &( ee_new->record ), &entry->record,
575 sizeof( Eventlog_record ) );
576 memcpy( &( ee_new->data_record ), &entry->data_record,
577 sizeof( Eventlog_data_record ) );
578 ee_new->data = entry->data;
580 return ee_new;
583 /********************************************************************
584 ********************************************************************/
586 static bool add_record_to_resp( EVENTLOG_R_READ_EVENTLOG * r_u,
587 Eventlog_entry * ee_new )
589 Eventlog_entry *insert_point;
591 insert_point = r_u->entry;
593 if ( NULL == insert_point ) {
594 r_u->entry = ee_new;
595 ee_new->next = NULL;
596 } else {
597 while ( ( NULL != insert_point->next ) ) {
598 insert_point = insert_point->next;
600 ee_new->next = NULL;
601 insert_point->next = ee_new;
603 r_u->num_records++;
604 r_u->num_bytes_in_resp += ee_new->record.length;
606 return True;
609 /********************************************************************
610 _eventlog_OpenEventLogW
611 ********************************************************************/
613 NTSTATUS _eventlog_OpenEventLogW(pipes_struct *p,
614 struct eventlog_OpenEventLogW *r)
616 const char *servername = "";
617 const char *logname = "";
618 EVENTLOG_INFO *info;
619 NTSTATUS result;
621 if (r->in.servername->string) {
622 servername = r->in.servername->string;
625 if (r->in.logname->string) {
626 logname = r->in.logname->string;
629 DEBUG( 10,("_eventlog_open_eventlog: Server [%s], Log [%s]\n",
630 servername, logname ));
632 /* according to MSDN, if the logfile cannot be found, we should
633 default to the "Application" log */
635 if ( !NT_STATUS_IS_OK( result = elog_open( p, logname, r->out.handle )) )
636 return result;
638 if ( !(info = find_eventlog_info_by_hnd( p, r->out.handle )) ) {
639 DEBUG(0,("_eventlog_open_eventlog: eventlog (%s) opened but unable to find handle!\n",
640 logname ));
641 elog_close( p, r->out.handle );
642 return NT_STATUS_INVALID_HANDLE;
645 DEBUG(10,("_eventlog_open_eventlog: Size [%d]\n", elog_size( info )));
647 sync_eventlog_params( info );
648 prune_eventlog( ELOG_TDB_CTX(info->etdb) );
650 return NT_STATUS_OK;
653 /********************************************************************
654 _eventlog_ClearEventLogW
655 This call still needs some work
656 ********************************************************************/
657 /** The windows client seems to be doing something funny with the file name
658 A call like
659 ClearEventLog(handle, "backup_file")
660 on the client side will result in the backup file name looking like this on the
661 server side:
662 \??\${CWD of client}\backup_file
663 If an absolute path gets specified, such as
664 ClearEventLog(handle, "C:\\temp\\backup_file")
665 then it is still mangled by the client into this:
666 \??\C:\temp\backup_file
667 when it is on the wire.
668 I'm not sure where the \?? is coming from, or why the ${CWD} of the client process
669 would be added in given that the backup file gets written on the server side. */
671 NTSTATUS _eventlog_ClearEventLogW(pipes_struct *p,
672 struct eventlog_ClearEventLogW *r)
674 EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
675 const char *backup_file_name = NULL;
677 if ( !info )
678 return NT_STATUS_INVALID_HANDLE;
680 if (r->in.backupfile && r->in.backupfile->string) {
682 backup_file_name = r->in.backupfile->string;
684 DEBUG(8,( "_eventlog_clear_eventlog: Using [%s] as the backup "
685 "file name for log [%s].",
686 backup_file_name, info->logname ) );
689 /* check for WRITE access to the file */
691 if ( !(info->access_granted&SA_RIGHT_FILE_WRITE_DATA) )
692 return NT_STATUS_ACCESS_DENIED;
694 /* Force a close and reopen */
696 elog_close_tdb( info->etdb, True );
697 become_root();
698 info->etdb = elog_open_tdb( info->logname, True );
699 unbecome_root();
701 if ( !info->etdb )
702 return NT_STATUS_ACCESS_DENIED;
704 return NT_STATUS_OK;
707 /********************************************************************
708 ********************************************************************/
710 NTSTATUS _eventlog_CloseEventLog( pipes_struct * p, struct eventlog_CloseEventLog *r )
712 return elog_close( p, r->in.handle );
715 /********************************************************************
716 ********************************************************************/
718 NTSTATUS _eventlog_read_eventlog( pipes_struct * p,
719 EVENTLOG_Q_READ_EVENTLOG * q_u,
720 EVENTLOG_R_READ_EVENTLOG * r_u )
722 EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, &q_u->handle );
723 Eventlog_entry *entry = NULL, *ee_new = NULL;
724 uint32 num_records_read = 0;
725 prs_struct *ps;
726 int bytes_left, record_number;
727 uint32 elog_read_type, elog_read_dir;
729 if (info == NULL) {
730 return NT_STATUS_INVALID_HANDLE;
733 info->flags = q_u->flags;
734 ps = &p->out_data.rdata;
736 bytes_left = q_u->max_read_size;
738 if ( !info->etdb )
739 return NT_STATUS_ACCESS_DENIED;
741 /* check for valid flags. Can't use the sequential and seek flags together */
743 elog_read_type = q_u->flags & (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ);
744 elog_read_dir = q_u->flags & (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ);
746 if ( elog_read_type == (EVENTLOG_SEQUENTIAL_READ|EVENTLOG_SEEK_READ)
747 || elog_read_dir == (EVENTLOG_FORWARDS_READ|EVENTLOG_BACKWARDS_READ) )
749 DEBUG(3,("_eventlog_read_eventlog: Invalid flags [0x%x] for ReadEventLog\n", q_u->flags));
750 return NT_STATUS_INVALID_PARAMETER;
753 /* a sequential read should ignore the offset */
755 if ( elog_read_type & EVENTLOG_SEQUENTIAL_READ )
756 record_number = info->current_record;
757 else
758 record_number = q_u->offset;
760 while ( bytes_left > 0 ) {
762 /* assume that when the record fetch fails, that we are done */
764 entry = get_eventlog_record (ps, ELOG_TDB_CTX(info->etdb), record_number);
765 if (!entry) {
766 break;
769 DEBUG( 8, ( "Retrieved record %d\n", record_number ) );
771 /* Now see if there is enough room to add */
773 if ( !(ee_new = read_package_entry( ps, entry )) )
774 return NT_STATUS_NO_MEMORY;
776 if ( r_u->num_bytes_in_resp + ee_new->record.length > q_u->max_read_size ) {
777 r_u->bytes_in_next_record = ee_new->record.length;
779 /* response would be too big to fit in client-size buffer */
781 bytes_left = 0;
782 break;
785 add_record_to_resp( r_u, ee_new );
786 bytes_left -= ee_new->record.length;
787 TALLOC_FREE(entry);
788 num_records_read = r_u->num_records - num_records_read;
790 DEBUG( 10, ( "_eventlog_read_eventlog: read [%d] records for a total "
791 "of [%d] records using [%d] bytes out of a max of [%d].\n",
792 num_records_read, r_u->num_records,
793 r_u->num_bytes_in_resp,
794 q_u->max_read_size ) );
796 if ( info->flags & EVENTLOG_FORWARDS_READ )
797 record_number++;
798 else
799 record_number--;
801 /* update the eventlog record pointer */
803 info->current_record = record_number;
806 /* crazy by WinXP uses NT_STATUS_BUFFER_TOO_SMALL to
807 say when there are no more records */
809 return (num_records_read ? NT_STATUS_OK : NT_STATUS_BUFFER_TOO_SMALL);
812 /********************************************************************
813 _eventlog_GetOldestRecord
814 ********************************************************************/
816 NTSTATUS _eventlog_GetOldestRecord(pipes_struct *p,
817 struct eventlog_GetOldestRecord *r)
819 EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
821 if (info == NULL) {
822 return NT_STATUS_INVALID_HANDLE;
825 if ( !( get_oldest_entry_hook( info ) ) )
826 return NT_STATUS_ACCESS_DENIED;
828 *r->out.oldest_entry = info->oldest_entry;
830 return NT_STATUS_OK;
833 /********************************************************************
834 _eventlog_GetNumRecords
835 ********************************************************************/
837 NTSTATUS _eventlog_GetNumRecords(pipes_struct *p,
838 struct eventlog_GetNumRecords *r)
840 EVENTLOG_INFO *info = find_eventlog_info_by_hnd( p, r->in.handle );
842 if (info == NULL) {
843 return NT_STATUS_INVALID_HANDLE;
846 if ( !( get_num_records_hook( info ) ) )
847 return NT_STATUS_ACCESS_DENIED;
849 *r->out.number = info->num_records;
851 return NT_STATUS_OK;
854 NTSTATUS _eventlog_BackupEventLogW(pipes_struct *p, struct eventlog_BackupEventLogW *r)
856 p->rng_fault_state = True;
857 return NT_STATUS_NOT_IMPLEMENTED;
860 NTSTATUS _eventlog_DeregisterEventSource(pipes_struct *p, struct eventlog_DeregisterEventSource *r)
862 p->rng_fault_state = True;
863 return NT_STATUS_NOT_IMPLEMENTED;
866 NTSTATUS _eventlog_ChangeNotify(pipes_struct *p, struct eventlog_ChangeNotify *r)
868 p->rng_fault_state = True;
869 return NT_STATUS_NOT_IMPLEMENTED;
872 NTSTATUS _eventlog_RegisterEventSourceW(pipes_struct *p, struct eventlog_RegisterEventSourceW *r)
874 p->rng_fault_state = True;
875 return NT_STATUS_NOT_IMPLEMENTED;
878 NTSTATUS _eventlog_OpenBackupEventLogW(pipes_struct *p, struct eventlog_OpenBackupEventLogW *r)
880 p->rng_fault_state = True;
881 return NT_STATUS_NOT_IMPLEMENTED;
884 NTSTATUS _eventlog_ReadEventLogW(pipes_struct *p, struct eventlog_ReadEventLogW *r)
886 p->rng_fault_state = True;
887 return NT_STATUS_NOT_IMPLEMENTED;
890 NTSTATUS _eventlog_ReportEventW(pipes_struct *p, struct eventlog_ReportEventW *r)
892 p->rng_fault_state = True;
893 return NT_STATUS_NOT_IMPLEMENTED;
896 NTSTATUS _eventlog_ClearEventLogA(pipes_struct *p, struct eventlog_ClearEventLogA *r)
898 p->rng_fault_state = True;
899 return NT_STATUS_NOT_IMPLEMENTED;
902 NTSTATUS _eventlog_BackupEventLogA(pipes_struct *p, struct eventlog_BackupEventLogA *r)
904 p->rng_fault_state = True;
905 return NT_STATUS_NOT_IMPLEMENTED;
908 NTSTATUS _eventlog_OpenEventLogA(pipes_struct *p, struct eventlog_OpenEventLogA *r)
910 p->rng_fault_state = True;
911 return NT_STATUS_NOT_IMPLEMENTED;
914 NTSTATUS _eventlog_RegisterEventSourceA(pipes_struct *p, struct eventlog_RegisterEventSourceA *r)
916 p->rng_fault_state = True;
917 return NT_STATUS_NOT_IMPLEMENTED;
920 NTSTATUS _eventlog_OpenBackupEventLogA(pipes_struct *p, struct eventlog_OpenBackupEventLogA *r)
922 p->rng_fault_state = True;
923 return NT_STATUS_NOT_IMPLEMENTED;
926 NTSTATUS _eventlog_ReadEventLogA(pipes_struct *p, struct eventlog_ReadEventLogA *r)
928 p->rng_fault_state = True;
929 return NT_STATUS_NOT_IMPLEMENTED;
932 NTSTATUS _eventlog_ReportEventA(pipes_struct *p, struct eventlog_ReportEventA *r)
934 p->rng_fault_state = True;
935 return NT_STATUS_NOT_IMPLEMENTED;
938 NTSTATUS _eventlog_RegisterClusterSvc(pipes_struct *p, struct eventlog_RegisterClusterSvc *r)
940 p->rng_fault_state = True;
941 return NT_STATUS_NOT_IMPLEMENTED;
944 NTSTATUS _eventlog_DeregisterClusterSvc(pipes_struct *p, struct eventlog_DeregisterClusterSvc *r)
946 p->rng_fault_state = True;
947 return NT_STATUS_NOT_IMPLEMENTED;
950 NTSTATUS _eventlog_WriteClusterEvents(pipes_struct *p, struct eventlog_WriteClusterEvents *r)
952 p->rng_fault_state = True;
953 return NT_STATUS_NOT_IMPLEMENTED;
956 NTSTATUS _eventlog_GetLogIntormation(pipes_struct *p, struct eventlog_GetLogIntormation *r)
958 p->rng_fault_state = True;
959 return NT_STATUS_NOT_IMPLEMENTED;
962 NTSTATUS _eventlog_FlushEventLog(pipes_struct *p, struct eventlog_FlushEventLog *r)
964 p->rng_fault_state = True;
965 return NT_STATUS_NOT_IMPLEMENTED;