mirror of
https://github.com/reactos/reactos.git
synced 2024-07-11 07:05:12 +00:00
[CMAKE]
Sync trunk up to r50570. svn path=/branches/cmake-bringup/; revision=50581
This commit is contained in:
commit
f22ed7dc10
|
@ -59,6 +59,7 @@ typedef struct
|
|||
|
||||
DWORD Position;
|
||||
HMONITOR Monitor;
|
||||
HMONITOR PreviousMonitor;
|
||||
DWORD DraggingPosition;
|
||||
HMONITOR DraggingMonitor;
|
||||
|
||||
|
@ -230,7 +231,7 @@ ITrayWindowImpl_GetScreenRect(IN OUT ITrayWindowImpl *This,
|
|||
MONITORINFO mi;
|
||||
|
||||
mi.cbSize = sizeof(mi);
|
||||
if (!GetMonitorInfo(This->Monitor,
|
||||
if (!GetMonitorInfo(hMonitor,
|
||||
&mi))
|
||||
{
|
||||
/* Hm, the monitor is gone? Try to find a monitor where it
|
||||
|
@ -639,6 +640,57 @@ ITrayWindowImpl_ApplyClipping(IN OUT ITrayWindowImpl *This,
|
|||
}
|
||||
}
|
||||
|
||||
static VOID
|
||||
ITrayWindowImpl_ResizeWorkArea(IN OUT ITrayWindowImpl *This)
|
||||
{
|
||||
RECT rcTray,rcWorkArea;
|
||||
|
||||
/* If monitor has changed then fix the previous monitors work area */
|
||||
if(This->PreviousMonitor!=This->Monitor)
|
||||
{
|
||||
ITrayWindowImpl_GetScreenRect(This,
|
||||
This->PreviousMonitor,
|
||||
&rcWorkArea);
|
||||
SystemParametersInfo(SPI_SETWORKAREA,
|
||||
1,
|
||||
&rcWorkArea,
|
||||
SPIF_SENDCHANGE);
|
||||
}
|
||||
|
||||
rcTray = This->rcTrayWnd[This->Position];
|
||||
|
||||
ITrayWindowImpl_GetScreenRect(This,
|
||||
This->Monitor,
|
||||
&rcWorkArea);
|
||||
This->PreviousMonitor=This->Monitor;
|
||||
|
||||
/* If AutoHide is false then change the workarea to exclude the area that
|
||||
the taskbar covers. */
|
||||
if(!This->AutoHide)
|
||||
{
|
||||
switch(This->Position)
|
||||
{
|
||||
case ABE_TOP:
|
||||
rcWorkArea.top=rcTray.bottom;
|
||||
break;
|
||||
case ABE_LEFT:
|
||||
rcWorkArea.left=rcTray.right;
|
||||
break;
|
||||
case ABE_RIGHT:
|
||||
rcWorkArea.right=rcTray.left;
|
||||
break;
|
||||
case ABE_BOTTOM:
|
||||
rcWorkArea.bottom=rcTray.top;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SystemParametersInfo(SPI_SETWORKAREA,
|
||||
1,
|
||||
&rcWorkArea,
|
||||
SPIF_SENDCHANGE);
|
||||
}
|
||||
|
||||
static VOID
|
||||
ITrayWindowImpl_CheckTrayWndPosition(IN OUT ITrayWindowImpl *This)
|
||||
{
|
||||
|
@ -656,6 +708,8 @@ ITrayWindowImpl_CheckTrayWndPosition(IN OUT ITrayWindowImpl *This)
|
|||
rcTray.bottom - rcTray.top,
|
||||
SWP_NOZORDER);
|
||||
|
||||
ITrayWindowImpl_ResizeWorkArea(This);
|
||||
|
||||
ITrayWindowImpl_ApplyClipping(This,
|
||||
TRUE);
|
||||
}
|
||||
|
@ -1954,6 +2008,7 @@ TrayWndProc(IN HWND hwnd,
|
|||
|
||||
if (wParam == SIZE_RESTORED && lParam == 0)
|
||||
{
|
||||
ITrayWindowImpl_ResizeWorkArea(This);
|
||||
/* Clip the tray window on multi monitor systems so the edges can't
|
||||
overlap into another monitor */
|
||||
ITrayWindowImpl_ApplyClipping(This,
|
||||
|
|
|
@ -102,9 +102,10 @@ AppearancePageProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
|
||||
g->Theme = g->ThemeAdv;
|
||||
g->bHasChanged = TRUE;
|
||||
g->ThemeId = -1; /* Customized */
|
||||
SendDlgItemMessage(hwndDlg, IDC_APPEARANCE_COLORSCHEME, CB_SETCURSEL, (WPARAM)-1, 0);
|
||||
SetDlgItemText(hwndDlg, IDC_APPEARANCE_COLORSCHEME, TEXT(""));
|
||||
// Effects dialog doesn't change the color scheme, therefore the following lines are commented out, until fixed finally
|
||||
//g->ThemeId = -1; /* Customized */
|
||||
//SendDlgItemMessage(hwndDlg, IDC_APPEARANCE_COLORSCHEME, CB_SETCURSEL, (WPARAM)-1, 0);
|
||||
//SetDlgItemText(hwndDlg, IDC_APPEARANCE_COLORSCHEME, TEXT(""));
|
||||
SendDlgItemMessage(hwndDlg, IDC_APPEARANCE_PREVIEW, PVM_UPDATETHEME, 0, (LPARAM)&g->Theme);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -307,7 +307,7 @@ VOID ApplyTheme(THEME* theme, INT ThemeId)
|
|||
theme->Effects.bTooltipAnimation = theme->Effects.bMenuAnimation;
|
||||
theme->Effects.bTooltipFade = theme->Effects.bMenuFade;
|
||||
SystemParametersInfo(SPI_SETDRAGFULLWINDOWS, theme->Effects.bDragFullWindows, (PVOID)&theme->Effects.bDragFullWindows, SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
|
||||
UPDATE_USERPREF(KEYBOARDCUES, &theme->Effects.bKeyboardCues);
|
||||
SystemParametersInfo(SPI_SETKEYBOARDCUES, 0, IntToPtr(theme->Effects.bKeyboardCues), SPIF_SENDCHANGE | SPIF_UPDATEINIFILE);
|
||||
//UPDATE_USERPREF(ACTIVEWINDOWTRACKING, &theme->Effects.bActiveWindowTracking);
|
||||
//UPDATE_USERPREF(MENUANIMATION, &theme->Effects.bMenuAnimation);
|
||||
//UPDATE_USERPREF(COMBOBOXANIMATION, &theme->Effects.bComboBoxAnimation);
|
||||
|
|
|
@ -599,12 +599,6 @@ GetFullPathNameA (
|
|||
TRACE("GetFullPathNameA(lpFileName %s, nBufferLength %d, lpBuffer %p, "
|
||||
"lpFilePart %p)\n",lpFileName,nBufferLength,lpBuffer,lpFilePart);
|
||||
|
||||
if (!lpFileName)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!(FileNameW = FilenameA2W(lpFileName, FALSE)))
|
||||
return 0;
|
||||
|
||||
|
@ -662,6 +656,14 @@ GetFullPathNameW (
|
|||
TRACE("GetFullPathNameW ret: lpBuffer %S lpFilePart %S Length %ld\n",
|
||||
lpBuffer, (lpFilePart == NULL) ? L"NULL" : *lpFilePart, Length / sizeof(WCHAR));
|
||||
|
||||
if (!lpFileName)
|
||||
{
|
||||
#if (WINVER >= _WIN32_WINNT_WIN7)
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Length/sizeof(WCHAR);
|
||||
}
|
||||
|
||||
|
|
|
@ -72,6 +72,9 @@ FilenameU2A_FitOrFail(
|
|||
{
|
||||
DWORD ret;
|
||||
|
||||
/* destLen should never exceed MAX_PATH */
|
||||
if (destLen > MAX_PATH) destLen = MAX_PATH;
|
||||
|
||||
ret = bIsFileApiAnsi? RtlUnicodeStringToAnsiSize(SourceU) : RtlUnicodeStringToOemSize(SourceU);
|
||||
/* ret incl. nullchar */
|
||||
|
||||
|
|
|
@ -800,6 +800,7 @@ WdmAudResetStreamByLegacy(
|
|||
MMRESULT
|
||||
WdmAudQueryMixerInfoByLegacy(
|
||||
IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
|
||||
IN DWORD DeviceId,
|
||||
IN UINT uMsg,
|
||||
IN LPVOID Parameter,
|
||||
IN DWORD Flags)
|
||||
|
@ -819,6 +820,7 @@ WdmAudQueryMixerInfoByLegacy(
|
|||
|
||||
ZeroMemory(&DeviceInfo, sizeof(WDMAUD_DEVICE_INFO));
|
||||
DeviceInfo.hDevice = Handle;
|
||||
DeviceInfo.DeviceIndex = DeviceId;
|
||||
DeviceInfo.DeviceType = MIXER_DEVICE_TYPE;
|
||||
DeviceInfo.Flags = Flags;
|
||||
|
||||
|
|
|
@ -9,6 +9,18 @@
|
|||
|
||||
#include "wdmaud.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
KSSTREAM_HEADER Header;
|
||||
HANDLE hDevice;
|
||||
PSOUND_OVERLAPPED Overlap;
|
||||
LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine;
|
||||
DWORD IoCtl;
|
||||
}IO_PACKET, *LPIO_PACKET;
|
||||
|
||||
BOOL MMixerLibraryInitialized = FALSE;
|
||||
|
||||
|
||||
|
||||
PVOID Alloc(ULONG NumBytes);
|
||||
MIXER_STATUS Close(HANDLE hDevice);
|
||||
|
@ -110,7 +122,7 @@ Free(PVOID Block)
|
|||
VOID
|
||||
Copy(PVOID Src, PVOID Dst, ULONG NumBytes)
|
||||
{
|
||||
CopyMemory(Src, Dst, NumBytes);
|
||||
RtlMoveMemory(Src, Dst, NumBytes);
|
||||
}
|
||||
|
||||
MIXER_STATUS
|
||||
|
@ -282,7 +294,6 @@ Enum(
|
|||
HeapFree(GetProcessHeap(), 0, DetailData);
|
||||
return MM_STATUS_NO_MEMORY;
|
||||
}
|
||||
DPRINT1("DeviceName %S\n", DetailData->DevicePath);
|
||||
wcscpy(*DeviceName, DetailData->DevicePath);
|
||||
HeapFree(GetProcessHeap(), 0, DetailData);
|
||||
|
||||
|
@ -324,6 +335,13 @@ WdmAudInitUserModeMixer()
|
|||
HDEVINFO DeviceHandle;
|
||||
MIXER_STATUS Status;
|
||||
|
||||
if (MMixerLibraryInitialized)
|
||||
{
|
||||
/* library is already initialized */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* create a device list */
|
||||
DeviceHandle = SetupDiGetClassDevs(&CategoryGuid,
|
||||
NULL,
|
||||
|
@ -350,6 +368,9 @@ WdmAudInitUserModeMixer()
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* library is now initialized */
|
||||
MMixerLibraryInitialized = TRUE;
|
||||
|
||||
/* completed successfully */
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -363,7 +384,7 @@ WdmAudCleanupByMMixer()
|
|||
|
||||
MMRESULT
|
||||
WdmAudGetMixerCapabilties(
|
||||
IN ULONG DeviceId,
|
||||
IN ULONG DeviceId,
|
||||
LPMIXERCAPSW Capabilities)
|
||||
{
|
||||
if (MMixerGetCapabilities(&MixerContext, DeviceId, Capabilities) == MM_STATUS_SUCCESS)
|
||||
|
@ -375,10 +396,11 @@ WdmAudGetMixerCapabilties(
|
|||
MMRESULT
|
||||
WdmAudGetLineInfo(
|
||||
IN HANDLE hMixer,
|
||||
IN DWORD MixerId,
|
||||
IN LPMIXERLINEW MixLine,
|
||||
IN ULONG Flags)
|
||||
{
|
||||
if (MMixerGetLineInfo(&MixerContext, hMixer, Flags, MixLine) == MM_STATUS_SUCCESS)
|
||||
if (MMixerGetLineInfo(&MixerContext, hMixer, MixerId, Flags, MixLine) == MM_STATUS_SUCCESS)
|
||||
return MMSYSERR_NOERROR;
|
||||
|
||||
return MMSYSERR_ERROR;
|
||||
|
@ -387,10 +409,11 @@ WdmAudGetLineInfo(
|
|||
MMRESULT
|
||||
WdmAudGetLineControls(
|
||||
IN HANDLE hMixer,
|
||||
IN DWORD MixerId,
|
||||
IN LPMIXERLINECONTROLSW MixControls,
|
||||
IN ULONG Flags)
|
||||
{
|
||||
if (MMixerGetLineControls(&MixerContext, hMixer, Flags, MixControls) == MM_STATUS_SUCCESS)
|
||||
if (MMixerGetLineControls(&MixerContext, hMixer, MixerId, Flags, MixControls) == MM_STATUS_SUCCESS)
|
||||
return MMSYSERR_NOERROR;
|
||||
|
||||
return MMSYSERR_ERROR;
|
||||
|
@ -399,10 +422,11 @@ WdmAudGetLineControls(
|
|||
MMRESULT
|
||||
WdmAudSetControlDetails(
|
||||
IN HANDLE hMixer,
|
||||
IN DWORD MixerId,
|
||||
IN LPMIXERCONTROLDETAILS MixDetails,
|
||||
IN ULONG Flags)
|
||||
{
|
||||
if (MMixerSetControlDetails(&MixerContext, hMixer, Flags, MixDetails) == MM_STATUS_SUCCESS)
|
||||
if (MMixerSetControlDetails(&MixerContext, hMixer, MixerId, Flags, MixDetails) == MM_STATUS_SUCCESS)
|
||||
return MMSYSERR_NOERROR;
|
||||
|
||||
return MMSYSERR_ERROR;
|
||||
|
@ -412,10 +436,11 @@ WdmAudSetControlDetails(
|
|||
MMRESULT
|
||||
WdmAudGetControlDetails(
|
||||
IN HANDLE hMixer,
|
||||
IN DWORD MixerId,
|
||||
IN LPMIXERCONTROLDETAILS MixDetails,
|
||||
IN ULONG Flags)
|
||||
{
|
||||
if (MMixerGetControlDetails(&MixerContext, hMixer, Flags, MixDetails) == MM_STATUS_SUCCESS)
|
||||
if (MMixerGetControlDetails(&MixerContext, hMixer, MixerId, Flags, MixDetails) == MM_STATUS_SUCCESS)
|
||||
return MMSYSERR_NOERROR;
|
||||
|
||||
return MMSYSERR_ERROR;
|
||||
|
@ -589,6 +614,7 @@ WdmAudGetNumWdmDevsByMMixer(
|
|||
MMRESULT
|
||||
WdmAudQueryMixerInfoByMMixer(
|
||||
IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
|
||||
IN DWORD MixerId,
|
||||
IN UINT uMsg,
|
||||
IN LPVOID Parameter,
|
||||
IN DWORD Flags)
|
||||
|
@ -596,6 +622,7 @@ WdmAudQueryMixerInfoByMMixer(
|
|||
LPMIXERLINEW MixLine;
|
||||
LPMIXERLINECONTROLSW MixControls;
|
||||
LPMIXERCONTROLDETAILS MixDetails;
|
||||
HANDLE hMixer = NULL;
|
||||
|
||||
MixLine = (LPMIXERLINEW)Parameter;
|
||||
MixControls = (LPMIXERLINECONTROLSW)Parameter;
|
||||
|
@ -603,19 +630,23 @@ WdmAudQueryMixerInfoByMMixer(
|
|||
|
||||
/* FIXME param checks */
|
||||
|
||||
if (SoundDeviceInstance)
|
||||
{
|
||||
hMixer = SoundDeviceInstance->Handle;
|
||||
}
|
||||
|
||||
switch(uMsg)
|
||||
{
|
||||
case MXDM_GETLINEINFO:
|
||||
return WdmAudGetLineInfo(SoundDeviceInstance->Handle, MixLine, Flags);
|
||||
return WdmAudGetLineInfo(hMixer, MixerId, MixLine, Flags);
|
||||
case MXDM_GETLINECONTROLS:
|
||||
return WdmAudGetLineControls(SoundDeviceInstance->Handle, MixControls, Flags);
|
||||
return WdmAudGetLineControls(hMixer, MixerId, MixControls, Flags);
|
||||
case MXDM_SETCONTROLDETAILS:
|
||||
return WdmAudSetControlDetails(SoundDeviceInstance->Handle, MixDetails, Flags);
|
||||
break;
|
||||
return WdmAudSetControlDetails(hMixer, MixerId, MixDetails, Flags);
|
||||
case MXDM_GETCONTROLDETAILS:
|
||||
return WdmAudGetControlDetails(SoundDeviceInstance->Handle, MixDetails, Flags);
|
||||
break;
|
||||
return WdmAudGetControlDetails(hMixer, MixerId, MixDetails, Flags);
|
||||
default:
|
||||
DPRINT1("MixerId %lu, uMsg %lu, Parameter %p, Flags %lu\n", MixerId, uMsg, Parameter, Flags);
|
||||
SND_ASSERT(0);
|
||||
return MMSYSERR_NOTSUPPORTED;
|
||||
}
|
||||
|
@ -633,6 +664,25 @@ WdmAudGetDeviceInterfaceStringByMMixer(
|
|||
return MMSYSERR_NOTSUPPORTED;
|
||||
}
|
||||
|
||||
VOID
|
||||
CALLBACK
|
||||
MixerEventCallback(
|
||||
IN PVOID MixerEventContext,
|
||||
IN HANDLE hMixer,
|
||||
IN ULONG NotificationType,
|
||||
IN ULONG Value)
|
||||
{
|
||||
PSOUND_DEVICE_INSTANCE Instance = (PSOUND_DEVICE_INSTANCE)MixerEventContext;
|
||||
|
||||
DriverCallback(Instance->WinMM.ClientCallback,
|
||||
HIWORD(Instance->WinMM.Flags),
|
||||
Instance->WinMM.Handle,
|
||||
NotificationType,
|
||||
Instance->WinMM.ClientCallbackInstanceData,
|
||||
(DWORD_PTR)Value,
|
||||
0);
|
||||
}
|
||||
|
||||
MMRESULT
|
||||
WdmAudSetMixerDeviceFormatByMMixer(
|
||||
IN PSOUND_DEVICE_INSTANCE Instance,
|
||||
|
@ -640,11 +690,7 @@ WdmAudSetMixerDeviceFormatByMMixer(
|
|||
IN PWAVEFORMATEX WaveFormat,
|
||||
IN DWORD WaveFormatSize)
|
||||
{
|
||||
Instance->hNotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
|
||||
if ( ! Instance->hNotifyEvent )
|
||||
return MMSYSERR_NOMEM;
|
||||
|
||||
if (MMixerOpen(&MixerContext, DeviceId, Instance->hNotifyEvent, NULL /* FIXME */, &Instance->Handle) == MM_STATUS_SUCCESS)
|
||||
if (MMixerOpen(&MixerContext, DeviceId, (PVOID)Instance, MixerEventCallback, &Instance->Handle) == MM_STATUS_SUCCESS)
|
||||
return MMSYSERR_NOERROR;
|
||||
|
||||
return MMSYSERR_BADDEVICEID;
|
||||
|
@ -706,7 +752,19 @@ WdmAudResetStreamByMMixer(
|
|||
IN MMDEVICE_TYPE DeviceType,
|
||||
IN BOOLEAN bStartReset)
|
||||
{
|
||||
/* FIXME */
|
||||
MIXER_STATUS Status;
|
||||
|
||||
if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE)
|
||||
{
|
||||
Status = MMixerSetWaveResetState(&MixerContext, SoundDeviceInstance->Handle, bStartReset);
|
||||
if (Status == MM_STATUS_SUCCESS)
|
||||
{
|
||||
/* completed successfully */
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return MMSYSERR_NOTSUPPORTED;
|
||||
}
|
||||
|
||||
|
@ -719,6 +777,29 @@ WdmAudGetWavePositionByMMixer(
|
|||
return MMSYSERR_NOTSUPPORTED;
|
||||
}
|
||||
|
||||
DWORD
|
||||
WINAPI
|
||||
IoStreamingThread(
|
||||
LPVOID lpParameter)
|
||||
{
|
||||
DWORD Length;
|
||||
MMRESULT Result;
|
||||
LPIO_PACKET Packet = (LPIO_PACKET)lpParameter;
|
||||
|
||||
Result = SyncOverlappedDeviceIoControl(Packet->hDevice,
|
||||
Packet->IoCtl,
|
||||
NULL,
|
||||
0,
|
||||
&Packet->Header,
|
||||
sizeof(KSSTREAM_HEADER),
|
||||
&Length);
|
||||
|
||||
Packet->CompletionRoutine(ERROR_SUCCESS, Packet->Header.DataUsed, (LPOVERLAPPED)Packet->Overlap);
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, Packet);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MMRESULT
|
||||
WdmAudCommitWaveBufferByMMixer(
|
||||
IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
|
||||
|
@ -727,10 +808,11 @@ WdmAudCommitWaveBufferByMMixer(
|
|||
IN PSOUND_OVERLAPPED Overlap,
|
||||
IN LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine)
|
||||
{
|
||||
KSSTREAM_HEADER Packet;
|
||||
PSOUND_DEVICE SoundDevice;
|
||||
MMDEVICE_TYPE DeviceType;
|
||||
MMRESULT Result;
|
||||
LPIO_PACKET Packet;
|
||||
HANDLE hThread;
|
||||
|
||||
Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
|
||||
|
||||
|
@ -742,31 +824,37 @@ WdmAudCommitWaveBufferByMMixer(
|
|||
Result = GetSoundDeviceType(SoundDevice, &DeviceType);
|
||||
SND_ASSERT( Result == MMSYSERR_NOERROR );
|
||||
|
||||
Packet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IO_PACKET));
|
||||
if ( ! Packet )
|
||||
{
|
||||
/* no memory */
|
||||
return MMSYSERR_NOMEM;
|
||||
}
|
||||
|
||||
/* setup stream packet */
|
||||
ZeroMemory(&Packet, sizeof(KSSTREAM_HEADER));
|
||||
Packet.Size = sizeof(KSSTREAM_HEADER);
|
||||
Packet.PresentationTime.Numerator = 1;
|
||||
Packet.PresentationTime.Denominator = 1;
|
||||
Packet.Data = OffsetPtr;
|
||||
Packet.FrameExtent = Length;
|
||||
Packet->Header.Size = sizeof(KSSTREAM_HEADER);
|
||||
Packet->Header.PresentationTime.Numerator = 1;
|
||||
Packet->Header.PresentationTime.Denominator = 1;
|
||||
Packet->Header.Data = OffsetPtr;
|
||||
Packet->Header.FrameExtent = Length;
|
||||
Packet->hDevice = SoundDeviceInstance->Handle;
|
||||
Packet->Overlap = Overlap;
|
||||
Packet->CompletionRoutine = CompletionRoutine;
|
||||
Packet->IoCtl = (DeviceType == WAVE_OUT_DEVICE_TYPE ? IOCTL_KS_WRITE_STREAM : IOCTL_KS_READ_STREAM);
|
||||
|
||||
if (DeviceType == WAVE_OUT_DEVICE_TYPE)
|
||||
{
|
||||
Packet.DataUsed = Length;
|
||||
Packet->Header.DataUsed = Length;
|
||||
}
|
||||
|
||||
Result = SyncOverlappedDeviceIoControl(SoundDeviceInstance->Handle,
|
||||
IOCTL_KS_WRITE_STREAM,
|
||||
NULL,
|
||||
0,
|
||||
&Packet,
|
||||
sizeof(KSSTREAM_HEADER),
|
||||
&Length);
|
||||
hThread = CreateThread(NULL, 0, IoStreamingThread, (LPVOID)Packet, 0, NULL);
|
||||
if (hThread == NULL)
|
||||
{
|
||||
/* error */
|
||||
return MMSYSERR_ERROR;
|
||||
}
|
||||
|
||||
/* HACK:
|
||||
* don't call completion routine directly
|
||||
*/
|
||||
CompletionRoutine(ERROR_SUCCESS, Length, (LPOVERLAPPED)Overlap);
|
||||
CloseHandle(hThread);
|
||||
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
|
|
@ -70,24 +70,28 @@ WdmAudCloseSoundDeviceByMMixer(
|
|||
MMRESULT
|
||||
WdmAudGetLineInfo(
|
||||
IN HANDLE hMixer,
|
||||
IN DWORD MixerId,
|
||||
IN LPMIXERLINEW MixLine,
|
||||
IN ULONG Flags);
|
||||
|
||||
MMRESULT
|
||||
WdmAudGetLineControls(
|
||||
IN HANDLE hMixer,
|
||||
IN DWORD MixerId,
|
||||
IN LPMIXERLINECONTROLSW MixControls,
|
||||
IN ULONG Flags);
|
||||
|
||||
MMRESULT
|
||||
WdmAudSetControlDetails(
|
||||
IN HANDLE hMixer,
|
||||
IN DWORD MixerId,
|
||||
IN LPMIXERCONTROLDETAILS MixDetails,
|
||||
IN ULONG Flags);
|
||||
|
||||
MMRESULT
|
||||
WdmAudGetControlDetails(
|
||||
IN HANDLE hMixer,
|
||||
IN DWORD MixerId,
|
||||
IN LPMIXERCONTROLDETAILS MixDetails,
|
||||
IN ULONG Flags);
|
||||
|
||||
|
@ -116,6 +120,7 @@ WdmAudSetMixerDeviceFormatByMMixer(
|
|||
MMRESULT
|
||||
WdmAudQueryMixerInfoByMMixer(
|
||||
IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
|
||||
IN DWORD DeviceId,
|
||||
IN UINT uMsg,
|
||||
IN LPVOID Parameter,
|
||||
IN DWORD Flags);
|
||||
|
@ -185,6 +190,7 @@ WdmAudSetMixerDeviceFormatByLegacy(
|
|||
MMRESULT
|
||||
WdmAudQueryMixerInfoByLegacy(
|
||||
IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
|
||||
IN DWORD DeviceId,
|
||||
IN UINT uMsg,
|
||||
IN LPVOID Parameter,
|
||||
IN DWORD Flags);
|
||||
|
|
|
@ -31,7 +31,6 @@ NpfsQueryDirectory(PNPFS_CCB Ccb,
|
|||
PNPFS_VCB Vcb;
|
||||
PNPFS_FCB PipeFcb;
|
||||
ULONG PipeIndex;
|
||||
BOOLEAN Found = FALSE;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PFILE_NAMES_INFORMATION NamesBuffer;
|
||||
PFILE_DIRECTORY_INFORMATION DirectoryBuffer;
|
||||
|
@ -39,6 +38,9 @@ NpfsQueryDirectory(PNPFS_CCB Ccb,
|
|||
PFILE_BOTH_DIR_INFORMATION BothDirBuffer;
|
||||
ULONG InfoSize = 0;
|
||||
ULONG NameLength;
|
||||
ULONG CurrentOffset = 0;
|
||||
ULONG LastOffset = 0;
|
||||
PULONG NextEntryOffset;
|
||||
|
||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
|
@ -103,7 +105,8 @@ NpfsQueryDirectory(PNPFS_CCB Ccb,
|
|||
if (First || (Stack->Flags & SL_RESTART_SCAN))
|
||||
{
|
||||
FileIndex = 0;
|
||||
} else if ((Stack->Flags & SL_INDEX_SPECIFIED) == 0)
|
||||
}
|
||||
else if ((Stack->Flags & SL_INDEX_SPECIFIED) == 0)
|
||||
{
|
||||
FileIndex = Ccb->u.Directory.FileIndex + 1;
|
||||
}
|
||||
|
@ -139,7 +142,6 @@ NpfsQueryDirectory(PNPFS_CCB Ccb,
|
|||
Vcb = Ccb->Fcb->Vcb;
|
||||
CurrentEntry = Vcb->PipeListHead.Flink;
|
||||
while (CurrentEntry != &Vcb->PipeListHead &&
|
||||
Found == FALSE &&
|
||||
Status == STATUS_SUCCESS)
|
||||
{
|
||||
/* Get the FCB of the next pipe */
|
||||
|
@ -174,13 +176,12 @@ NpfsQueryDirectory(PNPFS_CCB Ccb,
|
|||
}
|
||||
|
||||
/* Initialize the information struct */
|
||||
RtlZeroMemory(Buffer, InfoSize);
|
||||
RtlZeroMemory(&Buffer[CurrentOffset], InfoSize);
|
||||
|
||||
switch (FileInformationClass)
|
||||
{
|
||||
case FileDirectoryInformation:
|
||||
DirectoryBuffer = (PFILE_DIRECTORY_INFORMATION)Buffer;
|
||||
DirectoryBuffer->NextEntryOffset = 0;
|
||||
DirectoryBuffer = (PFILE_DIRECTORY_INFORMATION)&Buffer[CurrentOffset];
|
||||
DirectoryBuffer->FileIndex = PipeIndex;
|
||||
DirectoryBuffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||
DirectoryBuffer->EndOfFile.QuadPart = PipeFcb->CurrentInstances;
|
||||
|
@ -192,8 +193,7 @@ NpfsQueryDirectory(PNPFS_CCB Ccb,
|
|||
break;
|
||||
|
||||
case FileFullDirectoryInformation:
|
||||
FullDirBuffer = (PFILE_FULL_DIR_INFORMATION)Buffer;
|
||||
FullDirBuffer->NextEntryOffset = 0;
|
||||
FullDirBuffer = (PFILE_FULL_DIR_INFORMATION)&Buffer[CurrentOffset];
|
||||
FullDirBuffer->FileIndex = PipeIndex;
|
||||
FullDirBuffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||
FullDirBuffer->EndOfFile.QuadPart = PipeFcb->CurrentInstances;
|
||||
|
@ -205,7 +205,7 @@ NpfsQueryDirectory(PNPFS_CCB Ccb,
|
|||
break;
|
||||
|
||||
case FileBothDirectoryInformation:
|
||||
BothDirBuffer = (PFILE_BOTH_DIR_INFORMATION)Buffer;
|
||||
BothDirBuffer = (PFILE_BOTH_DIR_INFORMATION)&Buffer[CurrentOffset];
|
||||
BothDirBuffer->NextEntryOffset = 0;
|
||||
BothDirBuffer->FileIndex = PipeIndex;
|
||||
BothDirBuffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
||||
|
@ -218,8 +218,7 @@ NpfsQueryDirectory(PNPFS_CCB Ccb,
|
|||
break;
|
||||
|
||||
case FileNamesInformation:
|
||||
NamesBuffer = (PFILE_NAMES_INFORMATION)Buffer;
|
||||
NamesBuffer->NextEntryOffset = 0;
|
||||
NamesBuffer = (PFILE_NAMES_INFORMATION)&Buffer[CurrentOffset];
|
||||
NamesBuffer->FileIndex = PipeIndex;
|
||||
NamesBuffer->FileNameLength = NameLength;
|
||||
RtlCopyMemory(NamesBuffer->FileName,
|
||||
|
@ -233,15 +232,33 @@ NpfsQueryDirectory(PNPFS_CCB Ccb,
|
|||
break;
|
||||
}
|
||||
|
||||
*Size = InfoSize + NameLength;
|
||||
DPRINT("CurrentOffset: %lu\n", CurrentOffset);
|
||||
|
||||
/* Store the current pipe index in the CCB */
|
||||
Ccb->u.Directory.FileIndex = PipeIndex;
|
||||
Found = TRUE;
|
||||
|
||||
// if (Stack->Flags & SL_RETURN_SINGLE_ENTRY)
|
||||
// return STATUS_SUCCESS;
|
||||
/* Get the pointer to the previous entries NextEntryOffset */
|
||||
NextEntryOffset = (PULONG)&Buffer[LastOffset];
|
||||
|
||||
break;
|
||||
/* Set the previous entries NextEntryOffset */
|
||||
*NextEntryOffset = CurrentOffset - LastOffset;
|
||||
|
||||
/* Return the used buffer size */
|
||||
*Size = CurrentOffset + InfoSize + NameLength;
|
||||
|
||||
/* Leave, if there is no space left in the buffer */
|
||||
if (Status == STATUS_BUFFER_OVERFLOW)
|
||||
return Status;
|
||||
|
||||
/* Leave, if we should return only one entry */
|
||||
if (Stack->Flags & SL_RETURN_SINGLE_ENTRY)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
/* Store the current offset for the next round */
|
||||
LastOffset = CurrentOffset;
|
||||
|
||||
/* Set the offset for the next entry */
|
||||
CurrentOffset += ROUND_UP(InfoSize + NameLength, sizeof(ULONG));
|
||||
}
|
||||
|
||||
PipeIndex++;
|
||||
|
@ -250,7 +267,8 @@ NpfsQueryDirectory(PNPFS_CCB Ccb,
|
|||
CurrentEntry = CurrentEntry->Flink;
|
||||
}
|
||||
|
||||
if (Found == FALSE)
|
||||
/* Return STATUS_NO_MORE_FILES if no matching pipe name was found */
|
||||
if (CurrentOffset == 0)
|
||||
Status = STATUS_NO_MORE_FILES;
|
||||
|
||||
return Status;
|
||||
|
|
|
@ -5,6 +5,12 @@
|
|||
#include <ndk/iotypes.h>
|
||||
#include <pseh/pseh2.h>
|
||||
|
||||
#define ROUND_DOWN(n, align) \
|
||||
(((ULONG)n) & ~((align) - 1l))
|
||||
|
||||
#define ROUND_UP(n, align) \
|
||||
ROUND_DOWN(((ULONG)n) + (align) - 1, (align))
|
||||
|
||||
typedef enum _FCB_TYPE
|
||||
{
|
||||
FCB_INVALID,
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
|
||||
add_subdirectory(ks)
|
||||
add_subdirectory(swenum)
|
|
@ -27,6 +27,7 @@ list(APPEND SOURCE
|
|||
unknown.c
|
||||
worker.c
|
||||
kcom.c
|
||||
swenum.c
|
||||
ks.rc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ks.def)
|
||||
|
||||
|
|
|
@ -163,7 +163,7 @@ IKsAllocator_fnDeviceIoControl(
|
|||
|
||||
/* complete and forget irps */
|
||||
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ IKsAllocator_fnDeviceIoControl(
|
|||
{
|
||||
/* invalid request */
|
||||
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ IKsAllocator_fnDeviceIoControl(
|
|||
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
|
||||
Irp->IoStatus.Information = sizeof(KSSTREAMALLOCATOR_FUNCTIONTABLE);
|
||||
/* complete and forget irp */
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
if (!(Property->Flags & KSPROPERTY_TYPE_GET))
|
||||
|
@ -198,7 +198,7 @@ IKsAllocator_fnDeviceIoControl(
|
|||
/* only support retrieving the property */
|
||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||
/* complete and forget irp */
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
@ -212,7 +212,7 @@ IKsAllocator_fnDeviceIoControl(
|
|||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = sizeof(KSSTREAMALLOCATOR_FUNCTIONTABLE);
|
||||
/* complete request */
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (Property->Id == KSPROPERTY_STREAMALLOCATOR_STATUS)
|
||||
|
@ -223,7 +223,7 @@ IKsAllocator_fnDeviceIoControl(
|
|||
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
|
||||
Irp->IoStatus.Information = sizeof(KSPROPERTY_STREAMALLOCATOR_STATUS);
|
||||
/* complete and forget irp */
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
if (!(Property->Flags & KSPROPERTY_TYPE_GET))
|
||||
|
@ -231,7 +231,7 @@ IKsAllocator_fnDeviceIoControl(
|
|||
/* only support retrieving the property */
|
||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||
/* complete and forget irp */
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
@ -246,14 +246,14 @@ IKsAllocator_fnDeviceIoControl(
|
|||
Irp->IoStatus.Information = sizeof(KSSTREAMALLOCATOR_STATUS);
|
||||
|
||||
/* complete request */
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* unhandled request */
|
||||
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
@ -501,7 +501,7 @@ IKsAllocator_DispatchDeviceIoControl(
|
|||
|
||||
/* complete request */
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
@ -523,7 +523,7 @@ IKsAllocator_DispatchClose(
|
|||
|
||||
/* complete request */
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
|
|
@ -1332,7 +1332,7 @@ KopDispatchClose(
|
|||
|
||||
/* complete request */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -1416,7 +1416,7 @@ KopDispatchCreate(
|
|||
IoStack->FileObject->FsContext2 = (PVOID)Header;
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return Status;
|
||||
|
||||
|
@ -1429,7 +1429,7 @@ cleanup:
|
|||
FreeItem(Header);
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -1703,7 +1703,7 @@ KsCompletePendingRequest(
|
|||
if (IoStack->MajorFunction != IRP_MJ_CLOSE)
|
||||
{
|
||||
/* can be completed immediately */
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1711,7 +1711,7 @@ KsCompletePendingRequest(
|
|||
if (!NT_SUCCESS(Irp->IoStatus.Status))
|
||||
{
|
||||
/* closing failed, complete irp */
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1723,136 +1723,8 @@ KsCompletePendingRequest(
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsCreateBusEnumObject(
|
||||
IN PWCHAR BusIdentifier,
|
||||
IN PDEVICE_OBJECT BusDeviceObject,
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
||||
IN PDEVICE_OBJECT PnpDeviceObject OPTIONAL,
|
||||
IN REFGUID InterfaceGuid OPTIONAL,
|
||||
IN PWCHAR ServiceRelativePath OPTIONAL)
|
||||
{
|
||||
ULONG Length;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
UNICODE_STRING ServiceKeyPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\");
|
||||
PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension;
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
/* calculate sizeof bus enum device extension */
|
||||
Length = wcslen(BusIdentifier) * sizeof(WCHAR);
|
||||
Length += sizeof(BUS_ENUM_DEVICE_EXTENSION);
|
||||
|
||||
BusDeviceExtension = AllocateItem(NonPagedPool, Length);
|
||||
if (!BusDeviceExtension)
|
||||
{
|
||||
/* not enough memory */
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/* zero device extension */
|
||||
RtlZeroMemory(BusDeviceExtension, sizeof(BUS_ENUM_DEVICE_EXTENSION));
|
||||
|
||||
/* initialize bus device extension */
|
||||
wcscpy(BusDeviceExtension->BusIdentifier, BusIdentifier);
|
||||
|
||||
/* allocate service path string */
|
||||
Length = ServiceKeyPath.MaximumLength;
|
||||
Length += BusDeviceObject->DriverObject->DriverExtension->ServiceKeyName.MaximumLength;
|
||||
|
||||
if (ServiceRelativePath)
|
||||
{
|
||||
/* relative path for devices */
|
||||
Length += wcslen(ServiceRelativePath) + 2 * sizeof(WCHAR);
|
||||
}
|
||||
|
||||
BusDeviceExtension->ServicePath.Length = 0;
|
||||
BusDeviceExtension->ServicePath.MaximumLength = Length;
|
||||
BusDeviceExtension->ServicePath.Buffer = AllocateItem(NonPagedPool, Length);
|
||||
|
||||
if (!BusDeviceExtension->ServicePath.Buffer)
|
||||
{
|
||||
/* not enough memory */
|
||||
FreeItem(BusDeviceExtension);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RtlAppendUnicodeStringToString(&BusDeviceExtension->ServicePath, &ServiceKeyPath);
|
||||
RtlAppendUnicodeStringToString(&BusDeviceExtension->ServicePath, &BusDeviceObject->DriverObject->DriverExtension->ServiceKeyName);
|
||||
|
||||
if (ServiceRelativePath)
|
||||
{
|
||||
RtlAppendUnicodeToString(&BusDeviceExtension->ServicePath, L"\\");
|
||||
RtlAppendUnicodeToString(&BusDeviceExtension->ServicePath, ServiceRelativePath);
|
||||
}
|
||||
|
||||
if (InterfaceGuid)
|
||||
{
|
||||
/* register an device interface */
|
||||
Status = IoRegisterDeviceInterface(PhysicalDeviceObject, InterfaceGuid, NULL, &BusDeviceExtension->SymbolicLinkName);
|
||||
|
||||
/* check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
FreeItem(BusDeviceExtension->ServicePath.Buffer);
|
||||
FreeItem(BusDeviceExtension);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* now enable device interface */
|
||||
Status = IoSetDeviceInterfaceState(&BusDeviceExtension->SymbolicLinkName, TRUE);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
FreeItem(BusDeviceExtension->ServicePath.Buffer);
|
||||
FreeItem(BusDeviceExtension);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* set state enabled */
|
||||
BusDeviceExtension->Enabled = TRUE;
|
||||
}
|
||||
|
||||
/* store device objects */
|
||||
BusDeviceExtension->BusDeviceObject = BusDeviceObject;
|
||||
BusDeviceExtension->PnpDeviceObject = PnpDeviceObject;
|
||||
BusDeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
|
||||
|
||||
if (!PnpDeviceObject)
|
||||
{
|
||||
BusDeviceExtension->PnpDeviceObject = IoAttachDeviceToDeviceStack(BusDeviceObject, PhysicalDeviceObject);
|
||||
|
||||
if (!BusDeviceExtension->PnpDeviceObject)
|
||||
{
|
||||
/* failed to attach device */
|
||||
if (BusDeviceExtension->Enabled)
|
||||
{
|
||||
IoSetDeviceInterfaceState(&BusDeviceExtension->SymbolicLinkName, FALSE);
|
||||
RtlFreeUnicodeString(&BusDeviceExtension->SymbolicLinkName);
|
||||
}
|
||||
|
||||
/* free device extension */
|
||||
FreeItem(BusDeviceExtension->ServicePath.Buffer);
|
||||
FreeItem(BusDeviceExtension);
|
||||
|
||||
return STATUS_DEVICE_REMOVED;
|
||||
}
|
||||
}
|
||||
|
||||
/* attach device extension */
|
||||
DeviceExtension = (PDEVICE_EXTENSION)BusDeviceObject->DeviceExtension;
|
||||
DeviceExtension->DeviceHeader = (PKSIDEVICE_HEADER)BusDeviceExtension;
|
||||
|
||||
/* FIXME scan bus and invalidate device relations */
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KspSetGetBusDataCompletion(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp,
|
||||
|
@ -1979,47 +1851,6 @@ KsDeviceRegisterAdapterObject(
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsGetBusEnumIdentifier(
|
||||
IN PIRP Irp)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsGetBusEnumParentFDOFromChildPDO(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
OUT PDEVICE_OBJECT *FunctionalDeviceObject)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsGetBusEnumPnpDeviceObject(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PDEVICE_OBJECT *PnpDeviceObject)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
@implemented
|
||||
|
@ -2061,33 +1892,6 @@ KsGetNextSibling(
|
|||
return (PVOID)BasicHeader->Next.Pin;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsInstallBusEnumInterface(
|
||||
PIRP Irp)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsIsBusEnumChildDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
OUT PBOOLEAN ChildDevice)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
ULONG
|
||||
KspCountMethodSets(
|
||||
IN PKSAUTOMATION_TABLE AutomationTableA OPTIONAL,
|
||||
|
@ -2598,104 +2402,6 @@ cleanup:
|
|||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsServiceBusEnumCreateRequest(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN OUT PIRP Irp)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsServiceBusEnumPnpRequest(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN OUT PIRP Irp)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KspRemoveBusInterface(
|
||||
PVOID Ctx)
|
||||
{
|
||||
PKSREMOVE_BUS_INTERFACE_CTX Context =(PKSREMOVE_BUS_INTERFACE_CTX)Ctx;
|
||||
|
||||
/* TODO
|
||||
* get SWENUM_INSTALL_INTERFACE struct
|
||||
* open device key and delete the keys
|
||||
*/
|
||||
|
||||
UNIMPLEMENTED
|
||||
|
||||
/* set status */
|
||||
Context->Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||
|
||||
|
||||
/* signal completion */
|
||||
KeSetEvent(&Context->Event, IO_NO_INCREMENT, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KsRemoveBusEnumInterface(
|
||||
IN PIRP Irp)
|
||||
{
|
||||
KPROCESSOR_MODE Mode;
|
||||
LUID luid;
|
||||
KSREMOVE_BUS_INTERFACE_CTX Ctx;
|
||||
WORK_QUEUE_ITEM WorkItem;
|
||||
|
||||
/* get previous mode */
|
||||
Mode = ExGetPreviousMode();
|
||||
|
||||
/* convert to luid */
|
||||
luid = RtlConvertUlongToLuid(SE_LOAD_DRIVER_PRIVILEGE);
|
||||
|
||||
/* perform access check */
|
||||
if (!SeSinglePrivilegeCheck(luid, Mode))
|
||||
{
|
||||
/* insufficient privileges */
|
||||
return STATUS_PRIVILEGE_NOT_HELD;
|
||||
}
|
||||
/* initialize event */
|
||||
KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE);
|
||||
|
||||
/* store irp in ctx */
|
||||
Ctx.Irp = Irp;
|
||||
|
||||
/* initialize work item */
|
||||
ExInitializeWorkItem(&WorkItem, KspRemoveBusInterface, (PVOID)&Ctx);
|
||||
|
||||
/* now queue the work item */
|
||||
ExQueueWorkItem(&WorkItem, DelayedWorkQueue);
|
||||
|
||||
/* wait for completion */
|
||||
KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, NULL);
|
||||
|
||||
/* return result */
|
||||
return Ctx.Irp->IoStatus.Status;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
*/
|
||||
|
|
|
@ -339,7 +339,7 @@ IKsClock_DispatchDeviceIoControl(
|
|||
|
||||
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -353,7 +353,7 @@ IKsClock_DispatchClose(
|
|||
UNIMPLEMENTED
|
||||
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -282,8 +282,6 @@ IKsDevice_PnpStartDevice(
|
|||
NTSTATUS Status;
|
||||
PCM_RESOURCE_LIST TranslatedResourceList;
|
||||
PCM_RESOURCE_LIST UntranslatedResourceList;
|
||||
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor, UnPartialDescriptor;
|
||||
ULONG Index;
|
||||
|
||||
/* get current stack location */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
@ -302,42 +300,14 @@ IKsDevice_PnpStartDevice(
|
|||
{
|
||||
DPRINT1("NextDevice object failed to start with %x\n", Status);
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
TranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResourcesTranslated;
|
||||
UntranslatedResourceList = IoStack->Parameters.StartDevice.AllocatedResources;
|
||||
|
||||
DPRINT("ResourceDescriptorCount %lu\n", TranslatedResourceList->List[0].PartialResourceList.Count);
|
||||
for (Index = 0; Index < TranslatedResourceList->List[0].PartialResourceList.Count; Index ++ )
|
||||
{
|
||||
PartialDescriptor = &TranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[Index];
|
||||
UnPartialDescriptor = &UntranslatedResourceList->List[0].PartialResourceList.PartialDescriptors[Index];
|
||||
DPRINT("Descriptor Type %u\n", PartialDescriptor->Type);
|
||||
|
||||
if (PartialDescriptor->Type == CmResourceTypeInterrupt)
|
||||
{
|
||||
DPRINT("CmResourceTypeInterrupt Index %u TRANS Interrupt Number Affinity %x Level %u Vector %u Flags %x Share %x\n", Index, PartialDescriptor->u.Interrupt.Affinity, PartialDescriptor->u.Interrupt.Level, PartialDescriptor->u.Interrupt.Vector, PartialDescriptor->Flags, PartialDescriptor->ShareDisposition);
|
||||
DPRINT("CmResourceTypeInterrupt Index %u UNTRANS Interrupt Number Affinity %x Level %u Vector %u Flags %x Share %x\\n", Index, UnPartialDescriptor->u.Interrupt.Affinity, UnPartialDescriptor->u.Interrupt.Level, UnPartialDescriptor->u.Interrupt.Vector, UnPartialDescriptor->Flags, UnPartialDescriptor->ShareDisposition);
|
||||
|
||||
}
|
||||
else if (PartialDescriptor->Type == CmResourceTypePort)
|
||||
{
|
||||
DPRINT("CmResourceTypePort Index %u TRANS Port Length %u Start %u %u Flags %x Share %x\n", Index, PartialDescriptor->u.Port.Length, PartialDescriptor->u.Port.Start.HighPart, PartialDescriptor->u.Port.Start.LowPart, PartialDescriptor->Flags, PartialDescriptor->ShareDisposition);
|
||||
DPRINT("CmResourceTypePort Index %u UNTRANS Port Length %u Start %u %u Flags %x Share %x\n", Index, UnPartialDescriptor->u.Port.Length, UnPartialDescriptor->u.Port.Start.HighPart, UnPartialDescriptor->u.Port.Start.LowPart, UnPartialDescriptor->Flags, UnPartialDescriptor->ShareDisposition);
|
||||
}
|
||||
else if (PartialDescriptor->Type == CmResourceTypeMemory)
|
||||
{
|
||||
DPRINT("CmResourceTypeMemory Index %u TRANS Start %x Length %u Flags %x Share %x\n", Index, PartialDescriptor->u.Memory.Start.LowPart, PartialDescriptor->u.Memory.Length, PartialDescriptor->Flags, PartialDescriptor->ShareDisposition);
|
||||
DPRINT("CmResourceTypeMemory Index %u TRANS Start %x Length %u Flags %x Share %x\n", Index, UnPartialDescriptor->u.Memory.Start.LowPart, UnPartialDescriptor->u.Memory.Length, UnPartialDescriptor->Flags, UnPartialDescriptor->ShareDisposition);
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(DeviceHeader->KsDevice.Descriptor);
|
||||
ASSERT(DeviceHeader->KsDevice.Descriptor->Dispatch);
|
||||
ASSERT(DeviceHeader->KsDevice.Descriptor->Dispatch->Start);
|
||||
|
||||
|
||||
/* do we have a device descriptor */
|
||||
if (DeviceHeader->KsDevice.Descriptor)
|
||||
|
@ -361,7 +331,7 @@ IKsDevice_PnpStartDevice(
|
|||
{
|
||||
DPRINT1("Driver: failed to start %x\n", Status);
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -406,12 +376,17 @@ IKsDevice_PnpStartDevice(
|
|||
Status = KspSetFilterFactoriesState(DeviceHeader, TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* set state to run */
|
||||
DeviceHeader->KsDevice.Started = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* store result */
|
||||
Irp->IoStatus.Status = Status;
|
||||
/* complete request */
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
if (Ctx)
|
||||
{
|
||||
|
@ -420,7 +395,7 @@ IKsDevice_PnpStartDevice(
|
|||
}
|
||||
|
||||
/* return result */
|
||||
DPRINT1("IKsDevice_PnpStartDevice Status %x PostStartRoutine %p\n", Status, Ctx);
|
||||
DPRINT("IKsDevice_PnpStartDevice Status %x PostStartRoutine %p\n", Status, Ctx);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -477,7 +452,7 @@ IKsDevice_Pnp(
|
|||
{
|
||||
DPRINT1("Driver: query stop failed %x\n", Status);
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -487,7 +462,7 @@ IKsDevice_Pnp(
|
|||
DPRINT("Next Device: Status %x\n", Status);
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -513,7 +488,7 @@ IKsDevice_Pnp(
|
|||
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
case IRP_MN_QUERY_INTERFACE:
|
||||
|
@ -536,7 +511,7 @@ IKsDevice_Pnp(
|
|||
/* driver supports a private interface */
|
||||
DPRINT1("IRP_MN_QUERY_INTERFACE Device supports interface\n");
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -545,7 +520,7 @@ IKsDevice_Pnp(
|
|||
|
||||
DPRINT1("IRP_MN_QUERY_INTERFACE Next Device: Status %x\n", Status);
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
case IRP_MN_QUERY_DEVICE_RELATIONS:
|
||||
|
@ -556,7 +531,7 @@ IKsDevice_Pnp(
|
|||
DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS Next Device: Status %x\n", Status);
|
||||
|
||||
//Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
|
||||
|
@ -567,7 +542,7 @@ IKsDevice_Pnp(
|
|||
DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS Next Device: Status %x\n", Status);
|
||||
|
||||
//Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
|
||||
|
@ -578,7 +553,7 @@ IKsDevice_Pnp(
|
|||
DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS Next Device: Status %x\n", Status);
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
default:
|
||||
|
@ -587,7 +562,7 @@ IKsDevice_Pnp(
|
|||
Status = KspForwardIrpSynchronous(DeviceObject, Irp);
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
@ -604,7 +579,7 @@ IKsDevice_Power(
|
|||
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -669,17 +644,10 @@ IKsDevice_Create(
|
|||
}
|
||||
}
|
||||
|
||||
/* acquire list lock */
|
||||
/* release list lock */
|
||||
IKsDevice_fnReleaseDevice((IKsDevice*)&DeviceHeader->BasicHeader.OuterUnknown);
|
||||
|
||||
if (Status != STATUS_PENDING)
|
||||
{
|
||||
Irp->IoStatus.Information = 0;
|
||||
/* set return status */
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
/* done */
|
||||
return Status;
|
||||
|
||||
|
||||
|
@ -703,7 +671,7 @@ KsInitializeDevice(
|
|||
PKSIOBJECT_BAG Bag;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
DPRINT("KsInitializeDevice Descriptor %p\n", Descriptor);
|
||||
DPRINT1("KsInitializeDevice Descriptor %p\n", Descriptor);
|
||||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PDEVICE_EXTENSION)FunctionalDeviceObject->DeviceExtension;
|
||||
|
@ -714,7 +682,7 @@ KsInitializeDevice(
|
|||
/* point to allocated header */
|
||||
Header = DeviceExtension->DeviceHeader;
|
||||
|
||||
DPRINT("DeviceHeader %p\n", DeviceExtension->DeviceHeader);
|
||||
DPRINT1("DeviceHeader %p\n", DeviceExtension->DeviceHeader);
|
||||
|
||||
if (Descriptor && Descriptor->Dispatch)
|
||||
{
|
||||
|
@ -896,7 +864,7 @@ KsDereferenceSoftwareBusObject(
|
|||
IKsDevice * Device;
|
||||
PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)Header;
|
||||
|
||||
DPRINT1("KsDereferenceSoftwareBusObject DeviceHeader %p\n", Header);
|
||||
DPRINT("KsDereferenceSoftwareBusObject DeviceHeader %p\n", Header);
|
||||
|
||||
/* get device interface */
|
||||
Device = (IKsDevice*)DeviceHeader->BasicHeader.OuterUnknown;
|
||||
|
|
|
@ -16,6 +16,7 @@ typedef struct
|
|||
|
||||
IKsControlVtbl *lpVtblKsControl;
|
||||
IKsFilterFactory * FilterFactory;
|
||||
IKsProcessingObjectVtbl * lpVtblKsProcessingObject;
|
||||
LONG ref;
|
||||
|
||||
PKSIOBJECT_HEADER ObjectHeader;
|
||||
|
@ -25,6 +26,9 @@ typedef struct
|
|||
KMUTEX ControlMutex;
|
||||
KMUTEX ProcessingMutex;
|
||||
|
||||
PKSWORKER Worker;
|
||||
WORK_QUEUE_ITEM WorkItem;
|
||||
KSGATE Gate;
|
||||
|
||||
PFNKSFILTERPOWER Sleep;
|
||||
PFNKSFILTERPOWER Wake;
|
||||
|
@ -70,6 +74,196 @@ KSPROPERTY_SET FilterPropertySet[] =
|
|||
}
|
||||
};
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsProcessingObject_fnQueryInterface(
|
||||
IKsProcessingObject * iface,
|
||||
IN REFIID refiid,
|
||||
OUT PVOID* Output)
|
||||
{
|
||||
IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
|
||||
|
||||
if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
|
||||
{
|
||||
*Output = &This->Header.OuterUnknown;
|
||||
_InterlockedIncrement(&This->ref);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
IKsProcessingObject_fnAddRef(
|
||||
IKsProcessingObject * iface)
|
||||
{
|
||||
IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
|
||||
|
||||
return InterlockedIncrement(&This->ref);
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
IKsProcessingObject_fnRelease(
|
||||
IKsProcessingObject * iface)
|
||||
{
|
||||
IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
|
||||
|
||||
InterlockedDecrement(&This->ref);
|
||||
|
||||
/* Return new reference count */
|
||||
return This->ref;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
IKsProcessingObject_fnProcessingObjectWork(
|
||||
IKsProcessingObject * iface)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
LARGE_INTEGER TimeOut;
|
||||
IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
|
||||
|
||||
DPRINT1("processing object\n");
|
||||
/* first check if running at passive level */
|
||||
if (KeGetCurrentIrql() == PASSIVE_LEVEL)
|
||||
{
|
||||
/* acquire processing mutex */
|
||||
KeWaitForSingleObject(&This->ControlMutex, Executive, KernelMode, FALSE, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* dispatch level processing */
|
||||
if (KeReadStateMutex(&This->ControlMutex) == 0)
|
||||
{
|
||||
/* some thread was faster */
|
||||
DPRINT1("processing object too slow\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* acquire processing mutex */
|
||||
TimeOut.QuadPart = 0LL;
|
||||
Status = KeWaitForSingleObject(&This->ControlMutex, Executive, KernelMode, FALSE, &TimeOut);
|
||||
|
||||
if (Status == STATUS_TIMEOUT)
|
||||
{
|
||||
/* some thread was faster */
|
||||
DPRINT1("processing object too slow\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
|
||||
/* check if the and-gate has been enabled again */
|
||||
if (&This->Gate.Count != 0)
|
||||
{
|
||||
/* gate is open */
|
||||
DPRINT1("processing object gate open\n");
|
||||
break;
|
||||
}
|
||||
|
||||
DPRINT1("IKsProcessingObject_fnProcessingObjectWork not implemented\n");
|
||||
ASSERT(0);
|
||||
|
||||
}while(TRUE);
|
||||
|
||||
/* release process mutex */
|
||||
KeReleaseMutex(&This->ProcessingMutex, FALSE);
|
||||
}
|
||||
|
||||
PKSGATE
|
||||
NTAPI
|
||||
IKsProcessingObject_fnGetAndGate(
|
||||
IKsProcessingObject * iface)
|
||||
{
|
||||
IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
|
||||
|
||||
/* return and gate */
|
||||
return &This->Gate;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
IKsProcessingObject_fnProcess(
|
||||
IKsProcessingObject * iface,
|
||||
IN BOOLEAN Asynchronous)
|
||||
{
|
||||
IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
|
||||
|
||||
/* should the action be asynchronous */
|
||||
if (Asynchronous)
|
||||
{
|
||||
/* queue work item */
|
||||
KsQueueWorkItem(This->Worker, &This->WorkItem);
|
||||
DPRINT1("queueing\n");
|
||||
/* done */
|
||||
return;
|
||||
}
|
||||
|
||||
/* does the filter require explicit deferred processing */
|
||||
if ((This->Filter.Descriptor->Flags & (KSFILTER_FLAG_DISPATCH_LEVEL_PROCESSING | KSFILTER_FLAG_CRITICAL_PROCESSING | KSFILTER_FLAG_HYPERCRITICAL_PROCESSING)) &&
|
||||
KeGetCurrentIrql() > PASSIVE_LEVEL)
|
||||
{
|
||||
/* queue work item */
|
||||
KsQueueWorkItem(This->Worker, &This->WorkItem);
|
||||
DPRINT1("queueing\n");
|
||||
/* done */
|
||||
return;
|
||||
}
|
||||
DPRINT1("invoke\n");
|
||||
/* call worker routine directly */
|
||||
iface->lpVtbl->ProcessingObjectWork(iface);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
IKsProcessingObject_fnReset(
|
||||
IKsProcessingObject * iface)
|
||||
{
|
||||
IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtblKsProcessingObject);
|
||||
|
||||
/* acquire processing mutex */
|
||||
KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
|
||||
|
||||
/* check if the filter supports dispatch routines */
|
||||
if (This->Filter.Descriptor->Dispatch)
|
||||
{
|
||||
/* has the filter a reset routine */
|
||||
if (This->Filter.Descriptor->Dispatch->Reset)
|
||||
{
|
||||
/* reset filter */
|
||||
This->Filter.Descriptor->Dispatch->Reset(&This->Filter);
|
||||
}
|
||||
}
|
||||
|
||||
/* release process mutex */
|
||||
KeReleaseMutex(&This->ProcessingMutex, FALSE);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
IKsProcessingObject_fnTriggerNotification(
|
||||
IKsProcessingObject * iface)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static IKsProcessingObjectVtbl vt_IKsProcessingObject =
|
||||
{
|
||||
IKsProcessingObject_fnQueryInterface,
|
||||
IKsProcessingObject_fnAddRef,
|
||||
IKsProcessingObject_fnRelease,
|
||||
IKsProcessingObject_fnProcessingObjectWork,
|
||||
IKsProcessingObject_fnGetAndGate,
|
||||
IKsProcessingObject_fnProcess,
|
||||
IKsProcessingObject_fnReset,
|
||||
IKsProcessingObject_fnTriggerNotification
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IKsControl_fnQueryInterface(
|
||||
|
@ -485,7 +679,7 @@ IKsFilter_GetFilterFromIrp(
|
|||
Irp->IoStatus.Status = Status;
|
||||
|
||||
/* complete and forget irp */
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
return Status;
|
||||
|
@ -522,7 +716,7 @@ IKsFilter_DispatchClose(
|
|||
/* save the result */
|
||||
Irp->IoStatus.Status = Status;
|
||||
/* complete irp */
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
/* remove our instance from the filter factory */
|
||||
IKsFilter_RemoveFilterFromFilterFactory(This, This->Factory);
|
||||
|
@ -535,7 +729,7 @@ IKsFilter_DispatchClose(
|
|||
/* complete and forget */
|
||||
Irp->IoStatus.Status = Status;
|
||||
/* complete irp */
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
/* done */
|
||||
|
@ -881,7 +1075,7 @@ IKsFilter_DispatchDeviceIoControl(
|
|||
if (Status != STATUS_PENDING)
|
||||
{
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
/* done */
|
||||
|
@ -1227,7 +1421,7 @@ IKsFilter_DispatchCreatePin(
|
|||
{
|
||||
/* complete request */
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
/* done */
|
||||
|
@ -1243,7 +1437,7 @@ IKsFilter_DispatchCreateNode(
|
|||
{
|
||||
UNIMPLEMENTED
|
||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
@ -1356,6 +1550,20 @@ IKsFilter_RemoveFilterFromFilterFactory(
|
|||
}while(TRUE);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
IKsFilter_FilterCentricWorker(
|
||||
IN PVOID Ctx)
|
||||
{
|
||||
IKsProcessingObject * Object = (IKsProcessingObject*)Ctx;
|
||||
|
||||
/* sanity check */
|
||||
ASSERT(Object);
|
||||
|
||||
/* perform work */
|
||||
Object->lpVtbl->ProcessingObjectWork(Object);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KspCreateFilter(
|
||||
|
@ -1377,17 +1585,27 @@ KspCreateFilter(
|
|||
/* get the filter factory */
|
||||
Factory = iface->lpVtbl->GetStruct(iface);
|
||||
|
||||
if (!Factory || !Factory->FilterDescriptor || !Factory->FilterDescriptor->Dispatch || !Factory->FilterDescriptor->Dispatch->Create)
|
||||
if (!Factory || !Factory->FilterDescriptor)
|
||||
{
|
||||
/* Sorry it just will not work */
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
if (Factory->FilterDescriptor->Flags & KSFILTER_FLAG_DENY_USERMODE_ACCESS)
|
||||
{
|
||||
if (Irp->RequestorMode == UserMode)
|
||||
{
|
||||
/* filter not accessible from user mode */
|
||||
DPRINT1("Access denied\n");
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
|
||||
/* allocate filter instance */
|
||||
This = AllocateItem(NonPagedPool, sizeof(IKsFilterImpl));
|
||||
if (!This)
|
||||
{
|
||||
DPRINT("KspCreateFilter OutOfMemory\n");
|
||||
DPRINT1("KspCreateFilter OutOfMemory\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
|
@ -1397,7 +1615,7 @@ KspCreateFilter(
|
|||
{
|
||||
/* no memory */
|
||||
FreeItem(This);
|
||||
DPRINT("KspCreateFilter OutOfMemory\n");
|
||||
DPRINT1("KspCreateFilter OutOfMemory\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->BasicHeader.OuterUnknown;
|
||||
|
@ -1424,12 +1642,10 @@ KspCreateFilter(
|
|||
/* no memory */
|
||||
FreeItem(This->Filter.Bag);
|
||||
FreeItem(This);
|
||||
DPRINT("KspCreateFilter OutOfMemory\n");
|
||||
DPRINT1("KspCreateFilter OutOfMemory\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
DPRINT("KspCreateFilter Flags %lx\n", Factory->FilterDescriptor->Flags);
|
||||
|
||||
/* initialize pin create item */
|
||||
CreateItem[0].Create = IKsFilter_DispatchCreatePin;
|
||||
CreateItem[0].Context = (PVOID)This;
|
||||
|
@ -1446,11 +1662,13 @@ KspCreateFilter(
|
|||
This->ref = 1;
|
||||
This->Header.OuterUnknown = (PUNKNOWN)&vt_IKsFilter;
|
||||
This->lpVtblKsControl = &vt_IKsControl;
|
||||
This->lpVtblKsProcessingObject = &vt_IKsProcessingObject;
|
||||
|
||||
This->Factory = Factory;
|
||||
This->FilterFactory = iface;
|
||||
This->FileObject = IoStack->FileObject;
|
||||
KeInitializeMutex(&This->ProcessingMutex, 0);
|
||||
|
||||
/* initialize basic header */
|
||||
This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
|
||||
This->Header.Parent.KsFilterFactory = iface->lpVtbl->GetStruct(iface);
|
||||
|
@ -1460,17 +1678,39 @@ KspCreateFilter(
|
|||
InitializeListHead(&This->Header.EventList);
|
||||
KeInitializeSpinLock(&This->Header.EventListLock);
|
||||
|
||||
/* initialize and gate */
|
||||
KsGateInitializeAnd(&This->Gate, NULL);
|
||||
|
||||
/* FIXME initialize and gate based on pin flags */
|
||||
|
||||
/* initialize work item */
|
||||
ExInitializeWorkItem(&This->WorkItem, IKsFilter_FilterCentricWorker, (PVOID)This->lpVtblKsProcessingObject);
|
||||
|
||||
/* allocate counted work item */
|
||||
Status = KsRegisterCountedWorker(HyperCriticalWorkQueue, &This->WorkItem, &This->Worker);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* what can go wrong, goes wrong */
|
||||
DPRINT1("KsRegisterCountedWorker failed with %lx\n", Status);
|
||||
FreeItem(This);
|
||||
FreeItem(CreateItem);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* allocate the stream descriptors */
|
||||
Status = IKsFilter_CreateDescriptors(This, (PKSFILTER_DESCRIPTOR)Factory->FilterDescriptor);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* what can go wrong, goes wrong */
|
||||
DPRINT1("IKsFilter_CreateDescriptors failed with %lx\n", Status);
|
||||
KsUnregisterWorker(This->Worker);
|
||||
FreeItem(This);
|
||||
FreeItem(CreateItem);
|
||||
DPRINT("IKsFilter_CreateDescriptors failed with %lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* does the filter have a filter dispatch */
|
||||
if (Factory->FilterDescriptor->Dispatch)
|
||||
{
|
||||
|
@ -1489,6 +1729,7 @@ KspCreateFilter(
|
|||
DPRINT1("Driver: Status %x\n", Status);
|
||||
|
||||
/* free filter instance */
|
||||
KsUnregisterWorker(This->Worker);
|
||||
FreeItem(This);
|
||||
FreeItem(CreateItem);
|
||||
return Status;
|
||||
|
@ -1515,7 +1756,7 @@ KspCreateFilter(
|
|||
IKsFilter_AttachFilterToFilterFactory(This, This->Header.Parent.KsFilterFactory);
|
||||
|
||||
/* completed initialization */
|
||||
DPRINT("KspCreateFilter done %lx KsDevice %p\n", Status, This->Header.KsDevice);
|
||||
DPRINT1("KspCreateFilter done %lx KsDevice %p\n", Status, This->Header.KsDevice);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -1599,7 +1840,7 @@ KsFilterAddTopologyConnections (
|
|||
}
|
||||
|
||||
/*
|
||||
@unimplemented
|
||||
@implemented
|
||||
*/
|
||||
KSDDKAPI
|
||||
VOID
|
||||
|
@ -1608,7 +1849,20 @@ KsFilterAttemptProcessing(
|
|||
IN PKSFILTER Filter,
|
||||
IN BOOLEAN Asynchronous)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
PKSGATE Gate;
|
||||
IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
|
||||
|
||||
/* get gate */
|
||||
Gate = This->lpVtblKsProcessingObject->GetAndGate((IKsProcessingObject*)This->lpVtblKsProcessingObject);
|
||||
|
||||
if (!KsGateCaptureThreshold(Gate))
|
||||
{
|
||||
/* filter control gate is closed */
|
||||
return;
|
||||
}
|
||||
DPRINT1("processing\n");
|
||||
/* try initiate processing */
|
||||
This->lpVtblKsProcessingObject->Process((IKsProcessingObject*)This->lpVtblKsProcessingObject, Asynchronous);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1710,8 +1964,10 @@ NTAPI
|
|||
KsFilterGetAndGate(
|
||||
IN PKSFILTER Filter)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return NULL;
|
||||
IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
|
||||
|
||||
/* return and-gate */
|
||||
return &This->Gate;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -69,7 +69,7 @@ IKsFilterFactory_Create(
|
|||
{
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
return Status;
|
||||
|
|
|
@ -34,7 +34,7 @@ KsDispatchQuerySecurity(
|
|||
{
|
||||
/* no create item */
|
||||
Irp->IoStatus.Status = STATUS_NO_SECURITY_ON_OBJECT;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_NO_SECURITY_ON_OBJECT;
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ KsDispatchQuerySecurity(
|
|||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = Length;
|
||||
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,7 @@ KsDispatchSetSecurity(
|
|||
{
|
||||
/* no create item */
|
||||
Irp->IoStatus.Status = STATUS_NO_SECURITY_ON_OBJECT;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_NO_SECURITY_ON_OBJECT;
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ KsDispatchSetSecurity(
|
|||
|
||||
/* store result */
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
@ -1154,7 +1154,7 @@ KsDispatchInvalidDeviceRequest(
|
|||
IN PIRP Irp)
|
||||
{
|
||||
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
|
@ -1198,7 +1198,7 @@ KsDefaultDeviceIoCompletion(
|
|||
|
||||
/* complete request */
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
|
||||
return Status;
|
||||
|
@ -1649,8 +1649,9 @@ KsAddIrpToCancelableQueue(
|
|||
if (IoStack->MajorFunction == IRP_MJ_CREATE)
|
||||
{
|
||||
// complete the request
|
||||
DPRINT1("MS HACK\n");
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1736,7 +1737,7 @@ KsCancelRoutine(
|
|||
{
|
||||
/* let's complete it */
|
||||
Irp->IoStatus.Status = STATUS_CANCELLED;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1795,14 +1796,12 @@ FindMatchingCreateItem(
|
|||
continue;
|
||||
}
|
||||
|
||||
ASSERT(CreateItemEntry->CreateItem->ObjectClass.Buffer);
|
||||
|
||||
DPRINT("CreateItem %S Length %u Request %wZ %u\n", CreateItemEntry->CreateItem->ObjectClass.Buffer,
|
||||
CreateItemEntry->CreateItem->ObjectClass.Length,
|
||||
&RefString,
|
||||
BufferSize);
|
||||
RefString.Length);
|
||||
|
||||
if (CreateItemEntry->CreateItem->ObjectClass.Length > BufferSize)
|
||||
if (CreateItemEntry->CreateItem->ObjectClass.Length > RefString.Length)
|
||||
{
|
||||
/* create item doesnt match in length */
|
||||
Entry = Entry->Flink;
|
||||
|
@ -1853,7 +1852,7 @@ KspCreate(
|
|||
Irp->IoStatus.Information = 0;
|
||||
/* set return status */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1893,7 +1892,7 @@ KspCreate(
|
|||
Irp->IoStatus.Information = 0;
|
||||
/* set return status */
|
||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
@ -1929,7 +1928,7 @@ KspDispatchIrp(
|
|||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
/* complete and forget */
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -2036,6 +2035,7 @@ KsDispatchIrp(
|
|||
|
||||
/* get device extension */
|
||||
DeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
|
||||
|
||||
/* get device header */
|
||||
DeviceHeader = DeviceExtension->DeviceHeader;
|
||||
|
||||
|
|
|
@ -6,6 +6,13 @@
|
|||
#define TAG_KSDEVICE 'DESK'
|
||||
#define TAG_KSOBJECT_TAG 'HOSK'
|
||||
|
||||
VOID
|
||||
CompleteRequest(
|
||||
PIRP Irp,
|
||||
CCHAR PriorityBoost);
|
||||
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KspCreateObjectType(
|
||||
|
|
|
@ -307,3 +307,34 @@ DECLARE_INTERFACE_(IKsDevice, IUnknown)
|
|||
STDMETHOD_(NTSTATUS, CheckIoCapability)(THIS_
|
||||
IN ULONG Unknown)PURE;
|
||||
};
|
||||
|
||||
#undef INTERFACE
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* IKsProcessingObject
|
||||
*****************************************************************************
|
||||
*/
|
||||
|
||||
#undef INTERFACE
|
||||
#define INTERFACE IKsProcessingObject
|
||||
|
||||
DECLARE_INTERFACE_(IKsProcessingObject, IUnknown)
|
||||
{
|
||||
DEFINE_ABSTRACT_UNKNOWN()
|
||||
|
||||
STDMETHOD_(VOID, ProcessingObjectWork)(THIS) PURE;
|
||||
|
||||
STDMETHOD_(PKSGATE, GetAndGate)(THIS) PURE;
|
||||
|
||||
STDMETHOD_(VOID, Process)(THIS_
|
||||
IN BOOLEAN Asynchronous)PURE;
|
||||
|
||||
STDMETHOD_(VOID, Reset)(THIS) PURE;
|
||||
|
||||
STDMETHOD_(VOID, TriggerNotification)(THIS) PURE;
|
||||
|
||||
};
|
||||
|
||||
#undef INTERFACE
|
||||
|
||||
|
|
|
@ -134,12 +134,6 @@ typedef struct
|
|||
PIO_WORKITEM WorkItem;
|
||||
}PNP_POSTSTART_CONTEXT, *PPNP_POSTSTART_CONTEXT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PIRP Irp;
|
||||
KEVENT Event;
|
||||
}KSREMOVE_BUS_INTERFACE_CTX, *PKSREMOVE_BUS_INTERFACE_CTX;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PLIST_ENTRY List;
|
||||
|
@ -150,20 +144,97 @@ typedef struct
|
|||
|
||||
typedef BOOLEAN (NTAPI *PKSEVENT_SYNCHRONIZED_ROUTINE)(PKSEVENT_CTX Context);
|
||||
|
||||
struct __BUS_ENUM_DEVICE_EXTENSION__;
|
||||
struct __BUS_DEVICE_ENTRY__;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BOOLEAN Enabled;
|
||||
LIST_ENTRY Entry;
|
||||
ULONG IsBus;
|
||||
union
|
||||
{
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
ULONG DeviceReferenceCount;
|
||||
};
|
||||
union
|
||||
{
|
||||
struct __BUS_DEVICE_ENTRY__* DeviceEntry;
|
||||
ULONG Dummy1;
|
||||
};
|
||||
struct __BUS_ENUM_DEVICE_EXTENSION__ *BusDeviceExtension;
|
||||
ULONG DeviceObjectReferenceCount;
|
||||
}COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
|
||||
|
||||
PDEVICE_OBJECT PnpDeviceObject;
|
||||
typedef struct
|
||||
{
|
||||
PCOMMON_DEVICE_EXTENSION Ext;
|
||||
}DEV_EXTENSION, *PDEV_EXTENSION;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LIST_ENTRY Entry;
|
||||
GUID InterfaceGuid;
|
||||
UNICODE_STRING SymbolicLink;
|
||||
}BUS_INSTANCE_ENTRY, *PBUS_INSTANCE_ENTRY;
|
||||
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NotStarted = 0, // Not started yet
|
||||
Started, // Device has received the START_DEVICE IRP
|
||||
StopPending, // Device has received the QUERY_STOP IRP
|
||||
Stopped, // Device has received the STOP_DEVICE IRP
|
||||
RemovePending, // Device has received the QUERY_REMOVE IRP
|
||||
SurpriseRemovePending, // Device has received the SURPRISE_REMOVE IRP
|
||||
Deleted
|
||||
}DEVICE_STATE;
|
||||
|
||||
|
||||
typedef struct __BUS_DEVICE_ENTRY__
|
||||
{
|
||||
LIST_ENTRY Entry;
|
||||
LIST_ENTRY DeviceInterfaceList;
|
||||
LIST_ENTRY IrpPendingList;
|
||||
PDEVICE_OBJECT PDO;
|
||||
DEVICE_STATE DeviceState;
|
||||
GUID DeviceGuid;
|
||||
LPWSTR PDODeviceName;
|
||||
LPWSTR DeviceName;
|
||||
LPWSTR BusId;
|
||||
LARGE_INTEGER TimeCreated;
|
||||
LARGE_INTEGER TimeExpired;
|
||||
LPWSTR Instance;
|
||||
}BUS_DEVICE_ENTRY, *PBUS_DEVICE_ENTRY;
|
||||
|
||||
typedef struct __BUS_ENUM_DEVICE_EXTENSION__
|
||||
{
|
||||
COMMON_DEVICE_EXTENSION Common;
|
||||
KSPIN_LOCK Lock;
|
||||
KEVENT Event;
|
||||
UNICODE_STRING DeviceInterfaceLink;
|
||||
PDEVICE_OBJECT PhysicalDeviceObject;
|
||||
PDEVICE_OBJECT PnpDeviceObject;
|
||||
PDEVICE_OBJECT BusDeviceObject;
|
||||
|
||||
ULONG PdoCreated;
|
||||
KTIMER Timer;
|
||||
KDPC Dpc;
|
||||
WORK_QUEUE_ITEM WorkItem;
|
||||
ULONG DeviceAttached;
|
||||
UNICODE_STRING ServicePath;
|
||||
UNICODE_STRING SymbolicLinkName;
|
||||
|
||||
WCHAR BusIdentifier[1];
|
||||
}BUS_ENUM_DEVICE_EXTENSION, *PBUS_ENUM_DEVICE_EXTENSION;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PIRP Irp;
|
||||
PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension;
|
||||
KEVENT Event;
|
||||
NTSTATUS Status;
|
||||
WORK_QUEUE_ITEM WorkItem;
|
||||
}BUS_INSTALL_ENUM_CONTEXT, *PBUS_INSTALL_ENUM_CONTEXT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PUCHAR FilterData;
|
||||
|
|
|
@ -9,6 +9,19 @@
|
|||
|
||||
#include "priv.h"
|
||||
|
||||
VOID
|
||||
CompleteRequest(
|
||||
PIRP Irp,
|
||||
CCHAR PriorityBoost)
|
||||
{
|
||||
DPRINT("Completing IRP %p Status %x\n", Irp, Irp->IoStatus.Status);
|
||||
|
||||
ASSERT(Irp->IoStatus.Status != STATUS_PENDING);
|
||||
|
||||
|
||||
IoCompleteRequest(Irp, PriorityBoost);
|
||||
}
|
||||
|
||||
PVOID
|
||||
AllocateItem(
|
||||
IN POOL_TYPE PoolType,
|
||||
|
|
|
@ -1875,7 +1875,7 @@ IKsPin_DispatchKsStream(
|
|||
DPRINT1("KsProbeStreamIrp failed with %x\n", Status);
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -1888,7 +1888,7 @@ IKsPin_DispatchKsStream(
|
|||
{
|
||||
DPRINT("NoHeader Canceling Irp %p\n", Irp);
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -1911,7 +1911,7 @@ IKsPin_DispatchKsStream(
|
|||
{
|
||||
DPRINT("NoHeader->Data Canceling Irp %p\n", Irp);
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -1960,7 +1960,7 @@ IKsPin_DispatchKsStream(
|
|||
/* invalid device request */
|
||||
DPRINT("Filter Centric Processing No Process Routine\n");
|
||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
@ -2095,7 +2095,7 @@ IKsPin_DispatchDeviceIoControl(
|
|||
if (Status != STATUS_PENDING)
|
||||
{
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
/* done */
|
||||
|
@ -2135,7 +2135,7 @@ IKsPin_Close(
|
|||
{
|
||||
/* abort closing */
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -2145,7 +2145,7 @@ IKsPin_Close(
|
|||
if (Status != STATUS_PENDING)
|
||||
{
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
@ -2162,7 +2162,7 @@ IKsPin_DispatchCreateAllocator(
|
|||
UNIMPLEMENTED;
|
||||
|
||||
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
@ -2244,7 +2244,7 @@ IKsPin_DispatchCreateClock(
|
|||
|
||||
/* done */
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -2257,7 +2257,7 @@ IKsPin_DispatchCreateNode(
|
|||
UNIMPLEMENTED;
|
||||
|
||||
Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
CompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include "ksmedia.h"
|
||||
#include "bdamedia.h"
|
||||
#include <swenum.h>
|
||||
|
||||
|
||||
#define TAG_DEVICE_HEADER 'KSDH'
|
||||
#define REG_PINFLAG_B_MANY 0x4 /* strmif.h */
|
||||
|
|
2174
drivers/ksfilter/ks/swenum.c
Normal file
2174
drivers/ksfilter/ks/swenum.c
Normal file
File diff suppressed because it is too large
Load diff
11
drivers/ksfilter/swenum/CMakeLists.txt
Normal file
11
drivers/ksfilter/swenum/CMakeLists.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
list(APPEND SOURCE
|
||||
swenum.c)
|
||||
|
||||
add_library(swenum SHARED ${SOURCE})
|
||||
|
||||
set_module_type(swenum kernelmodedriver)
|
||||
add_importlibs(swenum ks ntoskrnl hal)
|
||||
|
||||
add_minicd_target(swenum reactos)
|
||||
add_livecd_target(swenum reactos/system32/drivers)
|
|
@ -18,8 +18,56 @@ SwDispatchPower(
|
|||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp)
|
||||
{
|
||||
NTSTATUS Status, PnpStatus;
|
||||
BOOLEAN ChildDevice;
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
PDEVICE_OBJECT PnpDeviceObject = NULL;
|
||||
|
||||
UNIMPLEMENTED;
|
||||
/* get current stack location */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* check if the device object is a child device */
|
||||
Status = KsIsBusEnumChildDevice(DeviceObject, &ChildDevice);
|
||||
|
||||
/* get bus enum pnp object */
|
||||
PnpStatus = KsGetBusEnumPnpDeviceObject(DeviceObject, &PnpDeviceObject);
|
||||
|
||||
/* check for success */
|
||||
if (!NT_SUCCESS(Status) || !NT_SUCCESS(PnpStatus))
|
||||
{
|
||||
/* start next power irp */
|
||||
PoStartNextPowerIrp(Irp);
|
||||
|
||||
/* just complete the irp */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
|
||||
/* complete the irp */
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
/* done */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (IoStack->MinorFunction == IRP_MN_SET_POWER || IoStack->MinorFunction == IRP_MN_QUERY_POWER)
|
||||
{
|
||||
/* fake success */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!ChildDevice)
|
||||
{
|
||||
/* forward to pnp device object */
|
||||
PoStartNextPowerIrp(Irp);
|
||||
|
||||
/* skip current location */
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* done */
|
||||
return PoCallDriver(PnpDeviceObject, Irp);
|
||||
}
|
||||
|
||||
/* start next power irp */
|
||||
PoStartNextPowerIrp(Irp);
|
||||
|
||||
/* just complete the irp */
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
|
@ -29,7 +77,6 @@ SwDispatchPower(
|
|||
|
||||
/* done */
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
@ -43,6 +90,9 @@ SwDispatchPnp(
|
|||
PIO_STACK_LOCATION IoStack;
|
||||
PDEVICE_OBJECT PnpDeviceObject = NULL;
|
||||
|
||||
/* get current stack location */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* check if the device object is a child device */
|
||||
Status = KsIsBusEnumChildDevice(DeviceObject, &ChildDevice);
|
||||
|
||||
|
@ -55,10 +105,30 @@ SwDispatchPnp(
|
|||
return Status;
|
||||
}
|
||||
|
||||
DPRINT("SwDispatchPnp ChildDevice %u Request %x\n", ChildDevice, IoStack->MinorFunction);
|
||||
|
||||
/* let ks handle it */
|
||||
Status = KsServiceBusEnumPnpRequest(DeviceObject, Irp);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
/* check if the request was for a pdo */
|
||||
if (!ChildDevice)
|
||||
{
|
||||
if (Status != STATUS_NOT_SUPPORTED)
|
||||
{
|
||||
/* store result */
|
||||
Irp->IoStatus.Status = Status;
|
||||
}
|
||||
|
||||
/* complete request */
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
/* done */
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT("SwDispatchPnp KsServiceBusEnumPnpRequest Status %x\n", Status);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* invalid request or not supported */
|
||||
Irp->IoStatus.Status = Status;
|
||||
|
@ -69,6 +139,8 @@ SwDispatchPnp(
|
|||
/* get bus enum pnp object */
|
||||
Status = KsGetBusEnumPnpDeviceObject(DeviceObject, &PnpDeviceObject);
|
||||
|
||||
DPRINT("SwDispatchPnp KsGetBusEnumPnpDeviceObject Status %x\n", Status);
|
||||
|
||||
/* check for success */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
|
@ -89,11 +161,49 @@ SwDispatchPnp(
|
|||
/* delete the device */
|
||||
IoDeleteDevice(DeviceObject);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCES || IoStack->MinorFunction == IRP_MN_QUERY_RESOURCE_REQUIREMENTS)
|
||||
{
|
||||
/* no resources required */
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
|
||||
/* skip current location */
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
/* call the pnp device object */
|
||||
return IoCallDriver(PnpDeviceObject, Irp);
|
||||
/* skip current location */
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* call the pnp device object */
|
||||
return IoCallDriver(PnpDeviceObject, Irp);
|
||||
}
|
||||
|
||||
if (IoStack->MajorFunction == IRP_MN_QUERY_PNP_DEVICE_STATE)
|
||||
{
|
||||
/* device cannot be disabled */
|
||||
Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
|
||||
/* skip current location */
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* call the pnp device object */
|
||||
return IoCallDriver(PnpDeviceObject, Irp);
|
||||
}
|
||||
|
||||
if (Status == STATUS_NOT_SUPPORTED)
|
||||
{
|
||||
/* skip current location */
|
||||
IoSkipCurrentIrpStackLocation(Irp);
|
||||
|
||||
/* call the pnp device object */
|
||||
return IoCallDriver(PnpDeviceObject, Irp);
|
||||
}
|
||||
}
|
||||
|
||||
/* complete the request */
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
|
@ -149,7 +259,7 @@ SwDispatchDeviceControl(
|
|||
IN PIRP Irp)
|
||||
{
|
||||
PIO_STACK_LOCATION IoStack;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* get current stack location */
|
||||
IoStack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
@ -158,16 +268,25 @@ SwDispatchDeviceControl(
|
|||
{
|
||||
/* install interface */
|
||||
Status = KsInstallBusEnumInterface(Irp);
|
||||
DPRINT("SwDispatchDeviceControl IOCTL_SWENUM_INSTALL_INTERFACE %x\n", Status);
|
||||
}
|
||||
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SWENUM_REMOVE_INTERFACE)
|
||||
{
|
||||
/* remove interface */
|
||||
Status = KsRemoveBusEnumInterface(Irp);
|
||||
DPRINT("SwDispatchDeviceControl IOCTL_SWENUM_REMOVE_INTERFACE %x\n", Status);
|
||||
|
||||
}
|
||||
else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_SWENUM_GET_BUS_ID)
|
||||
{
|
||||
/* get bus id */
|
||||
return KsGetBusEnumIdentifier(Irp);
|
||||
Status = KsGetBusEnumIdentifier(Irp);
|
||||
DPRINT("SwDispatchDeviceControl IOCTL_SWENUM_GET_BUS_ID %x\n", Status);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("SwDispatchDeviceControl Unknown IOCTL %x\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* store result */
|
||||
|
@ -193,6 +312,8 @@ SwDispatchCreate(
|
|||
/* check if the device object is a child device */
|
||||
Status = KsIsBusEnumChildDevice(DeviceObject, &ChildDevice);
|
||||
|
||||
DPRINT("SwDispatchCreate %x\n", Status);
|
||||
|
||||
/* check for success */
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
|
@ -205,6 +326,7 @@ SwDispatchCreate(
|
|||
}
|
||||
/* perform the create request */
|
||||
Status = KsServiceBusEnumCreateRequest(DeviceObject, Irp);
|
||||
DPRINT("SwDispatchCreate %x\n", Status);
|
||||
}
|
||||
|
||||
/* check the irp is pending */
|
||||
|
@ -245,6 +367,7 @@ SwAddDevice(
|
|||
NTSTATUS Status;
|
||||
PDEVICE_OBJECT FunctionalDeviceObject;
|
||||
|
||||
DPRINT("SWENUM AddDevice\n");
|
||||
/* create the device */
|
||||
Status = IoCreateDevice(DriverObject, sizeof(KSDEVICE_HEADER), NULL, FILE_DEVICE_BUS_EXTENDER, 0, FALSE, &FunctionalDeviceObject);
|
||||
|
||||
|
@ -303,7 +426,7 @@ DriverEntry(
|
|||
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SwDispatchDeviceControl;
|
||||
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = SwDispatchSystemControl;
|
||||
|
||||
|
||||
DPRINT("SWENUM loaded\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,13 +5,15 @@ include_directories(
|
|||
|
||||
add_definitions(
|
||||
-DNDIS40
|
||||
-D_NTDRIVER_)
|
||||
-D_NTDRIVER_
|
||||
-D_TDI_)
|
||||
|
||||
spec2def(tdi.sys misc/tdi.spec)
|
||||
|
||||
list(APPEND SOURCE
|
||||
cte/events.c
|
||||
cte/string.c
|
||||
cte/stubs.c
|
||||
cte/timer.c
|
||||
misc/main.c
|
||||
misc/tdi.rc
|
||||
tdi/dereg.c
|
||||
|
|
157
drivers/network/tdi/cte/events.c
Normal file
157
drivers/network/tdi/cte/events.c
Normal file
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* PROJECT: ReactOS TDI driver
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: drivers/network/tdi/cte/events.c
|
||||
* PURPOSE: CTE events support
|
||||
* PROGRAMMERS: Oleg Baikalow (obaikalow@gmail.com)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ntddk.h>
|
||||
|
||||
typedef struct _CTEBLOCK_EVENT
|
||||
{
|
||||
NTSTATUS Status;
|
||||
KEVENT Event;
|
||||
} CTEBLOCK_EVENT, *PCTEBLOCK_EVENT;
|
||||
|
||||
struct _CTE_DELAYED_EVENT;
|
||||
typedef void (*CTE_WORKER_ROUTINE)(struct _CTE_DELAYED_EVENT *, void *Context);
|
||||
|
||||
typedef struct _CTE_DELAYED_EVENT
|
||||
{
|
||||
BOOLEAN Queued;
|
||||
KSPIN_LOCK Lock;
|
||||
CTE_WORKER_ROUTINE WorkerRoutine;
|
||||
PVOID Context;
|
||||
WORK_QUEUE_ITEM WorkItem;
|
||||
} CTE_DELAYED_EVENT, *PCTE_DELAYED_EVENT;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CTEBlock(PCTEBLOCK_EVENT Block)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Perform the wait */
|
||||
Status = KeWaitForSingleObject(&Block->Event, UserRequest, KernelMode, FALSE, NULL);
|
||||
|
||||
/* Update event status if wait was not successful */
|
||||
if (!NT_SUCCESS(Status)) Block->Status = Status;
|
||||
|
||||
return Block->Status;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
InternalWorker(IN PVOID Parameter)
|
||||
{
|
||||
PCTE_DELAYED_EVENT Event = (PCTE_DELAYED_EVENT)Parameter;
|
||||
KIRQL OldIrql;
|
||||
|
||||
/* Acquire the lock */
|
||||
KeAcquireSpinLock(&Event->Lock, &OldIrql);
|
||||
|
||||
/* Make sure it is queued */
|
||||
ASSERT(Event->Queued);
|
||||
Event->Queued = FALSE;
|
||||
|
||||
/* Release the lock */
|
||||
KeReleaseSpinLock(&Event->Lock, OldIrql);
|
||||
|
||||
/* Call the real worker routine */
|
||||
(*Event->WorkerRoutine)(Event, Event->Context);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
CTEInitEvent(PCTE_DELAYED_EVENT Event,
|
||||
CTE_WORKER_ROUTINE Routine)
|
||||
{
|
||||
/* Init the structure, lock and a work item */
|
||||
Event->Queued = FALSE;
|
||||
KeInitializeSpinLock(&Event->Lock);
|
||||
Event->WorkerRoutine = Routine;
|
||||
ExInitializeWorkItem(&Event->WorkItem, InternalWorker, Event);
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CTELogEvent (
|
||||
ULONG Unknown0,
|
||||
ULONG Unknown1,
|
||||
ULONG Unknown2,
|
||||
ULONG Unknown3,
|
||||
ULONG Unknown4,
|
||||
ULONG Unknown5,
|
||||
ULONG Unknown6
|
||||
)
|
||||
{
|
||||
/* Probably call
|
||||
* IoAllocateErrorLogEntry and
|
||||
* IoWriteErrorLogEntry
|
||||
*/
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CTEScheduleEvent(PCTE_DELAYED_EVENT Event,
|
||||
PVOID Context)
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
|
||||
/* Acquire the lock */
|
||||
KeAcquireSpinLock(&Event->Lock, &OldIrql);
|
||||
|
||||
/* Make sure it is queued */
|
||||
if (!Event->Queued);
|
||||
{
|
||||
/* Mark it as queued and set optional context pointer */
|
||||
Event->Queued = TRUE;
|
||||
Event->Context = Context;
|
||||
|
||||
/* Actually queue it */
|
||||
ExQueueWorkItem(&Event->WorkItem, CriticalWorkQueue);
|
||||
}
|
||||
|
||||
/* Release the lock */
|
||||
KeReleaseSpinLock(&Event->Lock, OldIrql);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
LONG
|
||||
NTAPI
|
||||
CTESignal(PCTEBLOCK_EVENT Block, NTSTATUS Status)
|
||||
{
|
||||
/* Set status right away */
|
||||
Block->Status = Status;
|
||||
|
||||
/* Set the event */
|
||||
return KeSetEvent(&Block->Event, IO_NO_INCREMENT, FALSE);
|
||||
}
|
||||
|
||||
/* EOF */
|
|
@ -1,147 +0,0 @@
|
|||
/* $Id$
|
||||
*
|
||||
*/
|
||||
#include <ntddk.h>
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CTEBlock (
|
||||
ULONG Unknown0
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
CTEInitEvent (
|
||||
ULONG Unknown0,
|
||||
ULONG Unknown1
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
CTEInitTimer (
|
||||
ULONG Unknown0
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CTEInitialize (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
/* FIXME: what should it initialize? */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
CTELogEvent (
|
||||
ULONG Unknown0,
|
||||
ULONG Unknown1,
|
||||
ULONG Unknown2,
|
||||
ULONG Unknown3,
|
||||
ULONG Unknown4,
|
||||
ULONG Unknown5,
|
||||
ULONG Unknown6
|
||||
)
|
||||
{
|
||||
/* Probably call
|
||||
* IoAllocateErrorLogEntry and
|
||||
* IoWriteErrorLogEntry
|
||||
*/
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CTEScheduleEvent (
|
||||
ULONG Unknown0,
|
||||
ULONG Unknown1
|
||||
)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
LONG
|
||||
NTAPI
|
||||
CTESignal (
|
||||
ULONG Unknown0,
|
||||
ULONG Unknown1
|
||||
)
|
||||
{
|
||||
#if 0
|
||||
PKEVENT kevent = (PKEVENT) Unknown0;
|
||||
|
||||
return KeSetEvent (
|
||||
kevent,
|
||||
0,
|
||||
FALSE
|
||||
);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CTEStartTimer (
|
||||
ULONG Unknown0,
|
||||
ULONG Unknown1,
|
||||
ULONG Unknown2,
|
||||
ULONG Unknown3
|
||||
)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
ULONG
|
||||
NTAPI
|
||||
CTESystemUpTime (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* EOF */
|
118
drivers/network/tdi/cte/timer.c
Normal file
118
drivers/network/tdi/cte/timer.c
Normal file
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* PROJECT: ReactOS TDI driver
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: drivers/network/tdi/cte/timer.c
|
||||
* PURPOSE: CTE timer support
|
||||
* PROGRAMMERS: Oleg Baikalow (obaikalow@gmail.com)
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
|
||||
#include <ntddk.h>
|
||||
|
||||
/* FIXME: Move to a common header! */
|
||||
struct _CTE_DELAYED_EVENT;
|
||||
typedef void (*CTE_WORKER_ROUTINE)(struct _CTE_DELAYED_EVENT *, void *Context);
|
||||
|
||||
typedef struct _CTE_TIMER
|
||||
{
|
||||
BOOLEAN Queued;
|
||||
KSPIN_LOCK Lock;
|
||||
CTE_WORKER_ROUTINE Callback;
|
||||
PVOID Context;
|
||||
KDPC Dpc;
|
||||
KTIMER Timer;
|
||||
} CTE_TIMER, *PCTE_TIMER;
|
||||
|
||||
LONG CteTimeIncrement;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
InternalDpcRoutine(PKDPC Dpc,
|
||||
PVOID Context,
|
||||
PVOID SystemArgument1,
|
||||
PVOID SystemArgument2)
|
||||
{
|
||||
PCTE_TIMER Timer = (PCTE_TIMER)Context;
|
||||
|
||||
/* Call our registered callback */
|
||||
Timer->Callback((struct _CTE_DELAYED_EVENT *)Timer, Timer->Context);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
CTEInitTimer(PCTE_TIMER Timer)
|
||||
{
|
||||
/* Zero all fields */
|
||||
RtlZeroMemory(Timer, sizeof(CTE_TIMER));
|
||||
|
||||
/* Create a DPC and a timer */
|
||||
KeInitializeDpc(&Timer->Dpc, InternalDpcRoutine, Timer);
|
||||
KeInitializeTimer(&Timer->Timer);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CTEStartTimer(PCTE_TIMER Timer,
|
||||
ULONG DueTimeShort,
|
||||
CTE_WORKER_ROUTINE Callback,
|
||||
PVOID Context)
|
||||
{
|
||||
LARGE_INTEGER DueTime;
|
||||
|
||||
/* Make sure a callback was provided */
|
||||
ASSERT(Callback);
|
||||
|
||||
/* We need to convert due time, because DueTimeShort is in ms,
|
||||
but NT timer expects 100s of ns, negative one */
|
||||
DueTime.QuadPart = -Int32x32To64(DueTimeShort, 10000);
|
||||
|
||||
/* Set other timer members */
|
||||
Timer->Callback = Callback;
|
||||
Timer->Context = Context;
|
||||
|
||||
/* Set the timer */
|
||||
KeSetTimer(&Timer->Timer, DueTime, &Timer->Dpc);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
ULONG
|
||||
NTAPI
|
||||
CTESystemUpTime(VOID)
|
||||
{
|
||||
LARGE_INTEGER Ticks;
|
||||
|
||||
/* Get the tick count */
|
||||
KeQueryTickCount(&Ticks);
|
||||
|
||||
/* Convert to 100s of ns and then to ms*/
|
||||
Ticks.QuadPart = (Ticks.QuadPart * CteTimeIncrement) / 10000ULL;
|
||||
|
||||
return Ticks.LowPart;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
BOOLEAN
|
||||
NTAPI
|
||||
CTEInitialize(VOID)
|
||||
{
|
||||
/* Just return success */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* EOF */
|
|
@ -1,17 +1,20 @@
|
|||
/* $Id$
|
||||
*
|
||||
/*
|
||||
* DESCRIPTION: Entry point for TDI.SYS
|
||||
* (c) Captain Obvious
|
||||
*/
|
||||
#include <ntddk.h>
|
||||
|
||||
extern LONG CteTimeIncrement;
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
DriverEntry (
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PUNICODE_STRING RegistryPath
|
||||
)
|
||||
DriverEntry(IN PDRIVER_OBJECT DriverObject,
|
||||
IN PUNICODE_STRING RegistryPath)
|
||||
{
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
/* Initialize the time increment for CTE timers */
|
||||
CteTimeIncrement = KeQueryTimeIncrement();
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -27,13 +27,13 @@
|
|||
@ stdcall TdiDeregisterDeviceObject(ptr)
|
||||
@ stdcall TdiDeregisterNetAddress(ptr)
|
||||
@ stdcall TdiDeregisterNotificationHandler(ptr)
|
||||
@ stdcall TdiInitialize(ptr)
|
||||
@ stdcall TdiInitialize()
|
||||
@ stdcall TdiMapBuffer(ptr)
|
||||
@ stdcall TdiMapUserRequest(ptr ptr ptr)
|
||||
@ stdcall TdiOpenNetbiosAddress(long long long long)
|
||||
@ stdcall TdiRegisterAddressChangeHandler(long long long)
|
||||
@ stdcall TdiRegisterDeviceObject(long long)
|
||||
@ stdcall TdiRegisterNetAddress(long long)
|
||||
@ stdcall TdiRegisterNetAddress(long ptr ptr ptr)
|
||||
@ stdcall TdiRegisterNotificationHandler(long long long)
|
||||
@ stdcall TdiReturnChainedReceives(ptr long)
|
||||
@ stdcall TdiUnmapBuffer(ptr)
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
/* $Id$
|
||||
*
|
||||
*/
|
||||
#include <ntddk.h>
|
||||
#include <tdi.h>
|
||||
#include <tdikrnl.h>
|
||||
|
||||
/* De-/Register Action IDs for TdiDeRegister */
|
||||
|
||||
|
@ -21,18 +18,6 @@ enum
|
|||
} TDI_OBJECT_ACTION;
|
||||
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
TdiDeRegister (
|
||||
IN TDI_OBJECT_ACTION Action,
|
||||
IN OUT PVOID Object
|
||||
)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/* ADDRESS_CHANGE_HANDLER */
|
||||
|
||||
/*
|
||||
|
@ -40,20 +25,11 @@ TdiDeRegister (
|
|||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
TdiRegisterAddressChangeHandler (
|
||||
ULONG Unknown0,
|
||||
ULONG Unknown1,
|
||||
ULONG Unknown2
|
||||
)
|
||||
TdiRegisterAddressChangeHandler(IN TDI_ADD_ADDRESS_HANDLER AddHandler,
|
||||
IN TDI_DEL_ADDRESS_HANDLER DeleteHandler,
|
||||
OUT HANDLE *BindingHandle)
|
||||
{
|
||||
#if 0
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
Status = TdiDeRegister (
|
||||
R_ADDRESS_CHANGE_HANDLER,
|
||||
AddressChangeHandler
|
||||
);
|
||||
#endif
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
@ -62,14 +38,9 @@ TdiRegisterAddressChangeHandler (
|
|||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
TdiDeregisterAddressChangeHandler (
|
||||
IN PVOID AddressChangeHandler
|
||||
)
|
||||
TdiDeregisterAddressChangeHandler(IN HANDLE BindingHandle)
|
||||
{
|
||||
return TdiDeRegister (
|
||||
D_ADDRESS_CHANGE_HANDLER,
|
||||
AddressChangeHandler
|
||||
);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
@ -80,19 +51,10 @@ TdiDeregisterAddressChangeHandler (
|
|||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
TdiRegisterDeviceObject (
|
||||
ULONG Unknown0,
|
||||
ULONG Unknown1
|
||||
)
|
||||
TdiRegisterDeviceObject(IN PUNICODE_STRING DeviceName,
|
||||
OUT HANDLE *RegistrationHandle)
|
||||
{
|
||||
#if 0
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
Status = TdiDeRegister (
|
||||
R_DEVICE_OBJECT,
|
||||
DeviceObject
|
||||
);
|
||||
#endif
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
@ -101,14 +63,9 @@ TdiRegisterDeviceObject (
|
|||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
TdiDeregisterDeviceObject (
|
||||
IN PVOID DeviceObject
|
||||
)
|
||||
TdiDeregisterDeviceObject(IN HANDLE RegistrationHandle)
|
||||
{
|
||||
return TdiDeRegister (
|
||||
D_DEVICE_OBJECT,
|
||||
DeviceObject
|
||||
);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
@ -119,19 +76,12 @@ TdiDeregisterDeviceObject (
|
|||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
TdiRegisterNetAddress (
|
||||
ULONG Unknown0,
|
||||
ULONG Unknown1
|
||||
)
|
||||
TdiRegisterNetAddress(IN PTA_ADDRESS Address,
|
||||
IN PUNICODE_STRING DeviceName,
|
||||
IN PTDI_PNP_CONTEXT Context,
|
||||
OUT HANDLE *RegistrationHandle)
|
||||
{
|
||||
#if 0
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
Status = TdiDeRegister (
|
||||
R_NET_ADDRESS,
|
||||
NetAddress
|
||||
);
|
||||
#endif
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
@ -140,14 +90,9 @@ TdiRegisterNetAddress (
|
|||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
TdiDeregisterNetAddress (
|
||||
IN PVOID NetAddress
|
||||
)
|
||||
TdiDeregisterNetAddress(IN HANDLE RegistrationHandle)
|
||||
{
|
||||
return TdiDeRegister (
|
||||
D_NET_ADDRESS,
|
||||
NetAddress
|
||||
);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
@ -158,20 +103,11 @@ TdiDeregisterNetAddress (
|
|||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
TdiRegisterNotificationHandler (
|
||||
ULONG Unknown0,
|
||||
ULONG Unknown1,
|
||||
ULONG Unknown2
|
||||
)
|
||||
TdiRegisterNotificationHandler(IN TDI_BIND_HANDLER BindHandler,
|
||||
IN TDI_UNBIND_HANDLER UnbindHandler,
|
||||
OUT HANDLE *BindingHandle)
|
||||
{
|
||||
#if 0
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
Status = TdiDeRegister (
|
||||
R_NOTIFICATION_HANDLER,
|
||||
NotificationHandler
|
||||
);
|
||||
#endif
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
|
@ -180,15 +116,9 @@ TdiRegisterNotificationHandler (
|
|||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
TdiDeregisterNotificationHandler (
|
||||
IN PVOID NotificationHandler
|
||||
)
|
||||
TdiDeregisterNotificationHandler(IN HANDLE BindingHandle)
|
||||
{
|
||||
return TdiDeRegister (
|
||||
DT_NOTIFICATION_HANDLER,
|
||||
NotificationHandler
|
||||
);
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -75,9 +75,7 @@ TdiCopyMdlToBuffer (
|
|||
*/
|
||||
VOID
|
||||
NTAPI
|
||||
TdiInitialize (
|
||||
PVOID Unknown0
|
||||
)
|
||||
TdiInitialize ()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -319,6 +319,7 @@ FreeEventData(IN PVOID EventData)
|
|||
}
|
||||
|
||||
VOID
|
||||
CALLBACK
|
||||
EventCallback(
|
||||
IN PVOID MixerEventContext,
|
||||
IN HANDLE hMixer,
|
||||
|
@ -474,7 +475,7 @@ WdmAudGetControlDetails(
|
|||
DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
|
||||
|
||||
/* query mmixer library */
|
||||
Status = MMixerGetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixDetails);
|
||||
Status = MMixerGetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixDetails);
|
||||
|
||||
if (Status == MM_STATUS_SUCCESS)
|
||||
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
|
||||
|
@ -496,7 +497,7 @@ WdmAudGetLineInfo(
|
|||
DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
|
||||
|
||||
/* query mixer library */
|
||||
Status = MMixerGetLineInfo(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixLine);
|
||||
Status = MMixerGetLineInfo(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixLine);
|
||||
|
||||
if (Status == MM_STATUS_SUCCESS)
|
||||
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
|
||||
|
@ -518,7 +519,7 @@ WdmAudGetLineControls(
|
|||
DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
|
||||
|
||||
/* query mixer library */
|
||||
Status = MMixerGetLineControls(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixControls);
|
||||
Status = MMixerGetLineControls(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixControls);
|
||||
|
||||
if (Status == MM_STATUS_SUCCESS)
|
||||
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
|
||||
|
@ -542,7 +543,7 @@ WdmAudSetControlDetails(
|
|||
DeviceInfo->Flags &= ~MIXER_OBJECTF_HMIXER;
|
||||
|
||||
/* query mixer library */
|
||||
Status = MMixerSetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->Flags, &DeviceInfo->u.MixDetails);
|
||||
Status = MMixerSetControlDetails(&MixerContext, DeviceInfo->hDevice, DeviceInfo->DeviceIndex, DeviceInfo->Flags, &DeviceInfo->u.MixDetails);
|
||||
|
||||
if (Status == MM_STATUS_SUCCESS)
|
||||
return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO));
|
||||
|
|
|
@ -1573,11 +1573,6 @@ typedef struct
|
|||
Properties
|
||||
*/
|
||||
|
||||
#define KSPROPERTY_MEMBER_RANGES 0x00000001
|
||||
#define KSPROPERTY_MEMBER_STEPPEDRANGES 0x00000002
|
||||
#define KSPROPERTY_MEMBER_VALUES 0x00000003
|
||||
#define KSPROPERTY_MEMBER_FLAG_DEFAULT KSPROPERTY_MEMBER_RANGES
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GUID PropertySet;
|
||||
|
@ -1663,6 +1658,17 @@ typedef struct {
|
|||
const VOID* Members;
|
||||
} KSPROPERTY_MEMBERSLIST, *PKSPROPERTY_MEMBERSLIST;
|
||||
|
||||
#define KSPROPERTY_MEMBER_RANGES 0x00000001
|
||||
#define KSPROPERTY_MEMBER_STEPPEDRANGES 0x00000002
|
||||
#define KSPROPERTY_MEMBER_VALUES 0x00000003
|
||||
|
||||
#define KSPROPERTY_MEMBER_FLAG_DEFAULT 0x00000001
|
||||
#if (NTDDI_VERSION >= NTDDI_WINXP)
|
||||
#define KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL 0x00000002
|
||||
#define KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_UNIFORM 0x00000004
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
KSIDENTIFIER PropTypeSet;
|
||||
ULONG MembersListCount;
|
||||
|
@ -2922,6 +2928,232 @@ typedef struct
|
|||
XP / DX8
|
||||
*/
|
||||
#if defined(_NTDDK_)
|
||||
|
||||
typedef struct _KSGATE KSGATE, *PKSGATE;
|
||||
|
||||
struct _KSGATE {
|
||||
LONG Count;
|
||||
PKSGATE NextGate;
|
||||
};
|
||||
|
||||
#ifndef _NTOS_
|
||||
|
||||
static
|
||||
void
|
||||
__inline
|
||||
KsGateTurnInputOn(
|
||||
IN PKSGATE Gate OPTIONAL)
|
||||
{
|
||||
while (Gate && (InterlockedIncrement(&Gate->Count) == 1))
|
||||
{
|
||||
Gate = Gate->NextGate;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
__inline
|
||||
KsGateTurnInputOff(
|
||||
IN PKSGATE Gate OPTIONAL)
|
||||
{
|
||||
while (Gate && (InterlockedDecrement(&Gate->Count) == 0))
|
||||
{
|
||||
Gate = Gate->NextGate;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
__inline
|
||||
KsGateGetStateUnsafe(
|
||||
IN PKSGATE Gate)
|
||||
{
|
||||
ASSERT(Gate);
|
||||
return((BOOLEAN)(Gate->Count > 0));
|
||||
}
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
__inline
|
||||
KsGateCaptureThreshold(
|
||||
IN PKSGATE Gate)
|
||||
{
|
||||
BOOLEAN captured;
|
||||
|
||||
ASSERT(Gate);
|
||||
|
||||
captured = (BOOLEAN)(InterlockedCompareExchange(&Gate->Count,0,1) == 1);
|
||||
|
||||
if (captured)
|
||||
{
|
||||
KsGateTurnInputOff(Gate->NextGate);
|
||||
}
|
||||
|
||||
return captured;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
__inline
|
||||
KsGateInitialize(
|
||||
IN PKSGATE Gate,
|
||||
IN LONG InitialCount,
|
||||
IN PKSGATE NextGate OPTIONAL,
|
||||
IN BOOLEAN StateToPropagate
|
||||
)
|
||||
{
|
||||
ASSERT(Gate);
|
||||
Gate->Count = InitialCount;
|
||||
Gate->NextGate = NextGate;
|
||||
|
||||
if (NextGate)
|
||||
{
|
||||
if (InitialCount > 0)
|
||||
{
|
||||
if (StateToPropagate)
|
||||
{
|
||||
KsGateTurnInputOn(NextGate);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!StateToPropagate)
|
||||
{
|
||||
KsGateTurnInputOff(NextGate);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
__inline
|
||||
KsGateInitializeAnd(
|
||||
IN PKSGATE AndGate,
|
||||
IN PKSGATE NextOrGate OPTIONAL)
|
||||
{
|
||||
KsGateInitialize(AndGate,1,NextOrGate,TRUE);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
__inline
|
||||
KsGateInitializeOr(
|
||||
IN PKSGATE OrGate,
|
||||
IN PKSGATE NextAndGate OPTIONAL)
|
||||
{
|
||||
KsGateInitialize(OrGate,0,NextAndGate,FALSE);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
__inline
|
||||
KsGateAddOnInputToAnd(
|
||||
IN PKSGATE AndGate)
|
||||
{
|
||||
UNREFERENCED_PARAMETER (AndGate);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
__inline
|
||||
KsGateAddOffInputToAnd(
|
||||
IN PKSGATE AndGate)
|
||||
{
|
||||
KsGateTurnInputOff(AndGate);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
__inline
|
||||
KsGateRemoveOnInputFromAnd(
|
||||
IN PKSGATE AndGate)
|
||||
{
|
||||
UNREFERENCED_PARAMETER (AndGate);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
__inline
|
||||
KsGateRemoveOffInputFromAnd(
|
||||
IN PKSGATE AndGate)
|
||||
{
|
||||
KsGateTurnInputOn(AndGate);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
__inline
|
||||
KsGateAddOnInputToOr(
|
||||
IN PKSGATE OrGate)
|
||||
{
|
||||
KsGateTurnInputOn(OrGate);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
__inline
|
||||
KsGateAddOffInputToOr(
|
||||
IN PKSGATE OrGate)
|
||||
{
|
||||
UNREFERENCED_PARAMETER (OrGate);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
__inline
|
||||
KsGateRemoveOnInputFromOr(
|
||||
IN PKSGATE OrGate)
|
||||
{
|
||||
KsGateTurnInputOff(OrGate);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
__inline
|
||||
KsGateRemoveOffInputFromOr(
|
||||
IN PKSGATE OrGate)
|
||||
{
|
||||
UNREFERENCED_PARAMETER (OrGate);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
__inline
|
||||
KsGateTerminateAnd(
|
||||
IN PKSGATE AndGate)
|
||||
{
|
||||
ASSERT(AndGate);
|
||||
if (KsGateGetStateUnsafe(AndGate))
|
||||
{
|
||||
KsGateRemoveOnInputFromOr(AndGate->NextGate);
|
||||
}
|
||||
else
|
||||
{
|
||||
KsGateRemoveOffInputFromOr(AndGate->NextGate);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
__inline
|
||||
KsGateTerminateOr(
|
||||
IN PKSGATE OrGate)
|
||||
{
|
||||
ASSERT(OrGate);
|
||||
if (KsGateGetStateUnsafe(OrGate))
|
||||
{
|
||||
KsGateRemoveOnInputFromAnd(OrGate->NextGate);
|
||||
}
|
||||
else
|
||||
{
|
||||
KsGateRemoveOffInputFromAnd(OrGate->NextGate);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
struct _KSMAPPING {
|
||||
PHYSICAL_ADDRESS PhysicalAddress;
|
||||
ULONG ByteCount;
|
||||
|
@ -2934,14 +3166,8 @@ typedef enum {
|
|||
KSSTREAM_POINTER_STATE_LOCKED
|
||||
} KSSTREAM_POINTER_STATE;
|
||||
|
||||
typedef struct _KSGATE KSGATE, *PKSGATE;
|
||||
typedef struct _KSPROCESSPIN_INDEXENTRY KSPROCESSPIN_INDEXENTRY, *PKSPROCESSPIN_INDEXENTRY;
|
||||
|
||||
struct _KSGATE {
|
||||
LONG Count;
|
||||
PKSGATE NextGate;
|
||||
};
|
||||
|
||||
struct _KSSTREAM_POINTER_OFFSET
|
||||
{
|
||||
#if defined(_NTDDK_)
|
||||
|
|
|
@ -135,7 +135,7 @@
|
|||
{ \
|
||||
if ( ! (parameter_condition) ) \
|
||||
{ \
|
||||
SND_ERR(L"FAILED parameter check: %hS\n", #parameter_condition); \
|
||||
SND_ERR(L"FAILED parameter check: %hS at File %S Line %lu\n", #parameter_condition, __FILE__, __LINE__); \
|
||||
return MMSYSERR_INVALPARAM; \
|
||||
} \
|
||||
}
|
||||
|
@ -199,11 +199,11 @@ typedef MMRESULT (*WAVE_COMMIT_FUNC)(
|
|||
|
||||
typedef MMRESULT (*MMMIXERQUERY_FUNC) (
|
||||
IN struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance,
|
||||
IN DWORD DeviceId,
|
||||
IN UINT uMsg,
|
||||
IN LPVOID Parameter,
|
||||
IN DWORD Flags);
|
||||
|
||||
|
||||
typedef MMRESULT (*MMWAVEQUERYFORMATSUPPORT_FUNC)(
|
||||
IN struct _SOUND_DEVICE* Device,
|
||||
IN PWAVEFORMATEX WaveFormat,
|
||||
|
|
|
@ -147,6 +147,9 @@ struct statfs;
|
|||
#define M_PI_2 1.570796326794896619
|
||||
#endif
|
||||
|
||||
#ifndef M_PI_4
|
||||
#define M_PI_4 0.785398163397448309616
|
||||
#endif
|
||||
|
||||
/* Constructor functions */
|
||||
|
||||
|
|
|
@ -17,6 +17,14 @@
|
|||
#define EWX_INTERNAL_KILL_ALL_APPS (EWX_INTERNAL_FLAG | 0x200)
|
||||
#define EWX_INTERNAL_FLAG_LOGOFF 0x1000
|
||||
|
||||
#define WM_LOGONNOTIFY 0x0000004c
|
||||
|
||||
/* WPARAM values for WM_LOGONNOTIFY */
|
||||
#define LN_START_TASK_MANAGER 0x4
|
||||
#define LN_LOCK_WORKSTATION 0x5
|
||||
#define LN_UNLOCK_WORKSTATION 0x6
|
||||
#define LN_MESSAGE_BEEP 0x9
|
||||
|
||||
#endif /* REACTOS_WINLOGON_H_INCLUDED */
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
MMRESULT
|
||||
MmeGetLineInfo(
|
||||
IN UINT DeviceId,
|
||||
IN UINT Message,
|
||||
IN DWORD_PTR PrivateHandle,
|
||||
IN DWORD_PTR Parameter1,
|
||||
|
@ -32,6 +33,21 @@ MmeGetLineInfo(
|
|||
|
||||
//SND_TRACE(L"Getting mixer info %u\n", Message);
|
||||
|
||||
if ( PrivateHandle == 0 )
|
||||
{
|
||||
Result = GetSoundDevice(MIXER_DEVICE_TYPE, DeviceId, &SoundDevice);
|
||||
|
||||
if ( ! MMSUCCESS(Result) )
|
||||
return TranslateInternalMmResult(Result);
|
||||
|
||||
Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable);
|
||||
if ( ! MMSUCCESS(Result) )
|
||||
return TranslateInternalMmResult(Result);
|
||||
|
||||
Result = FunctionTable->QueryMixerInfo(NULL, DeviceId, Message, (LPVOID)Parameter1, Parameter2);
|
||||
return Result;
|
||||
}
|
||||
|
||||
VALIDATE_MMSYS_PARAMETER( PrivateHandle );
|
||||
SoundDeviceInstance = (PSOUND_DEVICE_INSTANCE) PrivateHandle;
|
||||
|
||||
|
@ -46,7 +62,7 @@ MmeGetLineInfo(
|
|||
if ( ! FunctionTable->QueryMixerInfo )
|
||||
return MMSYSERR_NOTSUPPORTED;
|
||||
|
||||
Result = FunctionTable->QueryMixerInfo(SoundDeviceInstance, Message, (LPVOID)Parameter1, Parameter2);
|
||||
Result = FunctionTable->QueryMixerInfo(SoundDeviceInstance, DeviceId, Message, (LPVOID)Parameter1, Parameter2);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
@ -100,7 +116,7 @@ mxdMessage(
|
|||
(LPWAVEOPENDESC) Parameter1, /* unused */
|
||||
Parameter2,
|
||||
(DWORD*) PrivateHandle);
|
||||
|
||||
VALIDATE_MMSYS_PARAMETER(*(DWORD_PTR*)PrivateHandle);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -113,7 +129,8 @@ mxdMessage(
|
|||
|
||||
case MXDM_GETCONTROLDETAILS :
|
||||
{
|
||||
Result = MmeGetLineInfo(Message,
|
||||
Result = MmeGetLineInfo(DeviceId,
|
||||
Message,
|
||||
PrivateHandle,
|
||||
Parameter1,
|
||||
Parameter2);
|
||||
|
@ -123,7 +140,8 @@ mxdMessage(
|
|||
|
||||
case MXDM_SETCONTROLDETAILS :
|
||||
{
|
||||
Result = MmeGetLineInfo(Message,
|
||||
Result = MmeGetLineInfo(DeviceId,
|
||||
Message,
|
||||
PrivateHandle,
|
||||
Parameter1,
|
||||
Parameter2);
|
||||
|
@ -133,7 +151,8 @@ mxdMessage(
|
|||
|
||||
case MXDM_GETLINECONTROLS :
|
||||
{
|
||||
Result = MmeGetLineInfo(Message,
|
||||
Result = MmeGetLineInfo(DeviceId,
|
||||
Message,
|
||||
PrivateHandle,
|
||||
Parameter1,
|
||||
Parameter2);
|
||||
|
@ -143,7 +162,8 @@ mxdMessage(
|
|||
|
||||
case MXDM_GETLINEINFO :
|
||||
{
|
||||
Result = MmeGetLineInfo(Message,
|
||||
Result = MmeGetLineInfo(DeviceId,
|
||||
Message,
|
||||
PrivateHandle,
|
||||
Parameter1,
|
||||
Parameter2);
|
||||
|
|
|
@ -130,11 +130,11 @@ MmeOpenDevice(
|
|||
UINT Message;
|
||||
PSOUND_DEVICE SoundDevice;
|
||||
PSOUND_DEVICE_INSTANCE SoundDeviceInstance;
|
||||
LPWAVEFORMATEX Format;
|
||||
LPWAVEFORMATEX Format = NULL;
|
||||
|
||||
SND_TRACE(L"Opening device");
|
||||
|
||||
VALIDATE_MMSYS_PARAMETER( IS_WAVE_DEVICE_TYPE(DeviceType) ); /* FIXME? wave in too? */
|
||||
VALIDATE_MMSYS_PARAMETER( IS_WAVE_DEVICE_TYPE(DeviceType) || IS_MIXER_DEVICE_TYPE(DeviceType) || IS_MIDI_DEVICE_TYPE(DeviceType) ); /* FIXME? wave in too? */
|
||||
VALIDATE_MMSYS_PARAMETER( OpenParameters );
|
||||
|
||||
Result = GetSoundDevice(DeviceType, DeviceId, &SoundDevice);
|
||||
|
|
|
@ -65,8 +65,6 @@ SetWaveDeviceFormat(
|
|||
SND_TRACE(L"Setting wave format\n");
|
||||
|
||||
VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) );
|
||||
VALIDATE_MMSYS_PARAMETER( Format );
|
||||
VALIDATE_MMSYS_PARAMETER( FormatSize >= sizeof(WAVEFORMATEX) );
|
||||
|
||||
Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
|
||||
if ( ! MMSUCCESS(Result) )
|
||||
|
@ -74,9 +72,14 @@ SetWaveDeviceFormat(
|
|||
|
||||
Result = GetSoundDeviceType(SoundDevice, &DeviceType);
|
||||
SND_ASSERT( Result == MMSYSERR_NOERROR );
|
||||
if (DeviceType == WAVE_IN_DEVICE_TYPE || DeviceType == WAVE_OUT_DEVICE_TYPE)
|
||||
{
|
||||
VALIDATE_MMSYS_PARAMETER( Format );
|
||||
VALIDATE_MMSYS_PARAMETER( FormatSize >= sizeof(WAVEFORMATEX) );
|
||||
}
|
||||
|
||||
/* Ensure we have a wave device (TODO: check if this applies to wavein as well) */
|
||||
VALIDATE_MMSYS_PARAMETER( IS_WAVE_DEVICE_TYPE(DeviceType) );
|
||||
VALIDATE_MMSYS_PARAMETER( IS_WAVE_DEVICE_TYPE(DeviceType) || IS_MIDI_DEVICE_TYPE(DeviceType) || IS_MIXER_DEVICE_TYPE(DeviceType));
|
||||
|
||||
/* Obtain the function table */
|
||||
Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable);
|
||||
|
|
|
@ -232,6 +232,8 @@ CompleteIO(
|
|||
|
||||
}while(dwNumberOfBytesTransferred);
|
||||
|
||||
// AUDIO-BRANCH DIFF
|
||||
// completion callback is performed in a thread
|
||||
DoWaveStreaming(SoundDeviceInstance);
|
||||
|
||||
//CompleteWavePortion(SoundDeviceInstance, dwNumberOfBytesTransferred);
|
||||
|
@ -277,8 +279,62 @@ StopStreamingInSoundThread(
|
|||
IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
|
||||
IN PVOID Parameter)
|
||||
{
|
||||
/* TODO */
|
||||
return MMSYSERR_NOTSUPPORTED;
|
||||
MMDEVICE_TYPE DeviceType;
|
||||
PMMFUNCTION_TABLE FunctionTable;
|
||||
MMRESULT Result;
|
||||
PSOUND_DEVICE SoundDevice;
|
||||
|
||||
/* set state reset in progress */
|
||||
SoundDeviceInstance->ResetInProgress = TRUE;
|
||||
|
||||
/* Get sound device */
|
||||
Result = GetSoundDeviceFromInstance(SoundDeviceInstance, &SoundDevice);
|
||||
SND_ASSERT( Result == MMSYSERR_NOERROR );
|
||||
|
||||
/* Obtain the function table */
|
||||
Result = GetSoundDeviceFunctionTable(SoundDevice, &FunctionTable);
|
||||
SND_ASSERT( Result == MMSYSERR_NOERROR );
|
||||
|
||||
/* Obtain device instance type */
|
||||
Result = GetSoundDeviceType(SoundDevice, &DeviceType);
|
||||
SND_ASSERT( Result == MMSYSERR_NOERROR );
|
||||
|
||||
/* Check if reset function is supported */
|
||||
if (FunctionTable->ResetStream)
|
||||
{
|
||||
/* cancel all current audio buffers */
|
||||
FunctionTable->ResetStream(SoundDeviceInstance, DeviceType, TRUE);
|
||||
}
|
||||
|
||||
/* complete all current headers */
|
||||
while( SoundDeviceInstance->HeadWaveHeader )
|
||||
{
|
||||
SND_TRACE(L"StopStreamingInSoundThread: Completing Header %p\n", SoundDeviceInstance->HeadWaveHeader);
|
||||
CompleteWaveHeader( SoundDeviceInstance, SoundDeviceInstance->HeadWaveHeader );
|
||||
}
|
||||
|
||||
/* there should be no oustanding buffers now */
|
||||
SND_ASSERT(SoundDeviceInstance->OutstandingBuffers == 0);
|
||||
|
||||
while(SoundDeviceInstance->OutstandingBuffers)
|
||||
{
|
||||
SND_ERR("StopStreamingInSoundThread OutStandingBufferCount %lu\n", SoundDeviceInstance->OutstandingBuffers);
|
||||
/* my hack of doom */
|
||||
Sleep(10);
|
||||
}
|
||||
|
||||
/* Check if reset function is supported */
|
||||
if (FunctionTable->ResetStream)
|
||||
{
|
||||
/* finish the reset */
|
||||
FunctionTable->ResetStream(SoundDeviceInstance, DeviceType, FALSE);
|
||||
}
|
||||
|
||||
/* clear state reset in progress */
|
||||
SoundDeviceInstance->ResetInProgress = FALSE;
|
||||
|
||||
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
||||
MMRESULT
|
||||
|
|
|
@ -109,6 +109,13 @@ wodMessage(
|
|||
case WODM_RESTART :
|
||||
{
|
||||
/* Continue playback when paused */
|
||||
Result = MmeSetState(PrivateHandle, TRUE);
|
||||
break;
|
||||
}
|
||||
case WODM_PAUSE :
|
||||
{
|
||||
/* pause playback */
|
||||
Result = MmeSetState(PrivateHandle, FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
6
lib/drivers/sound/mmixer/TODO
Normal file
6
lib/drivers/sound/mmixer/TODO
Normal file
|
@ -0,0 +1,6 @@
|
|||
=== MMIXER TASKS ===
|
||||
|
||||
- Add hacks for source lines, such that Wave Mixer line always has a volume control
|
||||
- Support custom mixer controls
|
||||
- Assign mixer controls after all controls have been assigned (starting on the destination lines)
|
||||
- TESTING & BUGFIXING
|
File diff suppressed because it is too large
Load diff
|
@ -11,7 +11,7 @@
|
|||
MIXER_STATUS
|
||||
MMixerGetPinDataFlowAndCommunication(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
IN LPMIXER_DATA MixerData,
|
||||
IN HANDLE hDevice,
|
||||
IN ULONG PinId,
|
||||
OUT PKSPIN_DATAFLOW DataFlow,
|
||||
OUT PKSPIN_COMMUNICATION Communication)
|
||||
|
@ -28,7 +28,7 @@ MMixerGetPinDataFlowAndCommunication(
|
|||
Pin.Property.Set = KSPROPSETID_Pin;
|
||||
|
||||
/* get pin dataflow */
|
||||
Status = MixerContext->Control(MixerData->hDevice, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned);
|
||||
Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)DataFlow, sizeof(KSPIN_DATAFLOW), &BytesReturned);
|
||||
if (Status != MM_STATUS_SUCCESS)
|
||||
{
|
||||
/* failed to retrieve dataflow */
|
||||
|
@ -39,7 +39,7 @@ MMixerGetPinDataFlowAndCommunication(
|
|||
Pin.Property.Id = KSPROPERTY_PIN_COMMUNICATION;
|
||||
|
||||
/* get pin communication */
|
||||
Status = MixerContext->Control(MixerData->hDevice, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned);
|
||||
Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)Communication, sizeof(KSPIN_COMMUNICATION), &BytesReturned);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ MMixerCheckFilterPinMidiSupport(
|
|||
IsEqualGUIDAligned(&DataRange->Specifier, &KSDATAFORMAT_SPECIFIER_NONE))
|
||||
{
|
||||
/* pin supports midi datarange */
|
||||
if (MMixerGetPinDataFlowAndCommunication(MixerContext, MixerData, PinId, &DataFlow, &Communication) == MM_STATUS_SUCCESS)
|
||||
if (MMixerGetPinDataFlowAndCommunication(MixerContext, MixerData->hDevice, PinId, &DataFlow, &Communication) == MM_STATUS_SUCCESS)
|
||||
{
|
||||
if (DataFlow == KSPIN_DATAFLOW_IN && Communication == KSPIN_COMMUNICATION_SINK)
|
||||
{
|
||||
|
|
|
@ -89,6 +89,7 @@ MMixerOpen(
|
|||
if (Status != MM_STATUS_SUCCESS)
|
||||
{
|
||||
/* invalid context passed */
|
||||
DPRINT1("invalid context\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
@ -97,6 +98,7 @@ MMixerOpen(
|
|||
if (!MixerInfo)
|
||||
{
|
||||
/* invalid mixer id */
|
||||
DPRINT1("invalid mixer id %lu\n", MixerId);
|
||||
return MM_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
|
@ -106,20 +108,21 @@ MMixerOpen(
|
|||
|
||||
/* store result */
|
||||
*MixerHandle = (HANDLE)MixerInfo;
|
||||
|
||||
return MM_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
MIXER_STATUS
|
||||
MMixerGetLineInfo(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
IN HANDLE MixerHandle,
|
||||
IN ULONG Flags,
|
||||
IN HANDLE MixerHandle,
|
||||
IN ULONG MixerId,
|
||||
IN ULONG Flags,
|
||||
OUT LPMIXERLINEW MixerLine)
|
||||
{
|
||||
MIXER_STATUS Status;
|
||||
LPMIXER_INFO MixerInfo;
|
||||
LPMIXERLINE_EXT MixerLineSrc;
|
||||
ULONG DestinationLineID;
|
||||
|
||||
/* verify mixer context */
|
||||
Status = MMixerVerifyContext(MixerContext);
|
||||
|
@ -129,25 +132,54 @@ MMixerGetLineInfo(
|
|||
/* invalid context passed */
|
||||
return Status;
|
||||
}
|
||||
if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER)
|
||||
{
|
||||
/* caller passed mixer id */
|
||||
MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
|
||||
|
||||
if (!MixerHandle)
|
||||
{
|
||||
/* invalid parameter */
|
||||
return MM_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
if (MixerLine->cbStruct != sizeof(MIXERLINEW))
|
||||
{
|
||||
DPRINT1("MixerLine Expected %lu but got %lu\n", sizeof(MIXERLINEW), MixerLine->cbStruct);
|
||||
return MM_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* clear hmixer from flags */
|
||||
Flags &=~MIXER_OBJECTF_HMIXER;
|
||||
|
||||
DPRINT("MMixerGetLineInfo MixerId %lu Flags %lu\n", MixerId, Flags);
|
||||
|
||||
if (Flags == MIXER_GETLINEINFOF_DESTINATION)
|
||||
{
|
||||
/* cast to mixer info */
|
||||
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
||||
|
||||
if (MixerLine->dwDestination != 0)
|
||||
{
|
||||
/* destination line member must be zero */
|
||||
return MM_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
/* calculate destination line id */
|
||||
DestinationLineID = (MixerLine->dwDestination + DESTINATION_LINE);
|
||||
|
||||
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE);
|
||||
ASSERT(MixerLineSrc);
|
||||
/* get destination line */
|
||||
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
|
||||
|
||||
if (MixerLineSrc == NULL)
|
||||
{
|
||||
DPRINT1("MixerCaps Name %S DestinationLineCount %lu dwDestination %lu not found\n", MixerInfo->MixCaps.szPname, MixerInfo->MixCaps.cDestinations, MixerLine->dwDestination);
|
||||
return MM_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
/* copy mixer line */
|
||||
MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
|
||||
|
||||
/* make sure it is null terminated */
|
||||
MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
|
||||
MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
|
||||
MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0';
|
||||
|
||||
/* done */
|
||||
return MM_STATUS_SUCCESS;
|
||||
}
|
||||
else if (Flags == MIXER_GETLINEINFOF_SOURCE)
|
||||
|
@ -155,41 +187,75 @@ MMixerGetLineInfo(
|
|||
/* cast to mixer info */
|
||||
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
||||
|
||||
/* calculate destination line id */
|
||||
DestinationLineID = (MixerLine->dwDestination + DESTINATION_LINE);
|
||||
|
||||
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE);
|
||||
ASSERT(MixerLineSrc);
|
||||
/* get destination line */
|
||||
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
|
||||
|
||||
if (MixerLineSrc == NULL)
|
||||
{
|
||||
DPRINT1("MixerCaps Name %S DestinationLineCount %lu dwDestination %lu not found\n", MixerInfo->MixCaps.szPname, MixerInfo->MixCaps.cDestinations, MixerLine->dwDestination);
|
||||
return MM_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* check if dwSource is out of bounds */
|
||||
if (MixerLine->dwSource >= MixerLineSrc->Line.cConnections)
|
||||
{
|
||||
DPRINT("dwSource %u > Destinations %u\n", MixerLine->dwSource, MixerLineSrc->Line.cConnections);
|
||||
|
||||
/* invalid parameter */
|
||||
return MM_STATUS_INVALID_PARAMETER;
|
||||
DPRINT1("MixerCaps Name %S MixerLineName %S Connections %lu dwSource %lu not found\n", MixerInfo->MixCaps.szPname, MixerLineSrc->Line.szName, MixerLineSrc->Line.cConnections, MixerLine->dwSource);
|
||||
return MM_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLine->dwSource * 0x10000);
|
||||
if (MixerLineSrc)
|
||||
{
|
||||
DPRINT("Line %u Name %S\n", MixerLineSrc->Line.dwSource, MixerLineSrc->Line.szName);
|
||||
MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
|
||||
return MM_STATUS_SUCCESS;
|
||||
}
|
||||
return MM_STATUS_UNSUCCESSFUL;
|
||||
/* calculate destination line id */
|
||||
DestinationLineID = (MixerLine->dwSource * SOURCE_LINE) + MixerLine->dwDestination;
|
||||
|
||||
DPRINT("MixerName %S cDestinations %lu MixerLineName %S cConnections %lu dwSource %lu dwDestination %lu ID %lx\n", MixerInfo->MixCaps.szPname, MixerInfo->MixCaps.cDestinations,
|
||||
MixerLineSrc->Line.szName, MixerLineSrc->Line.cConnections,
|
||||
MixerLine->dwSource, MixerLine->dwDestination,
|
||||
DestinationLineID);
|
||||
/* get target destination line id */
|
||||
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
|
||||
|
||||
/* sanity check */
|
||||
ASSERT(MixerLineSrc);
|
||||
|
||||
DPRINT("Line %u Name %S\n", MixerLineSrc->Line.dwSource, MixerLineSrc->Line.szName);
|
||||
|
||||
/* copy mixer line */
|
||||
MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
|
||||
|
||||
/* make sure it is null terminated */
|
||||
MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
|
||||
MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
|
||||
MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0';
|
||||
|
||||
/* done */
|
||||
return MM_STATUS_SUCCESS;
|
||||
}
|
||||
else if (Flags == MIXER_GETLINEINFOF_LINEID)
|
||||
{
|
||||
/* cast to mixer info */
|
||||
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
||||
|
||||
/* try to find line */
|
||||
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLine->dwLineID);
|
||||
if (!MixerLineSrc)
|
||||
{
|
||||
/* invalid parameter */
|
||||
DPRINT1("MMixerGetLineInfo: MixerName %S Line not found 0x%lx\n", MixerInfo->MixCaps.szPname, MixerLine->dwLineID);
|
||||
return MM_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* copy cached data */
|
||||
DPRINT("Line %u Name %S\n", MixerLineSrc->Line.dwSource, MixerLineSrc->Line.szName);
|
||||
|
||||
/* copy mixer line*/
|
||||
MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
|
||||
|
||||
/* make sure it is null terminated */
|
||||
MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
|
||||
MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
|
||||
MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0';
|
||||
|
||||
return MM_STATUS_SUCCESS;
|
||||
}
|
||||
else if (Flags == MIXER_GETLINEINFOF_COMPONENTTYPE)
|
||||
|
@ -197,6 +263,7 @@ MMixerGetLineInfo(
|
|||
/* cast to mixer info */
|
||||
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
||||
|
||||
/* find mixer line by component type */
|
||||
MixerLineSrc = MMixerGetSourceMixerLineByComponentType(MixerInfo, MixerLine->dwComponentType);
|
||||
if (!MixerLineSrc)
|
||||
{
|
||||
|
@ -204,12 +271,25 @@ MMixerGetLineInfo(
|
|||
return MM_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
ASSERT(MixerLineSrc);
|
||||
|
||||
/* copy cached data */
|
||||
/* copy mixer line */
|
||||
MixerContext->Copy(MixerLine, &MixerLineSrc->Line, sizeof(MIXERLINEW));
|
||||
|
||||
/* make sure it is null terminated */
|
||||
MixerLine->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
|
||||
MixerLine->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
|
||||
MixerLine->Target.szPname[MAXPNAMELEN-1] = L'\0';
|
||||
|
||||
/* done */
|
||||
return MM_STATUS_SUCCESS;
|
||||
}
|
||||
else if (Flags == MIXER_GETLINEINFOF_TARGETTYPE)
|
||||
{
|
||||
DPRINT1("MIXER_GETLINEINFOF_TARGETTYPE handling is unimplemented\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("Unknown Flags %lx handling is unimplemented\n", Flags);
|
||||
}
|
||||
|
||||
return MM_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
@ -218,13 +298,15 @@ MIXER_STATUS
|
|||
MMixerGetLineControls(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
IN HANDLE MixerHandle,
|
||||
IN ULONG MixerId,
|
||||
IN ULONG Flags,
|
||||
OUT LPMIXERLINECONTROLSW MixerLineControls)
|
||||
{
|
||||
LPMIXER_INFO MixerInfo;
|
||||
LPMIXERLINE_EXT MixerLineSrc;
|
||||
LPMIXERCONTROLW MixerControl;
|
||||
LPMIXERCONTROL_EXT MixerControl;
|
||||
MIXER_STATUS Status;
|
||||
PLIST_ENTRY Entry;
|
||||
ULONG Index;
|
||||
|
||||
/* verify mixer context */
|
||||
|
@ -236,23 +318,75 @@ MMixerGetLineControls(
|
|||
return Status;
|
||||
}
|
||||
|
||||
if (MixerLineControls->cbStruct != sizeof(MIXERLINECONTROLSW))
|
||||
{
|
||||
DPRINT1("Invalid MixerLineControls cbStruct passed %lu expected %lu\n", MixerLineControls->cbStruct, sizeof(MIXERLINECONTROLSW));
|
||||
/* invalid parameter */
|
||||
return MM_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (MixerLineControls->cbmxctrl != sizeof(MIXERCONTROLW))
|
||||
{
|
||||
DPRINT1("Invalid MixerLineControls cbmxctrl passed %lu expected %lu\n", MixerLineControls->cbStruct, sizeof(MIXERLINECONTROLSW));
|
||||
/* invalid parameter */
|
||||
return MM_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER)
|
||||
{
|
||||
/* caller passed mixer id */
|
||||
MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
|
||||
|
||||
if (!MixerHandle)
|
||||
{
|
||||
/* invalid parameter */
|
||||
return MM_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
Flags &= ~MIXER_OBJECTF_HMIXER;
|
||||
|
||||
DPRINT("MMixerGetLineControls MixerId %lu Flags %lu\n", MixerId, Flags);
|
||||
|
||||
if (Flags == MIXER_GETLINECONTROLSF_ALL)
|
||||
{
|
||||
/* cast to mixer info */
|
||||
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
||||
|
||||
/* get mixer line */
|
||||
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID);
|
||||
|
||||
if (!MixerLineSrc)
|
||||
{
|
||||
/* invalid line id */
|
||||
DPRINT("MMixerGetLineControls Line not found %lx\n", MixerLineControls->dwLineID);
|
||||
return MM_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
/* copy line control(s) */
|
||||
MixerContext->Copy(MixerLineControls->pamxctrl, MixerLineSrc->LineControls, min(MixerLineSrc->Line.cControls, MixerLineControls->cControls) * sizeof(MIXERCONTROLW));
|
||||
|
||||
if (MixerLineSrc->Line.cControls != MixerLineControls->cControls)
|
||||
{
|
||||
/* invalid parameter */
|
||||
DPRINT1("Invalid control count %lu expected %lu\n", MixerLineControls->cControls, MixerLineSrc->Line.cControls);
|
||||
return MM_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* copy line control(s) */
|
||||
Entry = MixerLineSrc->ControlsList.Flink;
|
||||
Index = 0;
|
||||
while(Entry != &MixerLineSrc->ControlsList)
|
||||
{
|
||||
/* get mixer control */
|
||||
MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(Entry, MIXERCONTROL_EXT, Entry);
|
||||
|
||||
/* copy mixer control */
|
||||
MixerContext->Copy(&MixerLineControls->pamxctrl[Index], &MixerControl->Control, sizeof(MIXERCONTROLW));
|
||||
|
||||
/* move to next */
|
||||
Entry = Entry->Flink;
|
||||
|
||||
/* increment mixer control offset */
|
||||
Index++;
|
||||
}
|
||||
return MM_STATUS_SUCCESS;
|
||||
}
|
||||
else if (Flags == MIXER_GETLINECONTROLSF_ONEBYTYPE)
|
||||
|
@ -260,29 +394,38 @@ MMixerGetLineControls(
|
|||
/* cast to mixer info */
|
||||
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
||||
|
||||
/* get mixer line */
|
||||
MixerLineSrc = MMixerGetSourceMixerLineByLineId(MixerInfo, MixerLineControls->dwLineID);
|
||||
|
||||
if (!MixerLineSrc)
|
||||
{
|
||||
/* invalid line id */
|
||||
DPRINT1("MMixerGetLineControls Line not found %lx\n", MixerLineControls->dwLineID);
|
||||
return MM_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ASSERT(MixerLineSrc);
|
||||
/* sanity checks */
|
||||
ASSERT(MixerLineControls->cControls == 1);
|
||||
ASSERT(MixerLineControls->cbmxctrl == sizeof(MIXERCONTROLW));
|
||||
ASSERT(MixerLineControls->pamxctrl != NULL);
|
||||
|
||||
Index = 0;
|
||||
for(Index = 0; Index < MixerLineSrc->Line.cControls; Index++)
|
||||
Entry = MixerLineSrc->ControlsList.Flink;
|
||||
while(Entry != &MixerLineSrc->ControlsList)
|
||||
{
|
||||
DPRINT("dwControlType %x\n", MixerLineSrc->LineControls[Index].dwControlType);
|
||||
if (MixerLineControls->dwControlType == MixerLineSrc->LineControls[Index].dwControlType)
|
||||
MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(Entry, MIXERCONTROL_EXT, Entry);
|
||||
if (MixerLineControls->dwControlType == MixerControl->Control.dwControlType)
|
||||
{
|
||||
/* found a control with that type */
|
||||
MixerContext->Copy(MixerLineControls->pamxctrl, &MixerLineSrc->LineControls[Index], sizeof(MIXERCONTROLW));
|
||||
MixerContext->Copy(MixerLineControls->pamxctrl, &MixerControl->Control, sizeof(MIXERCONTROLW));
|
||||
return MM_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
DPRINT("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x cControls %u \n", MixerLineControls->dwControlType, MixerLineControls->dwLineID, MixerLineSrc->Line.cControls);
|
||||
return MM_STATUS_UNSUCCESSFUL;
|
||||
|
||||
/* move to next entry */
|
||||
Entry = Entry->Flink;
|
||||
}
|
||||
|
||||
DPRINT("DeviceInfo->u.MixControls.dwControlType %x not found in Line %x cControls %u \n", MixerLineControls->dwControlType, MixerLineControls->dwLineID, MixerLineSrc->Line.cControls);
|
||||
return MM_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
else if (Flags == MIXER_GETLINECONTROLSF_ONEBYID)
|
||||
{
|
||||
|
@ -294,15 +437,24 @@ MMixerGetLineControls(
|
|||
if (Status != MM_STATUS_SUCCESS)
|
||||
{
|
||||
/* invalid parameter */
|
||||
DPRINT("MMixerGetLineControls ControlID not found %lx\n", MixerLineControls->dwLineID);
|
||||
return MM_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
ASSERT(MixerLineControls->cControls == 1);
|
||||
ASSERT(MixerLineControls->cbmxctrl == sizeof(MIXERCONTROLW));
|
||||
ASSERT(MixerLineControls->pamxctrl != NULL);
|
||||
|
||||
DPRINT("MMixerGetLineControls ControlID %lx ControlType %lx Name %S\n", MixerControl->Control.dwControlID, MixerControl->Control.dwControlType, MixerControl->Control.szName);
|
||||
|
||||
/* copy the controls */
|
||||
MixerContext->Copy(MixerLineControls->pamxctrl, MixerControl, sizeof(MIXERCONTROLW));
|
||||
MixerContext->Copy(MixerLineControls->pamxctrl, &MixerControl->Control, sizeof(MIXERCONTROLW));
|
||||
MixerLineControls->pamxctrl->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
|
||||
MixerLineControls->pamxctrl->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
|
||||
|
||||
return MM_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
UNIMPLEMENTED
|
||||
return MM_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
|
@ -310,6 +462,7 @@ MIXER_STATUS
|
|||
MMixerSetControlDetails(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
IN HANDLE MixerHandle,
|
||||
IN ULONG MixerId,
|
||||
IN ULONG Flags,
|
||||
OUT LPMIXERCONTROLDETAILS MixerControlDetails)
|
||||
{
|
||||
|
@ -317,7 +470,7 @@ MMixerSetControlDetails(
|
|||
ULONG NodeId;
|
||||
LPMIXER_INFO MixerInfo;
|
||||
LPMIXERLINE_EXT MixerLine;
|
||||
LPMIXERCONTROLW MixerControl;
|
||||
LPMIXERCONTROL_EXT MixerControl;
|
||||
|
||||
/* verify mixer context */
|
||||
Status = MMixerVerifyContext(MixerContext);
|
||||
|
@ -325,9 +478,23 @@ MMixerSetControlDetails(
|
|||
if (Status != MM_STATUS_SUCCESS)
|
||||
{
|
||||
/* invalid context passed */
|
||||
DPRINT1("invalid context\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER)
|
||||
{
|
||||
/* caller passed mixer id */
|
||||
MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
|
||||
|
||||
if (!MixerHandle)
|
||||
{
|
||||
/* invalid parameter */
|
||||
DPRINT1("invalid handle\n");
|
||||
return MM_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
/* get mixer info */
|
||||
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
||||
|
||||
|
@ -338,16 +505,21 @@ MMixerSetControlDetails(
|
|||
if (Status != MM_STATUS_SUCCESS)
|
||||
{
|
||||
/* failed to find control id */
|
||||
DPRINT1("invalid control id %lu\n", MixerControlDetails->dwControlID);
|
||||
return MM_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
switch(MixerControl->dwControlType)
|
||||
DPRINT("MMixerSetControlDetails ControlType %lx MixerControlName %S MixerLineName %S NodeID %lu\n", MixerControl->Control.dwControlType, MixerControl->Control.szName, MixerLine->Line.szName, NodeId);
|
||||
switch(MixerControl->Control.dwControlType)
|
||||
{
|
||||
case MIXERCONTROL_CONTROLTYPE_MUTE:
|
||||
Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo->hMixer, NodeId, MixerLine->Line.dwLineID, MixerControlDetails, TRUE);
|
||||
Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo, MixerControl, MixerLine->Line.dwLineID, MixerControlDetails, TRUE);
|
||||
break;
|
||||
case MIXERCONTROL_CONTROLTYPE_VOLUME:
|
||||
Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo->hMixer, NodeId, TRUE, MixerControl, MixerControlDetails, MixerLine);
|
||||
Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo, NodeId, TRUE, MixerControl, MixerControlDetails, MixerLine);
|
||||
break;
|
||||
case MIXERCONTROL_CONTROLTYPE_MUX:
|
||||
Status = MMixerSetGetMuxControlDetails(MixerContext, MixerInfo, NodeId, TRUE, Flags, MixerControl, MixerControlDetails, MixerLine);
|
||||
break;
|
||||
default:
|
||||
Status = MM_STATUS_NOT_IMPLEMENTED;
|
||||
|
@ -360,6 +532,7 @@ MIXER_STATUS
|
|||
MMixerGetControlDetails(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
IN HANDLE MixerHandle,
|
||||
IN ULONG MixerId,
|
||||
IN ULONG Flags,
|
||||
OUT LPMIXERCONTROLDETAILS MixerControlDetails)
|
||||
{
|
||||
|
@ -367,7 +540,7 @@ MMixerGetControlDetails(
|
|||
ULONG NodeId;
|
||||
LPMIXER_INFO MixerInfo;
|
||||
LPMIXERLINE_EXT MixerLine;
|
||||
LPMIXERCONTROLW MixerControl;
|
||||
LPMIXERCONTROL_EXT MixerControl;
|
||||
|
||||
/* verify mixer context */
|
||||
Status = MMixerVerifyContext(MixerContext);
|
||||
|
@ -378,6 +551,18 @@ MMixerGetControlDetails(
|
|||
return Status;
|
||||
}
|
||||
|
||||
if ((Flags & (MIXER_OBJECTF_MIXER | MIXER_OBJECTF_HMIXER)) == MIXER_OBJECTF_MIXER)
|
||||
{
|
||||
/* caller passed mixer id */
|
||||
MixerHandle = (HANDLE)MMixerGetMixerInfoByIndex(MixerContext, MixerId);
|
||||
|
||||
if (!MixerHandle)
|
||||
{
|
||||
/* invalid parameter */
|
||||
return MM_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
/* get mixer info */
|
||||
MixerInfo = (LPMIXER_INFO)MixerHandle;
|
||||
|
||||
|
@ -391,21 +576,162 @@ MMixerGetControlDetails(
|
|||
return MM_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
switch(MixerControl->dwControlType)
|
||||
switch(MixerControl->Control.dwControlType)
|
||||
{
|
||||
case MIXERCONTROL_CONTROLTYPE_MUTE:
|
||||
Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo, NodeId, MixerLine->Line.dwLineID, MixerControlDetails, FALSE);
|
||||
Status = MMixerSetGetMuteControlDetails(MixerContext, MixerInfo, MixerControl, MixerLine->Line.dwLineID, MixerControlDetails, FALSE);
|
||||
break;
|
||||
case MIXERCONTROL_CONTROLTYPE_VOLUME:
|
||||
Status = MMixerSetGetVolumeControlDetails(MixerContext, MixerInfo, NodeId, FALSE, MixerControl, MixerControlDetails, MixerLine);
|
||||
break;
|
||||
case MIXERCONTROL_CONTROLTYPE_ONOFF:
|
||||
DPRINT1("Not Implemented MIXERCONTROL_CONTROLTYPE_ONOFF\n");
|
||||
break;
|
||||
case MIXERCONTROL_CONTROLTYPE_MUX:
|
||||
Status = MMixerSetGetMuxControlDetails(MixerContext, MixerInfo, NodeId, FALSE, Flags, MixerControl, MixerControlDetails, MixerLine);
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = MM_STATUS_NOT_IMPLEMENTED;
|
||||
DPRINT1("ControlType %lx not implemented\n", MixerControl->Control.dwControlType);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
VOID
|
||||
MMixerPrintMixerLineControls(
|
||||
IN LPMIXERLINE_EXT MixerLine)
|
||||
{
|
||||
PLIST_ENTRY Entry;
|
||||
LPMIXERCONTROL_EXT MixerControl;
|
||||
ULONG Index = 0;
|
||||
|
||||
Entry = MixerLine->ControlsList.Flink;
|
||||
while(Entry != &MixerLine->ControlsList)
|
||||
{
|
||||
MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(Entry, MIXERCONTROL_EXT, Entry);
|
||||
|
||||
DPRINT1("\n");
|
||||
DPRINT1("Control Index: %lu\n", Index);
|
||||
DPRINT("\n");
|
||||
DPRINT1("cbStruct %u\n", MixerControl->Control.cbStruct);
|
||||
DPRINT1("dwControlID %lu\n", MixerControl->Control.dwControlID);
|
||||
DPRINT1("dwControlType %lx\n", MixerControl->Control.dwControlType);
|
||||
DPRINT1("fdwControl %lu\n", MixerControl->Control.fdwControl);
|
||||
DPRINT1("cMultipleItems %lu\n", MixerControl->Control.cMultipleItems);
|
||||
DPRINT1("szShortName %S\n", MixerControl->Control.szShortName);
|
||||
DPRINT1("szName %S\n", MixerControl->Control.szName);
|
||||
DPRINT1("Bounds.dwMinimum %lu\n", MixerControl->Control.Bounds.dwMinimum);
|
||||
DPRINT1("Bounds.dwMaximum %lu\n", MixerControl->Control.Bounds.dwMaximum);
|
||||
|
||||
DPRINT1("Metrics.Reserved[0] %lu\n", MixerControl->Control.Metrics.dwReserved[0]);
|
||||
DPRINT1("Metrics.Reserved[1] %lu\n", MixerControl->Control.Metrics.dwReserved[1]);
|
||||
DPRINT1("Metrics.Reserved[2] %lu\n", MixerControl->Control.Metrics.dwReserved[2]);
|
||||
DPRINT1("Metrics.Reserved[3] %lu\n", MixerControl->Control.Metrics.dwReserved[3]);
|
||||
DPRINT1("Metrics.Reserved[4] %lu\n", MixerControl->Control.Metrics.dwReserved[4]);
|
||||
DPRINT1("Metrics.Reserved[5] %lu\n", MixerControl->Control.Metrics.dwReserved[5]);
|
||||
|
||||
Entry = Entry->Flink;
|
||||
Index++;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
MMixerPrintMixers(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
IN PMIXER_LIST MixerList)
|
||||
{
|
||||
ULONG Index, SubIndex, DestinationLineID, SrcIndex;
|
||||
LPMIXER_INFO MixerInfo;
|
||||
LPMIXERLINE_EXT DstMixerLine, SrcMixerLine;
|
||||
|
||||
DPRINT1("MixerList %p\n", MixerList);
|
||||
DPRINT1("MidiInCount %lu\n", MixerList->MidiInListCount);
|
||||
DPRINT1("MidiOutCount %lu\n", MixerList->MidiOutListCount);
|
||||
DPRINT1("WaveInCount %lu\n", MixerList->WaveInListCount);
|
||||
DPRINT1("WaveOutCount %lu\n", MixerList->WaveOutListCount);
|
||||
DPRINT1("MixerCount %p\n", MixerList->MixerListCount);
|
||||
|
||||
|
||||
for(Index = 0; Index < MixerList->MixerListCount; Index++)
|
||||
{
|
||||
/* get mixer info */
|
||||
MixerInfo = MMixerGetMixerInfoByIndex(MixerContext, Index);
|
||||
|
||||
ASSERT(MixerInfo);
|
||||
DPRINT1("\n");
|
||||
DPRINT1("Name :%S\n", MixerInfo->MixCaps.szPname);
|
||||
DPRINT1("cDestinations: %lu\n", MixerInfo->MixCaps.cDestinations);
|
||||
DPRINT1("fdwSupport %lu\n", MixerInfo->MixCaps.fdwSupport);
|
||||
DPRINT1("vDriverVersion %lx\n", MixerInfo->MixCaps.vDriverVersion);
|
||||
DPRINT1("wMid %lx\n", MixerInfo->MixCaps.wMid);
|
||||
DPRINT1("wPid %lx\n", MixerInfo->MixCaps.wPid);
|
||||
|
||||
for(SubIndex = 0; SubIndex < MixerInfo->MixCaps.cDestinations; SubIndex++)
|
||||
{
|
||||
/* calculate destination line id */
|
||||
DestinationLineID = (SubIndex + DESTINATION_LINE);
|
||||
|
||||
/* get destination line */
|
||||
DstMixerLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
|
||||
DPRINT1("//----------------------------------------------------------------------------------------------\n");
|
||||
DPRINT1("\n");
|
||||
DPRINT1("Destination Index %lu\n", SubIndex);
|
||||
DPRINT1("\n");
|
||||
DPRINT1("cChannels %lu\n", DstMixerLine->Line.cChannels);
|
||||
DPRINT1("cConnections %lu\n", DstMixerLine->Line.cConnections);
|
||||
DPRINT1("cControls %lu\n", DstMixerLine->Line.cControls);
|
||||
DPRINT1("dwComponentType %lx\n", DstMixerLine->Line.dwComponentType);
|
||||
DPRINT1("dwDestination %lu\n", DstMixerLine->Line.dwDestination);
|
||||
DPRINT1("dwLineID %lx\n", DstMixerLine->Line.dwLineID);
|
||||
DPRINT1("dwSource %lx\n", DstMixerLine->Line.dwSource);
|
||||
DPRINT1("dwUser %lu\n", DstMixerLine->Line.dwUser);
|
||||
DPRINT1("fdwLine %lu\n", DstMixerLine->Line.fdwLine);
|
||||
DPRINT1("szName %S\n", DstMixerLine->Line.szName);
|
||||
DPRINT1("szShortName %S\n", DstMixerLine->Line.szShortName);
|
||||
DPRINT1("Target.dwDeviceId %lu\n", DstMixerLine->Line.Target.dwDeviceID);
|
||||
DPRINT1("Target.dwType %lu\n", DstMixerLine->Line.Target.dwType);
|
||||
DPRINT1("Target.szName %S\n", DstMixerLine->Line.Target.szPname);
|
||||
DPRINT1("Target.vDriverVersion %lx\n", DstMixerLine->Line.Target.vDriverVersion);
|
||||
DPRINT1("Target.wMid %lx\n", DstMixerLine->Line.Target.wMid );
|
||||
DPRINT1("Target.wPid %lx\n", DstMixerLine->Line.Target.wPid);
|
||||
MMixerPrintMixerLineControls(DstMixerLine);
|
||||
|
||||
for(SrcIndex = 0; SrcIndex < DstMixerLine->Line.cConnections; SrcIndex++)
|
||||
{
|
||||
/* calculate destination line id */
|
||||
DestinationLineID = (SOURCE_LINE * SrcIndex) + SubIndex;
|
||||
|
||||
/* get source line */
|
||||
SrcMixerLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
|
||||
DPRINT1("//==============================================================================================\n");
|
||||
DPRINT1("\n");
|
||||
DPRINT1("SrcLineIndex : %lu\n", SrcIndex);
|
||||
DPRINT1("\n");
|
||||
DPRINT1("cChannels %lu\n", SrcMixerLine->Line.cChannels);
|
||||
DPRINT1("cConnections %lu\n", SrcMixerLine->Line.cConnections);
|
||||
DPRINT1("cControls %lu\n", SrcMixerLine->Line.cControls);
|
||||
DPRINT1("dwComponentType %lx\n", SrcMixerLine->Line.dwComponentType);
|
||||
DPRINT1("dwDestination %lu\n", SrcMixerLine->Line.dwDestination);
|
||||
DPRINT1("dwLineID %lx\n", SrcMixerLine->Line.dwLineID);
|
||||
DPRINT1("dwSource %lx\n", SrcMixerLine->Line.dwSource);
|
||||
DPRINT1("dwUser %lu\n", SrcMixerLine->Line.dwUser);
|
||||
DPRINT1("fdwLine %lu\n", SrcMixerLine->Line.fdwLine);
|
||||
DPRINT1("szName %S\n", SrcMixerLine->Line.szName);
|
||||
DPRINT1("szShortName %S\n", SrcMixerLine->Line.szShortName);
|
||||
DPRINT1("Target.dwDeviceId %lu\n", SrcMixerLine->Line.Target.dwDeviceID);
|
||||
DPRINT1("Target.dwType %lu\n", SrcMixerLine->Line.Target.dwType);
|
||||
DPRINT1("Target.szName %S\n", SrcMixerLine->Line.Target.szPname);
|
||||
DPRINT1("Target.vDriverVersion %lx\n", SrcMixerLine->Line.Target.vDriverVersion);
|
||||
DPRINT1("Target.wMid %lx\n", SrcMixerLine->Line.Target.wMid );
|
||||
DPRINT1("Target.wPid %lx\n", SrcMixerLine->Line.Target.wPid);
|
||||
MMixerPrintMixerLineControls(SrcMixerLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MIXER_STATUS
|
||||
MMixerInitialize(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
|
@ -507,6 +833,18 @@ MMixerInitialize(
|
|||
Entry = Entry->Flink;
|
||||
}
|
||||
|
||||
Entry = MixerList->MixerData.Flink;
|
||||
while(Entry != &MixerList->MixerData)
|
||||
{
|
||||
MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry);
|
||||
|
||||
/* now handle alternative mixer types */
|
||||
MMixerHandleAlternativeMixers(MixerContext, MixerList, MixerData, MixerData->Topology);
|
||||
Entry = Entry->Flink;
|
||||
}
|
||||
|
||||
//MMixerPrintMixers(MixerContext, MixerList);
|
||||
|
||||
/* done */
|
||||
return MM_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ typedef MIXER_STATUS(*PMIXER_CLOSE)(
|
|||
typedef MIXER_STATUS(*PMIXER_CLOSEKEY)(
|
||||
IN HANDLE hKey);
|
||||
|
||||
typedef VOID (*PMIXER_EVENT)(
|
||||
typedef VOID (CALLBACK *PMIXER_EVENT)(
|
||||
IN PVOID MixerEventContext,
|
||||
IN HANDLE hMixer,
|
||||
IN ULONG NotificationType,
|
||||
|
@ -149,7 +149,8 @@ MMixerOpen(
|
|||
MIXER_STATUS
|
||||
MMixerGetLineInfo(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
IN HANDLE MixerHandle,
|
||||
IN HANDLE MixerHandle,
|
||||
IN ULONG MixerId,
|
||||
IN ULONG Flags,
|
||||
OUT LPMIXERLINEW MixerLine);
|
||||
|
||||
|
@ -157,6 +158,7 @@ MIXER_STATUS
|
|||
MMixerGetLineControls(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
IN HANDLE MixerHandle,
|
||||
IN ULONG MixerId,
|
||||
IN ULONG Flags,
|
||||
OUT LPMIXERLINECONTROLSW MixerLineControls);
|
||||
|
||||
|
@ -164,6 +166,7 @@ MIXER_STATUS
|
|||
MMixerSetControlDetails(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
IN HANDLE MixerHandle,
|
||||
IN ULONG MixerId,
|
||||
IN ULONG Flags,
|
||||
OUT LPMIXERCONTROLDETAILS MixerControlDetails);
|
||||
|
||||
|
@ -171,6 +174,7 @@ MIXER_STATUS
|
|||
MMixerGetControlDetails(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
IN HANDLE MixerHandle,
|
||||
IN ULONG MixerId,
|
||||
IN ULONG Flags,
|
||||
OUT LPMIXERCONTROLDETAILS MixerControlDetails);
|
||||
|
||||
|
@ -202,6 +206,12 @@ MMixerSetWaveStatus(
|
|||
IN HANDLE PinHandle,
|
||||
IN KSSTATE State);
|
||||
|
||||
MIXER_STATUS
|
||||
MMixerSetWaveResetState(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
IN HANDLE PinHandle,
|
||||
IN ULONG bBegin);
|
||||
|
||||
MIXER_STATUS
|
||||
MMixerGetWaveDevicePath(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
|
|
|
@ -27,6 +27,7 @@ typedef struct __TOPOLOGY_NODE__
|
|||
|
||||
ULONG NodeConnectedFromCount;
|
||||
struct __TOPOLOGY_NODE__ ** NodeConnectedFrom;
|
||||
PULONG LogicalPinNodeConnectedFrom;
|
||||
|
||||
ULONG PinConnectedFromCount;
|
||||
PULONG PinConnectedFrom;
|
||||
|
@ -55,6 +56,7 @@ typedef struct
|
|||
PULONG PinConnectedTo;
|
||||
|
||||
ULONG Visited;
|
||||
ULONG Reserved;
|
||||
}PIN, *PPIN;
|
||||
|
||||
|
||||
|
@ -72,7 +74,6 @@ typedef struct
|
|||
{
|
||||
LIST_ENTRY Entry;
|
||||
MIXERCAPSW MixCaps;
|
||||
HANDLE hMixer;
|
||||
LIST_ENTRY LineList;
|
||||
ULONG ControlId;
|
||||
LIST_ENTRY EventList;
|
||||
|
@ -81,12 +82,19 @@ typedef struct
|
|||
typedef struct
|
||||
{
|
||||
LIST_ENTRY Entry;
|
||||
ULONG PinId;
|
||||
MIXERCONTROLW Control;
|
||||
ULONG NodeID;
|
||||
HANDLE hDevice;
|
||||
PVOID ExtraData;
|
||||
}MIXERCONTROL_EXT, *LPMIXERCONTROL_EXT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
LIST_ENTRY Entry;
|
||||
ULONG PinId;
|
||||
MIXERLINEW Line;
|
||||
LPMIXERCONTROLW LineControls;
|
||||
PULONG NodeIds;
|
||||
LIST_ENTRY LineControlsExtraData;
|
||||
LIST_ENTRY ControlsList;
|
||||
|
||||
}MIXERLINE_EXT, *LPMIXERLINE_EXT;
|
||||
|
||||
typedef struct
|
||||
|
@ -114,6 +122,7 @@ typedef struct
|
|||
HANDLE hDeviceInterfaceKey;
|
||||
LPWSTR DeviceName;
|
||||
PTOPOLOGY Topology;
|
||||
LPMIXER_INFO MixerInfo;
|
||||
}MIXER_DATA, *LPMIXER_DATA;
|
||||
|
||||
typedef struct
|
||||
|
@ -170,8 +179,8 @@ typedef struct
|
|||
|
||||
}EVENT_NOTIFICATION_ENTRY, *PEVENT_NOTIFICATION_ENTRY;
|
||||
|
||||
#define DESTINATION_LINE 0xFFFF0000
|
||||
|
||||
#define DESTINATION_LINE (0xFFFF0000)
|
||||
#define SOURCE_LINE (0x10000)
|
||||
ULONG
|
||||
MMixerGetFilterPinCount(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
|
@ -270,14 +279,14 @@ MMixerGetMixerControlById(
|
|||
LPMIXER_INFO MixerInfo,
|
||||
DWORD dwControlID,
|
||||
LPMIXERLINE_EXT *MixerLine,
|
||||
LPMIXERCONTROLW *MixerControl,
|
||||
LPMIXERCONTROL_EXT *MixerControl,
|
||||
PULONG NodeId);
|
||||
|
||||
MIXER_STATUS
|
||||
MMixerSetGetMuteControlDetails(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
IN LPMIXER_INFO MixerInfo,
|
||||
IN ULONG NodeId,
|
||||
IN LPMIXERCONTROL_EXT MixerControl,
|
||||
IN ULONG dwLineID,
|
||||
IN LPMIXERCONTROLDETAILS MixerControlDetails,
|
||||
IN ULONG bSet);
|
||||
|
@ -288,10 +297,22 @@ MMixerSetGetVolumeControlDetails(
|
|||
IN LPMIXER_INFO MixerInfo,
|
||||
IN ULONG NodeId,
|
||||
IN ULONG bSet,
|
||||
LPMIXERCONTROLW MixerControl,
|
||||
LPMIXERCONTROL_EXT MixerControl,
|
||||
IN LPMIXERCONTROLDETAILS MixerControlDetails,
|
||||
LPMIXERLINE_EXT MixerLine);
|
||||
|
||||
MIXER_STATUS
|
||||
MMixerSetGetMuxControlDetails(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
IN LPMIXER_INFO MixerInfo,
|
||||
IN ULONG NodeId,
|
||||
IN ULONG bSet,
|
||||
IN ULONG Flags,
|
||||
LPMIXERCONTROL_EXT MixerControl,
|
||||
IN LPMIXERCONTROLDETAILS MixerControlDetails,
|
||||
LPMIXERLINE_EXT MixerLine);
|
||||
|
||||
|
||||
MIXER_STATUS
|
||||
MMixerSetGetControlDetails(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
|
@ -349,6 +370,26 @@ MMixerInitializePinConnect(
|
|||
IN OUT PKSPIN_CONNECT PinConnect,
|
||||
IN ULONG PinId);
|
||||
|
||||
MIXER_STATUS
|
||||
MMixerGetPinDataFlowAndCommunication(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
IN HANDLE hDevice,
|
||||
IN ULONG PinId,
|
||||
OUT PKSPIN_DATAFLOW DataFlow,
|
||||
OUT PKSPIN_COMMUNICATION Communication);
|
||||
|
||||
VOID
|
||||
MMixerHandleAlternativeMixers(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
IN PMIXER_LIST MixerList,
|
||||
IN LPMIXER_DATA MixerData,
|
||||
IN PTOPOLOGY Topology);
|
||||
|
||||
MIXER_STATUS
|
||||
MMixerGetMixerByName(
|
||||
IN PMIXER_LIST MixerList,
|
||||
IN LPWSTR MixerName,
|
||||
OUT LPMIXER_INFO *MixerInfo);
|
||||
|
||||
/* topology.c */
|
||||
|
||||
|
@ -462,8 +503,25 @@ MMixerIsTopologyNodeReserved(
|
|||
IN ULONG NodeIndex,
|
||||
OUT PULONG bReserved);
|
||||
|
||||
VOID
|
||||
MMixerSetTopologyPinReserved(
|
||||
IN PTOPOLOGY Topology,
|
||||
IN ULONG PinId);
|
||||
|
||||
VOID
|
||||
MMixerIsTopologyPinReserved(
|
||||
IN PTOPOLOGY Topology,
|
||||
IN ULONG PinId,
|
||||
OUT PULONG bReserved);
|
||||
|
||||
VOID
|
||||
MMixerGetTopologyPinCount(
|
||||
IN PTOPOLOGY Topology,
|
||||
OUT PULONG PinCount);
|
||||
|
||||
VOID
|
||||
MMixerGetConnectedFromLogicalTopologyPins(
|
||||
IN PTOPOLOGY Topology,
|
||||
IN ULONG NodeIndex,
|
||||
OUT PULONG OutPinCount,
|
||||
OUT PULONG OutPins);
|
||||
|
|
|
@ -54,6 +54,63 @@ MMixerVerifyContext(
|
|||
return MM_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
LPMIXERLINE_EXT
|
||||
MMixerGetMixerLineContainingNodeId(
|
||||
IN LPMIXER_INFO MixerInfo,
|
||||
IN ULONG NodeID)
|
||||
{
|
||||
PLIST_ENTRY Entry, ControlEntry;
|
||||
LPMIXERLINE_EXT MixerLineSrc;
|
||||
LPMIXERCONTROL_EXT MixerControl;
|
||||
|
||||
/* get first entry */
|
||||
Entry = MixerInfo->LineList.Flink;
|
||||
|
||||
while(Entry != &MixerInfo->LineList)
|
||||
{
|
||||
MixerLineSrc = (LPMIXERLINE_EXT)CONTAINING_RECORD(Entry, MIXERLINE_EXT, Entry);
|
||||
|
||||
ControlEntry = MixerLineSrc->ControlsList.Flink;
|
||||
while(ControlEntry != &MixerLineSrc->ControlsList)
|
||||
{
|
||||
MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(ControlEntry, MIXERCONTROL_EXT, Entry);
|
||||
if (MixerControl->NodeID == NodeID)
|
||||
{
|
||||
return MixerLineSrc;
|
||||
}
|
||||
ControlEntry = ControlEntry->Flink;
|
||||
}
|
||||
Entry = Entry->Flink;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VOID
|
||||
MMixerGetLowestLogicalTopologyPinOffsetFromArray(
|
||||
IN ULONG LogicalPinArrayCount,
|
||||
IN PULONG LogicalPinArray,
|
||||
OUT PULONG PinOffset)
|
||||
{
|
||||
ULONG Index;
|
||||
ULONG LowestId = 0;
|
||||
|
||||
for(Index = 1; Index < LogicalPinArrayCount; Index++)
|
||||
{
|
||||
if (LogicalPinArray[Index] != MAXULONG)
|
||||
{
|
||||
/* sanity check: logical pin id must be unique */
|
||||
ASSERT(LogicalPinArray[Index] != LogicalPinArray[LowestId]);
|
||||
}
|
||||
|
||||
if (LogicalPinArray[Index] < LogicalPinArray[LowestId])
|
||||
LowestId = Index;
|
||||
}
|
||||
|
||||
/* store result */
|
||||
*PinOffset = LowestId;
|
||||
}
|
||||
|
||||
VOID
|
||||
MMixerFreeMixerInfo(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
|
@ -67,6 +124,38 @@ MMixerFreeMixerInfo(
|
|||
MixerContext->Free((PVOID)MixerInfo);
|
||||
}
|
||||
|
||||
|
||||
LPMIXER_DATA
|
||||
MMixerGetMixerDataByDeviceHandle(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
IN HANDLE hDevice)
|
||||
{
|
||||
LPMIXER_DATA MixerData;
|
||||
PLIST_ENTRY Entry;
|
||||
PMIXER_LIST MixerList;
|
||||
|
||||
/* get mixer list */
|
||||
MixerList = (PMIXER_LIST)MixerContext->MixerContext;
|
||||
|
||||
if (!MixerList->MixerDataCount)
|
||||
return NULL;
|
||||
|
||||
Entry = MixerList->MixerData.Flink;
|
||||
|
||||
while(Entry != &MixerList->MixerData)
|
||||
{
|
||||
MixerData = (LPMIXER_DATA)CONTAINING_RECORD(Entry, MIXER_DATA, Entry);
|
||||
|
||||
if (MixerData->hDevice == hDevice)
|
||||
return MixerData;
|
||||
|
||||
/* move to next mixer entry */
|
||||
Entry = Entry->Flink;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
LPMIXER_INFO
|
||||
MMixerGetMixerInfoByIndex(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
|
@ -100,27 +189,31 @@ MMixerGetMixerInfoByIndex(
|
|||
return NULL;
|
||||
}
|
||||
|
||||
LPMIXERCONTROL_DATA
|
||||
MMixerGetMixerControlDataById(
|
||||
PLIST_ENTRY ListHead,
|
||||
DWORD dwControlId)
|
||||
MIXER_STATUS
|
||||
MMixerGetMixerByName(
|
||||
IN PMIXER_LIST MixerList,
|
||||
IN LPWSTR MixerName,
|
||||
OUT LPMIXER_INFO *OutMixerInfo)
|
||||
{
|
||||
LPMIXER_INFO MixerInfo;
|
||||
PLIST_ENTRY Entry;
|
||||
LPMIXERCONTROL_DATA Control;
|
||||
|
||||
/* get first entry */
|
||||
Entry = ListHead->Flink;
|
||||
|
||||
while(Entry != ListHead)
|
||||
Entry = MixerList->MixerList.Flink;
|
||||
while(Entry != &MixerList->MixerList)
|
||||
{
|
||||
Control = (LPMIXERCONTROL_DATA)CONTAINING_RECORD(Entry, MIXERCONTROL_DATA, Entry);
|
||||
DPRINT("dwSource %x dwSource %x\n", Control->dwControlID, dwControlId);
|
||||
if (Control->dwControlID == dwControlId)
|
||||
return Control;
|
||||
MixerInfo = (LPMIXER_INFO)CONTAINING_RECORD(Entry, MIXER_INFO, Entry);
|
||||
|
||||
DPRINT1("MixerName %S MixerName %S\n", MixerInfo->MixCaps.szPname, MixerName);
|
||||
if (wcsicmp(MixerInfo->MixCaps.szPname, MixerName) == 0)
|
||||
{
|
||||
*OutMixerInfo = MixerInfo;
|
||||
return MM_STATUS_SUCCESS;
|
||||
}
|
||||
/* move to next mixer entry */
|
||||
Entry = Entry->Flink;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
return MM_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
LPMIXERLINE_EXT
|
||||
|
@ -187,13 +280,13 @@ MIXER_STATUS
|
|||
MMixerGetMixerControlById(
|
||||
LPMIXER_INFO MixerInfo,
|
||||
DWORD dwControlID,
|
||||
LPMIXERLINE_EXT *MixerLine,
|
||||
LPMIXERCONTROLW *MixerControl,
|
||||
LPMIXERLINE_EXT *OutMixerLine,
|
||||
LPMIXERCONTROL_EXT *OutMixerControl,
|
||||
PULONG NodeId)
|
||||
{
|
||||
PLIST_ENTRY Entry;
|
||||
PLIST_ENTRY Entry, ControlEntry;
|
||||
LPMIXERLINE_EXT MixerLineSrc;
|
||||
ULONG Index;
|
||||
LPMIXERCONTROL_EXT MixerControl;
|
||||
|
||||
/* get first entry */
|
||||
Entry = MixerInfo->LineList.Flink;
|
||||
|
@ -202,18 +295,21 @@ MMixerGetMixerControlById(
|
|||
{
|
||||
MixerLineSrc = (LPMIXERLINE_EXT)CONTAINING_RECORD(Entry, MIXERLINE_EXT, Entry);
|
||||
|
||||
for(Index = 0; Index < MixerLineSrc->Line.cControls; Index++)
|
||||
ControlEntry = MixerLineSrc->ControlsList.Flink;
|
||||
while(ControlEntry != &MixerLineSrc->ControlsList)
|
||||
{
|
||||
if (MixerLineSrc->LineControls[Index].dwControlID == dwControlID)
|
||||
MixerControl = (LPMIXERCONTROL_EXT)CONTAINING_RECORD(ControlEntry, MIXERCONTROL_EXT, Entry);
|
||||
if (MixerControl->Control.dwControlID == dwControlID)
|
||||
{
|
||||
if (MixerLine)
|
||||
*MixerLine = MixerLineSrc;
|
||||
if (MixerControl)
|
||||
*MixerControl = &MixerLineSrc->LineControls[Index];
|
||||
if (OutMixerLine)
|
||||
*OutMixerLine = MixerLineSrc;
|
||||
if (OutMixerControl)
|
||||
*OutMixerControl = MixerControl;
|
||||
if (NodeId)
|
||||
*NodeId = MixerLineSrc->NodeIds[Index];
|
||||
*NodeId = MixerControl->NodeID;
|
||||
return MM_STATUS_SUCCESS;
|
||||
}
|
||||
ControlEntry = ControlEntry->Flink;
|
||||
}
|
||||
Entry = Entry->Flink;
|
||||
}
|
||||
|
@ -248,8 +344,8 @@ MMixerNotifyControlChange(
|
|||
PLIST_ENTRY Entry;
|
||||
PEVENT_NOTIFICATION_ENTRY NotificationEntry;
|
||||
|
||||
/* enumerate list and add a notification entry */
|
||||
Entry = MixerInfo->LineList.Flink;
|
||||
/* enumerate list and perform notification */
|
||||
Entry = MixerInfo->EventList.Flink;
|
||||
while(Entry != &MixerInfo->EventList)
|
||||
{
|
||||
/* get notification entry offset */
|
||||
|
@ -270,7 +366,7 @@ MIXER_STATUS
|
|||
MMixerSetGetMuteControlDetails(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
IN LPMIXER_INFO MixerInfo,
|
||||
IN ULONG NodeId,
|
||||
IN LPMIXERCONTROL_EXT MixerControl,
|
||||
IN ULONG dwLineID,
|
||||
IN LPMIXERCONTROLDETAILS MixerControlDetails,
|
||||
IN ULONG bSet)
|
||||
|
@ -290,7 +386,7 @@ MMixerSetGetMuteControlDetails(
|
|||
Value = Input->fValue;
|
||||
|
||||
/* set control details */
|
||||
Status = MMixerSetGetControlDetails(MixerContext, MixerInfo->hMixer, NodeId, bSet, KSPROPERTY_AUDIO_MUTE, 0, &Value);
|
||||
Status = MMixerSetGetControlDetails(MixerContext, MixerControl->hDevice, MixerControl->NodeID, bSet, KSPROPERTY_AUDIO_MUTE, 0, &Value);
|
||||
|
||||
if (Status != MM_STATUS_SUCCESS)
|
||||
return Status;
|
||||
|
@ -310,13 +406,262 @@ MMixerSetGetMuteControlDetails(
|
|||
return Status;
|
||||
}
|
||||
|
||||
MIXER_STATUS
|
||||
MMixerSetGetMuxControlDetails(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
IN LPMIXER_INFO MixerInfo,
|
||||
IN ULONG NodeId,
|
||||
IN ULONG bSet,
|
||||
IN ULONG Flags,
|
||||
IN LPMIXERCONTROL_EXT MixerControl,
|
||||
IN LPMIXERCONTROLDETAILS MixerControlDetails,
|
||||
IN LPMIXERLINE_EXT MixerLine)
|
||||
{
|
||||
MIXER_STATUS Status;
|
||||
PULONG LogicalNodes, ConnectedNodes;
|
||||
ULONG LogicalNodesCount, ConnectedNodesCount, Index, CurLogicalPinOffset, BytesReturned, OldLogicalPinOffset;
|
||||
LPMIXER_DATA MixerData;
|
||||
LPMIXERCONTROLDETAILS_LISTTEXTW ListText;
|
||||
LPMIXERCONTROLDETAILS_BOOLEAN Values;
|
||||
LPMIXERLINE_EXT SourceLine;
|
||||
KSNODEPROPERTY Request;
|
||||
|
||||
DPRINT("MixerControlDetails %p\n", MixerControlDetails);
|
||||
DPRINT("bSet %lx\n", bSet);
|
||||
DPRINT("Flags %lx\n", Flags);
|
||||
DPRINT("NodeId %lu\n", MixerControl->NodeID);
|
||||
DPRINT("MixerControlDetails dwControlID %lu\n", MixerControlDetails->dwControlID);
|
||||
DPRINT("MixerControlDetails cChannels %lu\n", MixerControlDetails->cChannels);
|
||||
DPRINT("MixerControlDetails cMultipleItems %lu\n", MixerControlDetails->cMultipleItems);
|
||||
DPRINT("MixerControlDetails cbDetails %lu\n", MixerControlDetails->cbDetails);
|
||||
DPRINT("MixerControlDetails paDetails %p\n", MixerControlDetails->paDetails);
|
||||
|
||||
if (MixerControl->Control.fdwControl & MIXERCONTROL_CONTROLF_UNIFORM)
|
||||
{
|
||||
/* control acts uniform */
|
||||
if (MixerControlDetails->cChannels != 1)
|
||||
{
|
||||
/* expected 1 channel */
|
||||
DPRINT1("Expected 1 channel but got %lu\n", MixerControlDetails->cChannels);
|
||||
return MM_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if multiple items match */
|
||||
if (MixerControlDetails->cMultipleItems != MixerControl->Control.cMultipleItems)
|
||||
{
|
||||
DPRINT1("MultipleItems mismatch %lu expected %lu\n", MixerControlDetails->cMultipleItems, MixerControl->Control.cMultipleItems);
|
||||
return MM_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
if (bSet)
|
||||
{
|
||||
if ((Flags & MIXER_SETCONTROLDETAILSF_QUERYMASK) == MIXER_SETCONTROLDETAILSF_CUSTOM)
|
||||
{
|
||||
/* tell me when this is hit */
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
else if ((Flags & (MIXER_SETCONTROLDETAILSF_VALUE | MIXER_SETCONTROLDETAILSF_CUSTOM)) == MIXER_SETCONTROLDETAILSF_VALUE)
|
||||
{
|
||||
/* sanity check */
|
||||
ASSERT(bSet == TRUE);
|
||||
ASSERT(MixerControlDetails->cbDetails == sizeof(MIXERCONTROLDETAILS_BOOLEAN));
|
||||
|
||||
Values = (LPMIXERCONTROLDETAILS_BOOLEAN)MixerControlDetails->paDetails;
|
||||
CurLogicalPinOffset = MAXULONG;
|
||||
for(Index = 0; Index < MixerControlDetails->cMultipleItems; Index++)
|
||||
{
|
||||
if (Values[Index].fValue)
|
||||
{
|
||||
/* mux can only activate one line at a time */
|
||||
ASSERT(CurLogicalPinOffset == MAXULONG);
|
||||
CurLogicalPinOffset = Index;
|
||||
}
|
||||
}
|
||||
|
||||
/* setup request */
|
||||
Request.NodeId = NodeId;
|
||||
Request.Reserved = 0;
|
||||
Request.Property.Flags = KSPROPERTY_TYPE_TOPOLOGY | KSPROPERTY_TYPE_GET;
|
||||
Request.Property.Id = KSPROPERTY_AUDIO_MUX_SOURCE;
|
||||
Request.Property.Set = KSPROPSETID_Audio;
|
||||
|
||||
/* perform getting source */
|
||||
Status = MixerContext->Control(MixerControl->hDevice, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSNODEPROPERTY), &OldLogicalPinOffset, sizeof(ULONG), &BytesReturned);
|
||||
if (Status != MM_STATUS_SUCCESS)
|
||||
{
|
||||
/* failed to get source */
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT("OldLogicalPinOffset %lu CurLogicalPinOffset %lu\n", OldLogicalPinOffset, CurLogicalPinOffset);
|
||||
|
||||
if (OldLogicalPinOffset == CurLogicalPinOffset)
|
||||
{
|
||||
/* cannot be unselected */
|
||||
return MM_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
/* perform setting source */
|
||||
Request.Property.Flags = KSPROPERTY_TYPE_TOPOLOGY | KSPROPERTY_TYPE_SET;
|
||||
Status = MixerContext->Control(MixerControl->hDevice, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSNODEPROPERTY), &CurLogicalPinOffset, sizeof(ULONG), &BytesReturned);
|
||||
if (Status != MM_STATUS_SUCCESS)
|
||||
{
|
||||
/* failed to set source */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* notify control change */
|
||||
MMixerNotifyControlChange(MixerContext, MixerInfo, MM_MIXM_CONTROL_CHANGE, MixerControl->Control.dwControlID );
|
||||
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((Flags & MIXER_GETCONTROLDETAILSF_QUERYMASK) == MIXER_GETCONTROLDETAILSF_VALUE)
|
||||
{
|
||||
/* setup request */
|
||||
Request.NodeId = NodeId;
|
||||
Request.Reserved = 0;
|
||||
Request.Property.Flags = KSPROPERTY_TYPE_TOPOLOGY | KSPROPERTY_TYPE_GET;
|
||||
Request.Property.Id = KSPROPERTY_AUDIO_MUX_SOURCE;
|
||||
Request.Property.Set = KSPROPSETID_Audio;
|
||||
|
||||
/* perform getting source */
|
||||
Status = MixerContext->Control(MixerControl->hDevice, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSNODEPROPERTY), &OldLogicalPinOffset, sizeof(ULONG), &BytesReturned);
|
||||
if (Status != MM_STATUS_SUCCESS)
|
||||
{
|
||||
/* failed to get source */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* gets the corresponding mixer data */
|
||||
MixerData = MMixerGetMixerDataByDeviceHandle(MixerContext, MixerControl->hDevice);
|
||||
|
||||
/* sanity check */
|
||||
ASSERT(MixerData);
|
||||
ASSERT(MixerData->Topology);
|
||||
ASSERT(MixerData->MixerInfo == MixerInfo);
|
||||
|
||||
/* get logical pin nodes */
|
||||
MMixerGetConnectedFromLogicalTopologyPins(MixerData->Topology, MixerControl->NodeID, &LogicalNodesCount, LogicalNodes);
|
||||
|
||||
/* sanity check */
|
||||
ASSERT(LogicalNodesCount == MixerControlDetails->cMultipleItems);
|
||||
ASSERT(LogicalNodesCount == MixerControl->Control.Metrics.dwReserved[0]);
|
||||
|
||||
Values = (LPMIXERCONTROLDETAILS_BOOLEAN)MixerControlDetails->paDetails;
|
||||
for(Index = 0; Index < ConnectedNodesCount; Index++)
|
||||
{
|
||||
/* getting logical pin offset */
|
||||
MMixerGetLowestLogicalTopologyPinOffsetFromArray(LogicalNodesCount, LogicalNodes, &CurLogicalPinOffset);
|
||||
|
||||
if (CurLogicalPinOffset == OldLogicalPinOffset)
|
||||
{
|
||||
/* mark index as active */
|
||||
Values[Index].fValue = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* index not active */
|
||||
Values[Index].fValue = FALSE;
|
||||
}
|
||||
|
||||
/* mark offset as consumed */
|
||||
LogicalNodes[CurLogicalPinOffset] = MAXULONG;
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
MixerContext->Free(LogicalNodes);
|
||||
|
||||
/* done */
|
||||
return MM_STATUS_SUCCESS;
|
||||
}
|
||||
else if ((Flags & MIXER_GETCONTROLDETAILSF_QUERYMASK) == MIXER_GETCONTROLDETAILSF_LISTTEXT)
|
||||
{
|
||||
/* sanity check */
|
||||
ASSERT(bSet == FALSE);
|
||||
|
||||
/* gets the corresponding mixer data */
|
||||
MixerData = MMixerGetMixerDataByDeviceHandle(MixerContext, MixerControl->hDevice);
|
||||
|
||||
/* sanity check */
|
||||
ASSERT(MixerData);
|
||||
ASSERT(MixerData->Topology);
|
||||
ASSERT(MixerData->MixerInfo == MixerInfo);
|
||||
|
||||
/* now allocate logical pin array */
|
||||
Status = MMixerAllocateTopologyNodeArray(MixerContext, MixerData->Topology, &LogicalNodes);
|
||||
if (Status != MM_STATUS_SUCCESS)
|
||||
{
|
||||
/* no memory */
|
||||
return MM_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* allocate connected node array */
|
||||
Status = MMixerAllocateTopologyNodeArray(MixerContext, MixerData->Topology, &ConnectedNodes);
|
||||
if (Status != MM_STATUS_SUCCESS)
|
||||
{
|
||||
/* no memory */
|
||||
MixerContext->Free(LogicalNodes);
|
||||
return MM_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* get logical pin nodes */
|
||||
MMixerGetConnectedFromLogicalTopologyPins(MixerData->Topology, MixerControl->NodeID, &LogicalNodesCount, LogicalNodes);
|
||||
|
||||
/* get connected nodes */
|
||||
MMixerGetNextNodesFromNodeIndex(MixerContext, MixerData->Topology, MixerControl->NodeID, TRUE, &ConnectedNodesCount, ConnectedNodes);
|
||||
|
||||
/* sanity check */
|
||||
ASSERT(ConnectedNodesCount == LogicalNodesCount);
|
||||
ASSERT(ConnectedNodesCount == MixerControlDetails->cMultipleItems);
|
||||
ASSERT(ConnectedNodesCount == MixerControl->Control.Metrics.dwReserved[0]);
|
||||
|
||||
ListText = (LPMIXERCONTROLDETAILS_LISTTEXTW)MixerControlDetails->paDetails;
|
||||
|
||||
for(Index = 0; Index < ConnectedNodesCount; Index++)
|
||||
{
|
||||
/* getting logical pin offset */
|
||||
MMixerGetLowestLogicalTopologyPinOffsetFromArray(LogicalNodesCount, LogicalNodes, &CurLogicalPinOffset);
|
||||
|
||||
/* get mixer line with that node */
|
||||
SourceLine = MMixerGetMixerLineContainingNodeId(MixerInfo, ConnectedNodes[CurLogicalPinOffset]);
|
||||
|
||||
/* sanity check */
|
||||
ASSERT(SourceLine);
|
||||
|
||||
DPRINT1("PinOffset %lu LogicalPin %lu NodeId %lu LineName %S\n", CurLogicalPinOffset, LogicalNodes[CurLogicalPinOffset], ConnectedNodes[CurLogicalPinOffset], SourceLine->Line.szName);
|
||||
|
||||
/* copy details */
|
||||
ListText[Index].dwParam1 = SourceLine->Line.dwLineID;
|
||||
ListText[Index].dwParam2 = SourceLine->Line.dwComponentType;
|
||||
MixerContext->Copy(ListText[Index].szName, SourceLine->Line.szName, (wcslen(SourceLine->Line.szName) + 1) * sizeof(WCHAR));
|
||||
|
||||
/* mark offset as consumed */
|
||||
LogicalNodes[CurLogicalPinOffset] = MAXULONG;
|
||||
}
|
||||
|
||||
/* cleanup */
|
||||
MixerContext->Free(LogicalNodes);
|
||||
MixerContext->Free(ConnectedNodes);
|
||||
|
||||
/* done */
|
||||
return MM_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return MM_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
MIXER_STATUS
|
||||
MMixerSetGetVolumeControlDetails(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
IN LPMIXER_INFO MixerInfo,
|
||||
IN ULONG NodeId,
|
||||
IN ULONG bSet,
|
||||
LPMIXERCONTROLW MixerControl,
|
||||
LPMIXERCONTROL_EXT MixerControl,
|
||||
IN LPMIXERCONTROLDETAILS MixerControlDetails,
|
||||
LPMIXERLINE_EXT MixerLine)
|
||||
{
|
||||
|
@ -329,7 +674,7 @@ MMixerSetGetVolumeControlDetails(
|
|||
if (MixerControlDetails->cbDetails != sizeof(MIXERCONTROLDETAILS_SIGNED))
|
||||
return MM_STATUS_INVALID_PARAMETER;
|
||||
|
||||
VolumeData = (LPMIXERVOLUME_DATA)MMixerGetMixerControlDataById(&MixerLine->LineControlsExtraData, MixerControl->dwControlID);
|
||||
VolumeData = (LPMIXERVOLUME_DATA)MixerControl->ExtraData;
|
||||
if (!VolumeData)
|
||||
return MM_STATUS_UNSUCCESSFUL;
|
||||
|
||||
|
@ -355,12 +700,12 @@ MMixerSetGetVolumeControlDetails(
|
|||
if (bSet)
|
||||
{
|
||||
/* TODO */
|
||||
Status = MMixerSetGetControlDetails(MixerContext, MixerInfo->hMixer, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 0, &Value);
|
||||
Status = MMixerSetGetControlDetails(MixerContext, MixerInfo->hMixer, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 1, &Value);
|
||||
Status = MMixerSetGetControlDetails(MixerContext, MixerControl->hDevice, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 0, &Value);
|
||||
Status = MMixerSetGetControlDetails(MixerContext, MixerControl->hDevice, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, 1, &Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = MMixerSetGetControlDetails(MixerContext, MixerInfo->hMixer, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, Channel, &Value);
|
||||
Status = MMixerSetGetControlDetails(MixerContext, MixerControl->hDevice, NodeId, bSet, KSPROPERTY_AUDIO_VOLUMELEVEL, Channel, &Value);
|
||||
}
|
||||
|
||||
if (!bSet)
|
||||
|
@ -372,7 +717,7 @@ MMixerSetGetVolumeControlDetails(
|
|||
else
|
||||
{
|
||||
/* notify clients of a line change MM_MIXM_CONTROL_CHANGE with MixerControl->dwControlID */
|
||||
MMixerNotifyControlChange(MixerContext, MixerInfo, MM_MIXM_CONTROL_CHANGE, MixerControl->dwControlID);
|
||||
MMixerNotifyControlChange(MixerContext, MixerInfo, MM_MIXM_CONTROL_CHANGE, MixerControl->Control.dwControlID);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
|
|
@ -264,7 +264,9 @@ MMixerHandleNodeToNodeConnection(
|
|||
{
|
||||
PTOPOLOGY_NODE InNode, OutNode;
|
||||
PTOPOLOGY_NODE * NewNodes;
|
||||
PULONG NewLogicalPinNodeConnectedFrom;
|
||||
ULONG Count;
|
||||
ULONG LogicalPinId;
|
||||
|
||||
/* sanity checks */
|
||||
ASSERT(Topology->TopologyNodesCount > Connection->ToNode);
|
||||
|
@ -274,6 +276,9 @@ MMixerHandleNodeToNodeConnection(
|
|||
InNode = &Topology->TopologyNodes[Connection->FromNode];
|
||||
OutNode = &Topology->TopologyNodes[Connection->ToNode];
|
||||
|
||||
/* get logical pin node id */
|
||||
LogicalPinId = Connection->ToNodePin;
|
||||
|
||||
/* get existing count */
|
||||
Count = OutNode->NodeConnectedFromCount;
|
||||
|
||||
|
@ -286,21 +291,42 @@ MMixerHandleNodeToNodeConnection(
|
|||
return MM_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
/* allocate logical pin nodes array */
|
||||
NewLogicalPinNodeConnectedFrom = MixerContext->Alloc((Count + 1) * sizeof(ULONG));
|
||||
if (!NewLogicalPinNodeConnectedFrom)
|
||||
{
|
||||
/* out of memory */
|
||||
MixerContext->Free(NewNodes);
|
||||
return MM_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
if (Count)
|
||||
{
|
||||
/* copy existing nodes */
|
||||
MixerContext->Copy(NewNodes, OutNode->NodeConnectedFrom, sizeof(PTOPOLOGY) * Count);
|
||||
|
||||
/* copy existing logical pin node array */
|
||||
MixerContext->Copy(NewLogicalPinNodeConnectedFrom, OutNode->LogicalPinNodeConnectedFrom, sizeof(ULONG) * Count);
|
||||
|
||||
/* release old nodes array */
|
||||
MixerContext->Free(OutNode->NodeConnectedFrom);
|
||||
|
||||
/* release old logical pin node array */
|
||||
MixerContext->Free(OutNode->LogicalPinNodeConnectedFrom);
|
||||
}
|
||||
|
||||
/* add new topology node */
|
||||
NewNodes[OutNode->NodeConnectedFromCount] = InNode;
|
||||
|
||||
/* add logical node id */
|
||||
NewLogicalPinNodeConnectedFrom[OutNode->NodeConnectedFromCount] = LogicalPinId;
|
||||
|
||||
/* replace old nodes array */
|
||||
OutNode->NodeConnectedFrom = NewNodes;
|
||||
|
||||
/* replace old logical pin node array */
|
||||
OutNode->LogicalPinNodeConnectedFrom = NewLogicalPinNodeConnectedFrom;
|
||||
|
||||
/* increment nodes count */
|
||||
OutNode->NodeConnectedFromCount++;
|
||||
|
||||
|
@ -745,16 +771,15 @@ MMixerGetUpOrDownstreamNodes(
|
|||
/* node should not have been visited */
|
||||
ASSERT(Node->Visited == FALSE);
|
||||
|
||||
/* mark node as visited */
|
||||
TopologyNode->Visited = TRUE;
|
||||
|
||||
/* add them to node array */
|
||||
MMixerAddPinIndexToArray(MixerContext, Node->NodeIndex, Topology->TopologyNodesCount, OutNodeCount, OutNodes);
|
||||
|
||||
/* recursively visit them */
|
||||
MMixerGetUpOrDownstreamNodes(MixerContext, Topology, TopologyNodes[Index], bUpStream, OutNodeCount, OutNodes);
|
||||
}
|
||||
|
||||
/* mark node as visited */
|
||||
TopologyNode->Visited = TRUE;
|
||||
|
||||
}
|
||||
|
||||
MIXER_STATUS
|
||||
|
@ -1137,6 +1162,32 @@ MMixerIsNodeConnectedToPin(
|
|||
return MM_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
MMixerGetConnectedFromLogicalTopologyPins(
|
||||
IN PTOPOLOGY Topology,
|
||||
IN ULONG NodeIndex,
|
||||
OUT PULONG OutPinCount,
|
||||
OUT PULONG OutPins)
|
||||
{
|
||||
ULONG Index;
|
||||
PTOPOLOGY_NODE Node;
|
||||
|
||||
/* sanity check */
|
||||
ASSERT(NodeIndex < Topology->TopologyNodesCount);
|
||||
|
||||
/* get node */
|
||||
Node = &Topology->TopologyNodes[NodeIndex];
|
||||
|
||||
for(Index = 0; Index < Node->NodeConnectedFromCount; Index++)
|
||||
{
|
||||
/* copy logical pin id */
|
||||
OutPins[Index] = Node->LogicalPinNodeConnectedFrom[Index];
|
||||
}
|
||||
|
||||
/* store pin count */
|
||||
*OutPinCount = Node->NodeConnectedFromCount;
|
||||
}
|
||||
|
||||
LPGUID
|
||||
MMixerGetNodeTypeFromTopology(
|
||||
IN PTOPOLOGY Topology,
|
||||
|
@ -1148,6 +1199,31 @@ MMixerGetNodeTypeFromTopology(
|
|||
return &Topology->TopologyNodes[NodeIndex].NodeType;
|
||||
}
|
||||
|
||||
VOID
|
||||
MMixerSetTopologyPinReserved(
|
||||
IN PTOPOLOGY Topology,
|
||||
IN ULONG PinId)
|
||||
{
|
||||
/* sanity check */
|
||||
ASSERT(PinId < Topology->TopologyPinsCount);
|
||||
|
||||
/* set reserved */
|
||||
Topology->TopologyPins[PinId].Reserved = TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
MMixerIsTopologyPinReserved(
|
||||
IN PTOPOLOGY Topology,
|
||||
IN ULONG PinId,
|
||||
OUT PULONG bReserved)
|
||||
{
|
||||
/* sanity check */
|
||||
ASSERT(PinId < Topology->TopologyPinsCount);
|
||||
|
||||
/* get reserved status */
|
||||
*bReserved = Topology->TopologyPins[PinId].Reserved;
|
||||
}
|
||||
|
||||
VOID
|
||||
MMixerSetTopologyNodeReserved(
|
||||
IN PTOPOLOGY Topology,
|
||||
|
|
|
@ -608,6 +608,16 @@ MMixerSetWaveStatus(
|
|||
{
|
||||
KSPROPERTY Property;
|
||||
ULONG Length;
|
||||
MIXER_STATUS Status;
|
||||
|
||||
/* verify mixer context */
|
||||
Status = MMixerVerifyContext(MixerContext);
|
||||
|
||||
if (Status != MM_STATUS_SUCCESS)
|
||||
{
|
||||
/* invalid context passed */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* setup property request */
|
||||
Property.Set = KSPROPSETID_Connection;
|
||||
|
@ -617,6 +627,31 @@ MMixerSetWaveStatus(
|
|||
return MixerContext->Control(PinHandle, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), &State, sizeof(KSSTATE), &Length);
|
||||
}
|
||||
|
||||
MIXER_STATUS
|
||||
MMixerSetWaveResetState(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
IN HANDLE PinHandle,
|
||||
IN ULONG bBegin)
|
||||
{
|
||||
ULONG Length;
|
||||
MIXER_STATUS Status;
|
||||
KSRESET Reset;
|
||||
|
||||
/* verify mixer context */
|
||||
Status = MMixerVerifyContext(MixerContext);
|
||||
|
||||
if (Status != MM_STATUS_SUCCESS)
|
||||
{
|
||||
/* invalid context passed */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* begin / stop reset */
|
||||
Reset = (bBegin ? KSRESET_BEGIN : KSRESET_END);
|
||||
|
||||
return MixerContext->Control(PinHandle, IOCTL_KS_RESET_STATE, &Reset, sizeof(KSRESET), NULL, 0, &Length);
|
||||
}
|
||||
|
||||
MIXER_STATUS
|
||||
MMixerGetWaveDevicePath(
|
||||
IN PMIXER_CONTEXT MixerContext,
|
||||
|
|
|
@ -264,8 +264,8 @@ LsaLogonUser(HANDLE LsaHandle,
|
|||
0,
|
||||
Reply->d.LogonUserReply.ProfileBufferLength);
|
||||
memcpy(*ProfileBuffer,
|
||||
(PVOID)((ULONG)Reply->d.LogonUserReply.Data +
|
||||
(ULONG)Reply->d.LogonUserReply.ProfileBuffer),
|
||||
(PVOID)((ULONG_PTR)Reply->d.LogonUserReply.Data +
|
||||
(ULONG_PTR)Reply->d.LogonUserReply.ProfileBuffer),
|
||||
Reply->d.LogonUserReply.ProfileBufferLength);
|
||||
*LogonId = Reply->d.LogonUserReply.LogonId;
|
||||
*Token = Reply->d.LogonUserReply.Token;
|
||||
|
|
|
@ -692,13 +692,18 @@ co_IntFixCaret(PWND Window, RECTL *lprc, UINT flags)
|
|||
{
|
||||
PDESKTOP Desktop;
|
||||
PTHRDCARETINFO CaretInfo;
|
||||
PTHREADINFO pti;
|
||||
PUSER_MESSAGE_QUEUE ActiveMessageQueue;
|
||||
HWND hWndCaret;
|
||||
PWND WndCaret;
|
||||
|
||||
ASSERT_REFS_CO(Window);
|
||||
|
||||
Desktop = ((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->rpdesk;
|
||||
CaretInfo = ((PUSER_MESSAGE_QUEUE)Desktop->ActiveMessageQueue)->CaretInfo;
|
||||
pti = PsGetCurrentThreadWin32Thread();
|
||||
Desktop = pti->rpdesk;
|
||||
ActiveMessageQueue = Desktop->ActiveMessageQueue;
|
||||
if (!ActiveMessageQueue) return 0;
|
||||
CaretInfo = ActiveMessageQueue->CaretInfo;
|
||||
hWndCaret = CaretInfo->hWnd;
|
||||
|
||||
WndCaret = UserGetWindowObject(hWndCaret);
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
static PTIMER FirstpTmr = NULL;
|
||||
static LIST_ENTRY TimersListHead;
|
||||
static LONG TimeLast = 0;
|
||||
|
||||
#define MAX_ELAPSE_TIME 0x7FFFFFFF
|
||||
|
@ -62,26 +62,13 @@ CreateTimer(VOID)
|
|||
HANDLE Handle;
|
||||
PTIMER Ret = NULL;
|
||||
|
||||
if (!FirstpTmr)
|
||||
Ret = UserCreateObject(gHandleTable, NULL, &Handle, otTimer, sizeof(TIMER));
|
||||
if (Ret)
|
||||
{
|
||||
ExInitializeResourceLite(&TimerLock);
|
||||
FirstpTmr = UserCreateObject(gHandleTable, NULL, &Handle, otTimer, sizeof(TIMER));
|
||||
if (FirstpTmr)
|
||||
{
|
||||
FirstpTmr->head.h = Handle;
|
||||
InitializeListHead(&FirstpTmr->ptmrList);
|
||||
}
|
||||
Ret = FirstpTmr;
|
||||
}
|
||||
else
|
||||
{
|
||||
Ret = UserCreateObject(gHandleTable, NULL, &Handle, otTimer, sizeof(TIMER));
|
||||
if (Ret)
|
||||
{
|
||||
Ret->head.h = Handle;
|
||||
InsertTailList(&FirstpTmr->ptmrList, &Ret->ptmrList);
|
||||
}
|
||||
Ret->head.h = Handle;
|
||||
InsertTailList(&TimersListHead, &Ret->ptmrList);
|
||||
}
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
|
@ -118,12 +105,13 @@ FindTimer(PWND Window,
|
|||
UINT_PTR nID,
|
||||
UINT flags)
|
||||
{
|
||||
PLIST_ENTRY pLE;
|
||||
PTIMER pTmr = FirstpTmr, RetTmr = NULL;
|
||||
PLIST_ENTRY pLE = TimersListHead.Flink;
|
||||
PTIMER pTmr, RetTmr = NULL;
|
||||
|
||||
TimerEnterExclusive();
|
||||
do
|
||||
while (pLE != &TimersListHead)
|
||||
{
|
||||
if (!pTmr) break;
|
||||
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
|
||||
|
||||
if ( pTmr->nID == nID &&
|
||||
pTmr->pWnd == Window &&
|
||||
|
@ -133,9 +121,8 @@ FindTimer(PWND Window,
|
|||
break;
|
||||
}
|
||||
|
||||
pLE = pTmr->ptmrList.Flink;
|
||||
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
|
||||
} while (pTmr != FirstpTmr);
|
||||
pLE = pLE->Flink;
|
||||
}
|
||||
TimerLeave();
|
||||
|
||||
return RetTmr;
|
||||
|
@ -145,20 +132,20 @@ PTIMER
|
|||
FASTCALL
|
||||
FindSystemTimer(PMSG pMsg)
|
||||
{
|
||||
PLIST_ENTRY pLE;
|
||||
PTIMER pTmr = FirstpTmr;
|
||||
PLIST_ENTRY pLE = TimersListHead.Flink;
|
||||
PTIMER pTmr = NULL;
|
||||
|
||||
TimerEnterExclusive();
|
||||
do
|
||||
while (pLE != &TimersListHead)
|
||||
{
|
||||
if (!pTmr) break;
|
||||
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
|
||||
|
||||
if ( pMsg->lParam == (LPARAM)pTmr->pfn &&
|
||||
(pTmr->flags & TMRF_SYSTEM) )
|
||||
break;
|
||||
|
||||
pLE = pTmr->ptmrList.Flink;
|
||||
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
|
||||
} while (pTmr != FirstpTmr);
|
||||
pLE = pLE->Flink;
|
||||
}
|
||||
TimerLeave();
|
||||
|
||||
return pTmr;
|
||||
|
@ -169,15 +156,14 @@ FASTCALL
|
|||
ValidateTimerCallback(PTHREADINFO pti,
|
||||
LPARAM lParam)
|
||||
{
|
||||
PLIST_ENTRY pLE;
|
||||
PLIST_ENTRY pLE = TimersListHead.Flink;
|
||||
BOOL Ret = FALSE;
|
||||
PTIMER pTmr = FirstpTmr;
|
||||
|
||||
if (!pTmr) return FALSE;
|
||||
PTIMER pTmr;
|
||||
|
||||
TimerEnterExclusive();
|
||||
do
|
||||
while (pLE != &TimersListHead)
|
||||
{
|
||||
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
|
||||
if ( (lParam == (LPARAM)pTmr->pfn) &&
|
||||
!(pTmr->flags & (TMRF_SYSTEM|TMRF_RIT)) &&
|
||||
(pTmr->pti->ppi == pti->ppi) )
|
||||
|
@ -185,9 +171,8 @@ ValidateTimerCallback(PTHREADINFO pti,
|
|||
Ret = TRUE;
|
||||
break;
|
||||
}
|
||||
pLE = pTmr->ptmrList.Flink;
|
||||
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
|
||||
} while (pTmr != FirstpTmr);
|
||||
pLE = pLE->Flink;
|
||||
}
|
||||
TimerLeave();
|
||||
|
||||
return Ret;
|
||||
|
@ -286,7 +271,7 @@ IntSetTimer( PWND Window,
|
|||
|
||||
ASSERT(MasterTimer != NULL);
|
||||
// Start the timer thread!
|
||||
if (pTmr == FirstpTmr)
|
||||
if (TimersListHead.Flink == TimersListHead.Blink) // There is only one timer
|
||||
KeSetTimer(MasterTimer, DueTime, NULL);
|
||||
|
||||
return Ret;
|
||||
|
@ -334,22 +319,21 @@ BOOL
|
|||
FASTCALL
|
||||
PostTimerMessages(PWND Window)
|
||||
{
|
||||
PLIST_ENTRY pLE;
|
||||
PLIST_ENTRY pLE = TimersListHead.Flink;
|
||||
PUSER_MESSAGE_QUEUE ThreadQueue;
|
||||
MSG Msg;
|
||||
PTHREADINFO pti;
|
||||
BOOL Hit = FALSE;
|
||||
PTIMER pTmr = FirstpTmr;
|
||||
|
||||
if (!pTmr) return FALSE;
|
||||
PTIMER pTmr;
|
||||
|
||||
pti = PsGetCurrentThreadWin32Thread();
|
||||
ThreadQueue = pti->MessageQueue;
|
||||
|
||||
TimerEnterExclusive();
|
||||
|
||||
do
|
||||
while(pLE != &TimersListHead)
|
||||
{
|
||||
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
|
||||
if ( (pTmr->flags & TMRF_READY) &&
|
||||
(pTmr->pti == pti) &&
|
||||
((pTmr->pWnd == Window) || (Window == NULL)) )
|
||||
|
@ -366,9 +350,8 @@ PostTimerMessages(PWND Window)
|
|||
break;
|
||||
}
|
||||
|
||||
pLE = pTmr->ptmrList.Flink;
|
||||
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
|
||||
} while (pTmr != FirstpTmr);
|
||||
pLE = pLE->Flink;
|
||||
}
|
||||
|
||||
TimerLeave();
|
||||
|
||||
|
@ -381,12 +364,10 @@ ProcessTimers(VOID)
|
|||
{
|
||||
LARGE_INTEGER TickCount, DueTime;
|
||||
LONG Time;
|
||||
PLIST_ENTRY pLE;
|
||||
PTIMER pTmr = FirstpTmr;
|
||||
PLIST_ENTRY pLE = TimersListHead.Flink;
|
||||
PTIMER pTmr;
|
||||
LONG TimerCount = 0;
|
||||
|
||||
if (!pTmr) return;
|
||||
|
||||
TimerEnterExclusive();
|
||||
|
||||
KeQueryTickCount(&TickCount);
|
||||
|
@ -394,8 +375,9 @@ ProcessTimers(VOID)
|
|||
|
||||
DueTime.QuadPart = (LONGLONG)(-500000);
|
||||
|
||||
do
|
||||
while(pLE != &TimersListHead)
|
||||
{
|
||||
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
|
||||
TimerCount++;
|
||||
if (pTmr->flags & TMRF_WAITING)
|
||||
{
|
||||
|
@ -440,9 +422,8 @@ ProcessTimers(VOID)
|
|||
pTmr->cmsCountdown -= Time - TimeLast;
|
||||
}
|
||||
|
||||
pLE = pTmr->ptmrList.Flink;
|
||||
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
|
||||
} while (pTmr != FirstpTmr);
|
||||
pLE = pLE->Flink;
|
||||
}
|
||||
|
||||
// Restart the timer thread!
|
||||
ASSERT(MasterTimer != NULL);
|
||||
|
@ -457,24 +438,24 @@ ProcessTimers(VOID)
|
|||
BOOL FASTCALL
|
||||
DestroyTimersForWindow(PTHREADINFO pti, PWND Window)
|
||||
{
|
||||
PLIST_ENTRY pLE;
|
||||
PTIMER pTmr = FirstpTmr;
|
||||
PLIST_ENTRY pLE = TimersListHead.Flink;
|
||||
PTIMER pTmr;
|
||||
BOOL TimersRemoved = FALSE;
|
||||
|
||||
if ((FirstpTmr == NULL) || (Window == NULL))
|
||||
if ((Window == NULL))
|
||||
return FALSE;
|
||||
|
||||
TimerEnterExclusive();
|
||||
|
||||
do
|
||||
while(pLE != &TimersListHead)
|
||||
{
|
||||
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
|
||||
pLE = pLE->Flink; /* get next timer list entry before current timer is removed */
|
||||
if ((pTmr) && (pTmr->pti == pti) && (pTmr->pWnd == Window))
|
||||
{
|
||||
TimersRemoved = RemoveTimer(pTmr);
|
||||
}
|
||||
pLE = pTmr->ptmrList.Flink;
|
||||
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
|
||||
} while (pTmr != FirstpTmr);
|
||||
}
|
||||
|
||||
TimerLeave();
|
||||
|
||||
|
@ -484,24 +465,21 @@ DestroyTimersForWindow(PTHREADINFO pti, PWND Window)
|
|||
BOOL FASTCALL
|
||||
DestroyTimersForThread(PTHREADINFO pti)
|
||||
{
|
||||
PLIST_ENTRY pLE;
|
||||
PTIMER pTmr = FirstpTmr;
|
||||
PLIST_ENTRY pLE = TimersListHead.Flink;
|
||||
PTIMER pTmr;
|
||||
BOOL TimersRemoved = FALSE;
|
||||
|
||||
if (FirstpTmr == NULL)
|
||||
return FALSE;
|
||||
|
||||
TimerEnterExclusive();
|
||||
|
||||
do
|
||||
while(pLE != &TimersListHead)
|
||||
{
|
||||
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
|
||||
pLE = pLE->Flink; /* get next timer list entry before current timer is removed */
|
||||
if ((pTmr) && (pTmr->pti == pti))
|
||||
{
|
||||
TimersRemoved = RemoveTimer(pTmr);
|
||||
}
|
||||
pLE = pTmr->ptmrList.Flink;
|
||||
pTmr = CONTAINING_RECORD(pLE, TIMER, ptmrList);
|
||||
} while (pTmr != FirstpTmr);
|
||||
}
|
||||
|
||||
TimerLeave();
|
||||
|
||||
|
@ -550,6 +528,9 @@ InitTimerImpl(VOID)
|
|||
/* yes we need this, since ExAllocatePoolWithTag isn't supposed to zero out allocated memory */
|
||||
RtlClearAllBits(&WindowLessTimersBitMap);
|
||||
|
||||
ExInitializeResourceLite(&TimerLock);
|
||||
InitializeListHead(&TimersListHead);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue