96c20da455a5657d53bda8e9517f4d41c3c2ec07
[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         InterlockedDecrement(&WmRef);\r
68 }\r
69 \r
70 STDMETHODIMP CWMProvider::\r
71 QueryInterface(REFIID riid, LPVOID FAR* ppvObj)\r
72 {\r
73         if (riid != IID_IUnknown && riid != IID_IWMProvider) {\r
74                 *ppvObj = NULL;\r
75                 return E_NOINTERFACE;\r
76         }\r
77 \r
78         *ppvObj = this;\r
79         AddRef();\r
80         return NOERROR;\r
81 }\r
82 \r
83 STDMETHODIMP_(ULONG) CWMProvider::\r
84 AddRef(void)\r
85 {\r
86         return InterlockedIncrement(&m_nRef);\r
87 }\r
88 \r
89 STDMETHODIMP_(ULONG) CWMProvider::\r
90 Release(void)\r
91 {\r
92         ULONG ref;\r
93 \r
94         ref = (ULONG) InterlockedDecrement(&m_nRef);\r
95         if (ref == 0) {\r
96                 Delete();\r
97         }\r
98         return ref;\r
99 }\r
100 \r
101 STDMETHODIMP CWMProvider::\r
102 CancelOverlappedRequests(void)\r
103 {\r
104         DWORD   bytes;\r
105 \r
106         return WmDeviceIoControl(m_hFile, WM_IOCTL_CANCEL, NULL, 0,\r
107                                                          NULL, 0, &bytes, NULL) ?\r
108                                                          NOERROR : HRESULT_FROM_WIN32(GetLastError());\r
109 }\r
110 \r
111 STDMETHODIMP CWMProvider::\r
112 GetOverlappedResult(OVERLAPPED *pOverlapped,\r
113                                         DWORD *pNumberOfBytesTransferred, BOOL bWait)\r
114 {\r
115         ::GetOverlappedResult(m_hFile, pOverlapped, pNumberOfBytesTransferred, bWait);\r
116         return (HRESULT) pOverlapped->Internal;\r
117 }\r
118 \r
119 STDMETHODIMP_(HANDLE) CWMProvider::\r
120 GetFileHandle(void)\r
121 {\r
122         return m_hFile;\r
123 }\r
124 \r
125 STDMETHODIMP_(BOOL) CWMProvider::\r
126 WmDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode,\r
127                                   LPVOID lpInBuffer, DWORD nInBufferSize,\r
128                                   LPVOID lpOutBuffer, DWORD nOutBufferSize,\r
129                                   LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped)\r
130 {\r
131         BOOL ret;\r
132 \r
133         if (lpOverlapped == NULL) {\r
134                 EnterCriticalSection(&m_CritSecWrite);\r
135                 DeviceIoControl(hDevice, dwIoControlCode,\r
136                                                 lpInBuffer, nInBufferSize,\r
137                                                 lpOutBuffer, nOutBufferSize,\r
138                                                 lpBytesReturned, &m_OverlapWrite);\r
139                 ret = ::GetOverlappedResult(m_hFile, &m_OverlapWrite, lpBytesReturned, TRUE);\r
140                 LeaveCriticalSection(&m_CritSecWrite);\r
141         } else {\r
142                 ret = DeviceIoControl(hDevice, dwIoControlCode,\r
143                                                           lpInBuffer, nInBufferSize,\r
144                                                           lpOutBuffer, nOutBufferSize,\r
145                                                           lpBytesReturned, lpOverlapped);\r
146         }\r
147 \r
148         return ret;\r
149 }\r
150 \r
151 STDMETHODIMP CWMProvider::\r
152 Register(WM_REGISTER *pAttributes, UINT64 *pId)\r
153 {\r
154         DWORD bytes;\r
155 \r
156         if (WmDeviceIoControl(m_hFile, WM_IOCTL_REGISTER,\r
157                                                   pAttributes, sizeof WM_REGISTER,\r
158                                                   pId, sizeof UINT64, &bytes, NULL)) {\r
159                 return NOERROR;\r
160         } else {\r
161                 return HRESULT_FROM_WIN32(GetLastError());\r
162         }\r
163 }\r
164 \r
165 STDMETHODIMP CWMProvider::\r
166 Deregister(UINT64 Id)\r
167 {\r
168         DWORD bytes;\r
169 \r
170         if (WmDeviceIoControl(m_hFile, WM_IOCTL_DEREGISTER,\r
171                                                   &Id, sizeof UINT64,\r
172                                                   NULL, 0, &bytes, NULL)) {\r
173                 return NOERROR;\r
174         } else {\r
175                 return HRESULT_FROM_WIN32(GetLastError());\r
176         }\r
177 }\r
178 \r
179 STDMETHODIMP CWMProvider::\r
180 Send(WM_MAD *pMad, OVERLAPPED *pOverlapped)\r
181 {\r
182         DWORD bytes;\r
183         HRESULT hr;\r
184 \r
185         bytes = (DWORD) sizeof(WM_MAD) + pMad->Length;\r
186         if (pOverlapped == NULL) {\r
187                 EnterCriticalSection(&m_CritSecWrite);\r
188                 WriteFile(m_hFile, pMad, bytes, &bytes, &m_OverlapWrite);\r
189                 hr = GetOverlappedResult(&m_OverlapWrite, &bytes, TRUE);\r
190                 LeaveCriticalSection(&m_CritSecWrite);\r
191         } else {\r
192                 if (WriteFile(m_hFile, pMad, bytes, &bytes, pOverlapped)) {\r
193                         hr = NOERROR;\r
194                 } else {\r
195                         hr = HRESULT_FROM_WIN32(GetLastError());\r
196                 }\r
197         }\r
198 \r
199         return hr;\r
200 }\r
201 \r
202 STDMETHODIMP CWMProvider::\r
203 Receive(WM_MAD *pMad, SIZE_T BufferSize, OVERLAPPED *pOverlapped)\r
204 {\r
205         DWORD bytes;\r
206         HRESULT hr;\r
207 \r
208         if (pOverlapped == NULL) {\r
209                 EnterCriticalSection(&m_CritSecRead);\r
210                 ReadFile(m_hFile, pMad, (DWORD) BufferSize, &bytes, &m_OverlapRead);\r
211                 hr = GetOverlappedResult(&m_OverlapRead, &bytes, TRUE);\r
212                 LeaveCriticalSection(&m_CritSecRead);\r
213         } else {\r
214                 if (ReadFile(m_hFile, pMad, (DWORD) BufferSize, &bytes, pOverlapped)) {\r
215                         hr = NOERROR;\r
216                 } else {\r
217                         hr = HRESULT_FROM_WIN32(GetLastError());\r
218                 }\r
219         }\r
220 \r
221         return hr;\r
222 }\r