Signed-off-by: Paul Gofman pgofman@codeweavers.com --- v3: - add stubs for all natively exported functions (taken from Windows 7 netio.sys version).
configure.ac | 1 + dlls/netio.sys/Makefile.in | 7 + dlls/netio.sys/netio.c | 48 +++++ dlls/netio.sys/netio.sys.spec | 391 ++++++++++++++++++++++++++++++++++ loader/wine.inf.in | 2 + 5 files changed, 449 insertions(+) create mode 100644 dlls/netio.sys/Makefile.in create mode 100644 dlls/netio.sys/netio.c create mode 100644 dlls/netio.sys/netio.sys.spec
diff --git a/configure.ac b/configure.ac index 83c451e0870..33a8a9a2888 100644 --- a/configure.ac +++ b/configure.ac @@ -3552,6 +3552,7 @@ WINE_CONFIG_MAKEFILE(dlls/netapi32) WINE_CONFIG_MAKEFILE(dlls/netapi32/tests) WINE_CONFIG_MAKEFILE(dlls/netcfgx) WINE_CONFIG_MAKEFILE(dlls/netcfgx/tests) +WINE_CONFIG_MAKEFILE(dlls/netio.sys) WINE_CONFIG_MAKEFILE(dlls/netprofm) WINE_CONFIG_MAKEFILE(dlls/netprofm/tests) WINE_CONFIG_MAKEFILE(dlls/newdev) diff --git a/dlls/netio.sys/Makefile.in b/dlls/netio.sys/Makefile.in new file mode 100644 index 00000000000..76e541021a6 --- /dev/null +++ b/dlls/netio.sys/Makefile.in @@ -0,0 +1,7 @@ +MODULE = netio.sys +IMPORTLIB = netio +IMPORTS = ntoskrnl +EXTRADLLFLAGS = -mno-cygwin -Wl,--subsystem,native + +C_SRCS = \ + netio.c diff --git a/dlls/netio.sys/netio.c b/dlls/netio.sys/netio.c new file mode 100644 index 00000000000..16bf47ca0a2 --- /dev/null +++ b/dlls/netio.sys/netio.c @@ -0,0 +1,48 @@ +/* + * WSK (Winsock Kernel) driver library. + * + * Copyright 2020 Paul Gofman pgofman@codeweavers.com for Codeweavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdarg.h> + +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winioctl.h" +#include "winternl.h" +#include "ddk/wdm.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(netio); + +static void WINAPI driver_unload(DRIVER_OBJECT *driver) +{ + TRACE("driver %p.\n", driver); +} + +NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *path) +{ + TRACE("driver %p, path %s.\n", driver, debugstr_w(path->Buffer)); + + driver->DriverUnload = driver_unload; + return STATUS_SUCCESS; +} + diff --git a/dlls/netio.sys/netio.sys.spec b/dlls/netio.sys/netio.sys.spec new file mode 100644 index 00000000000..a390f96674c --- /dev/null +++ b/dlls/netio.sys/netio.sys.spec @@ -0,0 +1,391 @@ +@ stub CancelMibChangeNotify2 +@ stub ConvertInterfaceAliasToLuid +@ stub ConvertInterfaceGuidToLuid +@ stub ConvertInterfaceIndexToLuid +@ stub ConvertInterfaceLuidToAlias +@ stub ConvertInterfaceLuidToGuid +@ stub ConvertInterfaceLuidToIndex +@ stub ConvertInterfaceLuidToNameA +@ stub ConvertInterfaceLuidToNameW +@ stub ConvertInterfaceNameToLuidA +@ stub ConvertInterfaceNameToLuidW +@ stub ConvertInterfacePhysicalAddressToLuid +@ stub ConvertStringToInterfacePhysicalAddress +@ stub CreateAnycastIpAddressEntry +@ stub CreateIpForwardEntry2 +@ stub CreateIpNetEntry2 +@ stub CreateSortedAddressPairs +@ stub CreateUnicastIpAddressEntry +@ stub DeleteAnycastIpAddressEntry +@ stub DeleteIpForwardEntry2 +@ stub DeleteIpNetEntry2 +@ stub DeleteUnicastIpAddressEntry +@ stub DllInitialize +@ stub DllUnload +@ stub FeAcquireClassifyHandle +@ stub FeAcquireWritableLayerDataPointer +@ stub FeApplyModifiedLayerData +@ stub FeCompleteClassify +@ stub FeGetWfpGlobalPtr +@ stub FePendClassify +@ stub FeReleaseCalloutContextList +@ stub FeReleaseClassifyHandle +@ stub FlushIpNetTable2 +@ stub FlushIpPathTable +@ stub FreeMibTable +@ stub FsbAllocate +@ stub FsbAllocateAtDpcLevel +@ stub FsbCreatePool +@ stub FsbDestroyPool +@ stub FsbFree +@ stub FwppAdvanceStreamDataPastOffset +@ stub FwppCopyStreamDataToBuffer +@ stub FwppStreamContinue +@ stub FwppStreamDeleteDpcQueue +@ stub FwppStreamInject +@ stub FwppTruncateStreamDataAfterOffset +@ stub GetAnycastIpAddressEntry +@ stub GetAnycastIpAddressTable +@ stub GetBestInterface +@ stub GetBestInterfaceEx +@ stub GetBestRoute2 +@ stub GetIfEntry2 +@ stub GetIfStackTable +@ stub GetIfTable2 +@ stub GetIfTable2Ex +@ stub GetInvertedIfStackTable +@ stub GetIpForwardEntry2 +@ stub GetIpForwardTable2 +@ stub GetIpInterfaceEntry +@ stub GetIpInterfaceTable +@ stub GetIpNetEntry2 +@ stub GetIpNetTable2 +@ stub GetIpPathEntry +@ stub GetIpPathTable +@ stub GetMulticastIpAddressEntry +@ stub GetMulticastIpAddressTable +@ stub GetTeredoPort +@ stub GetUnicastIpAddressEntry +@ stub GetUnicastIpAddressTable +@ stub HfAllocateHandle32 +@ stub HfCreateFactory +@ stub HfDestroyFactory +@ stub HfFreeHandle32 +@ stub HfGetPointerFromHandle32 +@ stub HfResumeHandle32 +@ stub HfSuspendHandle32 +@ stub if_indextoname +@ stub if_nametoindex +@ stub InitializeIpForwardEntry +@ stub InitializeIpInterfaceEntry +@ stub InitializeUnicastIpAddressEntry +@ stub InternalCleanupPersistentStore +@ stub InternalCreateAnycastIpAddressEntry +@ stub InternalCreateIpForwardEntry2 +@ stub InternalCreateIpNetEntry2 +@ stub InternalCreateUnicastIpAddressEntry +@ stub InternalDeleteAnycastIpAddressEntry +@ stub InternalDeleteIpForwardEntry2 +@ stub InternalDeleteIpNetEntry2 +@ stub InternalDeleteUnicastIpAddressEntry +@ stub InternalFindInterfaceByAddress +@ stub InternalGetAnycastIpAddressEntry +@ stub InternalGetAnycastIpAddressTable +@ stub InternalGetForwardIpTable2 +@ stub InternalGetIfEntry2 +@ stub InternalGetIfTable2 +@ stub InternalGetIpForwardEntry2 +@ stub InternalGetIpInterfaceEntry +@ stub InternalGetIpInterfaceTable +@ stub InternalGetIpNetEntry2 +@ stub InternalGetIpNetTable2 +@ stub InternalGetMulticastIpAddressEntry +@ stub InternalGetMulticastIpAddressTable +@ stub InternalGetUnicastIpAddressEntry +@ stub InternalGetUnicastIpAddressTable +@ stub InternalSetIpForwardEntry2 +@ stub InternalSetIpInterfaceEntry +@ stub InternalSetIpNetEntry2 +@ stub InternalSetTeredoPort +@ stub InternalSetUnicastIpAddressEntry +@ stub IoctlKfdAbortTransaction +@ stub IoctlKfdAddCache +@ stub IoctlKfdAddIndex +@ stub IoctlKfdBatchUpdate +@ stub IoctlKfdBeginEnumFilters +@ stub IoctlKfdCommitTransaction +@ stub IoctlKfdDeleteCache +@ stub IoctlKfdDeleteIndex +@ stub IoctlKfdEndEnumFilters +@ stub IoctlKfdMoveFilter +@ stub IoctlKfdQueryEnumFilters +@ stub IoctlKfdQueryLayerStatistics +@ stub IoctlKfdResetState +@ stub KfdAddCalloutEntry +@ stub KfdAleAcquireFlowHandleForFlow +@ stub KfdAleGetTableFromHandle +@ stub KfdAleInitializeFlowHandles +@ stub KfdAleInitializeFlowTable +@ stub KfdAleNotifyFlowDeletion +@ stub KfdAleReleaseFlowHandleForFlow +@ stub KfdAleRemoveFlowContextTable +@ stub KfdAleUninitializeFlowHandles +@ stub KfdAleUpdateEndpointContextStatus +@ stub KfdCheckAcceptBypass +@ stub KfdCheckAndCacheAcceptBypass +@ stub KfdCheckAndCacheConnectBypass +@ stub KfdCheckClassifyNeededAndUpdateEpoch +@ stub KfdCheckConnectBypass +@ stub KfdClassify +@ stub KfdDeleteCalloutEntry +@ stub KfdDeRefCallout +@ stub KfdDerefFilterContext +@ stub KfdDeregisterLayerChangeCallback +@ stub KfdDeregisterLayerChangeCallback2 +@ stub KfdEnumLayer +@ stub KfdFreeEnumHandle +@ stub KfdGetLayerActionFromEnumTemplate +@ stub KfdGetLayerCacheEpoch +@ stub KfdGetNextFilter +@ stub KfdGetOffloadEpoch +@ stub KfdGetRefCallout +@ stub KfdIsActiveCallout +@ stub KfdIsLayerEmpty +@ stub KfdIsLsoOffloadPossibleV4 +@ stub KfdIsLsoOffloadPossibleV6 +@ stub KfdIsV4InTransportFastEmpty +@ stub KfdIsV4OutTransportFastEmpty +@ stub KfdIsV6InTransportFastEmpty +@ stub KfdIsV6OutTransportFastEmpty +@ stub KfdNotifyFlowDeletion +@ stub KfdQueryLayerStats +@ stub KfdRegisterLayerChangeCallback +@ stub KfdRegisterLayerChangeCallback2 +@ stub KfdToggleFilterActivation +@ stub MatchCondition +@ stub MdpAllocate +@ stub MdpAllocateAtDpcLevel +@ stub MdpCreatePool +@ stub MdpDestroyPool +@ stub MdpFree +@ stub NetioAdvanceNetBufferList +@ stub NetioAdvanceToLocationInNetBuffer +@ stub NetioAllocateAndInitializeStackBlock +@ stub NetioAllocateAndReferenceCloneNetBufferList +@ stub NetioAllocateAndReferenceCloneNetBufferListEx +@ stub NetioAllocateAndReferenceCopyNetBufferListEx +@ stub NetioAllocateAndReferenceFragmentNetBufferList +@ stub NetioAllocateAndReferenceNetBufferAndNetBufferList +@ stub NetioAllocateAndReferenceNetBufferList +@ stub NetioAllocateAndReferenceNetBufferListNetBufferMdlAndData +@ stub NetioAllocateAndReferenceReassembledNetBufferList +@ stub NetioAllocateAndReferenceVacantNetBufferList +@ stub NetioAllocateMdl +@ stub NetioAllocateNetBuffer +@ stub NetioAllocateNetBufferListNetBufferMdlAndDataPool +@ stub NetioAllocateNetBufferMdlAndData +@ stub NetioAllocateNetBufferMdlAndDataPool +@ stub NetioAllocateOpaquePerProcessorContext +@ stub NetioAssociateQoSFlowWithNbl +@ stub NetioCleanupNetBufferListInformation +@ stub NetioCompleteCloneNetBufferListChain +@ stub NetioCompleteCopyNetBufferListChain +@ stub NetioCompleteNetBufferAndNetBufferListChain +@ stub NetioCompleteNetBufferListChain +@ stub NetioCopyNetBufferListInformation +@ stub NetioCreateQoSFlow +@ stub NetioDeleteQoSFlow +@ stub NetioDereferenceNetBufferList +@ stub NetioDereferenceNetBufferListChain +@ stub NetioExpandNetBuffer +@ stub NetioExtendNetBuffer +@ stub NetioFreeCloneNetBufferList +@ stub NetioFreeCopyNetBufferList +@ stub NetioFreeMdl +@ stub NetioFreeNetBuffer +@ stub NetioFreeNetBufferAndNetBufferList +@ stub NetioFreeNetBufferList +@ stub NetioFreeNetBufferListNetBufferMdlAndDataPool +@ stub NetioFreeNetBufferMdlAndDataPool +@ stub NetioFreeOpaquePerProcessorContext +@ stub NetioFreeStackBlock +@ stub NetioGetStatsForQoSFlow +@ stub NetioInitializeMdl +@ stub NetioInitializeNetBufferListAndFirstNetBufferContext +@ stub NetioInitializeNetBufferListContext +@ stub NetioInitializeNetBufferListContextPrimitive +@ stub NetioInitializeNetBufferListLibrary +@ stub NetioInitializeWorkQueue +@ stub NetioInsertWorkQueue +@ stub NetioQueryNetBufferListTrafficClass +@ stub NetioReferenceNetBufferList +@ stub NetioReferenceNetBufferListChain +@ stub NetioRegisterProcessorAddCallback +@ stub NetioRegSyncDefaultChangeHandler +@ stub NetioRegSyncInterface +@ stub NetioRegSyncQueryAndUpdateKeyValue +@ stub NetioRetreatNetBuffer +@ stub NetioRetreatNetBufferList +@ stub NetioShutdownWorkQueue +@ stub NetioSqmInitialize +@ stub NetioSqmTerminate +@ stub NetioSqmWriteEvent +@ stub NetioStackBlockProcessorAddHandler +@ stub NetioUnInitializeNetBufferListLibrary +@ stub NetioUnRegisterProcessorAddCallback +@ stub NetioUpdateNetBufferListContext +@ stub NetioValidateNetBuffer +@ stub NetioValidateNetBufferList +@ stub NmrClientAttachProvider +@ stub NmrClientDetachProviderComplete +@ stub NmrDeregisterClient +@ stub NmrDeregisterProvider +@ stub NmrProviderDetachClientComplete +@ stub NmrRegisterClient +@ stub NmrRegisterProvider +@ stub NmrWaitForClientDeregisterComplete +@ stub NmrWaitForProviderDeregisterComplete +@ stub NotifyIpInterfaceChange +@ stub NotifyRouteChange2 +@ stub NotifyStableUnicastIpAddressTable +@ stub NotifyTeredoPortChange +@ stub NotifyUnicastIpAddressChange +@ stub NsiAllocateAndGetTable +@ stub NsiClearPersistentSetting +@ stub NsiDeregisterChangeNotification +@ stub NsiDeregisterChangeNotificationEx +@ stub NsiDeregisterLegacyHandler +@ stub NsiEnumerateObjectsAllParameters +@ stub NsiEnumerateObjectsAllParametersEx +@ stub NsiEnumerateObjectsAllPersistentParametersWithMask +@ stub NsiFreeTable +@ stub NsiGetAllParameters +@ stub NsiGetAllParametersEx +@ stub NsiGetAllPersistentParametersWithMask +@ stub NsiGetModuleHandle +@ stub NsiGetObjectSecurity +@ stub NsiGetParameter +@ stub NsiGetParameterEx +@ stub NsiReferenceDefaultObjectSecurity +@ stub NsiRegisterChangeNotification +@ stub NsiRegisterChangeNotificationEx +@ stub NsiRegisterLegacyHandler +@ stub NsiResetPersistentSetting +@ stub NsiSetAllParameters +@ stub NsiSetAllParametersEx +@ stub NsiSetAllPersistentParametersWithMask +@ stub NsiSetObjectSecurity +@ stub NsiSetParameter +@ stub NsiSetParameterEx +@ stub PtCheckTable +@ stub PtCreateTable +@ stub PtDeleteEntry +@ stub PtDestroyTable +@ stub PtEnumOverTable +@ stub PtGetData +@ stub PtGetExactMatch +@ stub PtGetKey +@ stub PtGetLongestMatch +@ stub PtGetNextShorterMatch +@ stub PtGetNumNodes +@ stub PtInsertEntry +@ stub PtSetData +@ stub ResolveIpNetEntry2 +@ stub RtlAllocateDummyMdlChain +@ stub RtlCleanupTimerWheel +@ stub RtlCleanupTimerWheelEntry +@ stub RtlCleanupToeplitzHash +@ stub RtlCompute37Hash +@ stub RtlComputeToeplitzHash +@ stub RtlCopyBufferToMdl +@ stub RtlCopyMdlToBuffer +@ stub RtlCopyMdlToMdl +@ stub RtlCopyMdlToMdlIndirect +@ stub RtlDeleteElementGenericTableBasicAvl +@ stub RtlEndTimerWheelEnumeration +@ stub RtlEnumerateNextTimerWheelEntry +@ stub RtlFreeDummyMdlChain +@ stub RtlGetNextExpirationTimerWheelTick +@ stub RtlGetNextExpiredTimerWheelEntry +@ stub RtlIndicateTimerWheelEntryTimerStart +@ stub RtlInitializeTimerWheel +@ stub RtlInitializeTimerWheelEntry +@ stub RtlInitializeTimerWheelEnumeration +@ stub RtlInitializeToeplitzHash +@ stub RtlInsertElementGenericTableBasicAvl +@ stub RtlInvalidateExpiredTimerWheelEntryTimers +@ stub RtlInvokeStartRoutines +@ stub RtlInvokeStopRoutines +@ stub RtlIsTimerWheelSuspended +@ stub RtlResumeTimerWheel +@ stub RtlReturnTimerWheelEntry +@ stub RtlSuspendTimerWheel +@ stub RtlUpdateCurrentTimerWheelTick +@ stub SetIpForwardEntry2 +@ stub SetIpInterfaceEntry +@ stub SetIpNetEntry2 +@ stub SetUnicastIpAddressEntry +@ stub SetWfpDeviceObject +@ stub TlDefaultEventAbort +@ stub TlDefaultEventConnect +@ stub TlDefaultEventDisconnect +@ stub TlDefaultEventError +@ stub TlDefaultEventInspect +@ stub TlDefaultEventNotify +@ stub TlDefaultEventReceive +@ stub TlDefaultEventReceiveMessages +@ stub TlDefaultEventSendBacklog +@ stub TlDefaultRequestCancel +@ stub TlDefaultRequestCloseEndpoint +@ stub TlDefaultRequestConnect +@ stub TlDefaultRequestDisconnect +@ stub TlDefaultRequestEndpoint +@ stub TlDefaultRequestIoControl +@ stub TlDefaultRequestIoControlEndpoint +@ stub TlDefaultRequestListen +@ stub TlDefaultRequestMessage +@ stub TlDefaultRequestQueryDispatch +@ stub TlDefaultRequestQueryDispatchEndpoint +@ stub TlDefaultRequestReceive +@ stub TlDefaultRequestReleaseIndicationList +@ stub TlDefaultRequestResume +@ stub TlDefaultRequestSend +@ stub TlDefaultRequestSendMessages +@ stub WfpAssociateContextToFlow +@ stub WfpDeleteEntryLru +@ stub WfpExpireEntryLru +@ stub WfpGetPacketTagCount +@ stub WfpInitializeLeastRecentlyUsedList +@ stub WfpInsertEntryLru +@ stub WfpMacInboundShim +@ stub WfpMacOutboundShim +@ stub WfpNblInfoAlloc +@ stub WfpNblInfoCleanup +@ stub WfpNblInfoClone +@ stub WfpNblInfoDestroyIfUnused +@ stub WfpNblInfoDispatchTableClear +@ stub WfpNblInfoDispatchTableSet +@ stub WfpNblInfoGet +@ stub WfpNblInfoInit +@ stub WfpNblInfoSet +@ stub WfpPacketTagCountIncrement +@ stub WfpProcessFlowDelete +@ stub WfpRefreshEntryLru +@ stub WfpRemoveContextFromFlow +@ stub WfpScavangeLeastRecentlyUsedList +@ stub WfpSetBucketsToEmptyLru +@ stub WfpStartMacShim +@ stub WfpStartStreamShim +@ stub WfpStopStreamShim +@ stub WfpStreamEndpointCleanupBegin +@ stub WfpStreamInspectDisconnect +@ stub WfpStreamInspectReceive +@ stub WfpStreamInspectRemoteDisconnect +@ stub WfpStreamInspectSend +@ stub WfpStreamIsFilterPresent +@ stub WfpUninitializeLeastRecentlyUsedList +@ stub WskCaptureProviderNPI +@ stub WskDeregister +@ stub WskQueryProviderCharacteristics +@ stub WskRegister +@ stub WskReleaseProviderNPI diff --git a/loader/wine.inf.in b/loader/wine.inf.in index 0a43cc779cb..de0dd4e4554 100644 --- a/loader/wine.inf.in +++ b/loader/wine.inf.in @@ -2617,6 +2617,7 @@ HKLM,%CurrentVersion%\Telephony\Country List\998,"SameAreaRule",,"G" 12,,ksecdd.sys,- 12,,mountmgr.sys,- 12,,ndis.sys,- +12,,netio.sys,- 12,,scsiport.sys,- 12,,tdi.sys,- 12,,usbd.sys,- @@ -2673,6 +2674,7 @@ HKLM,%CurrentVersion%\Telephony\Country List\998,"SameAreaRule",,"G" 12,,ksecdd.sys 12,,mountmgr.sys 12,,ndis.sys +12,,netio.sys 12,,scsiport.sys 12,,tdi.sys 12,,usbd.sys
From: Alistair Leslie-Hughes leslie_alistair@hotmail.com
Minor edits applied to original patch.
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- include/Makefile.in | 1 + include/ddk/wsk.h | 116 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 include/ddk/wsk.h
diff --git a/include/Makefile.in b/include/Makefile.in index 9796dd8e5d9..01dc4dbe6cf 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -186,6 +186,7 @@ SOURCES = \ ddk/usbioctl.h \ ddk/usbiodef.h \ ddk/wdm.h \ + ddk/wsk.h \ ddk/winddiui.h \ ddk/winsplp.h \ ddraw.h \ diff --git a/include/ddk/wsk.h b/include/ddk/wsk.h new file mode 100644 index 00000000000..c7100bb7997 --- /dev/null +++ b/include/ddk/wsk.h @@ -0,0 +1,116 @@ +/* + * Copyright 2020 Alistair Leslie-Hughes + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#ifndef _INC_WSK +#define _INC_WSK + +#include <winsock2.h> + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct _WSK_CLIENT; +typedef struct _WSK_CLIENT WSK_CLIENT, *PWSK_CLIENT; +typedef struct _WSK_CLIENT_CONNECTION_DISPATCH WSK_CLIENT_CONNECTION_DISPATCH, *PWSK_CLIENT_CONNECTION_DISPATCH; + +typedef struct _WSK_BUF +{ + PMDL Mdl; + ULONG Offset; + SIZE_T Length; +} WSK_BUF, *PWSK_BUF; + +typedef struct _WSK_DATA_INDICATION +{ + struct _WSK_DATA_INDICATION *Next; + WSK_BUF Buffer; +} WSK_DATA_INDICATION, *PWSK_DATA_INDICATION; + +typedef NTSTATUS (WINAPI *PFN_WSK_CLIENT_EVENT)(void *context, ULONG event, void *info, SIZE_T length); +typedef NTSTATUS (WINAPI *PFN_WSK_DISCONNECT_EVENT)(void *context, ULONG flags); +typedef NTSTATUS (WINAPI *PFN_WSK_SEND_BACKLOG_EVENT)(void *socket_context, SIZE_T ideal_backlog_size); +typedef NTSTATUS (WINAPI *PFN_WSK_SOCKET)(WSK_CLIENT *client, ADDRESS_FAMILY family, + USHORT type, ULONG protocol, ULONG flags, void *context, const void *dispatch, + PEPROCESS process, PETHREAD thread, SECURITY_DESCRIPTOR *security, IRP *irp); +typedef NTSTATUS (WINAPI *PFN_WSK_SOCKET_CONNECT)(WSK_CLIENT *client, USHORT type, + ULONG protocol, SOCKADDR *local, SOCKADDR *remote, ULONG flags, void *context, + const WSK_CLIENT_CONNECTION_DISPATCH *dispatch, PEPROCESS process, PETHREAD owning, + SECURITY_DESCRIPTOR *descriptor, IRP *irp); +typedef NTSTATUS (WINAPI *PFN_WSK_CONTROL_CLIENT)(WSK_CLIENT *client, ULONG control, + SIZE_T input_size, void *input, SIZE_T output_size, void *output, SIZE_T *returned, + IRP *irp); +typedef NTSTATUS (WINAPI *PFN_WSK_GET_ADDRESS_INFO)(WSK_CLIENT *client, UNICODE_STRING *node_name, + UNICODE_STRING *service_name, ULONG name_space, GUID *provider, ADDRINFOEXW *hints, + ADDRINFOEXW **result, PEPROCESS process, PETHREAD thread, IRP *irp); +typedef void (WINAPI *PFN_WSK_FREE_ADDRESS_INFO)(WSK_CLIENT *client, ADDRINFOEXW *addrinfo); +typedef NTSTATUS (WINAPI *PFN_WSK_GET_NAME_INFO)(WSK_CLIENT *client, SOCKADDR *addr, + ULONG length, UNICODE_STRING *node_name, UNICODE_STRING *service_name, + ULONG flags, PEPROCESS process, PETHREAD thread, IRP *irp); +typedef NTSTATUS (WINAPI* PFN_WSK_RECEIVE_EVENT)(void *context, ULONG flags, + WSK_DATA_INDICATION *indication, SIZE_T size, SIZE_T *accepted); + +typedef struct _WSK_PROVIDER_DISPATCH +{ + USHORT Version; + USHORT Reserved; + PFN_WSK_SOCKET WskSocket; + PFN_WSK_SOCKET_CONNECT WskSocketConnect; + PFN_WSK_CONTROL_CLIENT WskControlClient; + PFN_WSK_GET_ADDRESS_INFO WskGetAddressInfo; + PFN_WSK_FREE_ADDRESS_INFO WskFreeAddressInfo; + PFN_WSK_GET_NAME_INFO WskGetNameInfo; +} WSK_PROVIDER_DISPATCH, *PWSK_PROVIDER_DISPATCH; + +typedef struct _WSK_CLIENT_CONNECTION_DISPATCH +{ + PFN_WSK_RECEIVE_EVENT WskReceiveEvent; + PFN_WSK_DISCONNECT_EVENT WskDisconnectEvent; + PFN_WSK_SEND_BACKLOG_EVENT WskSendBacklogEvent; +} WSK_CLIENT_CONNECTION_DISPATCH, *PWSK_CLIENT_CONNECTION_DISPATCH; + +typedef struct _WSK_CLIENT_DISPATCH +{ + USHORT Version; + USHORT Reserved; + PFN_WSK_CLIENT_EVENT WskClientEvent; +} WSK_CLIENT_DISPATCH, *PWSK_CLIENT_DISPATCH; + +typedef struct _WSK_CLIENT_NPI +{ + void *ClientContext; + const WSK_CLIENT_DISPATCH *Dispatch; +} WSK_CLIENT_NPI, *PWSK_CLIENT_NPI; + +typedef struct _WSK_REGISTRATION +{ + ULONGLONG ReservedRegistrationState; + void *ReservedRegistrationContext; + KSPIN_LOCK ReservedRegistrationLock; +} WSK_REGISTRATION, *PWSK_REGISTRATION; + +typedef struct _WSK_PROVIDER_NPI +{ + PWSK_CLIENT Client; + const WSK_PROVIDER_DISPATCH *Dispatch; +} WSK_PROVIDER_NPI, *PWSK_PROVIDER_NPI; + +#ifdef __cplusplus +} +#endif +#endif
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/netio.sys/netio.c | 8 ++++++++ dlls/netio.sys/netio.sys.spec | 2 +- include/ddk/wsk.h | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/dlls/netio.sys/netio.c b/dlls/netio.sys/netio.c index 16bf47ca0a2..fdb32c1dd9a 100644 --- a/dlls/netio.sys/netio.c +++ b/dlls/netio.sys/netio.c @@ -29,10 +29,18 @@ #include "winioctl.h" #include "winternl.h" #include "ddk/wdm.h" +#include "ddk/wsk.h" #include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(netio);
+NTSTATUS WINAPI WskRegister(WSK_CLIENT_NPI *wsk_client_npi, WSK_REGISTRATION *wsk_registration) +{ + FIXME("wsk_client_npi %p, wsk_registration %p stub.\n", wsk_client_npi, wsk_registration); + + return STATUS_NOT_IMPLEMENTED; +} + static void WINAPI driver_unload(DRIVER_OBJECT *driver) { TRACE("driver %p.\n", driver); diff --git a/dlls/netio.sys/netio.sys.spec b/dlls/netio.sys/netio.sys.spec index a390f96674c..d886ab8db9e 100644 --- a/dlls/netio.sys/netio.sys.spec +++ b/dlls/netio.sys/netio.sys.spec @@ -387,5 +387,5 @@ @ stub WskCaptureProviderNPI @ stub WskDeregister @ stub WskQueryProviderCharacteristics -@ stub WskRegister +@ stdcall WskRegister(ptr ptr) @ stub WskReleaseProviderNPI diff --git a/include/ddk/wsk.h b/include/ddk/wsk.h index c7100bb7997..835adbba9dc 100644 --- a/include/ddk/wsk.h +++ b/include/ddk/wsk.h @@ -110,6 +110,8 @@ typedef struct _WSK_PROVIDER_NPI const WSK_PROVIDER_DISPATCH *Dispatch; } WSK_PROVIDER_NPI, *PWSK_PROVIDER_NPI;
+NTSTATUS WINAPI WskRegister(WSK_CLIENT_NPI *wsk_client_npi, WSK_REGISTRATION *wsk_registration); + #ifdef __cplusplus } #endif
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/netio.sys/netio.c | 5 +++++ dlls/netio.sys/netio.sys.spec | 2 +- include/ddk/wsk.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/dlls/netio.sys/netio.c b/dlls/netio.sys/netio.c index fdb32c1dd9a..d3448fced81 100644 --- a/dlls/netio.sys/netio.c +++ b/dlls/netio.sys/netio.c @@ -41,6 +41,11 @@ NTSTATUS WINAPI WskRegister(WSK_CLIENT_NPI *wsk_client_npi, WSK_REGISTRATION *ws return STATUS_NOT_IMPLEMENTED; }
+void WINAPI WskDeregister(WSK_REGISTRATION *wsk_registration) +{ + FIXME("wsk_registration %p stub.\n", wsk_registration); +} + static void WINAPI driver_unload(DRIVER_OBJECT *driver) { TRACE("driver %p.\n", driver); diff --git a/dlls/netio.sys/netio.sys.spec b/dlls/netio.sys/netio.sys.spec index d886ab8db9e..915259c6f4d 100644 --- a/dlls/netio.sys/netio.sys.spec +++ b/dlls/netio.sys/netio.sys.spec @@ -385,7 +385,7 @@ @ stub WfpStreamIsFilterPresent @ stub WfpUninitializeLeastRecentlyUsedList @ stub WskCaptureProviderNPI -@ stub WskDeregister +@ stdcall WskDeregister(ptr) @ stub WskQueryProviderCharacteristics @ stdcall WskRegister(ptr ptr) @ stub WskReleaseProviderNPI diff --git a/include/ddk/wsk.h b/include/ddk/wsk.h index 835adbba9dc..e990d054bd7 100644 --- a/include/ddk/wsk.h +++ b/include/ddk/wsk.h @@ -111,6 +111,7 @@ typedef struct _WSK_PROVIDER_NPI } WSK_PROVIDER_NPI, *PWSK_PROVIDER_NPI;
NTSTATUS WINAPI WskRegister(WSK_CLIENT_NPI *wsk_client_npi, WSK_REGISTRATION *wsk_registration); +void WINAPI WskDeregister(WSK_REGISTRATION *wsk_registration);
#ifdef __cplusplus }
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/netio.sys/netio.c | 9 +++++++++ dlls/netio.sys/netio.sys.spec | 2 +- include/ddk/wsk.h | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/dlls/netio.sys/netio.c b/dlls/netio.sys/netio.c index d3448fced81..16e09bd08fb 100644 --- a/dlls/netio.sys/netio.c +++ b/dlls/netio.sys/netio.c @@ -34,6 +34,15 @@
WINE_DEFAULT_DEBUG_CHANNEL(netio);
+NTSTATUS WINAPI WskCaptureProviderNPI(WSK_REGISTRATION *wsk_registration, ULONG wait_timeout, + WSK_PROVIDER_NPI *wsk_provider_npi) +{ + FIXME("wsk_registration %p, wait_timeout %u, wsk_provider_npi %p stub.\n", + wsk_registration, wait_timeout, wsk_provider_npi); + + return STATUS_NOT_IMPLEMENTED; +} + NTSTATUS WINAPI WskRegister(WSK_CLIENT_NPI *wsk_client_npi, WSK_REGISTRATION *wsk_registration) { FIXME("wsk_client_npi %p, wsk_registration %p stub.\n", wsk_client_npi, wsk_registration); diff --git a/dlls/netio.sys/netio.sys.spec b/dlls/netio.sys/netio.sys.spec index 915259c6f4d..53891a7d275 100644 --- a/dlls/netio.sys/netio.sys.spec +++ b/dlls/netio.sys/netio.sys.spec @@ -384,7 +384,7 @@ @ stub WfpStreamInspectSend @ stub WfpStreamIsFilterPresent @ stub WfpUninitializeLeastRecentlyUsedList -@ stub WskCaptureProviderNPI +@ stdcall WskCaptureProviderNPI(ptr long ptr) @ stdcall WskDeregister(ptr) @ stub WskQueryProviderCharacteristics @ stdcall WskRegister(ptr ptr) diff --git a/include/ddk/wsk.h b/include/ddk/wsk.h index e990d054bd7..ead8f830a22 100644 --- a/include/ddk/wsk.h +++ b/include/ddk/wsk.h @@ -112,6 +112,8 @@ typedef struct _WSK_PROVIDER_NPI
NTSTATUS WINAPI WskRegister(WSK_CLIENT_NPI *wsk_client_npi, WSK_REGISTRATION *wsk_registration); void WINAPI WskDeregister(WSK_REGISTRATION *wsk_registration); +NTSTATUS WINAPI WskCaptureProviderNPI(WSK_REGISTRATION *wsk_registration, ULONG wait_timeout, + WSK_PROVIDER_NPI *wsk_provider_npi);
#ifdef __cplusplus }
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/netio.sys/netio.c | 5 +++++ dlls/netio.sys/netio.sys.spec | 2 +- include/ddk/wsk.h | 1 + 3 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/dlls/netio.sys/netio.c b/dlls/netio.sys/netio.c index 16e09bd08fb..ac34b765a8b 100644 --- a/dlls/netio.sys/netio.c +++ b/dlls/netio.sys/netio.c @@ -43,6 +43,11 @@ NTSTATUS WINAPI WskCaptureProviderNPI(WSK_REGISTRATION *wsk_registration, ULONG return STATUS_NOT_IMPLEMENTED; }
+void WINAPI WskReleaseProviderNPI(WSK_REGISTRATION *wsk_registration) +{ + FIXME("wsk_registration %p stub.\n", wsk_registration); +} + NTSTATUS WINAPI WskRegister(WSK_CLIENT_NPI *wsk_client_npi, WSK_REGISTRATION *wsk_registration) { FIXME("wsk_client_npi %p, wsk_registration %p stub.\n", wsk_client_npi, wsk_registration); diff --git a/dlls/netio.sys/netio.sys.spec b/dlls/netio.sys/netio.sys.spec index 53891a7d275..facd8ab9996 100644 --- a/dlls/netio.sys/netio.sys.spec +++ b/dlls/netio.sys/netio.sys.spec @@ -388,4 +388,4 @@ @ stdcall WskDeregister(ptr) @ stub WskQueryProviderCharacteristics @ stdcall WskRegister(ptr ptr) -@ stub WskReleaseProviderNPI +@ stdcall WskReleaseProviderNPI(ptr) diff --git a/include/ddk/wsk.h b/include/ddk/wsk.h index ead8f830a22..d19da999be8 100644 --- a/include/ddk/wsk.h +++ b/include/ddk/wsk.h @@ -114,6 +114,7 @@ NTSTATUS WINAPI WskRegister(WSK_CLIENT_NPI *wsk_client_npi, WSK_REGISTRATION *ws void WINAPI WskDeregister(WSK_REGISTRATION *wsk_registration); NTSTATUS WINAPI WskCaptureProviderNPI(WSK_REGISTRATION *wsk_registration, ULONG wait_timeout, WSK_PROVIDER_NPI *wsk_provider_npi); +void WINAPI WskReleaseProviderNPI(WSK_REGISTRATION *wsk_registration);
#ifdef __cplusplus }
ndis.sys links to netio.sys on newer Windows. Adding the dependency now is needed to get libnetio.cross.a built to be usable in ntoskrnl.exe test drivers.
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ndis.sys/Makefile.in | 1 + dlls/ntoskrnl.exe/tests/driver4.c | 0 dlls/ntoskrnl.exe/tests/driver4.spec | 1 + 3 files changed, 2 insertions(+) create mode 100644 dlls/ntoskrnl.exe/tests/driver4.c create mode 100644 dlls/ntoskrnl.exe/tests/driver4.spec
diff --git a/dlls/ndis.sys/Makefile.in b/dlls/ndis.sys/Makefile.in index cc522606258..70e6bb2afdf 100644 --- a/dlls/ndis.sys/Makefile.in +++ b/dlls/ndis.sys/Makefile.in @@ -1,4 +1,5 @@ MODULE = ndis.sys +IMPORTS = ntoskrnl netio EXTRADLLFLAGS = -Wl,--subsystem,native
EXTRADLLFLAGS = -mno-cygwin diff --git a/dlls/ntoskrnl.exe/tests/driver4.c b/dlls/ntoskrnl.exe/tests/driver4.c new file mode 100644 index 00000000000..e69de29bb2d diff --git a/dlls/ntoskrnl.exe/tests/driver4.spec b/dlls/ntoskrnl.exe/tests/driver4.spec new file mode 100644 index 00000000000..ad33444716a --- /dev/null +++ b/dlls/ntoskrnl.exe/tests/driver4.spec @@ -0,0 +1 @@ +# nothing here yet
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntoskrnl.exe/tests/driver.c | 140 +-------------------------- dlls/ntoskrnl.exe/tests/utils.h | 161 +++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+), 138 deletions(-) create mode 100644 dlls/ntoskrnl.exe/tests/utils.h
diff --git a/dlls/ntoskrnl.exe/tests/driver.c b/dlls/ntoskrnl.exe/tests/driver.c index f51064986b5..b3865fea0d9 100644 --- a/dlls/ntoskrnl.exe/tests/driver.c +++ b/dlls/ntoskrnl.exe/tests/driver.c @@ -35,6 +35,8 @@
#include "driver.h"
+#include "utils.h" + static const WCHAR device_name[] = {'\','D','e','v','i','c','e', '\','W','i','n','e','T','e','s','t','D','r','i','v','e','r',0}; static const WCHAR upper_name[] = {'\','D','e','v','i','c','e', @@ -45,17 +47,6 @@ static const WCHAR driver_link[] = {'\','D','o','s','D','e','v','i','c','e','s' static DRIVER_OBJECT *driver_obj; static DEVICE_OBJECT *lower_device, *upper_device;
-static HANDLE okfile; -static LONG successes; -static LONG failures; -static LONG skipped; -static LONG todo_successes; -static LONG todo_failures; -static int todo_level, todo_do_loop; -static int running_under_wine; -static int winetest_debug; -static int winetest_report_success; - static POBJECT_TYPE *pExEventObjectType, *pIoFileObjectType, *pPsThreadType, *pIoDriverObjectType; static PEPROCESS *pPsInitialSystemProcess; static void *create_caller_thread; @@ -64,133 +55,6 @@ static PETHREAD create_irp_thread;
NTSTATUS WINAPI ZwQueryInformationProcess(HANDLE,PROCESSINFOCLASS,void*,ULONG,ULONG*);
-static void kvprintf(const char *format, __ms_va_list ap) -{ - static char buffer[512]; - IO_STATUS_BLOCK io; - int len = vsnprintf(buffer, sizeof(buffer), format, ap); - ZwWriteFile(okfile, NULL, NULL, NULL, &io, buffer, len, NULL, NULL); -} - -static void WINAPIV kprintf(const char *format, ...) -{ - __ms_va_list valist; - - __ms_va_start(valist, format); - kvprintf(format, valist); - __ms_va_end(valist); -} - -static void WINAPIV vok_(const char *file, int line, int condition, const char *msg, __ms_va_list args) -{ - const char *current_file; - - if (!(current_file = drv_strrchr(file, '/')) && - !(current_file = drv_strrchr(file, '\'))) - current_file = file; - else - current_file++; - - if (todo_level) - { - if (condition) - { - kprintf("%s:%d: Test succeeded inside todo block: ", current_file, line); - kvprintf(msg, args); - InterlockedIncrement(&todo_failures); - } - else - { - if (winetest_debug > 0) - { - kprintf("%s:%d: Test marked todo: ", current_file, line); - kvprintf(msg, args); - } - InterlockedIncrement(&todo_successes); - } - } - else - { - if (!condition) - { - kprintf("%s:%d: Test failed: ", current_file, line); - kvprintf(msg, args); - InterlockedIncrement(&failures); - } - else - { - if (winetest_report_success) - kprintf("%s:%d: Test succeeded\n", current_file, line); - InterlockedIncrement(&successes); - } - } -} - -static void WINAPIV ok_(const char *file, int line, int condition, const char *msg, ...) -{ - __ms_va_list args; - __ms_va_start(args, msg); - vok_(file, line, condition, msg, args); - __ms_va_end(args); -} - -static void vskip_(const char *file, int line, const char *msg, __ms_va_list args) -{ - const char *current_file; - - if (!(current_file = drv_strrchr(file, '/')) && - !(current_file = drv_strrchr(file, '\'))) - current_file = file; - else - current_file++; - - kprintf("%s:%d: Tests skipped: ", current_file, line); - kvprintf(msg, args); - skipped++; -} - -static void WINAPIV win_skip_(const char *file, int line, const char *msg, ...) -{ - __ms_va_list args; - __ms_va_start(args, msg); - if (running_under_wine) - vok_(file, line, 0, msg, args); - else - vskip_(file, line, msg, args); - __ms_va_end(args); -} - -static void winetest_start_todo( int is_todo ) -{ - todo_level = (todo_level << 1) | (is_todo != 0); - todo_do_loop=1; -} - -static int winetest_loop_todo(void) -{ - int do_loop=todo_do_loop; - todo_do_loop=0; - return do_loop; -} - -static void winetest_end_todo(void) -{ - todo_level >>= 1; -} - -static int broken(int condition) -{ - return !running_under_wine && condition; -} - -#define ok(condition, ...) ok_(__FILE__, __LINE__, condition, __VA_ARGS__) -#define todo_if(is_todo) for (winetest_start_todo(is_todo); \ - winetest_loop_todo(); \ - winetest_end_todo()) -#define todo_wine todo_if(running_under_wine) -#define todo_wine_if(is_todo) todo_if((is_todo) && running_under_wine) -#define win_skip(...) win_skip_(__FILE__, __LINE__, __VA_ARGS__) - static void *get_proc_address(const char *name) { UNICODE_STRING name_u; diff --git a/dlls/ntoskrnl.exe/tests/utils.h b/dlls/ntoskrnl.exe/tests/utils.h new file mode 100644 index 00000000000..8b09bff1d39 --- /dev/null +++ b/dlls/ntoskrnl.exe/tests/utils.h @@ -0,0 +1,161 @@ +/* + * ntoskrnl.exe testing framework + * + * Copyright 2015 Sebastian Lackner + * Copyright 2015 Michael Müller + * Copyright 2015 Christian Costa + * Copyright 2020 Paul Gofman for Codeweavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +static HANDLE okfile; +static LONG successes; +static LONG failures; +static LONG skipped; +static LONG todo_successes; +static LONG todo_failures; +static int todo_level, todo_do_loop; +static int running_under_wine; +static int winetest_debug; +static int winetest_report_success; + +static inline void kvprintf(const char *format, __ms_va_list ap) +{ + static char buffer[512]; + IO_STATUS_BLOCK io; + int len = vsnprintf(buffer, sizeof(buffer), format, ap); + ZwWriteFile(okfile, NULL, NULL, NULL, &io, buffer, len, NULL, NULL); +} + +static inline void WINAPIV kprintf(const char *format, ...) +{ + __ms_va_list valist; + + __ms_va_start(valist, format); + kvprintf(format, valist); + __ms_va_end(valist); +} + +static inline void WINAPIV vok_(const char *file, int line, int condition, const char *msg, __ms_va_list args) +{ + const char *current_file; + + if (!(current_file = drv_strrchr(file, '/')) && + !(current_file = drv_strrchr(file, '\'))) + current_file = file; + else + current_file++; + + if (todo_level) + { + if (condition) + { + kprintf("%s:%d: Test succeeded inside todo block: ", current_file, line); + kvprintf(msg, args); + InterlockedIncrement(&todo_failures); + } + else + { + if (winetest_debug > 0) + { + kprintf("%s:%d: Test marked todo: ", current_file, line); + kvprintf(msg, args); + } + InterlockedIncrement(&todo_successes); + } + } + else + { + if (!condition) + { + kprintf("%s:%d: Test failed: ", current_file, line); + kvprintf(msg, args); + InterlockedIncrement(&failures); + } + else + { + if (winetest_report_success) + kprintf("%s:%d: Test succeeded\n", current_file, line); + InterlockedIncrement(&successes); + } + } +} + +static inline void WINAPIV ok_(const char *file, int line, int condition, const char *msg, ...) +{ + __ms_va_list args; + __ms_va_start(args, msg); + vok_(file, line, condition, msg, args); + __ms_va_end(args); +} + +static inline void vskip_(const char *file, int line, const char *msg, __ms_va_list args) +{ + const char *current_file; + + if (!(current_file = drv_strrchr(file, '/')) && + !(current_file = drv_strrchr(file, '\'))) + current_file = file; + else + current_file++; + + kprintf("%s:%d: Tests skipped: ", current_file, line); + kvprintf(msg, args); + skipped++; +} + +static inline void WINAPIV win_skip_(const char *file, int line, const char *msg, ...) +{ + __ms_va_list args; + __ms_va_start(args, msg); + if (running_under_wine) + vok_(file, line, 0, msg, args); + else + vskip_(file, line, msg, args); + __ms_va_end(args); +} + +static inline void winetest_start_todo( int is_todo ) +{ + todo_level = (todo_level << 1) | (is_todo != 0); + todo_do_loop=1; +} + +static inline int winetest_loop_todo(void) +{ + int do_loop=todo_do_loop; + todo_do_loop=0; + return do_loop; +} + +static inline void winetest_end_todo(void) +{ + todo_level >>= 1; +} + +static inline int broken(int condition) +{ + return !running_under_wine && condition; +} + +#define ok(condition, ...) ok_(__FILE__, __LINE__, condition, __VA_ARGS__) +#define todo_if(is_todo) for (winetest_start_todo(is_todo); \ + winetest_loop_todo(); \ + winetest_end_todo()) +#define todo_wine todo_if(running_under_wine) +#define todo_wine_if(is_todo) todo_if((is_todo) && running_under_wine) +#define win_skip(...) win_skip_(__FILE__, __LINE__, __VA_ARGS__) +
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- include/ddk/wsk.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/include/ddk/wsk.h b/include/ddk/wsk.h index d19da999be8..18a7de3b2c5 100644 --- a/include/ddk/wsk.h +++ b/include/ddk/wsk.h @@ -27,6 +27,8 @@ extern "C"
struct _WSK_CLIENT; typedef struct _WSK_CLIENT WSK_CLIENT, *PWSK_CLIENT; +#define MAKE_WSK_VERSION(major, minor) ((USHORT)((major) << 8) | (USHORT)((minor) & 0xff)) + typedef struct _WSK_CLIENT_CONNECTION_DISPATCH WSK_CLIENT_CONNECTION_DISPATCH, *PWSK_CLIENT_CONNECTION_DISPATCH;
typedef struct _WSK_BUF
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- include/ddk/wsk.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/include/ddk/wsk.h b/include/ddk/wsk.h index 18a7de3b2c5..a46eeadcc4b 100644 --- a/include/ddk/wsk.h +++ b/include/ddk/wsk.h @@ -28,6 +28,8 @@ extern "C" struct _WSK_CLIENT; typedef struct _WSK_CLIENT WSK_CLIENT, *PWSK_CLIENT; #define MAKE_WSK_VERSION(major, minor) ((USHORT)((major) << 8) | (USHORT)((minor) & 0xff)) +#define WSK_NO_WAIT 0 +#define WSK_INFINITE_WAIT 0xffffffff
typedef struct _WSK_CLIENT_CONNECTION_DISPATCH WSK_CLIENT_CONNECTION_DISPATCH, *PWSK_CLIENT_CONNECTION_DISPATCH;
Test driver should import netio.sys which is available since Vista, so a new test driver is needed to preserve XP compatibility for the existing tests.
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntoskrnl.exe/tests/Makefile.in | 4 + dlls/ntoskrnl.exe/tests/driver4.c | 249 ++++++++++++++++++++++++++++ dlls/ntoskrnl.exe/tests/ntoskrnl.c | 59 ++++++- 3 files changed, 304 insertions(+), 8 deletions(-)
diff --git a/dlls/ntoskrnl.exe/tests/Makefile.in b/dlls/ntoskrnl.exe/tests/Makefile.in index 7946b8de220..06c06671ca1 100644 --- a/dlls/ntoskrnl.exe/tests/Makefile.in +++ b/dlls/ntoskrnl.exe/tests/Makefile.in @@ -7,6 +7,8 @@ driver2_IMPORTS = winecrt0 ntoskrnl driver2_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native driver3_IMPORTS = winecrt0 ntoskrnl driver3_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native +driver4_IMPORTS = winecrt0 ntoskrnl netio +driver4_EXTRADLLFLAGS = -nodefaultlibs -nostartfiles -Wl,--subsystem,native
SOURCES = \ driver.c \ @@ -15,4 +17,6 @@ SOURCES = \ driver2.spec \ driver3.c \ driver3.spec \ + driver4.c \ + driver4.spec \ ntoskrnl.c diff --git a/dlls/ntoskrnl.exe/tests/driver4.c b/dlls/ntoskrnl.exe/tests/driver4.c index e69de29bb2d..10e583993e3 100644 --- a/dlls/ntoskrnl.exe/tests/driver4.c +++ b/dlls/ntoskrnl.exe/tests/driver4.c @@ -0,0 +1,249 @@ +/* + * ntoskrnl.exe testing framework + * + * Copyright 2020 Paul Gofman for Codeweavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdarg.h> +#include <stdio.h> + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" +#include "winternl.h" +#include "winioctl.h" +#include "ddk/ntddk.h" +#include "ddk/ntifs.h" +#include "ddk/wdm.h" +#include "ddk/wsk.h" + +#include "driver.h" + +#include "utils.h" + +static DRIVER_OBJECT *driver_obj; +static DEVICE_OBJECT *lower_device, *upper_device; + +static unsigned int create_count, close_count; + +static const WCHAR driver_link[] = L"\DosDevices\WineTestDriver4"; +static const WCHAR device_name[] = L"\Device\WineTestDriver4"; +static const WCHAR upper_name[] = L"\Device\WineTestUpper4"; + +static FILE_OBJECT *last_created_file; +static void *create_caller_thread; +static PETHREAD create_irp_thread; + +static POBJECT_TYPE *pIoDriverObjectType; + +static WSK_CLIENT_NPI client_npi; +static WSK_REGISTRATION registration; +static WSK_PROVIDER_NPI provider_npi; + +static void netio_init(void) +{ + const WSK_CLIENT_DISPATCH client_dispatch = + { + MAKE_WSK_VERSION(1, 0), 0, NULL + }; + + NTSTATUS status; + + client_npi.Dispatch = &client_dispatch; + status = WskRegister(&client_npi, ®istration); + todo_wine ok(status == STATUS_SUCCESS, "Got unexpected status %#x.\n", status); + + status = WskCaptureProviderNPI(®istration, WSK_INFINITE_WAIT, &provider_npi); + todo_wine ok(status == STATUS_SUCCESS, "Got unexpected status %#x.\n", status); +} + +static void netio_uninit(void) +{ + WskReleaseProviderNPI(®istration); + WskDeregister(®istration); +} + +static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *stack) +{ + ULONG length = stack->Parameters.DeviceIoControl.OutputBufferLength; + void *buffer = irp->AssociatedIrp.SystemBuffer; + struct test_input *test_input = buffer; + OBJECT_ATTRIBUTES attr = {0}; + UNICODE_STRING pathU; + IO_STATUS_BLOCK io; + + if (!buffer) + return STATUS_ACCESS_VIOLATION; + if (length < sizeof(failures)) + return STATUS_BUFFER_TOO_SMALL; + + attr.Length = sizeof(attr); + RtlInitUnicodeString(&pathU, test_input->path); + running_under_wine = test_input->running_under_wine; + winetest_debug = test_input->winetest_debug; + winetest_report_success = test_input->winetest_report_success; + attr.ObjectName = &pathU; + attr.Attributes = OBJ_KERNEL_HANDLE; /* needed to be accessible from system threads */ + ZwOpenFile(&okfile, FILE_APPEND_DATA | SYNCHRONIZE, &attr, &io, 0, FILE_SYNCHRONOUS_IO_NONALERT); + + netio_init(); + + if (winetest_debug) + { + kprintf("%04x:ntoskrnl: %d tests executed (%d marked as todo, %d %s), %d skipped.\n", + PsGetCurrentProcessId(), successes + failures + todo_successes + todo_failures, + todo_successes, failures + todo_failures, + (failures + todo_failures != 1) ? "failures" : "failure", skipped ); + } + ZwClose(okfile); + + *((LONG *)buffer) = failures; + irp->IoStatus.Status = STATUS_SUCCESS; + irp->IoStatus.Information = sizeof(failures); + IoCompleteRequest(irp, IO_NO_INCREMENT); + return STATUS_PENDING; +} + +static NTSTATUS WINAPI driver_iocontrol(DEVICE_OBJECT *device, IRP *irp) +{ + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); + NTSTATUS status = STATUS_NOT_SUPPORTED; + + switch (stack->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_WINETEST_MAIN_TEST: + status = main_test(device, irp, stack); + break; + case IOCTL_WINETEST_DETACH: + IoDetachDevice(lower_device); + status = STATUS_SUCCESS; + break; + default: + break; + } + + if (status != STATUS_PENDING) + { + irp->IoStatus.Status = status; + IoCompleteRequest(irp, IO_NO_INCREMENT); + } + else IoMarkIrpPending(irp); + return status; +} + +static NTSTATUS WINAPI driver_create(DEVICE_OBJECT *device, IRP *irp) +{ + IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); + DWORD *context = ExAllocatePool(PagedPool, sizeof(*context)); + + last_created_file = irpsp->FileObject; + ++create_count; + if (context) + *context = create_count; + irpsp->FileObject->FsContext = context; + create_caller_thread = KeGetCurrentThread(); + create_irp_thread = irp->Tail.Overlay.Thread; + + irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + +static NTSTATUS WINAPI driver_close(DEVICE_OBJECT *device, IRP *irp) +{ + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); + + netio_uninit(); + + ++close_count; + if (stack->FileObject->FsContext) + ExFreePool(stack->FileObject->FsContext); + irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; +} + +static VOID WINAPI driver_unload(DRIVER_OBJECT *driver) +{ + UNICODE_STRING linkW; + + DbgPrint("Unloading driver.\n"); + + RtlInitUnicodeString(&linkW, driver_link); + IoDeleteSymbolicLink(&linkW); + + IoDeleteDevice(upper_device); + IoDeleteDevice(lower_device); +} + +NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, PUNICODE_STRING registry) +{ + static const WCHAR IoDriverObjectTypeW[] = L"IoDriverObjectType"; + static const WCHAR driver_nameW[] = L"\Driver\WineTestDriver4"; + UNICODE_STRING nameW, linkW; + NTSTATUS status; + void *obj; + + DbgPrint("Loading driver.\n"); + + driver_obj = driver; + + driver->DriverUnload = driver_unload; + driver->MajorFunction[IRP_MJ_CREATE] = driver_create; + driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = driver_iocontrol; + driver->MajorFunction[IRP_MJ_CLOSE] = driver_close; + + RtlInitUnicodeString(&nameW, IoDriverObjectTypeW); + pIoDriverObjectType = MmGetSystemRoutineAddress(&nameW); + + RtlInitUnicodeString(&nameW, driver_nameW); + if ((status = ObReferenceObjectByName(&nameW, 0, NULL, 0, *pIoDriverObjectType, KernelMode, NULL, &obj))) + return status; + if (obj != driver) + { + ObDereferenceObject(obj); + return STATUS_UNSUCCESSFUL; + } + ObDereferenceObject(obj); + + RtlInitUnicodeString(&nameW, device_name); + RtlInitUnicodeString(&linkW, driver_link); + + if (!(status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN, + FILE_DEVICE_SECURE_OPEN, FALSE, &lower_device))) + { + status = IoCreateSymbolicLink(&linkW, &nameW); + lower_device->Flags &= ~DO_DEVICE_INITIALIZING; + } + + if (!status) + { + RtlInitUnicodeString(&nameW, upper_name); + + status = IoCreateDevice(driver, 0, &nameW, FILE_DEVICE_UNKNOWN, + FILE_DEVICE_SECURE_OPEN, FALSE, &upper_device); + } + + if (!status) + { + IoAttachDeviceToDeviceStack(upper_device, lower_device); + upper_device->Flags &= ~DO_DEVICE_INITIALIZING; + } + + return status; +} diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 8d2da92455a..c2afee3dfe9 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -109,17 +109,25 @@ static SC_HANDLE load_driver(char *filename, const char *resname, const char *dr return service; }
-static BOOL start_driver(HANDLE service) +static BOOL start_driver(HANDLE service, BOOL vista_plus) { SERVICE_STATUS status; BOOL ret;
SetLastError(0xdeadbeef); ret = StartServiceA(service, 0, NULL); - if (!ret && (GetLastError() == ERROR_DRIVER_BLOCKED || GetLastError() == ERROR_INVALID_IMAGE_HASH)) + if (!ret && (GetLastError() == ERROR_DRIVER_BLOCKED || GetLastError() == ERROR_INVALID_IMAGE_HASH + || (vista_plus && GetLastError() == ERROR_FILE_NOT_FOUND))) { - /* If Secure Boot is enabled or the machine is 64-bit, it will reject an unsigned driver. */ - skip("Failed to start service; probably your machine doesn't accept unsigned drivers.\n"); + if (vista_plus && GetLastError() == ERROR_FILE_NOT_FOUND) + { + skip("Windows Vista or newer is required to run this service.\n"); + } + else + { + /* If Secure Boot is enabled or the machine is 64-bit, it will reject an unsigned driver. */ + skip("Failed to start service; probably your machine doesn't accept unsigned drivers.\n"); + } DeleteService(service); CloseServiceHandle(service); return FALSE; @@ -143,13 +151,14 @@ static BOOL start_driver(HANDLE service) return TRUE; }
+static ULONG64 modified_value; + static void main_test(void) { static const WCHAR dokW[] = {'d','o','k',0}; WCHAR temppathW[MAX_PATH], pathW[MAX_PATH]; struct test_input *test_input; DWORD len, written, read; - ULONG64 modified_value; UNICODE_STRING pathU; LONG new_failures; char buffer[512]; @@ -178,8 +187,6 @@ static void main_test(void) ok(res, "DeviceIoControl failed: %u\n", GetLastError()); ok(written == sizeof(new_failures), "got size %x\n", written);
- todo_wine ok(modified_value == 0xdeadbeeffeedcafe, "Got unexpected value %#I64x.\n", modified_value); - okfile = CreateFileW(pathW, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); ok(okfile != INVALID_HANDLE_VALUE, "failed to create %s: %u\n", wine_dbgstr_w(pathW), GetLastError());
@@ -506,6 +513,37 @@ static void test_driver3(void) DeleteFileA(filename); }
+void test_driver4(void) +{ + char filename[MAX_PATH]; + SC_HANDLE service; + DWORD written; + BOOL ret; + + if (!(service = load_driver(filename, "driver4.dll", "WineTestDriver4"))) + return; + + if (!start_driver(service, TRUE)) + { + DeleteFileA(filename); + return; + } + + device = CreateFileA("\\.\WineTestDriver4", 0, 0, NULL, OPEN_EXISTING, 0, NULL); + ok(device != INVALID_HANDLE_VALUE, "failed to open device: %u\n", GetLastError()); + + main_test(); + + ret = DeviceIoControl(device, IOCTL_WINETEST_DETACH, NULL, 0, NULL, 0, &written, NULL); + ok(ret, "DeviceIoControl failed: %u\n", GetLastError()); + + CloseHandle(device); + + unload_driver(service); + ret = DeleteFileA(filename); + ok(ret, "DeleteFile failed: %u\n", GetLastError()); +} + START_TEST(ntoskrnl) { char filename[MAX_PATH], filename2[MAX_PATH]; @@ -523,7 +561,7 @@ START_TEST(ntoskrnl) subtest("driver"); if (!(service = load_driver(filename, "driver.dll", "WineTestDriver"))) return; - if (!start_driver(service)) + if (!start_driver(service, FALSE)) { DeleteFileA(filename); return; @@ -535,7 +573,10 @@ START_TEST(ntoskrnl)
test_basic_ioctl(); test_mismatched_status_ioctl(); + main_test(); + todo_wine ok(modified_value == 0xdeadbeeffeedcafe, "Got unexpected value %#I64x.\n", modified_value); + test_overlapped(); test_load_driver(service2); test_file_handles(); @@ -556,4 +597,6 @@ START_TEST(ntoskrnl) ok(ret, "DeleteFile failed: %u\n", GetLastError());
test_driver3(); + subtest("driver4"); + test_driver4(); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=72658
Your paranoid android.
=== w8 (testbot log) ===
An error occurred while waiting for the test to complete: the 2920 process does not exist or is not a child process