WASAPI GetDisplayName von "Systemsounds" auflösen



  • Hi
    bin momentan dabei, mich mit der Vista/7 audio-api, der WASAPI, auseinanderzusetzen (soll mal zur steuerung der session-volumes dienen, z.B. als plugin für automatisierungssoftware)
    ich schaffe es auch (ok, mit mehr oder weniger "kopierter" code 😉 aus msdn und so)
    -endpoints zu enumerieren
    -sessions zu enumerieren (btw. da war m*crosoft ma wieder absolut inkonsequent -.-, bei xp-ja, vista-nein und 7 wieder ja)
    -ein ISimpleAudioVolume auf die Enumerierten Sessions zu erhalten
    -den dazu passenden IAudioSessionControl bzw. IAudioSessionControl2 zu erhalten
    -die beiden interfaces anzusprechen (einfache funktionen)

    momentan hänge ich aber ein wenig an der zuordnung der sessions. gibt zwar funktionen für pid und groups, jedoch auch die funktion IAudioSessionControl(2)::GetDisplayName(LPWSTR *pRetVal). Mit dieser erhalte ich auch ein wchar_t array, in dem der angegebene DisplayName steht (so wie im lautstärkemixer zu sehen; ok, bei den meisten programmen nicht angegeben sondern aus fenstertitel ua. genommen, steht auch in den remarks von getdisplayname, dass sndvol das so macht).

    Das heißt, nicht der DisplayName im klartext (nicht immer, es kann auch ein direkt verwendeter string drinstehn), sondern ein pfad mit einer (resourcen- ?) id.
    Also statt "Systemsounds" steht da "@%SystemRoot%\System32\AudioSrv.Dll,-202" (ohne anführungszeichen).
    ->folgende versuche beziehen sich auf systemsounds, jedoch suche ich eine möglichkeit, mit der sich diese strings generell auflösen lassen.<-
    Ich dachte mir, schauste halt ma schnell die audiosrv.dll mit resourcehacker an, jedoch hat die keine passende resource.
    Dann hab ich versucht, mit Loadlibrary(L"@%SystemRoot%\\System32\\AudioSrv.Dll") oder GetModuleHandle(...s.o.) iwie diese dll zu öffnen, aber ich bekomme immer einen 126 (ERROR_MOD_NOT_FOUND) zurück.
    Ich bekomme diese datei irgendwie nicht geöffnet.
    Dann habe ich (kp, warum) im registrierungs-editor nach dem dll-pfad mit der nummer gesucht. wider erwarten hab ich sogar einige treffer gehabt. Diese waren immer in einem ???/Local Settings/MUICache/96/46693477, verschiedene pfade, nur diese letzten 4 ebenen sind immer gleich, mit dem string als wert-name und "systemsounds" als wert-daten.
    Aber ich kann das doch nicht als aus der registry (aus irgendwelchen caches oder sogar an wechselnden orten??) laden oder gar hardcoden??
    Übrigens steht (z.B. in den remarks) der GetDisplayName Funktion nichts zu irgendwelchen string-verweisen.

    Frage: wisst ihr eine methode, diese strings vernünftig und "irgendwie korrekt" aufzulösen?
    Oder habe ich diesen string gar völlig falsch interpretiert und muss wo ganz anders ansetzen?

    Danke im voraus und ich freue mich auf antworten 😉

    Ele



  • ahhh...
    hab ne ziemlich lange zeit gebraucht, um auf ne doch recht einfache lösung zu kommen.
    Mit LoadLibraryEx(L"C:\\Windows\\System32\\AudioSrv.Dll",NULL,LOAD_LIBRARY_AS_DATAFILE) funktionierts wie gewünscht.

    Hab mir dann auch gleich ne Funktion gebastelt, die den gesamten "Referenz"-String in den Menschenlesbaren umwandelt

    #define RSR_RET_NOERR 0
    #define RSR_RET_INTFUNCERR -1
    #define RSR_RET_STRERR -2
    #define RSR_RET_PTRERR -3
    
    int ReplaceStringRef(LPCWSTR pIn, LPWSTR *pOut)
    {
    	LPWSTR tmpOut;
    	int outStrLen=0;
    	if(pIn[0]=='@') //handelt es sich um einen "Referenz-String"?
    	{
    
    		int commapos;
    		for(commapos=wcslen(pIn);commapos>0&&pIn[commapos]!=',';commapos--);
    		if(commapos==0)
    		{
    			return RSR_RET_STRERR;
    		}
    		LPWSTR lpPathTmp=new wchar_t[commapos+1];
    		LPWSTR lpRefNum=new wchar_t[wcslen(pIn)-commapos-1];
    		wcsncpy_s(lpPathTmp,commapos+1,pIn+1,commapos-1);
    		wcsncpy_s(lpRefNum,wcslen(pIn)-commapos-1,pIn+commapos+2,wcslen(pIn)-commapos-1);
    		int RefNum;
    		swscanf_s(lpRefNum,L"%i",&RefNum);
    		delete [] lpRefNum;
    		DWORD expNeNum=ExpandEnvironmentStrings(lpPathTmp,NULL,0);
    		if(expNeNum==0)
    		{
    			delete [] lpPathTmp;
    			return RSR_RET_INTFUNCERR;
    		}
    		LPWSTR lpPath=new wchar_t[expNeNum];
    		if(ExpandEnvironmentStrings(lpPathTmp,lpPath,expNeNum)==0)
    		{
    			delete [] lpPath;
    			return RSR_RET_INTFUNCERR;
    		}
    		delete [] lpPathTmp;
    		HMODULE lib=LoadLibraryEx(lpPath,NULL,LOAD_LIBRARY_AS_DATAFILE);
    		if(lib==0)
    		{
    			delete [] lpPath;
    			return RSR_RET_INTFUNCERR;
    		}
    		delete [] lpPath;
    		for(int i=1;outStrLen==0||outStrLen==(i-1)*32-1;i++)
    		{
    			tmpOut=new wchar_t[i*32];
    			outStrLen=LoadString(lib,RefNum,tmpOut,i*32);
    			if(outStrLen==0)
    			{
    				delete [] tmpOut;
    				FreeLibrary(lib);
    				return RSR_RET_INTFUNCERR;
    			}
    			else if (outStrLen==i*4-1)
    			{
    				delete [] tmpOut;
    			}
    		}
    		outStrLen++;
    		FreeLibrary(lib);
    	}
    	else
    	{
    		outStrLen=wcslen(pIn)+1;
    		tmpOut=new wchar_t[outStrLen];
    		for(int i=0;i<outStrLen;i++)tmpOut[i]=pIn[i];
    	}
    
    	if(pOut==NULL)
    	{
    		delete [] tmpOut;
    		return RSR_RET_PTRERR;
    	}
    	*pOut=new wchar_t[outStrLen]; //String mit der richtigen länge ohne ungenutzte zeichen nach dem 0-Terminator
    	wcsncpy_s(*pOut,outStrLen,tmpOut,outStrLen-1);
    	delete [] tmpOut;
    	return RSR_RET_NOERR;
    }
    

    man muss aber den pointer der ausgabe manuell mit delete [] freigeben.
    funktioniert wie gewollt.
    danke trotzdem für eure mühen 😉

    Ele


Anmelden zum Antworten