diff --git a/base/shell/explorer-new/traywnd.c b/base/shell/explorer-new/traywnd.c index 926e435eb09..e041d609ffe 100644 --- a/base/shell/explorer-new/traywnd.c +++ b/base/shell/explorer-new/traywnd.c @@ -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, diff --git a/dll/cpl/desk/appearance.c b/dll/cpl/desk/appearance.c index 2c23b3cc614..65e9ad6890a 100644 --- a/dll/cpl/desk/appearance.c +++ b/dll/cpl/desk/appearance.c @@ -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; diff --git a/dll/cpl/desk/theme.c b/dll/cpl/desk/theme.c index 04cebd51b73..bdedc662f07 100644 --- a/dll/cpl/desk/theme.c +++ b/dll/cpl/desk/theme.c @@ -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); diff --git a/dll/win32/kernel32/file/dir.c b/dll/win32/kernel32/file/dir.c index c1de9c0b987..a364e6a1f46 100644 --- a/dll/win32/kernel32/file/dir.c +++ b/dll/win32/kernel32/file/dir.c @@ -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); } diff --git a/dll/win32/kernel32/file/file.c b/dll/win32/kernel32/file/file.c index 24e4e47ba45..b79bc2b9876 100644 --- a/dll/win32/kernel32/file/file.c +++ b/dll/win32/kernel32/file/file.c @@ -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 */ diff --git a/dll/win32/wdmaud.drv/legacy.c b/dll/win32/wdmaud.drv/legacy.c index 88df5b2c080..45007d81164 100644 --- a/dll/win32/wdmaud.drv/legacy.c +++ b/dll/win32/wdmaud.drv/legacy.c @@ -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; diff --git a/dll/win32/wdmaud.drv/mmixer.c b/dll/win32/wdmaud.drv/mmixer.c index a3a021ce29d..a98418aa792 100644 --- a/dll/win32/wdmaud.drv/mmixer.c +++ b/dll/win32/wdmaud.drv/mmixer.c @@ -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; } diff --git a/dll/win32/wdmaud.drv/wdmaud.h b/dll/win32/wdmaud.drv/wdmaud.h index 26a2aead84c..87936508798 100644 --- a/dll/win32/wdmaud.drv/wdmaud.h +++ b/dll/win32/wdmaud.drv/wdmaud.h @@ -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); diff --git a/drivers/filesystems/npfs/dirctl.c b/drivers/filesystems/npfs/dirctl.c index 2fbfbd4fa4d..ef7b1317774 100644 --- a/drivers/filesystems/npfs/dirctl.c +++ b/drivers/filesystems/npfs/dirctl.c @@ -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; diff --git a/drivers/filesystems/npfs/npfs.h b/drivers/filesystems/npfs/npfs.h index 0049fd3fdac..b5435859641 100644 --- a/drivers/filesystems/npfs/npfs.h +++ b/drivers/filesystems/npfs/npfs.h @@ -5,6 +5,12 @@ #include #include +#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, diff --git a/drivers/ksfilter/CMakeLists.txt b/drivers/ksfilter/CMakeLists.txt index 6a8aaa161ee..521247b7157 100644 --- a/drivers/ksfilter/CMakeLists.txt +++ b/drivers/ksfilter/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(ks) +add_subdirectory(swenum) \ No newline at end of file diff --git a/drivers/ksfilter/ks/CMakeLists.txt b/drivers/ksfilter/ks/CMakeLists.txt index bd19acd1136..a4888e7cf76 100644 --- a/drivers/ksfilter/ks/CMakeLists.txt +++ b/drivers/ksfilter/ks/CMakeLists.txt @@ -27,6 +27,7 @@ list(APPEND SOURCE unknown.c worker.c kcom.c + swenum.c ks.rc ${CMAKE_CURRENT_BINARY_DIR}/ks.def) diff --git a/drivers/ksfilter/ks/allocators.c b/drivers/ksfilter/ks/allocators.c index 5a4970f1b58..b3fbbbe20d5 100644 --- a/drivers/ksfilter/ks/allocators.c +++ b/drivers/ksfilter/ks/allocators.c @@ -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; } diff --git a/drivers/ksfilter/ks/api.c b/drivers/ksfilter/ks/api.c index 64c341c20b3..3a037bfa168 100644 --- a/drivers/ksfilter/ks/api.c +++ b/drivers/ksfilter/ks/api.c @@ -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 */ diff --git a/drivers/ksfilter/ks/clocks.c b/drivers/ksfilter/ks/clocks.c index 05064be740a..2e3f03f0b55 100644 --- a/drivers/ksfilter/ks/clocks.c +++ b/drivers/ksfilter/ks/clocks.c @@ -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; } diff --git a/drivers/ksfilter/ks/device.c b/drivers/ksfilter/ks/device.c index 432548c6d91..49d5787820e 100644 --- a/drivers/ksfilter/ks/device.c +++ b/drivers/ksfilter/ks/device.c @@ -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; diff --git a/drivers/ksfilter/ks/filter.c b/drivers/ksfilter/ks/filter.c index 5f4a74b9b64..1e6ebbf661e 100644 --- a/drivers/ksfilter/ks/filter.c +++ b/drivers/ksfilter/ks/filter.c @@ -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; } /* diff --git a/drivers/ksfilter/ks/filterfactory.c b/drivers/ksfilter/ks/filterfactory.c index e60bfc41e81..51c9a65d273 100644 --- a/drivers/ksfilter/ks/filterfactory.c +++ b/drivers/ksfilter/ks/filterfactory.c @@ -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; diff --git a/drivers/ksfilter/ks/irp.c b/drivers/ksfilter/ks/irp.c index fb36d6df78a..b3c67e7ff6a 100644 --- a/drivers/ksfilter/ks/irp.c +++ b/drivers/ksfilter/ks/irp.c @@ -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; diff --git a/drivers/ksfilter/ks/ksfunc.h b/drivers/ksfilter/ks/ksfunc.h index 6a4d85df867..1c51a8c1c80 100644 --- a/drivers/ksfilter/ks/ksfunc.h +++ b/drivers/ksfilter/ks/ksfunc.h @@ -6,6 +6,13 @@ #define TAG_KSDEVICE 'DESK' #define TAG_KSOBJECT_TAG 'HOSK' +VOID +CompleteRequest( + PIRP Irp, + CCHAR PriorityBoost); + + + NTSTATUS NTAPI KspCreateObjectType( diff --git a/drivers/ksfilter/ks/ksiface.h b/drivers/ksfilter/ks/ksiface.h index ad95fc9a922..f5e388887ba 100644 --- a/drivers/ksfilter/ks/ksiface.h +++ b/drivers/ksfilter/ks/ksiface.h @@ -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 + diff --git a/drivers/ksfilter/ks/kstypes.h b/drivers/ksfilter/ks/kstypes.h index 0e64312e095..0be5956264c 100644 --- a/drivers/ksfilter/ks/kstypes.h +++ b/drivers/ksfilter/ks/kstypes.h @@ -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; diff --git a/drivers/ksfilter/ks/misc.c b/drivers/ksfilter/ks/misc.c index 057103d3414..9ba4b2611b5 100644 --- a/drivers/ksfilter/ks/misc.c +++ b/drivers/ksfilter/ks/misc.c @@ -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, diff --git a/drivers/ksfilter/ks/pin.c b/drivers/ksfilter/ks/pin.c index a6caeb30de0..883f098b43d 100644 --- a/drivers/ksfilter/ks/pin.c +++ b/drivers/ksfilter/ks/pin.c @@ -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; } diff --git a/drivers/ksfilter/ks/priv.h b/drivers/ksfilter/ks/priv.h index 75b514158cc..8eb1959c288 100644 --- a/drivers/ksfilter/ks/priv.h +++ b/drivers/ksfilter/ks/priv.h @@ -19,6 +19,8 @@ #include "ksmedia.h" #include "bdamedia.h" +#include + #define TAG_DEVICE_HEADER 'KSDH' #define REG_PINFLAG_B_MANY 0x4 /* strmif.h */ diff --git a/drivers/ksfilter/ks/swenum.c b/drivers/ksfilter/ks/swenum.c new file mode 100644 index 00000000000..08d5286bd58 --- /dev/null +++ b/drivers/ksfilter/ks/swenum.c @@ -0,0 +1,2174 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Kernel Streaming + * FILE: drivers/ksfilter/ks/swenum.c + * PURPOSE: KS Software BUS functions + * PROGRAMMER: Johannes Anderwald + */ + + +#include "priv.h" + +LONG KsDeviceCount = 0; + +typedef NTSTATUS (NTAPI *PKSP_BUS_ENUM_CALLBACK)( + IN PHANDLE hKey, + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, + IN PBUS_DEVICE_ENTRY DummyEntry, + IN LPWSTR RootName, + IN LPWSTR DirectoryName); + +NTSTATUS +KspCreatePDO( + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, + IN PBUS_DEVICE_ENTRY DeviceEntry, + OUT PDEVICE_OBJECT * OutDeviceObject) +{ + PDEVICE_OBJECT DeviceObject; + WCHAR Buffer[50]; + ULONG CurDeviceId; + UNICODE_STRING DeviceName; + NTSTATUS Status; + PCOMMON_DEVICE_EXTENSION DeviceExtension; + + /* increment device count */ + CurDeviceId = InterlockedIncrement(&KsDeviceCount); + + /* generate new device id */ + swprintf(Buffer, L"\\Device\\KSENUM%08x", CurDeviceId); + + /* initialize new device name */ + RtlInitUnicodeString(&DeviceName, Buffer); + + /* create new device object */ + Status = IoCreateDevice(BusDeviceExtension->BusDeviceObject->DriverObject, sizeof(PVOID), &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject); + + /* check for success */ + if (!NT_SUCCESS(Status)) + { + /* failed to create pdo */ + return Status; + } + + /* now allocate device extension */ + DeviceExtension = (PCOMMON_DEVICE_EXTENSION)AllocateItem(NonPagedPool, sizeof(COMMON_DEVICE_EXTENSION)); + if (!DeviceExtension) + { + /* no memory */ + IoDeleteDevice(DeviceObject); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* store device extension */ + *((PVOID*)DeviceObject->DeviceExtension) = DeviceExtension; + + /* initialize device extension */ + DeviceExtension->IsBus = FALSE; + DeviceExtension->DeviceObject = DeviceObject; + DeviceExtension->DeviceEntry = DeviceEntry; + DeviceExtension->BusDeviceExtension = BusDeviceExtension; + + /* TODO: update last creation time in bus device extension */ + + /* setup flags */ + DeviceObject->Flags |= DO_POWER_PAGABLE; + DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING; + /* TODO: fire time when expired */ + + *OutDeviceObject = DeviceObject; + + return STATUS_SUCCESS; +} + +NTSTATUS +KspRegisterDeviceAssociation( + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, + IN PBUS_DEVICE_ENTRY DeviceEntry, + IN OUT PBUS_INSTANCE_ENTRY BusInstanceEntry) +{ + NTSTATUS Status; + UNICODE_STRING ReferenceString; + + /* initialize reference string */ + RtlInitUnicodeString(&ReferenceString, DeviceEntry->DeviceName); + + /* register device interface */ + Status = IoRegisterDeviceInterface(BusDeviceExtension->PhysicalDeviceObject, &BusInstanceEntry->InterfaceGuid, &ReferenceString, &BusInstanceEntry->SymbolicLink); + + /* check for success */ + if (!NT_SUCCESS(Status)) + { + /* failed */ + return Status; + } + + /* now enable the interface */ + Status = IoSetDeviceInterfaceState(&BusInstanceEntry->SymbolicLink, TRUE); + + /* check for success */ + if (!NT_SUCCESS(Status)) + { + /* failed, free memory */ + FreeItem(BusInstanceEntry->SymbolicLink.Buffer); + return Status; + } + + DPRINT1("Registered DeviceInterface %wZ\n", &BusInstanceEntry->SymbolicLink); + + + /* done */ + return Status; +} + +VOID +KspRemoveDeviceAssociations( + IN PBUS_DEVICE_ENTRY DeviceEntry) +{ + PLIST_ENTRY Entry; + PBUS_INSTANCE_ENTRY CurEntry; + + /* remove all entries */ + Entry = DeviceEntry->DeviceInterfaceList.Flink; + + while(Entry != &DeviceEntry->DeviceInterfaceList) + { + /* get offset */ + CurEntry = (PBUS_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, BUS_INSTANCE_ENTRY, Entry); + + /* sanity check */ + ASSERT(CurEntry->SymbolicLink.Buffer); + + /* de-register interface */ + IoSetDeviceInterfaceState(&CurEntry->SymbolicLink, FALSE); + + /* free symbolic link buffer */ + FreeItem(CurEntry->SymbolicLink.Buffer); + + /* remove entry from list */ + RemoveEntryList(Entry); + + /* move to next entry */ + Entry = Entry->Flink; + + /* free entry */ + FreeItem(CurEntry); + } +} + +NTSTATUS +KspEnumerateBusRegistryKeys( + IN HANDLE hKey, + IN LPWSTR ReferenceString, + IN PKSP_BUS_ENUM_CALLBACK Callback, + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, + IN PBUS_DEVICE_ENTRY DeviceEntry) +{ + UNICODE_STRING String; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE hNewKey; + NTSTATUS Status; + ULONG ResultLength, Index, KeyInfoLength; + KEY_FULL_INFORMATION KeyInformation; + PKEY_BASIC_INFORMATION KeyInfo; + + /* initialize key name */ + RtlInitUnicodeString(&String, ReferenceString); + + /* initialize object attributes */ + InitializeObjectAttributes(&ObjectAttributes, &String, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hKey, NULL); + + /* open new key */ + Status = ZwOpenKey(&hNewKey, GENERIC_READ, &ObjectAttributes); + + /* check for success */ + if (!NT_SUCCESS(Status)) + { + /* failed to open key */ + + return Status; + } + + /* query key stats */ + Status = ZwQueryKey(hNewKey, KeyFullInformation, &KeyInformation, sizeof(KeyInformation), &ResultLength); + + if (!NT_SUCCESS(Status)) + { + /* close key */ + ZwClose(hNewKey); + + /* done */ + return Status; + } + + /* calculate key info length */ + KeyInfoLength = KeyInformation.MaxNameLen + sizeof(KEY_BASIC_INFORMATION) + 1 * sizeof(WCHAR); + + /* allocate buffer */ + KeyInfo = (PKEY_BASIC_INFORMATION)AllocateItem(NonPagedPool, KeyInfoLength); + if (!KeyInfo) + { + + /* no memory */ + ZwClose(hNewKey); + + /* done */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* enumerate all keys */ + for(Index = 0; Index < KeyInformation.SubKeys; Index++) + { + + /* query sub key */ + Status = ZwEnumerateKey(hNewKey, Index, KeyBasicInformation, (PVOID)KeyInfo, KeyInfoLength, &ResultLength); + + /* check for success */ + if (NT_SUCCESS(Status)) + { + /* perform callback */ + Status = Callback(hNewKey, BusDeviceExtension, DeviceEntry, ReferenceString, KeyInfo->Name); + + /* should enumeration stop */ + if (!NT_SUCCESS(Status)) + break; + } + } + + /* free info buffer */ + FreeItem(KeyInfo); + + /* close key */ + ZwClose(hNewKey); + + /* done */ + return Status; +} + +NTSTATUS +NTAPI +KspCreateDeviceAssociation( + IN PHANDLE hKey, + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, + IN PBUS_DEVICE_ENTRY DeviceEntry, + IN LPWSTR ReferenceString, + IN LPWSTR InterfaceString) +{ + GUID DeviceGuid; + NTSTATUS Status; + PLIST_ENTRY Entry; + PBUS_INSTANCE_ENTRY CurEntry; + UNICODE_STRING DeviceName; + + /* initialize interface string */ + RtlInitUnicodeString(&DeviceName, InterfaceString); + + /* first convert device name to guid */ + RtlGUIDFromString(&DeviceName, &DeviceGuid); + + /* check if the device is already present */ + Entry = DeviceEntry->DeviceInterfaceList.Flink; + + while(Entry != &DeviceEntry->DeviceInterfaceList) + { + /* get offset */ + CurEntry = (PBUS_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, BUS_INSTANCE_ENTRY, Entry); + + if (IsEqualGUIDAligned(&CurEntry->InterfaceGuid, &DeviceGuid)) + { + /* entry already exists */ + return STATUS_SUCCESS; + } + + /* move to next entry */ + Entry = Entry->Flink; + } + + /* time to allocate new entry */ + CurEntry = (PBUS_INSTANCE_ENTRY)AllocateItem(NonPagedPool, sizeof(BUS_INSTANCE_ENTRY)); + + if (!CurEntry) + { + /* no memory */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* store guid */ + RtlMoveMemory(&CurEntry->InterfaceGuid, &DeviceGuid, sizeof(GUID)); + + /* now register the association */ + Status = KspRegisterDeviceAssociation(BusDeviceExtension, DeviceEntry, CurEntry); + + /* check for success */ + if (NT_SUCCESS(Status)) + { + /* store entry */ + InsertTailList(&DeviceEntry->DeviceInterfaceList, &CurEntry->Entry); + } + else + { + /* failed to associated device */ + FreeItem(CurEntry); + } + + /* done */ + return Status; +} + +NTSTATUS +NTAPI +KspCreateDeviceReference( + IN PHANDLE hKey, + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, + IN PBUS_DEVICE_ENTRY DummyEntry, + IN LPWSTR DeviceCategory, + IN LPWSTR ReferenceString) +{ + LPWSTR DeviceName; + ULONG Length; + PLIST_ENTRY Entry; + PBUS_DEVICE_ENTRY DeviceEntry = NULL; /* GCC warning */ + BOOLEAN ItemExists = FALSE; + UNICODE_STRING String; + NTSTATUS Status; + KIRQL OldLevel; + + /* first construct device name & reference guid */ + Length = wcslen(DeviceCategory) + wcslen(ReferenceString); + + /* append '&' and null byte */ + Length += 2; + + /* allocate device name */ + DeviceName = AllocateItem(NonPagedPool, Length * sizeof(WCHAR)); + + if (!DeviceName) + { + /* not enough memory */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* construct device name */ + swprintf(DeviceName, L"%s&%s", DeviceCategory, ReferenceString); + + /* scan list and check if it is already present */ + Entry = BusDeviceExtension->Common.Entry.Flink; + + while(Entry != &BusDeviceExtension->Common.Entry) + { + /* get real offset */ + DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); + + /* check if name matches */ + if (!wcsicmp(DeviceEntry->DeviceName, DeviceName)) + { + /* item already exists */ + ItemExists = TRUE; + break; + } + + /* move to next entry */ + Entry = Entry->Flink; + } + + if (!ItemExists) + { + /* allocate new device entry */ + DeviceEntry = AllocateItem(NonPagedPool, sizeof(BUS_DEVICE_ENTRY)); + if (!DeviceEntry) + { + /* no memory */ + FreeItem(DeviceName); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* initialize device entry */ + InitializeListHead(&DeviceEntry->DeviceInterfaceList); + InitializeListHead(&DeviceEntry->IrpPendingList); + + /* copy device guid */ + RtlInitUnicodeString(&String, ReferenceString); + RtlGUIDFromString(&String, &DeviceEntry->DeviceGuid); + + /* copy device names */ + DeviceEntry->DeviceName = DeviceName; + DeviceEntry->Instance = (DeviceName + wcslen(DeviceCategory) + 1); + + /* copy name */ + DeviceEntry->BusId = AllocateItem(NonPagedPool, (wcslen(DeviceCategory) + 1) * sizeof(WCHAR)); + if (!DeviceEntry->BusId) + { + /* no memory */ + FreeItem(DeviceName); + FreeItem(DeviceEntry); + return STATUS_INSUFFICIENT_RESOURCES; + } + wcscpy(DeviceEntry->BusId, DeviceCategory); + } + + /* now enumerate the devices */ + Status = KspEnumerateBusRegistryKeys(hKey, ReferenceString, KspCreateDeviceAssociation, BusDeviceExtension, DeviceEntry); + + /* check if list is empty */ + if (IsListEmpty(&DeviceEntry->DeviceInterfaceList)) + { + /* invalid device settings */ + FreeItem(DeviceEntry->BusId); + FreeItem(DeviceEntry->DeviceName); + FreeItem(DeviceEntry); + + ASSERT(ItemExists == FALSE); + + return STATUS_INVALID_DEVICE_STATE; + } + + /* check if enumeration failed */ + if (!NT_SUCCESS(Status)) + { + /* failed */ + KspRemoveDeviceAssociations(DeviceEntry); + FreeItem(DeviceEntry->BusId); + FreeItem(DeviceEntry->DeviceName); + FreeItem(DeviceEntry); + + ASSERT(ItemExists == FALSE); + + /* done */ + return Status; + } + + if (!ItemExists) + { + /* acquire lock */ + KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); + + /* successfully initialized entry */ + InsertTailList(&BusDeviceExtension->Common.Entry, &DeviceEntry->Entry); + + /* release lock */ + KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); + } + + /* done */ + return Status; +} + +NTSTATUS +NTAPI +KspCreateDeviceReferenceTrampoline( + IN PHANDLE hKey, + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, + IN PBUS_DEVICE_ENTRY DummyEntry, + IN LPWSTR DeviceCategory, + IN LPWSTR ReferenceString) +{ + return KspEnumerateBusRegistryKeys(hKey, ReferenceString, KspCreateDeviceReference, BusDeviceExtension, DummyEntry); +} + + +NTSTATUS +KspOpenBusRegistryKey( + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, + OUT PHANDLE hKey) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + + /* initialize object attributes */ + InitializeObjectAttributes(&ObjectAttributes, &BusDeviceExtension->ServicePath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); + + return ZwCreateKey(hKey, GENERIC_READ | GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL); +} + +NTSTATUS +KspScanBus( + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension) +{ + HANDLE hKey; + NTSTATUS Status; + + /* first open key */ + Status = KspOpenBusRegistryKey(BusDeviceExtension, &hKey); + + /* check for success */ + if (!NT_SUCCESS(Status)) + { + /* no success */ + + return Status; + } + + /* TODO clear reference marks */ + + /* construct device entries */ + Status = KspEnumerateBusRegistryKeys(hKey, NULL, KspCreateDeviceReferenceTrampoline, BusDeviceExtension, NULL); + + /* TODO: delete unreferenced devices */ + + /* close handle */ + ZwClose(hKey); + + /* done */ + return Status; +} + + +NTSTATUS +NTAPI +KspBusQueryReferenceString( + IN PVOID Context, + IN OUT PWCHAR *String) +{ + LPWSTR Name; + ULONG Length; + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)Context; + + /* sanity checks */ + ASSERT(BusDeviceExtension); + ASSERT(BusDeviceExtension->BusIdentifier); + + /* calculate length */ + Length = wcslen(BusDeviceExtension->BusIdentifier) + 1; + + /* allocate buffer */ + Name = AllocateItem(PagedPool, Length * sizeof(WCHAR)); + + if (!Name) + { + /* failed to allocate buffer */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* copy buffer */ + wcscpy(Name, BusDeviceExtension->BusIdentifier); + + /* store result */ + *String = Name; + + /* done */ + return STATUS_SUCCESS; +} + +VOID +NTAPI +KspBusDeviceReference( + IN PVOID Context) +{ + PCOMMON_DEVICE_EXTENSION ChildDeviceExtension = (PCOMMON_DEVICE_EXTENSION)Context; + + /* reference count */ + InterlockedIncrement((PLONG)&ChildDeviceExtension->DeviceReferenceCount); +} + +VOID +NTAPI +KspBusDeviceDereference( + IN PVOID Context) +{ + PCOMMON_DEVICE_EXTENSION ChildDeviceExtension = (PCOMMON_DEVICE_EXTENSION)Context; + + /* reference count */ + InterlockedDecrement((PLONG)&ChildDeviceExtension->DeviceReferenceCount); +} + +VOID +NTAPI +KspBusReferenceDeviceObject( + IN PVOID Context) +{ + PCOMMON_DEVICE_EXTENSION ChildDeviceExtension = (PCOMMON_DEVICE_EXTENSION)Context; + + /* reference count */ + InterlockedIncrement((PLONG)&ChildDeviceExtension->DeviceObjectReferenceCount); +} + +VOID +NTAPI +KspBusDereferenceDeviceObject( + IN PVOID Context) +{ + PCOMMON_DEVICE_EXTENSION ChildDeviceExtension = (PCOMMON_DEVICE_EXTENSION)Context; + + /* reference count */ + InterlockedDecrement((PLONG)&ChildDeviceExtension->DeviceObjectReferenceCount); +} + +NTSTATUS +KspQueryBusDeviceInterface( + IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, + IN PIRP Irp) +{ + PBUS_INTERFACE_SWENUM Interface; + PIO_STACK_LOCATION IoStack; + + /* get current irp stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* sanity checks */ + ASSERT(IoStack->Parameters.QueryInterface.Size == sizeof(BUS_INTERFACE_SWENUM)); + ASSERT(IoStack->Parameters.QueryInterface.Interface); + + /* fill in interface */ + Interface = (PBUS_INTERFACE_SWENUM)IoStack->Parameters.QueryInterface.Interface; + Interface->Interface.Size = sizeof(BUS_INTERFACE_SWENUM); + Interface->Interface.Version = BUS_INTERFACE_SWENUM_VERSION; + Interface->Interface.Context = ChildDeviceExtension; + Interface->Interface.InterfaceReference = KspBusDeviceReference; + Interface->Interface.InterfaceDereference = KspBusDeviceDereference; + Interface->ReferenceDeviceObject = KspBusReferenceDeviceObject; + Interface->DereferenceDeviceObject = KspBusDereferenceDeviceObject; + Interface->QueryReferenceString = KspBusQueryReferenceString; + + return STATUS_SUCCESS; +} + +NTSTATUS +KspEnableBusDeviceInterface( + PBUS_DEVICE_ENTRY DeviceEntry, + BOOLEAN bEnable) +{ + PLIST_ENTRY Entry; + PBUS_INSTANCE_ENTRY InstanceEntry; + NTSTATUS Status = STATUS_SUCCESS; + + /* enable now all interfaces */ + Entry = DeviceEntry->DeviceInterfaceList.Flink; + + while(Entry != &DeviceEntry->DeviceInterfaceList) + { + /* get bus instance entry */ + InstanceEntry = (PBUS_INSTANCE_ENTRY)CONTAINING_RECORD(Entry, BUS_INSTANCE_ENTRY, Entry); + DPRINT1("Enabling %u %wZ Irql %u\n", bEnable, &InstanceEntry->SymbolicLink, KeGetCurrentIrql()); + + /* set interface state */ + Status = IoSetDeviceInterfaceState(&InstanceEntry->SymbolicLink, bEnable); + + if (!NT_SUCCESS(Status)) + { + /* failed to set interface */ + break; + } + + /* move to next entry */ + Entry = Entry->Flink; + } + + /* done */ + return Status; +} + +NTSTATUS +KspDoReparseForIrp( + PIRP Irp, + PBUS_DEVICE_ENTRY DeviceEntry) +{ + ULONG Length; + LPWSTR Buffer; + PIO_STACK_LOCATION IoStack; + + /* get stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* sanity checks */ + ASSERT(DeviceEntry->PDODeviceName); + ASSERT(DeviceEntry->Instance); + ASSERT(IoStack->FileObject); + ASSERT(IoStack->FileObject->FileName.Buffer); + + /* calculate length */ + Length = wcslen(DeviceEntry->PDODeviceName); + Length += wcslen(DeviceEntry->Instance); + + /* zero byte and '\\' */ + Length += 2; + + /* allocate buffer */ + Buffer = AllocateItem(NonPagedPool, Length * sizeof(WCHAR)); + if (!Buffer) + { + /* no resources */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* construct buffer */ + swprintf(Buffer, L"%s\\%s", DeviceEntry->PDODeviceName, DeviceEntry->Instance); + + ExFreePool(IoStack->FileObject->FileName.Buffer); + + /* store new file name */ + RtlInitUnicodeString(&IoStack->FileObject->FileName, Buffer); + + /* done */ + return STATUS_REPARSE; +} + +VOID +KspCompletePendingIrps( + IN PBUS_DEVICE_ENTRY DeviceEntry, + IN OUT NTSTATUS ResultCode) +{ + PLIST_ENTRY Entry; + PIRP Irp; + NTSTATUS Status; + + /* go through list */ + while(!IsListEmpty(&DeviceEntry->IrpPendingList)) + { + /* get first entry */ + Entry = RemoveHeadList(&DeviceEntry->IrpPendingList); + + /* get irp */ + Irp = (PIRP)CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry); + + if (ResultCode == STATUS_REPARSE) + { + /* construct reparse information */ + Status = KspDoReparseForIrp(Irp, DeviceEntry); + } + else + { + /* use default code */ + Status = ResultCode; + } + + /* store result code */ + Irp->IoStatus.Status = Status; + + DPRINT1("Completing IRP %p Status %x\n", Irp, Status); + + /* complete the request */ + CompleteRequest(Irp, IO_NO_INCREMENT); + } + +} + + + +NTSTATUS +KspStartBusDevice( + IN PDEVICE_OBJECT DeviceObject, + IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, + IN PIRP Irp) +{ + WCHAR PDOName[256]; + NTSTATUS Status; + ULONG ResultLength; + LPWSTR Name; + PBUS_DEVICE_ENTRY DeviceEntry; + + /* FIXME handle pending remove */ + + /* get full device name */ + Status = IoGetDeviceProperty(DeviceObject, DevicePropertyPhysicalDeviceObjectName, sizeof(PDOName), (PVOID)PDOName, &ResultLength); + + if (!NT_SUCCESS(Status)) + { + /* failed to get device name */ + return Status; + } + + /* allocate device name buffer */ + Name = AllocateItem(NonPagedPool, (ResultLength + 1) * sizeof(WCHAR)); + if (!Name) + { + /* no memory */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* copy name */ + wcscpy(Name, PDOName); + + /* TODO: time stamp creation time */ + + /* get device entry */ + DeviceEntry = (PBUS_DEVICE_ENTRY)ChildDeviceExtension->DeviceEntry; + + /* sanity check */ + ASSERT(DeviceEntry); + + /* store device name */ + DeviceEntry->PDODeviceName = Name; + + /* mark device as started */ + DeviceEntry->DeviceState = Started; + + /* reference start time */ + KeQuerySystemTime(&DeviceEntry->TimeCreated); + + DPRINT1("KspStartBusDevice Name %S DeviceName %S Instance %S Started\n", Name, DeviceEntry->DeviceName, DeviceEntry->Instance); + + /* enable device classes */ + //KspEnableBusDeviceInterface(DeviceEntry, TRUE); + + /* done */ + return STATUS_SUCCESS; +} + +NTSTATUS +KspQueryBusDeviceCapabilities( + IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, + IN PIRP Irp) +{ + PDEVICE_CAPABILITIES Capabilities; + PIO_STACK_LOCATION IoStack; + + /* get stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* get capabilities */ + Capabilities = IoStack->Parameters.DeviceCapabilities.Capabilities; + + RtlZeroMemory(Capabilities, sizeof(DEVICE_CAPABILITIES)); + + /* setup capabilities */ + Capabilities->UniqueID = TRUE; + Capabilities->SilentInstall = TRUE; + Capabilities->SurpriseRemovalOK = TRUE; + Capabilities->Address = 0; + Capabilities->UINumber = 0; + Capabilities->SystemWake = PowerSystemWorking; /* FIXME common device extension */ + Capabilities->DeviceWake = PowerDeviceD0; + + /* done */ + return STATUS_SUCCESS; +} + +NTSTATUS +KspQueryBusInformation( + IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, + IN PIRP Irp) +{ + PPNP_BUS_INFORMATION BusInformation; + + /* allocate bus information */ + BusInformation = (PPNP_BUS_INFORMATION)AllocateItem(PagedPool, sizeof(PNP_BUS_INFORMATION)); + + if (!BusInformation) + { + /* no memory */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* return info */ + BusInformation->BusNumber = 0; + BusInformation->LegacyBusType = InterfaceTypeUndefined; + RtlMoveMemory(&BusInformation->BusTypeGuid, &KSMEDIUMSETID_Standard, sizeof(GUID)); + + /* store result */ + Irp->IoStatus.Information = (ULONG_PTR)BusInformation; + + /* done */ + return STATUS_SUCCESS; +} + +NTSTATUS +KspQueryBusDevicePnpState( + IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, + IN PIRP Irp) +{ + /* set device flags */ + Irp->IoStatus.Information = PNP_DEVICE_DONT_DISPLAY_IN_UI | PNP_DEVICE_NOT_DISABLEABLE; + + /* done */ + return STATUS_SUCCESS; +} + +NTSTATUS +KspQueryId( + IN PCOMMON_DEVICE_EXTENSION ChildDeviceExtension, + IN PIRP Irp) +{ + PIO_STACK_LOCATION IoStack; + PBUS_DEVICE_ENTRY DeviceEntry; + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; + LPWSTR Name; + ULONG Length; + + /* get current irp stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + if (IoStack->Parameters.QueryId.IdType == BusQueryInstanceID) + { + /* get device entry */ + DeviceEntry = (PBUS_DEVICE_ENTRY) ChildDeviceExtension->DeviceEntry; + + /* sanity check */ + ASSERT(DeviceEntry); + ASSERT(DeviceEntry->Instance); + + /* calculate length */ + Length = wcslen(DeviceEntry->Instance) + 1; + + /* allocate buffer */ + Name = AllocateItem(PagedPool, Length * sizeof(WCHAR)); + + if (!Name) + { + /* failed to allocate buffer */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* copy buffer */ + wcscpy(Name, DeviceEntry->Instance); + + /* store result */ + Irp->IoStatus.Information = (ULONG_PTR)Name; + + /* done */ + return STATUS_SUCCESS; + } + else if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID || + IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs) + { + /* get device entry */ + DeviceEntry = (PBUS_DEVICE_ENTRY) ChildDeviceExtension->DeviceEntry; + + /* get bus device extension */ + BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION) ChildDeviceExtension->BusDeviceExtension; + + /* sanity check */ + ASSERT(DeviceEntry); + ASSERT(DeviceEntry->BusId); + ASSERT(BusDeviceExtension); + ASSERT(BusDeviceExtension->BusIdentifier); + + /* calculate length */ + Length = wcslen(BusDeviceExtension->BusIdentifier); + Length += wcslen(DeviceEntry->BusId); + + /* extra length for '\\' and zero byte */ + Length += 2; + + /* allocate buffer */ + Name = ExAllocatePool(PagedPool, Length * sizeof(WCHAR)); + if (!Name) + { + /* failed to allocate buffer */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* construct id */ + swprintf(Name, L"%s\\%s", BusDeviceExtension->BusIdentifier, DeviceEntry->BusId); + + /* store result */ + Irp->IoStatus.Information = (ULONG_PTR)Name; + + /* done */ + return STATUS_SUCCESS; + } + else + { + /* other ids are not supported */ + //DPRINT1("Not Supported ID Type %x\n", IoStack->Parameters.QueryId.IdType); + return Irp->IoStatus.Status; + } +} + +NTSTATUS +KspInstallInterface( + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, + IN PSWENUM_INSTALL_INTERFACE InstallInterface) +{ + ULONG Length, Index; + UNICODE_STRING DeviceString, InterfaceString, ReferenceString; + HANDLE hKey, hDeviceKey, hInterfaceKey, hReferenceKey; + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + + /* sanity check */ + ASSERT(InstallInterface); + + /* calculate length */ + Length = wcslen(InstallInterface->ReferenceString); + + /* check for invalid characters */ + for(Index = 0; Index < Length; Index++) + { + if (InstallInterface->ReferenceString[Index] <= L' ' || + InstallInterface->ReferenceString[Index] > L'~' || + InstallInterface->ReferenceString[Index] == L',' || + InstallInterface->ReferenceString[Index] == L'\\' || + InstallInterface->ReferenceString[Index] == L'/') + { + /* invalid character */ + return STATUS_INVALID_PARAMETER; + } + } + + /* open bus key */ + Status = KspOpenBusRegistryKey(BusDeviceExtension, &hKey); + if (NT_SUCCESS(Status)) + { + /* convert device guid to string */ + Status = RtlStringFromGUID(&InstallInterface->DeviceId, &DeviceString); + if (NT_SUCCESS(Status)) + { + /* initialize object attributes */ + InitializeObjectAttributes(&ObjectAttributes, &DeviceString, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hKey, NULL); + + /* construct device key */ + Status = ZwCreateKey(&hDeviceKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL); + if (NT_SUCCESS(Status)) + { + /* initialize reference string */ + RtlInitUnicodeString(&ReferenceString, InstallInterface->ReferenceString); + + /* initialize object attributes */ + InitializeObjectAttributes(&ObjectAttributes, &ReferenceString, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hDeviceKey, NULL); + + /* construct device key */ + Status = ZwCreateKey(&hReferenceKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL); + if (NT_SUCCESS(Status)) + { + /* convert interface guid to string */ + Status = RtlStringFromGUID(&InstallInterface->InterfaceId, &InterfaceString); + if (NT_SUCCESS(Status)) + { + /* initialize object attributes */ + InitializeObjectAttributes(&ObjectAttributes, &InterfaceString, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hReferenceKey, NULL); + + /* construct device key */ + Status = ZwCreateKey(&hInterfaceKey, GENERIC_WRITE, &ObjectAttributes, 0, NULL, 0, NULL); + if (NT_SUCCESS(Status)) + { + /* close key */ + ZwClose(hInterfaceKey); + } + /* free interface string */ + RtlFreeUnicodeString(&InterfaceString); + } + /* close reference key */ + ZwClose(hReferenceKey); + } + /* close device key */ + ZwClose(hDeviceKey); + } + /* free device string */ + RtlFreeUnicodeString(&DeviceString); + } + /* close bus key */ + ZwClose(hKey); + } + + /* done */ + return Status; + } + +VOID +NTAPI +KspInstallBusEnumInterface( + IN PVOID Ctx) +{ + PIO_STACK_LOCATION IoStack; + NTSTATUS Status; + PLIST_ENTRY Entry; + PBUS_DEVICE_ENTRY DeviceEntry; + PSWENUM_INSTALL_INTERFACE InstallInterface; + KIRQL OldLevel; + PBUS_INSTALL_ENUM_CONTEXT Context = (PBUS_INSTALL_ENUM_CONTEXT)Ctx; + + /* get current irp stack location */ + IoStack = IoGetCurrentIrpStackLocation(Context->Irp); + + /* get install request */ + InstallInterface = (PSWENUM_INSTALL_INTERFACE)Context->Irp->AssociatedIrp.SystemBuffer; + + /* sanity check */ + ASSERT(InstallInterface); + ASSERT(Context->BusDeviceExtension); + + if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SWENUM_INSTALL_INTERFACE)) + { + /* buffer too small */ + Context->Status = STATUS_INVALID_PARAMETER; + + /* signal completion */ + KeSetEvent(&Context->Event, 0, FALSE); + + /* done */ + return; + } + + /* FIXME locks */ + + /* now install the interface */ + Status = KspInstallInterface(Context->BusDeviceExtension, InstallInterface); + if (!NT_SUCCESS(Status)) + { + /* failed to install interface */ + Context->Status = Status; + + /* signal completion */ + KeSetEvent(&Context->Event, 0, FALSE); + + /* done */ + return; + } + + /* acquire device entry lock */ + KeAcquireSpinLock(&Context->BusDeviceExtension->Lock, &OldLevel); + + /* now iterate all device entries */ + Entry = Context->BusDeviceExtension->Common.Entry.Flink; + while(Entry != &Context->BusDeviceExtension->Common.Entry) + { + /* get device entry */ + DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); + + if (IsEqualGUIDAligned(&DeviceEntry->DeviceGuid, &InstallInterface->DeviceId) && + !wcsicmp(DeviceEntry->Instance, InstallInterface->ReferenceString)) + { + if (!DeviceEntry->PDO) + { + /* create pdo */ + Status = KspCreatePDO(Context->BusDeviceExtension, DeviceEntry, &DeviceEntry->PDO); + + /* done */ + break; + } + } + + /* move to next entry */ + Entry = Entry->Flink; + } + + /* release device entry lock */ + KeReleaseSpinLock(&Context->BusDeviceExtension->Lock, OldLevel); + + /* signal that bus driver relations has changed */ + IoInvalidateDeviceRelations(Context->BusDeviceExtension->PhysicalDeviceObject, BusRelations); + + /* update status */ + Context->Status = Status; + + /* signal completion */ + KeSetEvent(&Context->Event, 0, FALSE); +} + + +VOID +NTAPI +KspBusWorkerRoutine( + IN PVOID Parameter) +{ + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; + PBUS_DEVICE_ENTRY DeviceEntry; + PLIST_ENTRY Entry; + LARGE_INTEGER Time, Diff; + BOOLEAN DoInvalidate = FALSE; + KIRQL OldLevel; + + /* acquire lock */ + KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); + + /* get device extension */ + BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)Parameter; + + /* get current time */ + KeQuerySystemTime(&Time); + + /* enumerate all device entries */ + Entry = BusDeviceExtension->Common.Entry.Flink; + while(Entry != &BusDeviceExtension->Common.Entry) + { + /* get offset to device entry */ + DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); + + /* sanity check */ + ASSERT(DeviceEntry); + + //DPRINT1("DeviceEntry %p PDO %p State %x\n", DeviceEntry, DeviceEntry->PDO, DeviceEntry->DeviceState); + + if (DeviceEntry->PDO) + { + if (DeviceEntry->DeviceState == NotStarted) + { + Diff.QuadPart = Time.QuadPart - DeviceEntry->TimeCreated.QuadPart; + + if (Diff.QuadPart > Int32x32To64(15000, 10000)) + { + DPRINT1("DeviceID %S Instance %S TimeCreated %I64u Now %I64u Diff %I64u hung\n", DeviceEntry->DeviceName, DeviceEntry->Instance, DeviceEntry->TimeCreated.QuadPart, Time.QuadPart, Diff.QuadPart); + + /* release spin lock */ + KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); + + /* deactivate interfaces */ + //KspEnableBusDeviceInterface(DeviceEntry, FALSE); + + /* re-acquire lock */ + KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); + + /* pending remove device object */ + DeviceEntry->DeviceState = StopPending; + + /* perform invalidation */ + DoInvalidate = TRUE; + } + } + else if (DeviceEntry->DeviceState == Started) + { + /* found pending irps */ + KspCompletePendingIrps(DeviceEntry, STATUS_REPARSE); + } + } + + + /* move to next */ + Entry = Entry->Flink; + } + + /* release lock */ + KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); + + if (DoInvalidate) + { + /* invalidate device relations */ + IoInvalidateDeviceRelations(BusDeviceExtension->PhysicalDeviceObject, BusRelations); + } + + Time.QuadPart = Int32x32To64(5000, -10000); + KeSetTimer(&BusDeviceExtension->Timer, Time, &BusDeviceExtension->Dpc); +} + +VOID +NTAPI +KspBusDpcRoutine( + IN PKDPC Dpc, + IN PVOID DeferredContext OPTIONAL, + IN PVOID SystemArgument1 OPTIONAL, + IN PVOID SystemArgument2 OPTIONAL) +{ + /* get device extension */ + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeferredContext; + + /* queue the item */ + ExQueueWorkItem(&BusDeviceExtension->WorkItem, DelayedWorkQueue); +} + +VOID +NTAPI +KspRemoveBusInterface( + PVOID Ctx) +{ + PBUS_INSTALL_ENUM_CONTEXT Context =(PBUS_INSTALL_ENUM_CONTEXT)Ctx; + + /* TODO + * get SWENUM_INSTALL_INTERFACE struct + * open device key and delete the keys + */ + + UNIMPLEMENTED + + /* set status */ + Context->Status = STATUS_NOT_IMPLEMENTED; + + + /* signal completion */ + KeSetEvent(&Context->Event, IO_NO_INCREMENT, FALSE); +} + +NTSTATUS +KspQueryBusRelations( + IN PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension, + IN PIRP Irp) +{ + PDEVICE_RELATIONS DeviceRelations; + PLIST_ENTRY Entry; + PBUS_DEVICE_ENTRY DeviceEntry; + ULONG Count = 0, Length; + KIRQL OldLevel; + + /* acquire lock */ + KeAcquireSpinLock(&BusDeviceExtension->Lock, &OldLevel); + + /* first scan all device entries */ + Entry = BusDeviceExtension->Common.Entry.Flink; + + while(Entry != &BusDeviceExtension->Common.Entry) + { + /* get offset to device entry */ + DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); + + /* is there a pdo yet */ + if (DeviceEntry->PDO && (DeviceEntry->DeviceState == NotStarted || DeviceEntry->DeviceState == Started)) + { + /* increment count */ + Count++; + } + + /* move to next entry */ + Entry = Entry->Flink; + } + + /* calculate length */ + Length = sizeof(DEVICE_RELATIONS) + (Count > 1 ? sizeof(PDEVICE_OBJECT) * (Count-1) : 0); + + /* allocate device relations */ + DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(NonPagedPool, Length); + + if (!DeviceRelations) + { + /* not enough memory */ + KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* rescan device entries */ + Entry = BusDeviceExtension->Common.Entry.Flink; + + while(Entry != &BusDeviceExtension->Common.Entry) + { + /* get offset to device entry */ + DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); + + /* is there a pdo yet */ + if (DeviceEntry->PDO && (DeviceEntry->DeviceState == NotStarted || DeviceEntry->DeviceState == Started)) + { + /* store pdo */ + DeviceRelations->Objects[DeviceRelations->Count] = DeviceEntry->PDO; + + /* reference device object */ + ObReferenceObject(DeviceEntry->PDO); + + /* increment pdo count */ + DeviceRelations->Count++; + } + + /* move to next entry */ + Entry = Entry->Flink; + } + + /* release lock */ + KeReleaseSpinLock(&BusDeviceExtension->Lock, OldLevel); + + /* FIXME handle existing device relations */ + ASSERT(Irp->IoStatus.Information == 0); + + /* store device relations */ + Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; + + /* done */ + return STATUS_SUCCESS; +} + +//------------------------------------------------------------------------------------ + +/* + @implemented +*/ + +KSDDKAPI +NTSTATUS +NTAPI +KsGetBusEnumIdentifier( + IN PIRP Irp) +{ + PDEV_EXTENSION DeviceExtension; + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; + PIO_STACK_LOCATION IoStack; + ULONG Length; + NTSTATUS Status; + LPWSTR Buffer; + + DPRINT1("KsGetBusEnumIdentifier\n"); + + /* get stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* sanity checks */ + ASSERT(IoStack->DeviceObject); + ASSERT(IoStack->DeviceObject->DeviceExtension); + + /* get device extension */ + DeviceExtension = (PDEV_EXTENSION)IoStack->DeviceObject->DeviceExtension; + + /* get bus device extension */ + BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; + + /* sanity checks */ + ASSERT(BusDeviceExtension); + ASSERT(BusDeviceExtension->Common.IsBus); + + if (!BusDeviceExtension) + { + /* invalid parameter */ + return STATUS_INVALID_PARAMETER; + } + + /* get length */ + Length = (wcslen(BusDeviceExtension->BusIdentifier)+1) * sizeof(WCHAR); + + /* is there an output buffer provided */ + if (IoStack->Parameters.DeviceIoControl.InputBufferLength) + { + if (Length > IoStack->Parameters.DeviceIoControl.InputBufferLength) + { + /* buffer is too small */ + return STATUS_BUFFER_TOO_SMALL; + } + + /* now allocate buffer */ + Buffer = AllocateItem(NonPagedPool, Length); + if (!Buffer) + { + /* no memory */ + Status = STATUS_INSUFFICIENT_RESOURCES; + } + else + { + /* copy bus identifier */ + wcscpy(Buffer, BusDeviceExtension->BusIdentifier); + + /* store buffer */ + Irp->AssociatedIrp.SystemBuffer = Buffer; + + /* set flag that buffer gets copied back */ + Irp->Flags |= IRP_BUFFERED_IO | IRP_DEALLOCATE_BUFFER | IRP_INPUT_OPERATION; + + /* done */ + Status = STATUS_SUCCESS; + } + } + else + { + /* no buffer provided */ + Status = STATUS_BUFFER_OVERFLOW; + } + + /* done */ + Irp->IoStatus.Status = Status; + return Status; +} + +/* + @implemented +*/ +KSDDKAPI +NTSTATUS +NTAPI +KsGetBusEnumParentFDOFromChildPDO( + IN PDEVICE_OBJECT DeviceObject, + OUT PDEVICE_OBJECT *FunctionalDeviceObject) +{ + PDEV_EXTENSION DeviceExtension; + + DPRINT1("KsGetBusEnumParentFDOFromChildPDO\n"); + + /* get device extension */ + DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; + + /* check if this is child pdo */ + if (DeviceExtension->Ext->IsBus == FALSE) + { + /* return bus device object */ + *FunctionalDeviceObject = DeviceExtension->Ext->BusDeviceExtension->BusDeviceObject; + + /* done */ + return STATUS_SUCCESS; + } + + /* invalid parameter */ + return STATUS_INVALID_PARAMETER; +} + + +/* + @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; + PDEV_EXTENSION DeviceExtension; + + DPRINT1("KsCreateBusEnumObject %S BusDeviceObject %p\n", ServiceRelativePath, BusDeviceObject); + + /* 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; + } + + /* get device extension */ + DeviceExtension = (PDEV_EXTENSION)BusDeviceObject->DeviceExtension; + + DPRINT1("DeviceExtension %p BusDeviceExtension %p\n", DeviceExtension, DeviceExtension->Ext); + + /* store bus device extension */ + DeviceExtension->Ext = (PCOMMON_DEVICE_EXTENSION)BusDeviceExtension; + + DPRINT1("DeviceExtension %p BusDeviceExtension %p\n", DeviceExtension, DeviceExtension->Ext); + + + /* 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->DeviceInterfaceLink); + + /* check for success */ + if (!NT_SUCCESS(Status)) + { + + FreeItem(BusDeviceExtension->ServicePath.Buffer); + FreeItem(BusDeviceExtension); + return Status; + } + + /* now enable device interface */ + Status = IoSetDeviceInterfaceState(&BusDeviceExtension->DeviceInterfaceLink, TRUE); + + if (!NT_SUCCESS(Status)) + { + FreeItem(BusDeviceExtension->ServicePath.Buffer); + FreeItem(BusDeviceExtension); + return Status; + } + } + + /* initialize common device extension */ + BusDeviceExtension->Common.BusDeviceExtension = NULL; + BusDeviceExtension->Common.DeviceObjectReferenceCount = 1; + BusDeviceExtension->Common.DeviceReferenceCount = 1; + BusDeviceExtension->Common.IsBus = TRUE; + InitializeListHead(&BusDeviceExtension->Common.Entry); + + /* store device objects */ + BusDeviceExtension->BusDeviceObject = BusDeviceObject; + BusDeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject; + + /* initialize lock */ + KeInitializeSpinLock(&BusDeviceExtension->Lock); + + /* initialize timer */ + KeInitializeTimer(&BusDeviceExtension->Timer); + + /* initialize dpc */ + KeInitializeDpc(&BusDeviceExtension->Dpc, KspBusDpcRoutine, (PVOID)BusDeviceExtension); + + /* initialize event */ + KeInitializeEvent(&BusDeviceExtension->Event, SynchronizationEvent, FALSE); + + /* initialize work item */ + ExInitializeWorkItem(&BusDeviceExtension->WorkItem, KspBusWorkerRoutine, (PVOID)BusDeviceExtension); + + if (!PnpDeviceObject) + { + /* attach device */ + BusDeviceExtension->PnpDeviceObject = IoAttachDeviceToDeviceStack(BusDeviceObject, PhysicalDeviceObject); + + if (!BusDeviceExtension->PnpDeviceObject) + { + /* failed to attach device */ + if (BusDeviceExtension->DeviceInterfaceLink.Buffer) + { + IoSetDeviceInterfaceState(&BusDeviceExtension->DeviceInterfaceLink, FALSE); + RtlFreeUnicodeString(&BusDeviceExtension->DeviceInterfaceLink); + } + + /* free device extension */ + FreeItem(BusDeviceExtension->ServicePath.Buffer); + FreeItem(BusDeviceExtension); + + return STATUS_DEVICE_REMOVED; + } + + /* mark device as attached */ + BusDeviceExtension->DeviceAttached = TRUE; + } + else + { + /* directly attach */ + BusDeviceExtension->PnpDeviceObject = PnpDeviceObject; + } + + /* now scan the bus */ + Status = KspScanBus(BusDeviceExtension); + + /* check for success */ + if (!NT_SUCCESS(Status)) + { + /* failed to scan bus */ + if (BusDeviceExtension->DeviceInterfaceLink.Buffer) + { + IoSetDeviceInterfaceState(&BusDeviceExtension->DeviceInterfaceLink, FALSE); + RtlFreeUnicodeString(&BusDeviceExtension->DeviceInterfaceLink); + } + + if (BusDeviceExtension->DeviceAttached) + { + /* detach device */ + IoDetachDevice(BusDeviceExtension->PnpDeviceObject); + } + + /* free device extension */ + FreeItem(BusDeviceExtension->ServicePath.Buffer); + FreeItem(BusDeviceExtension); + } + + DPRINT("KsCreateBusEnumObject Status %x\n", Status); + /* done */ + return Status; +} + +/* + @implemented +*/ +KSDDKAPI +NTSTATUS +NTAPI +KsGetBusEnumPnpDeviceObject( + IN PDEVICE_OBJECT DeviceObject, + IN PDEVICE_OBJECT *PnpDeviceObject) +{ + PDEV_EXTENSION DeviceExtension; + PCOMMON_DEVICE_EXTENSION CommonDeviceExtension; + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; + + DPRINT("KsGetBusEnumPnpDeviceObject\n"); + + if (!DeviceObject->DeviceExtension) + { + /* invalid parameter */ + return STATUS_INVALID_PARAMETER; + } + + /* get device extension */ + DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; + + /* get common device extension */ + CommonDeviceExtension = DeviceExtension->Ext; + + if (!CommonDeviceExtension) + { + /* invalid parameter */ + return STATUS_INVALID_PARAMETER; + } + + if (!CommonDeviceExtension->IsBus) + { + /* getting pnp device object is only supported for software bus device object */ + return STATUS_INVALID_PARAMETER; + } + + /* sanity checks */ + ASSERT(CommonDeviceExtension); + ASSERT(CommonDeviceExtension->IsBus); + + /* cast to bus device extension */ + BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)CommonDeviceExtension; + + /* store result */ + *PnpDeviceObject = BusDeviceExtension->PnpDeviceObject; + + /* done */ + return STATUS_SUCCESS; +} + +/* + @implemented +*/ +KSDDKAPI +NTSTATUS +NTAPI +KsInstallBusEnumInterface( + PIRP Irp) +{ + BUS_INSTALL_ENUM_CONTEXT Context; + KPROCESSOR_MODE Mode; + LUID luid; + PIO_STACK_LOCATION IoStack; + PDEV_EXTENSION DeviceExtension; + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; + + DPRINT1("KsInstallBusEnumInterface\n"); + + /* get current irp stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* 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; + } + + /* get device extension */ + DeviceExtension = (PDEV_EXTENSION)IoStack->DeviceObject->DeviceExtension; + + /* get bus device extension */ + BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; + + + /* initialize context */ + Context.Irp = Irp; + KeInitializeEvent(&Context.Event, NotificationEvent, FALSE); + Context.BusDeviceExtension = BusDeviceExtension; + ExInitializeWorkItem(&Context.WorkItem, KspInstallBusEnumInterface, (PVOID)&Context); + + /* queue the work item */ + ExQueueWorkItem(&Context.WorkItem, DelayedWorkQueue); + /* wait for completion */ + KeWaitForSingleObject(&Context.Event, Executive, KernelMode, FALSE, NULL); + + /* store result */ + Irp->IoStatus.Status = Context.Status; + + /* done */ + return Context.Status; +} + +/* + @implemented +*/ +KSDDKAPI +NTSTATUS +NTAPI +KsIsBusEnumChildDevice( + IN PDEVICE_OBJECT DeviceObject, + OUT PBOOLEAN ChildDevice) +{ + PDEV_EXTENSION DeviceExtension; + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; + + DPRINT("KsIsBusEnumChildDevice %p\n", DeviceObject); + + /* get device extension */ + DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; + + /* get bus device extension */ + BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; + + if (!BusDeviceExtension) + { + /* not a bus device */ + return STATUS_INVALID_PARAMETER; + } + + /* store result */ + *ChildDevice = (BusDeviceExtension->Common.IsBus == FALSE); + + return STATUS_SUCCESS; +} + +/* + @implemented +*/ +KSDDKAPI +NTSTATUS +NTAPI +KsServiceBusEnumCreateRequest( + IN PDEVICE_OBJECT DeviceObject, + IN OUT PIRP Irp) +{ + PLIST_ENTRY Entry; + PBUS_DEVICE_ENTRY DeviceEntry = NULL; /* fix gcc */ + PIO_STACK_LOCATION IoStack; + BOOLEAN ItemExists = FALSE; + PDEV_EXTENSION DeviceExtension; + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; + //PCOMMON_DEVICE_EXTENSION ChildDeviceExtension; + NTSTATUS Status; + LARGE_INTEGER Time; + + /* FIXME: locks */ + + /* get device extension */ + DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; + + /* get bus device extension */ + BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; + + /* get current irp stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* sanity checks */ + ASSERT(IoStack->FileObject); + ASSERT(IoStack->FileObject->FileName.Buffer); + + DPRINT1("KsServiceBusEnumCreateRequest IRP %p Name %wZ\n", Irp, &IoStack->FileObject->FileName); + + /* scan list and check if it is already present */ + Entry = BusDeviceExtension->Common.Entry.Flink; + + while(Entry != &BusDeviceExtension->Common.Entry) + { + /* get real offset */ + DeviceEntry = (PBUS_DEVICE_ENTRY)CONTAINING_RECORD(Entry, BUS_DEVICE_ENTRY, Entry); + + /* check if name matches */ + if (!wcsicmp(DeviceEntry->DeviceName, IoStack->FileObject->FileName.Buffer + 1)) + { + /* item already exists */ + ItemExists = TRUE; + break; + } + + /* move to next entry */ + Entry = Entry->Flink; + } + + if (!ItemExists) + { + /* interface not registered */ + DPRINT1("Interface %wZ not registered\n", &IoStack->FileObject->FileName); + return STATUS_OBJECT_NAME_NOT_FOUND; + } + + /* is there a pdo yet */ + if (DeviceEntry->PDO) + { + if (DeviceEntry->DeviceState == Started) + { + /* issue reparse */ + Status = KspDoReparseForIrp(Irp, DeviceEntry); + DPRINT("REPARSE Irp %p '%wZ'\n", Irp, &IoStack->FileObject->FileName); + + Irp->IoStatus.Status = Status; + return Status; + } + + /* delay processing until pnp is finished with enumeration */ + IoMarkIrpPending(Irp); + + /* insert into irp pending list */ + InsertTailList(&DeviceEntry->IrpPendingList, &Irp->Tail.Overlay.ListEntry); + + Time.QuadPart = Int32x32To64(1500, -10000); + DbgPrint("PENDING Irp %p %wZ\n", Irp, &IoStack->FileObject->FileName); + + /* query current time */ + KeQuerySystemTime(&DeviceEntry->TimeCreated); + + /* set timer */ + KeSetTimer(&BusDeviceExtension->Timer, Time, &BusDeviceExtension->Dpc); + + /* done for now */ + return STATUS_PENDING; + + } + else + { + /* time to create PDO */ + Status = KspCreatePDO(BusDeviceExtension, DeviceEntry, &DeviceEntry->PDO); + + if (!NT_SUCCESS(Status)) + { + /* failed to create PDO */ + DPRINT1("KsServiceBusEnumCreateRequest failed to create PDO with %x\n", Status); + return Status; + } + DPRINT1("PENDING CREATE Irp %p %wZ\n", Irp, &IoStack->FileObject->FileName); + + /* delay processing until pnp is finished with enumeration */ + IoMarkIrpPending(Irp); + + /* insert into irp pending list */ + InsertTailList(&DeviceEntry->IrpPendingList, &Irp->Tail.Overlay.ListEntry); + + /* get current time */ + KeQuerySystemTime(&DeviceEntry->TimeCreated); + + /* invalidate device relations */ + IoInvalidateDeviceRelations(BusDeviceExtension->PhysicalDeviceObject, BusRelations); + + /* done for now */ + return STATUS_PENDING; + } +} + +/* + @implemented +*/ +KSDDKAPI +NTSTATUS +NTAPI +KsServiceBusEnumPnpRequest( + IN PDEVICE_OBJECT DeviceObject, + IN OUT PIRP Irp) +{ + PDEV_EXTENSION DeviceExtension; + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; + PCOMMON_DEVICE_EXTENSION ChildDeviceExtension; + PIO_STACK_LOCATION IoStack; + NTSTATUS Status; + LARGE_INTEGER Time; + PDEVICE_RELATIONS DeviceRelation; + PBUS_DEVICE_ENTRY DeviceEntry; + + /* get device extension */ + DeviceExtension = (PDEV_EXTENSION)DeviceObject->DeviceExtension; + + /* get bus device extension */ + BusDeviceExtension = (PBUS_ENUM_DEVICE_EXTENSION)DeviceExtension->Ext; + + /* get current irp stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + if (BusDeviceExtension->Common.IsBus) + { + if (IoStack->MinorFunction == IRP_MN_START_DEVICE) + { + /* no op for bus driver */ + Status = STATUS_SUCCESS; + } + else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS) + { + /* handle bus device relations */ + ASSERT(IoStack->Parameters.QueryDeviceRelations.Type == BusRelations); + + Status = KspQueryBusRelations(BusDeviceExtension, Irp); + } + else + { + /* get default status */ + Status = Irp->IoStatus.Status; + } + } + else + { + /* get child device extension */ + ChildDeviceExtension = DeviceExtension->Ext; + + /* get bus device extension */ + BusDeviceExtension = ChildDeviceExtension->BusDeviceExtension; + + if (IoStack->MinorFunction == IRP_MN_QUERY_ID) + { + /* query id */ + Status = KspQueryId(ChildDeviceExtension, Irp); + } + else if (IoStack->MinorFunction == IRP_MN_REMOVE_DEVICE) + { + ASSERT(ChildDeviceExtension->DeviceEntry->DeviceState != Started || ChildDeviceExtension->DeviceEntry->DeviceState == NotStarted); + ASSERT(ChildDeviceExtension->DeviceEntry->PDO == DeviceObject); + + /* backup device entry */ + DeviceEntry = ChildDeviceExtension->DeviceEntry; + + /* free device extension */ + FreeItem(ChildDeviceExtension); + + /* clear PDO reference */ + DeviceEntry->PDO = NULL; + + /* delete the device */ + IoDeleteDevice(DeviceObject); + + if (DeviceEntry->PDODeviceName) + { + /* delete pdo device name */ + FreeItem(DeviceEntry->PDODeviceName); + + /* set to null */ + DeviceEntry->PDODeviceName = NULL; + } + + /* set state no notstarted */ + DeviceEntry->DeviceState = NotStarted; + + /* time to create PDO */ + KspCreatePDO(BusDeviceExtension, DeviceEntry, &DeviceEntry->PDO); + + /* invalidate device relations */ + IoInvalidateDeviceRelations(BusDeviceExtension->PhysicalDeviceObject, BusRelations); + + /* done */ + Status = STATUS_SUCCESS; + } + else if (IoStack->MinorFunction == IRP_MN_QUERY_BUS_INFORMATION) + { + /* query bus information */ + Status = KspQueryBusInformation(ChildDeviceExtension, Irp); + } + else if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCES) + { + /* no op */ + Status = STATUS_SUCCESS; + } + else if (IoStack->MinorFunction == IRP_MN_QUERY_RESOURCE_REQUIREMENTS) + { + /* no op */ + Status = STATUS_SUCCESS; + } + else if (IoStack->MinorFunction == IRP_MN_START_DEVICE) + { + /* start bus */ + Status = KspStartBusDevice(DeviceObject, ChildDeviceExtension, Irp); + + /* set time out */ + Time.QuadPart = Int32x32To64(1500, -10000); + + /* sanity check */ + ASSERT(BusDeviceExtension); + + /* set timer */ + KeSetTimer(&BusDeviceExtension->Timer, Time, &BusDeviceExtension->Dpc); + } + else if (IoStack->MinorFunction == IRP_MN_QUERY_CAPABILITIES) + { + /* query capabilities */ + Status = KspQueryBusDeviceCapabilities(ChildDeviceExtension, Irp); + } + else if (IoStack->MinorFunction == IRP_MN_QUERY_PNP_DEVICE_STATE) + { + /* query pnp state */ + Status = KspQueryBusDevicePnpState(ChildDeviceExtension, Irp); + } + else if (IoStack->MinorFunction == IRP_MN_QUERY_INTERFACE) + { + /* query interface */ + Status = KspQueryBusDeviceInterface(ChildDeviceExtension, Irp); + } + else if (IoStack->MinorFunction == IRP_MN_QUERY_DEVICE_RELATIONS && IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation) + { + /* handle target device relations */ + ASSERT(IoStack->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation); + ASSERT(Irp->IoStatus.Information == 0); + + /* allocate device relation */ + DeviceRelation = AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS)); + if (DeviceRelation) + { + DeviceRelation->Count = 1; + DeviceRelation->Objects[0] = DeviceObject; + + /* reference self */ + ObReferenceObject(DeviceObject); + + /* store result */ + Irp->IoStatus.Information = (ULONG_PTR)DeviceRelation; + + /* done */ + Status = STATUS_SUCCESS; + } + else + { + /* no memory */ + Status = STATUS_INSUFFICIENT_RESOURCES; + } + } + else + { + /* get default status */ + Status = Irp->IoStatus.Status; + } + } + + DPRINT("KsServiceBusEnumPnpRequest %p Bus %u Function %x Status %x\n", DeviceObject, BusDeviceExtension->Common.IsBus, IoStack->MinorFunction, Status); + Irp->IoStatus.Status = Status; + return Status; +} + +/* + @implemented +*/ +KSDDKAPI +NTSTATUS +NTAPI +KsRemoveBusEnumInterface( + IN PIRP Irp) +{ + KPROCESSOR_MODE Mode; + LUID luid; + BUS_INSTALL_ENUM_CONTEXT Ctx; + PDEV_EXTENSION DeviceExtension; + PBUS_ENUM_DEVICE_EXTENSION BusDeviceExtension; + PIO_STACK_LOCATION IoStack; + + DPRINT1("KsRemoveBusEnumInterface\n"); + + /* get io stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + /* get device extension */ + DeviceExtension = (PDEV_EXTENSION)IoStack->DeviceObject->DeviceExtension; + + /* get bus device extension */ + BusDeviceExtension = DeviceExtension->Ext->BusDeviceExtension; + + /* 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 context */ + KeInitializeEvent(&Ctx.Event, NotificationEvent, FALSE); + Ctx.Irp = Irp; + Ctx.BusDeviceExtension = BusDeviceExtension; + ExInitializeWorkItem(&Ctx.WorkItem, KspRemoveBusInterface, (PVOID)&Ctx); + + /* now queue the work item */ + ExQueueWorkItem(&Ctx.WorkItem, DelayedWorkQueue); + + /* wait for completion */ + KeWaitForSingleObject(&Ctx.Event, Executive, KernelMode, FALSE, NULL); + + /* return result */ + return Ctx.Status; +} diff --git a/drivers/ksfilter/swenum/CMakeLists.txt b/drivers/ksfilter/swenum/CMakeLists.txt new file mode 100644 index 00000000000..fbf53f76f61 --- /dev/null +++ b/drivers/ksfilter/swenum/CMakeLists.txt @@ -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) diff --git a/drivers/ksfilter/swenum/swenum.c b/drivers/ksfilter/swenum/swenum.c index 459e60b377f..c2aeaad5ea3 100644 --- a/drivers/ksfilter/swenum/swenum.c +++ b/drivers/ksfilter/swenum/swenum.c @@ -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; } diff --git a/drivers/network/tdi/CMakeLists.txt b/drivers/network/tdi/CMakeLists.txt index 4afa01328f9..1b57c6f1c4b 100644 --- a/drivers/network/tdi/CMakeLists.txt +++ b/drivers/network/tdi/CMakeLists.txt @@ -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 diff --git a/drivers/network/tdi/cte/events.c b/drivers/network/tdi/cte/events.c new file mode 100644 index 00000000000..dd6aff158e3 --- /dev/null +++ b/drivers/network/tdi/cte/events.c @@ -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 + +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 */ diff --git a/drivers/network/tdi/cte/stubs.c b/drivers/network/tdi/cte/stubs.c deleted file mode 100644 index e1a2b6b84c0..00000000000 --- a/drivers/network/tdi/cte/stubs.c +++ /dev/null @@ -1,147 +0,0 @@ -/* $Id$ - * - */ -#include - - -/* - * @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 */ diff --git a/drivers/network/tdi/cte/timer.c b/drivers/network/tdi/cte/timer.c new file mode 100644 index 00000000000..aa82dfe1455 --- /dev/null +++ b/drivers/network/tdi/cte/timer.c @@ -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 + +/* 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 */ diff --git a/drivers/network/tdi/misc/main.c b/drivers/network/tdi/misc/main.c index c7882d0e622..d66341c8dd9 100644 --- a/drivers/network/tdi/misc/main.c +++ b/drivers/network/tdi/misc/main.c @@ -1,17 +1,20 @@ -/* $Id$ - * +/* * DESCRIPTION: Entry point for TDI.SYS + * (c) Captain Obvious */ #include +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; } diff --git a/drivers/network/tdi/misc/tdi.spec b/drivers/network/tdi/misc/tdi.spec index a1810644793..918d518ca95 100644 --- a/drivers/network/tdi/misc/tdi.spec +++ b/drivers/network/tdi/misc/tdi.spec @@ -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) diff --git a/drivers/network/tdi/tdi/dereg.c b/drivers/network/tdi/tdi/dereg.c index baab13f7525..787b3e63c7e 100644 --- a/drivers/network/tdi/tdi/dereg.c +++ b/drivers/network/tdi/tdi/dereg.c @@ -1,8 +1,5 @@ -/* $Id$ - * - */ #include -#include +#include /* 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 */ diff --git a/drivers/network/tdi/tdi/stubs.c b/drivers/network/tdi/tdi/stubs.c index ce4c58cb75b..0396d83d455 100644 --- a/drivers/network/tdi/tdi/stubs.c +++ b/drivers/network/tdi/tdi/stubs.c @@ -75,9 +75,7 @@ TdiCopyMdlToBuffer ( */ VOID NTAPI -TdiInitialize ( - PVOID Unknown0 - ) +TdiInitialize () { } diff --git a/drivers/wdm/audio/legacy/wdmaud/mmixer.c b/drivers/wdm/audio/legacy/wdmaud/mmixer.c index fbc76389405..0ac17446f43 100644 --- a/drivers/wdm/audio/legacy/wdmaud/mmixer.c +++ b/drivers/wdm/audio/legacy/wdmaud/mmixer.c @@ -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)); diff --git a/include/psdk/ks.h b/include/psdk/ks.h index 8cd467a2f02..81259228a18 100644 --- a/include/psdk/ks.h +++ b/include/psdk/ks.h @@ -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_) diff --git a/include/reactos/libs/sound/mmebuddy.h b/include/reactos/libs/sound/mmebuddy.h index 1a2a5431242..1cc7f52db4f 100644 --- a/include/reactos/libs/sound/mmebuddy.h +++ b/include/reactos/libs/sound/mmebuddy.h @@ -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, diff --git a/include/reactos/wine/port.h b/include/reactos/wine/port.h index b5c93b8054b..a1050121ab2 100644 --- a/include/reactos/wine/port.h +++ b/include/reactos/wine/port.h @@ -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 */ diff --git a/include/reactos/winlogon.h b/include/reactos/winlogon.h index 4c00b674e81..42eaf620468 100644 --- a/include/reactos/winlogon.h +++ b/include/reactos/winlogon.h @@ -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 */ diff --git a/lib/drivers/sound/mmebuddy/mixer/mxdMessage.c b/lib/drivers/sound/mmebuddy/mixer/mxdMessage.c index 08815ba8eee..7652d9ef7ea 100644 --- a/lib/drivers/sound/mmebuddy/mixer/mxdMessage.c +++ b/lib/drivers/sound/mmebuddy/mixer/mxdMessage.c @@ -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); diff --git a/lib/drivers/sound/mmebuddy/mmewrap.c b/lib/drivers/sound/mmebuddy/mmewrap.c index 583d198ca87..9e03770c175 100644 --- a/lib/drivers/sound/mmebuddy/mmewrap.c +++ b/lib/drivers/sound/mmebuddy/mmewrap.c @@ -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); diff --git a/lib/drivers/sound/mmebuddy/wave/format.c b/lib/drivers/sound/mmebuddy/wave/format.c index ecc5bbc1d9a..34541c4fa0c 100644 --- a/lib/drivers/sound/mmebuddy/wave/format.c +++ b/lib/drivers/sound/mmebuddy/wave/format.c @@ -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); diff --git a/lib/drivers/sound/mmebuddy/wave/streaming.c b/lib/drivers/sound/mmebuddy/wave/streaming.c index a28093359b5..63ac5e0a89d 100644 --- a/lib/drivers/sound/mmebuddy/wave/streaming.c +++ b/lib/drivers/sound/mmebuddy/wave/streaming.c @@ -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 diff --git a/lib/drivers/sound/mmebuddy/wave/wodMessage.c b/lib/drivers/sound/mmebuddy/wave/wodMessage.c index 330c5f2aab6..a1202a8e5cc 100644 --- a/lib/drivers/sound/mmebuddy/wave/wodMessage.c +++ b/lib/drivers/sound/mmebuddy/wave/wodMessage.c @@ -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; } diff --git a/lib/drivers/sound/mmixer/TODO b/lib/drivers/sound/mmixer/TODO new file mode 100644 index 00000000000..05cf9c29474 --- /dev/null +++ b/lib/drivers/sound/mmixer/TODO @@ -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 \ No newline at end of file diff --git a/lib/drivers/sound/mmixer/controls.c b/lib/drivers/sound/mmixer/controls.c index 5b5dd1831ae..e7bd2886ef5 100644 --- a/lib/drivers/sound/mmixer/controls.c +++ b/lib/drivers/sound/mmixer/controls.c @@ -8,44 +8,67 @@ #include "priv.h" +const GUID KSNODETYPE_DESKTOP_MICROPHONE = {0xDFF21BE2, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; +const GUID KSNODETYPE_LEGACY_AUDIO_CONNECTOR = {0xDFF21FE4, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; +const GUID KSNODETYPE_TELEPHONE = {0xDFF21EE2, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; +const GUID KSNODETYPE_PHONE_LINE = {0xDFF21EE1, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; +const GUID KSNODETYPE_DOWN_LINE_PHONE = {0xDFF21EE3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; +const GUID KSNODETYPE_DESKTOP_SPEAKER = {0xDFF21CE4, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; +const GUID KSNODETYPE_ROOM_SPEAKER = {0xDFF21CE5, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; +const GUID KSNODETYPE_COMMUNICATION_SPEAKER = {0xDFF21CE6, 0xF70F, 0x11D0, {0xB9,0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; +const GUID KSNODETYPE_HEADPHONES = {0xDFF21CE2, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; +const GUID KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO = {0xDFF21CE3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; +const GUID KSNODETYPE_MICROPHONE = {0xDFF21BE1, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9,0x22, 0x31, 0x96}}; +const GUID KSCATEGORY_AUDIO = {0x6994AD04L, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; +const GUID KSNODETYPE_SPDIF_INTERFACE = {0xDFF21FE5, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; +const GUID KSNODETYPE_ANALOG_CONNECTOR = {0xDFF21FE1, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; +const GUID KSNODETYPE_SPEAKER = {0xDFF21CE1, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; +const GUID KSNODETYPE_CD_PLAYER = {0xDFF220E3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; +const GUID KSNODETYPE_SYNTHESIZER = {0xDFF220F3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; +const GUID KSNODETYPE_LINE_CONNECTOR = {0xDFF21FE3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0,0xC9, 0x22, 0x31, 0x96}}; +const GUID PINNAME_VIDEO_CAPTURE = {0xfb6c4281, 0x353, 0x11d1, {0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba}}; + MIXER_STATUS MMixerAddMixerControl( IN PMIXER_CONTEXT MixerContext, IN LPMIXER_INFO MixerInfo, + IN HANDLE hMixer, IN PTOPOLOGY Topology, IN ULONG NodeIndex, IN LPMIXERLINE_EXT MixerLine, - OUT LPMIXERCONTROLW MixerControl) + IN ULONG MaxChannels) { LPGUID NodeType; KSP_NODE Node; ULONG BytesReturned; MIXER_STATUS Status; LPWSTR Name; + LPMIXERCONTROL_EXT MixerControl; + + /* allocate mixer control */ + MixerControl = MixerContext->Alloc(sizeof(MIXERCONTROL_EXT)); + if (!MixerControl) + { + /* no memory */ + return MM_STATUS_NO_MEMORY; + } + /* initialize mixer control */ - MixerControl->cbStruct = sizeof(MIXERCONTROLW); - MixerControl->dwControlID = MixerInfo->ControlId; + MixerControl->hDevice = hMixer; + MixerControl->NodeID = NodeIndex; + MixerControl->ExtraData = NULL; + + MixerControl->Control.cbStruct = sizeof(MIXERCONTROLW); + MixerControl->Control.dwControlID = MixerInfo->ControlId; /* get node type */ NodeType = MMixerGetNodeTypeFromTopology(Topology, NodeIndex); /* store control type */ - MixerControl->dwControlType = MMixerGetControlTypeFromTopologyNode(NodeType); + MixerControl->Control.dwControlType = MMixerGetControlTypeFromTopologyNode(NodeType); - MixerControl->fdwControl = MIXERCONTROL_CONTROLF_UNIFORM; /* FIXME */ - MixerControl->cMultipleItems = 0; /* FIXME */ - - if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE) - { - MixerControl->Bounds.dwMinimum = 0; - MixerControl->Bounds.dwMaximum = 1; - } - else if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME) - { - MixerControl->Bounds.dwMinimum = 0; - MixerControl->Bounds.dwMaximum = 0xFFFF; - MixerControl->Metrics.cSteps = 0xC0; /* FIXME */ - } + MixerControl->Control.fdwControl = (MaxChannels > 1 ? 0 : MIXERCONTROL_CONTROLF_UNIFORM); + MixerControl->Control.cMultipleItems = 0; /* setup request to retrieve name */ Node.NodeId = NodeIndex; @@ -55,7 +78,7 @@ MMixerAddMixerControl( Node.Reserved = 0; /* get node name size */ - Status = MixerContext->Control(MixerInfo->hMixer, IOCTL_KS_PROPERTY, (PVOID)&Node, sizeof(KSP_NODE), NULL, 0, &BytesReturned); + Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Node, sizeof(KSP_NODE), NULL, 0, &BytesReturned); if (Status == MM_STATUS_MORE_ENTRIES) { @@ -68,44 +91,66 @@ MMixerAddMixerControl( } /* get node name */ - Status = MixerContext->Control(MixerInfo->hMixer, IOCTL_KS_PROPERTY, (PVOID)&Node, sizeof(KSP_NODE), (LPVOID)Name, BytesReturned, &BytesReturned); + Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Node, sizeof(KSP_NODE), (LPVOID)Name, BytesReturned, &BytesReturned); if (Status == MM_STATUS_SUCCESS) { - MixerContext->Copy(MixerControl->szShortName, Name, (min(MIXER_SHORT_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR)); - MixerControl->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0'; + MixerContext->Copy(MixerControl->Control.szShortName, Name, (min(MIXER_SHORT_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR)); + MixerControl->Control.szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0'; - MixerContext->Copy(MixerControl->szName, Name, (min(MIXER_LONG_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR)); - MixerControl->szName[MIXER_LONG_NAME_CHARS-1] = L'\0'; + MixerContext->Copy(MixerControl->Control.szName, Name, (min(MIXER_LONG_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR)); + MixerControl->Control.szName[MIXER_LONG_NAME_CHARS-1] = L'\0'; } /* free name buffer */ MixerContext->Free(Name); } + /* increment control count */ MixerInfo->ControlId++; -#if 0 - if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_MUX) + + /* insert control */ + InsertTailList(&MixerLine->ControlsList, &MixerControl->Entry); + + if (MixerControl->Control.dwControlType == MIXERCONTROL_CONTROLTYPE_MUX) { - KSNODEPROPERTY Property; - ULONG PinId = 2; + ULONG NodesCount; + PULONG Nodes; - /* setup the request */ - RtlZeroMemory(&Property, sizeof(KSNODEPROPERTY)); + /* allocate topology nodes array */ + Status = MMixerAllocateTopologyNodeArray(MixerContext, Topology, &Nodes); - Property.NodeId = NodeIndex; - Property.Property.Id = KSPROPERTY_AUDIO_MUX_SOURCE; - Property.Property.Flags = KSPROPERTY_TYPE_SET; - Property.Property.Set = KSPROPSETID_Audio; + if (Status != MM_STATUS_SUCCESS) + { + /* out of memory */ + return STATUS_NO_MEMORY; + } - /* get node volume level info */ - Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSNODEPROPERTY), (PVOID)&PinId, sizeof(ULONG), &BytesReturned); + /* get connected node count */ + MMixerGetNextNodesFromNodeIndex(MixerContext, Topology, NodeIndex, TRUE, &NodesCount, Nodes); - DPRINT1("Status %x NodeIndex %u PinId %u\n", Status, NodeIndex, PinId); - //DbgBreakPoint(); - }else -#endif - if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME) + /* TODO */ + MixerContext->Free(Nodes); + + /* setup mux bounds */ + MixerControl->Control.Bounds.dwMinimum = 0; + MixerControl->Control.Bounds.dwMaximum = NodesCount - 1; + MixerControl->Control.Metrics.dwReserved[0] = NodesCount; + MixerControl->Control.cMultipleItems = NodesCount; + MixerControl->Control.fdwControl |= MIXERCONTROL_CONTROLF_UNIFORM | MIXERCONTROL_CONTROLF_MULTIPLE; + } + else if (MixerControl->Control.dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE) + { + MixerControl->Control.Bounds.dwMinimum = 0; + MixerControl->Control.Bounds.dwMaximum = 1; + } + else if (MixerControl->Control.dwControlType == MIXERCONTROL_CONTROLTYPE_ONOFF) + { + /* only needs to set bounds */ + MixerControl->Control.Bounds.dwMinimum = 0; + MixerControl->Control.Bounds.dwMaximum = 1; + } + else if (MixerControl->Control.dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME) { KSNODEPROPERTY_AUDIO_CHANNEL Property; ULONG Length; @@ -113,6 +158,10 @@ MMixerAddMixerControl( PKSPROPERTY_MEMBERSHEADER Members; PKSPROPERTY_STEPPING_LONG Range; + MixerControl->Control.Bounds.dwMinimum = 0; + MixerControl->Control.Bounds.dwMaximum = 0xFFFF; + MixerControl->Control.Metrics.cSteps = 0xC0; /* FIXME */ + Length = sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_STEPPING_LONG); Desc = (PKSPROPERTY_DESCRIPTION)MixerContext->Alloc(Length); ASSERT(Desc); @@ -122,11 +171,11 @@ MMixerAddMixerControl( Property.NodeProperty.NodeId = NodeIndex; Property.NodeProperty.Property.Id = KSPROPERTY_AUDIO_VOLUMELEVEL; - Property.NodeProperty.Property.Flags = KSPROPERTY_TYPE_BASICSUPPORT; + Property.NodeProperty.Property.Flags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_TOPOLOGY; Property.NodeProperty.Property.Set = KSPROPSETID_Audio; /* get node volume level info */ - Status = MixerContext->Control(MixerInfo->hMixer, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL), Desc, Length, &BytesReturned); + Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL), Desc, Length, &BytesReturned); if (Status == MM_STATUS_SUCCESS) { @@ -151,7 +200,7 @@ MMixerAddMixerControl( Steps = MaxRange / Range->SteppingDelta + 1; /* store mixer control info there */ - VolumeData->Header.dwControlID = MixerControl->dwControlID; + VolumeData->Header.dwControlID = MixerControl->Control.dwControlID; VolumeData->SignedMaximum = Range->Bounds.SignedMaximum; VolumeData->SignedMinimum = Range->Bounds.SignedMinimum; VolumeData->SteppingDelta = Range->SteppingDelta; @@ -172,13 +221,13 @@ MMixerAddMixerControl( VolumeData->Values[Index] = Value; Value += Range->SteppingDelta; } - InsertTailList(&MixerLine->LineControlsExtraData, &VolumeData->Header.Entry); + MixerControl->ExtraData = VolumeData; } } MixerContext->Free(Desc); } - DPRINT("Status %x Name %S\n", Status, MixerControl->szName); + DPRINT("Status %x Name %S\n", Status, MixerControl->Control.szName); return MM_STATUS_SUCCESS; } @@ -201,12 +250,16 @@ MMixerCreateDestinationLine( /* initialize mixer destination line */ DestinationLine->Line.cbStruct = sizeof(MIXERLINEW); - DestinationLine->Line.dwSource = MAXULONG; - DestinationLine->Line.dwLineID = DESTINATION_LINE; - DestinationLine->Line.fdwLine = MIXERLINE_LINEF_ACTIVE; - DestinationLine->Line.dwUser = 0; - DestinationLine->Line.dwComponentType = (bInputMixer == 0 ? MIXERLINE_COMPONENTTYPE_DST_SPEAKERS : MIXERLINE_COMPONENTTYPE_DST_WAVEIN); DestinationLine->Line.cChannels = 2; /* FIXME */ + DestinationLine->Line.cConnections = 0; + DestinationLine->Line.cControls = 0; + DestinationLine->Line.dwComponentType = (bInputMixer == 0 ? MIXERLINE_COMPONENTTYPE_DST_SPEAKERS : MIXERLINE_COMPONENTTYPE_DST_WAVEIN); + DestinationLine->Line.dwDestination = MixerInfo->MixCaps.cDestinations; + DestinationLine->Line.dwLineID = MixerInfo->MixCaps.cDestinations + DESTINATION_LINE; + DestinationLine->Line.dwSource = MAXULONG; + DestinationLine->Line.dwUser = 0; + DestinationLine->Line.fdwLine = MIXERLINE_LINEF_ACTIVE; + if (LineName) { @@ -219,7 +272,7 @@ MMixerCreateDestinationLine( } DestinationLine->Line.Target.dwType = (bInputMixer == 0 ? MIXERLINE_TARGETTYPE_WAVEOUT : MIXERLINE_TARGETTYPE_WAVEIN); - DestinationLine->Line.Target.dwDeviceID = !bInputMixer; + DestinationLine->Line.Target.dwDeviceID = 0; //FIXME DestinationLine->Line.Target.wMid = MixerInfo->MixCaps.wMid; DestinationLine->Line.Target.wPid = MixerInfo->MixCaps.wPid; DestinationLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion; @@ -228,10 +281,13 @@ MMixerCreateDestinationLine( wcscpy(DestinationLine->Line.Target.szPname, MixerInfo->MixCaps.szPname); /* initialize extra line */ - InitializeListHead(&DestinationLine->LineControlsExtraData); + InitializeListHead(&DestinationLine->ControlsList); /* insert into mixer info */ - InsertHeadList(&MixerInfo->LineList, &DestinationLine->Entry); + InsertTailList(&MixerInfo->LineList, &DestinationLine->Entry); + + /* increment destination count */ + MixerInfo->MixCaps.cDestinations++; /* done */ return MM_STATUS_SUCCESS; @@ -241,6 +297,7 @@ MIXER_STATUS MMixerGetPinName( IN PMIXER_CONTEXT MixerContext, IN LPMIXER_INFO MixerInfo, + IN HANDLE hMixer, IN ULONG PinId, IN OUT LPWSTR * OutBuffer) { @@ -257,7 +314,7 @@ MMixerGetPinName( Pin.Property.Id = KSPROPERTY_PIN_NAME; /* try get pin name size */ - Status = MixerContext->Control(MixerInfo->hMixer, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), NULL, 0, &BytesReturned); + Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), NULL, 0, &BytesReturned); /* check if buffer overflowed */ if (Status == MM_STATUS_MORE_ENTRIES) @@ -271,7 +328,7 @@ MMixerGetPinName( } /* try get pin name */ - Status = MixerContext->Control(MixerInfo->hMixer, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)Buffer, BytesReturned, &BytesReturned); + Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)Buffer, BytesReturned, &BytesReturned); if (Status != MM_STATUS_SUCCESS) { /* failed to get pin name */ @@ -292,6 +349,7 @@ MIXER_STATUS MMixerBuildMixerDestinationLine( IN PMIXER_CONTEXT MixerContext, IN OUT LPMIXER_INFO MixerInfo, + IN HANDLE hMixer, IN ULONG PinId, IN ULONG bInput) { @@ -299,7 +357,7 @@ MMixerBuildMixerDestinationLine( MIXER_STATUS Status; /* try get pin name */ - Status = MMixerGetPinName(MixerContext, MixerInfo, PinId, &PinName); + Status = MMixerGetPinName(MixerContext, MixerInfo, hMixer, PinId, &PinName); if (Status == MM_STATUS_SUCCESS) { /* create mixer destination line */ @@ -385,6 +443,7 @@ MMixerCountMixerControls( IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, IN ULONG PinId, + IN ULONG bInputMixer, IN ULONG bUpStream, OUT PULONG OutNodesCount, OUT PULONG OutNodes, @@ -424,6 +483,12 @@ MMixerCountMixerControls( if (bTerminator) { /* found terminator */ + if (bInputMixer) + { + /* add mux source for source destination line */ + OutNodes[Count] = NodeIndex; + Count++; + } break; } @@ -458,10 +523,140 @@ MMixerCountMixerControls( return MM_STATUS_SUCCESS; } +MIXER_STATUS +MMixerGetChannelCountEnhanced( + IN PMIXER_CONTEXT MixerContext, + IN LPMIXER_INFO MixerInfo, + IN HANDLE hMixer, + IN ULONG NodeId, + OUT PULONG MaxChannels) +{ + KSPROPERTY_DESCRIPTION Description; + PKSPROPERTY_DESCRIPTION NewDescription; + PKSPROPERTY_MEMBERSHEADER Header; + ULONG BytesReturned; + KSP_NODE Request; + MIXER_STATUS Status; + + /* try #1 obtain it via description */ + Request.NodeId = NodeId; + Request.Reserved = 0; + Request.Property.Set = KSPROPSETID_Audio; + Request.Property.Flags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_TOPOLOGY; + Request.Property.Id = KSPROPERTY_AUDIO_VOLUMELEVEL; + + + /* get description */ + Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSP_NODE), (PVOID)&Description, sizeof(KSPROPERTY_DESCRIPTION), &BytesReturned); + if (Status == MM_STATUS_SUCCESS) + { + if (Description.DescriptionSize >= sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) && (Description.MembersListCount > 0)) + { + /* allocate new description */ + NewDescription = MixerContext->Alloc(Description.DescriptionSize); + + if (!NewDescription) + { + /* not enough memory */ + return MM_STATUS_NO_MEMORY; + } + + /* get description */ + Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSP_NODE), (PVOID)NewDescription, Description.DescriptionSize, &BytesReturned); + if (Status == MM_STATUS_SUCCESS) + { + /* get header */ + Header = (PKSPROPERTY_MEMBERSHEADER)(NewDescription + 1); + + if (Header->Flags & KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL) + { + /* found enhanced flag */ + ASSERT(Header->MembersCount > 1); + + /* store channel count */ + *MaxChannels = Header->MembersCount; + + /* free description */ + MixerContext->Free(NewDescription); + + /* done */ + return MM_STATUS_SUCCESS; + } + } + + /* free description */ + MixerContext->Free(NewDescription); + } + } + + /* failed to get channel count enhanced */ + return MM_STATUS_UNSUCCESSFUL; +} + +VOID +MMixerGetChannelCountLegacy( + IN PMIXER_CONTEXT MixerContext, + IN LPMIXER_INFO MixerInfo, + IN HANDLE hMixer, + IN ULONG NodeId, + OUT PULONG MaxChannels) +{ + ULONG BytesReturned; + MIXER_STATUS Status; + KSNODEPROPERTY_AUDIO_CHANNEL Channel; + LONG Volume; + + /* setup request */ + Channel.Reserved = 0; + Channel.NodeProperty.NodeId = NodeId; + Channel.NodeProperty.Reserved = 0; + Channel.NodeProperty.Property.Flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_TOPOLOGY; + Channel.NodeProperty.Property.Set = KSPROPSETID_Audio; + Channel.Channel = 0; + Channel.NodeProperty.Property.Id = KSPROPERTY_AUDIO_VOLUMELEVEL; + + do + { + /* get channel volume */ + Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Channel, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL), (PVOID)&Volume, sizeof(LONG), &BytesReturned); + if (Status != MM_STATUS_SUCCESS) + break; + + /* increment channel count */ + Channel.Channel++; + + }while(TRUE); + + /* store channel count */ + *MaxChannels = Channel.Channel; + +} + +VOID +MMixerGetMaxChannelsForNode( + IN PMIXER_CONTEXT MixerContext, + IN LPMIXER_INFO MixerInfo, + IN HANDLE hMixer, + IN ULONG NodeId, + OUT PULONG MaxChannels) +{ + MIXER_STATUS Status; + + /* try to get it enhanced */ + Status = MMixerGetChannelCountEnhanced(MixerContext, MixerInfo, hMixer, NodeId, MaxChannels); + + if (Status != MM_STATUS_SUCCESS) + { + /* get it old-fashioned way */ + MMixerGetChannelCountLegacy(MixerContext, MixerInfo, hMixer, NodeId, MaxChannels); + } +} + MIXER_STATUS MMixerAddMixerControlsToMixerLineByNodeIndexArray( IN PMIXER_CONTEXT MixerContext, IN LPMIXER_INFO MixerInfo, + IN HANDLE hMixer, IN PTOPOLOGY Topology, IN OUT LPMIXERLINE_EXT DstLine, IN ULONG NodesCount, @@ -469,18 +664,8 @@ MMixerAddMixerControlsToMixerLineByNodeIndexArray( { ULONG Index, Count, bReserved; MIXER_STATUS Status; - - /* store nodes array */ - DstLine->NodeIds = Nodes; - - /* allocate MIXERCONTROLSW array */ - DstLine->LineControls = MixerContext->Alloc(NodesCount * sizeof(MIXERCONTROLW)); - - if (!DstLine->LineControls) - { - /* out of memory */ - return MM_STATUS_NO_MEMORY; - } + LPGUID NodeType; + ULONG MaxChannels; /* initialize control count */ Count = 0; @@ -489,18 +674,36 @@ MMixerAddMixerControlsToMixerLineByNodeIndexArray( { /* check if the node has already been reserved to a line */ MMixerIsTopologyNodeReserved(Topology, Nodes[Index], &bReserved); - +#if 0 /* MS lies */ if (bReserved) { /* node is already used, skip it */ continue; } - +#endif /* set node status as used */ MMixerSetTopologyNodeReserved(Topology, Nodes[Index]); + /* query node type */ + NodeType = MMixerGetNodeTypeFromTopology(Topology, Nodes[Index]); + + if (IsEqualGUIDAligned(NodeType, &KSNODETYPE_VOLUME)) + { + /* calculate maximum channel count for node */ + MMixerGetMaxChannelsForNode(MixerContext, MixerInfo, hMixer, Nodes[Index], &MaxChannels); + + DPRINT("NodeId %lu MaxChannels %lu Line %S Id %lu\n", Nodes[Index], MaxChannels, DstLine->Line.szName, DstLine->Line.dwLineID); + /* calculate maximum channels */ + DstLine->Line.cChannels = min(DstLine->Line.cChannels, MaxChannels); + } + else + { + /* use default of one channel */ + MaxChannels = 1; + } + /* now add the mixer control */ - Status = MMixerAddMixerControl(MixerContext, MixerInfo, Topology, Nodes[Index], DstLine, &DstLine->LineControls[Count]); + Status = MMixerAddMixerControl(MixerContext, MixerInfo, hMixer, Topology, Nodes[Index], DstLine, MaxChannels); if (Status == MM_STATUS_SUCCESS) { @@ -516,19 +719,230 @@ MMixerAddMixerControlsToMixerLineByNodeIndexArray( return MM_STATUS_SUCCESS; } +MIXER_STATUS +MMixerGetComponentAndTargetType( + IN PMIXER_CONTEXT MixerContext, + IN OUT LPMIXER_INFO MixerInfo, + IN HANDLE hMixer, + IN ULONG PinId, + OUT PULONG ComponentType, + OUT PULONG TargetType) +{ + KSPIN_DATAFLOW DataFlow; + KSPIN_COMMUNICATION Communication; + MIXER_STATUS Status; + KSP_PIN Request; + ULONG BytesReturned; + GUID Guid; + BOOLEAN BridgePin = FALSE; + PKSPIN_PHYSICALCONNECTION Connection; + + /* first dataflow type */ + Status = MMixerGetPinDataFlowAndCommunication(MixerContext, hMixer, PinId, &DataFlow, &Communication); + + if (Status != MM_STATUS_SUCCESS) + { + /* failed to get dataflow */ + return Status; + } + + /* now get pin category guid */ + Request.PinId = PinId; + Request.Reserved = 0; + Request.Property.Flags = KSPROPERTY_TYPE_GET; + Request.Property.Set = KSPROPSETID_Pin; + Request.Property.Id = KSPROPERTY_PIN_CATEGORY; + + + /* get pin category */ + Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSP_PIN), &Guid, sizeof(GUID), &BytesReturned); + if (Status != MM_STATUS_SUCCESS) + { + /* failed to get dataflow */ + return Status; + } + + /* check if it has a physical connection */ + Status = MMixerGetPhysicalConnection(MixerContext, hMixer, PinId, &Connection); + if (Status == MM_STATUS_SUCCESS) + { + /* pin is a brige pin */ + BridgePin = TRUE; + + /* free physical connection */ + MixerContext->Free(Connection); + } + + if (DataFlow == KSPIN_DATAFLOW_IN) + { + if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_MICROPHONE) || + IsEqualGUIDAligned(&Guid, &KSNODETYPE_DESKTOP_MICROPHONE)) + { + /* type microphone */ + *TargetType = MIXERLINE_TARGETTYPE_WAVEIN; + *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE; + } + else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_LEGACY_AUDIO_CONNECTOR) || + IsEqualGUIDAligned(&Guid, &KSCATEGORY_AUDIO) || + IsEqualGUIDAligned(&Guid, &KSNODETYPE_SPEAKER)) + { + /* type waveout */ + *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT; + *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT; + } + else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_CD_PLAYER)) + { + /* type cd player */ + *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED; + *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC; + } + else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_SYNTHESIZER)) + { + /* type synthesizer */ + *TargetType = MIXERLINE_TARGETTYPE_MIDIOUT; + *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER; + } + else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_LINE_CONNECTOR)) + { + /* type line */ + *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED; + *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_LINE; + } + else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_TELEPHONE) || + IsEqualGUIDAligned(&Guid, &KSNODETYPE_PHONE_LINE) || + IsEqualGUIDAligned(&Guid, &KSNODETYPE_DOWN_LINE_PHONE)) + { + /* type telephone */ + *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED; + *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE; + } + else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_ANALOG_CONNECTOR)) + { + /* type analog */ + if (BridgePin) + *TargetType = MIXERLINE_TARGETTYPE_WAVEIN; + else + *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT; + + *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_ANALOG; + } + else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_SPDIF_INTERFACE)) + { + /* type analog */ + if (BridgePin) + *TargetType = MIXERLINE_TARGETTYPE_WAVEIN; + else + *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT; + + *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_DIGITAL; + } + else + { + /* unknown type */ + *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED; + *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED; + DPRINT1("Unknown Category for PinId %lu BridgePin %lu\n", PinId, BridgePin); + } + } + else + { + if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_SPEAKER) || + IsEqualGUIDAligned(&Guid, &KSNODETYPE_DESKTOP_SPEAKER) || + IsEqualGUIDAligned(&Guid, &KSNODETYPE_ROOM_SPEAKER) || + IsEqualGUIDAligned(&Guid, &KSNODETYPE_COMMUNICATION_SPEAKER)) + { + /* type waveout */ + *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT; + *ComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; + } + else if (IsEqualGUIDAligned(&Guid, &KSCATEGORY_AUDIO) || + IsEqualGUIDAligned(&Guid, &PINNAME_CAPTURE)) + { + /* type wavein */ + *TargetType = MIXERLINE_TARGETTYPE_WAVEIN; + *ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN; + } + else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_HEADPHONES) || + IsEqualGUIDAligned(&Guid, &KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO)) + { + /* type head phones */ + *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT; + *ComponentType = MIXERLINE_COMPONENTTYPE_DST_HEADPHONES; + } + else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_TELEPHONE) || + IsEqualGUIDAligned(&Guid, &KSNODETYPE_PHONE_LINE) || + IsEqualGUIDAligned(&Guid, &KSNODETYPE_DOWN_LINE_PHONE)) + { + /* type waveout */ + *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED; + *ComponentType = MIXERLINE_COMPONENTTYPE_DST_TELEPHONE; + } + else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_ANALOG_CONNECTOR)) + { + /* type analog */ + if (BridgePin) + { + *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT; + *ComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; + } + else + { + *TargetType = MIXERLINE_TARGETTYPE_WAVEIN; + *ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN; + } + } + else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_SPDIF_INTERFACE)) + { + /* type spdif */ + if (BridgePin) + { + *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT; + *ComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; + } + else + { + *TargetType = MIXERLINE_TARGETTYPE_WAVEIN; + *ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN; + } + } + else + { + /* unknown type */ + *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED; + *ComponentType = MIXERLINE_COMPONENTTYPE_DST_UNDEFINED; + DPRINT1("Unknown Category for PinId %lu BridgePin %lu\n", PinId, BridgePin); + } + } + + /* done */ + return MM_STATUS_SUCCESS; +} + MIXER_STATUS MMixerBuildMixerSourceLine( IN PMIXER_CONTEXT MixerContext, IN OUT LPMIXER_INFO MixerInfo, + IN HANDLE hMixer, IN PTOPOLOGY Topology, IN ULONG PinId, IN ULONG NodesCount, IN PULONG Nodes, + IN ULONG DestinationLineID, OUT LPMIXERLINE_EXT * OutSrcLine) { LPMIXERLINE_EXT SrcLine, DstLine; LPWSTR PinName; MIXER_STATUS Status; + ULONG ComponentType, TargetType; + + /* get component and target type */ + Status = MMixerGetComponentAndTargetType(MixerContext, MixerInfo, hMixer, PinId, &ComponentType, &TargetType); + if (Status != MM_STATUS_SUCCESS) + { + /* failed to get component status */ + TargetType = MIXERLINE_TARGETTYPE_UNDEFINED; + ComponentType = MIXERLINE_COMPONENTTYPE_DST_UNDEFINED; + } /* construct source line */ SrcLine = (LPMIXERLINE_EXT)MixerContext->Alloc(sizeof(MIXERLINE_EXT)); @@ -540,36 +954,35 @@ MMixerBuildMixerSourceLine( } /* get destination line */ - DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE); + DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID); ASSERT(DstLine); /* initialize mixer src line */ - SrcLine->hDevice = MixerInfo->hMixer; SrcLine->PinId = PinId; - SrcLine->NodeIds = Nodes; /* initialize mixer line */ SrcLine->Line.cbStruct = sizeof(MIXERLINEW); - SrcLine->Line.dwDestination = 0; + SrcLine->Line.dwDestination = MixerInfo->MixCaps.cDestinations-1; SrcLine->Line.dwSource = DstLine->Line.cConnections; - SrcLine->Line.dwLineID = (DstLine->Line.cConnections * 0x10000); + SrcLine->Line.dwLineID = (DstLine->Line.cConnections * SOURCE_LINE)+ (MixerInfo->MixCaps.cDestinations-1); SrcLine->Line.fdwLine = MIXERLINE_LINEF_ACTIVE | MIXERLINE_LINEF_SOURCE; + SrcLine->Line.dwComponentType = ComponentType; SrcLine->Line.dwUser = 0; SrcLine->Line.cChannels = DstLine->Line.cChannels; SrcLine->Line.cConnections = 0; - SrcLine->Line.Target.dwType = 1; + SrcLine->Line.Target.dwType = TargetType; SrcLine->Line.Target.dwDeviceID = DstLine->Line.Target.dwDeviceID; SrcLine->Line.Target.wMid = MixerInfo->MixCaps.wMid; SrcLine->Line.Target.wPid = MixerInfo->MixCaps.wPid; SrcLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion; - InitializeListHead(&SrcLine->LineControlsExtraData); + InitializeListHead(&SrcLine->ControlsList); /* copy name */ ASSERT(MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] == L'\0'); wcscpy(SrcLine->Line.Target.szPname, MixerInfo->MixCaps.szPname); /* get pin name */ - Status = MMixerGetPinName(MixerContext, MixerInfo, PinId, &PinName); + Status = MMixerGetPinName(MixerContext, MixerInfo, hMixer, PinId, &PinName); if (Status == MM_STATUS_SUCCESS) { @@ -585,7 +998,7 @@ MMixerBuildMixerSourceLine( } /* add the controls to mixer line */ - Status = MMixerAddMixerControlsToMixerLineByNodeIndexArray(MixerContext, MixerInfo, Topology, SrcLine, NodesCount, Nodes); + Status = MMixerAddMixerControlsToMixerLineByNodeIndexArray(MixerContext, MixerInfo, hMixer, Topology, SrcLine, NodesCount, Nodes); if (Status != MM_STATUS_SUCCESS) { /* failed */ @@ -602,7 +1015,9 @@ MIXER_STATUS MMixerAddMixerSourceLines( IN PMIXER_CONTEXT MixerContext, IN OUT LPMIXER_INFO MixerInfo, + IN HANDLE hMixer, IN PTOPOLOGY Topology, + IN ULONG DestinationLineID, IN ULONG LineTerminator) { PULONG AllNodes, AllPins, AllPinNodes; @@ -612,7 +1027,7 @@ MMixerAddMixerSourceLines( LPMIXERLINE_EXT DstLine, SrcLine; /* get destination line */ - DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE); + DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID); ASSERT(DstLine); /* allocate an array to store all nodes which are upstream of the line terminator */ @@ -693,8 +1108,11 @@ MMixerAddMixerSourceLines( if (AllPinNodesCount) { +#ifdef MMIXER_DEBUG + ULONG TempIndex; +#endif /* now build the mixer source line */ - Status = MMixerBuildMixerSourceLine(MixerContext, MixerInfo, Topology, PinId, AllPinNodesCount, AllPinNodes, &SrcLine); + Status = MMixerBuildMixerSourceLine(MixerContext, MixerInfo, hMixer, Topology, PinId, AllPinNodesCount, AllPinNodes, DestinationLineID, &SrcLine); if (Status == MM_STATUS_SUCCESS) { @@ -703,8 +1121,23 @@ MMixerAddMixerSourceLines( /* increment destination line count */ DstLine->Line.cConnections++; + + /* mark pin as reserved */ + MMixerSetTopologyPinReserved(Topology, PinId); + +#ifdef MMIXER_DEBUG + DPRINT1("Adding PinId %lu AllPinNodesCount %lu to DestinationLine %lu\n", PinId, AllPinNodesCount, DestinationLineID); + for(TempIndex = 0; TempIndex < AllPinNodesCount; TempIndex++) + DPRINT1("NodeIndex %lu\n", AllPinNodes[TempIndex]); +#endif } } + else + { +#ifdef MMIXER_DEBUG + DPRINT1("Discarding DestinationLineID %lu PinId %lu NO NODES!\n", DestinationLineID, PinId); +#endif + } }while(Index != 0); @@ -716,9 +1149,11 @@ MIXER_STATUS MMixerAddMixerControlsToDestinationLine( IN PMIXER_CONTEXT MixerContext, IN OUT LPMIXER_INFO MixerInfo, + IN HANDLE hMixer, IN PTOPOLOGY Topology, IN ULONG PinId, IN ULONG bInput, + IN ULONG DestinationLineId, OUT PULONG OutLineTerminator) { PULONG Nodes; @@ -737,7 +1172,7 @@ MMixerAddMixerControlsToDestinationLine( } /* get all destination line controls */ - Status = MMixerCountMixerControls(MixerContext, Topology, PinId, TRUE, &NodesCount, Nodes, &LineTerminator); + Status = MMixerCountMixerControls(MixerContext, Topology, PinId, bInput, TRUE, &NodesCount, Nodes, &LineTerminator); /* check for success */ if (Status != MM_STATUS_SUCCESS) @@ -748,7 +1183,7 @@ MMixerAddMixerControlsToDestinationLine( } /* get destination mixer line */ - DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE); + DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineId); /* sanity check */ ASSERT(DstLine); @@ -756,7 +1191,7 @@ MMixerAddMixerControlsToDestinationLine( if (NodesCount > 0) { /* add all nodes as mixer controls to the destination line */ - Status = MMixerAddMixerControlsToMixerLineByNodeIndexArray(MixerContext, MixerInfo, Topology, DstLine, NodesCount, Nodes); + Status = MMixerAddMixerControlsToMixerLineByNodeIndexArray(MixerContext, MixerInfo, hMixer, Topology, DstLine, NodesCount, Nodes); if (Status != MM_STATUS_SUCCESS) { /* failed to add controls */ @@ -776,6 +1211,7 @@ VOID MMixerApplyOutputFilterHack( IN PMIXER_CONTEXT MixerContext, IN LPMIXER_DATA MixerData, + IN HANDLE hMixer, IN OUT PULONG PinsCount, IN OUT PULONG Pins) { @@ -786,7 +1222,7 @@ MMixerApplyOutputFilterHack( for(Index = 0; Index < *PinsCount; Index++) { /* check if it has a physical connection */ - Status = MMixerGetPhysicalConnection(MixerContext, MixerData->hDevice, Pins[Index], &Connection); + Status = MMixerGetPhysicalConnection(MixerContext, hMixer, Pins[Index], &Connection); if (Status == MM_STATUS_SUCCESS) { @@ -823,7 +1259,7 @@ MMixerHandlePhysicalConnection( IN PKSPIN_PHYSICALCONNECTION OutConnection) { MIXER_STATUS Status; - ULONG PinsCount, LineTerminator; + ULONG PinsCount, LineTerminator, DestinationLineID; PULONG Pins; PTOPOLOGY Topology; @@ -840,23 +1276,44 @@ MMixerHandlePhysicalConnection( DPRINT("Name %S, Pin %lu bInput %lu\n", OutConnection->SymbolicLinkName, OutConnection->Pin, bInput); - /* store connected mixer handle */ - MixerInfo->hMixer = MixerData->hDevice; + /* sanity check */ + ASSERT(MixerData->MixerInfo == NULL || MixerData->MixerInfo == MixerInfo); + /* associate with mixer */ + MixerData->MixerInfo = MixerInfo; - Status = MMixerBuildTopology(MixerContext, MixerData, &Topology); - if (Status != MM_STATUS_SUCCESS) + if (MixerData->Topology == NULL) { - /* failed to create topology */ - return Status; + /* construct new topology */ + Status = MMixerBuildTopology(MixerContext, MixerData, &Topology); + if (Status != MM_STATUS_SUCCESS) + { + /* failed to create topology */ + return Status; + } + + /* store topology */ + MixerData->Topology = Topology; + } + else + { + /* re-use existing topology */ + Topology = MixerData->Topology; } - /* allocate pin index array which will hold all referenced pins */ - Status = MMixerAllocateTopologyPinArray(MixerContext, Topology, &Pins); - ASSERT(Status == MM_STATUS_SUCCESS); + /* mark pin as consumed */ + MMixerSetTopologyPinReserved(Topology, OutConnection->Pin); if (!bInput) { + /* allocate pin index array which will hold all referenced pins */ + Status = MMixerAllocateTopologyPinArray(MixerContext, Topology, &Pins); + if (Status != MM_STATUS_SUCCESS) + { + /* failed to create topology */ + return Status; + } + /* the mixer is an output mixer * find end pin of the node path */ @@ -878,88 +1335,111 @@ MMixerHandlePhysicalConnection( * WorkArround: remove all pin ids which have a physical connection * because bridge pins may belong to different render paths */ - MMixerApplyOutputFilterHack(MixerContext, MixerData, &PinsCount, Pins); + MMixerApplyOutputFilterHack(MixerContext, MixerData, MixerData->hDevice, &PinsCount, Pins); /* sanity checks */ ASSERT(PinsCount != 0); ASSERT(PinsCount == 1); /* create destination line */ - Status = MMixerBuildMixerDestinationLine(MixerContext, MixerInfo, Pins[0], bInput); + Status = MMixerBuildMixerDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Pins[0], bInput); + + /* calculate destination line id */ + DestinationLineID = (DESTINATION_LINE + MixerInfo->MixCaps.cDestinations-1); if (Status != MM_STATUS_SUCCESS) { + /* failed to build destination line */ MixerContext->Free(Pins); - //MMixerFreeTopology(Topology); /* return error code */ return Status; } /* add mixer controls to destination line */ - Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, Topology, Pins[0], bInput, &LineTerminator); + Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Topology, Pins[0], bInput, DestinationLineID, &LineTerminator); if (Status == MM_STATUS_SUCCESS) { /* now add the rest of the source lines */ - Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, Topology, LineTerminator); + Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, MixerData->hDevice, Topology, DestinationLineID, LineTerminator); } + + /* mark pin as consumed */ + MMixerSetTopologyPinReserved(Topology, Pins[0]); + + /* free topology pin array */ + MixerContext->Free(Pins); } else { - Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, Topology, OutConnection->Pin, bInput, &LineTerminator); + /* calculate destination line id */ + DestinationLineID = (DESTINATION_LINE + MixerInfo->MixCaps.cDestinations-1); + + /* add mixer controls */ + Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Topology, OutConnection->Pin, bInput, DestinationLineID, &LineTerminator); if (Status == MM_STATUS_SUCCESS) { /* now add the rest of the source lines */ - Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, Topology, LineTerminator); + Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, MixerData->hDevice, Topology, DestinationLineID, LineTerminator); } } - /* free topology */ - //MMixerFreeTopology(Topology); - return Status; } - MIXER_STATUS MMixerInitializeFilter( IN PMIXER_CONTEXT MixerContext, IN PMIXER_LIST MixerList, IN LPMIXER_DATA MixerData, + IN LPMIXER_INFO MixerInfo, IN PTOPOLOGY Topology, IN ULONG NodeIndex, - IN ULONG bInputMixer) + IN ULONG bInputMixer, + IN OUT LPMIXER_INFO * OutMixerInfo) { - LPMIXER_INFO MixerInfo; + ULONG Index; MIXER_STATUS Status; PKSPIN_PHYSICALCONNECTION OutConnection; ULONG * Pins; ULONG PinsFound; + ULONG NewMixerInfo = FALSE; - /* allocate a mixer info struct */ - MixerInfo = (LPMIXER_INFO) MixerContext->Alloc(sizeof(MIXER_INFO)); - if (!MixerInfo) + if (MixerInfo == NULL) { - /* no memory */ - return MM_STATUS_NO_MEMORY; + /* allocate a mixer info struct */ + MixerInfo = (LPMIXER_INFO) MixerContext->Alloc(sizeof(MIXER_INFO)); + if (!MixerInfo) + { + /* no memory */ + return MM_STATUS_NO_MEMORY; + } + + /* new mixer info */ + NewMixerInfo = TRUE; + + /* intialize mixer caps */ + MixerInfo->MixCaps.wMid = MM_MICROSOFT; /* FIXME */ + MixerInfo->MixCaps.wPid = MM_PID_UNMAPPED; /* FIXME */ + MixerInfo->MixCaps.vDriverVersion = 1; /* FIXME */ + MixerInfo->MixCaps.fdwSupport = 0; + MixerInfo->MixCaps.cDestinations = 0; + + /* get mixer name */ + MMixerGetDeviceName(MixerContext, MixerInfo->MixCaps.szPname, MixerData->hDeviceInterfaceKey); + + /* initialize line list */ + InitializeListHead(&MixerInfo->LineList); + InitializeListHead(&MixerInfo->EventList); + + /* associate with mixer data */ + MixerData->MixerInfo = MixerInfo; } - /* intialize mixer caps */ - MixerInfo->MixCaps.wMid = MM_MICROSOFT; /* FIXME */ - MixerInfo->MixCaps.wPid = MM_PID_UNMAPPED; /* FIXME */ - MixerInfo->MixCaps.vDriverVersion = 1; /* FIXME */ - MixerInfo->MixCaps.fdwSupport = 0; - MixerInfo->MixCaps.cDestinations = 1; - MixerInfo->hMixer = MixerData->hDevice; - - /* get mixer name */ - MMixerGetDeviceName(MixerContext, MixerInfo->MixCaps.szPname, MixerData->hDeviceInterfaceKey); - - /* initialize line list */ - InitializeListHead(&MixerInfo->LineList); - InitializeListHead(&MixerInfo->EventList); + /* store mixer info */ + *OutMixerInfo = MixerInfo; /* now allocate an array which will receive the indices of the pin * which has a ADC / DAC nodetype in its path @@ -977,7 +1457,7 @@ MMixerInitializeFilter( PinsFound = 0; MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, NodeIndex, !bInputMixer, &PinsFound, Pins); - /* if there is now pin found, we have a broken topology */ + /* if there is no pin found, we have a broken topology */ ASSERT(PinsFound != 0); /* now create a wave info struct */ @@ -990,10 +1470,16 @@ MMixerInitializeFilter( return Status; } + /* mark all found pins as reserved */ + for(Index = 0; Index < PinsFound; Index++) + { + MMixerSetTopologyPinReserved(Topology, Pins[Index]); + } + if (bInputMixer) { /* pre create the mixer destination line for input mixers */ - Status = MMixerBuildMixerDestinationLine(MixerContext, MixerInfo, Pins[0], bInputMixer); + Status = MMixerBuildMixerDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Pins[0], bInputMixer); if (Status != MM_STATUS_SUCCESS) { @@ -1027,6 +1513,9 @@ MMixerInitializeFilter( if (Status == MM_STATUS_SUCCESS) { + /* mark pin as reserved */ + MMixerSetTopologyPinReserved(Topology, Pins[0]); + /* topology on the topoloy filter */ Status = MMixerHandlePhysicalConnection(MixerContext, MixerList, MixerData, MixerInfo, bInputMixer, OutConnection); @@ -1044,26 +1533,91 @@ MMixerInitializeFilter( /* free pins */ MixerContext->Free(Pins); - if (!bInputMixer && MixerList->MixerListCount == 1) + if (NewMixerInfo) { - /* FIXME preferred device should be inserted at front - * windows always inserts output mixer in front - */ + /* insert mixer */ InsertHeadList(&MixerList->MixerList, &MixerInfo->Entry); + /* increment mixer count */ + MixerList->MixerListCount++; } - else - { - /* insert at back */ - InsertTailList(&MixerList->MixerList, &MixerInfo->Entry); - } - - /* increment mixer count */ - MixerList->MixerListCount++; /* done */ return Status; } +VOID +MMixerHandleAlternativeMixers( + IN PMIXER_CONTEXT MixerContext, + IN PMIXER_LIST MixerList, + IN LPMIXER_DATA MixerData, + IN PTOPOLOGY Topology) +{ + ULONG Index, PinCount, Reserved; + MIXER_STATUS Status; + ULONG DestinationLineID, LineTerminator; + LPMIXERLINE_EXT DstLine; + + DPRINT("DeviceName %S\n", MixerData->DeviceName); + + /* get topology pin count */ + MMixerGetTopologyPinCount(Topology, &PinCount); + + for(Index = 0; Index < PinCount; Index++) + { + MMixerIsTopologyPinReserved(Topology, Index, &Reserved); + + /* check if it has already been reserved */ + if (Reserved == TRUE) + { + /* pin has already been reserved */ + continue; + } + + DPRINT("MixerName %S Available PinID %lu\n", MixerData->DeviceName, Index); + + /* sanity check */ + //ASSERT(MixerData->MixerInfo); + + if (!MixerData->MixerInfo) + { + DPRINT1("Expected mixer info\n"); + continue; + } + + /* build the destination line */ + Status = MMixerBuildMixerDestinationLine(MixerContext, MixerData->MixerInfo, MixerData->hDevice, Index, TRUE); + if (Status != MM_STATUS_SUCCESS) + { + /* failed to build destination line */ + continue; + } + + /* calculate destination line id */ + DestinationLineID = (DESTINATION_LINE + MixerData->MixerInfo->MixCaps.cDestinations-1); + + /* add mixer controls to destination line */ + Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerData->MixerInfo, MixerData->hDevice, MixerData->Topology, Index, TRUE, DestinationLineID, &LineTerminator); + if (Status == MM_STATUS_SUCCESS) + { + /* now add the rest of the source lines */ + Status = MMixerAddMixerSourceLines(MixerContext, MixerData->MixerInfo, MixerData->hDevice, MixerData->Topology, DestinationLineID, LineTerminator); + } + + /* mark pin as consumed */ + MMixerSetTopologyPinReserved(Topology, Index); + + /* now grab destination line */ + DstLine = MMixerGetSourceMixerLineByLineId(MixerData->MixerInfo, DestinationLineID); + + /* set type and target as undefined */ + DstLine->Line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_UNDEFINED; + DstLine->Line.Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED; + DstLine->Line.Target.vDriverVersion = 0; + DstLine->Line.Target.wMid = 0; + DstLine->Line.Target.wPid = 0; + } +} + MIXER_STATUS MMixerSetupFilter( IN PMIXER_CONTEXT MixerContext, @@ -1074,6 +1628,7 @@ MMixerSetupFilter( MIXER_STATUS Status; PTOPOLOGY Topology; ULONG NodeIndex; + LPMIXER_INFO MixerInfo = NULL; /* check if topology has already been built */ if (MixerData->Topology == NULL) @@ -1101,7 +1656,7 @@ MMixerSetupFilter( if (NodeIndex != MAXULONG) { /* it has */ - Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, Topology, NodeIndex, FALSE); + Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, NULL, Topology, NodeIndex, FALSE, &MixerInfo); /* check for success */ if (Status == MM_STATUS_SUCCESS) @@ -1109,7 +1664,11 @@ MMixerSetupFilter( /* increment mixer count */ (*DeviceCount)++; } - + else + { + /* reset mixer info in case of error */ + MixerInfo = NULL; + } } /* check if the filter has an wave in node */ @@ -1117,7 +1676,7 @@ MMixerSetupFilter( if (NodeIndex != MAXULONG) { /* it has */ - Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, Topology, NodeIndex, TRUE); + Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, MixerInfo, Topology, NodeIndex, TRUE, &MixerInfo); /* check for success */ if (Status == MM_STATUS_SUCCESS) @@ -1128,8 +1687,10 @@ MMixerSetupFilter( } + /* TODO: apply hacks for Wave source line */ + /* activate midi devices */ - MMixerInitializeMidiForFilter(MixerContext, MixerList, MixerData, Topology); + //MMixerInitializeMidiForFilter(MixerContext, MixerList, MixerData, Topology); /* done */ return Status; @@ -1175,7 +1736,7 @@ MMixerAddEvent( /* initialize notification entry */ EventData->MixerEventContext = MixerEventContext; - EventData->MixerEventRoutine; + EventData->MixerEventRoutine = MixerEventRoutine; /* store event */ InsertTailList(&MixerInfo->EventList, &EventData->Entry); diff --git a/lib/drivers/sound/mmixer/midi.c b/lib/drivers/sound/mmixer/midi.c index e60d14999c2..4809c910eab 100644 --- a/lib/drivers/sound/mmixer/midi.c +++ b/lib/drivers/sound/mmixer/midi.c @@ -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) { diff --git a/lib/drivers/sound/mmixer/mixer.c b/lib/drivers/sound/mmixer/mixer.c index b04b50c702f..980a49e6bce 100644 --- a/lib/drivers/sound/mmixer/mixer.c +++ b/lib/drivers/sound/mmixer/mixer.c @@ -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; } diff --git a/lib/drivers/sound/mmixer/mmixer.h b/lib/drivers/sound/mmixer/mmixer.h index 846d4e9d83b..5cd530abffa 100644 --- a/lib/drivers/sound/mmixer/mmixer.h +++ b/lib/drivers/sound/mmixer/mmixer.h @@ -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, diff --git a/lib/drivers/sound/mmixer/priv.h b/lib/drivers/sound/mmixer/priv.h index 8a4855f8ca8..3746f6d247b 100644 --- a/lib/drivers/sound/mmixer/priv.h +++ b/lib/drivers/sound/mmixer/priv.h @@ -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); diff --git a/lib/drivers/sound/mmixer/sup.c b/lib/drivers/sound/mmixer/sup.c index 126bcb53662..9052e94fb9c 100644 --- a/lib/drivers/sound/mmixer/sup.c +++ b/lib/drivers/sound/mmixer/sup.c @@ -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; } diff --git a/lib/drivers/sound/mmixer/topology.c b/lib/drivers/sound/mmixer/topology.c index 44e85da9c22..c1d4c3d1051 100644 --- a/lib/drivers/sound/mmixer/topology.c +++ b/lib/drivers/sound/mmixer/topology.c @@ -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, diff --git a/lib/drivers/sound/mmixer/wave.c b/lib/drivers/sound/mmixer/wave.c index c48f03bba58..1d39f37c479 100644 --- a/lib/drivers/sound/mmixer/wave.c +++ b/lib/drivers/sound/mmixer/wave.c @@ -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, diff --git a/lib/lsalib/lsa.c b/lib/lsalib/lsa.c index 94cd6af8e16..31c2aeb197f 100644 --- a/lib/lsalib/lsa.c +++ b/lib/lsalib/lsa.c @@ -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; diff --git a/subsystems/win32/win32k/ntuser/painting.c b/subsystems/win32/win32k/ntuser/painting.c index 53f7b41d1ee..c9bc3146a60 100644 --- a/subsystems/win32/win32k/ntuser/painting.c +++ b/subsystems/win32/win32k/ntuser/painting.c @@ -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); diff --git a/subsystems/win32/win32k/ntuser/timer.c b/subsystems/win32/win32k/ntuser/timer.c index b99c918b566..401caadd306 100644 --- a/subsystems/win32/win32k/ntuser/timer.c +++ b/subsystems/win32/win32k/ntuser/timer.c @@ -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; }