--- /dev/null
+/*\r
+ * Copyright (c) 2005 Mellanox. All rights reserved.\r
+ */\r
+\r
+/*\r
+ This file includes two classes: One is used as a full refcount implmentation.\r
+\r
+ The second class is only the ref count interface. It should be used by abstract \r
+ classes.\r
+ \r
+*/\r
+\r
+\r
+class RefCountImpl {\r
+public :\r
+\r
+ RefCountImpl() {\r
+ m_ref = 1;\r
+ }\r
+\r
+ ULONG AddRef(void) {\r
+ ASSERT(m_ref > 0); \r
+ LONG result = InterlockedIncrement(&m_ref);\r
+ return (ULONG)result;\r
+ }\r
+\r
+ ULONG Release(void) { \r
+ ASSERT(m_ref > 0);\r
+ LONG result = InterlockedDecrement(&m_ref);\r
+ if ( result == 0 ) {\r
+ delete this;\r
+ }\r
+ return (ULONG)result; \r
+ }\r
+\r
+ virtual ~RefCountImpl() {};\r
+private :\r
+ long m_ref;\r
+};\r
+++ /dev/null
-/* Copyright mellanox 2005 */\r
-\r
-\r
-\r
-#define SDP_DEVICE_NAME L"\\Device\\SdpDriver"\r
-#define SDP_LINK_NAME L"\\DosDevices\\Global\\SdpDriver"\r
-\r
/* Copyright mellanox 2005 */\r
\r
+#ifndef _SDP_SHARED_H\r
+#define _SDP_SHARED_H\r
+\r
#define ProviderName L"SdpDriver"\r
\r
#define SDP_DEVICE_NAME L"\\Device\\"ProviderName\r
int Errno;\r
};\r
\r
+#endif //_SDP_SHARED_H
\ No newline at end of file
--- /dev/null
+/*\r
+ * Copyright (c) 2005 Mellanox. All rights reserved.\r
+ */\r
+\r
+\r
+#ifndef _SDP_PRECOMP_\r
+#define _SDP_PRECOMP_\r
+extern "C" {\r
+#include <NTDDK.h>\r
+}\r
+\r
+// External classes declrations\r
+class SdpSocket;\r
+\r
+\r
+#include "SdpTrace.h"\r
+#include "RefCount.h"\r
+#include "sdpdriver.h"\r
+#include "SdpShared.h"\r
+#include "SdpUserFile.h"\r
+#include "SdpGenUtils.h"\r
+#include "SdpSocket.h"\r
+\r
+\r
+#endif // _SDP_PRECOMP_\r
TARGETPATH=..\..\..\bin\kernel\obj$(BUILD_ALT_DIR)\r
TARGETTYPE=DRIVER\r
\r
-SOURCES= SdpDriver.cpp \\r
+SOURCES= SdpDriver.cpp \\r
+ SdpUserFile.cpp \\r
+ SdpGenUtils.cpp \\r
+ SdpSocket.cpp\r
\r
INCLUDES=..\include;..\..\..\inc;..\..\..\inc\kernel;\r
\r
/* Copyright mellanox */\r
\r
-extern "C" {\r
-#include <NTDDK.h>\r
-}\r
-#include "sdpdriver.h"\r
-#include "SdpShared.h"\r
-#include "SdpTrace.h"\r
+\r
+#include "Precompile.h"\r
\r
SdpDriver *g_pSdpDriver = NULL;\r
\r
PVOID pInputBuffer = NULL;\r
PVOID pOutputBuffer = NULL;\r
ULONG OutputDataSize = 0;\r
+ int Method;\r
+ SdpUserFile *pSdpUserFile = NULL;\r
\r
\r
\r
case IRP_MJ_CREATE: {\r
SDP_PRINT(SDP_TRACE, SDP_DRIVER, ("IRP_MJ_CREATE pIrpSp->FileObject = 0x%x\n", \r
pIrpSp->FileObject ));\r
+ pSdpUserFile = new SdpUserFile;\r
+ if (pSdpUserFile == NULL) {\r
+ rc = STATUS_NO_MEMORY;\r
+ SDP_PRINT(SDP_ERR, SDP_DRIVER, ("new SdpUserFile failed rc = 0x%x\n", rc )); \r
+ goto Cleanup;\r
+ } \r
+ rc = pSdpUserFile->Init();\r
+ if (!NT_SUCCESS(rc)) {\r
+ SDP_PRINT(SDP_ERR, SDP_DRIVER, ("pSdpUserFile->Init failed rc = 0x%x\n", rc )); \r
+ goto Cleanup;\r
+ }\r
+ // Everything went well, and windows is still using this object.\r
+ // As a result we want to make sure that this object will not be\r
+ // freed\r
+ pIrpSp->FileObject->FsContext = pSdpUserFile;\r
+ pSdpUserFile = NULL;\r
+ \r
\r
break;\r
}\r
// All IRPs that were associated with this device should be cleaned\r
SDP_PRINT(SDP_TRACE, SDP_DRIVER, ("IRP_MJ_CLEANUP pIrpSp->FileObject = 0x%x\n", \r
pIrpSp->FileObject ));\r
+ pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext;\r
+ // The object is being shutdown, and it's cleaning should\r
+ // be started\r
+ pSdpUserFile->Shutdown();\r
+ // The file object is still holding referance to the object,\r
+ // so we set the pointer to NULL\r
+ pSdpUserFile = NULL;\r
+ \r
break;\r
\r
}\r
//released. All outstanding I/O requests have been completed or canceled.\r
SDP_PRINT(SDP_TRACE, SDP_DRIVER, ("IRP_MJ_CLOSE pIrpSp->FileObject = 0x%x\n", \r
pIrpSp->FileObject ));\r
-\r
+ pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext;\r
+ // Nothing to do, the referance count will be removed once\r
+ // we leave the function\r
break;\r
}\r
case IRP_MJ_DEVICE_CONTROL: {\r
}\r
\r
// Handle the mode of the request and get it's params\r
+ Method = pIrpSp->Parameters.DeviceIoControl.IoControlCode & 0x3;\r
+ switch (Method) {\r
+ case METHOD_BUFFERED: {\r
+ pInputBuffer = pOutputBuffer = \r
+ pIrp->AssociatedIrp.SystemBuffer;\r
+ break;\r
+ }\r
+\r
+ case METHOD_IN_DIRECT:\r
+ case METHOD_OUT_DIRECT: {\r
+ pInputBuffer = pIrp->AssociatedIrp.SystemBuffer;\r
+ if (pIrp->MdlAddress && \r
+ pIrpSp->Parameters.DeviceIoControl.OutputBufferLength) {\r
+ if (NULL == (pOutputBuffer = \r
+ MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, LowPagePriority))) {\r
+ rc = STATUS_INSUFFICIENT_RESOURCES;\r
+ goto Cleanup;\r
+ }\r
+ }\r
+ break;\r
+ }\r
+\r
+ case METHOD_NEITHER: {\r
+ pInputBuffer = \r
+ pIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;\r
+ pOutputBuffer = pIrp->UserBuffer;\r
+ break;\r
+ }\r
+ }\r
+\r
+ // If 'METHOD_NEITHER' probe the buffer\r
+ if (METHOD_NEITHER == Method) {\r
+\r
+ __try {\r
+\r
+ if (pInputBuffer) {\r
+ ProbeForRead(\r
+ pInputBuffer, \r
+ pIrpSp->Parameters.DeviceIoControl.InputBufferLength,\r
+ sizeof(UCHAR)\r
+ );\r
+ }\r
+ if (pOutputBuffer) {\r
+ ProbeForWrite(\r
+ pOutputBuffer,\r
+ pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,\r
+ sizeof(UCHAR)\r
+ );\r
+ }\r
+\r
+ } __except(EXCEPTION_EXECUTE_HANDLER) {\r
+ rc = STATUS_ACCESS_VIOLATION;\r
+ SDP_PRINT(SDP_ERR, SDP_DRIVER, ("IRP_MJ_DEVICE_CONTROL Access "\r
+ "violition when trying to read/write data\n" ));\r
+ \r
+ ASSERT(FALSE);\r
+ goto Cleanup;\r
+ }\r
+ }\r
\r
\r
// Handle the request itself\r
rc = g_pSdpDriver->DispatchDeviceIoControl(\r
pIrpSp->FileObject,\r
pIrp,\r
+ pIrpSp,\r
pInputBuffer,\r
pIrpSp->Parameters.DeviceIoControl.InputBufferLength,\r
pOutputBuffer,\r
} \r
}\r
\r
+Cleanup:\r
if (rc != STATUS_PENDING) {\r
pIrp->IoStatus.Status = rc;\r
pIrp->IoStatus.Information = OutputDataSize;\r
IoCompleteRequest(pIrp, IO_NO_INCREMENT);\r
}\r
+ if (pSdpUserFile) {\r
+ pSdpUserFile->Release();\r
+ }\r
return rc;\r
}\r
\r
+// A macro to verify input/output params length\r
+#define VERIFY_BUFFERS(InputBufferLength, OutputBufferLength, InStruct, OutStruct) \\r
+if ((InputBufferLength < sizeof (InStruct)) || \\r
+ (OutputBufferLength < sizeof (OutStruct))) { \\r
+ SDP_PRINT(SDP_ERR, SDP_DRIVER, \\r
+ ("DispatchDeviceIoControl bad buffer sizes\n" )); \\r
+ ASSERT(FALSE); \\r
+ rc = STATUS_ACCESS_VIOLATION; \\r
+ goto Cleanup; \\r
+}\r
+\r
+\r
\r
NTSTATUS SdpDriver::DispatchDeviceIoControl(\r
IN PFILE_OBJECT pDeviceObject,\r
IN PIRP pIrp,\r
- PVOID pInputBuffer,\r
- ULONG InputBufferLength,\r
- PVOID pOutputBuffer,\r
- ULONG OutputBufferLength,\r
- ULONG IoControlCode,\r
- ULONG &OutputDataSize\r
+ IN PIO_STACK_LOCATION pIrpSp,\r
+ IN PVOID pInputBuffer,\r
+ IN ULONG InputBufferLength,\r
+ IN PVOID pOutputBuffer,\r
+ IN ULONG OutputBufferLength,\r
+ IN ULONG IoControlCode,\r
+ OUT ULONG &OutputDataSize\r
)\r
{\r
NTSTATUS rc = STATUS_SUCCESS;\r
+ SdpUserFile *pSdpUserFile = NULL;\r
+ SdpSocket *pSdpSocket = NULL;\r
+ \r
switch (IoControlCode) {\r
case IOCTL_WSP_SOCKET :\r
- SDP_PRINT(SDP_DEBUG, SDP_DRIVER, ("DispatchDeviceIoControl IOCTL_WSP_SOCKET recieved\n" )); \r
-\r
+ SDP_PRINT(SDP_DEBUG, SDP_DRIVER, ("DispatchDeviceIoControl IOCTL_WSP_SOCKET recieved\n" )); \r
+ VERIFY_BUFFERS(InputBufferLength, OutputBufferLength, WspSocketIn, WspSocketOut);\r
+ pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext;\r
+ pSdpSocket = new SdpSocket;\r
+ if (pSdpSocket == NULL) {\r
+ rc = STATUS_NO_MEMORY;\r
+ SDP_PRINT(SDP_ERR, SDP_DRIVER, ("new SdpSocket failed rc = 0x%x\n", rc )); \r
+ goto Cleanup;\r
+ }\r
+ rc = pSdpSocket->Init((WspSocketIn *)pInputBuffer, (WspSocketOut *)pOutputBuffer);\r
+ if (!NT_SUCCESS(rc)) {\r
+ SDP_PRINT(SDP_ERR, SDP_DRIVER, ("pSdpSocket->Init failed rc = 0x%x\n", rc )); \r
+ goto Cleanup;\r
+ }\r
+ rc = pSdpUserFile->AddSocket(pSdpSocket);\r
+ if (!NT_SUCCESS(rc)) {\r
+ SDP_PRINT(SDP_ERR, SDP_DRIVER, ("pSdpUserFile->AddSocket failed rc = 0x%x\n", rc )); \r
+ goto Cleanup;\r
+ }\r
\r
break;\r
+ \r
default:\r
// This is an unrecgnized IOCTL\r
ASSERT(FALSE);\r
\r
}\r
Cleanup:\r
+ if (pSdpSocket) {\r
+ pSdpSocket->Release();\r
+ }\r
return rc;\r
}\r
\r
NTSTATUS DispatchDeviceIoControl(\r
IN PFILE_OBJECT pDeviceObject,\r
IN PIRP pIrp,\r
- PVOID pInputBuffer,\r
- ULONG InputBufferLength,\r
- PVOID pOutputBuffer,\r
- ULONG OutputBufferLength,\r
- ULONG IoControlCode,\r
- ULONG &OutputDataSize\r
+ IN PIO_STACK_LOCATION pIrpSp,\r
+ IN PVOID pInputBuffer,\r
+ IN ULONG InputBufferLength,\r
+ IN PVOID pOutputBuffer,\r
+ IN ULONG OutputBufferLength,\r
+ IN ULONG IoControlCode,\r
+ OUT ULONG &OutputDataSize\r
);\r
\r
\r
--- /dev/null
+/* Copyright mellanox */\r
+\r
+#include "Precompile.h"\r
+\r
+\r
+\r
+void* __cdecl operator new(size_t n ) throw() {\r
+ return ExAllocatePoolWithTag(NonPagedPool , n, GLOBAL_ALLOCATION_TAG);\r
+}\r
+\r
+void __cdecl operator delete(void* p) {\r
+ ExFreePoolWithTag(p, GLOBAL_ALLOCATION_TAG);\r
+}\r
+\r
--- /dev/null
+/* Copyright mellanox */\r
+#ifndef _SDP_GEN_UTILS_H\r
+#define _SDP_GEN_UTILS_H\r
+\r
+\r
+\r
+#define GLOBAL_ALLOCATION_TAG ' pdS'\r
+\r
+\r
+class CSpinLockWrapper {\r
+ KSPIN_LOCK &m_SpinLock;\r
+ KIRQL m_OldIrql;\r
+\r
+public:\r
+\r
+ CSpinLockWrapper (KSPIN_LOCK &SpinLock) : m_SpinLock(SpinLock){\r
+ // Spinlock must already be initialized\r
+#if DBG\r
+ m_OldIrql = 0xff;\r
+#endif\r
+ }\r
+ \r
+ void Lock() {\r
+ ASSERT(m_OldIrql == 0xff);\r
+ KeAcquireSpinLock(&m_SpinLock, &m_OldIrql);\r
+ }\r
+\r
+ void Unlock() {\r
+ ASSERT(m_OldIrql != 0xff);\r
+ KeReleaseSpinLock(&m_SpinLock, m_OldIrql);\r
+#if DBG \r
+ m_OldIrql = 0xff;\r
+#endif\r
+ }\r
+\r
+ ~CSpinLockWrapper() {\r
+ ASSERT(m_OldIrql == 0xff);\r
+ }\r
+\r
+};\r
+\r
+#endif // _SDP_GEN_UTILS_H\r
--- /dev/null
+/* Copyright mellanox */\r
+\r
+\r
+#include "Precompile.h"\r
+\r
+NTSTATUS SdpSocket::Init(\r
+ WspSocketIn *pSocketInParam, \r
+ WspSocketOut *pSocketOutParam)\r
+{\r
+ SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("SdpSocket::Init this = 0x%x\n", this));\r
+\r
+ m_CreationFlags = pSocketInParam->dwFlags;\r
+ pSocketOutParam->Errno = 0;// No error\r
+ pSocketOutParam->pSocket = this; // give the user a handle to the socket\r
+ \r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+VOID SdpSocket::Shutdown()\r
+{\r
+ SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("SdpSocket::Shutdown called this = 0x%x\n", this));\r
+\r
+\r
+}\r
+\r
--- /dev/null
+/* Copyright mellanox */\r
+\r
+/*\r
+This class is being used to truck all the user objects that are being\r
+created per user mode dll (each dll opens a handle to the driver once)\r
+\r
+It keeps a list of all the objects so we know when to remove them.\r
+\r
+*/\r
+\r
+#ifndef _SDP_SOCKET_H\r
+#define _SDP_SOCKET_H\r
+\r
+\r
+class SdpSocket : public RefCountImpl {\r
+private: \r
+ // This flags are being Initiated when the socket is being\r
+ // created\r
+ ULONG m_CreationFlags;\r
+\r
+ \r
+public:\r
+ NTSTATUS Init(\r
+ WspSocketIn *pSocketInParam, \r
+ WspSocketOut *pSocketOutParam);\r
+\r
+ VOID Shutdown();\r
+\r
+\r
+ LIST_ENTRY m_UserFileList;\r
+};\r
+\r
+#endif // _SDP_SOCKET_H\r
+\r
#define SDP_ERR 0x00000010\r
\r
// Debug toppics\r
-#define SDP_API 0x000001\r
-#define SDP_CONNECT 0x000002\r
+#define SDP_API 0x000001\r
+#define SDP_CONNECT 0x000002\r
#define SDP_DRIVER 0x000004\r
+#define SDP_SOCKET 0x000008\r
\r
+// BUGBUG: CONVERT TO A FUNCTION\r
\r
-BOOLEAN CheckCondition(int sev, int top, char *file, int line) {\r
- return TRUE;\r
-}\r
+//BOOLEAN CheckCondition(int sev, int top, char *file, int line) {\r
+// return TRUE;\r
+//}\r
+#define CheckCondition(a,b,c,d) TRUE\r
\r
#define SDP_PRINT(sev, toppic ,var_args) \\r
if (CheckCondition(sev, toppic ,__FILE__, __LINE__) != FALSE) \\r
--- /dev/null
+/* Copyright mellanox */\r
+\r
+#include "Precompile.h"\r
+\r
+NTSTATUS SdpUserFile::Init()\r
+{\r
+ KeInitializeSpinLock(&m_Lock);\r
+ InitializeListHead(&m_SocketsList);\r
+ m_shutdown = false;\r
+\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+void SdpUserFile::Shutdown()\r
+{ \r
+ // go over the entire list, and release it's objects\r
+ CSpinLockWrapper Lock(m_Lock);\r
+ Lock.Lock();\r
+ if (m_shutdown) {\r
+ // Nothing to do\r
+ Lock.Unlock();\r
+ return;\r
+ }\r
+ while (!IsListEmpty(&m_SocketsList)) {\r
+ PLIST_ENTRY pTemp = RemoveHeadList(&m_SocketsList);\r
+ SdpSocket *pSdpSocket = CONTAINING_RECORD(pTemp, SdpSocket, m_UserFileList );\r
+\r
+ // Don't call release with the lock being hold\r
+ Lock.Unlock();\r
+ pSdpSocket->Shutdown();\r
+ pSdpSocket->Release();\r
+ // It seems that we shoule be protected by the m_shutdown\r
+ // flag, but will take the lock just in case\r
+ Lock.Lock();\r
+\r
+ }\r
+ Lock.Unlock();\r
+}\r
+\r
+NTSTATUS SdpUserFile::AddSocket(SdpSocket *pSdpSocket)\r
+{\r
+ CSpinLockWrapper Lock(m_Lock);\r
+ Lock.Lock();\r
+ if (m_shutdown) {\r
+ Lock.Unlock();\r
+ return STATUS_FILE_CLOSED;\r
+ }\r
+ InsertHeadList(&m_SocketsList, &pSdpSocket->m_UserFileList);\r
+ pSdpSocket->AddRef();\r
+ \r
+ Lock.Unlock();\r
+ return STATUS_SUCCESS;\r
+\r
+}\r
+\r
+\r
--- /dev/null
+/* Copyright mellanox */\r
+\r
+/*\r
+This class is being used to truck all the user objects that are being\r
+created per user mode dll (each dll opens a handle to the driver once)\r
+\r
+It keeps a list of all the objects so we know when to remove them.\r
+\r
+*/\r
+\r
+#ifndef _SDP_USER_FILE_H\r
+#define _SDP_USER_FILE_H\r
+\r
+\r
+\r
+class SdpUserFile : public RefCountImpl {\r
+private: \r
+ KSPIN_LOCK m_Lock;\r
+ bool m_shutdown;\r
+\r
+// BUGBUG: Use something more effiecent for this storage\r
+ LIST_ENTRY m_SocketsList; \r
+ \r
+public:\r
+\r
+ NTSTATUS Init();\r
+ VOID Shutdown();\r
+ \r
+ NTSTATUS AddSocket(SdpSocket *pSdpSocket);\r
+\r
+};\r
+\r
+#endif //_SDP_USER_FILE_H\r
+\r