ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

session.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.