winverbs: delete critical sections when no longer needed
[mirror/winof/.git] / core / winmad / user / wm_provider.cpp
1 /*\r
2  * Copyright (c) 2008 Intel Corporation. All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenIB.org BSD license\r
5  * below:\r
6  *\r
7  *     Redistribution and use in source and binary forms, with or\r
8  *     without modification, are permitted provided that the following\r
9  *     conditions are met:\r
10  *\r
11  *      - Redistributions of source code must retain the above\r
12  *        copyright notice, this list of conditions and the following\r
13  *        disclaimer.\r
14  *\r
15  *      - Redistributions in binary form must reproduce the above\r
16  *        copyright notice, this list of conditions and the following\r
17  *        disclaimer in the documentation and/or other materials\r
18  *        provided with the distribution.\r
19  *\r
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV\r
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
24  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
25  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
26  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
27  * SOFTWARE.\r
28  */\r
29 \r
30 #include <windows.h>\r
31 #include <winioctl.h>\r
32 \r
33 #include "wm_memory.h"\r
34 #include "wm_provider.h"\r
35 #include "wm_ioctl.h"\r
36 \r
37 CWMProvider::CWMProvider()\r
38 {\r
39         InitializeCriticalSection(&m_CritSecRead);\r
40         InitializeCriticalSection(&m_CritSecWrite);\r
41         m_OverlapRead.hEvent = NULL;\r
42         m_OverlapWrite.hEvent = NULL;\r
43         m_nRef = 1;\r
44         m_hFile = INVALID_HANDLE_VALUE;\r
45         InterlockedIncrement(&WmRef);\r
46 }\r
47 \r
48 STDMETHODIMP CWMProvider::\r
49 Init(void)\r
50 {\r
51         m_OverlapRead.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\r
52         m_OverlapWrite.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\r
53 \r
54         return (m_OverlapRead.hEvent != NULL && m_OverlapWrite.hEvent != NULL) ?\r
55                         NOERROR : E_OUTOFMEMORY;\r
56 }\r
57 \r
58 CWMProvider::~CWMProvider()\r
59 {\r
60         if (m_OverlapRead.hEvent != NULL) {\r
61                 CloseHandle(m_OverlapWrite.hEvent);\r
62         }\r
63         if (m_OverlapWrite.hEvent != NULL) {\r
64                 CloseHandle(m_OverlapWrite.hEvent);\r
65         }\r
66         CloseHandle(m_hFile);\r
67         DeleteCriticalSection(&m_CritSecRead);\r
68         DeleteCriticalSection(&m_CritSecWrite);\r
69         InterlockedDecrement(&WmRef);\r
70 }\r
71 \r
72 STDMETHODIMP CWMProvider::\r
73 QueryInterface(REFIID riid, LPVOID FAR* ppvObj)\r
74 {\r
75         if (riid != IID_IUnknown && riid != IID_IWMProvider) {\r
76                 *ppvObj = NULL;\r
77                 return E_NOINTERFACE;\r
78         }\r
79 \r
80         *ppvObj = this;\r
81         AddRef();\r
82         return NOERROR;\r
83 }\r
84 \r
85 STDMETHODIMP_(ULONG) CWMProvider::\r
86 AddRef(void)\r
87 {\r
88         return InterlockedIncrement(&m_nRef);\r
89 }\r
90 \r
91 STDMETHODIMP_(ULONG) CWMProvider::\r
92 Release(void)\r
93 {\r
94         ULONG ref;\r
95 \r
96         ref = (ULONG) InterlockedDecrement(&m_nRef);\r
97         if (ref == 0) {\r
98                 Delete();\r
99         }\r
100         return ref;\r
101 }\r
102 \r
103 STDMETHODIMP CWMProvider::\r
104 CancelOverlappedRequests(void)\r
105 {\r
106         DWORD   bytes;\r
107 \r
108         return WmDeviceIoControl(m_hFile, WM_IOCTL_CANCEL, NULL, 0,\r
109                                                          NULL, 0, &bytes, NULL) ?\r
110                                                          NOERROR : HRESULT_FROM_WIN32(GetLastError());\r
111 }\r
112 \r
113 STDMETHODIMP CWMProvider::\r
114 GetOverlappedResult(OVERLAPPED *pOverlapped,\r
115                                         DWORD *pNumberOfBytesTransferred, BOOL bWait)\r
116 {\r
117         ::GetOverlappedResult(m_hFile, pOverlapped, pNumberOfBytesTransferred, bWait);\r
118         return (HRESULT) pOverlapped->Internal;\r
119 }\r
120 \r
121 STDMETHODIMP_(HANDLE) CWMProvider::\r
122 GetFileHandle(void)\r
123 {\r
124         return m_hFile;\r
125 }\r
126 \r
127 STDMETHODIMP_(BOOL) CWMProvider::\r
128 WmDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode,\r
129                                   LPVOID lpInBuffer, DWORD nInBufferSize,\r
130                                   LPVOID lpOutBuffer, DWORD nOutBufferSize,\r
131                                   LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)\r
132 {\r
133         BOOL ret;\r
134 \r
135         if (lpOverlapped == NULL) {\r
136                 EnterCriticalSection(&m_CritSecWrite);\r
137                 DeviceIoControl(hDevice, dwIoControlCode,\r
138                                                 lpInBuffer, nInBufferSize,\r
139                                                 lpOutBuffer, nOutBufferSize,\r
140                                                 lpBytesReturned, &m_OverlapWrite);\r
141                 ret = ::GetOverlappedResult(m_hFile, &m_OverlapWrite, lpBytesReturned, TRUE);\r
142                 LeaveCriticalSection(&m_CritSecWrite);\r
143         } else {\r
144                 ret = DeviceIoControl(hDevice, dwIoControlCode,\r
145                                                           lpInBuffer, nInBufferSize,\r
146                                                           lpOutBuffer, nOutBufferSize,\r
147                                                           lpBytesReturned, lpOverlapped);\r
148         }\r
149 \r
150         return ret;\r
151 }\r
152 \r
153 STDMETHODIMP CWMProvider::\r
154 Register(WM_REGISTER *pAttributes, UINT64 *pId)\r
155 {\r
156         DWORD bytes;\r
157 \r
158         if (WmDeviceIoControl(m_hFile, WM_IOCTL_REGISTER,\r
159                                                   pAttributes, sizeof WM_REGISTER,\r
160                                                   pId, sizeof UINT64, &bytes, NULL)) {\r
161                 return NOERROR;\r
162         } else {\r
163                 return HRESULT_FROM_WIN32(GetLastError());\r
164         }\r
165 }\r
166 \r
167 STDMETHODIMP CWMProvider::\r
168 Deregister(UINT64 Id)\r
169 {\r
170         DWORD bytes;\r
171 \r
172         if (WmDeviceIoControl(m_hFile, WM_IOCTL_DEREGISTER,\r
173                                                   &Id, sizeof UINT64,\r
174                                                   NULL, 0, &bytes, NULL)) {\r
175                 return NOERROR;\r
176         } else {\r
177                 return HRESULT_FROM_WIN32(GetLastError());\r
178         }\r
179 }\r
180 \r
181 STDMETHODIMP CWMProvider::\r
182 Send(WM_MAD *pMad, OVERLAPPED *pOverlapped)\r
183 {\r
184         DWORD bytes;\r
185         HRESULT hr;\r
186 \r
187         bytes = (DWORD) sizeof(WM_MAD) + pMad->Length;\r
188         if (pOverlapped == NULL) {\r
189                 EnterCriticalSection(&m_CritSecWrite);\r
190                 WriteFile(m_hFile, pMad, bytes, &bytes, &m_OverlapWrite);\r
191                 hr = GetOverlappedResult(&m_OverlapWrite, &bytes, TRUE);\r
192                 LeaveCriticalSection(&m_CritSecWrite);\r
193         } else {\r
194                 if (WriteFile(m_hFile, pMad, bytes, &bytes, pOverlapped)) {\r
195                         hr = NOERROR;\r
196                 } else {\r
197                         hr = HRESULT_FROM_WIN32(GetLastError());\r
198                 }\r
199         }\r
200 \r
201         return hr;\r
202 }\r
203 \r
204 STDMETHODIMP CWMProvider::\r
205 Receive(WM_MAD *pMad, SIZE_T BufferSize, OVERLAPPED *pOverlapped)\r
206 {\r
207         DWORD bytes;\r
208         HRESULT hr;\r
209 \r
210         if (pOverlapped == NULL) {\r
211                 EnterCriticalSection(&m_CritSecRead);\r
212                 ReadFile(m_hFile, pMad, (DWORD) BufferSize, &bytes, &m_OverlapRead);\r
213                 hr = GetOverlappedResult(&m_OverlapRead, &bytes, TRUE);\r
214                 LeaveCriticalSection(&m_CritSecRead);\r
215         } else {\r
216                 if (ReadFile(m_hFile, pMad, (DWORD) BufferSize, &bytes, pOverlapped)) {\r
217                         hr = NOERROR;\r
218                 } else {\r
219                         hr = HRESULT_FROM_WIN32(GetLastError());\r
220                 }\r
221         }\r
222 \r
223         return hr;\r
224 }\r