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 // ******************************************************************
findDrvPath(char * clsidstr,char * dllpath,int dllpathsize)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 
newDrvStruct(HKEY hkey,char * keyname,int drvID,LPASIODRVSTRUCT lpdrv)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 
deleteDrvStruct(LPASIODRVSTRUCT lpdrv)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 
getDrvStruct(int drvID,LPASIODRVSTRUCT lpdrv)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 // ******************************************************************
AsioDriverList()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 
309