root/source3/rpc_server/srv_eventlog_nt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. eventlog_info_destructor
  2. find_eventlog_info_by_hnd
  3. elog_check_access
  4. elog_validate_logname
  5. get_num_records_hook
  6. get_oldest_entry_hook
  7. elog_open
  8. elog_close
  9. elog_size
  10. sync_eventlog_params
  11. _eventlog_OpenEventLogW
  12. _eventlog_ClearEventLogW
  13. _eventlog_CloseEventLog
  14. _eventlog_ReadEventLogW
  15. _eventlog_GetOldestRecord
  16. _eventlog_GetNumRecords
  17. _eventlog_BackupEventLogW
  18. _eventlog_GetLogInformation
  19. _eventlog_FlushEventLog
  20. _eventlog_DeregisterEventSource
  21. _eventlog_ChangeNotify
  22. _eventlog_RegisterEventSourceW
  23. _eventlog_OpenBackupEventLogW
  24. _eventlog_ReportEventW
  25. _eventlog_ClearEventLogA
  26. _eventlog_BackupEventLogA
  27. _eventlog_OpenEventLogA
  28. _eventlog_RegisterEventSourceA
  29. _eventlog_OpenBackupEventLogA
  30. _eventlog_ReadEventLogA
  31. _eventlog_ReportEventA
  32. _eventlog_RegisterClusterSvc
  33. _eventlog_DeregisterClusterSvc
  34. _eventlog_WriteClusterEvents
  35. _eventlog_ReportEventAndSourceW

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

/* [<][>][^][v][top][bottom][index][help] */