diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index a695fec..fe68db4 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -8,7 +8,7 @@ jobs: strategy: fail-fast: false matrix: - ruby: [ '2.4', '2.5', '2.6', '2.7', '3.0' ] + ruby: [ '3.0', '3.1', '3.2' ] os: - ubuntu-latest name: Ruby ${{ matrix.ruby }} building fat gem testing on ${{ matrix.os }} diff --git a/ext/winevt/winevt.c b/ext/winevt/winevt.c index 9dd3df9..621b5d8 100644 --- a/ext/winevt/winevt.c +++ b/ext/winevt/winevt.c @@ -7,6 +7,7 @@ VALUE rb_cSubscribe; VALUE rb_eWinevtQueryError; VALUE rb_eChannelNotFoundError; VALUE rb_eRemoteHandlerError; +VALUE rb_eSubscribeHandlerError; static ID id_call; @@ -20,6 +21,7 @@ Init_winevt(void) rb_eWinevtQueryError = rb_define_class_under(rb_cQuery, "Error", rb_eStandardError); rb_eChannelNotFoundError = rb_define_class_under(rb_cEventLog, "ChannelNotFoundError", rb_eStandardError); rb_eRemoteHandlerError = rb_define_class_under(rb_cSubscribe, "RemoteHandlerError", rb_eRuntimeError); + rb_eSubscribeHandlerError = rb_define_class_under(rb_cSubscribe, "SubscribeHandlerError", rb_eRuntimeError); Init_winevt_channel(rb_cEventLog); Init_winevt_bookmark(rb_cEventLog); diff --git a/ext/winevt/winevt_c.h b/ext/winevt/winevt_c.h index 2c894bc..baafc5e 100644 --- a/ext/winevt/winevt_c.h +++ b/ext/winevt/winevt_c.h @@ -61,6 +61,7 @@ extern VALUE rb_cSubscribe; extern VALUE rb_eWinevtQueryError; extern VALUE rb_eChannelNotFoundError; extern VALUE rb_eRemoteHandlerError; +extern VALUE rb_eSubscribeHandlerError; extern VALUE rb_cLocale; extern VALUE rb_cSession; diff --git a/ext/winevt/winevt_subscribe.c b/ext/winevt/winevt_subscribe.c index 577b5f2..b8846f2 100644 --- a/ext/winevt/winevt_subscribe.c +++ b/ext/winevt/winevt_subscribe.c @@ -174,7 +174,7 @@ rb_winevt_subscribe_subscribe(int argc, VALUE* argv, VALUE self) struct WinevtSession* winevtSession; struct WinevtSubscribe* winevtSubscribe; - hSignalEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + hSignalEvent = CreateEvent(NULL, TRUE, TRUE, NULL); TypedData_Get_Struct( self, struct WinevtSubscribe, &rb_winevt_subscribe_type, winevtSubscribe); @@ -341,6 +341,8 @@ rb_winevt_subscribe_next(VALUE self) EVT_HANDLE hEvents[SUBSCRIBE_ARRAY_SIZE]; ULONG count = 0; DWORD status = ERROR_SUCCESS; + DWORD dwWait = 0; + struct WinevtSubscribe* winevtSubscribe; TypedData_Get_Struct( @@ -355,6 +357,23 @@ rb_winevt_subscribe_next(VALUE self) return Qfalse; } + /* If a signalEvent notifies whether a state of processed event(s) + * is existing or not. + * For checking for a result of WaitForSingleObject, + * we need to raise SubscribeHandlerError exception when + * WAIT_FAILED is detected for further investigations. + * Note that we don't need to wait explicitly here. + * Because this function is inside of each enumerator. + * So, WaitForSingleObject should return immediately and should be + * processed with the latter each loops if there is no more items. + * Just intended to check that there is no errors here. */ + dwWait = WaitForSingleObject(winevtSubscribe->signalEvent, 0); + if (dwWait == WAIT_FAILED) { + raise_system_error(rb_eSubscribeHandlerError, GetLastError()); + } else if (dwWait != WAIT_OBJECT_0) { + return Qfalse; + } + if (!EvtNext(winevtSubscribe->subscription, SUBSCRIBE_ARRAY_SIZE, hEvents, @@ -368,6 +387,8 @@ rb_winevt_subscribe_next(VALUE self) if (ERROR_NO_MORE_ITEMS != status) { return Qfalse; } + + ResetEvent(winevtSubscribe->signalEvent); } if (status == ERROR_SUCCESS) {