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