windows-nt/Source/XPSP1/NT/multimedia/media/winmm/agfxc.cpp
2020-09-26 16:20:57 +08:00

264 lines
7.8 KiB
C++

// agfxc.cpp : Client side code for agfx.
//
// Created by FrankYe on 7/3/2000
//
#define UNICODE
#define _UNICODE
#include <windows.h>
#include <mmsystem.h>
#include <mmsysp.h>
#include <tchar.h>
#include <regstr.h>
#include <ks.h>
#include <ksmedia.h>
#include "agfxp.h"
#include "audiosrv.h"
#include "audiosrvc.h"
// ISSUE-2000/09/25-FrankYe TODO list
// - move heap helpers somewhere else
// - remove ClientUpdatePnpInfo, and hHeap extern definitions
extern "C" void ClientUpdatePnpInfo(void);
extern "C" HANDLE hHeap;
//
// This global variable tracks the most device interfaces contained in any
// DEVICEINTERFACELIST structure created by these functions. This helps
// validate the input to gfxDestroyDeviceInterfaceList
//
LONG gcMostDeviceInterfaces = 0;
#define RPC_CALL_START RpcTryExcept {
#define RPC_CALL_END_(status) } RpcExcept(1) { status = RpcExceptionCode(); } RpcEndExcept
#define RPC_CALL_END } RpcExcept(1) { RpcExceptionCode(); } RpcEndExcept
//=============================================================================
//=== Heap helpers ===
//=============================================================================
static BOOL HeapFreeIfNotNull(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem)
{
return lpMem ? HeapFree(hHeap, dwFlags, lpMem) : TRUE;
}
//=============================================================================
//=== gfx API ===
//=============================================================================
WINMMAPI LONG WINAPI gfxModifyGfx(DWORD Id, ULONG Order)
{
LONG status;
ClientUpdatePnpInfo();
RPC_CALL_START;
status = s_gfxModifyGfx(Id, Order);
RPC_CALL_END_(status);
return status;
}
WINMMAPI LONG WINAPI gfxAddGfx(IN PCWSTR ZoneFactoryDi, IN PCWSTR GfxFactoryDi, IN ULONG Type, IN ULONG Order, OUT PULONG pNewId)
{
LONG status;
if (IsBadStringPtr(ZoneFactoryDi, (UINT_PTR)(-1))) return ERROR_INVALID_PARAMETER;
if (IsBadStringPtr(GfxFactoryDi, (UINT_PTR)(-1))) return ERROR_INVALID_PARAMETER;
if (IsBadWritePtr(pNewId, sizeof(*pNewId))) return ERROR_INVALID_PARAMETER;
ClientUpdatePnpInfo();
RPC_CALL_START;
status = s_gfxAddGfx((PWSTR)ZoneFactoryDi, (PWSTR)GfxFactoryDi, Type, Order, pNewId);
RPC_CALL_END_(status);
return status;
}
WINMMAPI LONG WINAPI gfxRemoveGfx(DWORD Id)
{
LONG status;
ClientUpdatePnpInfo();
RPC_CALL_START;
status = s_gfxRemoveGfx(Id);
RPC_CALL_END_(status);
return status;
}
WINMMAPI LONG WINAPI gfxDestroyDeviceInterfaceList(PDEVICEINTERFACELIST pDiList)
{
LONG Count;
PTSTR *ppDi;
LONG result;
if (IsBadReadPtr(&pDiList->Count, sizeof(pDiList->Count))) return ERROR_INVALID_PARAMETER;
Count = pDiList->Count;
if (Count < 0 || Count > gcMostDeviceInterfaces) return ERROR_INVALID_PARAMETER;
if (IsBadWritePtr(pDiList, (PBYTE)&pDiList->DeviceInterface[Count] - (PBYTE)pDiList)) return ERROR_INVALID_PARAMETER;
ppDi = &pDiList->DeviceInterface[0];
while (Count-- > 0) if (IsBadStringPtr(*ppDi, (UINT_PTR)(-1))) return ERROR_INVALID_PARAMETER;
// Now we are reasonably confident that we have good input
// parameters. We design the following logic to return the
// first error encountered, if any.
ClientUpdatePnpInfo();
result = NO_ERROR;
Count = pDiList->Count;
ppDi = &pDiList->DeviceInterface[0];
while (Count-- > 0) if (!HeapFree(hHeap, 0, *(ppDi++)) && (NO_ERROR == result)) result = GetLastError();
if ((!HeapFree(hHeap, 0, pDiList)) && (NO_ERROR == result)) result = GetLastError();
SetLastError(result);
return result;
}
WINMMAPI LONG WINAPI gfxEnumerateGfxs(PCWSTR ZoneFactoryDi, GFXENUMCALLBACK pGfxEnumCallback, PVOID Context)
{
LONG lresult;
UNIQUE_PGFXLIST pGfxList = NULL;
if (IsBadStringPtr(ZoneFactoryDi, (UINT_PTR)(-1))) return ERROR_INVALID_PARAMETER;
if (IsBadCodePtr((FARPROC)pGfxEnumCallback)) return ERROR_INVALID_PARAMETER;
ClientUpdatePnpInfo();
RPC_CALL_START;
lresult = s_gfxCreateGfxList((PWSTR)ZoneFactoryDi, &pGfxList);
RPC_CALL_END_(lresult);
// ISSUE-2000/09/25-FrankYe Should not have to check for pGfxList != NULL. Fix this interface
if (!lresult && pGfxList)
{
if (pGfxList->Count > 0)
{
int i = 0;
while (i < pGfxList->Count)
{
if (!lresult) lresult = pGfxEnumCallback(Context,
pGfxList->Gfx[i].Id,
pGfxList->Gfx[i].GfxFactoryDi,
*(LPCLSID)(&pGfxList->Gfx[i].Clsid),
pGfxList->Gfx[i].Type,
pGfxList->Gfx[i].Order);
HeapFree(hHeap, 0, pGfxList->Gfx[i].GfxFactoryDi);
i++;
}
}
HeapFree(hHeap, 0, pGfxList);
}
return lresult;
}
WINMMAPI LONG WINAPI gfxCreateGfxFactoriesList(PCWSTR ZoneFactoryDi, OUT PDEVICEINTERFACELIST *ppDiList)
{
LONG lresult;
UNIQUE_PDILIST pDiList = NULL;
if (IsBadWritePtr(ppDiList, sizeof(*ppDiList))) return ERROR_INVALID_PARAMETER;
ClientUpdatePnpInfo();
RPC_CALL_START;
lresult = s_gfxCreateGfxFactoriesList((PWSTR)ZoneFactoryDi, &pDiList);
RPC_CALL_END_(lresult);
if (!lresult) {
gcMostDeviceInterfaces = max(gcMostDeviceInterfaces, pDiList->Count);
*ppDiList = (PDEVICEINTERFACELIST)pDiList;
}
return lresult;
}
WINMMAPI LONG WINAPI gfxCreateZoneFactoriesList(OUT PDEVICEINTERFACELIST *ppDiList)
{
LONG lresult;
UNIQUE_PDILIST pDiList = NULL;
if (IsBadWritePtr(ppDiList, sizeof(*ppDiList))) return ERROR_INVALID_PARAMETER;
ClientUpdatePnpInfo();
RPC_CALL_START;
lresult = s_gfxCreateZoneFactoriesList(&pDiList);
RPC_CALL_END_(lresult);
if (!lresult) {
gcMostDeviceInterfaces = max(gcMostDeviceInterfaces, pDiList->Count);
*ppDiList = (PDEVICEINTERFACELIST)pDiList;
}
return lresult;
}
WINMMAPI LONG WINAPI gfxBatchChange(PGFXREMOVEREQUEST paGfxRemoveRequests, ULONG cGfxRemoveRequests,
PGFXMODIFYREQUEST paGfxModifyRequests, ULONG cGfxModifyRequests,
PGFXADDREQUEST paGfxAddRequests, ULONG cGfxAddRequests)
{
ULONG Index;
LONG Error;
if ((cGfxRemoveRequests > 0) && IsBadWritePtr(paGfxRemoveRequests, cGfxRemoveRequests * sizeof(*paGfxRemoveRequests))) return ERROR_INVALID_PARAMETER;
if ((cGfxModifyRequests > 0) && IsBadWritePtr(paGfxModifyRequests, cGfxModifyRequests * sizeof(*paGfxModifyRequests))) return ERROR_INVALID_PARAMETER;
if ((cGfxAddRequests > 0) && IsBadWritePtr(paGfxAddRequests, cGfxAddRequests * sizeof(*paGfxAddRequests))) return ERROR_INVALID_PARAMETER;
ClientUpdatePnpInfo();
Error = ERROR_SUCCESS;
for (Index = 0; Index < cGfxRemoveRequests && ERROR_SUCCESS == Error; Index++)
{
Error = gfxRemoveGfx(paGfxRemoveRequests[Index].IdToRemove);
paGfxRemoveRequests[Index].Error = Error;
}
for (Index = 0; Index < cGfxModifyRequests && ERROR_SUCCESS == Error; Index++)
{
Error = gfxModifyGfx(paGfxModifyRequests[Index].IdToModify,
paGfxModifyRequests[Index].NewOrder);
paGfxModifyRequests[Index].Error = Error;
}
for (Index = 0; Index < cGfxAddRequests && ERROR_SUCCESS == Error; Index++)
{
Error = gfxAddGfx(paGfxAddRequests[Index].ZoneFactoryDi,
paGfxAddRequests[Index].GfxFactoryDi,
paGfxAddRequests[Index].Type,
paGfxAddRequests[Index].Order,
&paGfxAddRequests[Index].NewId);
paGfxAddRequests[Index].Error = Error;
}
return Error;
}
WINMMAPI LONG WINAPI gfxOpenGfx(DWORD dwGfxId, PHANDLE pFileHandle)
{
LONG status;
ClientUpdatePnpInfo();
RPC_CALL_START;
status = s_gfxOpenGfx(GetCurrentProcessId(), dwGfxId, (RHANDLE*)pFileHandle);
RPC_CALL_END_(status);
return status;
}
WINMMAPI void WINAPI gfxLogon(DWORD dwProcessId)
{
ClientUpdatePnpInfo();
RPC_CALL_START;
s_gfxLogon(AudioSrv_IfHandle, dwProcessId);
RPC_CALL_END;
}
WINMMAPI void WINAPI gfxLogoff(void)
{
ClientUpdatePnpInfo();
RPC_CALL_START;
s_gfxLogoff();
RPC_CALL_END;
}