Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

309 lines
7.5KB

  1. #include <windows.h>
  2. #include "iasiodrv.h"
  3. #include "asiolist.h"
  4. #define ASIODRV_DESC "description"
  5. #define INPROC_SERVER "InprocServer32"
  6. #define ASIO_PATH "software\\asio"
  7. #define COM_CLSID "clsid"
  8. // ******************************************************************
  9. // Local Functions
  10. // ******************************************************************
  11. static LONG findDrvPath (char *clsidstr,char *dllpath,int dllpathsize)
  12. {
  13. HKEY hkEnum,hksub,hkpath;
  14. char databuf[512];
  15. LONG cr,rc = -1;
  16. DWORD datatype,datasize;
  17. DWORD index;
  18. OFSTRUCT ofs;
  19. HFILE hfile;
  20. BOOL found = FALSE;
  21. #ifdef UNICODE
  22. CharLowerBuffA(clsidstr,strlen(clsidstr));
  23. if ((cr = RegOpenKeyA(HKEY_CLASSES_ROOT,COM_CLSID,&hkEnum)) == ERROR_SUCCESS) {
  24. index = 0;
  25. while (cr == ERROR_SUCCESS && !found) {
  26. cr = RegEnumKeyA(hkEnum,index++,databuf,512);
  27. if (cr == ERROR_SUCCESS) {
  28. CharLowerBuffA(databuf,strlen(databuf));
  29. if (!(strcmp(databuf,clsidstr))) {
  30. if ((cr = RegOpenKeyExA(hkEnum,databuf,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {
  31. if ((cr = RegOpenKeyExA(hksub,INPROC_SERVER,0,KEY_READ,&hkpath)) == ERROR_SUCCESS) {
  32. datatype = REG_SZ; datasize = (DWORD)dllpathsize;
  33. cr = RegQueryValueEx(hkpath,0,0,&datatype,(LPBYTE)dllpath,&datasize);
  34. if (cr == ERROR_SUCCESS) {
  35. memset(&ofs,0,sizeof(OFSTRUCT));
  36. ofs.cBytes = sizeof(OFSTRUCT);
  37. hfile = OpenFile(dllpath,&ofs,OF_EXIST);
  38. if (hfile) rc = 0;
  39. }
  40. RegCloseKey(hkpath);
  41. }
  42. RegCloseKey(hksub);
  43. }
  44. found = TRUE; // break out
  45. }
  46. }
  47. }
  48. RegCloseKey(hkEnum);
  49. }
  50. #else
  51. CharLowerBuff(clsidstr,strlen(clsidstr));
  52. if ((cr = RegOpenKey(HKEY_CLASSES_ROOT,COM_CLSID,&hkEnum)) == ERROR_SUCCESS) {
  53. index = 0;
  54. while (cr == ERROR_SUCCESS && !found) {
  55. cr = RegEnumKey(hkEnum,index++,databuf,512);
  56. if (cr == ERROR_SUCCESS) {
  57. CharLowerBuff(databuf,strlen(databuf));
  58. if (!(strcmp(databuf,clsidstr))) {
  59. if ((cr = RegOpenKeyEx(hkEnum,databuf,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {
  60. if ((cr = RegOpenKeyEx(hksub,INPROC_SERVER,0,KEY_READ,&hkpath)) == ERROR_SUCCESS) {
  61. datatype = REG_SZ; datasize = (DWORD)dllpathsize;
  62. cr = RegQueryValueEx(hkpath,0,0,&datatype,(LPBYTE)dllpath,&datasize);
  63. if (cr == ERROR_SUCCESS) {
  64. memset(&ofs,0,sizeof(OFSTRUCT));
  65. ofs.cBytes = sizeof(OFSTRUCT);
  66. hfile = OpenFile(dllpath,&ofs,OF_EXIST);
  67. if (hfile) rc = 0;
  68. }
  69. RegCloseKey(hkpath);
  70. }
  71. RegCloseKey(hksub);
  72. }
  73. found = TRUE; // break out
  74. }
  75. }
  76. }
  77. RegCloseKey(hkEnum);
  78. }
  79. #endif
  80. return rc;
  81. }
  82. static LPASIODRVSTRUCT newDrvStruct (HKEY hkey,char *keyname,int drvID,LPASIODRVSTRUCT lpdrv)
  83. {
  84. HKEY hksub;
  85. char databuf[256];
  86. char dllpath[MAXPATHLEN];
  87. WORD wData[100];
  88. CLSID clsid;
  89. DWORD datatype,datasize;
  90. LONG cr,rc;
  91. if (!lpdrv) {
  92. if ((cr = RegOpenKeyExA(hkey,keyname,0,KEY_READ,&hksub)) == ERROR_SUCCESS) {
  93. datatype = REG_SZ; datasize = 256;
  94. cr = RegQueryValueExA(hksub,COM_CLSID,0,&datatype,(LPBYTE)databuf,&datasize);
  95. if (cr == ERROR_SUCCESS) {
  96. rc = findDrvPath (databuf,dllpath,MAXPATHLEN);
  97. if (rc == 0) {
  98. lpdrv = new ASIODRVSTRUCT[1];
  99. if (lpdrv) {
  100. memset(lpdrv,0,sizeof(ASIODRVSTRUCT));
  101. lpdrv->drvID = drvID;
  102. MultiByteToWideChar(CP_ACP,0,(LPCSTR)databuf,-1,(LPWSTR)wData,100);
  103. if ((cr = CLSIDFromString((LPOLESTR)wData,(LPCLSID)&clsid)) == S_OK) {
  104. memcpy(&lpdrv->clsid,&clsid,sizeof(CLSID));
  105. }
  106. datatype = REG_SZ; datasize = 256;
  107. cr = RegQueryValueExA(hksub,ASIODRV_DESC,0,&datatype,(LPBYTE)databuf,&datasize);
  108. if (cr == ERROR_SUCCESS) {
  109. strcpy(lpdrv->drvname,databuf);
  110. }
  111. else strcpy(lpdrv->drvname,keyname);
  112. }
  113. }
  114. }
  115. RegCloseKey(hksub);
  116. }
  117. }
  118. else lpdrv->next = newDrvStruct(hkey,keyname,drvID+1,lpdrv->next);
  119. return lpdrv;
  120. }
  121. static void deleteDrvStruct (LPASIODRVSTRUCT lpdrv)
  122. {
  123. IASIO *iasio;
  124. if (lpdrv != 0) {
  125. deleteDrvStruct(lpdrv->next);
  126. if (lpdrv->asiodrv) {
  127. iasio = (IASIO *)lpdrv->asiodrv;
  128. iasio->Release();
  129. }
  130. delete lpdrv;
  131. }
  132. }
  133. static LPASIODRVSTRUCT getDrvStruct (int drvID,LPASIODRVSTRUCT lpdrv)
  134. {
  135. while (lpdrv) {
  136. if (lpdrv->drvID == drvID) return lpdrv;
  137. lpdrv = lpdrv->next;
  138. }
  139. return 0;
  140. }
  141. // ******************************************************************
  142. // ******************************************************************
  143. // AsioDriverList
  144. // ******************************************************************
  145. AsioDriverList::AsioDriverList ()
  146. {
  147. HKEY hkEnum = 0;
  148. char keyname[MAXDRVNAMELEN];
  149. LPASIODRVSTRUCT pdl;
  150. LONG cr;
  151. DWORD index = 0;
  152. BOOL fin = FALSE;
  153. numdrv = 0;
  154. lpdrvlist = 0;
  155. #ifdef UNICODE
  156. cr = RegOpenKeyA(HKEY_LOCAL_MACHINE,ASIO_PATH,&hkEnum);
  157. #else
  158. cr = RegOpenKey(HKEY_LOCAL_MACHINE,ASIO_PATH,&hkEnum);
  159. #endif
  160. while (cr == ERROR_SUCCESS) {
  161. #ifdef UNICODE
  162. if ((cr = RegEnumKeyA(hkEnum,index++,keyname,MAXDRVNAMELEN))== ERROR_SUCCESS) {
  163. #else
  164. if ((cr = RegEnumKey(hkEnum,index++,keyname,MAXDRVNAMELEN))== ERROR_SUCCESS) {
  165. #endif
  166. lpdrvlist = newDrvStruct (hkEnum,keyname,0,lpdrvlist);
  167. }
  168. else fin = TRUE;
  169. }
  170. if (hkEnum) RegCloseKey(hkEnum);
  171. pdl = lpdrvlist;
  172. while (pdl) {
  173. numdrv++;
  174. pdl = pdl->next;
  175. }
  176. if (numdrv) CoInitialize(0); // initialize COM
  177. }
  178. AsioDriverList::~AsioDriverList ()
  179. {
  180. if (numdrv) {
  181. deleteDrvStruct(lpdrvlist);
  182. CoUninitialize();
  183. }
  184. }
  185. LONG AsioDriverList::asioGetNumDev (VOID)
  186. {
  187. return (LONG)numdrv;
  188. }
  189. LONG AsioDriverList::asioOpenDriver (int drvID,LPVOID *asiodrv)
  190. {
  191. LPASIODRVSTRUCT lpdrv = 0;
  192. long rc;
  193. if (!asiodrv) return DRVERR_INVALID_PARAM;
  194. if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
  195. if (!lpdrv->asiodrv) {
  196. rc = CoCreateInstance(lpdrv->clsid,0,CLSCTX_INPROC_SERVER,lpdrv->clsid,asiodrv);
  197. if (rc == S_OK) {
  198. lpdrv->asiodrv = *asiodrv;
  199. return 0;
  200. }
  201. // else if (rc == REGDB_E_CLASSNOTREG)
  202. // strcpy (info->messageText, "Driver not registered in the Registration Database!");
  203. }
  204. else rc = DRVERR_DEVICE_ALREADY_OPEN;
  205. }
  206. else rc = DRVERR_DEVICE_NOT_FOUND;
  207. return rc;
  208. }
  209. LONG AsioDriverList::asioCloseDriver (int drvID)
  210. {
  211. LPASIODRVSTRUCT lpdrv = 0;
  212. IASIO *iasio;
  213. if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
  214. if (lpdrv->asiodrv) {
  215. iasio = (IASIO *)lpdrv->asiodrv;
  216. iasio->Release();
  217. lpdrv->asiodrv = 0;
  218. }
  219. }
  220. return 0;
  221. }
  222. LONG AsioDriverList::asioGetDriverName (int drvID,char *drvname,int drvnamesize)
  223. {
  224. LPASIODRVSTRUCT lpdrv = 0;
  225. if (!drvname) return DRVERR_INVALID_PARAM;
  226. if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
  227. if (strlen(lpdrv->drvname) < (unsigned int)drvnamesize) {
  228. strcpy(drvname,lpdrv->drvname);
  229. }
  230. else {
  231. memcpy(drvname,lpdrv->drvname,drvnamesize-4);
  232. drvname[drvnamesize-4] = '.';
  233. drvname[drvnamesize-3] = '.';
  234. drvname[drvnamesize-2] = '.';
  235. drvname[drvnamesize-1] = 0;
  236. }
  237. return 0;
  238. }
  239. return DRVERR_DEVICE_NOT_FOUND;
  240. }
  241. LONG AsioDriverList::asioGetDriverPath (int drvID,char *dllpath,int dllpathsize)
  242. {
  243. LPASIODRVSTRUCT lpdrv = 0;
  244. if (!dllpath) return DRVERR_INVALID_PARAM;
  245. if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
  246. if (strlen(lpdrv->dllpath) < (unsigned int)dllpathsize) {
  247. strcpy(dllpath,lpdrv->dllpath);
  248. return 0;
  249. }
  250. dllpath[0] = 0;
  251. return DRVERR_INVALID_PARAM;
  252. }
  253. return DRVERR_DEVICE_NOT_FOUND;
  254. }
  255. LONG AsioDriverList::asioGetDriverCLSID (int drvID,CLSID *clsid)
  256. {
  257. LPASIODRVSTRUCT lpdrv = 0;
  258. if (!clsid) return DRVERR_INVALID_PARAM;
  259. if ((lpdrv = getDrvStruct(drvID,lpdrvlist)) != 0) {
  260. memcpy(clsid,&lpdrv->clsid,sizeof(CLSID));
  261. return 0;
  262. }
  263. return DRVERR_DEVICE_NOT_FOUND;
  264. }