ReactOS  0.4.15-dev-1201-gb2cf5a4
session.c
Go to the documentation of this file.
1 /*
2  *
3  * COPYRIGHT: See COPYING in the top level directory
4  * PROJECT: ReactOS Multimedia
5  * FILE: dll/win32/mmdrv/session.c
6  * PURPOSE: Multimedia User Mode Driver (session management)
7  * PROGRAMMER: Andrew Greenwood
8  * UPDATE HISTORY:
9  * Jan 14, 2007: Created
10  */
11 
12 #include "mmdrv.h"
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 /* Each session is tracked, but the list must be locked when in use */
18 
21 
22 
23 /*
24  Obtains a pointer to the session associated with a device type and ID.
25  If no session exists, returns NULL. This is mainly used to see if a
26  session already exists prior to creating a new one.
27 */
28 
32  UINT device_id)
33 {
34  SessionInfo* session_info;
35 
37  session_info = session_list;
38 
39  while ( session_info )
40  {
41  if ( ( session_info->device_type == device_type ) &&
42  ( session_info->device_id == device_id ) )
43  {
45  return session_info;
46  }
47 
48  session_info = session_info->next;
49  }
50 
52  return NULL;
53 }
54 
55 
56 /*
57  Creates a new session, associated with the specified device type and ID.
58  Whilst the session list is locked, this also checks to see if an existing
59  session is associated with the device.
60 */
61 
65  UINT device_id,
66  SessionInfo** session_info)
67 {
68  HANDLE heap = GetProcessHeap();
69 
70  ASSERT(session_info);
71 
73 
74  /* Ensure we're not creating a duplicate session */
75 
76  if ( GetSession(device_type, device_id) )
77  {
78  DPRINT("Already allocated session\n");
80  return MMSYSERR_ALLOCATED;
81  }
82 
83  *session_info = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(SessionInfo));
84 
85  if ( ! *session_info )
86  {
87  DPRINT("Failed to allocate mem for session info\n");
89  return MMSYSERR_NOMEM;
90  }
91 
92  (*session_info)->device_type = device_type;
93  (*session_info)->device_id = device_id;
94 
95  /* Add to the list */
96 
97  (*session_info)->next = session_list;
98  session_list = *session_info;
99 
101 
102  return MMSYSERR_NOERROR;
103 }
104 
105 
106 /*
107  Removes a session from the list and destroys it. This function does NOT
108  perform any additional cleanup. Think of it as a slightly more advanced
109  free()
110 */
111 
112 VOID
114 {
115  HANDLE heap = GetProcessHeap();
116  SessionInfo* session_node;
117  SessionInfo* session_prev;
118 
119  /* TODO: More cleanup stuff */
120 
121  /* Remove from the list */
122 
124 
125  session_node = session_list;
126  session_prev = NULL;
127 
128  while ( session_node )
129  {
130  if ( session_node == session )
131  {
132  /* Bridge the gap for when we go */
133  session_prev->next = session->next;
134  break;
135  }
136 
137  /* Save the previous node, fetch the next */
138  session_prev = session_node;
139  session_node = session_node->next;
140  }
141 
143 
144  HeapFree(heap, 0, session);
145 }
146 
147 
148 /*
149  Allocates events and other resources for the session thread, starts it,
150  and waits for it to announce that it is ready to work for us.
151 */
152 
153 MMRESULT
155 {
156  LPTASKCALLBACK task;
158 
159  ASSERT(session_info);
160 
161  /* This is our "ready" event, sent when the thread is idle */
162 
163  session_info->thread.ready_event = CreateEvent(NULL, FALSE, FALSE, NULL);
164 
165  if ( ! session_info->thread.ready_event )
166  {
167  DPRINT("Couldn't create thread_ready event\n");
168  return MMSYSERR_NOMEM;
169  }
170 
171  /* This is our "go" event, sent when we want the thread to do something */
172 
173  session_info->thread.go_event = CreateEvent(NULL, FALSE, FALSE, NULL);
174 
175  if ( ! session_info->thread.go_event )
176  {
177  DPRINT("Couldn't create thread_go event\n");
178  CloseHandle(session_info->thread.ready_event);
179  return MMSYSERR_NOMEM;
180  }
181 
182  /* TODO - other kinds of devices need attention, too */
183  task = ( session_info->device_type == WaveOutDevice )
185 
186  ASSERT(task);
187 
188  /* Effectively, this is a beefed-up CreateThread */
189 
190  result = mmTaskCreate(task,
191  &session_info->thread.handle,
192  (DWORD_PTR)session_info);
193 
194  if ( result != MMSYSERR_NOERROR )
195  {
196  DPRINT("Task creation failed\n");
197  CloseHandle(session_info->thread.ready_event);
198  CloseHandle(session_info->thread.go_event);
199  return result;
200  }
201 
202  /* Wait for the thread to be ready before completing */
203 
204  WaitForSingleObject(session_info->thread.ready_event, INFINITE);
205 
206  return MMSYSERR_NOERROR;
207 }
208 
209 
210 /*
211  The session thread is pretty simple. Upon creation, it announces that it
212  is ready to do stuff for us. When we want it to perform an action, we use
213  CallSessionThread with an appropriate function and parameter, then tell
214  the thread we want it to do something. When it's finished, it announces
215  that it is ready once again.
216 */
217 
218 MMRESULT
220  SessionInfo* session_info,
221  ThreadFunction function,
222  PVOID thread_parameter)
223 {
224  ASSERT(session_info);
225 
226  session_info->thread.function = function;
227  session_info->thread.parameter = thread_parameter;
228 
229  DPRINT("Calling session thread\n");
230  SetEvent(session_info->thread.go_event);
231 
232  DPRINT("Waiting for thread response\n");
234 
235  return session_info->thread.result;
236 }
237 
238 
239 DWORD
241  DWORD_PTR private_handle,
243  DWORD_PTR parameter)
244 {
245  return CallSessionThread((SessionInfo*) private_handle,
246  message,
247  (PVOID) parameter);
248 }
#define CreateEvent
Definition: winbase.h:3588
SessionInfo * GetSession(DeviceType device_type, UINT device_id)
Definition: session.c:30
DWORD function
Definition: mmdrv.h:117
Definition: tftpd.h:59
#define CloseHandle
Definition: compat.h:598
UINT APIENTRY mmTaskCreate(LPTASKCALLBACK lpfn, HANDLE FAR *lph, DWORD dwInst)
HANDLE ready_event
Definition: mmdrv.h:113
DeviceType
Definition: mmdrv.h:41
device_type
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
UINT MMRESULT
Definition: mmsystem.h:962
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
DWORD ThreadFunction
Definition: mmdrv.h:85
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
#define MMSYSERR_NOMEM
Definition: mmsystem.h:103
#define FALSE
Definition: types.h:117
DWORD HandleBySessionThread(DWORD_PTR private_handle, DWORD_PTR message, DWORD_PTR parameter)
Definition: session.c:240
MMRESULT result
Definition: mmdrv.h:120
UINT device_id
Definition: mmdrv.h:134
VOID DestroySession(SessionInfo *session)
Definition: session.c:113
smooth NULL
Definition: ftsmooth.c:416
void DPRINT(...)
Definition: polytest.cpp:61
HANDLE handle
Definition: mmdrv.h:112
MMRESULT StartSessionThread(SessionInfo *session_info)
Definition: session.c:154
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define GetProcessHeap()
Definition: compat.h:595
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
struct _SessionInfo * next
Definition: mmdrv.h:131
#define MMSYSERR_ALLOCATED
Definition: mmsystem.h:100
DeviceType device_type
Definition: mmdrv.h:133
SessionInfo * session_list
Definition: session.c:19
unsigned long DWORD
Definition: ntddk_ex.h:95
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
MMRESULT CallSessionThread(SessionInfo *session_info, ThreadFunction function, PVOID thread_parameter)
Definition: session.c:219
CRITICAL_SECTION session_lock
Definition: session.c:20
uint32_t DWORD_PTR
Definition: typedefs.h:65
TASKCALLBACK FAR * LPTASKCALLBACK
Definition: mmddk.h:33
DWORD WaveThread(LPVOID parameter)
Definition: wave.c:266
ThreadInfo thread
Definition: mmdrv.h:172
unsigned int UINT
Definition: ndis.h:50
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
HANDLE go_event
Definition: mmdrv.h:114
#define INFINITE
Definition: serial.h:102
GLuint64EXT * result
Definition: glext.h:11304
#define HeapFree(x, y, z)
Definition: compat.h:594
PVOID parameter
Definition: mmdrv.h:118
MMRESULT CreateSession(DeviceType device_type, UINT device_id, SessionInfo **session_info)
Definition: session.c:63