Class: Win32::ChangeJournal

Inherits:
Object
  • Object
show all
Defined in:
ext/win32/changejournal.c

Defined Under Namespace

Classes: Error

Constant Summary collapse

VERSION =

The version of the win32-changejournal library

0.3.3

Instance Method Summary collapse

Constructor Details

#initialize(v_drive) ⇒ Object

:call-seq:

Win32::ChangeJournal.new(volume)

Returns a new ChangeJournal object and places a monitor on volume.

Example:

# Put a change journal monitor on the C: drive
cj = Win32::Change::Journal.new("C:\\")


336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
# File 'ext/win32/changejournal.c', line 336

static VALUE changejournal_init(VALUE self, VALUE v_drive)
{
   ChangeJournalStruct* ptr;
   LPCTSTR lpDriveLetter = StringValuePtr(v_drive);

   Data_Get_Struct(self, ChangeJournalStruct, ptr);

   // Do not allow a block for this class
   if(rb_block_given_p())
      rb_raise(cCJError, "block not permitted for this class");

   // Initialize member variables
   ptr->hCJ = INVALID_HANDLE_VALUE;
   ptr->hCJAsync = INVALID_HANDLE_VALUE;
   ZeroMemory(&(ptr->oCJAsync), sizeof(ptr->oCJAsync));
   ptr->pbCJData = NULL;
   ptr->pUsnRecord = NULL;

   /* Initialize the ChangeJournal object with the current drive letter and tell
    * it to allocate a buffer of 10000 bytes to read journal records.
    */
   if(!Init(ptr, lpDriveLetter[0], 10000))
      rb_raise(rb_eTypeError, "initialization error");

   InitialzeForMonitoring(ptr);

   return self;
}

Instance Method Details

#Win32::ChangeJournalObject

Deletes the change journal on a volume, or waits for notification of change journal deletion.

Example:

require 'win32/changejournal'
cj = Win32::ChangeJournal.new("C:\\")
cj.wait(5)
cj.delete


473
474
475
476
477
478
479
480
481
482
483
# File 'ext/win32/changejournal.c', line 473

static VALUE changejournal_delete(VALUE self){
   ChangeJournalStruct *ptr;
   USN_JOURNAL_DATA ujd;

   Data_Get_Struct(self, ChangeJournalStruct, ptr);

   Query(ptr, &ujd);
   Delete(ptr, ujd.UsnJournalID, USN_DELETE_FLAG_DELETE);

   return self;
}

#wait(*args) ⇒ Object

:call-seq:

Win32::ChangeJournal#wait(num_seconds=INFINITE)
Win32::ChangeJournal#wait(num_seconds=INFINITE){ |struct| ... }

Waits up to ‘num_seconds’ for a notification to occur, or infinitely if no value is specified.

If a block is provided, yields a frozen ChangeJournalStruct that contains three members - file_name, action, and path.

Example:

require 'win32/changejournal'
cj = Win32::ChangeJournal.new("C:\\")

# Wait for something to happen for 5 seconds, but ignore the details
cj.wait(5)

# Wait for 5 seconds, print the details if any, then bail out
cj.wait(5){ |struct| p struct }

# Wait indefinitely, and print the details when something happens
cj.wait{ |struct| p struct }


391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
# File 'ext/win32/changejournal.c', line 391

static VALUE changejournal_wait(int argc, VALUE* argv, VALUE self){
	VALUE v_timeout, v_block;
   ChangeJournalStruct *ptr;
   DWORD dwTimeout, dwWait;
   READ_USN_JOURNAL_DATA rujd;
   BOOL fOk;

   Data_Get_Struct(self, ChangeJournalStruct, ptr);

   rb_scan_args(argc, argv, "01&", &v_timeout, &v_block);

   if(NIL_P(v_timeout)){
      dwTimeout = INFINITE;
   }
   else{
      dwTimeout = NUM2UINT(v_timeout);
      dwTimeout *= 1000; // Convert milliseconds to seconds
   }

   rujd = ptr->rujd;
   rujd.BytesToWaitFor = 1;

   // Try to read at least one byte from the journal at the specified USN.
   // When 1 byte is available, the event in m_oCJAsync will be signaled.

   fOk = DeviceIoControl(
      ptr->hCJAsync,
      FSCTL_READ_USN_JOURNAL,
      &rujd,
      sizeof(rujd),
      &ptr->UsnAsync,
      sizeof(ptr->UsnAsync),
      NULL,
      &ptr->oCJAsync
   );

   // Do nothing
   if(!fOk && (GetLastError() != ERROR_IO_PENDING)) { }

   dwWait = WaitForSingleObject(ptr->oCJAsync.hEvent, dwTimeout);

   switch(dwWait){
      case WAIT_FAILED:
         rb_raise(cCJError, ErrorDescription(GetLastError()));
         break;
      case WAIT_OBJECT_0:
         rb_iv_set(self, "@signaled", Qtrue);
         if(Qnil != v_block){
            rb_yield(get_file_action(ptr));
         }
         return INT2NUM(1);
         break;
      case WAIT_ABANDONED_0:
         return INT2NUM(-1);
         break;
      case WAIT_TIMEOUT:
         return INT2NUM(0);
         break;
      default:
         rb_raise(cCJError,
            "unknown return value from WaitForSingleObject()"
         );
   };

   return self;
}