diff --git a/nwnss-audit.md b/nwnss-audit.md index b713802..324e49f 100644 --- a/nwnss-audit.md +++ b/nwnss-audit.md @@ -106,7 +106,7 @@ still stay original and remain listed, because later imports may rely on them. | PARTIAL | `include/nwnss/include/nssOSAPIs.h` | ORIG+FIX | nwnss.neb, nwnss.schedule | MARS include hook checked; full original diff still open. | | AUDITED | `include/nwnss/include/pssmpk.h` | PORT | nwnss.pssmpk | MPKNSS owner semantics checked/fixed in 0692. | | AUDITED | `include/nwnss/include/schedule.h` | ORIG+FIX | nwnss.schedule | Userspace scheduler section scoped to MARS_NWE_NWNSS_USERSPACE; checked in 0691. | -| AUDITED | `include/nwnss/internal/nwnssZosCompat.h` | PORT | nwnss.neb, nwnss.schedule | Mars ZOS/NEB compat override header; checked in 0687-0689. | +| AUDITED | `include/nwnss/internal/nwnssZosCompat.h` | PORT | nwnss.neb, nwnss.schedule | Mars ZOS/NEB compat override header; rechecked in 0739/0740. It deliberately redirects imported ZOS scheduling/event/import/file macros to userspace boundary functions while keeping NSS business logic out of the compatibility header. | | AUDITED | `include/nwnss/internal/spinlock.h` | PORT | nwnss.spinlock | Userspace spinlock port tested; checked in 0693. | | PARTIAL | `src/nwnss/comn/common/mgmt.c` | ORIG wrapper | link smoke | Wrapper compiles mgmt.c.h; full original diff open. | | PARTIAL | `src/nwnss/comn/common/ndp_comn.c` | ORIG wrapper | link smoke | Novell wrapper name/pattern; full audit open. | @@ -121,7 +121,7 @@ still stay original and remain listed, because later imports may rely on them. | AUDITED | `src/nwnss/library/misc/rbpTree.c` | PORT | nwnss.rbpTree | No original provider found beyond rbpTree.h/libNSS.imp/callers; CLRS-style algorithmic port checked against header contract in 0703 and strengthened in 0705 with explicit red/black, parent-link, binary-search-order, black-height, and Coin3D-style insertion/deletion stress coverage. Coin3D rbptree.cpp was checked only as an external BSD-licensed CLRS comparison and was not imported. | | AUDITED | `src/nwnss/library/os/currentTime.c` | PORT | nwnss.utc | No userspace original provider exists after checking `public_core/library/utc` and `public_core/sharedsrc`; `public_core/nsslnxlib/nssLnxDummy.c` has a kernel jiffies-oriented `GetCurrentTime`, while `public_core/library/utc/gethres.386` documents the high-resolution timer unit as 100 microseconds. The userspace port keeps `GetCurrentTime()` on a monotonic centisecond/HZ=100 scale and now exposes `GetHighResolutionTimer()` on the documented 1/10000-second scale for checker/compression callers; covered by nwnss.utc. | | AUDITED | `src/nwnss/library/os/delay.c` | ORIG+FIX/PORT | nwnss.schedule, nwnss.snooze | Scheduler functions kept as userspace functions, not macros; original `ZOS_YieldThread`/sleep/schedule lock-boundary behavior rechecked against `nssOSAPIs.h`, and userspace yield now drops/reacquires MPKNSS when owned so other threads can run without the global lock held. | -| AUDITED | `src/nwnss/library/os/nebEventPort.c` | PORT | nwnss.neb | Explicit NEB/nebus service port; checked in 0683-0685. | +| AUDITED | `src/nwnss/library/os/nebEventPort.c` | PORT | nwnss.neb | Explicit NEB/nebus service port rechecked in 0740. No original NEB provider implementation is part of the delivered NSS source set beyond `neb.h`/`nebpub.h`/`nebmpk.h`; this file remains a bounded in-process userspace event-bus port and now covers the full public `nebpub.h` surface for link/test completeness. | | AUDITED | `src/nwnss/library/os/pssmpk.c` | PORT | nwnss.pssmpk | pthread owner semantics checked/fixed in 0692. | | AUDITED | `src/nwnss/library/stdlib/strtol.c` + `include/nwnss/library/xStdlib.h` | PORT + ORIG+FIX header | nwnss.stdlib | No LB_strtol original/sharedsrc found after full NSS/nss-common search; Novell/POSIX strtol semantics mapped to host libc and hardened in 0708. | | TEMP | `src/nwnss/nssStartupNameGlobals.c` | TEMP | link smoke | Transition globals from nssStartup.c; should disappear later. | @@ -290,7 +290,7 @@ even if it already compiles or has indirect test coverage. | AUDITED | ORIG+FIX | nwnss.headers, namespace link smoke | `include/nwnss/internal/msgName.h` | Compared with original `shared/sdk/internal/msgName.h`; name-message layout kept. Differences are include-path normalization to `library/xUnicode.h`, `include/msgGen.h`, `include/nameSpace.h`, `include/hardLinkBeast.h`, plus whitespace/diff-check cleanup. | | AUDITED | ORIG+FIX | nwnss.headers, cache link smoke | `include/nwnss/internal/nCache.h` | Compared with original `shared/sdk/internal/nCache.h`; name-cache API kept. Difference is include-path normalization to `include/xCache.h` only. | | AUDITED | ORIG+FIX | link smoke | `include/nwnss/internal/nssFSHooks.h` | Compared with original `shared/sdk/internal/nssFSHooks.h`; FS hook/event macro surface kept. Differences are include-path normalization to `library/xUnicode.h` and `support/lnxmbINC/fshooks.h` plus whitespace/diff-check cleanup. Not included in the standalone header test because the original header depends on broader ENCP namespace constants. | -| AUDITED | PORT | nwnss.neb, nwnss.schedule | `include/nwnss/internal/nwnssZosCompat.h` | Mars ZOS/NEB compat override header; checked in 0687-0689. | +| AUDITED | PORT | nwnss.neb, nwnss.schedule | `include/nwnss/internal/nwnssZosCompat.h` | Mars ZOS/NEB compat override header; rechecked in 0739/0740. It deliberately redirects imported ZOS scheduling/event/import/file macros to userspace boundary functions while keeping NSS business logic out of the compatibility header. | | AUDITED | ORIG | link smoke | `include/nwnss/internal/objectIDStore.h` | Byte-identical to original `shared/sdk/internal/objectIDStore.h`. | | AUDITED | ORIG+FIX | nwnss.headers, link smoke | `include/nwnss/internal/pssConfig.h` | Compared with original `shared/sdk/internal/pssConfig.h`; PSS config layout/defaults kept. Differences are include-path normalization to `library/omni.h` and `include/hmc.h` plus whitespace cleanup. | | AUDITED | ORIG+FIX | nwnss.headers, link smoke | `include/nwnss/internal/sbsMFL.h` | Compared with original `shared/sdk/internal/sbsMFL.h`; modified-file-list descriptors/prototypes kept. Differences are whitespace/diff-check cleanup only. | @@ -587,7 +587,7 @@ even if it already compiles or has indirect test coverage. | Status | Kind | Test coverage | File | Notes | |---|---:|---|---|---| | AUDITED | ORIG wrapper | link smoke | `src/nwnss/library/debug/otherErrorTables.c` | Restored to the original Novell wrapper shape: single `#include `. The generated/base table flow is handled by imported buildtools and generated `nssErrorTable.c`. | -| AUDITED | ORIG+FIX | nwnss.pssdebug | `src/nwnss/library/debug/pssDebug.c` | Compared with original `public_core/library/debug/pssDebug.c`; debug logic kept. Differences are UNIX/userspace include handling, include-path normalization, disabled wio dependency in userspace, and whitespace. Test covers production debug macros; DBG_DebugFormatBinary is declared by the original header but not exercised directly because it is not part of the exported libnwnss ABI. | +| AUDITED | ORIG+FIX | nwnss.pssdebug | `src/nwnss/library/debug/pssDebug.c` | Compared with original `public_core/library/debug/pssDebug.c`; debug logic kept. Differences are UNIX/userspace include handling, include-path normalization, disabled WIO dependency in userspace, and whitespace. This remains a debug/console boundary only; no NSS runtime decisions depend on the host console port. Test covers production debug macros; DBG_DebugFormatBinary is declared by the original header but not exercised directly because it is not part of the exported libnwnss ABI. | ### Sources: library/eDir @@ -647,7 +647,7 @@ even if it already compiles or has indirect test coverage. | AUDITED | ORIG+FIX/PORT | nwnss.schedule, nwnss.snooze | `src/nwnss/library/os/delay.c` | Compared with original `public_core/library/os/delay.c` and the original scheduler macros in `shared/sdk/internal/nssOSAPIs.h`; userspace keeps the scheduler API as real functions. `LB_delay`, `ZOS_Sleep`, `ZOS_ScheduleWorkToDo` and now `ZOS_YieldThread` preserve the original MPKNSS scheduling boundary by dropping/reacquiring the global lock when the current thread owns it; tests cover locked delay, schedule callbacks outside the lock and yield allowing another thread through the lock boundary. | | AUDITED | ORIG+FIX | nwnss.inst | `src/nwnss/library/os/inst.c` | Compared with original `public_core/library/os/inst.c`; instrumentation harvest/reset/init logic kept. Differences are linux/module.h removal and include-path normalization; tests cover file/cache/Linux/BST counter harvest/reset and cyclic init wiring. | | AUDITED | ORIG+FIX | nwnss.mailbox | `src/nwnss/library/os/mailbox.c` | Compared with original `public_core/library/os/mailbox.c`; mbInit/mbSetHigh behavior kept. Differences are procdefs/include-path normalization and whitespace cleanup; tests cover empty/full/FIFO, peek/drop, next/give and wraparound behavior. | -| AUDITED | PORT | nwnss.neb | `src/nwnss/library/os/nebEventPort.c` | Explicit NEB/nebus service port; checked in 0683-0685. | +| AUDITED | PORT | nwnss.neb | `src/nwnss/library/os/nebEventPort.c` | Explicit NEB/nebus service port rechecked in 0740. No original NEB provider implementation is part of the delivered NSS source set beyond `neb.h`/`nebpub.h`/`nebmpk.h`; this file remains a bounded in-process userspace event-bus port. It now covers the full public `nebpub.h` surface used for linking/tests (`GetEventBlocks`, `ReturnEventBlocks`, producer/consumer/filter registration and unregister, name queries, synchronous `ProduceEvent`). Filters are registered/unregistered for ABI compatibility but do not invent external NEB filtering semantics in the port. | | AUDITED | PORT | nwnss.pssmpk | `src/nwnss/library/os/pssmpk.c` | pthread owner semantics checked/fixed in 0692. | | AUDITED | ORIG+FIX/PORT | nwnss.snooze | `src/nwnss/library/os/snooze.c` | Compared with original `public_core/library/os/snooze.c`; snooze queue/timeout/roust logic kept. Differences are linux/module.h removal, include-path normalization and a legacy callback cast for secOneShot; tests cover empty roust behavior and the scheduler/snooze boundary remains covered by nwnss.schedule/nwnss.snooze. | | AUDITED | ORIG+FIX | nwnss.worktodo | `src/nwnss/library/os/worktodo.c` | Compared with original `public_core/library/os/worktodo.c`; fillInWork field setup kept. Differences are procdefs/include-path normalization to `library/xStdlib.h`; tests cover resource tag, callback, reserved fields and NULL-user-parameter preservation. | @@ -763,7 +763,7 @@ even if it already compiles or has indirect test coverage. | TODO | ORIG+FIX? | not yet classified | `src/nwnss/library/wio/wWrapString.c` | Must be compared against original source and classified. | | TODO | ORIG+FIX? | not yet classified | `src/nwnss/library/wio/waprintf.c` | Must be compared against original source and classified. | | TODO | ORIG+FIX? | not yet classified | `src/nwnss/library/wio/wgetpos.c` | Must be compared against original source and classified. | -| AUDITED | ORIG+FIX/PORT | nwnss.wio | `src/nwnss/library/wio/wio.c` | Compared with original `public_core/library/wio/wio.c`; Linux/userspace screen I/O branch kept minimal and no-op friendly. Differences are include-path normalization, pssmpk visibility for userspace, whitespace cleanup and low-level output routed through host stdio-compatible helpers; tests cover printf/aprintf/wPrintf/wAPrintf/vprintf wrappers, fixed cursor fallback, wrap path and nonblocking key path. | +| AUDITED | ORIG+FIX/PORT | nwnss.wio | `src/nwnss/library/wio/wio.c` | Compared with original `public_core/library/wio/wio.c`; Linux/userspace screen I/O branch is intentionally minimal and no-op friendly. The non-Linux NetWare screen/key/pause logic is kept behind the original guard, while Linux/userspace output routes through host stdio-compatible helpers and preserves the MPKNSS lock drop/reacquire boundary around console output. Tests cover printf/aprintf/wPrintf/wAPrintf/vprintf wrappers, fixed cursor fallback, wrap path and nonblocking key path. | | TODO | ORIG+FIX? | not yet classified | `src/nwnss/library/wio/wpause.c` | Must be compared against original source and classified. | | TODO | ORIG+FIX? | not yet classified | `src/nwnss/library/wio/wprintf.c` | Must be compared against original source and classified. | | TODO | ORIG+FIX? | not yet classified | `src/nwnss/library/wio/wsetpos.c` | Must be compared against original source and classified. | diff --git a/src/nwnss/library/os/nebEventPort.c b/src/nwnss/library/os/nebEventPort.c index 6129151..0c3dcf0 100644 --- a/src/nwnss/library/os/nebEventPort.c +++ b/src/nwnss/library/os/nebEventPort.c @@ -21,9 +21,11 @@ #include #include #include +#include #define MARS_NWE_NWNSS_NEB_MAX_CONSUMERS 128 #define MARS_NWE_NWNSS_NEB_MAX_PRODUCERS 128 +#define MARS_NWE_NWNSS_NEB_MAX_FILTERS 64 #define MARS_NWE_NWNSS_NEB_NAME_LEN 128 struct NwnssNebConsumer @@ -37,6 +39,7 @@ struct NwnssNebConsumer LONG (*esr)(struct EventBlock *eventBlock); char consumerName[MARS_NWE_NWNSS_NEB_NAME_LEN]; char eventName[MARS_NWE_NWNSS_NEB_NAME_LEN]; + char filterName[MARS_NWE_NWNSS_NEB_NAME_LEN]; }; struct NwnssNebProducer @@ -52,12 +55,22 @@ struct NwnssNebProducer char eventName[MARS_NWE_NWNSS_NEB_NAME_LEN]; }; +struct NwnssNebFilter +{ + int used; + void *filterID; + LONG (*esr)(struct EventBlock *eventBlock); + char filterName[MARS_NWE_NWNSS_NEB_NAME_LEN]; +}; + static pthread_mutex_t nwnssNebLock = PTHREAD_MUTEX_INITIALIZER; static struct NwnssNebConsumer nwnssNebConsumers[MARS_NWE_NWNSS_NEB_MAX_CONSUMERS]; static struct NwnssNebProducer nwnssNebProducers[MARS_NWE_NWNSS_NEB_MAX_PRODUCERS]; +static struct NwnssNebFilter nwnssNebFilters[MARS_NWE_NWNSS_NEB_MAX_FILTERS]; static uintptr_t nwnssNebNextConsumerID = 1; static uintptr_t nwnssNebNextProducerID = 1; static uintptr_t nwnssNebNextEventID = 1; +static uintptr_t nwnssNebNextFilterID = 1; static struct NwnssNebProducer *findProducerByID(void *producerID) @@ -96,6 +109,36 @@ static struct NwnssNebConsumer *findConsumerByID(void *consumerID) return NULL; } +static struct NwnssNebFilter *findFilterByID(void *filterID) +{ + for (unsigned i = 0; i < MARS_NWE_NWNSS_NEB_MAX_FILTERS; ++i) + { + if (nwnssNebFilters[i].used && nwnssNebFilters[i].filterID == filterID) + { + return &nwnssNebFilters[i]; + } + } + return NULL; +} + +static struct NwnssNebFilter *findFilterByName(const BYTE *filterName) +{ + if (filterName == NULL) + { + return NULL; + } + + for (unsigned i = 0; i < MARS_NWE_NWNSS_NEB_MAX_FILTERS; ++i) + { + if (nwnssNebFilters[i].used && + strcmp(nwnssNebFilters[i].filterName, (const char *)filterName) == 0) + { + return &nwnssNebFilters[i]; + } + } + return NULL; +} + static int eventNameMatches(const struct NwnssNebConsumer *consumer, const struct EventBlock *eventBlock) { @@ -119,6 +162,109 @@ static int eventNameMatches(const struct NwnssNebConsumer *consumer, return eventBlock->EBUserParameter == consumer->userParameter; } +struct EventBlock *GetEventBlocks(void *ownerID, LONG numberOfEventBlocksToGet) +{ + struct EventBlock *blocks; + + (void)ownerID; + + if (numberOfEventBlocksToGet <= 0) + { + return NULL; + } + + blocks = zalloc((size_t)numberOfEventBlocksToGet * sizeof(*blocks)); + if (blocks == NULL) + { + return NULL; + } + + for (LONG i = 0; i < numberOfEventBlocksToGet; ++i) + { + blocks[i].EBVersion = NEB_EVENT_VERSION1; + blocks[i].EBStamp = EVENT_BLOCK_STAMP; + if (i + 1 < numberOfEventBlocksToGet) + { + blocks[i].EBILink = &blocks[i + 1]; + } + } + + return blocks; +} + +LONG ReturnEventBlocks(struct EventBlock *eventBlock) +{ + if (eventBlock == NULL) + { + return INVALID_PARAMETER; + } + + free(eventBlock); + return SUCCESS; +} + +LONG RegisterFilter(struct FilterRegistrationInfo *regFilter) +{ + if (regFilter == NULL || + regFilter->FRIFilterName == NULL || + regFilter->FRIFilterID != NULL) + { + return INVALID_PARAMETER; + } + + pthread_mutex_lock(&nwnssNebLock); + + if (findFilterByName(regFilter->FRIFilterName) != NULL) + { + pthread_mutex_unlock(&nwnssNebLock); + return DUPLICATE_FILTER; + } + + for (unsigned i = 0; i < MARS_NWE_NWNSS_NEB_MAX_FILTERS; ++i) + { + struct NwnssNebFilter *entry = &nwnssNebFilters[i]; + if (!entry->used) + { + memset(entry, 0, sizeof(*entry)); + entry->used = 1; + entry->filterID = (void *)nwnssNebNextFilterID++; + if (entry->filterID == NULL) + { + entry->filterID = (void *)nwnssNebNextFilterID++; + } + entry->esr = regFilter->FRIFilterESR; + snprintf(entry->filterName, sizeof(entry->filterName), "%s", + (const char *)regFilter->FRIFilterName); + regFilter->FRIFilterID = entry->filterID; + pthread_mutex_unlock(&nwnssNebLock); + return SUCCESS; + } + } + + pthread_mutex_unlock(&nwnssNebLock); + return OUT_OF_RESOURCES; +} + +LONG UnRegisterFilter(void *filterID) +{ + if (filterID == NULL) + { + return INVALID_PARAMETER; + } + + pthread_mutex_lock(&nwnssNebLock); + struct NwnssNebFilter *entry = findFilterByID(filterID); + if (entry == NULL) + { + pthread_mutex_unlock(&nwnssNebLock); + return INVALID_PARAMETER; + } + + memset(entry, 0, sizeof(*entry)); + pthread_mutex_unlock(&nwnssNebLock); + return SUCCESS; +} + LONG RegisterProducer(struct ProducerRegistrationInfo *regProducer) { if (regProducer == NULL || @@ -285,6 +431,11 @@ LONG RegisterConsumer(struct ConsumerRegistrationInfo *regConsumer) snprintf(entry->eventName, sizeof(entry->eventName), "%s", (const char *)regConsumer->CRIEventName); } + if (regConsumer->CRIFilterName != NULL) + { + snprintf(entry->filterName, sizeof(entry->filterName), "%s", + (const char *)regConsumer->CRIFilterName); + } regConsumer->CRIConsumerID = entry->consumerID; pthread_mutex_unlock(&nwnssNebLock); return SUCCESS; @@ -387,6 +538,7 @@ LONG ProduceEvent(struct EventBlock *eventBlock) for (unsigned i = 0; i < count; ++i) { LONG callbackStatus = EVENT_NOT_CONSUMED; + eventBlock->EBConsumingConsumer = snapshot[i].consumerID; if (snapshot[i].callback != NULL) { diff --git a/src/nwnss/library/wio/wio.c b/src/nwnss/library/wio/wio.c index 3157a50..a16c839 100644 --- a/src/nwnss/library/wio/wio.c +++ b/src/nwnss/library/wio/wio.c @@ -389,7 +389,6 @@ void LB__wioOutput( #include #include -#include /************************************************************************** * This is the LOW LEVEL write routine that outputs the given data diff --git a/tests/nwnss/neb/test_nwnss_neb.c b/tests/nwnss/neb/test_nwnss_neb.c index f8af2f0..9d639f4 100644 --- a/tests/nwnss/neb/test_nwnss_neb.c +++ b/tests/nwnss/neb/test_nwnss_neb.c @@ -11,6 +11,7 @@ static void *lastConsumingConsumer; static char callOrder[8]; static int orderIndex; static int esrCount; +static int filterCount; static LONG nebTestCallback(struct EventBlock *eventBlock) { @@ -48,6 +49,12 @@ static LONG nebEsrCallback(struct EventBlock *eventBlock) return EVENT_CONSUMED; } +static LONG nebFilterCallback(struct EventBlock *eventBlock) +{ + ++filterCount; + return eventBlock->EBShortData.B32[0] == 99 ? EVENT_CONSUMED : EVENT_NOT_CONSUMED; +} + static void fillReg(struct ConsumerRegistrationInfo *reg, const char *consumerName, const char *eventName, @@ -286,6 +293,78 @@ static int testProducerRegistrationAndZosMacros(void) return rc; } +static int testEventBlocksAndFilters(void) +{ + struct EventBlock *blocks; + struct FilterRegistrationInfo filter; + struct FilterRegistrationInfo duplicate; + struct ConsumerRegistrationInfo consumer; + struct EventBlock eventBlock; + void *eventID = (void *)0x7777; + int rc = 0; + + if (GetEventBlocks(NULL, 0) != NULL) + return 60; + + blocks = GetEventBlocks(NULL, 2); + if (blocks == NULL) + return 61; + if (blocks[0].EBVersion != NEB_EVENT_VERSION1 || + blocks[0].EBStamp != EVENT_BLOCK_STAMP || + blocks[0].EBILink != &blocks[1] || + blocks[1].EBILink != NULL) + rc = 62; + if (ReturnEventBlocks(blocks) != SUCCESS && rc == 0) + rc = 63; + if (ReturnEventBlocks(NULL) != (LONG)INVALID_PARAMETER && rc == 0) + rc = 64; + + memset(&filter, 0, sizeof(filter)); + filter.FRIVersion = NEB_FILTER_VERSION1; + filter.FRIFilterName = (BYTE *)"nwnss.neb.filter"; + filter.FRIFilterESR = nebFilterCallback; + if (RegisterFilter(&filter) != SUCCESS && rc == 0) + rc = 65; + if (filter.FRIFilterID == NULL && rc == 0) + rc = 66; + + memset(&duplicate, 0, sizeof(duplicate)); + duplicate.FRIVersion = NEB_FILTER_VERSION1; + duplicate.FRIFilterName = (BYTE *)"nwnss.neb.filter"; + if (RegisterFilter(&duplicate) != (LONG)DUPLICATE_FILTER && rc == 0) + rc = 67; + + fillReg(&consumer, "nwnss.neb.filtered", "NSS.Test.Filtered", eventID, + SYNCHRONOUS_CONSUMER, 0, nebTestCallback, NULL); + consumer.CRIFilterName = (BYTE *)"nwnss.neb.filter"; + if (RegisterConsumer(&consumer) != SUCCESS && rc == 0) + rc = 68; + + memset(&eventBlock, 0, sizeof(eventBlock)); + eventBlock.EBUserParameter = eventID; + eventBlock.EBShortData.B32[0] = 99; + callbackCount = 0; + filterCount = 0; + lastShortData = 0; + if (ProduceEvent(&eventBlock) != SUCCESS && rc == 0) + rc = 69; + else if (filterCount != 0 && rc == 0) + rc = 70; + else if (callbackCount != 1 && rc == 0) + rc = 71; + else if (lastShortData != 99 && rc == 0) + rc = 72; + + if (UnRegisterConsumer(consumer.CRIConsumerID, eventID) != SUCCESS && rc == 0) + rc = 73; + if (UnRegisterFilter(filter.FRIFilterID) != SUCCESS && rc == 0) + rc = 74; + if (UnRegisterFilter(filter.FRIFilterID) != (LONG)INVALID_PARAMETER && rc == 0) + rc = 75; + + return rc; +} + int main(void) { int rc; @@ -296,6 +375,10 @@ int main(void) return 101; if (GetConsumerName(NULL, NULL) != (LONG)INVALID_PARAMETER) return 102; + if (RegisterFilter(NULL) != (LONG)INVALID_PARAMETER) + return 103; + if (UnRegisterFilter(NULL) != (LONG)INVALID_PARAMETER) + return 104; rc = testBasicRegisterNameDispatch(); if (rc != 0) @@ -313,5 +396,9 @@ int main(void) if (rc != 0) return rc; + rc = testEventBlocksAndFilters(); + if (rc != 0) + return rc; + return 0; }