ReactOS 0.4.15-dev-7968-g24a56f8
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{
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
112VOID
114{
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
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
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
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
239DWORD
241 DWORD_PTR private_handle,
243 DWORD_PTR parameter)
244{
245 return CallSessionThread((SessionInfo*) private_handle,
246 message,
247 (PVOID) parameter);
248}
device_type
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapFree(x, y, z)
Definition: compat.h:735
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
TASKCALLBACK FAR * LPTASKCALLBACK
Definition: mmddk.h:33
UINT APIENTRY mmTaskCreate(LPTASKCALLBACK lpfn, HANDLE FAR *lph, DWORD dwInst)
MMRESULT CallSessionThread(SessionInfo *session_info, ThreadFunction function, PVOID thread_parameter)
Definition: session.c:219
SessionInfo * GetSession(DeviceType device_type, UINT device_id)
Definition: session.c:30
MMRESULT CreateSession(DeviceType device_type, UINT device_id, SessionInfo **session_info)
Definition: session.c:63
SessionInfo * session_list
Definition: session.c:19
MMRESULT StartSessionThread(SessionInfo *session_info)
Definition: session.c:154
DWORD HandleBySessionThread(DWORD_PTR private_handle, DWORD_PTR message, DWORD_PTR parameter)
Definition: session.c:240
CRITICAL_SECTION session_lock
Definition: session.c:20
VOID DestroySession(SessionInfo *session)
Definition: session.c:113
#define INFINITE
Definition: serial.h:102
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint64EXT * result
Definition: glext.h:11304
DeviceType
Definition: mmdrv.h:42
@ WaveOutDevice
Definition: mmdrv.h:43
DWORD ThreadFunction
Definition: mmdrv.h:85
DWORD WaveThread(LPVOID parameter)
Definition: wave.c:266
#define MMSYSERR_NOMEM
Definition: mmsystem.h:103
UINT MMRESULT
Definition: mmsystem.h:962
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define MMSYSERR_ALLOCATED
Definition: mmsystem.h:100
#define ASSERT(a)
Definition: mode.c:44
unsigned int UINT
Definition: ndis.h:50
static HANDLE heap
Definition: heap.c:65
#define DPRINT
Definition: sndvol32.h:71
ThreadInfo thread
Definition: mmdrv.h:172
DeviceType device_type
Definition: mmdrv.h:133
struct _SessionInfo * next
Definition: mmdrv.h:131
UINT device_id
Definition: mmdrv.h:134
MMRESULT result
Definition: mmdrv.h:120
HANDLE handle
Definition: mmdrv.h:112
HANDLE ready_event
Definition: mmdrv.h:113
PVOID parameter
Definition: mmdrv.h:118
DWORD function
Definition: mmdrv.h:117
HANDLE go_event
Definition: mmdrv.h:114
Definition: tftpd.h:60
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
uint32_t DWORD_PTR
Definition: typedefs.h:65
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
#define CreateEvent
Definition: winbase.h:3748
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)