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

internal.c
Go to the documentation of this file.
00001 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
00002 
00003 /*
00004  *      MSACM32 library
00005  *
00006  *      Copyright 1998  Patrik Stridvall
00007  *        1999  Eric Pouech
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00022  */
00023 
00024 #include <stdarg.h>
00025 #include <string.h>
00026 
00027 #include "windef.h"
00028 #include "winbase.h"
00029 #include "wingdi.h"
00030 #include "winuser.h"
00031 #include "winerror.h"
00032 #include "winreg.h"
00033 #include "mmsystem.h"
00034 #include "mmreg.h"
00035 #include "msacm.h"
00036 #include "msacmdrv.h"
00037 #include "wineacm.h"
00038 #include "wine/debug.h"
00039 #include "wine/unicode.h"
00040 
00041 WINE_DEFAULT_DEBUG_CHANNEL(msacm);
00042 
00043 /**********************************************************************/
00044 
00045 HANDLE MSACM_hHeap = NULL;
00046 PWINE_ACMDRIVERID MSACM_pFirstACMDriverID = NULL;
00047 static PWINE_ACMDRIVERID MSACM_pLastACMDriverID;
00048 
00049 static DWORD MSACM_suspendBroadcastCount = 0;
00050 static BOOL MSACM_pendingBroadcast = FALSE;
00051 static PWINE_ACMNOTIFYWND MSACM_pFirstACMNotifyWnd = NULL;
00052 static PWINE_ACMNOTIFYWND MSACM_pLastACMNotifyWnd = NULL;
00053 
00054 static void MSACM_ReorderDriversByPriority(void);
00055 
00056 /***********************************************************************
00057  *           MSACM_RegisterDriverFromRegistry()
00058  */
00059 PWINE_ACMDRIVERID MSACM_RegisterDriverFromRegistry(LPCWSTR pszRegEntry)
00060 {
00061     static const WCHAR msacmW[] = {'M','S','A','C','M','.'};
00062     static const WCHAR drvkey[] = {'S','o','f','t','w','a','r','e','\\',
00063                    'M','i','c','r','o','s','o','f','t','\\',
00064                    'W','i','n','d','o','w','s',' ','N','T','\\',
00065                    'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00066                    'D','r','i','v','e','r','s','3','2','\0'};
00067     WCHAR buf[2048];
00068     DWORD bufLen, lRet;
00069     HKEY hKey;
00070     PWINE_ACMDRIVERID padid = NULL;
00071     
00072     /* The requested registry entry must have the format msacm.XXXXX in order to
00073        be recognized in any future sessions of msacm
00074      */
00075     if (0 == strncmpiW(pszRegEntry, msacmW, sizeof(msacmW)/sizeof(WCHAR))) {
00076         lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, drvkey, 0, KEY_QUERY_VALUE, &hKey);
00077         if (lRet != ERROR_SUCCESS) {
00078             WARN("unable to open registry key - 0x%08x\n", lRet);
00079         } else {
00080             bufLen = sizeof(buf);
00081             lRet = RegQueryValueExW(hKey, pszRegEntry, NULL, NULL, (LPBYTE)buf, &bufLen);
00082             if (lRet != ERROR_SUCCESS) {
00083                 WARN("unable to query requested subkey %s - 0x%08x\n", debugstr_w(pszRegEntry), lRet);
00084             } else {
00085                 MSACM_RegisterDriver(pszRegEntry, buf, 0);
00086             }
00087             RegCloseKey( hKey );
00088         }
00089     }
00090     return padid;
00091 }
00092 
00093 #if 0
00094 /***********************************************************************
00095  *           MSACM_DumpCache
00096  */
00097 static  void MSACM_DumpCache(PWINE_ACMDRIVERID padid)
00098 {
00099     unsigned    i;
00100 
00101     TRACE("cFilterTags=%lu cFormatTags=%lu fdwSupport=%08lx\n",
00102       padid->cFilterTags, padid->cFormatTags, padid->fdwSupport);
00103     for (i = 0; i < padid->cache->cFormatTags; i++) {
00104     TRACE("\tdwFormatTag=%lu cbwfx=%lu\n",
00105           padid->aFormatTag[i].dwFormatTag, padid->aFormatTag[i].cbwfx);
00106     }
00107 }
00108 #endif
00109 
00110 /***********************************************************************
00111  *           MSACM_FindFormatTagInCache         [internal]
00112  *
00113  *  Returns TRUE is the format tag fmtTag is present in the cache.
00114  *  If so, idx is set to its index.
00115  */
00116 BOOL MSACM_FindFormatTagInCache(const WINE_ACMDRIVERID* padid, DWORD fmtTag, LPDWORD idx)
00117 {
00118     unsigned    i;
00119 
00120     for (i = 0; i < padid->cFormatTags; i++) {
00121     if (padid->aFormatTag[i].dwFormatTag == fmtTag) {
00122         if (idx) *idx = i;
00123         return TRUE;
00124     }
00125     }
00126     return FALSE;
00127 }
00128 
00129 /***********************************************************************
00130  *           MSACM_FillCache
00131  */
00132 static BOOL MSACM_FillCache(PWINE_ACMDRIVERID padid)
00133 {
00134     HACMDRIVER              had = 0;
00135     unsigned int                ntag;
00136     ACMDRIVERDETAILSW           add;
00137     ACMFORMATTAGDETAILSW        aftd;
00138 
00139     if (acmDriverOpen(&had, (HACMDRIVERID)padid, 0) != 0)
00140     return FALSE;
00141 
00142     padid->aFormatTag = NULL;
00143     add.cbStruct = sizeof(add);
00144     if (MSACM_Message(had, ACMDM_DRIVER_DETAILS, (LPARAM)&add,  0))
00145     goto errCleanUp;
00146 
00147     if (add.cFormatTags > 0) {
00148     padid->aFormatTag = HeapAlloc(MSACM_hHeap, HEAP_ZERO_MEMORY,
00149                       add.cFormatTags * sizeof(padid->aFormatTag[0]));
00150     if (!padid->aFormatTag) goto errCleanUp;
00151     }
00152 
00153     padid->cFormatTags = add.cFormatTags;
00154     padid->cFilterTags = add.cFilterTags;
00155     padid->fdwSupport  = add.fdwSupport;
00156 
00157     aftd.cbStruct = sizeof(aftd);
00158 
00159     for (ntag = 0; ntag < add.cFormatTags; ntag++) {
00160     aftd.dwFormatTagIndex = ntag;
00161     if (MSACM_Message(had, ACMDM_FORMATTAG_DETAILS, (LPARAM)&aftd, ACM_FORMATTAGDETAILSF_INDEX)) {
00162         TRACE("IIOs (%s)\n", debugstr_w(padid->pszDriverAlias));
00163         goto errCleanUp;
00164     }
00165     padid->aFormatTag[ntag].dwFormatTag = aftd.dwFormatTag;
00166     padid->aFormatTag[ntag].cbwfx = aftd.cbFormatSize;
00167     }
00168 
00169     acmDriverClose(had, 0);
00170 
00171     return TRUE;
00172 
00173 errCleanUp:
00174     if (had) acmDriverClose(had, 0);
00175     HeapFree(MSACM_hHeap, 0, padid->aFormatTag);
00176     padid->aFormatTag = NULL;
00177     return FALSE;
00178 }
00179 
00180 /***********************************************************************
00181  *           MSACM_GetRegistryKey
00182  */
00183 static  LPWSTR  MSACM_GetRegistryKey(const WINE_ACMDRIVERID* padid)
00184 {
00185     static const WCHAR  baseKey[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
00186                                      'A','u','d','i','o','C','o','m','p','r','e','s','s','i','o','n','M','a','n','a','g','e','r','\\',
00187                                      'D','r','i','v','e','r','C','a','c','h','e','\\','\0'};
00188     LPWSTR  ret;
00189     int     len;
00190 
00191     if (!padid->pszDriverAlias) {
00192     ERR("No alias needed for registry entry\n");
00193     return NULL;
00194     }
00195     len = strlenW(baseKey);
00196     ret = HeapAlloc(MSACM_hHeap, 0, (len + strlenW(padid->pszDriverAlias) + 1) * sizeof(WCHAR));
00197     if (!ret) return NULL;
00198 
00199     strcpyW(ret, baseKey);
00200     strcpyW(ret + len, padid->pszDriverAlias);
00201     CharLowerW(ret + len);
00202     return ret;
00203 }
00204 
00205 /***********************************************************************
00206  *           MSACM_ReadCache
00207  */
00208 static BOOL MSACM_ReadCache(PWINE_ACMDRIVERID padid)
00209 {
00210     LPWSTR  key = MSACM_GetRegistryKey(padid);
00211     HKEY    hKey;
00212     DWORD   type, size;
00213 
00214     if (!key) return FALSE;
00215 
00216     padid->aFormatTag = NULL;
00217 
00218     if (RegCreateKeyW(HKEY_LOCAL_MACHINE, key, &hKey))
00219     goto errCleanUp;
00220 
00221     size = sizeof(padid->cFormatTags);
00222     if (RegQueryValueExA(hKey, "cFormatTags", 0, &type, (void*)&padid->cFormatTags, &size))
00223     goto errCleanUp;
00224     size = sizeof(padid->cFilterTags);
00225     if (RegQueryValueExA(hKey, "cFilterTags", 0, &type, (void*)&padid->cFilterTags, &size))
00226     goto errCleanUp;
00227     size = sizeof(padid->fdwSupport);
00228     if (RegQueryValueExA(hKey, "fdwSupport", 0, &type, (void*)&padid->fdwSupport, &size))
00229     goto errCleanUp;
00230 
00231     if (padid->cFormatTags > 0) {
00232     size = padid->cFormatTags * sizeof(padid->aFormatTag[0]);
00233     padid->aFormatTag = HeapAlloc(MSACM_hHeap, HEAP_ZERO_MEMORY, size);
00234     if (!padid->aFormatTag) goto errCleanUp;
00235     if (RegQueryValueExA(hKey, "aFormatTagCache", 0, &type, (void*)padid->aFormatTag, &size))
00236         goto errCleanUp;
00237     }
00238     HeapFree(MSACM_hHeap, 0, key);
00239     return TRUE;
00240 
00241  errCleanUp:
00242     HeapFree(MSACM_hHeap, 0, key);
00243     HeapFree(MSACM_hHeap, 0, padid->aFormatTag);
00244     padid->aFormatTag = NULL;
00245     RegCloseKey(hKey);
00246     return FALSE;
00247 }
00248 
00249 /***********************************************************************
00250  *           MSACM_WriteCache
00251  */
00252 static  BOOL MSACM_WriteCache(const WINE_ACMDRIVERID *padid)
00253 {
00254     LPWSTR  key = MSACM_GetRegistryKey(padid);
00255     HKEY    hKey;
00256 
00257     if (!key) return FALSE;
00258 
00259     if (RegCreateKeyW(HKEY_LOCAL_MACHINE, key, &hKey))
00260     goto errCleanUp;
00261 
00262     if (RegSetValueExA(hKey, "cFormatTags", 0, REG_DWORD, (const void*)&padid->cFormatTags, sizeof(DWORD)))
00263     goto errCleanUp;
00264     if (RegSetValueExA(hKey, "cFilterTags", 0, REG_DWORD, (const void*)&padid->cFilterTags, sizeof(DWORD)))
00265     goto errCleanUp;
00266     if (RegSetValueExA(hKey, "fdwSupport", 0, REG_DWORD, (const void*)&padid->fdwSupport, sizeof(DWORD)))
00267     goto errCleanUp;
00268     if (RegSetValueExA(hKey, "aFormatTagCache", 0, REG_BINARY,
00269                (void*)padid->aFormatTag,
00270                padid->cFormatTags * sizeof(padid->aFormatTag[0])))
00271     goto errCleanUp;
00272     HeapFree(MSACM_hHeap, 0, key);
00273     return TRUE;
00274 
00275  errCleanUp:
00276     HeapFree(MSACM_hHeap, 0, key);
00277     return FALSE;
00278 }
00279 
00280 /***********************************************************************
00281  *           MSACM_RegisterDriver()
00282  */
00283 PWINE_ACMDRIVERID MSACM_RegisterDriver(LPCWSTR pszDriverAlias, LPCWSTR pszFileName,
00284                        PWINE_ACMLOCALDRIVER pLocalDriver)
00285 {
00286     PWINE_ACMDRIVERID   padid;
00287 
00288     TRACE("(%s, %s, %p)\n", 
00289           debugstr_w(pszDriverAlias), debugstr_w(pszFileName), pLocalDriver);
00290 
00291     padid = HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMDRIVERID));
00292     if (!padid)
00293         return NULL;
00294     padid->obj.dwType = WINE_ACMOBJ_DRIVERID;
00295     padid->obj.pACMDriverID = padid;
00296     padid->pszDriverAlias = NULL;
00297     if (pszDriverAlias)
00298     {
00299         padid->pszDriverAlias = HeapAlloc( MSACM_hHeap, 0, (strlenW(pszDriverAlias)+1) * sizeof(WCHAR) );
00300         if (!padid->pszDriverAlias) {
00301             HeapFree(MSACM_hHeap, 0, padid);
00302             return NULL;
00303         }
00304         strcpyW( padid->pszDriverAlias, pszDriverAlias );
00305     }
00306     padid->pszFileName = NULL;
00307     if (pszFileName)
00308     {
00309         padid->pszFileName = HeapAlloc( MSACM_hHeap, 0, (strlenW(pszFileName)+1) * sizeof(WCHAR) );
00310         if (!padid->pszFileName) {
00311             HeapFree(MSACM_hHeap, 0, padid->pszDriverAlias);
00312             HeapFree(MSACM_hHeap, 0, padid);
00313             return NULL;
00314         }
00315         strcpyW( padid->pszFileName, pszFileName );
00316     }
00317     padid->pLocalDriver = pLocalDriver;
00318 
00319     padid->pACMDriverList = NULL;
00320     
00321     if (pLocalDriver) {
00322         padid->pPrevACMDriverID = NULL;
00323         padid->pNextACMDriverID = MSACM_pFirstACMDriverID;
00324         if (MSACM_pFirstACMDriverID)
00325             MSACM_pFirstACMDriverID->pPrevACMDriverID = padid;
00326         MSACM_pFirstACMDriverID = padid;
00327         if (!MSACM_pLastACMDriverID)
00328             MSACM_pLastACMDriverID = padid;
00329     } else {
00330         padid->pNextACMDriverID = NULL;
00331         padid->pPrevACMDriverID = MSACM_pLastACMDriverID;
00332         if (MSACM_pLastACMDriverID)
00333         MSACM_pLastACMDriverID->pNextACMDriverID = padid;
00334         MSACM_pLastACMDriverID = padid;
00335         if (!MSACM_pFirstACMDriverID)
00336         MSACM_pFirstACMDriverID = padid;
00337     }
00338     /* disable the driver if we cannot load the cache */
00339     if ((!padid->pszDriverAlias || !MSACM_ReadCache(padid)) && !MSACM_FillCache(padid)) {
00340     WARN("Couldn't load cache for ACM driver (%s)\n", debugstr_w(pszFileName));
00341     MSACM_UnregisterDriver(padid);
00342     return NULL;
00343     }
00344 
00345     if (pLocalDriver) padid->fdwSupport |= ACMDRIVERDETAILS_SUPPORTF_LOCAL;
00346     return padid;
00347 }
00348 
00349 /***********************************************************************
00350  *           MSACM_RegisterAllDrivers()
00351  */
00352 void MSACM_RegisterAllDrivers(void)
00353 {
00354     static const WCHAR msacm32[] = {'m','s','a','c','m','3','2','.','d','l','l','\0'};
00355     static const WCHAR msacmW[] = {'M','S','A','C','M','.'};
00356     static const WCHAR drv32[] = {'d','r','i','v','e','r','s','3','2','\0'};
00357     static const WCHAR sys[] = {'s','y','s','t','e','m','.','i','n','i','\0'};
00358     static const WCHAR drvkey[] = {'S','o','f','t','w','a','r','e','\\',
00359                    'M','i','c','r','o','s','o','f','t','\\',
00360                    'W','i','n','d','o','w','s',' ','N','T','\\',
00361                    'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
00362                    'D','r','i','v','e','r','s','3','2','\0'};
00363     DWORD i, cnt = 0, bufLen, lRet;
00364     WCHAR buf[2048], *name, *s;
00365     FILETIME lastWrite;
00366     HKEY hKey;
00367 
00368     /* FIXME: What if the user edits system.ini while the program is running?
00369      * Does Windows handle that?  */
00370     if (MSACM_pFirstACMDriverID) return;
00371 
00372     lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, drvkey, 0, KEY_QUERY_VALUE, &hKey);
00373     if (lRet == ERROR_SUCCESS) {
00374     RegQueryInfoKeyW( hKey, 0, 0, 0, &cnt, 0, 0, 0, 0, 0, 0, 0);
00375     for (i = 0; i < cnt; i++) {
00376         bufLen = sizeof(buf) / sizeof(buf[0]);
00377         lRet = RegEnumKeyExW(hKey, i, buf, &bufLen, 0, 0, 0, &lastWrite);
00378         if (lRet != ERROR_SUCCESS) continue;
00379         if (strncmpiW(buf, msacmW, sizeof(msacmW)/sizeof(msacmW[0]))) continue;
00380         if (!(name = strchrW(buf, '='))) continue;
00381         *name = 0;
00382         MSACM_RegisterDriver(buf, name + 1, 0);
00383     }
00384         RegCloseKey( hKey );
00385     }
00386 
00387     if (GetPrivateProfileSectionW(drv32, buf, sizeof(buf)/sizeof(buf[0]), sys))
00388     {
00389     for(s = buf; *s;  s += strlenW(s) + 1)
00390     {
00391         if (strncmpiW(s, msacmW, sizeof(msacmW)/sizeof(msacmW[0]))) continue;
00392         if (!(name = strchrW(s, '='))) continue;
00393         *name = 0;
00394         MSACM_RegisterDriver(s, name + 1, 0);
00395         *name = '=';
00396     }
00397     }
00398     MSACM_ReorderDriversByPriority();
00399     MSACM_RegisterDriver(msacm32, msacm32, 0);
00400 }
00401 
00402 /***********************************************************************
00403  *           MSACM_RegisterNotificationWindow()
00404  */
00405 PWINE_ACMNOTIFYWND MSACM_RegisterNotificationWindow(HWND hNotifyWnd, DWORD dwNotifyMsg)
00406 {
00407     PWINE_ACMNOTIFYWND  panwnd;
00408 
00409     TRACE("(%p,0x%08x)\n", hNotifyWnd, dwNotifyMsg);
00410 
00411     panwnd = HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMNOTIFYWND));
00412     panwnd->obj.dwType = WINE_ACMOBJ_NOTIFYWND;
00413     panwnd->obj.pACMDriverID = 0;
00414     panwnd->hNotifyWnd = hNotifyWnd;
00415     panwnd->dwNotifyMsg = dwNotifyMsg;
00416     panwnd->fdwSupport = 0;
00417     
00418     panwnd->pNextACMNotifyWnd = NULL;
00419     panwnd->pPrevACMNotifyWnd = MSACM_pLastACMNotifyWnd;
00420     if (MSACM_pLastACMNotifyWnd)
00421         MSACM_pLastACMNotifyWnd->pNextACMNotifyWnd = panwnd;
00422     MSACM_pLastACMNotifyWnd = panwnd;
00423     if (!MSACM_pFirstACMNotifyWnd)
00424         MSACM_pFirstACMNotifyWnd = panwnd;
00425 
00426     return panwnd;
00427 }
00428 
00429 /***********************************************************************
00430  *           MSACM_BroadcastNotification()
00431  */
00432 void MSACM_BroadcastNotification(void)
00433 {
00434     if (MSACM_suspendBroadcastCount <= 0) {
00435         PWINE_ACMNOTIFYWND panwnd;
00436 
00437         for (panwnd = MSACM_pFirstACMNotifyWnd; panwnd; panwnd = panwnd->pNextACMNotifyWnd) 
00438         if (!(panwnd->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED))
00439             SendMessageW(panwnd->hNotifyWnd, panwnd->dwNotifyMsg, 0, 0);
00440     } else {
00441         MSACM_pendingBroadcast = TRUE;
00442     }
00443 }
00444 
00445 /***********************************************************************
00446  *           MSACM_DisableNotifications()
00447  */
00448 void MSACM_DisableNotifications(void)
00449 {
00450     MSACM_suspendBroadcastCount++;
00451 }
00452 
00453 /***********************************************************************
00454  *           MSACM_EnableNotifications()
00455  */
00456 void MSACM_EnableNotifications(void)
00457 {
00458     if (MSACM_suspendBroadcastCount > 0) {
00459         MSACM_suspendBroadcastCount--;
00460         if (MSACM_suspendBroadcastCount == 0 && MSACM_pendingBroadcast) {
00461             MSACM_pendingBroadcast = FALSE;
00462             MSACM_BroadcastNotification();
00463         }
00464     }
00465 }
00466 
00467 /***********************************************************************
00468  *           MSACM_UnRegisterNotificationWindow()
00469  */
00470 PWINE_ACMNOTIFYWND MSACM_UnRegisterNotificationWindow(const WINE_ACMNOTIFYWND *panwnd)
00471 {
00472     PWINE_ACMNOTIFYWND p;
00473 
00474     for (p = MSACM_pFirstACMNotifyWnd; p; p = p->pNextACMNotifyWnd) {
00475         if (p == panwnd) {
00476             PWINE_ACMNOTIFYWND pNext = p->pNextACMNotifyWnd;
00477 
00478             if (p->pPrevACMNotifyWnd) p->pPrevACMNotifyWnd->pNextACMNotifyWnd = p->pNextACMNotifyWnd;
00479             if (p->pNextACMNotifyWnd) p->pNextACMNotifyWnd->pPrevACMNotifyWnd = p->pPrevACMNotifyWnd;
00480             if (MSACM_pFirstACMNotifyWnd == p) MSACM_pFirstACMNotifyWnd = p->pNextACMNotifyWnd;
00481             if (MSACM_pLastACMNotifyWnd == p) MSACM_pLastACMNotifyWnd = p->pPrevACMNotifyWnd;
00482             HeapFree(MSACM_hHeap, 0, p);
00483             
00484             return pNext;
00485         }
00486     }
00487     return NULL;
00488 }
00489 
00490 /***********************************************************************
00491  *           MSACM_RePositionDriver()
00492  */
00493 void MSACM_RePositionDriver(PWINE_ACMDRIVERID padid, DWORD dwPriority)
00494 {
00495     PWINE_ACMDRIVERID pTargetPosition = NULL;
00496                 
00497     /* Remove selected driver from linked list */
00498     if (MSACM_pFirstACMDriverID == padid) {
00499         MSACM_pFirstACMDriverID = padid->pNextACMDriverID;
00500     }
00501     if (MSACM_pLastACMDriverID == padid) {
00502         MSACM_pLastACMDriverID = padid->pPrevACMDriverID;
00503     }
00504     if (padid->pPrevACMDriverID != NULL) {
00505         padid->pPrevACMDriverID->pNextACMDriverID = padid->pNextACMDriverID;
00506     }
00507     if (padid->pNextACMDriverID != NULL) {
00508         padid->pNextACMDriverID->pPrevACMDriverID = padid->pPrevACMDriverID;
00509     }
00510     
00511     /* Look up position where selected driver should be */
00512     if (dwPriority == 1) {
00513         pTargetPosition = padid->pPrevACMDriverID;
00514         while (pTargetPosition->pPrevACMDriverID != NULL &&
00515             !(pTargetPosition->pPrevACMDriverID->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_LOCAL)) {
00516             pTargetPosition = pTargetPosition->pPrevACMDriverID;
00517         }
00518     } else if (dwPriority == -1) {
00519         pTargetPosition = padid->pNextACMDriverID;
00520         while (pTargetPosition->pNextACMDriverID != NULL) {
00521             pTargetPosition = pTargetPosition->pNextACMDriverID;
00522         }
00523     }
00524     
00525     /* Place selected driver in selected position */
00526     padid->pPrevACMDriverID = pTargetPosition->pPrevACMDriverID;
00527     padid->pNextACMDriverID = pTargetPosition;
00528     if (padid->pPrevACMDriverID != NULL) {
00529         padid->pPrevACMDriverID->pNextACMDriverID = padid;
00530     } else {
00531         MSACM_pFirstACMDriverID = padid;
00532     }
00533     if (padid->pNextACMDriverID != NULL) {
00534         padid->pNextACMDriverID->pPrevACMDriverID = padid;
00535     } else {
00536         MSACM_pLastACMDriverID = padid;
00537     }
00538 }
00539 
00540 /***********************************************************************
00541  *           MSACM_ReorderDriversByPriority()
00542  * Reorders all drivers based on the priority list indicated by the registry key:
00543  * HKCU\\Software\\Microsoft\\Multimedia\\Audio Compression Manager\\Priority v4.00
00544  */
00545 static void MSACM_ReorderDriversByPriority(void)
00546 {
00547     PWINE_ACMDRIVERID   padid;
00548     unsigned int iNumDrivers;
00549     PWINE_ACMDRIVERID * driverList = NULL;
00550     HKEY hPriorityKey = NULL;
00551     
00552     TRACE("\n");
00553     
00554     /* Count drivers && alloc corresponding memory for list */
00555     iNumDrivers = 0;
00556     for (padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) iNumDrivers++;
00557     if (iNumDrivers > 1)
00558     {
00559         LONG lError;
00560         static const WCHAR basePriorityKey[] = {
00561             'S','o','f','t','w','a','r','e','\\',
00562             'M','i','c','r','o','s','o','f','t','\\',
00563             'M','u','l','t','i','m','e','d','i','a','\\',
00564             'A','u','d','i','o',' ','C','o','m','p','r','e','s','s','i','o','n',' ','M','a','n','a','g','e','r','\\',
00565             'P','r','i','o','r','i','t','y',' ','v','4','.','0','0','\0'
00566         };
00567         unsigned int i;
00568         LONG lBufferLength;
00569         WCHAR szBuffer[256];
00570         
00571         driverList = HeapAlloc(MSACM_hHeap, 0, iNumDrivers * sizeof(PWINE_ACMDRIVERID));
00572         if (!driverList)
00573         {
00574             ERR("out of memory\n");
00575             goto errCleanUp;
00576         }
00577 
00578         lError = RegOpenKeyW(HKEY_CURRENT_USER, basePriorityKey, &hPriorityKey);
00579         if (lError != ERROR_SUCCESS) {
00580             TRACE("RegOpenKeyW failed, possibly key does not exist yet\n");
00581             hPriorityKey = NULL;
00582             goto errCleanUp;
00583         } 
00584             
00585         /* Copy drivers into list to simplify linked list modification */
00586         for (i = 0, padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID, i++)
00587         {
00588             driverList[i] = padid;
00589         }
00590 
00591         /* Query each of the priorities in turn. Alias key is in lowercase. 
00592             The general form of the priority record is the following:
00593             "PriorityN" --> "1, msacm.driveralias"
00594             where N is an integer, and the value is a string of the driver
00595             alias, prefixed by "1, " for an enabled driver, or "0, " for a
00596             disabled driver.
00597             */
00598         for (i = 0; i < iNumDrivers; i++)
00599         {
00600             static const WCHAR priorityTmpl[] = {'P','r','i','o','r','i','t','y','%','l','d','\0'};
00601             WCHAR szSubKey[17];
00602             unsigned int iTargetPosition;
00603             unsigned int iCurrentPosition;
00604             WCHAR * pAlias;
00605             static const WCHAR sPrefix[] = {'m','s','a','c','m','.','\0'};
00606             
00607             /* Build expected entry name */
00608             snprintfW(szSubKey, 17, priorityTmpl, i + 1);
00609             lBufferLength = sizeof(szBuffer);
00610             lError = RegQueryValueExW(hPriorityKey, szSubKey, NULL, NULL, (LPBYTE)szBuffer, (LPDWORD)&lBufferLength);
00611             if (lError != ERROR_SUCCESS) continue;
00612 
00613             /* Recovered driver alias should be at this position */
00614             iTargetPosition = i;
00615             
00616             /* Locate driver alias in driver list */
00617             pAlias = strstrW(szBuffer, sPrefix);
00618             if (pAlias == NULL) continue;
00619             
00620             for (iCurrentPosition = 0; iCurrentPosition < iNumDrivers; iCurrentPosition++) {
00621                 if (strcmpiW(driverList[iCurrentPosition]->pszDriverAlias, pAlias) == 0) 
00622                     break;
00623             }
00624             if (iCurrentPosition < iNumDrivers && iTargetPosition != iCurrentPosition) {
00625                 padid = driverList[iTargetPosition];
00626                 driverList[iTargetPosition] = driverList[iCurrentPosition];
00627                 driverList[iCurrentPosition] = padid;
00628 
00629                 /* Locate enabled status */
00630                 if (szBuffer[0] == '1') {
00631                     driverList[iTargetPosition]->fdwSupport &= ~ACMDRIVERDETAILS_SUPPORTF_DISABLED;
00632                 } else if (szBuffer[0] == '0') {
00633                     driverList[iTargetPosition]->fdwSupport |= ACMDRIVERDETAILS_SUPPORTF_DISABLED;
00634                 }
00635             }
00636         }
00637         
00638         /* Re-assign pointers so that linked list traverses the ordered array */
00639         for (i = 0; i < iNumDrivers; i++) {
00640             driverList[i]->pPrevACMDriverID = (i > 0) ? driverList[i - 1] : NULL;
00641             driverList[i]->pNextACMDriverID = (i < iNumDrivers - 1) ? driverList[i + 1] : NULL;
00642         }
00643         MSACM_pFirstACMDriverID = driverList[0];
00644         MSACM_pLastACMDriverID = driverList[iNumDrivers - 1];
00645     }
00646     
00647 errCleanUp:
00648     if (hPriorityKey != NULL) RegCloseKey(hPriorityKey);
00649     HeapFree(MSACM_hHeap, 0, driverList);
00650 }
00651 
00652 /***********************************************************************
00653  *           MSACM_WriteCurrentPriorities()
00654  * Writes out current order of driver priorities to registry key:
00655  * HKCU\\Software\\Microsoft\\Multimedia\\Audio Compression Manager\\Priority v4.00
00656  */
00657 void MSACM_WriteCurrentPriorities(void)
00658 {
00659     LONG lError;
00660     HKEY hPriorityKey;
00661     static const WCHAR basePriorityKey[] = {
00662         'S','o','f','t','w','a','r','e','\\',
00663         'M','i','c','r','o','s','o','f','t','\\',
00664         'M','u','l','t','i','m','e','d','i','a','\\',
00665         'A','u','d','i','o',' ','C','o','m','p','r','e','s','s','i','o','n',' ','M','a','n','a','g','e','r','\\',
00666         'P','r','i','o','r','i','t','y',' ','v','4','.','0','0','\0'
00667     };
00668     PWINE_ACMDRIVERID padid;
00669     DWORD dwPriorityCounter;
00670     static const WCHAR priorityTmpl[] = {'P','r','i','o','r','i','t','y','%','l','d','\0'};
00671     static const WCHAR valueTmpl[] = {'%','c',',',' ','%','s','\0'};
00672     static const WCHAR converterAlias[] = {'I','n','t','e','r','n','a','l',' ','P','C','M',' ','C','o','n','v','e','r','t','e','r','\0'};
00673     WCHAR szSubKey[17];
00674     WCHAR szBuffer[256];
00675 
00676     /* Delete ACM priority key and create it anew */
00677     lError = RegDeleteKeyW(HKEY_CURRENT_USER, basePriorityKey);
00678     if (lError != ERROR_SUCCESS && lError != ERROR_FILE_NOT_FOUND) {
00679         ERR("unable to remove current key %s (0x%08x) - priority changes won't persist past application end.\n",
00680             debugstr_w(basePriorityKey), lError);
00681         return;
00682     }
00683     lError = RegCreateKeyW(HKEY_CURRENT_USER, basePriorityKey, &hPriorityKey);
00684     if (lError != ERROR_SUCCESS) {
00685         ERR("unable to create key %s (0x%08x) - priority changes won't persist past application end.\n",
00686             debugstr_w(basePriorityKey), lError);
00687         return;
00688     }
00689     
00690     /* Write current list of priorities */
00691     for (dwPriorityCounter = 0, padid = MSACM_pFirstACMDriverID; padid; padid = padid->pNextACMDriverID) {        
00692         if (padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_LOCAL) continue;
00693         if (padid->pszDriverAlias == NULL) continue;    /* internal PCM converter is last */
00694 
00695         /* Build required value name */
00696         dwPriorityCounter++;
00697         snprintfW(szSubKey, 17, priorityTmpl, dwPriorityCounter);
00698         
00699         /* Value has a 1 in front for enabled drivers and 0 for disabled drivers */
00700         snprintfW(szBuffer, 256, valueTmpl, (padid->fdwSupport & ACMDRIVERDETAILS_SUPPORTF_DISABLED) ? '0' : '1', padid->pszDriverAlias);
00701         strlwrW(szBuffer);
00702         
00703         lError = RegSetValueExW(hPriorityKey, szSubKey, 0, REG_SZ, (BYTE *)szBuffer, (strlenW(szBuffer) + 1) * sizeof(WCHAR));
00704         if (lError != ERROR_SUCCESS) {
00705             ERR("unable to write value for %s under key %s (0x%08x)\n",
00706                 debugstr_w(padid->pszDriverAlias), debugstr_w(basePriorityKey), lError);
00707         }
00708     }
00709     
00710     /* Build required value name */
00711     dwPriorityCounter++;
00712     snprintfW(szSubKey, 17, priorityTmpl, dwPriorityCounter);
00713         
00714     /* Value has a 1 in front for enabled drivers and 0 for disabled drivers */
00715     snprintfW(szBuffer, 256, valueTmpl, '1', converterAlias);
00716         
00717     lError = RegSetValueExW(hPriorityKey, szSubKey, 0, REG_SZ, (BYTE *)szBuffer, (strlenW(szBuffer) + 1) * sizeof(WCHAR));
00718     if (lError != ERROR_SUCCESS) {
00719         ERR("unable to write value for %s under key %s (0x%08x)\n",
00720             debugstr_w(converterAlias), debugstr_w(basePriorityKey), lError);
00721     }
00722     RegCloseKey(hPriorityKey);
00723 }
00724 
00725 static PWINE_ACMLOCALDRIVER MSACM_pFirstACMLocalDriver;
00726 static PWINE_ACMLOCALDRIVER MSACM_pLastACMLocalDriver;
00727 
00728 static PWINE_ACMLOCALDRIVER MSACM_UnregisterLocalDriver(PWINE_ACMLOCALDRIVER paldrv)
00729 {
00730     PWINE_ACMLOCALDRIVER pNextACMLocalDriver;
00731 
00732     if (paldrv->pACMInstList) {
00733         ERR("local driver instances still present after closing all drivers - memory leak\n");
00734         return NULL;
00735     }
00736 
00737     if (paldrv == MSACM_pFirstACMLocalDriver)
00738         MSACM_pFirstACMLocalDriver = paldrv->pNextACMLocalDrv;
00739     if (paldrv == MSACM_pLastACMLocalDriver)
00740         MSACM_pLastACMLocalDriver = paldrv->pPrevACMLocalDrv;
00741 
00742     if (paldrv->pPrevACMLocalDrv)
00743         paldrv->pPrevACMLocalDrv->pNextACMLocalDrv = paldrv->pNextACMLocalDrv;
00744     if (paldrv->pNextACMLocalDrv)
00745         paldrv->pNextACMLocalDrv->pPrevACMLocalDrv = paldrv->pPrevACMLocalDrv;
00746 
00747     pNextACMLocalDriver = paldrv->pNextACMLocalDrv;
00748 
00749     HeapFree(MSACM_hHeap, 0, paldrv);
00750 
00751     return pNextACMLocalDriver;
00752 }
00753 
00754 /***********************************************************************
00755  *           MSACM_UnregisterDriver()
00756  */
00757 PWINE_ACMDRIVERID MSACM_UnregisterDriver(PWINE_ACMDRIVERID p)
00758 {
00759     PWINE_ACMDRIVERID pNextACMDriverID;
00760 
00761     while (p->pACMDriverList)
00762     acmDriverClose((HACMDRIVER) p->pACMDriverList, 0);
00763 
00764     HeapFree(MSACM_hHeap, 0, p->pszDriverAlias);
00765     HeapFree(MSACM_hHeap, 0, p->pszFileName);
00766     HeapFree(MSACM_hHeap, 0, p->aFormatTag);
00767 
00768     if (p == MSACM_pFirstACMDriverID)
00769     MSACM_pFirstACMDriverID = p->pNextACMDriverID;
00770     if (p == MSACM_pLastACMDriverID)
00771     MSACM_pLastACMDriverID = p->pPrevACMDriverID;
00772 
00773     if (p->pPrevACMDriverID)
00774     p->pPrevACMDriverID->pNextACMDriverID = p->pNextACMDriverID;
00775     if (p->pNextACMDriverID)
00776     p->pNextACMDriverID->pPrevACMDriverID = p->pPrevACMDriverID;
00777 
00778     pNextACMDriverID = p->pNextACMDriverID;
00779 
00780     if (p->pLocalDriver) MSACM_UnregisterLocalDriver(p->pLocalDriver);
00781     HeapFree(MSACM_hHeap, 0, p);
00782 
00783     return pNextACMDriverID;
00784 }
00785 
00786 /***********************************************************************
00787  *           MSACM_UnregisterAllDrivers()
00788  */
00789 void MSACM_UnregisterAllDrivers(void)
00790 {
00791     PWINE_ACMNOTIFYWND panwnd = MSACM_pFirstACMNotifyWnd;
00792     PWINE_ACMDRIVERID p = MSACM_pFirstACMDriverID;
00793 
00794     while (p) {
00795     MSACM_WriteCache(p);
00796     p = MSACM_UnregisterDriver(p);
00797     }
00798     
00799     while (panwnd) {
00800     panwnd = MSACM_UnRegisterNotificationWindow(panwnd);
00801     }
00802 }
00803 
00804 /***********************************************************************
00805  *           MSACM_GetObj()
00806  */
00807 PWINE_ACMOBJ MSACM_GetObj(HACMOBJ hObj, DWORD type)
00808 {
00809     PWINE_ACMOBJ    pao = (PWINE_ACMOBJ)hObj;
00810 
00811     if (pao == NULL || IsBadReadPtr(pao, sizeof(WINE_ACMOBJ)) ||
00812     ((type != WINE_ACMOBJ_DONTCARE) && (type != pao->dwType)))
00813     return NULL;
00814     return pao;
00815 }
00816 
00817 /***********************************************************************
00818  *           MSACM_GetDriverID()
00819  */
00820 PWINE_ACMDRIVERID MSACM_GetDriverID(HACMDRIVERID hDriverID)
00821 {
00822     return (PWINE_ACMDRIVERID)MSACM_GetObj((HACMOBJ)hDriverID, WINE_ACMOBJ_DRIVERID);
00823 }
00824 
00825 /***********************************************************************
00826  *           MSACM_GetDriver()
00827  */
00828 PWINE_ACMDRIVER MSACM_GetDriver(HACMDRIVER hDriver)
00829 {
00830     return (PWINE_ACMDRIVER)MSACM_GetObj((HACMOBJ)hDriver, WINE_ACMOBJ_DRIVER);
00831 }
00832 
00833 /***********************************************************************
00834  *           MSACM_GetNotifyWnd()
00835  */
00836 PWINE_ACMNOTIFYWND MSACM_GetNotifyWnd(HACMDRIVERID hDriver)
00837 {
00838     return (PWINE_ACMNOTIFYWND)MSACM_GetObj((HACMOBJ)hDriver, WINE_ACMOBJ_NOTIFYWND);
00839 }
00840 
00841 /***********************************************************************
00842  *           MSACM_GetLocalDriver()
00843  */
00844 /* 
00845 PWINE_ACMLOCALDRIVER MSACM_GetLocalDriver(HACMDRIVER hDriver)
00846 {
00847     return (PWINE_ACMLOCALDRIVER)MSACM_GetObj((HACMOBJ)hDriver, WINE_ACMOBJ_LOCALDRIVER);
00848 }
00849 */
00850 #define MSACM_DRIVER_SendMessage(PDRVRINST, msg, lParam1, lParam2) \
00851         (PDRVRINST)->pLocalDriver->lpDrvProc((PDRVRINST)->dwDriverID, (HDRVR)(PDRVRINST), msg, lParam1, lParam2)
00852 
00853 /***********************************************************************
00854  *           MSACM_Message()
00855  */
00856 MMRESULT MSACM_Message(HACMDRIVER had, UINT uMsg, LPARAM lParam1, LPARAM lParam2)
00857 {
00858     PWINE_ACMDRIVER pad = MSACM_GetDriver(had);
00859 
00860     if (!pad) return MMSYSERR_INVALHANDLE;
00861     if (pad->hDrvr) return SendDriverMessage(pad->hDrvr, uMsg, lParam1, lParam2);
00862     if (pad->pLocalDrvrInst) return MSACM_DRIVER_SendMessage(pad->pLocalDrvrInst, uMsg, lParam1, lParam2);
00863 
00864     return MMSYSERR_INVALHANDLE;
00865 }
00866 
00867 PWINE_ACMLOCALDRIVER MSACM_RegisterLocalDriver(HMODULE hModule, DRIVERPROC lpDriverProc)
00868 {
00869     PWINE_ACMLOCALDRIVER paldrv;
00870 
00871     TRACE("(%p, %p)\n", hModule, lpDriverProc);
00872     if (!hModule || !lpDriverProc) return NULL;
00873     
00874     /* look up previous instance of local driver module */
00875     for (paldrv = MSACM_pFirstACMLocalDriver; paldrv; paldrv = paldrv->pNextACMLocalDrv)
00876     {
00877         if (paldrv->hModule == hModule && paldrv->lpDrvProc == lpDriverProc) return paldrv;
00878     }
00879 
00880     paldrv = HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMLOCALDRIVER));
00881     paldrv->obj.dwType = WINE_ACMOBJ_LOCALDRIVER;
00882     paldrv->obj.pACMDriverID = 0;
00883     paldrv->hModule = hModule;
00884     paldrv->lpDrvProc = lpDriverProc;
00885     paldrv->pACMInstList = NULL;
00886 
00887     paldrv->pNextACMLocalDrv = NULL;
00888     paldrv->pPrevACMLocalDrv = MSACM_pLastACMLocalDriver;
00889     if (MSACM_pLastACMLocalDriver)
00890     MSACM_pLastACMLocalDriver->pNextACMLocalDrv = paldrv;
00891     MSACM_pLastACMLocalDriver = paldrv;
00892     if (!MSACM_pFirstACMLocalDriver)
00893     MSACM_pFirstACMLocalDriver = paldrv;
00894 
00895     return paldrv;
00896 }
00897 
00898 /**************************************************************************
00899  *          MSACM_GetNumberOfModuleRefs     [internal]
00900  *
00901  * Returns the number of open drivers which share the same module.
00902  * Inspired from implementation in dlls/winmm/driver.c
00903  */
00904 static unsigned MSACM_GetNumberOfModuleRefs(HMODULE hModule, DRIVERPROC lpDrvProc, WINE_ACMLOCALDRIVERINST ** found)
00905 {
00906     PWINE_ACMLOCALDRIVER lpDrv;
00907     unsigned        count = 0;
00908 
00909     if (found) *found = NULL;
00910     for (lpDrv = MSACM_pFirstACMLocalDriver; lpDrv; lpDrv = lpDrv->pNextACMLocalDrv)
00911     {
00912     if (lpDrv->hModule == hModule && lpDrv->lpDrvProc == lpDrvProc)
00913         {
00914             PWINE_ACMLOCALDRIVERINST pInst = lpDrv->pACMInstList;
00915         
00916         while (pInst) {
00917                 if (found && !*found) *found = pInst;
00918             count++;
00919             pInst = pInst->pNextACMInst;
00920         }
00921     }
00922     }
00923     return count;
00924 }
00925 
00926 /**************************************************************************
00927  *              MSACM_RemoveFromList        [internal]
00928  *
00929  * Generates all the logic to handle driver closure / deletion
00930  * Removes a driver struct to the list of open drivers.
00931  */
00932 static  BOOL    MSACM_RemoveFromList(PWINE_ACMLOCALDRIVERINST lpDrv)
00933 {
00934     PWINE_ACMLOCALDRIVER pDriverBase = lpDrv->pLocalDriver;
00935     PWINE_ACMLOCALDRIVERINST pPrevInst;
00936 
00937     /* last of this driver in list ? */
00938     if (MSACM_GetNumberOfModuleRefs(pDriverBase->hModule, pDriverBase->lpDrvProc, NULL) == 1) {
00939         MSACM_DRIVER_SendMessage(lpDrv, DRV_DISABLE, 0L, 0L);
00940         MSACM_DRIVER_SendMessage(lpDrv, DRV_FREE,    0L, 0L);
00941     }
00942     
00943     pPrevInst = NULL;
00944     if (pDriverBase->pACMInstList != lpDrv) {
00945         pPrevInst = pDriverBase->pACMInstList;
00946         while (pPrevInst && pPrevInst->pNextACMInst != lpDrv)
00947             pPrevInst = pPrevInst->pNextACMInst;
00948         if (!pPrevInst) {
00949             ERR("requested to remove invalid instance %p\n", pPrevInst);
00950             return FALSE;
00951         }
00952     }
00953     if (!pPrevInst) {
00954         /* first driver instance on list */
00955         pDriverBase->pACMInstList = lpDrv->pNextACMInst;
00956     } else {
00957         pPrevInst->pNextACMInst = lpDrv->pNextACMInst;
00958     }
00959     return TRUE;
00960 }
00961 
00962 /**************************************************************************
00963  *              MSACM_AddToList     [internal]
00964  *
00965  * Adds a driver struct to the list of open drivers.
00966  * Generates all the logic to handle driver creation / open.
00967  */
00968 static  BOOL    MSACM_AddToList(PWINE_ACMLOCALDRIVERINST lpNewDrv, LPARAM lParam2)
00969 {
00970     PWINE_ACMLOCALDRIVER pDriverBase = lpNewDrv->pLocalDriver;
00971 
00972     /* first of this driver in list ? */
00973     if (MSACM_GetNumberOfModuleRefs(pDriverBase->hModule, pDriverBase->lpDrvProc, NULL) == 0) {
00974         if (MSACM_DRIVER_SendMessage(lpNewDrv, DRV_LOAD, 0L, 0L) != DRV_SUCCESS) {
00975             FIXME("DRV_LOAD failed on driver %p\n", lpNewDrv);
00976             return FALSE;
00977         }
00978         /* returned value is not checked */
00979         MSACM_DRIVER_SendMessage(lpNewDrv, DRV_ENABLE, 0L, 0L);
00980     }
00981 
00982     lpNewDrv->pNextACMInst = NULL;
00983     if (pDriverBase->pACMInstList == NULL) {
00984     pDriverBase->pACMInstList = lpNewDrv;
00985     } else {
00986         PWINE_ACMLOCALDRIVERINST lpDrvInst = pDriverBase->pACMInstList;
00987     
00988         while (lpDrvInst->pNextACMInst != NULL)
00989             lpDrvInst = lpDrvInst->pNextACMInst;
00990 
00991     lpDrvInst->pNextACMInst = lpNewDrv;
00992     }
00993 
00994     /* Now just open a new instance of a driver on this module */
00995     lpNewDrv->dwDriverID = MSACM_DRIVER_SendMessage(lpNewDrv, DRV_OPEN, 0, lParam2);
00996 
00997     if (lpNewDrv->dwDriverID == 0) {
00998         FIXME("DRV_OPEN failed on driver %p\n", lpNewDrv);
00999         MSACM_RemoveFromList(lpNewDrv);
01000         return FALSE;
01001     }
01002     return TRUE;
01003 }
01004 
01005 PWINE_ACMLOCALDRIVERINST MSACM_OpenLocalDriver(PWINE_ACMLOCALDRIVER paldrv, LPARAM lParam2)
01006 {
01007     PWINE_ACMLOCALDRIVERINST pDrvInst;
01008     
01009     pDrvInst = HeapAlloc(MSACM_hHeap, 0, sizeof(WINE_ACMLOCALDRIVERINST));
01010     if (!pDrvInst)
01011         return NULL;
01012 
01013     pDrvInst->pLocalDriver = paldrv;
01014     pDrvInst->dwDriverID = 0;
01015     pDrvInst->pNextACMInst = NULL;
01016     pDrvInst->bSession = FALSE;
01017     
01018     /* Win32 installable drivers must support a two phase opening scheme:
01019      * + first open with NULL as lParam2 (session instance),
01020      * + then do a second open with the real non null lParam2)
01021      */
01022     if (MSACM_GetNumberOfModuleRefs(paldrv->hModule, paldrv->lpDrvProc, NULL) == 0 && lParam2)
01023     {
01024         PWINE_ACMLOCALDRIVERINST   ret;
01025 
01026         if (!MSACM_AddToList(pDrvInst, 0L))
01027         {
01028             ERR("load0 failed\n");
01029             goto exit;
01030         }
01031         ret = MSACM_OpenLocalDriver(paldrv, lParam2);
01032         if (!ret)
01033         {
01034             ERR("load1 failed\n");
01035             /* If MSACM_CloseLocalDriver returns TRUE,
01036              * then pDrvInst has been freed
01037              */
01038             if (!MSACM_CloseLocalDriver(pDrvInst))
01039                 goto exit;
01040 
01041             return NULL;
01042         }
01043         pDrvInst->bSession = TRUE;
01044         return ret;
01045     }
01046     
01047     if (!MSACM_AddToList(pDrvInst, lParam2))
01048     {
01049         ERR("load failed\n");
01050         goto exit;
01051     }
01052 
01053     TRACE("=> %p\n", pDrvInst);
01054     return pDrvInst;
01055 exit:
01056     HeapFree(MSACM_hHeap, 0, pDrvInst);
01057     return NULL;
01058 }
01059 
01060 LRESULT MSACM_CloseLocalDriver(PWINE_ACMLOCALDRIVERINST paldrv)
01061 {
01062     if (MSACM_RemoveFromList(paldrv)) {
01063         PWINE_ACMLOCALDRIVERINST lpDrv0;
01064         PWINE_ACMLOCALDRIVER pDriverBase = paldrv->pLocalDriver;
01065     
01066         MSACM_DRIVER_SendMessage(paldrv, DRV_CLOSE, 0, 0);
01067         paldrv->dwDriverID = 0;
01068     
01069         if (paldrv->bSession)
01070             ERR("should not directly close session instance (%p)\n", paldrv);
01071 
01072         /* if driver has an opened session instance, we have to close it too */
01073         if (MSACM_GetNumberOfModuleRefs(pDriverBase->hModule, pDriverBase->lpDrvProc, &lpDrv0) == 1 &&
01074                 lpDrv0->bSession)
01075         {
01076             MSACM_DRIVER_SendMessage(lpDrv0, DRV_CLOSE, 0L, 0L);
01077             lpDrv0->dwDriverID = 0;
01078             MSACM_RemoveFromList(lpDrv0);
01079             HeapFree(GetProcessHeap(), 0, lpDrv0);
01080         }
01081 
01082         HeapFree(MSACM_hHeap, 0, paldrv);
01083         return TRUE;
01084     }
01085     ERR("unable to close driver instance\n");
01086     return FALSE;
01087 }

Generated on Sat May 26 2012 04:17:03 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.