Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensession.c
Go to the documentation of this file.
00001 /* 00002 * 00003 * COPYRIGHT: See COPYING in the top level directory 00004 * PROJECT: ReactOS Multimedia 00005 * FILE: dll/win32/mmdrv/session.c 00006 * PURPOSE: Multimedia User Mode Driver (session management) 00007 * PROGRAMMER: Andrew Greenwood 00008 * UPDATE HISTORY: 00009 * Jan 14, 2007: Created 00010 */ 00011 00012 #include <mmdrv.h> 00013 00014 /* Each session is tracked, but the list must be locked when in use */ 00015 00016 SessionInfo* session_list = NULL; 00017 CRITICAL_SECTION session_lock; 00018 00019 00020 /* 00021 Obtains a pointer to the session associated with a device type and ID. 00022 If no session exists, returns NULL. This is mainly used to see if a 00023 session already exists prior to creating a new one. 00024 */ 00025 00026 SessionInfo* 00027 GetSession( 00028 DeviceType device_type, 00029 UINT device_id) 00030 { 00031 SessionInfo* session_info; 00032 00033 EnterCriticalSection(&session_lock); 00034 session_info = session_list; 00035 00036 while ( session_info ) 00037 { 00038 if ( ( session_info->device_type == device_type ) && 00039 ( session_info->device_id == device_id ) ) 00040 { 00041 LeaveCriticalSection(&session_lock); 00042 return session_info; 00043 } 00044 00045 session_info = session_info->next; 00046 } 00047 00048 LeaveCriticalSection(&session_lock); 00049 return NULL; 00050 } 00051 00052 00053 /* 00054 Creates a new session, associated with the specified device type and ID. 00055 Whilst the session list is locked, this also checks to see if an existing 00056 session is associated with the device. 00057 */ 00058 00059 MMRESULT 00060 CreateSession( 00061 DeviceType device_type, 00062 UINT device_id, 00063 SessionInfo** session_info) 00064 { 00065 HANDLE heap = GetProcessHeap(); 00066 00067 ASSERT(session_info); 00068 00069 EnterCriticalSection(&session_lock); 00070 00071 /* Ensure we're not creating a duplicate session */ 00072 00073 if ( GetSession(device_type, device_id) ) 00074 { 00075 DPRINT("Already allocated session\n"); 00076 LeaveCriticalSection(&session_lock); 00077 return MMSYSERR_ALLOCATED; 00078 } 00079 00080 *session_info = HeapAlloc(heap, HEAP_ZERO_MEMORY, sizeof(SessionInfo)); 00081 00082 if ( ! *session_info ) 00083 { 00084 DPRINT("Failed to allocate mem for session info\n"); 00085 LeaveCriticalSection(&session_lock); 00086 return MMSYSERR_NOMEM; 00087 } 00088 00089 (*session_info)->device_type = device_type; 00090 (*session_info)->device_id = device_id; 00091 00092 /* Add to the list */ 00093 00094 (*session_info)->next = session_list; 00095 session_list = *session_info; 00096 00097 LeaveCriticalSection(&session_lock); 00098 00099 return MMSYSERR_NOERROR; 00100 } 00101 00102 00103 /* 00104 Removes a session from the list and destroys it. This function does NOT 00105 perform any additional cleanup. Think of it as a slightly more advanced 00106 free() 00107 */ 00108 00109 VOID 00110 DestroySession(SessionInfo* session) 00111 { 00112 HANDLE heap = GetProcessHeap(); 00113 SessionInfo* session_node; 00114 SessionInfo* session_prev; 00115 00116 /* TODO: More cleanup stuff */ 00117 00118 /* Remove from the list */ 00119 00120 EnterCriticalSection(&session_lock); 00121 00122 session_node = session_list; 00123 session_prev = NULL; 00124 00125 while ( session_node ) 00126 { 00127 if ( session_node == session ) 00128 { 00129 /* Bridge the gap for when we go */ 00130 session_prev->next = session->next; 00131 break; 00132 } 00133 00134 /* Save the previous node, fetch the next */ 00135 session_prev = session_node; 00136 session_node = session_node->next; 00137 } 00138 00139 LeaveCriticalSection(&session_lock); 00140 00141 HeapFree(heap, 0, session); 00142 } 00143 00144 00145 /* 00146 Allocates events and other resources for the session thread, starts it, 00147 and waits for it to announce that it is ready to work for us. 00148 */ 00149 00150 MMRESULT 00151 StartSessionThread(SessionInfo* session_info) 00152 { 00153 LPTASKCALLBACK task; 00154 MMRESULT result; 00155 00156 ASSERT(session_info); 00157 00158 /* This is our "ready" event, sent when the thread is idle */ 00159 00160 session_info->thread.ready_event = CreateEvent(NULL, FALSE, FALSE, NULL); 00161 00162 if ( ! session_info->thread.ready_event ) 00163 { 00164 DPRINT("Couldn't create thread_ready event\n"); 00165 return MMSYSERR_NOMEM; 00166 } 00167 00168 /* This is our "go" event, sent when we want the thread to do something */ 00169 00170 session_info->thread.go_event = CreateEvent(NULL, FALSE, FALSE, NULL); 00171 00172 if ( ! session_info->thread.go_event ) 00173 { 00174 DPRINT("Couldn't create thread_go event\n"); 00175 CloseHandle(session_info->thread.ready_event); 00176 return MMSYSERR_NOMEM; 00177 } 00178 00179 /* TODO - other kinds of devices need attention, too */ 00180 task = ( session_info->device_type == WaveOutDevice ) 00181 ? (LPTASKCALLBACK) WaveThread : NULL; 00182 00183 ASSERT(task); 00184 00185 /* Effectively, this is a beefed-up CreateThread */ 00186 00187 result = mmTaskCreate(task, 00188 &session_info->thread.handle, 00189 (DWORD_PTR)session_info); 00190 00191 if ( result != MMSYSERR_NOERROR ) 00192 { 00193 DPRINT("Task creation failed\n"); 00194 CloseHandle(session_info->thread.ready_event); 00195 CloseHandle(session_info->thread.go_event); 00196 return result; 00197 } 00198 00199 /* Wait for the thread to be ready before completing */ 00200 00201 WaitForSingleObject(session_info->thread.ready_event, INFINITE); 00202 00203 return MMSYSERR_NOERROR; 00204 } 00205 00206 00207 /* 00208 The session thread is pretty simple. Upon creation, it announces that it 00209 is ready to do stuff for us. When we want it to perform an action, we use 00210 CallSessionThread with an appropriate function and parameter, then tell 00211 the thread we want it to do something. When it's finished, it announces 00212 that it is ready once again. 00213 */ 00214 00215 MMRESULT 00216 CallSessionThread( 00217 SessionInfo* session_info, 00218 ThreadFunction function, 00219 PVOID thread_parameter) 00220 { 00221 ASSERT(session_info); 00222 00223 session_info->thread.function = function; 00224 session_info->thread.parameter = thread_parameter; 00225 00226 DPRINT("Calling session thread\n"); 00227 SetEvent(session_info->thread.go_event); 00228 00229 DPRINT("Waiting for thread response\n"); 00230 WaitForSingleObject(session_info->thread.ready_event, INFINITE); 00231 00232 return session_info->thread.result; 00233 } 00234 00235 00236 DWORD 00237 HandleBySessionThread( 00238 DWORD_PTR private_handle, 00239 DWORD_PTR message, 00240 DWORD_PTR parameter) 00241 { 00242 return CallSessionThread((SessionInfo*) private_handle, 00243 message, 00244 (PVOID) parameter); 00245 } Generated on Fri May 25 2012 04:22:25 for ReactOS by
1.7.6.1
|