diff --git a/base/applications/taskmgr/taskmgr.c b/base/applications/taskmgr/taskmgr.c index 3f8bcbd9a4a..c409f808b1f 100644 --- a/base/applications/taskmgr/taskmgr.c +++ b/base/applications/taskmgr/taskmgr.c @@ -869,6 +869,7 @@ void TaskManager_OnTabWndSelChange(void) HMENU hViewMenu; HMENU hSubMenu; WCHAR szTemp[256]; + SYSTEM_INFO sysInfo; hMenu = GetMenu(hMainWnd); hViewMenu = GetSubMenu(hMenu, 2); @@ -947,16 +948,28 @@ void TaskManager_OnTabWndSelChange(void) DeleteMenu(hMenu, 3, MF_BYPOSITION); DrawMenuBar(hMainWnd); } - hSubMenu = CreatePopupMenu(); - LoadStringW(hInst, IDS_MENU_ONEGRAPHALLCPUS, szTemp, 256); - AppendMenuW(hSubMenu, MF_STRING, ID_VIEW_CPUHISTORY_ONEGRAPHALL, szTemp); + GetSystemInfo(&sysInfo); - LoadStringW(hInst, IDS_MENU_ONEGRAPHPERCPU, szTemp, 256); - AppendMenuW(hSubMenu, MF_STRING, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, szTemp); + /* Hide CPU graph options on single CPU systems */ + if (sysInfo.dwNumberOfProcessors > 1) + { + hSubMenu = CreatePopupMenu(); - LoadStringW(hInst, IDS_MENU_CPUHISTORY, szTemp, 256); - AppendMenuW(hViewMenu, MF_STRING|MF_POPUP, (UINT_PTR) hSubMenu, szTemp); + LoadStringW(hInst, IDS_MENU_ONEGRAPHALLCPUS, szTemp, 256); + AppendMenuW(hSubMenu, MF_STRING, ID_VIEW_CPUHISTORY_ONEGRAPHALL, szTemp); + + LoadStringW(hInst, IDS_MENU_ONEGRAPHPERCPU, szTemp, 256); + AppendMenuW(hSubMenu, MF_STRING, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, szTemp); + + LoadStringW(hInst, IDS_MENU_CPUHISTORY, szTemp, 256); + AppendMenuW(hViewMenu, MF_STRING|MF_POPUP, (UINT_PTR) hSubMenu, szTemp); + + if (TaskManagerSettings.CPUHistory_OneGraphPerCPU) + CheckMenuRadioItem(hSubMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, MF_BYCOMMAND); + else + CheckMenuRadioItem(hSubMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHALL, MF_BYCOMMAND); + } LoadStringW(hInst, IDS_MENU_SHOWKERNELTIMES, szTemp, 256); AppendMenuW(hViewMenu, MF_STRING, ID_VIEW_SHOWKERNELTIMES, szTemp); @@ -965,10 +978,7 @@ void TaskManager_OnTabWndSelChange(void) CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_CHECKED); else CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_UNCHECKED); - if (TaskManagerSettings.CPUHistory_OneGraphPerCPU) - CheckMenuRadioItem(hSubMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, MF_BYCOMMAND); - else - CheckMenuRadioItem(hSubMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHALL, MF_BYCOMMAND); + /* * Give the tab control focus */ diff --git a/base/shell/cmd/console.c b/base/shell/cmd/console.c index 18541bf389f..8184af747ea 100644 --- a/base/shell/cmd/console.c +++ b/base/shell/cmd/console.c @@ -166,7 +166,7 @@ VOID ConOutChar (TCHAR c) VOID ConPuts(LPTSTR szText, DWORD nStdHandle) { ConWrite(szText, _tcslen(szText), nStdHandle); - ConWrite(_T("\n"), 1, nStdHandle); + ConWrite(_T("\r\n"), 2, nStdHandle); } VOID ConOutResPaging(BOOL NewPage, UINT resID) diff --git a/base/shell/cmd/filecomp.c b/base/shell/cmd/filecomp.c index 4ca8b837311..7cb99a72f12 100644 --- a/base/shell/cmd/filecomp.c +++ b/base/shell/cmd/filecomp.c @@ -703,7 +703,7 @@ VOID CompleteFilename (LPTSTR strIN, BOOL bNext, LPTSTR strOut, UINT cusor) LastSpace = i; } - /* insert the quoation and move things around */ + /* insert the quotation and move things around */ if(szPrefix[LastSpace + 1] != _T('\"') && LastSpace != -1) { memmove ( &szPrefix[LastSpace+1], &szPrefix[LastSpace], (_tcslen(szPrefix)-LastSpace+1) * sizeof(TCHAR) ); @@ -712,14 +712,17 @@ VOID CompleteFilename (LPTSTR strIN, BOOL bNext, LPTSTR strOut, UINT cusor) { _tcscat(szPrefix,_T("\"")); } - szPrefix[LastSpace + 1] = _T('\"'); + szPrefix[LastSpace + 1] = _T('\"'); } else if(LastSpace == -1) { - _tcscpy(szBaseWord,_T("\"")); - _tcscat(szBaseWord,szPrefix); - _tcscpy(szPrefix,szBaseWord); - + /* Add quotation only if none exists already */ + if (szPrefix[0] != _T('\"')) + { + _tcscpy(szBaseWord,_T("\"")); + _tcscat(szBaseWord,szPrefix); + _tcscpy(szPrefix,szBaseWord); + } } } diff --git a/base/shell/explorer/utility/window.cpp b/base/shell/explorer/utility/window.cpp index cfbce1db79f..296f3cebd16 100644 --- a/base/shell/explorer/utility/window.cpp +++ b/base/shell/explorer/utility/window.cpp @@ -268,7 +268,7 @@ LRESULT CALLBACK Window::WindowWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPAR case WM_CREATE: return pThis->Init((LPCREATESTRUCT)lparam); - case WM_NCDESTROY: + case WM_NCDESTROY: delete pThis; return 0; diff --git a/base/system/format/format.c b/base/system/format/format.c index 59f9f302a0a..ba9f42b3a05 100755 --- a/base/system/format/format.c +++ b/base/system/format/format.c @@ -363,6 +363,12 @@ _tmain(int argc, TCHAR *argv[]) PrintWin32Error( szMsg, GetLastError()); return -1; } + else if ( driveType == 1 ) + { + LoadString( GetModuleHandle(NULL), STRING_NO_VOLUME, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); + PrintWin32Error( szMsg, GetLastError()); + return -1; + } if( driveType != DRIVE_FIXED ) { LoadString( GetModuleHandle(NULL), STRING_INSERT_DISK, (LPTSTR) szMsg,RC_STRING_MAX_SIZE); diff --git a/boot/bootdata/packages/reactos.dff b/boot/bootdata/packages/reactos.dff index 49d33a7067a..e4caa7b4367 100644 --- a/boot/bootdata/packages/reactos.dff +++ b/boot/bootdata/packages/reactos.dff @@ -487,11 +487,13 @@ drivers\base\beep\beep.sys 2 drivers\base\null\null.sys 2 drivers\base\nmidebug\nmidebug.sys 2 -drivers\battery\cmbatt\cmbatt.sys 2 drivers\battery\battc\battc.sys 2 drivers\bus\isapnp\isapnp.sys 2 +drivers\bus\acpi\cmbatt\cmbatt.sys 2 +drivers\bus\acpi\compbatt\compbatt.sys 2 + drivers\directx\dxapi\dxapi.sys 2 drivers\directx\dxg\dxg.sys 2 drivers\directx\dxgthk\dxgthk.sys 2 diff --git a/boot/bootdata/txtsetup.sif b/boot/bootdata/txtsetup.sif index 7977e447752..870c0d26951 100644 --- a/boot/bootdata/txtsetup.sif +++ b/boot/bootdata/txtsetup.sif @@ -76,7 +76,7 @@ hal.dll=,,,,,,,,,,,,2 [Files.pci_mp] ntkrnlmp.exe=,,,,,,,,,,ntoskrnl.exe,,2 -halmp.dll=,,,,,,,,,,hal.dll,,2 +halmps.dll=,,,,,,,,,,hal.dll,,2 [Display] ; = ,,,,, diff --git a/boot/freeldr/freeldr/arch/i386/hardware.c b/boot/freeldr/freeldr/arch/i386/hardware.c index d4654ccd138..1dff167c987 100644 --- a/boot/freeldr/freeldr/arch/i386/hardware.c +++ b/boot/freeldr/freeldr/arch/i386/hardware.c @@ -1419,10 +1419,10 @@ DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey) /* Set Interrupt */ PartialDescriptor = &PartialResourceList->PartialDescriptors[1]; PartialDescriptor->Type = CmResourceTypeInterrupt; - PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; + PartialDescriptor->ShareDisposition = CmResourceShareShared; PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; PartialDescriptor->u.Interrupt.Level = Irq[i]; - PartialDescriptor->u.Interrupt.Vector = 0; + PartialDescriptor->u.Interrupt.Vector = Irq[i]; PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF; /* Set serial data (device specific) */ @@ -1529,7 +1529,7 @@ DetectParallelPorts(PCONFIGURATION_COMPONENT_DATA BusKey) PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; PartialDescriptor->u.Interrupt.Level = Irq[i]; - PartialDescriptor->u.Interrupt.Vector = 0; + PartialDescriptor->u.Interrupt.Vector = Irq[i]; PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF; } @@ -1715,7 +1715,7 @@ DetectKeyboardController(PCONFIGURATION_COMPONENT_DATA BusKey) PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; PartialDescriptor->u.Interrupt.Level = 1; - PartialDescriptor->u.Interrupt.Vector = 0; + PartialDescriptor->u.Interrupt.Vector = 1; PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF; /* Set IO Port 0x60 */ @@ -1887,7 +1887,7 @@ DetectPS2Mouse(PCONFIGURATION_COMPONENT_DATA BusKey) PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareUndetermined; PartialResourceList.PartialDescriptors[0].Flags = CM_RESOURCE_INTERRUPT_LATCHED; PartialResourceList.PartialDescriptors[0].u.Interrupt.Level = 12; - PartialResourceList.PartialDescriptors[0].u.Interrupt.Vector = 0; + PartialResourceList.PartialDescriptors[0].u.Interrupt.Vector = 12; PartialResourceList.PartialDescriptors[0].u.Interrupt.Affinity = 0xFFFFFFFF; /* Create controller key */ diff --git a/dll/directx/devenum/createdevenum.c b/dll/directx/devenum/createdevenum.c index bded7050123..19b41c9fbd6 100644 --- a/dll/directx/devenum/createdevenum.c +++ b/dll/directx/devenum/createdevenum.c @@ -48,6 +48,7 @@ #include "wine/debug.h" #include "mmddk.h" +#include WINE_DEFAULT_DEBUG_CHANNEL(devenum); @@ -124,6 +125,7 @@ HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator( WCHAR wszRegKey[MAX_PATH]; HKEY hkey; HKEY hbasekey; + BOOL bInterface = FALSE; CreateDevEnumImpl *This = (CreateDevEnumImpl *)iface; TRACE("(%p)->(%s, %p, %lx)\n\tDeviceClass:\t%s\n", This, debugstr_guid(clsidDeviceClass), ppEnumMoniker, dwFlags, debugstr_guid(clsidDeviceClass)); @@ -174,12 +176,23 @@ HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator( } else { - FIXME("Category %s not found\n", debugstr_guid(clsidDeviceClass)); - return S_FALSE; + wcscpy(wszRegKey, REGSTR_PATH_DEVICE_CLASSES); + wcscat(wszRegKey, L"\\"); + + if (!StringFromGUID2(clsidDeviceClass, wszRegKey + wcslen(wszRegKey), MAX_PATH - CLSID_STR_LEN)) + return E_OUTOFMEMORY; + + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszRegKey, 0, KEY_READ, &hkey) != ERROR_SUCCESS) + { + FIXME("Category %s not found\n", debugstr_guid(clsidDeviceClass)); + return S_FALSE; + } + + bInterface = TRUE; } } - return DEVENUM_IEnumMoniker_Construct(hkey, ppEnumMoniker); + return DEVENUM_IEnumMoniker_Construct(hkey, ppEnumMoniker, bInterface); } /********************************************************************** diff --git a/dll/directx/devenum/devenum_private.h b/dll/directx/devenum/devenum_private.h index 9ec3b580852..8914aef9f08 100644 --- a/dll/directx/devenum/devenum_private.h +++ b/dll/directx/devenum/devenum_private.h @@ -71,6 +71,7 @@ typedef struct LONG ref; DWORD index; HKEY hkey; + BOOL bInterface; } EnumMonikerImpl; typedef struct @@ -79,10 +80,11 @@ typedef struct LONG ref; HKEY hkey; + BOOL bInterface; } MediaCatMoniker; MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct(void); -HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, IEnumMoniker ** ppEnumMoniker); +HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, IEnumMoniker ** ppEnumMoniker, BOOL bInterface); HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator( ICreateDevEnum * iface, REFCLSID clsidDeviceClass, diff --git a/dll/directx/devenum/mediacatenum.c b/dll/directx/devenum/mediacatenum.c index b8c50743bc6..d14cd9aba1e 100644 --- a/dll/directx/devenum/mediacatenum.c +++ b/dll/directx/devenum/mediacatenum.c @@ -42,6 +42,7 @@ typedef struct IPropertyBagVtbl *lpVtbl; LONG ref; HKEY hkey; + BOOL bInterface; } RegPropBagImpl; @@ -108,13 +109,31 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Read( RegPropBagImpl *This = (RegPropBagImpl *)iface; HRESULT res = S_OK; LONG reswin32; + WCHAR buffer[MAX_PATH]; + HKEY hkey; + LPCOLESTR pszName; TRACE("(%p)->(%s, %p, %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog); if (!pszPropName || !pVar) return E_POINTER; - reswin32 = RegQueryValueExW(This->hkey, pszPropName, NULL, NULL, NULL, &received); + hkey = This->hkey; + pszName = pszPropName; + if (This->bInterface) + { + buffer[0] = 0; + received = sizeof(buffer)/sizeof(WCHAR); + reswin32 = RegEnumKeyEx(This->hkey, 0, buffer, &received, NULL, NULL, NULL, NULL); + + reswin32 = RegOpenKeyExW(This->hkey, buffer, 0, KEY_READ, &hkey); + + if (!wcsicmp(pszPropName, L"DevicePath")) + pszName = L"SymbolicLink"; + + } + + reswin32 = RegQueryValueExW(hkey, pszName, NULL, NULL, NULL, &received); res = HRESULT_FROM_WIN32(reswin32); if (SUCCEEDED(res)) @@ -122,7 +141,7 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Read( pData = HeapAlloc(GetProcessHeap(), 0, received); /* work around a GCC bug that occurs here unless we use the reswin32 variable as well */ - reswin32 = RegQueryValueExW(This->hkey, pszPropName, NULL, &type, pData, &received); + reswin32 = RegQueryValueExW(hkey, pszName, NULL, &type, pData, &received); res = HRESULT_FROM_WIN32(reswin32); } @@ -201,6 +220,9 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Read( if (pData) HeapFree(GetProcessHeap(), 0, pData); + if (This->bInterface) + RegCloseKey(hkey); + TRACE("<- %lx\n", res); return res; } @@ -270,7 +292,7 @@ static IPropertyBagVtbl IPropertyBag_Vtbl = DEVENUM_IPropertyBag_Write }; -static HRESULT DEVENUM_IPropertyBag_Construct(HANDLE hkey, IPropertyBag **ppBag) +static HRESULT DEVENUM_IPropertyBag_Construct(HANDLE hkey, IPropertyBag **ppBag, BOOL bInterface) { RegPropBagImpl * rpb = CoTaskMemAlloc(sizeof(RegPropBagImpl)); if (!rpb) @@ -278,6 +300,8 @@ static HRESULT DEVENUM_IPropertyBag_Construct(HANDLE hkey, IPropertyBag **ppBag) rpb->lpVtbl = &IPropertyBag_Vtbl; rpb->ref = 1; rpb->hkey = hkey; + rpb->bInterface = bInterface; + *ppBag = (IPropertyBag*)rpb; DEVENUM_LockModule(); return S_OK; @@ -393,6 +417,7 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToObject( { IUnknown * pObj = NULL; IPropertyBag * pProp = NULL; + IPersistPropertyBag * pBag; CLSID clsID; VARIANT var; HRESULT res = E_FAIL; @@ -430,6 +455,15 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToObject( if (pObj!=NULL) { + if (This->bInterface) + { + res = IUnknown_QueryInterface(pObj, &IID_IPersistPropertyBag, (void**)&pBag); + if (SUCCEEDED(res)) + { + res = IPersistPropertyBag_Load(pBag, pProp, NULL); /* FIXME */ + IPersistPropertyBag_Release(pBag); + } + } /* get the requested interface from the loaded class */ res= IUnknown_QueryInterface(pObj,riidResult,ppvResult); } @@ -463,7 +497,7 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToStorage( { HANDLE hkey; DuplicateHandle(GetCurrentProcess(), This->hkey, GetCurrentProcess(), &hkey, 0, 0, DUPLICATE_SAME_ACCESS); - return DEVENUM_IPropertyBag_Construct(hkey, (IPropertyBag**)ppvObj); + return DEVENUM_IPropertyBag_Construct(hkey, (IPropertyBag**)ppvObj, This->bInterface); } return MK_E_NOSTORAGE; @@ -679,6 +713,7 @@ MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct() pMoniker->lpVtbl = &IMoniker_Vtbl; pMoniker->ref = 0; pMoniker->hkey = NULL; + pMoniker->bInterface = FALSE; DEVENUM_IMediaCatMoniker_AddRef((LPMONIKER)pMoniker); @@ -764,6 +799,7 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Next(LPENUMMONIKER iface, ULONG celt, if (!pMoniker) return E_OUTOFMEMORY; + pMoniker->bInterface = This->bInterface; if (RegOpenKeyW(This->hkey, buffer, &pMoniker->hkey) != ERROR_SUCCESS) { DEVENUM_IMediaCatMoniker_Release((LPMONIKER)pMoniker); @@ -829,7 +865,7 @@ static IEnumMonikerVtbl IEnumMoniker_Vtbl = DEVENUM_IEnumMoniker_Clone }; -HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, IEnumMoniker ** ppEnumMoniker) +HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, IEnumMoniker ** ppEnumMoniker, BOOL bInterface) { EnumMonikerImpl * pEnumMoniker = CoTaskMemAlloc(sizeof(EnumMonikerImpl)); if (!pEnumMoniker) @@ -839,6 +875,7 @@ HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, IEnumMoniker ** ppEnumMoniker) pEnumMoniker->ref = 1; pEnumMoniker->index = 0; pEnumMoniker->hkey = hkey; + pEnumMoniker->bInterface = bInterface; *ppEnumMoniker = (IEnumMoniker *)pEnumMoniker; diff --git a/dll/directx/ksproxy/enumpins.cpp b/dll/directx/ksproxy/enumpins.cpp index a6c3bdfbd16..da07796d066 100644 --- a/dll/directx/ksproxy/enumpins.cpp +++ b/dll/directx/ksproxy/enumpins.cpp @@ -71,7 +71,6 @@ CEnumPins::QueryInterface( OutputDebugStringW(Buffer); CoTaskMemFree(lpstr); -DebugBreak(); return E_NOINTERFACE; } diff --git a/dll/directx/ksproxy/input_pin.cpp b/dll/directx/ksproxy/input_pin.cpp index 51b78726ccb..e56eacb938c 100644 --- a/dll/directx/ksproxy/input_pin.cpp +++ b/dll/directx/ksproxy/input_pin.cpp @@ -700,7 +700,6 @@ CInputPin::Receive(IMediaSample *pSample) { #ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::Receive NotImplemented\n"); - DebugBreak(); #endif return E_NOTIMPL; @@ -712,7 +711,6 @@ CInputPin::ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSample { #ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::ReceiveMultiple NotImplemented\n"); - DebugBreak(); #endif return E_NOTIMPL; @@ -724,7 +722,6 @@ CInputPin::ReceiveCanBlock( void) { #ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::ReceiveCanBlock NotImplemented\n"); - DebugBreak(); #endif return S_FALSE; @@ -923,7 +920,6 @@ CInputPin::KsQualityNotify( OutputDebugStringW(L"CInputPin::KsQualityNotify NotImplemented\n"); #endif - DebugBreak(); return E_NOTIMPL; } @@ -1114,7 +1110,6 @@ CInputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) { #ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::Connect NotImplemented\n"); - DebugBreak(); #endif return NOERROR; } @@ -1199,7 +1194,6 @@ CInputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt) #ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::ConnectionMediaType NotImplemented\n"); - DebugBreak(); #endif return E_NOTIMPL; @@ -1496,7 +1490,6 @@ CInputPin::CreatePin( WCHAR Buffer[100]; swprintf(Buffer, L"CInputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName); OutputDebugStringW(Buffer); - DebugBreak(); #endif hr = E_FAIL; } @@ -1629,7 +1622,6 @@ CInputPin::CreatePinHandle( { #ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::CreatePinHandle GetSupportedSets failed\n"); - DebugBreak(); #endif return hr; } @@ -1640,7 +1632,6 @@ CInputPin::CreatePinHandle( { #ifdef KSPROXY_TRACE OutputDebugStringW(L"CInputPin::CreatePinHandle LoadProxyPlugins failed\n"); - DebugBreak(); #endif return hr; } @@ -1783,7 +1774,6 @@ CInputPin::LoadProxyPlugins( { // store plugin m_Plugins.push_back(pUnknown); -DebugBreak(); } // close key RegCloseKey(hSubKey); diff --git a/dll/directx/ksproxy/mediasample.cpp b/dll/directx/ksproxy/mediasample.cpp index e0411938444..28270cdc3bd 100644 --- a/dll/directx/ksproxy/mediasample.cpp +++ b/dll/directx/ksproxy/mediasample.cpp @@ -21,7 +21,6 @@ public: STDMETHODIMP_(ULONG) Release() { InterlockedDecrement(&m_Ref); - DebugBreak(); if (!m_Ref) { if (m_Allocator) @@ -280,7 +279,6 @@ STDMETHODCALLTYPE CMediaSample::SetMediaType(AM_MEDIA_TYPE *pMediaType) { OutputDebugStringW(L"CMediaSample::SetMediaType NotImplemented\n"); - DebugBreak(); return E_NOTIMPL; } diff --git a/dll/directx/ksproxy/output_pin.cpp b/dll/directx/ksproxy/output_pin.cpp index 17f07804a20..f9f37725c53 100644 --- a/dll/directx/ksproxy/output_pin.cpp +++ b/dll/directx/ksproxy/output_pin.cpp @@ -1548,7 +1548,6 @@ COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) OutputDebugStringW(L"COutputPin::Connect no IMemInputPin interface\n"); #endif - DebugBreak(); return hr; } @@ -1946,13 +1945,26 @@ COutputPin::CreatePin( // query for pin medium hr = KsQueryMediums(&MediumList); if (FAILED(hr)) + { +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + swprintf(Buffer, L"COutputPin::CreatePin KsQueryMediums failed %lx\n", hr); + OutputDebugStringW(Buffer); +#endif return hr; + } // query for pin interface hr = KsQueryInterfaces(&InterfaceList); if (FAILED(hr)) { // failed +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + swprintf(Buffer, L"COutputPin::CreatePin KsQueryInterfaces failed %lx\n", hr); + OutputDebugStringW(Buffer); +#endif + CoTaskMemFree(MediumList); return hr; } @@ -2003,6 +2015,12 @@ COutputPin::CreatePin( CoTaskMemFree(MediumList); CoTaskMemFree(InterfaceList); +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + swprintf(Buffer, L"COutputPin::CreatePin failed to create interface handler %lx\n", hr); + OutputDebugStringW(Buffer); +#endif + return hr; } @@ -2010,7 +2028,12 @@ COutputPin::CreatePin( hr = InterfaceHandler->KsSetPin((IKsPin*)this); if (FAILED(hr)) { - // failed to load interface handler plugin + // failed to initialize interface handler plugin +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + swprintf(Buffer, L"COutputPin::CreatePin failed to initialize interface handler %lx\n", hr); + OutputDebugStringW(Buffer); +#endif InterfaceHandler->Release(); CoTaskMemFree(MediumList); CoTaskMemFree(InterfaceList); @@ -2027,7 +2050,6 @@ COutputPin::CreatePin( WCHAR Buffer[100]; swprintf(Buffer, L"COutputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName); OutputDebugStringW(Buffer); - DebugBreak(); #endif hr = E_FAIL; @@ -2037,6 +2059,12 @@ COutputPin::CreatePin( CoTaskMemFree(MediumList); CoTaskMemFree(InterfaceList); +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + swprintf(Buffer, L"COutputPin::CreatePin Result %lx\n", hr); + OutputDebugStringW(Buffer); +#endif + return hr; } @@ -2058,6 +2086,8 @@ COutputPin::CreatePinHandle( //KSPROPERTY Property; //ULONG BytesReturned; + OutputDebugStringW(L"COutputPin::CreatePinHandle\n"); + if (m_hPin != INVALID_HANDLE_VALUE) { // pin already exists @@ -2173,7 +2203,6 @@ COutputPin::CreatePinHandle( if (FAILED(InitializeIOThread())) { OutputDebugStringW(L"COutputPin::CreatePinHandle failed to initialize i/o thread\n"); - DebugBreak(); } LPGUID pGuid; @@ -2184,8 +2213,7 @@ COutputPin::CreatePinHandle( if (FAILED(hr)) { #ifdef KSPROXY_TRACE - OutputDebugStringW(L"CInputPin::CreatePinHandle GetSupportedSets failed\n"); - DebugBreak(); + OutputDebugStringW(L"COutputPin::CreatePinHandle GetSupportedSets failed\n"); #endif return hr; } @@ -2195,8 +2223,7 @@ COutputPin::CreatePinHandle( if (FAILED(hr)) { #ifdef KSPROXY_TRACE - OutputDebugStringW(L"CInputPin::CreatePinHandle LoadProxyPlugins failed\n"); - DebugBreak(); + OutputDebugStringW(L"COutputPin::CreatePinHandle LoadProxyPlugins failed\n"); #endif return hr; } @@ -2338,7 +2365,6 @@ COutputPin::LoadProxyPlugins( { // store plugin m_Plugins.push_back(pUnknown); -DebugBreak(); } // close key RegCloseKey(hSubKey); diff --git a/dll/directx/ksproxy/precomp.h b/dll/directx/ksproxy/precomp.h index eae5de0f1aa..f7268b1e026 100644 --- a/dll/directx/ksproxy/precomp.h +++ b/dll/directx/ksproxy/precomp.h @@ -3,7 +3,7 @@ #define _FORCENAMELESSUNION #define BUILDING_KS #define _KSDDK_ -//#define KSPROXY_TRACE +#define KSPROXY_TRACE #include //#include #include diff --git a/dll/directx/ksproxy/proxy.cpp b/dll/directx/ksproxy/proxy.cpp index bd34ec8184b..175eff205ca 100644 --- a/dll/directx/ksproxy/proxy.cpp +++ b/dll/directx/ksproxy/proxy.cpp @@ -1954,7 +1954,6 @@ CKsProxy::IsDirty() { #ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::IsDirty Notimplemented\n"); - DebugBreak(); #endif return E_NOTIMPL; } @@ -2035,7 +2034,6 @@ CKsProxy::Load( }while(Length > 0); - DebugBreak(); return S_OK; } @@ -2059,7 +2057,6 @@ CKsProxy::GetSizeMax( { #ifdef KSPROXY_TRACE OutputDebugStringW(L"CKsProxy::GetSizeMax Notimplemented\n"); - DebugBreak(); #endif return E_NOTIMPL; @@ -2480,23 +2477,50 @@ CKsProxy::CreatePins() // query current instance count hr = GetPinInstanceCount(Index, &Instances); if (FAILED(hr)) + { +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + swprintf(Buffer, L"CKsProxy::CreatePins GetPinInstanceCount failed with %lx\n", hr); + OutputDebugStringW(Buffer); +#endif continue; + } + // query pin communication; hr = GetPinCommunication(Index, &Communication); if (FAILED(hr)) + { +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + swprintf(Buffer, L"CKsProxy::CreatePins GetPinCommunication failed with %lx\n", hr); + OutputDebugStringW(Buffer); +#endif continue; + } if (Instances.CurrentCount == Instances.PossibleCount) { // already maximum reached for this pin +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + swprintf(Buffer, L"CKsProxy::CreatePins Instances.CurrentCount == Instances.PossibleCount\n"); + OutputDebugStringW(Buffer); +#endif continue; } // get direction of pin hr = GetPinDataflow(Index, &DataFlow); if (FAILED(hr)) + { +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + swprintf(Buffer, L"CKsProxy::CreatePins GetPinDataflow failed with %lx\n", hr); + OutputDebugStringW(Buffer); +#endif continue; + } if (DataFlow == KSPIN_DATAFLOW_IN) hr = GetPinName(Index, DataFlow, InputPin, &PinName); @@ -2504,7 +2528,14 @@ CKsProxy::CreatePins() hr = GetPinName(Index, DataFlow, OutputPin, &PinName); if (FAILED(hr)) + { +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + swprintf(Buffer, L"CKsProxy::CreatePins GetPinName failed with %lx\n", hr); + OutputDebugStringW(Buffer); +#endif continue; + } // construct the pins if (DataFlow == KSPIN_DATAFLOW_IN) @@ -2512,6 +2543,11 @@ CKsProxy::CreatePins() hr = CInputPin_Constructor((IBaseFilter*)this, PinName, m_hDevice, Index, Communication, IID_IPin, (void**)&pPin); if (FAILED(hr)) { +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + swprintf(Buffer, L"CKsProxy::CreatePins CInputPin_Constructor failed with %lx\n", hr); + OutputDebugStringW(Buffer); +#endif CoTaskMemFree(PinName); continue; } @@ -2522,6 +2558,11 @@ CKsProxy::CreatePins() hr = COutputPin_Constructor((IBaseFilter*)this, PinName, Index, Communication, IID_IPin, (void**)&pPin); if (FAILED(hr)) { +#ifdef KSPROXY_TRACE + WCHAR Buffer[100]; + swprintf(Buffer, L"CKsProxy::CreatePins COutputPin_Constructor failed with %lx\n", hr); + OutputDebugStringW(Buffer); +#endif CoTaskMemFree(PinName); continue; } @@ -2627,9 +2668,12 @@ CKsProxy::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog) hr = LoadProxyPlugins(pGuid, NumGuids); if (FAILED(hr)) { +#if 0 //HACK CloseHandle(m_hDevice); m_hDevice = NULL; return hr; +#endif + OutputDebugStringW(L"CKsProxy::LoadProxyPlugins failed!\n"); } // free sets @@ -2638,6 +2682,14 @@ CKsProxy::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog) // now create the input / output pins hr = CreatePins(); +#ifdef KSPROXY_TRACE + swprintf(Buffer, L"CKsProxy::Load CreatePins %lx\n", hr); + OutputDebugStringW(Buffer); +#endif + + //HACK + hr = S_OK; + return hr; } @@ -2986,10 +3038,6 @@ STDMETHODCALLTYPE CKsProxy::EnumPins( IEnumPins **ppEnum) { -#ifdef KSPROXY_TRACE - OutputDebugStringW(L"CKsProxy::EnumPins\n"); -#endif - return CEnumPins_fnConstructor(m_Pins, IID_IEnumPins, (void**)ppEnum); } diff --git a/dll/directx/msdvbnp/enumpins.cpp b/dll/directx/msdvbnp/enumpins.cpp index 567705907b7..9466aaae8f3 100644 --- a/dll/directx/msdvbnp/enumpins.cpp +++ b/dll/directx/msdvbnp/enumpins.cpp @@ -155,14 +155,6 @@ CEnumPins_fnConstructor( { CEnumPins * handler = new CEnumPins(NumPins, pins); -#ifdef MSDVBNP_TRACE - WCHAR Buffer[MAX_PATH]; - LPOLESTR lpstr; - StringFromCLSID(riid, &lpstr); - swprintf(Buffer, L"CEnumPins_fnConstructor riid %s pUnknown %p\n", lpstr, pUnknown); - OutputDebugStringW(Buffer); -#endif - if (!handler) return E_OUTOFMEMORY; diff --git a/dll/directx/msdvbnp/msdvbnp.cpp b/dll/directx/msdvbnp/msdvbnp.cpp index 2da8108bdcf..b67f232e13f 100644 --- a/dll/directx/msdvbnp/msdvbnp.cpp +++ b/dll/directx/msdvbnp/msdvbnp.cpp @@ -122,7 +122,7 @@ DllGetClassObject( { UINT i; HRESULT hres = E_OUTOFMEMORY; - IClassFactory * pcf = NULL; + IClassFactory * pcf = NULL; if (!ppv) return E_INVALIDARG; @@ -138,7 +138,7 @@ DllGetClassObject( } } - if (!pcf) + if (!pcf) { return CLASS_E_CLASSNOTAVAILABLE; } diff --git a/dll/directx/msdvbnp/networkprovider.cpp b/dll/directx/msdvbnp/networkprovider.cpp index 7dea3667142..0ac050d23d8 100644 --- a/dll/directx/msdvbnp/networkprovider.cpp +++ b/dll/directx/msdvbnp/networkprovider.cpp @@ -201,7 +201,6 @@ CNetworkProvider::QueryInterface( swprintf(Buffer, L"CNetworkProvider::QueryInterface: NoInterface for %s !!!\n", lpstr); OutputDebugStringW(Buffer); CoTaskMemFree(lpstr); - DebugBreak(); return E_NOINTERFACE; } diff --git a/dll/directx/msdvbnp/pin.cpp b/dll/directx/msdvbnp/pin.cpp index e2acef06a43..b53ba433cf0 100644 --- a/dll/directx/msdvbnp/pin.cpp +++ b/dll/directx/msdvbnp/pin.cpp @@ -51,7 +51,7 @@ public: HRESULT STDMETHODCALLTYPE EndFlush(); HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate); - CPin(IBaseFilter * ParentFilter) : m_Ref(0), m_ParentFilter(ParentFilter){}; + CPin(IBaseFilter * ParentFilter); virtual ~CPin(){}; static LPCWSTR PIN_ID; @@ -59,11 +59,31 @@ public: protected: LONG m_Ref; IBaseFilter * m_ParentFilter; + AM_MEDIA_TYPE m_MediaType; + IPin * m_Pin; }; LPCWSTR CPin::PIN_ID = L"Antenna Out"; + +CPin::CPin( + IBaseFilter * ParentFilter) : m_Ref(0), + m_ParentFilter(ParentFilter), + m_Pin(0) +{ + m_MediaType.majortype = KSDATAFORMAT_TYPE_BDA_ANTENNA; + m_MediaType.subtype = MEDIASUBTYPE_None; + m_MediaType.formattype = FORMAT_None; + m_MediaType.bFixedSizeSamples = true; + m_MediaType.bTemporalCompression = false; + m_MediaType.lSampleSize = sizeof(CHAR); + m_MediaType.pUnk = NULL; + m_MediaType.cbFormat = 0; + m_MediaType.pbFormat = NULL; +} + + HRESULT STDMETHODCALLTYPE CPin::QueryInterface( @@ -100,36 +120,97 @@ HRESULT STDMETHODCALLTYPE CPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt) { + HRESULT hr; OutputDebugStringW(L"CPin::Connect called\n"); - return E_NOTIMPL; + + if (pmt) + { + hr = pReceivePin->QueryAccept(pmt); + if (FAILED(hr)) + { + OutputDebugStringW(L"CPin::Connect QueryAccept failed\n"); + return hr; + } + } + else + { + // query accept + hr = pReceivePin->QueryAccept(&m_MediaType); + if (FAILED(hr)) + { + OutputDebugStringW(L"CPin::Connect QueryAccept pmt default failed\n"); + return hr; + } + + pmt = &m_MediaType; + } + + // receive connection; + hr = pReceivePin->ReceiveConnection((IPin*)this, pmt); + if (SUCCEEDED(hr)) + { + // increment reference count + pReceivePin->AddRef(); + m_Pin = pReceivePin; + OutputDebugStringW(L"CPin::Connect success\n"); + } + + return hr; } HRESULT STDMETHODCALLTYPE CPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt) { - OutputDebugStringW(L"CPin::ReceiveConnection called\n"); - return E_NOTIMPL; + return E_UNEXPECTED; } + HRESULT STDMETHODCALLTYPE CPin::Disconnect( void) { - OutputDebugStringW(L"CPin::Disconnect called\n"); - return E_NOTIMPL; +#ifdef MSDVBNP_TRACE + OutputDebugStringW(L"CPin::Disconnect\n"); +#endif + + if (!m_Pin) + { + // pin was not connected + return S_FALSE; + } + + m_Pin->Release(); + m_Pin = NULL; + + return S_OK; } HRESULT STDMETHODCALLTYPE CPin::ConnectedTo(IPin **pPin) { - OutputDebugStringW(L"CPin::ConnectedTo called\n"); +#ifdef MSDVBNP_TRACE + OutputDebugStringW(L"CPin::ConnectedTo\n"); +#endif + + if (!pPin) + return E_POINTER; + + if (m_Pin) + { + // increment reference count + m_Pin->AddRef(); + *pPin = m_Pin; + return S_OK; + } + + *pPin = NULL; return VFW_E_NOT_CONNECTED; } HRESULT STDMETHODCALLTYPE CPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt) { - OutputDebugStringW(L"CPin::ConnectionMediaType called\n"); + OutputDebugStringW(L"CPin::ConnectionMediaType NotImplemented\n"); return E_NOTIMPL; } HRESULT @@ -170,7 +251,7 @@ HRESULT STDMETHODCALLTYPE CPin::QueryAccept(const AM_MEDIA_TYPE *pmt) { - OutputDebugStringW(L"CPin::QueryAccept called\n"); + OutputDebugStringW(L"CPin::QueryAccept NotImplemented\n"); return E_NOTIMPL; } HRESULT @@ -200,35 +281,35 @@ HRESULT STDMETHODCALLTYPE CPin::QueryInternalConnections(IPin **apPin, ULONG *nPin) { - OutputDebugStringW(L"CPin::QueryInternalConnections called\n"); + OutputDebugStringW(L"CPin::QueryInternalConnections NotImplemented\n"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CPin::EndOfStream( void) { - OutputDebugStringW(L"CPin::EndOfStream called\n"); + OutputDebugStringW(L"CPin::EndOfStream NotImplemented\n"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CPin::BeginFlush( void) { - OutputDebugStringW(L"CPin::BeginFlush called\n"); + OutputDebugStringW(L"CPin::BeginFlush NotImplemented\n"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CPin::EndFlush( void) { - OutputDebugStringW(L"CPin::EndFlush called\n"); + OutputDebugStringW(L"CPin::EndFlush NotImplemented\n"); return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE CPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate) { - OutputDebugStringW(L"CPin::NewSegment called\n"); + OutputDebugStringW(L"CPin::NewSegment NotImplemented\n"); return E_NOTIMPL; } diff --git a/dll/win32/gdi32/objects/region.c b/dll/win32/gdi32/objects/region.c index e1f187ad3d2..3e2b7fe5b65 100644 --- a/dll/win32/gdi32/objects/region.c +++ b/dll/win32/gdi32/objects/region.c @@ -104,7 +104,6 @@ BOOL FASTCALL DeleteRegion( HRGN hRgn ) { -//#if 0 PRGN_ATTR Rgn_Attr; if ((GdiGetHandleUserData((HGDIOBJ) hRgn, GDI_OBJECT_TYPE_REGION, (PVOID) &Rgn_Attr)) && @@ -128,7 +127,6 @@ DeleteRegion( HRGN hRgn ) } } } -//#endif return NtGdiDeleteObjectApp((HGDIOBJ) hRgn); } @@ -581,8 +579,110 @@ INT WINAPI ExtSelectClipRgn( IN HDC hdc, IN HRGN hrgn, IN INT iMode) { - /* FIXME some part need be done on user mode size */ - return NtGdiExtSelectClipRgn(hdc,hrgn, iMode); + INT Ret; + HRGN NewRgn = NULL; + +#if 0 +// Handle something other than a normal dc object. + if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) + { + if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) + return MFDRV_ExtSelectClipRgn( hdc, ); + else + { + PLDC pLDC = GdiGetLDC(hdc); + if ( pLDC ) + { + if (pLDC->iType != LDC_EMFLDC || EMFDRV_ExtSelectClipRgn( hdc, )) + return NtGdiExtSelectClipRgn(hdc, ); + } + else + SetLastError(ERROR_INVALID_HANDLE); + return ERROR; + } + } +#endif +#if 0 + if ( hrgn ) + { + if ( GetLayout(hdc) & LAYOUT_RTL ) + { + if ( MirrorRgnDC(hdc, hrgn, &NewRgn) ) + { + if ( NewRgn ) hrgn = NewRgn; + } + } + } +#endif + /* Batch handles RGN_COPY only! */ + if (iMode == RGN_COPY) + { +#if 0 + PDC_ATTR pDc_Attr; + PRGN_ATTR pRgn_Attr = NULL; + + /* hrgn can be NULL unless the RGN_COPY mode is specified. */ + if (hrgn) + GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr); + + if ( GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &pDc_Attr) && + pDc_Attr ) + { + PGDI_TABLE_ENTRY pEntry = GdiHandleTable + GDI_HANDLE_GET_INDEX(hdc); + PTEB pTeb = NtCurrentTeb(); + + if ( pTeb->Win32ThreadInfo != NULL && + pTeb->GdiTebBatch.HDC == hdc && + !(pDc_Attr->ulDirty_ & DC_DIBSECTION) && + !(pEntry->Flags & GDI_ENTRY_VALIDATE_VIS) ) + { + if (!hrgn || + (hrgn && pRgn_Attr && pRgn_Attr->Flags <= SIMPLEREGION) ) + { + if ((pTeb->GdiTebBatch.Offset + sizeof(GDIBSEXTSELCLPRGN)) <= GDIBATCHBUFSIZE) + { + PGDIBSEXTSELCLPRGN pgO = (PGDIBSEXTSELCLPRGN)(&pTeb->GdiTebBatch.Buffer[0] + + pTeb->GdiTebBatch.Offset); + pgO->gbHdr.Cmd = GdiBCExtSelClipRgn; + pgO->gbHdr.Size = sizeof(GDIBSEXTSELCLPRGN); + pgO->fnMode = iMode; + + if ( hrgn && pRgn_Attr ) + { + Ret = pRgn_Attr->Flags; + + if ( pDc_Attr->VisRectRegion.Rect.left >= pRgn_Attr->Rect.right || + pDc_Attr->VisRectRegion.Rect.top >= pRgn_Attr->Rect.bottom || + pDc_Attr->VisRectRegion.Rect.right <= pRgn_Attr->Rect.left || + pDc_Attr->VisRectRegion.Rect.bottom <= pRgn_Attr->Rect.top ) + Ret = NULLREGION; + + pgO->left = pRgn_Attr->Rect.left; + pgO->top = pRgn_Attr->Rect.top; + pgO->right = pRgn_Attr->Rect.right; + pgO->bottom = pRgn_Attr->Rect.bottom; + } + else + { + Ret = pDc_Attr->VisRectRegion.Flags; + pgO->fnMode |= 0x80000000; // Set no hrgn mode. + } + pTeb->GdiTebBatch.Offset += sizeof(GDIBSEXTSELCLPRGN); + pTeb->GdiBatchCount++; + if (pTeb->GdiBatchCount >= GDI_BatchLimit) NtGdiFlush(); + if ( NewRgn ) DeleteObject(NewRgn); + return Ret; + } + } + } + } +#endif + } + Ret = NtGdiExtSelectClipRgn(hdc, hrgn, iMode); + + if ( NewRgn ) DeleteObject(NewRgn); + + return Ret; } /* diff --git a/dll/win32/shell32/dialogs.c b/dll/win32/shell32/dialogs.c index e5aa28f74e8..792ed62be1b 100644 --- a/dll/win32/shell32/dialogs.c +++ b/dll/win32/shell32/dialogs.c @@ -612,9 +612,11 @@ int WINAPI RestartDialogEx(HWND hWndOwner, LPCWSTR lpwstrReason, DWORD uFlags, D int WINAPI LogoffWindowsDialog(HWND hWndOwner) { - UNIMPLEMENTED; - ExitWindowsEx(EWX_LOGOFF, 0); - return 0; + if (ConfirmDialog(hWndOwner, IDS_LOGOFF_PROMPT, IDS_LOGOFF_TITLE)) + { + ExitWindowsEx(EWX_LOGOFF, 0); + } + return 0; } /************************************************************************* diff --git a/dll/win32/shell32/lang/bg-BG.rc b/dll/win32/shell32/lang/bg-BG.rc index fea6d988882..5cda676dd5e 100644 --- a/dll/win32/shell32/lang/bg-BG.rc +++ b/dll/win32/shell32/lang/bg-BG.rc @@ -666,6 +666,8 @@ BEGIN IDS_RESTART_PROMPT " ?" IDS_SHUTDOWN_TITLE "" IDS_SHUTDOWN_PROMPT " ?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" // shell folder path default values IDS_PROGRAMS " \\" diff --git a/dll/win32/shell32/lang/ca-ES.rc b/dll/win32/shell32/lang/ca-ES.rc index df5cb9e4b24..a26fab0e23f 100644 --- a/dll/win32/shell32/lang/ca-ES.rc +++ b/dll/win32/shell32/lang/ca-ES.rc @@ -665,6 +665,8 @@ BEGIN IDS_RESTART_PROMPT "Do you want to restart the system?" IDS_SHUTDOWN_TITLE "Shutdown" IDS_SHUTDOWN_PROMPT "Do you want to shutdown?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Start Menu\\Programs" diff --git a/dll/win32/shell32/lang/cs-CZ.rc b/dll/win32/shell32/lang/cs-CZ.rc index b08beea99f9..f2652e6a2d4 100644 --- a/dll/win32/shell32/lang/cs-CZ.rc +++ b/dll/win32/shell32/lang/cs-CZ.rc @@ -666,6 +666,8 @@ BEGIN IDS_RESTART_PROMPT "Opravdu chcete restartovat systm?" IDS_SHUTDOWN_TITLE "Vypnout" IDS_SHUTDOWN_PROMPT "Opravdu chcete vypnout pota?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Nabdka Start\\Programy" diff --git a/dll/win32/shell32/lang/da-DK.rc b/dll/win32/shell32/lang/da-DK.rc index 40e1eabce06..b9cf5217235 100644 --- a/dll/win32/shell32/lang/da-DK.rc +++ b/dll/win32/shell32/lang/da-DK.rc @@ -654,6 +654,8 @@ BEGIN IDS_RESTART_PROMPT "nsker du at Genstarte Systemet?" IDS_SHUTDOWN_TITLE "Luk Ned" IDS_SHUTDOWN_PROMPT "nsker du at Lukke Ned?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Start Menu\\Programmer" diff --git a/dll/win32/shell32/lang/de-DE.rc b/dll/win32/shell32/lang/de-DE.rc index db0fa82a369..09f6559a447 100644 --- a/dll/win32/shell32/lang/de-DE.rc +++ b/dll/win32/shell32/lang/de-DE.rc @@ -669,6 +669,8 @@ BEGIN IDS_RESTART_PROMPT "Mchten Sie das System neu starten?" IDS_SHUTDOWN_TITLE "Herunterfahren" IDS_SHUTDOWN_PROMPT "Mchten Sie das System herunterfahren?" + IDS_LOGOFF_TITLE "Ausloggen" + IDS_LOGOFF_PROMPT "Mchten Sie sich ausloggen?" /* shell folder path default values */ IDS_PROGRAMS "Startmen\\Programme" diff --git a/dll/win32/shell32/lang/el-GR.rc b/dll/win32/shell32/lang/el-GR.rc index 6b35ec3f541..0821f013408 100644 --- a/dll/win32/shell32/lang/el-GR.rc +++ b/dll/win32/shell32/lang/el-GR.rc @@ -666,6 +666,8 @@ BEGIN IDS_RESTART_PROMPT " ;" IDS_SHUTDOWN_TITLE "" IDS_SHUTDOWN_PROMPT " ;" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Start Menu\\Programs" diff --git a/dll/win32/shell32/lang/en-GB.rc b/dll/win32/shell32/lang/en-GB.rc index 38203c24077..3dfbfd940df 100644 --- a/dll/win32/shell32/lang/en-GB.rc +++ b/dll/win32/shell32/lang/en-GB.rc @@ -665,6 +665,8 @@ BEGIN IDS_RESTART_PROMPT "Do you want to restart the system?" IDS_SHUTDOWN_TITLE "Shutdown" IDS_SHUTDOWN_PROMPT "Do you want to shutdown?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Start Menu\\Programs" diff --git a/dll/win32/shell32/lang/en-US.rc b/dll/win32/shell32/lang/en-US.rc index 63d38cba154..200c97ae1fb 100644 --- a/dll/win32/shell32/lang/en-US.rc +++ b/dll/win32/shell32/lang/en-US.rc @@ -665,6 +665,8 @@ BEGIN IDS_RESTART_PROMPT "Do you want to restart the system?" IDS_SHUTDOWN_TITLE "Shutdown" IDS_SHUTDOWN_PROMPT "Do you want to shutdown?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Start Menu\\Programs" diff --git a/dll/win32/shell32/lang/es-ES.rc b/dll/win32/shell32/lang/es-ES.rc index 0e20abcf95f..a0dacf6a7a7 100644 --- a/dll/win32/shell32/lang/es-ES.rc +++ b/dll/win32/shell32/lang/es-ES.rc @@ -668,6 +668,8 @@ BEGIN IDS_RESTART_PROMPT "Desea reiniciar el equipo?" IDS_SHUTDOWN_TITLE "Apagar" IDS_SHUTDOWN_PROMPT "Desea apagar el equipo?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Men Inicio\\Programas" diff --git a/dll/win32/shell32/lang/fi-FI.rc b/dll/win32/shell32/lang/fi-FI.rc index 2620c2b4277..778576a08fb 100644 --- a/dll/win32/shell32/lang/fi-FI.rc +++ b/dll/win32/shell32/lang/fi-FI.rc @@ -665,6 +665,8 @@ BEGIN IDS_RESTART_PROMPT "Haluatko simuloida Windows:n uudelleenkynnistmist?" IDS_SHUTDOWN_TITLE "Sammuta" IDS_SHUTDOWN_PROMPT "Haluatko lopettaa Wine:n istunnon?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Kynnist\\Ohjelmat" diff --git a/dll/win32/shell32/lang/fr-FR.rc b/dll/win32/shell32/lang/fr-FR.rc index 98cd95fa6f0..3f712a60bbd 100644 --- a/dll/win32/shell32/lang/fr-FR.rc +++ b/dll/win32/shell32/lang/fr-FR.rc @@ -669,6 +669,8 @@ BEGIN IDS_RESTART_PROMPT "Voulez-vous redmarrer votre ordinateur ?" IDS_SHUTDOWN_TITLE "Arrter" IDS_SHUTDOWN_PROMPT "Voulez-vous fermer la session ReactOS ?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Menu Dmarrer\\Programmes" diff --git a/dll/win32/shell32/lang/hu-HU.rc b/dll/win32/shell32/lang/hu-HU.rc index 7016d5021a8..22a26038c7c 100644 --- a/dll/win32/shell32/lang/hu-HU.rc +++ b/dll/win32/shell32/lang/hu-HU.rc @@ -668,6 +668,8 @@ BEGIN IDS_RESTART_PROMPT "jra szeretnd indtani a rendszert?" IDS_SHUTDOWN_TITLE "Kikapcsols" IDS_SHUTDOWN_PROMPT "Kiakarod kapcsolni szmtgpt?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Start Menu\\Programs" diff --git a/dll/win32/shell32/lang/it-IT.rc b/dll/win32/shell32/lang/it-IT.rc index 986ecfeeb46..4407298403c 100644 --- a/dll/win32/shell32/lang/it-IT.rc +++ b/dll/win32/shell32/lang/it-IT.rc @@ -666,6 +666,8 @@ BEGIN IDS_RESTART_PROMPT "Volete riavviare il sistema?" IDS_SHUTDOWN_TITLE "Termina sessione" IDS_SHUTDOWN_PROMPT "Volete terminare la sessione di ReactOS?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Menu Avvio\\Programmi" diff --git a/dll/win32/shell32/lang/ja-JP.rc b/dll/win32/shell32/lang/ja-JP.rc index 47c5bfb9923..12f24d34adb 100644 --- a/dll/win32/shell32/lang/ja-JP.rc +++ b/dll/win32/shell32/lang/ja-JP.rc @@ -665,6 +665,8 @@ BEGIN IDS_RESTART_PROMPT "VXeċN܂?" IDS_SHUTDOWN_TITLE "Vbg_E" IDS_SHUTDOWN_PROMPT "Vbg_E܂?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "X^[g j[\\vO" diff --git a/dll/win32/shell32/lang/ko-KR.rc b/dll/win32/shell32/lang/ko-KR.rc index e9e67b71a4e..9d7ad808fa6 100644 --- a/dll/win32/shell32/lang/ko-KR.rc +++ b/dll/win32/shell32/lang/ko-KR.rc @@ -665,6 +665,8 @@ BEGIN IDS_RESTART_PROMPT "Do you want to restart the system?" IDS_SHUTDOWN_TITLE "Shutdown" IDS_SHUTDOWN_PROMPT "Do you want to shutdown?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Start Menu\\Programs" diff --git a/dll/win32/shell32/lang/nl-NL.rc b/dll/win32/shell32/lang/nl-NL.rc index 5ff6c83a59a..b0e1c919a5f 100644 --- a/dll/win32/shell32/lang/nl-NL.rc +++ b/dll/win32/shell32/lang/nl-NL.rc @@ -665,6 +665,8 @@ BEGIN IDS_RESTART_PROMPT "Do you want to restart the system?" IDS_SHUTDOWN_TITLE "Shutdown" IDS_SHUTDOWN_PROMPT "Do you want to shutdown?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Start Menu\\Programs" diff --git a/dll/win32/shell32/lang/no-NO.rc b/dll/win32/shell32/lang/no-NO.rc index 90dc27d3aa6..43c637f1dcb 100644 --- a/dll/win32/shell32/lang/no-NO.rc +++ b/dll/win32/shell32/lang/no-NO.rc @@ -668,6 +668,8 @@ BEGIN IDS_RESTART_PROMPT "Vil du starte datamaskinen p nytt?" IDS_SHUTDOWN_TITLE "Avslutt" IDS_SHUTDOWN_PROMPT "Vil du sl av datamaskinen?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Start-meny\\Programmer" diff --git a/dll/win32/shell32/lang/pl-PL.rc b/dll/win32/shell32/lang/pl-PL.rc index b6d33a64fd4..a0d3682dc1f 100644 --- a/dll/win32/shell32/lang/pl-PL.rc +++ b/dll/win32/shell32/lang/pl-PL.rc @@ -672,6 +672,8 @@ BEGIN IDS_RESTART_PROMPT "Czy chcesz zrestartowa system?" IDS_SHUTDOWN_TITLE "Wycz" IDS_SHUTDOWN_PROMPT "Czy chcesz wyczy system?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Menu Start\\Programy" diff --git a/dll/win32/shell32/lang/pt-BR.rc b/dll/win32/shell32/lang/pt-BR.rc index 048d4c39110..5bcee218b35 100644 --- a/dll/win32/shell32/lang/pt-BR.rc +++ b/dll/win32/shell32/lang/pt-BR.rc @@ -667,6 +667,8 @@ BEGIN IDS_RESTART_PROMPT "Voc quer simular a reinicializao do Windows?" IDS_SHUTDOWN_TITLE "Desligar" IDS_SHUTDOWN_PROMPT "Voc quer finalizar a sesso no Wine?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Menu Iniciar\\Programas" diff --git a/dll/win32/shell32/lang/pt-PT.rc b/dll/win32/shell32/lang/pt-PT.rc index c20e670e3a2..dbf3fe2453c 100644 --- a/dll/win32/shell32/lang/pt-PT.rc +++ b/dll/win32/shell32/lang/pt-PT.rc @@ -667,6 +667,8 @@ BEGIN IDS_RESTART_PROMPT "Deseja simular a reinicializao do Windows?" IDS_SHUTDOWN_TITLE "Desligar" IDS_SHUTDOWN_PROMPT "Deseja finalizar esta sesso do Wine?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Menu Iniciar\\Programas" diff --git a/dll/win32/shell32/lang/ro-RO.rc b/dll/win32/shell32/lang/ro-RO.rc index 656bc410bc9..efbff8594d2 100644 --- a/dll/win32/shell32/lang/ro-RO.rc +++ b/dll/win32/shell32/lang/ro-RO.rc @@ -668,6 +668,8 @@ BEGIN IDS_RESTART_PROMPT "Vreți să reporniți sistemul?" IDS_SHUTDOWN_TITLE "Închidere" IDS_SHUTDOWN_PROMPT "Vreți să închideți computerul?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Meniu Start\\Programe" diff --git a/dll/win32/shell32/lang/ru-RU.rc b/dll/win32/shell32/lang/ru-RU.rc index 7d6e1e1e06e..6c3f488f3eb 100644 --- a/dll/win32/shell32/lang/ru-RU.rc +++ b/dll/win32/shell32/lang/ru-RU.rc @@ -664,6 +664,8 @@ BEGIN IDS_RESTART_PROMPT " ReactOS?" IDS_SHUTDOWN_TITLE " " IDS_SHUTDOWN_PROMPT " ReactOS?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS " \\" diff --git a/dll/win32/shell32/lang/sk-SK.rc b/dll/win32/shell32/lang/sk-SK.rc index 2ec58ec12ae..e45b141e87f 100644 --- a/dll/win32/shell32/lang/sk-SK.rc +++ b/dll/win32/shell32/lang/sk-SK.rc @@ -671,6 +671,8 @@ BEGIN IDS_RESTART_PROMPT "Naozaj chcete retartova systm?" IDS_SHUTDOWN_TITLE "Vypn" IDS_SHUTDOWN_PROMPT "Naozaj chcete vypn pota?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Ponuka tart\\Programy" diff --git a/dll/win32/shell32/lang/sl-SI.rc b/dll/win32/shell32/lang/sl-SI.rc index 876be4b4927..5038af1c123 100644 --- a/dll/win32/shell32/lang/sl-SI.rc +++ b/dll/win32/shell32/lang/sl-SI.rc @@ -665,6 +665,8 @@ BEGIN IDS_RESTART_PROMPT "Do you want to restart the system?" IDS_SHUTDOWN_TITLE "Shutdown" IDS_SHUTDOWN_PROMPT "Do you want to shutdown?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Start Menu\\Programs" diff --git a/dll/win32/shell32/lang/sv-SE.rc b/dll/win32/shell32/lang/sv-SE.rc index e7a520f5ba4..08a6f59e70f 100644 --- a/dll/win32/shell32/lang/sv-SE.rc +++ b/dll/win32/shell32/lang/sv-SE.rc @@ -665,6 +665,8 @@ BEGIN IDS_RESTART_PROMPT "Do you want to restart the system?" IDS_SHUTDOWN_TITLE "Shutdown" IDS_SHUTDOWN_PROMPT "Do you want to shutdown?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Start Menu\\Programs" diff --git a/dll/win32/shell32/lang/tr-TR.rc b/dll/win32/shell32/lang/tr-TR.rc index 49a154c3408..3ab92cbb104 100644 --- a/dll/win32/shell32/lang/tr-TR.rc +++ b/dll/win32/shell32/lang/tr-TR.rc @@ -665,6 +665,8 @@ BEGIN IDS_RESTART_PROMPT "Do you want to restart the system?" IDS_SHUTDOWN_TITLE "Oturumu Kapat" IDS_SHUTDOWN_PROMPT "Do you want to shutdown?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Start Menu\\Programlar" diff --git a/dll/win32/shell32/lang/uk-UA.rc b/dll/win32/shell32/lang/uk-UA.rc index 3846965c696..cf2847ed9ab 100644 --- a/dll/win32/shell32/lang/uk-UA.rc +++ b/dll/win32/shell32/lang/uk-UA.rc @@ -666,6 +666,8 @@ BEGIN IDS_RESTART_PROMPT " ?" IDS_SHUTDOWN_TITLE "" IDS_SHUTDOWN_PROMPT " '?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Start Menu\\Programs" diff --git a/dll/win32/shell32/lang/zh-CN.rc b/dll/win32/shell32/lang/zh-CN.rc index 5180db558cd..18c4d5439d4 100644 --- a/dll/win32/shell32/lang/zh-CN.rc +++ b/dll/win32/shell32/lang/zh-CN.rc @@ -654,6 +654,8 @@ BEGIN IDS_RESTART_PROMPT "Ƿϵͳ?" IDS_SHUTDOWN_TITLE "ػ" IDS_SHUTDOWN_PROMPT "Ƿرϵͳ?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Start Menu\\Programs" diff --git a/dll/win32/shell32/lang/zh-TW.rc b/dll/win32/shell32/lang/zh-TW.rc index fc76bf15798..f7c59a2e1ff 100644 --- a/dll/win32/shell32/lang/zh-TW.rc +++ b/dll/win32/shell32/lang/zh-TW.rc @@ -666,6 +666,8 @@ BEGIN IDS_RESTART_PROMPT "Do you want to restart the system?" IDS_SHUTDOWN_TITLE "Shutdown" IDS_SHUTDOWN_PROMPT "Do you want to shutdown?" + IDS_LOGOFF_TITLE "Log Off" + IDS_LOGOFF_PROMPT "Do you want to log off?" /* shell folder path default values */ IDS_PROGRAMS "Start Menu\\Programs" diff --git a/dll/win32/shell32/shresdef.h b/dll/win32/shell32/shresdef.h index e28efb0e240..981e17ff9ce 100644 --- a/dll/win32/shell32/shresdef.h +++ b/dll/win32/shell32/shresdef.h @@ -90,6 +90,9 @@ #define IDS_FONTS 76 #define IDS_PRINTERS 77 +#define IDS_LOGOFF_TITLE 78 +#define IDS_LOGOFF_PROMPT 79 + #define IDS_CREATEFOLDER_DENIED 128 #define IDS_CREATEFOLDER_CAPTION 129 #define IDS_DELETEITEM_CAPTION 130 diff --git a/drivers/battery/cmbatt/cmbatt.c b/drivers/battery/cmbatt/cmbatt.c deleted file mode 100644 index b85f3ebc504..00000000000 --- a/drivers/battery/cmbatt/cmbatt.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * PROJECT: ReactOS Kernel - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/battery/cmbatt/cmbatt.c - * PURPOSE: Control Method Battery Miniclass Driver - * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org) - */ - -#include - -#define NDEBUG -#include - -LIST_ENTRY BatteryList; -KSPIN_LOCK BatteryListLock; - -VOID -NTAPI -CmBattUnload(PDRIVER_OBJECT DriverObject) -{ - DPRINT("Control method battery miniclass driver unloaded\n"); -} - -NTSTATUS -NTAPI -CmBattDeviceControl(PDEVICE_OBJECT DeviceObject, - PIRP Irp) -{ - PCMBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; - NTSTATUS Status; - - Status = BatteryClassIoctl(DeviceExtension->BattClassHandle, - Irp); - - if (Status == STATUS_NOT_SUPPORTED) - { - Irp->IoStatus.Status = Status; - Irp->IoStatus.Information = 0; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - } - - return Status; -} - -NTSTATUS -NTAPI -CmBattPnP(PDEVICE_OBJECT DeviceObject, - PIRP Irp) -{ - PCMBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; - - UNIMPLEMENTED - - IoSkipCurrentIrpStackLocation(Irp); - - return IoCallDriver(DeviceExtension->Ldo, Irp); -} - -NTSTATUS -NTAPI -CmBattSystemControl(PDEVICE_OBJECT DeviceObject, - PIRP Irp) -{ - UNIMPLEMENTED - - Irp->IoStatus.Status = STATUS_WMI_GUID_NOT_FOUND; - Irp->IoStatus.Information = 0; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return STATUS_WMI_GUID_NOT_FOUND; -} - -NTSTATUS -NTAPI -CmBattPower(PDEVICE_OBJECT DeviceObject, - PIRP Irp) -{ - PCMBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; - - UNIMPLEMENTED - - IoSkipCurrentIrpStackLocation(Irp); - - PoStartNextPowerIrp(Irp); - - return PoCallDriver(DeviceExtension->Ldo, Irp); -} - -NTSTATUS -NTAPI -CmBattCreateClose(PDEVICE_OBJECT DeviceObject, - PIRP Irp) -{ - Irp->IoStatus.Status = STATUS_SUCCESS; - Irp->IoStatus.Information = 0; - - IoCompleteRequest(Irp, IO_NO_INCREMENT); - - return STATUS_SUCCESS; -} - -NTSTATUS -NTAPI -CmBattAddDevice(PDRIVER_OBJECT DriverObject, - PDEVICE_OBJECT PhysicalDeviceObject) -{ - NTSTATUS Status; - PDEVICE_OBJECT DeviceObject; - PCMBATT_DEVICE_EXTENSION DeviceExtension; - BATTERY_MINIPORT_INFO BattInfo; - - Status = IoCreateDevice(DriverObject, - sizeof(CMBATT_DEVICE_EXTENSION), - NULL, - FILE_DEVICE_BATTERY, - 0, - FALSE, - &DeviceObject); - if (!NT_SUCCESS(Status)) - return Status; - - DeviceExtension = DeviceObject->DeviceExtension; - - DeviceExtension->Pdo = PhysicalDeviceObject; - DeviceExtension->Fdo = DeviceObject; - DeviceExtension->Ldo = IoAttachDeviceToDeviceStack(DeviceObject, - PhysicalDeviceObject); - - DeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE; - - /* We require an extra stack entry */ - DeviceObject->StackSize = PhysicalDeviceObject->StackSize + 2; - - BattInfo.MajorVersion = BATTERY_CLASS_MAJOR_VERSION; - BattInfo.MinorVersion = BATTERY_CLASS_MINOR_VERSION; - BattInfo.Context = DeviceExtension; - BattInfo.QueryTag = CmBattQueryTag; - BattInfo.QueryInformation = CmBattQueryInformation; - BattInfo.SetInformation = CmBattSetInformation; - BattInfo.QueryStatus = CmBattQueryStatus; - BattInfo.SetStatusNotify = CmBattSetStatusNotify; - BattInfo.DisableStatusNotify = CmBattDisableStatusNotify; - BattInfo.Pdo = PhysicalDeviceObject; - BattInfo.DeviceName = NULL; - - Status = BatteryClassInitializeDevice(&BattInfo, - &DeviceExtension->BattClassHandle); - if (!NT_SUCCESS(Status)) - { - IoDetachDevice(DeviceExtension->Ldo); - IoDeleteDevice(DeviceObject); - return Status; - } - - ExInterlockedInsertTailList(&BatteryList, - &DeviceExtension->ListEntry, - &BatteryListLock); - - DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; - - DPRINT("Successfully registered battery with battc (0x%x)\n", DeviceExtension->BattClassHandle); - - return STATUS_SUCCESS; -} - -NTSTATUS -NTAPI -DriverEntry(PDRIVER_OBJECT DriverObject, - PUNICODE_STRING RegistryPath) -{ - DPRINT("Control method battery miniclass driver initialized\n"); - - DriverObject->DriverUnload = CmBattUnload; - DriverObject->DriverExtension->AddDevice = CmBattAddDevice; - DriverObject->MajorFunction[IRP_MJ_POWER] = CmBattPower; - DriverObject->MajorFunction[IRP_MJ_PNP] = CmBattPnP; - DriverObject->MajorFunction[IRP_MJ_CREATE] = CmBattCreateClose; - DriverObject->MajorFunction[IRP_MJ_CLOSE] = CmBattCreateClose; - DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = CmBattDeviceControl; - DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = CmBattSystemControl; - - KeInitializeSpinLock(&BatteryListLock); - InitializeListHead(&BatteryList); - - return STATUS_SUCCESS; -} diff --git a/drivers/battery/cmbatt/cmbatt.h b/drivers/battery/cmbatt/cmbatt.h deleted file mode 100644 index e70b561d3df..00000000000 --- a/drivers/battery/cmbatt/cmbatt.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -* PROJECT: ReactOS Kernel -* LICENSE: GPL - See COPYING in the top level directory -* FILE: drivers/battery/cmbatt/cmbatt.h -* PURPOSE: Control Method Battery Miniclass Driver -* PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org) -*/ - -#pragma once - -#include -#include - -typedef struct _CMBATT_DEVICE_EXTENSION { - PDEVICE_OBJECT Pdo; - PDEVICE_OBJECT Ldo; - PDEVICE_OBJECT Fdo; - PVOID BattClassHandle; - LIST_ENTRY ListEntry; -} CMBATT_DEVICE_EXTENSION, *PCMBATT_DEVICE_EXTENSION; - -NTSTATUS -NTAPI -CmBattQueryTag(PVOID Context, - PULONG BatteryTag); - -NTSTATUS -NTAPI -CmBattDisableStatusNotify(PVOID Context); - -NTSTATUS -NTAPI -CmBattSetStatusNotify(PVOID Context, - ULONG BatteryTag, - PBATTERY_NOTIFY BatteryNotify); - -NTSTATUS -NTAPI -CmBattQueryInformation(PVOID Context, - ULONG BatteryTag, - BATTERY_QUERY_INFORMATION_LEVEL Level, - OPTIONAL LONG AtRate, - PVOID Buffer, - ULONG BufferLength, - PULONG ReturnedLength); - -NTSTATUS -NTAPI -CmBattQueryStatus(PVOID Context, - ULONG BatteryTag, - PBATTERY_STATUS BatteryStatus); - -NTSTATUS -NTAPI -CmBattSetInformation(PVOID Context, - ULONG BatteryTag, - BATTERY_SET_INFORMATION_LEVEL Level, - OPTIONAL PVOID Buffer); diff --git a/drivers/battery/cmbatt/cmbatt.rbuild b/drivers/battery/cmbatt/cmbatt.rbuild deleted file mode 100644 index c41a072779c..00000000000 --- a/drivers/battery/cmbatt/cmbatt.rbuild +++ /dev/null @@ -1,11 +0,0 @@ - - - - ntoskrnl - hal - battc - . - cmbatt.c - miniclass.c - cmbatt.rc - diff --git a/drivers/battery/cmbatt/cmbatt.rc b/drivers/battery/cmbatt/cmbatt.rc deleted file mode 100644 index 2fd6bc7713c..00000000000 --- a/drivers/battery/cmbatt/cmbatt.rc +++ /dev/null @@ -1,5 +0,0 @@ -#define REACTOS_VERSION_DLL -#define REACTOS_STR_FILE_DESCRIPTION "Control Method Battery Miniclass Driver\0" -#define REACTOS_STR_INTERNAL_NAME "cmbatt\0" -#define REACTOS_STR_ORIGINAL_FILENAME "cmbatt.sys\0" -#include diff --git a/drivers/battery/cmbatt/miniclass.c b/drivers/battery/cmbatt/miniclass.c deleted file mode 100644 index bb75d9aa319..00000000000 --- a/drivers/battery/cmbatt/miniclass.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * PROJECT: ReactOS Kernel - * LICENSE: GPL - See COPYING in the top level directory - * FILE: drivers/battery/cmbatt/miniclass.c - * PURPOSE: Control Method Battery Miniclass Driver - * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org) - */ - -#include - -#define NDEBUG -#include - -NTSTATUS -NTAPI -CmBattQueryTag(PVOID Context, - PULONG BatteryTag) -{ - UNIMPLEMENTED - - *BatteryTag = 0; - - return STATUS_SUCCESS; -} - -NTSTATUS -NTAPI -CmBattDisableStatusNotify(PVOID Context) -{ - UNIMPLEMENTED - - return STATUS_NOT_SUPPORTED; -} - -NTSTATUS -NTAPI -CmBattSetStatusNotify(PVOID Context, - ULONG BatteryTag, - PBATTERY_NOTIFY BatteryNotify) -{ - UNIMPLEMENTED - - return STATUS_NOT_SUPPORTED; -} - -NTSTATUS -NTAPI -CmBattQueryInformation(PVOID Context, - ULONG BatteryTag, - BATTERY_QUERY_INFORMATION_LEVEL Level, - OPTIONAL LONG AtRate, - PVOID Buffer, - ULONG BufferLength, - PULONG ReturnedLength) -{ - UNIMPLEMENTED - - return STATUS_NOT_SUPPORTED; -} - -NTSTATUS -NTAPI -CmBattQueryStatus(PVOID Context, - ULONG BatteryTag, - PBATTERY_STATUS BatteryStatus) -{ - UNIMPLEMENTED - - return STATUS_NOT_SUPPORTED; -} - -NTSTATUS -NTAPI -CmBattSetInformation(PVOID Context, - ULONG BatteryTag, - BATTERY_SET_INFORMATION_LEVEL Level, - OPTIONAL PVOID Buffer) -{ - UNIMPLEMENTED - - return STATUS_NOT_SUPPORTED; -} diff --git a/drivers/battery/directory.rbuild b/drivers/battery/directory.rbuild index 2da9fe08c92..ee79df907b5 100644 --- a/drivers/battery/directory.rbuild +++ b/drivers/battery/directory.rbuild @@ -4,7 +4,4 @@ - - - diff --git a/drivers/bus/acpi/cmbatt/cmbatt.rbuild b/drivers/bus/acpi/cmbatt/cmbatt.rbuild index 34c85adccf1..1af50b4c7a7 100644 --- a/drivers/bus/acpi/cmbatt/cmbatt.rbuild +++ b/drivers/bus/acpi/cmbatt/cmbatt.rbuild @@ -1,6 +1,6 @@ - + ntoskrnl hal battc diff --git a/drivers/bus/directory.rbuild b/drivers/bus/directory.rbuild index a6904a2b137..11a8fbe3852 100644 --- a/drivers/bus/directory.rbuild +++ b/drivers/bus/directory.rbuild @@ -10,4 +10,7 @@ + + + diff --git a/drivers/bus/pci/pdo.c b/drivers/bus/pci/pdo.c index f19e45c1f4c..6fde92e8311 100644 --- a/drivers/bus/pci/pdo.c +++ b/drivers/bus/pci/pdo.c @@ -775,7 +775,7 @@ PdoQueryResources( Descriptor->ShareDisposition = CmResourceShareShared; Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine; - Descriptor->u.Interrupt.Vector = 0; + Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine; Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF; } } @@ -1186,6 +1186,49 @@ PdoQueryInterface( return Status; } +static NTSTATUS +PdoStartDevice( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PCM_RESOURCE_LIST RawResList = IrpSp->Parameters.StartDevice.AllocatedResources; + PCM_FULL_RESOURCE_DESCRIPTOR RawFullDesc; + PCM_PARTIAL_RESOURCE_DESCRIPTOR RawPartialDesc; + ULONG i, ii; + PPDO_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + UCHAR Irq; + + /* TODO: Assign the other resources we get to the card */ + + for (i = 0; i < RawResList->Count; i++) + { + RawFullDesc = &RawResList->List[i]; + + for (ii = 0; ii < RawFullDesc->PartialResourceList.Count; ii++) + { + RawPartialDesc = &RawFullDesc->PartialResourceList.PartialDescriptors[ii]; + + if (RawPartialDesc->Type == CmResourceTypeInterrupt) + { + DPRINT1("Assigning IRQ %x to PCI device (%x, %x)\n", + RawPartialDesc->u.Interrupt.Vector, + DeviceExtension->PciDevice->SlotNumber.u.AsULONG, + DeviceExtension->PciDevice->BusNumber); + + Irq = (UCHAR)RawPartialDesc->u.Interrupt.Vector; + HalSetBusDataByOffset(PCIConfiguration, + DeviceExtension->PciDevice->BusNumber, + DeviceExtension->PciDevice->SlotNumber.u.AsULONG, + &Irq, + 0x3c /* PCI_INTERRUPT_LINE */, + sizeof(UCHAR)); + } + } + } + + return STATUS_SUCCESS; +} static NTSTATUS PdoReadConfig( @@ -1247,6 +1290,33 @@ PdoWriteConfig( return STATUS_SUCCESS; } +static NTSTATUS +PdoQueryDeviceRelations( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + PIO_STACK_LOCATION IrpSp) +{ + PDEVICE_RELATIONS DeviceRelations; + + /* We only support TargetDeviceRelation for child PDOs */ + if (IrpSp->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation) + return Irp->IoStatus.Status; + + /* We can do this because we only return 1 PDO for TargetDeviceRelation */ + DeviceRelations = ExAllocatePool(PagedPool, sizeof(*DeviceRelations)); + if (!DeviceRelations) + return STATUS_INSUFFICIENT_RESOURCES; + + DeviceRelations->Count = 1; + DeviceRelations->Objects[0] = DeviceObject; + + /* The PnP manager will remove this when it is done with the PDO */ + ObReferenceObject(DeviceObject); + + Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; + + return STATUS_SUCCESS; +} static NTSTATUS PdoSetPower( @@ -1319,8 +1389,7 @@ PdoPnpControl( break; case IRP_MN_QUERY_DEVICE_RELATIONS: - /* FIXME: Possibly handle for RemovalRelations */ - DPRINT("Unimplemented IRP_MN_QUERY_DEVICE_RELATIONS received\n"); + Status = PdoQueryDeviceRelations(DeviceObject, Irp, IrpSp); break; case IRP_MN_QUERY_DEVICE_TEXT: @@ -1352,6 +1421,9 @@ PdoPnpControl( break; case IRP_MN_START_DEVICE: + Status = PdoStartDevice(DeviceObject, Irp, IrpSp); + break; + case IRP_MN_QUERY_STOP_DEVICE: case IRP_MN_CANCEL_STOP_DEVICE: case IRP_MN_STOP_DEVICE: diff --git a/drivers/bus/pcix/arb/ar_busno.c b/drivers/bus/pcix/arb/ar_busno.c new file mode 100644 index 00000000000..5086357c836 --- /dev/null +++ b/drivers/bus/pcix/arb/ar_busno.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/arb/ar_busno.c + * PURPOSE: Bus Number Arbitration + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/arb/ar_memio.c b/drivers/bus/pcix/arb/ar_memio.c new file mode 100644 index 00000000000..47d6e07b150 --- /dev/null +++ b/drivers/bus/pcix/arb/ar_memio.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/arb/ar_memiono.c + * PURPOSE: Memory and I/O Port Resource Arbitration + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/arb/arb_comn.c b/drivers/bus/pcix/arb/arb_comn.c new file mode 100644 index 00000000000..37591694584 --- /dev/null +++ b/drivers/bus/pcix/arb/arb_comn.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/arb/arb_comn.c + * PURPOSE: Common Arbitration Code + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/arb/tr_irq.c b/drivers/bus/pcix/arb/tr_irq.c new file mode 100644 index 00000000000..7d27173b463 --- /dev/null +++ b/drivers/bus/pcix/arb/tr_irq.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/arb/tr_irq.c + * PURPOSE: IRQ Resource Translation + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/debug.c b/drivers/bus/pcix/debug.c new file mode 100644 index 00000000000..2185b02482a --- /dev/null +++ b/drivers/bus/pcix/debug.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/debug.c + * PURPOSE: Debug Helpers + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/device.c b/drivers/bus/pcix/device.c new file mode 100644 index 00000000000..7f08dcf0b46 --- /dev/null +++ b/drivers/bus/pcix/device.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/device.c + * PURPOSE: Device Management + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/dispatch.c b/drivers/bus/pcix/dispatch.c new file mode 100644 index 00000000000..e69416d156e --- /dev/null +++ b/drivers/bus/pcix/dispatch.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/dispatch.c + * PURPOSE: WDM Dispatch Routines + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/enum.c b/drivers/bus/pcix/enum.c new file mode 100644 index 00000000000..d67db2862ae --- /dev/null +++ b/drivers/bus/pcix/enum.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/enum.c + * PURPOSE: PCI Bus/Device Enumeration + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/fdo.c b/drivers/bus/pcix/fdo.c new file mode 100644 index 00000000000..f4d30951e4e --- /dev/null +++ b/drivers/bus/pcix/fdo.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/fdo.c + * PURPOSE: FDO Device Management + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/guid.c b/drivers/bus/pcix/guid.c new file mode 100644 index 00000000000..7dd27e965ce --- /dev/null +++ b/drivers/bus/pcix/guid.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/guid.c + * PURPOSE: GUID Data + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/hookhal.c b/drivers/bus/pcix/hookhal.c new file mode 100644 index 00000000000..786add8376e --- /dev/null +++ b/drivers/bus/pcix/hookhal.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/hookhal.c + * PURPOSE: HAL Bus Handler Dispatch Routine Support + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/init.c b/drivers/bus/pcix/init.c new file mode 100644 index 00000000000..18cbed0677b --- /dev/null +++ b/drivers/bus/pcix/init.c @@ -0,0 +1,30 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/init.c + * PURPOSE: Driver Initialization + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +NTSTATUS +NTAPI +DriverEntry(IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +{ + DPRINT1("PCI: DriverEntry!\n"); + + /* FIXME: TODO */ + return STATUS_NOT_SUPPORTED; +} + +/* EOF */ diff --git a/drivers/bus/pcix/intrface/agpintrf.c b/drivers/bus/pcix/intrface/agpintrf.c new file mode 100644 index 00000000000..351ae575b9d --- /dev/null +++ b/drivers/bus/pcix/intrface/agpintrf.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/intrface/agpintrf.c + * PURPOSE: AGP Interface + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/intrface/busintrf.c b/drivers/bus/pcix/intrface/busintrf.c new file mode 100644 index 00000000000..468d9edd1f0 --- /dev/null +++ b/drivers/bus/pcix/intrface/busintrf.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/intrface/busintrf.c + * PURPOSE: Bus Interface + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/intrface/cardbus.c b/drivers/bus/pcix/intrface/cardbus.c new file mode 100644 index 00000000000..a36f2d886f4 --- /dev/null +++ b/drivers/bus/pcix/intrface/cardbus.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/intrface/cardbus.c + * PURPOSE: CardBus Interface + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/intrface/ideintrf.c b/drivers/bus/pcix/intrface/ideintrf.c new file mode 100644 index 00000000000..ec2ff82ee8e --- /dev/null +++ b/drivers/bus/pcix/intrface/ideintrf.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/intrface/ideintrf.c + * PURPOSE: IDE Interface + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/intrface/intrface.c b/drivers/bus/pcix/intrface/intrface.c new file mode 100644 index 00000000000..e8d0dd5e91a --- /dev/null +++ b/drivers/bus/pcix/intrface/intrface.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/intrface/intrface.c + * PURPOSE: Common Interface Support Routines + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/intrface/lddintrf.c b/drivers/bus/pcix/intrface/lddintrf.c new file mode 100644 index 00000000000..43224559e85 --- /dev/null +++ b/drivers/bus/pcix/intrface/lddintrf.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/intrface/lddintrf.c + * PURPOSE: Legacy Device Detection Interface + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/intrface/locintrf.c b/drivers/bus/pcix/intrface/locintrf.c new file mode 100644 index 00000000000..a633d98654a --- /dev/null +++ b/drivers/bus/pcix/intrface/locintrf.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/intrface/locintrf.c + * PURPOSE: Location Interface + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/intrface/pmeintf.c b/drivers/bus/pcix/intrface/pmeintf.c new file mode 100644 index 00000000000..ecb3b6e88e9 --- /dev/null +++ b/drivers/bus/pcix/intrface/pmeintf.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/intrface/pmeintf.c + * PURPOSE: Power Management Event# Signal Interface + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/intrface/routintf.c b/drivers/bus/pcix/intrface/routintf.c new file mode 100644 index 00000000000..6332953d685 --- /dev/null +++ b/drivers/bus/pcix/intrface/routintf.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/intrface/routinf.c + * PURPOSE: Routing Interface + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/pci.h b/drivers/bus/pcix/pci.h new file mode 100644 index 00000000000..63432115bb8 --- /dev/null +++ b/drivers/bus/pcix/pci.h @@ -0,0 +1,11 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/pci.h + * PURPOSE: Main Header File + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +#include + +/* EOF */ diff --git a/drivers/bus/pcix/pci.rc b/drivers/bus/pcix/pci.rc new file mode 100644 index 00000000000..001529b970c --- /dev/null +++ b/drivers/bus/pcix/pci.rc @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "PCI Bus Driver\0" +#define REACTOS_STR_INTERNAL_NAME "pci\0" +#define REACTOS_STR_ORIGINAL_FILENAME "pci.sys\0" +#include diff --git a/drivers/bus/pcix/pci/busno.c b/drivers/bus/pcix/pci/busno.c new file mode 100644 index 00000000000..e5a981631c4 --- /dev/null +++ b/drivers/bus/pcix/pci/busno.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/pci/busno.c + * PURPOSE: Bus Number Management + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/pci/config.c b/drivers/bus/pcix/pci/config.c new file mode 100644 index 00000000000..9bdbb0f2741 --- /dev/null +++ b/drivers/bus/pcix/pci/config.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/pci/config.c + * PURPOSE: PCI Configuration Space Routines + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/pci/devhere.c b/drivers/bus/pcix/pci/devhere.c new file mode 100644 index 00000000000..4a666b9fefc --- /dev/null +++ b/drivers/bus/pcix/pci/devhere.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/pci/devhere.c + * PURPOSE: PCI Device Detection and Location + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/pci/id.c b/drivers/bus/pcix/pci/id.c new file mode 100644 index 00000000000..d4fd9102cfc --- /dev/null +++ b/drivers/bus/pcix/pci/id.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/pci/id.c + * PURPOSE: PCI Device Identification + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/pci/ppbridge.c b/drivers/bus/pcix/pci/ppbridge.c new file mode 100644 index 00000000000..738b5c047b9 --- /dev/null +++ b/drivers/bus/pcix/pci/ppbridge.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/pci/ppbridge.c + * PURPOSE: PCI-to-PCI Bridge Support + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/pci/romimage.c b/drivers/bus/pcix/pci/romimage.c new file mode 100644 index 00000000000..96575f39099 --- /dev/null +++ b/drivers/bus/pcix/pci/romimage.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/pci/romimage.c + * PURPOSE: PCI ROM Image Support + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/pci/state.c b/drivers/bus/pcix/pci/state.c new file mode 100644 index 00000000000..d2f3048bf9e --- /dev/null +++ b/drivers/bus/pcix/pci/state.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/pci/state.c + * PURPOSE: Bus/Device State Support + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/pcivrify.c b/drivers/bus/pcix/pcivrify.c new file mode 100644 index 00000000000..15ed1b6f3d4 --- /dev/null +++ b/drivers/bus/pcix/pcivrify.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/pcivrify.c + * PURPOSE: PCI Driver Verifier Support + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/pcix.rbuild b/drivers/bus/pcix/pcix.rbuild new file mode 100644 index 00000000000..257387b1c1f --- /dev/null +++ b/drivers/bus/pcix/pcix.rbuild @@ -0,0 +1,49 @@ + + + + + . + ntoskrnl + hal + + ar_busno.c + ar_memio.c + arb_comn.c + tr_irq.c + + + agpintrf.c + busintrf.c + cardbus.c + ideintrf.c + intrface.c + lddintrf.c + locintrf.c + pmeintf.c + routintf.c + + + busno.c + config.c + devhere.c + id.c + ppbridge.c + romimage.c + state.c + + debug.c + device.c + dispatch.c + enum.c + fdo.c + guid.c + hookhal.c + init.c + pcivrify.c + pdo.c + power.c + usage.c + utils.c + pci.rc + pci.h + diff --git a/drivers/bus/pcix/pdo.c b/drivers/bus/pcix/pdo.c new file mode 100644 index 00000000000..b54dda4bac7 --- /dev/null +++ b/drivers/bus/pcix/pdo.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/pdo.c + * PURPOSE: PDO Device Management + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/power.c b/drivers/bus/pcix/power.c new file mode 100644 index 00000000000..71a745b8fdf --- /dev/null +++ b/drivers/bus/pcix/power.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/power.c + * PURPOSE: Bus/Device Power Management + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/usage.c b/drivers/bus/pcix/usage.c new file mode 100644 index 00000000000..b317439fc42 --- /dev/null +++ b/drivers/bus/pcix/usage.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/usage.c + * PURPOSE: Bus/Device Usage Reporting + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/bus/pcix/utils.c b/drivers/bus/pcix/utils.c new file mode 100644 index 00000000000..a73b0de719a --- /dev/null +++ b/drivers/bus/pcix/utils.c @@ -0,0 +1,19 @@ +/* + * PROJECT: ReactOS PCI Bus Driver + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: drivers/bus/pci/utils.c + * PURPOSE: Utility/Helper Support Code + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +/* EOF */ diff --git a/drivers/ksfilter/ks/api.c b/drivers/ksfilter/ks/api.c index af9fd813e4d..f1ac9a848db 100644 --- a/drivers/ksfilter/ks/api.c +++ b/drivers/ksfilter/ks/api.c @@ -94,6 +94,8 @@ KsReleaseDeviceSecurityLock( { PKSIDEVICE_HEADER Header = (PKSIDEVICE_HEADER)DevHeader; + DPRINT("KsReleaseDevice\n"); + ExReleaseResourceLite(&Header->SecurityLock); KeLeaveCriticalRegion(); } @@ -1589,7 +1591,7 @@ KsAcquireControl( /* sanity check */ ASSERT(BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin); - KeWaitForSingleObject(&BasicHeader->ControlMutex, Executive, KernelMode, FALSE, NULL); + KeWaitForSingleObject(BasicHeader->ControlMutex, Executive, KernelMode, FALSE, NULL); } @@ -1606,7 +1608,7 @@ KsReleaseControl( /* sanity check */ ASSERT(BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin); - KeReleaseMutex(&BasicHeader->ControlMutex, FALSE); + KeReleaseMutex(BasicHeader->ControlMutex, FALSE); } @@ -1621,7 +1623,10 @@ KsAcquireDevice( IN PKSDEVICE Device) { IKsDevice *KsDevice; - PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice); + PKSIDEVICE_HEADER DeviceHeader; + + DPRINT("KsAcquireDevice\n"); + DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice); /* get device interface*/ KsDevice = (IKsDevice*)&DeviceHeader->lpVtblIKsDevice; diff --git a/drivers/ksfilter/ks/bag.c b/drivers/ksfilter/ks/bag.c index 1b7eec9bc5e..d0b76cc8cd1 100644 --- a/drivers/ksfilter/ks/bag.c +++ b/drivers/ksfilter/ks/bag.c @@ -89,6 +89,8 @@ KsAddItemToObjectBag( PKSIOBJECT_BAG Bag; PKSIOBJECT_BAG_ENTRY BagEntry; + DPRINT("KsAddItemToObjectBag\n"); + /* get real object bag */ Bag = (PKSIOBJECT_BAG)ObjectBag; @@ -363,6 +365,8 @@ _KsEdit( PVOID Item; NTSTATUS Status; + DPRINT("_KsEdit\n"); + /* get real object bag */ Bag = (PKSIOBJECT_BAG)ObjectBag; diff --git a/drivers/ksfilter/ks/clocks.c b/drivers/ksfilter/ks/clocks.c index 39611935076..f3e7d7acbb8 100644 --- a/drivers/ksfilter/ks/clocks.c +++ b/drivers/ksfilter/ks/clocks.c @@ -98,10 +98,10 @@ IKsClock_DispatchDeviceIoControl( { UNIMPLEMENTED - Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_NOT_IMPLEMENTED; + return STATUS_SUCCESS; } NTSTATUS diff --git a/drivers/ksfilter/ks/connectivity.c b/drivers/ksfilter/ks/connectivity.c index ae9200b518b..7c9b8226de2 100644 --- a/drivers/ksfilter/ks/connectivity.c +++ b/drivers/ksfilter/ks/connectivity.c @@ -392,34 +392,18 @@ KsPinPropertyHandler( break; } - /* calculate size */ - Size = sizeof(KSMULTIPLE_ITEM); - Size += max(1, Descriptor[Pin->PinId].InterfacesCount) * sizeof(KSPIN_INTERFACE); - - if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size) + if (Descriptor[Pin->PinId].Interfaces) { - Irp->IoStatus.Information = Size; - Status = STATUS_MORE_ENTRIES; - break; - } - - Item = (KSMULTIPLE_ITEM*)Buffer; - Item->Size = Size; - - if (Descriptor[Pin->PinId].InterfacesCount) - { - Item->Count = Descriptor[Pin->PinId].InterfacesCount; - RtlMoveMemory((PVOID)(Item + 1), Descriptor[Pin->PinId].Interfaces, Descriptor[Pin->PinId].InterfacesCount * sizeof(KSPIN_INTERFACE)); + /* use mediums provided by driver */ + return KsHandleSizedListQuery(Irp, Descriptor[Pin->PinId].InterfacesCount, sizeof(KSPIN_MEDIUM), Descriptor[Pin->PinId].Interfaces); } else { - Item->Count = 1; - RtlMoveMemory((PVOID)(Item + 1), &StandardPinInterface, sizeof(KSPIN_INTERFACE)); + /* use standard medium */ + return KsHandleSizedListQuery(Irp, 1, sizeof(KSPIN_INTERFACE), &StandardPinInterface); } - - Status = STATUS_SUCCESS; - Irp->IoStatus.Information = Size; break; + case KSPROPERTY_PIN_MEDIUMS: Pin = (KSP_PIN*)Property; if (Pin->PinId >= DescriptorsCount) diff --git a/drivers/ksfilter/ks/device.c b/drivers/ksfilter/ks/device.c index 345689f49b8..cf1d3f73216 100644 --- a/drivers/ksfilter/ks/device.c +++ b/drivers/ksfilter/ks/device.c @@ -492,7 +492,7 @@ IKsDevice_Pnp( } case IRP_MN_QUERY_INTERFACE: { - Status = STATUS_SUCCESS; + Status = STATUS_UNSUCCESSFUL; /* check for pnp notification support */ if (Dispatch) { @@ -508,6 +508,7 @@ IKsDevice_Pnp( if (NT_SUCCESS(Status)) { /* driver supports a private interface */ + DPRINT1("IRP_MN_QUERY_INTERFACE Device supports interface\n"); Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; diff --git a/drivers/ksfilter/ks/deviceinterface.c b/drivers/ksfilter/ks/deviceinterface.c index b1e74cdfd26..cd0ffe274bb 100644 --- a/drivers/ksfilter/ks/deviceinterface.c +++ b/drivers/ksfilter/ks/deviceinterface.c @@ -18,7 +18,7 @@ KspSetDeviceInterfacesState( /* set device interface state */ Status = IoSetDeviceInterfaceState(&SymEntry->SymbolicLink, Enable); - DPRINT("KspSetDeviceInterfacesState SymbolicLink %S Status %lx\n", SymEntry->SymbolicLink.Buffer, Status, Enable); + DPRINT("KspSetDeviceInterfacesState SymbolicLink '%S' Status %lx\n", SymEntry->SymbolicLink.Buffer, Status, Enable); /* check for success */ if (!NT_SUCCESS(Status)) diff --git a/drivers/ksfilter/ks/driver.c b/drivers/ksfilter/ks/driver.c index f6ace30b2bb..0b6cf43a96e 100644 --- a/drivers/ksfilter/ks/driver.c +++ b/drivers/ksfilter/ks/driver.c @@ -37,11 +37,14 @@ NTAPI KsGetDevice( IN PVOID Object) { - PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)(ULONG_PTR)Object - sizeof(KSBASIC_HEADER); + PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER)); - DPRINT("KsGetDevice %p\n", Object); + DPRINT("KsGetDevice\n"); - ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory || BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == BasicHeader->Type); + ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory || BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin); + ASSERT(BasicHeader->KsDevice); + ASSERT(BasicHeader->KsDevice->Started); + ASSERT(BasicHeader->KsDevice->PhysicalDeviceObject); return BasicHeader->KsDevice; } @@ -151,6 +154,8 @@ KsInitializeDriver( PKS_DRIVER_EXTENSION DriverObjectExtension; NTSTATUS Status = STATUS_SUCCESS; + DPRINT("KsInitializeDriver\n"); + if (Descriptor) { Status = IoAllocateDriverObjectExtension(DriverObject, (PVOID)KsInitializeDriver, sizeof(KS_DRIVER_EXTENSION), (PVOID*)&DriverObjectExtension); diff --git a/drivers/ksfilter/ks/filter.c b/drivers/ksfilter/ks/filter.c index 7a8e5b2defc..2fb69977f58 100644 --- a/drivers/ksfilter/ks/filter.c +++ b/drivers/ksfilter/ks/filter.c @@ -21,10 +21,12 @@ typedef struct PKSIOBJECT_HEADER ObjectHeader; KSTOPOLOGY Topology; + KSPIN_DESCRIPTOR_EX * PinDescriptorsEx; KSPIN_DESCRIPTOR * PinDescriptors; ULONG PinDescriptorCount; PKSFILTERFACTORY Factory; PFILE_OBJECT FileObject; + KMUTEX ControlMutex; KMUTEX ProcessingMutex; @@ -33,7 +35,7 @@ typedef struct ULONG *PinInstanceCount; PKSPIN * FirstPin; - KSPROCESSPIN_INDEXENTRY ProcessPinIndex; + PKSPROCESSPIN_INDEXENTRY ProcessPinIndex; }IKsFilterImpl; @@ -287,43 +289,32 @@ IKsFilter_fnAddProcessPin( IKsFilter * iface, IN PKSPROCESSPIN ProcessPin) { - PKSPROCESSPIN *Pins; + NTSTATUS Status; IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl); /* first acquire processing mutex */ KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL); - /* allocate new pins array */ - Pins = AllocateItem(NonPagedPool, sizeof(PKSPROCESSPIN) * (This->ProcessPinIndex.Count + 1)); + /* sanity check */ + ASSERT(This->PinDescriptorCount > ProcessPin->Pin->Id); - /* check if allocation succeeded */ - if (Pins) + /* allocate new process pin array */ + Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex[ProcessPin->Pin->Id].Pins, + (This->PinDescriptorCount + 1) * sizeof(PKSPROCESSPIN), + This->PinDescriptorCount * sizeof(PKSPROCESSPIN), + 0); + + if (NT_SUCCESS(Status)) { - if (This->ProcessPinIndex.Count) - { - /* copy old pin index */ - RtlMoveMemory(Pins, This->ProcessPinIndex.Pins, sizeof(PKSPROCESSPIN) * This->ProcessPinIndex.Count); - } - - /* add new process pin */ - Pins[This->ProcessPinIndex.Count] = ProcessPin; - - /* free old process pin */ - FreeItem(This->ProcessPinIndex.Pins); - - /* store new process pin index */ - This->ProcessPinIndex.Pins = Pins; - This->ProcessPinIndex.Count++; + /* store process pin */ + This->ProcessPinIndex[ProcessPin->Pin->Id].Pins[This->ProcessPinIndex[ProcessPin->Pin->Id].Count] = ProcessPin; + This->ProcessPinIndex[ProcessPin->Pin->Id].Count++; } /* release process mutex */ KeReleaseMutex(&This->ProcessingMutex, FALSE); - if (Pins) - return STATUS_SUCCESS; - else - return STATUS_INSUFFICIENT_RESOURCES; - + return Status; } NTSTATUS @@ -333,25 +324,39 @@ IKsFilter_fnRemoveProcessPin( IN PKSPROCESSPIN ProcessPin) { ULONG Index; + ULONG Count; + PKSPROCESSPIN * Pins; + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl); /* first acquire processing mutex */ KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL); - /* iterate through process pin index array and search for the process pin to be removed */ - for(Index = 0; Index < This->ProcessPinIndex.Count; Index++) + /* sanity check */ + ASSERT(ProcessPin->Pin); + ASSERT(ProcessPin->Pin->Id); + + Count = This->ProcessPinIndex[ProcessPin->Pin->Id].Count; + Pins = This->ProcessPinIndex[ProcessPin->Pin->Id].Pins; + + /* search for current process pin */ + for(Index = 0; Index < Count; Index++) { - if (This->ProcessPinIndex.Pins[Index] == ProcessPin) + if (Pins[Index] == ProcessPin) { - /* found process pin */ - if (Index + 1 < This->ProcessPinIndex.Count) - { - /* erase entry */ - RtlMoveMemory(&This->ProcessPinIndex.Pins[Index], &This->ProcessPinIndex.Pins[Index+1], This->ProcessPinIndex.Count - Index - 1); - } - /* decrement process pin count */ - This->ProcessPinIndex.Count--; + RtlMoveMemory(&Pins[Index], &Pins[Index + 1], (Count - (Index + 1)) * sizeof(PKSPROCESSPIN)); + break; } + + } + + /* decrement pin count */ + This->ProcessPinIndex[ProcessPin->Pin->Id].Count--; + + if (!This->ProcessPinIndex[ProcessPin->Pin->Id].Count) + { + /* clear entry object bag will delete it */ + This->ProcessPinIndex[ProcessPin->Pin->Id].Pins = NULL; } /* release process mutex */ @@ -406,8 +411,9 @@ NTAPI IKsFilter_fnGetProcessDispatch( IKsFilter * iface) { - UNIMPLEMENTED - return NULL; + IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl); + + return This->ProcessPinIndex; } static IKsFilterVtbl vt_IKsFilter = @@ -529,7 +535,7 @@ KspHandlePropertyInstances( KSPIN_CINSTANCES * Instances; KSP_PIN * Pin = (KSP_PIN*)Request; - if (!This->Factory->FilterDescriptor || !This->Factory->FilterDescriptor->PinDescriptorsCount) + if (!This->Factory->FilterDescriptor || !This->PinDescriptorCount) { /* no filter / pin descriptor */ IoStatus->Status = STATUS_NOT_IMPLEMENTED; @@ -538,11 +544,11 @@ KspHandlePropertyInstances( /* ignore custom structs for now */ ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); - ASSERT(This->Factory->FilterDescriptor->PinDescriptorsCount > Pin->PinId); + ASSERT(This->PinDescriptorCount > Pin->PinId); Instances = (KSPIN_CINSTANCES*)Data; /* max instance count */ - Instances->PossibleCount = This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].InstancesPossible; + Instances->PossibleCount = This->PinDescriptorsEx[Pin->PinId].InstancesPossible; /* current instance count */ Instances->CurrentCount = This->PinInstanceCount[Pin->PinId]; @@ -561,7 +567,7 @@ KspHandleNecessaryPropertyInstances( PULONG Result; KSP_PIN * Pin = (KSP_PIN*)Request; - if (!This->Factory->FilterDescriptor || !This->Factory->FilterDescriptor->PinDescriptorsCount) + if (!This->Factory->FilterDescriptor || !This->PinDescriptorCount) { /* no filter / pin descriptor */ IoStatus->Status = STATUS_NOT_IMPLEMENTED; @@ -570,10 +576,10 @@ KspHandleNecessaryPropertyInstances( /* ignore custom structs for now */ ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); - ASSERT(This->Factory->FilterDescriptor->PinDescriptorsCount > Pin->PinId); + ASSERT(This->PinDescriptorCount > Pin->PinId); Result = (PULONG)Data; - *Result = This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].InstancesNecessary; + *Result = This->PinDescriptorsEx[Pin->PinId].InstancesNecessary; IoStatus->Information = sizeof(ULONG); IoStatus->Status = STATUS_SUCCESS; @@ -599,7 +605,7 @@ KspHandleDataIntersection( MultipleItem = (PKSMULTIPLE_ITEM)(Pin + 1); DataRange = (PKSDATARANGE)(MultipleItem + 1); - if (!This->Factory->FilterDescriptor || !This->Factory->FilterDescriptor->PinDescriptorsCount) + if (!This->Factory->FilterDescriptor || !This->PinDescriptorCount) { /* no filter / pin descriptor */ IoStatus->Status = STATUS_NOT_IMPLEMENTED; @@ -608,11 +614,11 @@ KspHandleDataIntersection( /* ignore custom structs for now */ ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); - ASSERT(This->Factory->FilterDescriptor->PinDescriptorsCount > Pin->PinId); + ASSERT(This->PinDescriptorCount > Pin->PinId); - if (This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].IntersectHandler == NULL || - This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges == NULL || - This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRangesCount == 0) + if (This->PinDescriptorsEx[Pin->PinId].IntersectHandler == NULL || + This->PinDescriptors[Pin->PinId].DataRanges == NULL || + This->PinDescriptors[Pin->PinId].DataRangesCount == 0) { /* no driver supported intersect handler / no provided data ranges */ IoStatus->Status = STATUS_NOT_IMPLEMENTED; @@ -622,16 +628,16 @@ KspHandleDataIntersection( for(Index = 0; Index < MultipleItem->Count; Index++) { /* Call miniport's properitary handler */ - Status = This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].IntersectHandler(NULL, /* context */ - Irp, - Pin, - DataRange, - (PKSDATAFORMAT)This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges, - DataLength, - Data, - &Length); + Status = This->PinDescriptorsEx[Pin->PinId].IntersectHandler(NULL, /* context */ + Irp, + Pin, + DataRange, + (PKSDATAFORMAT)This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges, + DataLength, + Data, + &Length); - if (Status == STATUS_SUCCESS) + if (Status == STATUS_SUCCESS || Status == STATUS_BUFFER_OVERFLOW) { IoStatus->Information = Length; break; @@ -695,6 +701,8 @@ KspPinPropertyHandler( UNIMPLEMENTED Status = STATUS_UNSUCCESSFUL; } + DPRINT("KspPinPropertyHandler Pins %lu Request->Id %lu Status %lx\n", This->PinDescriptorCount, Request->Id, Status); + return Status; } @@ -736,6 +744,7 @@ IKsFilter_DispatchDeviceIoControl( } /* call property handler supported by ks */ + KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (KSPROPERTY_ITEM*)This; Status = KspPropertyHandler(Irp, 2, FilterPropertySet, NULL, sizeof(KSPROPERTY_ITEM)); if (Status == STATUS_NOT_FOUND) @@ -755,8 +764,11 @@ IKsFilter_DispatchDeviceIoControl( } } - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + if (Status != STATUS_PENDING) + { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } /* done */ return Status; @@ -783,43 +795,15 @@ IKsFilter_CreateDescriptors( KSFILTER_DESCRIPTOR* FilterDescriptor) { ULONG Index = 0; + NTSTATUS Status; /* initialize pin descriptors */ - if (FilterDescriptor->PinDescriptorsCount) - { - /* allocate pin instance count array */ - This->PinInstanceCount = AllocateItem(NonPagedPool, sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount); - if(!This->PinDescriptors) - { - return STATUS_INSUFFICIENT_RESOURCES; - } - - /* allocate first pin array */ - This->FirstPin = AllocateItem(NonPagedPool, sizeof(PKSPIN) * FilterDescriptor->PinDescriptorsCount); - if(!This->FirstPin) - { - FreeItem(This->PinDescriptors); - return STATUS_INSUFFICIENT_RESOURCES; - } - - - /* allocate pin descriptor array */ - This->PinDescriptors = AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * FilterDescriptor->PinDescriptorsCount); - if(!This->PinDescriptors) - { - FreeItem(This->PinInstanceCount); - return STATUS_INSUFFICIENT_RESOURCES; - } - - /* set pin count */ - This->PinDescriptorCount = FilterDescriptor->PinDescriptorsCount; - /* now copy those pin descriptors over */ - for(Index = 0; Index < FilterDescriptor->PinDescriptorsCount; Index++) - { - /* copy one pin per time */ - RtlMoveMemory(&This->PinDescriptors[Index], &FilterDescriptor->PinDescriptors[Index].PinDescriptor, sizeof(KSPIN_DESCRIPTOR)); - } - } + This->FirstPin = NULL; + This->PinInstanceCount = NULL; + This->PinDescriptors = NULL; + This->PinDescriptorsEx = NULL; + This->ProcessPinIndex = NULL; + This->PinDescriptorCount = 0; /* initialize topology descriptor */ This->Topology.CategoriesCount = FilterDescriptor->CategoriesCount; @@ -828,30 +812,117 @@ IKsFilter_CreateDescriptors( This->Topology.TopologyConnectionsCount = FilterDescriptor->ConnectionsCount; This->Topology.TopologyConnections = FilterDescriptor->Connections; - if (This->Topology.TopologyNodesCount > 0) + /* are there any templates */ + if (FilterDescriptor->PinDescriptorsCount) { - This->Topology.TopologyNodes = AllocateItem(NonPagedPool, sizeof(GUID) * This->Topology.TopologyNodesCount); + /* sanity check */ + ASSERT(FilterDescriptor->PinDescriptors); + + /* FIXME handle variable sized pin descriptors */ + ASSERT(FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); + + /* store pin descriptors ex */ + Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinDescriptorsEx, sizeof(KSPIN_DESCRIPTOR_EX) * FilterDescriptor->PinDescriptorsCount, + sizeof(KSPIN_DESCRIPTOR_EX) * FilterDescriptor->PinDescriptorsCount, 0); + + if (!NT_SUCCESS(Status)) + { + DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status); + return Status; + } + + /* store pin descriptors */ + Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinDescriptors, sizeof(KSPIN_DESCRIPTOR) * FilterDescriptor->PinDescriptorsCount, + sizeof(KSPIN_DESCRIPTOR) * FilterDescriptor->PinDescriptorsCount, 0); + + if (!NT_SUCCESS(Status)) + { + DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status); + return Status; + } + + /* store pin instance count ex */ + Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinInstanceCount, sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount, + sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount, 0); + + if (!NT_SUCCESS(Status)) + { + DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status); + return Status; + } + + /* store instantiated pin arrays */ + Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->FirstPin, sizeof(PKSPIN) * FilterDescriptor->PinDescriptorsCount, + sizeof(PKSPIN) * FilterDescriptor->PinDescriptorsCount, 0); + + if (!NT_SUCCESS(Status)) + { + DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status); + return Status; + } + + /* add new pin factory */ + RtlMoveMemory(This->PinDescriptorsEx, FilterDescriptor->PinDescriptors, sizeof(KSPIN_DESCRIPTOR_EX) * FilterDescriptor->PinDescriptorsCount); + + for(Index = 0; Index < FilterDescriptor->PinDescriptorsCount; Index++) + { + RtlMoveMemory(&This->PinDescriptors[Index], &FilterDescriptor->PinDescriptors[Index].PinDescriptor, sizeof(KSPIN_DESCRIPTOR)); + } + + /* allocate process pin index */ + Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex, sizeof(KSPROCESSPIN_INDEXENTRY) * FilterDescriptor->PinDescriptorsCount, + sizeof(KSPROCESSPIN_INDEXENTRY) * FilterDescriptor->PinDescriptorsCount, 0); + + if (!NT_SUCCESS(Status)) + { + DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status); + return Status; + } + + /* store new pin descriptor count */ + This->PinDescriptorCount = FilterDescriptor->PinDescriptorsCount; + + } + + if (FilterDescriptor->NodeDescriptorsCount) + { + /* sanity check */ + ASSERT(FilterDescriptor->NodeDescriptors); + + /* FIXME handle variable sized node descriptors */ + ASSERT(FilterDescriptor->NodeDescriptorSize == sizeof(KSNODE_DESCRIPTOR)); + + This->Topology.TopologyNodes = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount); /* allocate topology node types array */ if (!This->Topology.TopologyNodes) + { + DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor->NodeDescriptorsCount); return STATUS_INSUFFICIENT_RESOURCES; + } - This->Topology.TopologyNodesNames = AllocateItem(NonPagedPool, sizeof(GUID) * This->Topology.TopologyNodesCount); + This->Topology.TopologyNodesNames = AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescriptor->NodeDescriptorsCount); /* allocate topology names array */ if (!This->Topology.TopologyNodesNames) { FreeItem((PVOID)This->Topology.TopologyNodes); + DPRINT("IKsFilter_CreateDescriptors OutOfMemory TopologyNodesCount %lu\n", FilterDescriptor->NodeDescriptorsCount); return STATUS_INSUFFICIENT_RESOURCES; } - for(Index = 0; Index < This->Topology.TopologyNodesCount; Index++) + DPRINT("NodeDescriptorCount %lu\n", FilterDescriptor->NodeDescriptorsCount); + for(Index = 0; Index < FilterDescriptor->NodeDescriptorsCount; Index++) { + DPRINT("Index %lu Type %p Name %p\n", Index, FilterDescriptor->NodeDescriptors[Index].Type, FilterDescriptor->NodeDescriptors[Index].Name); + /* copy topology type */ - RtlMoveMemory((PVOID)&This->Topology.TopologyNodes[Index], FilterDescriptor->NodeDescriptors[Index].Type, sizeof(GUID)); + if (FilterDescriptor->NodeDescriptors[Index].Type) + RtlMoveMemory((PVOID)&This->Topology.TopologyNodes[Index], FilterDescriptor->NodeDescriptors[Index].Type, sizeof(GUID)); + /* copy topology name */ - RtlMoveMemory((PVOID)&This->Topology.TopologyNodesNames[Index], FilterDescriptor->NodeDescriptors[Index].Name, sizeof(GUID)); + if (FilterDescriptor->NodeDescriptors[Index].Name) + RtlMoveMemory((PVOID)&This->Topology.TopologyNodesNames[Index], FilterDescriptor->NodeDescriptors[Index].Name, sizeof(GUID)); } } - /* done! */ return STATUS_SUCCESS; } @@ -861,72 +932,24 @@ IKsFilter_CopyFilterDescriptor( IKsFilterImpl * This, const KSFILTER_DESCRIPTOR* FilterDescriptor) { - This->Filter.Descriptor = (const KSFILTER_DESCRIPTOR*)AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR)); + NTSTATUS Status; + + This->Filter.Descriptor = AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR)); if (!This->Filter.Descriptor) return STATUS_INSUFFICIENT_RESOURCES; - /* copy all fields */ + Status = KsAddItemToObjectBag(This->Filter.Bag, (PVOID)This->Filter.Descriptor, NULL); + if (!NT_SUCCESS(Status)) + { + FreeItem((PVOID)This->Filter.Descriptor); + This->Filter.Descriptor = NULL; + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* copy filter descriptor fields */ RtlMoveMemory((PVOID)This->Filter.Descriptor, FilterDescriptor, sizeof(KSFILTER_DESCRIPTOR)); - - /* perform deep copy of pin descriptors */ - if (FilterDescriptor->PinDescriptorsCount) - { - KSPIN_DESCRIPTOR_EX * PinDescriptors = (KSPIN_DESCRIPTOR_EX *)AllocateItem(NonPagedPool, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount); - - - if (!PinDescriptors) - { - FreeItem((PVOID)This->Filter.Descriptor); - return STATUS_INSUFFICIENT_RESOURCES; - } - RtlMoveMemory((PVOID)PinDescriptors, FilterDescriptor->PinDescriptors, FilterDescriptor->PinDescriptorSize * FilterDescriptor->PinDescriptorsCount); - - /* brain-dead gcc hack */ - RtlMoveMemory((PVOID)&This->Filter.Descriptor->PinDescriptors, PinDescriptors, sizeof(PKSPIN_DESCRIPTOR_EX)); - - } - - /* perform deep copy of node descriptors */ - if (FilterDescriptor->NodeDescriptorsCount) - { - KSNODE_DESCRIPTOR* NodeDescriptor = AllocateItem(NonPagedPool, FilterDescriptor->NodeDescriptorsCount * FilterDescriptor->NodeDescriptorSize); - if (!NodeDescriptor) - { - if (This->Filter.Descriptor->PinDescriptors) - FreeItem((PVOID)This->Filter.Descriptor->PinDescriptors); - FreeItem((PVOID)This->Filter.Descriptor); - return STATUS_INSUFFICIENT_RESOURCES; - } - RtlMoveMemory((PVOID)NodeDescriptor, FilterDescriptor->NodeDescriptors, FilterDescriptor->NodeDescriptorsCount * FilterDescriptor->NodeDescriptorSize); - - /* brain-dead gcc hack */ - RtlMoveMemory((PVOID)&This->Filter.Descriptor->NodeDescriptors, NodeDescriptor, sizeof(PKSNODE_DESCRIPTOR)); - } - - /* perform deep copy of connections descriptors */ - if (FilterDescriptor->NodeDescriptorsCount) - { - KSTOPOLOGY_CONNECTION* Connections = AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY_CONNECTION) * FilterDescriptor->ConnectionsCount); - if (!Connections) - { - if (This->Filter.Descriptor->PinDescriptors) - FreeItem((PVOID)This->Filter.Descriptor->PinDescriptors); - - if (This->Filter.Descriptor->NodeDescriptors) - FreeItem((PVOID)This->Filter.Descriptor->PinDescriptors); - - FreeItem((PVOID)This->Filter.Descriptor); - return STATUS_INSUFFICIENT_RESOURCES; - } - - RtlMoveMemory((PVOID)Connections, FilterDescriptor->Connections, sizeof(KSTOPOLOGY_CONNECTION) * FilterDescriptor->ConnectionsCount); - - /* brain-dead gcc hack */ - RtlMoveMemory((PVOID)&This->Filter.Descriptor->Connections, Connections, sizeof(PKSTOPOLOGY_CONNECTION)); - } - - return STATUS_SUCCESS; + return Status; } @@ -984,24 +1007,40 @@ IKsFilter_DispatchCreatePin( PKSPIN_CONNECT Connect; NTSTATUS Status; + DPRINT("IKsFilter_DispatchCreatePin\n"); + /* get the create item */ CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp); /* get the filter object */ This = (IKsFilterImpl*)CreateItem->Context; + /* sanity check */ + ASSERT(This->Header.Type == KsObjectTypeFilter); + /* acquire control mutex */ - KeWaitForSingleObject(&This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL); + KeWaitForSingleObject(This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL); /* now validate the connect request */ Status = KsValidateConnectRequest(Irp, This->PinDescriptorCount, This->PinDescriptors, &Connect); + DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest %lx\n", Status); + if (NT_SUCCESS(Status)) { - if (This->PinInstanceCount[Connect->PinId] < This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible) + /* sanity check */ + ASSERT(Connect->PinId < This->PinDescriptorCount); + + DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest PinId %lu CurrentInstanceCount %lu MaxPossible %lu\n", Connect->PinId, + This->PinInstanceCount[Connect->PinId], + This->PinDescriptorsEx[Connect->PinId].InstancesPossible); + + if (This->PinInstanceCount[Connect->PinId] < This->PinDescriptorsEx[Connect->PinId].InstancesPossible) { /* create the pin */ - Status = KspCreatePin(DeviceObject, Irp, This->Header.KsDevice, This->FilterFactory, (IKsFilter*)&This->lpVtbl, Connect, (KSPIN_DESCRIPTOR_EX*)&This->Filter.Descriptor->PinDescriptors[Connect->PinId]); + Status = KspCreatePin(DeviceObject, Irp, This->Header.KsDevice, This->FilterFactory, (IKsFilter*)&This->lpVtbl, Connect, &This->PinDescriptorsEx[Connect->PinId]); + + DPRINT("IKsFilter_DispatchCreatePin KspCreatePin %lx\n", Status); if (NT_SUCCESS(Status)) { @@ -1013,11 +1052,12 @@ IKsFilter_DispatchCreatePin( { /* maximum instance count reached, bye-bye */ Status = STATUS_UNSUCCESSFUL; + DPRINT("IKsFilter_DispatchCreatePin MaxInstance %lu CurInstance %lu %lx\n", This->PinDescriptorsEx[Connect->PinId].InstancesPossible, This->PinInstanceCount[Connect->PinId]); } } /* release control mutex */ - KeReleaseMutex(&This->Header.ControlMutex, FALSE); + KeReleaseMutex(This->Header.ControlMutex, FALSE); if (Status != STATUS_PENDING) { @@ -1025,7 +1065,9 @@ IKsFilter_DispatchCreatePin( Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); } + /* done */ + DPRINT("IKsFilter_DispatchCreatePin Result %lx\n", Status); return Status; } @@ -1118,40 +1160,52 @@ KspCreateFilter( } /* allocate filter instance */ - This = AllocateItem(NonPagedPool, sizeof(IKsFilterFactory)); + This = AllocateItem(NonPagedPool, sizeof(IKsFilterImpl)); if (!This) - return STATUS_INSUFFICIENT_RESOURCES; - - /* copy filter descriptor */ - Status = IKsFilter_CopyFilterDescriptor(This, Factory->FilterDescriptor); - if (!NT_SUCCESS(Status)) { - /* not enough memory */ - FreeItem(This); + DPRINT("KspCreateFilter OutOfMemory\n"); return STATUS_INSUFFICIENT_RESOURCES; } - /* get current irp stack */ - IoStack = IoGetCurrentIrpStackLocation(Irp); - /* initialize object bag */ This->Filter.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG)); if (!This->Filter.Bag) { /* no memory */ FreeItem(This); + DPRINT("KspCreateFilter OutOfMemory\n"); return STATUS_INSUFFICIENT_RESOURCES; } + KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice; + KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->Filter.Bag, NULL); + + /* copy filter descriptor */ + Status = IKsFilter_CopyFilterDescriptor(This, Factory->FilterDescriptor); + if (!NT_SUCCESS(Status)) + { + /* not enough memory */ + FreeItem(This->Filter.Bag); + FreeItem(This); + DPRINT("KspCreateFilter IKsFilter_CopyFilterDescriptor failed %lx\n", Status); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* get current irp stack */ + IoStack = IoGetCurrentIrpStackLocation(Irp); /* allocate create items */ CreateItem = AllocateItem(NonPagedPool, sizeof(KSOBJECT_CREATE_ITEM) * 2); if (!CreateItem) { /* no memory */ + FreeItem(This->Filter.Bag); FreeItem(This); + DPRINT("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; @@ -1164,9 +1218,6 @@ KspCreateFilter( RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_TopologyNode); - KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice; - KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->Filter.Bag, NULL); - /* initialize filter instance */ This->ref = 1; This->lpVtbl = &vt_IKsFilter; @@ -1181,7 +1232,8 @@ KspCreateFilter( This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice; This->Header.Parent.KsFilterFactory = iface->lpVtbl->GetStruct(iface); This->Header.Type = KsObjectTypeFilter; - KeInitializeMutex(&This->Header.ControlMutex, 0); + This->Header.ControlMutex = &This->ControlMutex; + KeInitializeMutex(This->Header.ControlMutex, 0); InitializeListHead(&This->Header.EventList); KeInitializeSpinLock(&This->Header.EventListLock); @@ -1192,6 +1244,7 @@ KspCreateFilter( /* what can go wrong, goes wrong */ FreeItem(This); FreeItem(CreateItem); + DPRINT("IKsFilter_CreateDescriptors failed with %lx\n", Status); return Status; } @@ -1202,6 +1255,9 @@ KspCreateFilter( if (Factory->FilterDescriptor->Dispatch->Create) { /* now let driver initialize the filter instance */ + + ASSERT(This->Header.KsDevice); + ASSERT(This->Header.KsDevice->Started); Status = Factory->FilterDescriptor->Dispatch->Create(&This->Filter, Irp); if (!NT_SUCCESS(Status) && Status != STATUS_PENDING) @@ -1236,6 +1292,7 @@ KspCreateFilter( IKsFilter_AttachFilterToFilterFactory(This, This->Header.Parent.KsFilterFactory); /* completed initialization */ + DPRINT("KspCreateFilter done %lx\n", Status); return Status; } @@ -1355,77 +1412,68 @@ KsFilterCreatePinFactory ( OUT PULONG PinID) { ULONG Count; - ULONG *PinInstanceCount; - KSPIN_DESCRIPTOR_EX * PinDescriptorsEx; - KSPIN_DESCRIPTOR * PinDescriptors; - PKSPIN *FirstPin; + NTSTATUS Status; IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter); - /* calculate existing count */ + DPRINT("KsFilterCreatePinFactory\n"); + + /* calculate new count */ Count = This->PinDescriptorCount + 1; - /* allocate pin descriptors array */ - PinDescriptorsEx = AllocateItem(NonPagedPool, max(This->Filter.Descriptor->PinDescriptorSize, sizeof(KSPIN_DESCRIPTOR_EX)) * Count); - if (!PinDescriptorsEx) - return STATUS_INSUFFICIENT_RESOURCES; + /* sanity check */ + ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); - /* allocate pin instance count array */ - PinInstanceCount = AllocateItem(NonPagedPool, sizeof(ULONG) * Count); - if (!PinInstanceCount) + /* allocate pin descriptors ex array */ + Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinDescriptorsEx, Count * sizeof(KSPIN_DESCRIPTOR_EX), This->PinDescriptorCount * sizeof(KSPIN_DESCRIPTOR_EX), 0); + if (!NT_SUCCESS(Status)) { - /* not enough memory */ - FreeItem(PinDescriptorsEx); - return STATUS_INSUFFICIENT_RESOURCES; + /* failed */ + DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status); + return Status; } - /* allocate pin descriptor array for pin property handling */ - PinDescriptors = AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * Count); - if (!PinDescriptors) + /* allocate pin descriptors array */ + Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinDescriptors, Count * sizeof(KSPIN_DESCRIPTOR), This->PinDescriptorCount * sizeof(KSPIN_DESCRIPTOR), 0); + if (!NT_SUCCESS(Status)) { - /* not enough memory */ - FreeItem(PinDescriptorsEx); - FreeItem(PinInstanceCount); - return STATUS_INSUFFICIENT_RESOURCES; + /* failed */ + DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status); + return Status; + } + + + /* allocate pin instance count array */ + Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->PinInstanceCount, sizeof(ULONG) * Count, sizeof(ULONG) * This->PinDescriptorCount, 0); + if (!NT_SUCCESS(Status)) + { + /* failed */ + DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status); + return Status; } /* allocate first pin array */ - FirstPin = AllocateItem(NonPagedPool, sizeof(PKSPIN) * Count); - if (!FirstPin) + Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->FirstPin, sizeof(PKSPIN) * Count, sizeof(PKSPIN) * This->PinDescriptorCount, 0); + if (!NT_SUCCESS(Status)) { - /* not enough memory */ - FreeItem(PinDescriptorsEx); - FreeItem(PinInstanceCount); - FreeItem(PinDescriptors); - return STATUS_INSUFFICIENT_RESOURCES; - } - - /* now copy all fields */ - if (Count > 1) - { - /* copy old descriptors */ - RtlMoveMemory(PinDescriptorsEx, This->Filter.Descriptor->PinDescriptors, max(This->Filter.Descriptor->PinDescriptorSize, sizeof(KSPIN_DESCRIPTOR_EX)) * This->PinDescriptorCount); - RtlMoveMemory(PinInstanceCount, This->PinInstanceCount, This->PinDescriptorCount * sizeof(ULONG)); - RtlMoveMemory(PinDescriptors, This->PinDescriptors, sizeof(KSPIN_DESCRIPTOR) * This->PinDescriptorCount); - RtlMoveMemory(FirstPin, This->FirstPin, sizeof(PKSPIN) * This->PinDescriptorCount); - - /* now free old descriptors */ - FreeItem(This->PinInstanceCount); - FreeItem((PVOID)This->Filter.Descriptor->PinDescriptors); - FreeItem(This->PinDescriptors); - FreeItem(This->FirstPin); + /* failed */ + DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status); + return Status; } /* add new pin factory */ - RtlMoveMemory((PVOID)((ULONG_PTR)PinDescriptorsEx + max(This->Filter.Descriptor->PinDescriptorSize, sizeof(KSPIN_DESCRIPTOR_EX)) * This->PinDescriptorCount), InPinDescriptor, sizeof(KSPIN_DESCRIPTOR)); - RtlMoveMemory((PVOID)(PinDescriptors + This->PinDescriptorCount), &InPinDescriptor->PinDescriptor, sizeof(KSPIN_DESCRIPTOR)); + RtlMoveMemory(&This->PinDescriptorsEx[This->PinDescriptorCount], InPinDescriptor, sizeof(KSPIN_DESCRIPTOR_EX)); + RtlMoveMemory(&This->PinDescriptors[This->PinDescriptorCount], &InPinDescriptor->PinDescriptor, sizeof(KSPIN_DESCRIPTOR)); - /* replace old descriptor by using a gcc-compliant hack */ - RtlMoveMemory((PVOID)&This->Filter.Descriptor->PinDescriptors, PinDescriptorsEx, sizeof(KSPIN_DESCRIPTOR_EX*)); - RtlMoveMemory((PVOID)&This->Filter.Descriptor->PinDescriptorsCount, &Count, sizeof(ULONG)); - This->PinDescriptors = PinDescriptors; - This->PinInstanceCount = PinInstanceCount; - This->FirstPin = FirstPin; + /* allocate process pin index */ + Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex, sizeof(KSPROCESSPIN_INDEXENTRY) * Count, + sizeof(KSPROCESSPIN_INDEXENTRY) * This->PinDescriptorCount, 0); + + if (!NT_SUCCESS(Status)) + { + DPRINT("KsFilterCreatePinFactory _KsEdit failed %lx\n", Status); + return Status; + } /* store new pin id */ *PinID = This->PinDescriptorCount; @@ -1433,6 +1481,8 @@ KsFilterCreatePinFactory ( /* increment pin descriptor count */ This->PinDescriptorCount++; + + DPRINT("KsFilterCreatePinFactory done\n"); return STATUS_SUCCESS; } @@ -1522,6 +1572,8 @@ KsGetFilterFromIrp( PIO_STACK_LOCATION IoStack; PKSIOBJECT_HEADER ObjectHeader; + DPRINT("KsGetFilterFromIrp\n"); + /* get current irp stack location */ IoStack = IoGetCurrentIrpStackLocation(Irp); diff --git a/drivers/ksfilter/ks/filterfactory.c b/drivers/ksfilter/ks/filterfactory.c index dc48f3c5c58..18b2147b679 100644 --- a/drivers/ksfilter/ks/filterfactory.c +++ b/drivers/ksfilter/ks/filterfactory.c @@ -21,6 +21,8 @@ typedef struct PFNKSFILTERFACTORYPOWER WakeCallback; LIST_ENTRY SymbolicLinkList; + KMUTEX ControlMutex; + }IKsFilterFactoryImpl; VOID @@ -41,6 +43,7 @@ IKsFilterFactory_Create( IN PIRP Irp) { PKSOBJECT_CREATE_ITEM CreateItem; + IKsFilterFactoryImpl * Factory; IKsFilterFactory * iface; NTSTATUS Status; @@ -53,7 +56,10 @@ IKsFilterFactory_Create( } /* get filter factory interface */ - iface = (IKsFilterFactory*)CONTAINING_RECORD(CreateItem->Context, IKsFilterFactoryImpl, FilterFactory); + Factory = (IKsFilterFactoryImpl*)CONTAINING_RECORD(CreateItem->Context, IKsFilterFactoryImpl, FilterFactory); + + /* get interface */ + iface = (IKsFilterFactory*)&Factory->lpVtbl; /* create a filter instance */ Status = KspCreateFilter(DeviceObject, Irp, iface); @@ -221,17 +227,16 @@ IKsFilterFactory_fnInitialize( This->Header.Parent.KsDevice = &DeviceExtension->DeviceHeader->KsDevice; This->DeviceHeader = DeviceExtension->DeviceHeader; + /* initialize filter factory control mutex */ + This->Header.ControlMutex = &This->ControlMutex; + KeInitializeMutex(This->Header.ControlMutex, 0); + /* unused fields */ - KeInitializeMutex(&This->Header.ControlMutex, 0); InitializeListHead(&This->Header.EventList); KeInitializeSpinLock(&This->Header.EventListLock); - InitializeListHead(&This->SymbolicLinkList); - /* initialize filter factory control mutex */ - KeInitializeMutex(&This->Header.ControlMutex, 0); - /* does the device use a reference string */ if (RefString || !Descriptor->ReferenceGuid) { @@ -253,6 +258,8 @@ IKsFilterFactory_fnInitialize( FreeString = TRUE; } + DPRINT("IKsFilterFactory_fnInitialize CategoriesCount %u ReferenceString '%S'\n", Descriptor->CategoriesCount,ReferenceString.Buffer); + /* now register the device interface */ Status = KspRegisterDeviceInterfaces(DeviceExtension->DeviceHeader->KsDevice.PhysicalDeviceObject, Descriptor->CategoriesCount, @@ -365,6 +372,10 @@ KspCreateFilterFactory( } /* return result */ + DPRINT("KsCreateFilterFactory %x\n", Status); + /* sanity check */ + ASSERT(Status == STATUS_SUCCESS); + return Status; } diff --git a/drivers/ksfilter/ks/kstypes.h b/drivers/ksfilter/ks/kstypes.h index 4bdc04c0bcb..d5c7588fda1 100644 --- a/drivers/ksfilter/ks/kstypes.h +++ b/drivers/ksfilter/ks/kstypes.h @@ -58,7 +58,7 @@ typedef struct { KSOBJECTTYPE Type; PKSDEVICE KsDevice; - KMUTEX ControlMutex; + PRKMUTEX ControlMutex; LIST_ENTRY EventList; KSPIN_LOCK EventListLock; union diff --git a/drivers/ksfilter/ks/pin.c b/drivers/ksfilter/ks/pin.c index 431fb2646f2..a4cc63bfbc6 100644 --- a/drivers/ksfilter/ks/pin.c +++ b/drivers/ksfilter/ks/pin.c @@ -11,13 +11,13 @@ typedef struct _KSISTREAM_POINTER { - KSSTREAM_POINTER StreamPointer; PFNKSSTREAMPOINTER Callback; PIRP Irp; KTIMER Timer; KDPC TimerDpc; struct _KSISTREAM_POINTER *Next; - + PKSPIN Pin; + KSSTREAM_POINTER StreamPointer; }KSISTREAM_POINTER, *PKSISTREAM_POINTER; typedef struct @@ -29,8 +29,9 @@ typedef struct LIST_ENTRY Entry; IKsPinVtbl *lpVtbl; - LONG ref; + + IKsFilter * Filter; KMUTEX ProcessingMutex; PFILE_OBJECT FileObject; @@ -50,8 +51,363 @@ typedef struct PFNKSPINFRAMERETURN FrameReturn; PFNKSPINIRPCOMPLETION IrpCompletion; + KSCLOCK_FUNCTIONTABLE ClockTable; + PFILE_OBJECT ClockFileObject; + IKsReferenceClockVtbl * lpVtblReferenceClock; + PKSDEFAULTCLOCK DefaultClock; + + PKSWORKER PinWorker; + WORK_QUEUE_ITEM PinWorkQueueItem; + IRP * Irp; + KEVENT FrameComplete; + + }IKsPinImpl; +NTSTATUS NTAPI IKsPin_PinStatePropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); +NTSTATUS NTAPI IKsPin_PinDataFormatPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); +NTSTATUS NTAPI IKsPin_PinAllocatorFramingPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); +NTSTATUS NTAPI IKsPin_PinStreamAllocator(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); +NTSTATUS NTAPI IKsPin_PinMasterClock(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); +NTSTATUS NTAPI IKsPin_PinPipeId(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data); + + + +DEFINE_KSPROPERTY_CONNECTIONSET(PinConnectionSet, IKsPin_PinStatePropertyHandler, IKsPin_PinDataFormatPropertyHandler, IKsPin_PinAllocatorFramingPropertyHandler); +DEFINE_KSPROPERTY_STREAMSET(PinStreamSet, IKsPin_PinStreamAllocator, IKsPin_PinMasterClock, IKsPin_PinPipeId); + +//TODO +// KSPROPSETID_Connection +// KSPROPERTY_CONNECTION_ACQUIREORDERING +// KSPROPSETID_StreamInterface +// KSPROPERTY_STREAMINTERFACE_HEADERSIZE + +KSPROPERTY_SET PinPropertySet[] = +{ + { + &KSPROPSETID_Connection, + sizeof(PinConnectionSet) / sizeof(KSPROPERTY_ITEM), + (const KSPROPERTY_ITEM*)&PinConnectionSet, + 0, + NULL + }, + { + &KSPROPSETID_Stream, + sizeof(PinStreamSet) / sizeof(KSPROPERTY_ITEM), + (const KSPROPERTY_ITEM*)&PinStreamSet, + 0, + NULL + } +}; + +const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; +const GUID KSPROPSETID_Stream = {0x65aaba60L, 0x98ae, 0x11cf, {0xa1, 0x0d, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4}}; +const GUID KSPROPSETID_Clock = {0xDF12A4C0L, 0xAC17, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; + +NTSTATUS +NTAPI +IKsPin_PinStreamAllocator( + IN PIRP Irp, + IN PKSIDENTIFIER Request, + IN OUT PVOID Data) +{ + UNIMPLEMENTED + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +IKsPin_PinMasterClock( + IN PIRP Irp, + IN PKSIDENTIFIER Request, + IN OUT PVOID Data) +{ + PIO_STACK_LOCATION IoStack; + PKSIOBJECT_HEADER ObjectHeader; + IKsPinImpl * This; + NTSTATUS Status = STATUS_SUCCESS; + PHANDLE Handle; + PFILE_OBJECT FileObject; + KPROCESSOR_MODE Mode; + KSPROPERTY Property; + ULONG BytesReturned; + + /* get current irp stack */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + DPRINT("IKsPin_PinMasterClock\n"); + + /* sanity check */ + ASSERT(IoStack->FileObject); + ASSERT(IoStack->FileObject->FsContext2); + + /* get the object header */ + ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2; + + /* locate ks pin implemention from KSPIN offset */ + This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin); + + /* acquire control mutex */ + KeWaitForSingleObject(This->BasicHeader.ControlMutex, Executive, KernelMode, FALSE, NULL); + + Handle = (PHANDLE)Data; + + if (Request->Flags & KSPROPERTY_TYPE_GET) + { + if (This->Pin.Descriptor->PinDescriptor.Communication != KSPIN_COMMUNICATION_NONE && + This->Pin.Descriptor->Dispatch && + (This->Pin.Descriptor->Flags & KSPIN_FLAG_IMPLEMENT_CLOCK)) + { + *Handle = NULL; + Status = STATUS_SUCCESS; + } + else + { + /* no clock available */ + Status = STATUS_UNSUCCESSFUL; + } + } + else if (Request->Flags & KSPROPERTY_TYPE_SET) + { + if (This->Pin.ClientState != KSSTATE_STOP) + { + /* can only set in stopped state */ + Status = STATUS_INVALID_DEVICE_STATE; + } + else + { + if (*Handle) + { + Mode = ExGetPreviousMode(); + + Status = ObReferenceObjectByHandle(*Handle, SYNCHRONIZE | DIRECTORY_QUERY, IoFileObjectType, Mode, (PVOID*)&FileObject, NULL); + + DPRINT("IKsPin_PinMasterClock ObReferenceObjectByHandle %lx\n", Status); + if (NT_SUCCESS(Status)) + { + Property.Set = KSPROPSETID_Clock; + Property.Id = KSPROPERTY_CLOCK_FUNCTIONTABLE; + Property.Flags = KSPROPERTY_TYPE_GET; + + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), &This->ClockTable, sizeof(KSCLOCK_FUNCTIONTABLE), &BytesReturned); + + DPRINT("IKsPin_PinMasterClock KSPROPERTY_CLOCK_FUNCTIONTABLE %lx\n", Status); + + if (NT_SUCCESS(Status)) + { + This->ClockFileObject = FileObject; + } + else + { + ObDereferenceObject(FileObject); + } + } + } + else + { + /* zeroing clock handle */ + RtlZeroMemory(&This->ClockTable, sizeof(KSCLOCK_FUNCTIONTABLE)); + Status = STATUS_SUCCESS; + if (This->ClockFileObject) + { + FileObject = This->ClockFileObject; + This->ClockFileObject = NULL; + + ObDereferenceObject(This->ClockFileObject); + } + } + } + } + + /* release processing mutex */ + KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE); + + DPRINT("IKsPin_PinStatePropertyHandler Status %lx\n", Status); + return Status; +} + + + +NTSTATUS +NTAPI +IKsPin_PinPipeId( + IN PIRP Irp, + IN PKSIDENTIFIER Request, + IN OUT PVOID Data) +{ + UNIMPLEMENTED + return STATUS_NOT_IMPLEMENTED; +} + + +NTSTATUS +NTAPI +IKsPin_PinStatePropertyHandler( + IN PIRP Irp, + IN PKSIDENTIFIER Request, + IN OUT PVOID Data) +{ + PIO_STACK_LOCATION IoStack; + PKSIOBJECT_HEADER ObjectHeader; + IKsPinImpl * This; + NTSTATUS Status = STATUS_SUCCESS; + KSSTATE OldState; + PKSSTATE NewState; + + /* get current irp stack */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + DPRINT("IKsPin_PinStatePropertyHandler\n"); + + /* sanity check */ + ASSERT(IoStack->FileObject); + ASSERT(IoStack->FileObject->FsContext2); + + /* get the object header */ + ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2; + + /* locate ks pin implemention from KSPIN offset */ + This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin); + + /* acquire control mutex */ + KeWaitForSingleObject(This->BasicHeader.ControlMutex, Executive, KernelMode, FALSE, NULL); + + /* grab state */ + NewState = (PKSSTATE)Data; + + if (Request->Flags & KSPROPERTY_TYPE_GET) + { + *NewState = This->Pin.DeviceState; + Irp->IoStatus.Information = sizeof(KSSTATE); + } + else if (Request->Flags & KSPROPERTY_TYPE_SET) + { + if (This->Pin.Descriptor->Dispatch->SetDeviceState) + { + /* backup old state */ + OldState = This->Pin.ClientState; + + /* set new state */ + This->Pin.ClientState = *NewState; + This->Pin.DeviceState = *NewState; + + /* check if it supported */ + Status = This->Pin.Descriptor->Dispatch->SetDeviceState(&This->Pin, *NewState, OldState); + + DPRINT("IKsPin_PinStatePropertyHandler NewState %lu Result %lx\n", *NewState, Status); + + if (!NT_SUCCESS(Status)) + { + /* revert to old state */ + This->Pin.ClientState = OldState; + This->Pin.DeviceState = OldState; + DbgBreakPoint(); + } + else + { + /* update device state */ + This->Pin.DeviceState = *NewState; + } + } + else + { + /* just set new state */ + This->Pin.DeviceState = *NewState; + This->Pin.ClientState = *NewState; + } + } + + /* release processing mutex */ + KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE); + + DPRINT("IKsPin_PinStatePropertyHandler Status %lx\n", Status); + return Status; +} + +NTSTATUS +NTAPI +IKsPin_PinAllocatorFramingPropertyHandler( + IN PIRP Irp, + IN PKSIDENTIFIER Request, + IN OUT PVOID Data) +{ + UNIMPLEMENTED + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +IKsPin_PinDataFormatPropertyHandler( + IN PIRP Irp, + IN PKSPROPERTY Request, + IN OUT PVOID Data) +{ + PIO_STACK_LOCATION IoStack; + PKSIOBJECT_HEADER ObjectHeader; + IKsPinImpl * This; + NTSTATUS Status = STATUS_SUCCESS; + + /* get current irp stack */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + DPRINT("IKsPin_PinDataFormatPropertyHandler\n"); + + /* sanity check */ + ASSERT(IoStack->FileObject); + ASSERT(IoStack->FileObject->FsContext2); + + /* get the object header */ + ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2; + + /* locate ks pin implemention from KSPIN offset */ + This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin); + + /* acquire control mutex */ + KeWaitForSingleObject(This->BasicHeader.ControlMutex, Executive, KernelMode, FALSE, NULL); + + if (Request->Flags & KSPROPERTY_TYPE_GET) + { + if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < This->Pin.ConnectionFormat->FormatSize) + { + /* buffer too small */ + Irp->IoStatus.Information = This->Pin.ConnectionFormat->FormatSize; + Status = STATUS_BUFFER_TOO_SMALL; + } + else + { + /* copy format */ + RtlMoveMemory(Data, This->Pin.ConnectionFormat, This->Pin.ConnectionFormat->FormatSize); + } + } + else if (Request->Flags & KSPROPERTY_TYPE_SET) + { + /* set format */ + if (This->Pin.Descriptor->Flags & KSPIN_FLAG_FIXED_FORMAT) + { + /* format cannot be changed */ + Status = STATUS_INVALID_DEVICE_REQUEST; + } + else + { + /* FIXME check if the format is supported */ + Status = _KsEdit(This->Pin.Bag, (PVOID*)&This->Pin.ConnectionFormat, IoStack->Parameters.DeviceIoControl.OutputBufferLength, This->Pin.ConnectionFormat->FormatSize, 0); + + if (NT_SUCCESS(Status)) + { + /* store new format */ + RtlMoveMemory(This->Pin.ConnectionFormat, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength); + } + } + } + + /* release processing mutex */ + KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE); + + DPRINT("IKsPin_PinDataFormatPropertyHandler Status %lx\n", Status); + + return Status; +} + NTSTATUS NTAPI IKsPin_fnQueryInterface( @@ -67,6 +423,7 @@ IKsPin_fnQueryInterface( _InterlockedIncrement(&This->ref); return STATUS_SUCCESS; } + DbgBreakPoint(); return STATUS_UNSUCCESSFUL; } @@ -270,6 +627,209 @@ static IKsPinVtbl vt_IKsPin = //============================================================== +NTSTATUS +NTAPI +IKsReferenceClock_fnQueryInterface( + IKsReferenceClock * iface, + IN REFIID refiid, + OUT PVOID* Output) +{ + IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock); + + return IKsPin_fnQueryInterface((IKsPin*)&This->lpVtbl, refiid, Output); +} + +ULONG +NTAPI +IKsReferenceClock_fnAddRef( + IKsReferenceClock * iface) +{ + IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock); + + return IKsPin_fnAddRef((IKsPin*)&This->lpVtbl); +} + +ULONG +NTAPI +IKsReferenceClock_fnRelease( + IKsReferenceClock * iface) +{ + IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock); + + return IKsPin_fnRelease((IKsPin*)&This->lpVtbl); +} + +LONGLONG +NTAPI +IKsReferenceClock_fnGetTime( + IKsReferenceClock * iface) +{ + LONGLONG Result; + + IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock); + + if (!This->ClockFileObject || !This->ClockTable.GetTime) + { + Result = 0; + } + else + { + Result = This->ClockTable.GetTime(This->ClockFileObject); + } + + return Result; +} + +LONGLONG +NTAPI +IKsReferenceClock_fnGetPhysicalTime( + IKsReferenceClock * iface) +{ + LONGLONG Result; + + IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock); + + if (!This->ClockFileObject || !This->ClockTable.GetPhysicalTime) + { + Result = 0; + } + else + { + Result = This->ClockTable.GetPhysicalTime(This->ClockFileObject); + } + + return Result; +} + + +LONGLONG +NTAPI +IKsReferenceClock_fnGetCorrelatedTime( + IKsReferenceClock * iface, + OUT PLONGLONG SystemTime) +{ + LONGLONG Result; + + IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock); + + if (!This->ClockFileObject || !This->ClockTable.GetCorrelatedTime) + { + Result = 0; + } + else + { + Result = This->ClockTable.GetCorrelatedTime(This->ClockFileObject, SystemTime); + } + + return Result; +} + + +LONGLONG +NTAPI +IKsReferenceClock_fnGetCorrelatedPhysicalTime( + IKsReferenceClock * iface, + OUT PLONGLONG SystemTime) +{ + LONGLONG Result; + + IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock); + + if (!This->ClockFileObject || !This->ClockTable.GetCorrelatedPhysicalTime) + { + Result = 0; + } + else + { + Result = This->ClockTable.GetCorrelatedPhysicalTime(This->ClockFileObject, SystemTime); + } + + return Result; +} + +NTSTATUS +NTAPI +IKsReferenceClock_fnGetResolution( + IKsReferenceClock * iface, + OUT PKSRESOLUTION Resolution) +{ + KSPROPERTY Property; + ULONG BytesReturned; + + IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock); + + DPRINT1("IKsReferenceClock_fnGetResolution\n"); + + if (!This->ClockFileObject) + { + Resolution->Error = 0; + Resolution->Granularity = 1; + DPRINT1("IKsReferenceClock_fnGetResolution Using HACK\n"); + return STATUS_SUCCESS; + } + + + if (!This->ClockFileObject) + return STATUS_DEVICE_NOT_READY; + + + Property.Set = KSPROPSETID_Clock; + Property.Id = KSPROPERTY_CLOCK_RESOLUTION; + Property.Flags = KSPROPERTY_TYPE_GET; + + return KsSynchronousIoControlDevice(This->ClockFileObject, KernelMode, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), Resolution, sizeof(KSRESOLUTION), &BytesReturned); + +} + +NTSTATUS +NTAPI +IKsReferenceClock_fnGetState( + IKsReferenceClock * iface, + OUT PKSSTATE State) +{ + KSPROPERTY Property; + ULONG BytesReturned; + + IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock); + + DPRINT1("IKsReferenceClock_fnGetState\n"); + + if (!This->ClockFileObject) + { + *State = This->Pin.ClientState; + DPRINT1("IKsReferenceClock_fnGetState Using HACK\n"); + return STATUS_SUCCESS; + } + + + if (!This->ClockFileObject) + return STATUS_DEVICE_NOT_READY; + + + Property.Set = KSPROPSETID_Clock; + Property.Id = KSPROPERTY_CLOCK_RESOLUTION; + Property.Flags = KSPROPERTY_TYPE_GET; + + return KsSynchronousIoControlDevice(This->ClockFileObject, KernelMode, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), State, sizeof(KSSTATE), &BytesReturned); +} + +static IKsReferenceClockVtbl vt_ReferenceClock = +{ + IKsReferenceClock_fnQueryInterface, + IKsReferenceClock_fnAddRef, + IKsReferenceClock_fnRelease, + IKsReferenceClock_fnGetTime, + IKsReferenceClock_fnGetPhysicalTime, + IKsReferenceClock_fnGetCorrelatedTime, + IKsReferenceClock_fnGetCorrelatedPhysicalTime, + IKsReferenceClock_fnGetResolution, + IKsReferenceClock_fnGetState +}; + + +//============================================================== + + /* @implemented */ @@ -339,6 +899,8 @@ KsPinAttemptProcessing( IN PKSPIN Pin, IN BOOLEAN Asynchronous) { + DPRINT("KsPinAttemptProcessing\n"); + DbgBreakPoint(); UNIMPLEMENTED } @@ -447,7 +1009,7 @@ KsPinGetParentFilter( } /* - @unimplemented + @implemented */ NTSTATUS NTAPI @@ -455,8 +1017,22 @@ NTAPI IN PKSPIN Pin, OUT PIKSREFERENCECLOCK* Interface) { - UNIMPLEMENTED - return STATUS_UNSUCCESSFUL; + NTSTATUS Status = STATUS_DEVICE_NOT_READY; + IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin); + + if (This->ClockFileObject) + { + /* clock is available */ + *Interface = (PIKSREFERENCECLOCK)&This->lpVtblReferenceClock; + Status = STATUS_SUCCESS; + } +//HACK + *Interface = (PIKSREFERENCECLOCK)&This->lpVtblReferenceClock; + Status = STATUS_SUCCESS; + + DPRINT("KsPinGetReferenceClockInterface Pin %p Interface %p Status %x\n", Pin, Interface, Status); + + return Status; } /* @@ -545,13 +1121,26 @@ KsGetPinFromIrp( IN PIRP Irp) { PKSIOBJECT_HEADER ObjectHeader; + PKSPIN Pin; + PKSBASIC_HEADER Header; PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp); + DPRINT("KsGetPinFromIrp\n"); + /* get object header */ ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2; - /* return object type */ - return (PKSPIN)ObjectHeader->ObjectType; + if (!ObjectHeader) + return NULL; + + Pin = (PKSPIN)ObjectHeader->ObjectType; + Header = (PKSBASIC_HEADER)((ULONG_PTR)Pin - sizeof(KSBASIC_HEADER)); + + /* sanity check */ + ASSERT(Header->Type == KsObjectTypePin); + + /* return object type */ + return Pin; } @@ -623,8 +1212,33 @@ KsPinGetLeadingEdgeStreamPointer( IN PKSPIN Pin, IN KSSTREAM_POINTER_STATE State) { - UNIMPLEMENTED - return NULL; + IKsPinImpl * This; + + This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin); + + DPRINT("KsPinGetLeadingEdgeStreamPointer Pin %p State %x Count %lu Remaining %lu\n", Pin, State, + This->LeadingEdgeStreamPointer->StreamPointer.Offset->Count, + This->LeadingEdgeStreamPointer->StreamPointer.Offset->Remaining); + + /* sanity check */ + ASSERT(This->LeadingEdgeStreamPointer); + ASSERT(State == KSSTREAM_POINTER_STATE_LOCKED); + + if (State == KSSTREAM_POINTER_STATE_LOCKED) + { + /* do we have an irp packet */ + if (!This->Irp) + { + /* run out of packets */ + return NULL; + } + + if (!This->LeadingEdgeStreamPointer->StreamPointer.Offset->Remaining) + return NULL; + } + DPRINT("LeadingEdge %p\n", &This->LeadingEdgeStreamPointer->StreamPointer); + This->LeadingEdgeStreamPointer->Pin = &This->Pin; + return &This->LeadingEdgeStreamPointer->StreamPointer; } /* @@ -679,6 +1293,8 @@ KsStreamPointerUnlock( IN BOOLEAN Eject) { UNIMPLEMENTED + DPRINT("KsStreamPointerUnlock Eject %lu\n", Eject); + DbgBreakPoint(); } /* @@ -693,6 +1309,8 @@ KsStreamPointerAdvanceOffsetsAndUnlock( IN ULONG OutUsed, IN BOOLEAN Eject) { + DPRINT("KsStreamPointerAdvanceOffsets InUsed %lu OutUsed %lu Eject %lu\n", InUsed, OutUsed, Eject); + DbgBreakPoint(); UNIMPLEMENTED } @@ -707,7 +1325,9 @@ KsStreamPointerDelete( { IKsPinImpl * This; PKSISTREAM_POINTER Cur, Last; - PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)StreamPointer; + PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer); + + DPRINT("KsStreamPointerDelete %p\n", Pointer); This = (IKsPinImpl*)CONTAINING_RECORD(Pointer->StreamPointer.Pin, IKsPinImpl, Pin); @@ -743,7 +1363,7 @@ KsStreamPointerDelete( } /* - @unimplemented + @implemented */ KSDDKAPI NTSTATUS @@ -754,12 +1374,57 @@ KsStreamPointerClone( IN ULONG ContextSize, OUT PKSSTREAM_POINTER* CloneStreamPointer) { - UNIMPLEMENTED - return STATUS_NOT_IMPLEMENTED; + IKsPinImpl * This; + PKSISTREAM_POINTER CurFrame; + PKSISTREAM_POINTER NewFrame; + ULONG RefCount; + ULONG Size; + + DPRINT("KsStreamPointerClone StreamPointer %p CancelCallback %p ContextSize %p CloneStreamPointer %p\n", StreamPointer, CancelCallback, ContextSize, CloneStreamPointer); + + /* get stream pointer */ + CurFrame = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer); + + /* calculate context size */ + Size = sizeof(KSISTREAM_POINTER) + ContextSize; + + /* allocate new stream pointer */ + NewFrame = (PKSISTREAM_POINTER)ExAllocatePool(NonPagedPool, Size); + + if (!NewFrame) + return STATUS_INSUFFICIENT_RESOURCES; + + /* get current irp stack location */ + RefCount = (ULONG)CurFrame->Irp->Tail.Overlay.DriverContext[0]; + + /* increment reference count */ + RefCount++; + CurFrame->Irp->Tail.Overlay.DriverContext[0] = (PVOID)RefCount; + + /* copy stream pointer */ + RtlMoveMemory(NewFrame, CurFrame, sizeof(KSISTREAM_POINTER)); + + if (ContextSize) + NewFrame->StreamPointer.Context = (NewFrame + 1); + + /* locate pin */ + This = (IKsPinImpl*)CONTAINING_RECORD(CurFrame->Pin, IKsPinImpl, Pin); + + NewFrame->StreamPointer.Pin = &This->Pin; + + ASSERT(NewFrame->StreamPointer.Pin); + ASSERT(NewFrame->StreamPointer.Context); + ASSERT(NewFrame->StreamPointer.Offset); + ASSERT(NewFrame->StreamPointer.StreamHeader); + + /* store result */ + *CloneStreamPointer = &NewFrame->StreamPointer; + + return STATUS_SUCCESS; } /* - @unimplemented + @implemented */ KSDDKAPI NTSTATUS @@ -770,8 +1435,58 @@ KsStreamPointerAdvanceOffsets( IN ULONG OutUsed, IN BOOLEAN Eject) { - UNIMPLEMENTED - return STATUS_NOT_IMPLEMENTED; + PKSISTREAM_POINTER CurFrame; + IKsPinImpl * This; + + DPRINT("KsStreamPointerAdvanceOffsets InUsed %lu OutUsed %lu Eject %lu\n", InUsed, OutUsed, Eject); + + /* get stream pointer */ + CurFrame = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer); + + CurFrame->StreamPointer.OffsetIn.Remaining -= InUsed; + CurFrame->StreamPointer.OffsetOut.Remaining -= OutUsed; + CurFrame->StreamPointer.OffsetIn.Count -= InUsed; + CurFrame->StreamPointer.OffsetOut.Count -= OutUsed; + CurFrame->StreamPointer.OffsetIn.Data = (PVOID)((ULONG_PTR)CurFrame->StreamPointer.OffsetIn.Data + InUsed); + CurFrame->StreamPointer.OffsetOut.Data = (PVOID)((ULONG_PTR)CurFrame->StreamPointer.OffsetOut.Data + OutUsed); + + if (!CurFrame->StreamPointer.OffsetIn.Remaining) + CurFrame->StreamPointer.OffsetIn.Data = NULL; + + if (!CurFrame->StreamPointer.OffsetOut.Remaining) + CurFrame->StreamPointer.OffsetOut.Data = NULL; + + /* locate pin */ + This = (IKsPinImpl*)CONTAINING_RECORD(CurFrame->Pin, IKsPinImpl, Pin); + + if (This->Pin.Descriptor->PinDescriptor.DataFlow == KSPIN_DATAFLOW_IN) + { + if (CurFrame->StreamPointer.OffsetIn.Remaining == 0) + { + /* get next mapping */ + This->Irp = KsRemoveIrpFromCancelableQueue(&This->IrpList, &This->IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem); + if (!This->Irp) + return STATUS_DEVICE_NOT_READY; + + /* FIXME handle me */ + ASSERT(0); + } + } + else + { + if (CurFrame->StreamPointer.OffsetOut.Remaining == 0) + { + /* get next mapping */ + This->Irp = KsRemoveIrpFromCancelableQueue(&This->IrpList, &This->IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem); + if (!This->Irp) + return STATUS_DEVICE_NOT_READY; + + /* FIXME handle me */ + ASSERT(0); + } + } + + return STATUS_SUCCESS; } /* @@ -864,7 +1579,11 @@ NTAPI KsPinGetFirstCloneStreamPointer( IN PKSPIN Pin) { - IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin); + IKsPinImpl * This; + + DPRINT("KsPinGetFirstCloneStreamPointer %p\n", Pin); + DbgBreakPoint(); + This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin); /* return first cloned stream pointer */ return &This->ClonedStreamPointer->StreamPointer; } @@ -880,6 +1599,8 @@ KsStreamPointerGetNextClone( { PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)StreamPointer; + DPRINT("KsStreamPointerGetNextClone\n"); + DbgBreakPoint(); /* is there a another cloned stream pointer */ if (!Pointer->Next) return NULL; @@ -888,6 +1609,269 @@ KsStreamPointerGetNextClone( return &Pointer->Next->StreamPointer; } +VOID +NTAPI +IKsPin_PinCentricWorker( + IN PVOID Parameter) +{ + PIO_STACK_LOCATION IoStack; + PKSSTREAM_HEADER Header; + ULONG NumHeaders; + NTSTATUS Status; + PIRP Irp; + IKsPinImpl * This = (IKsPinImpl*)Parameter; + + DPRINT("IKsPin_PinCentricWorker\n"); + + /* sanity checks */ + ASSERT(This); + ASSERT(This->Pin.Descriptor); + ASSERT(This->Pin.Descriptor->Dispatch); + ASSERT(This->Pin.Descriptor->Dispatch->Process); + ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); + ASSERT(!(This->Pin.Descriptor->Flags & KSPIN_FLAG_DISPATCH_LEVEL_PROCESSING)); + ASSERT(This->LeadingEdgeStreamPointer); + + do + { + /* do we have an irp packet */ + if (!This->Irp) + { + /* fetch new irp packet */ + This->Irp = KsRemoveIrpFromCancelableQueue(&This->IrpList, &This->IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem); + + if (!This->Irp) + { + /* reached last packet */ + break; + } + } + + /* get current irp stack location */ + IoStack = IoGetCurrentIrpStackLocation(This->Irp); + + if (This->Irp->RequestorMode == UserMode) + This->LeadingEdgeStreamPointer->StreamPointer.StreamHeader = Header = (PKSSTREAM_HEADER)This->Irp->AssociatedIrp.SystemBuffer; + else + This->LeadingEdgeStreamPointer->StreamPointer.StreamHeader = Header = (PKSSTREAM_HEADER)This->Irp->UserBuffer; + + /* calculate num headers */ + NumHeaders = IoStack->Parameters.DeviceIoControl.OutputBufferLength / Header->Size; + + /* assume headers of same length */ + ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength % Header->Size == 0); + + /* FIXME support multiple stream headers */ + ASSERT(NumHeaders == 1); + + if (This->Irp->RequestorMode == UserMode) + { + /* prepare header */ + Header->Data = MmGetSystemAddressForMdlSafe(This->Irp->MdlAddress, NormalPagePriority); + } + + /* set up stream pointer */ + This->LeadingEdgeStreamPointer->Irp = Irp = This->Irp; + This->LeadingEdgeStreamPointer->StreamPointer.Context = NULL; + This->LeadingEdgeStreamPointer->StreamPointer.Pin = &This->Pin; + This->LeadingEdgeStreamPointer->StreamPointer.OffsetOut.Count = max(Header->DataUsed, Header->FrameExtent); + This->LeadingEdgeStreamPointer->StreamPointer.OffsetOut.Data = Header->Data; + This->LeadingEdgeStreamPointer->StreamPointer.OffsetOut.Count = max(Header->DataUsed, Header->FrameExtent); + This->LeadingEdgeStreamPointer->StreamPointer.OffsetOut.Remaining = max(Header->DataUsed, Header->FrameExtent); + This->LeadingEdgeStreamPointer->Pin = &This->Pin; + + DPRINT("IKsPin_PinCentricWorker calling Pin Process Routine\n"); + + Status = This->Pin.Descriptor->Dispatch->Process(&This->Pin); + DPRINT("IKsPin_PinCentricWorker Status %lx, Count %lu Remaining %lu\n", Status, + This->LeadingEdgeStreamPointer->StreamPointer.Offset->Count, + This->LeadingEdgeStreamPointer->StreamPointer.Offset->Remaining); + + ASSERT(Status != STATUS_PENDING); + + // HACK complete irp + Irp->IoStatus.Information = max(Header->DataUsed, Header->FrameExtent); + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + KsDecrementCountedWorker(This->PinWorker); + + + break; + + }while(TRUE); +} + +NTSTATUS +NTAPI +IKsPin_DispatchKsStream( + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + IKsPinImpl * This) +{ + PKSPROCESSPIN_INDEXENTRY ProcessPinIndex; + PKSFILTER Filter; + PIO_STACK_LOCATION IoStack; + NTSTATUS Status = STATUS_SUCCESS; + + DPRINT("IKsPin_DispatchKsStream\n"); + + /* FIXME handle reset states */ + ASSERT(This->Pin.ResetState == KSRESET_END); + + /* get current stack location */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM) + Status = KsProbeStreamIrp(Irp, KSSTREAM_WRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, This->Pin.StreamHeaderSize); + else + Status = KsProbeStreamIrp(Irp, KSSTREAM_READ | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, This->Pin.StreamHeaderSize); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("KsProbeStreamIrp failed with %x\n", Status); + + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; + } + + if (This->Pin.Descriptor->Dispatch->Process) + { + /* it is a pin centric avstream */ + + /* mark irp as pending */ + IoMarkIrpPending(Irp); + + /* add irp to cancelable queue */ + KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL /* FIXME */); + + /* sanity checks */ + ASSERT(!(This->Pin.Descriptor->Flags & KSPIN_FLAG_DISPATCH_LEVEL_PROCESSING)); + ASSERT(This->PinWorker); + + /* start the processing loop */ + KsIncrementCountedWorker(This->PinWorker); + + Status = STATUS_PENDING; + } + else + { + /* filter-centric avstream */ + ASSERT(This->Filter); + + ProcessPinIndex = This->Filter->lpVtbl->GetProcessDispatch(This->Filter); + Filter = This->Filter->lpVtbl->GetStruct(This->Filter); + + ASSERT(ProcessPinIndex); + ASSERT(Filter); + ASSERT(Filter->Descriptor); + ASSERT(Filter->Descriptor->Dispatch); + + if (!Filter->Descriptor->Dispatch->Process) + { + /* invalid device request */ + DPRINT("Filter Centric Processing No Process Routine\n"); + Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_UNSUCCESSFUL; + } + + /* mark irp as pending */ + IoMarkIrpPending(Irp); + + /* add irp to cancelable queue */ + KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL /* FIXME */); + + + Status = Filter->Descriptor->Dispatch->Process(Filter, ProcessPinIndex); + + DPRINT("IKsPin_DispatchKsStream FilterCentric: Status %lx \n", Status); + + } + + return Status; +} + + +NTSTATUS +IKsPin_DispatchKsProperty( + PDEVICE_OBJECT DeviceObject, + PIRP Irp, + IKsPinImpl * This) +{ + NTSTATUS Status; + PKSPROPERTY Property; + PIO_STACK_LOCATION IoStack; + UNICODE_STRING GuidString; + ULONG PropertySetsCount = 0, PropertyItemSize = 0; + const KSPROPERTY_SET* PropertySets = NULL; + + /* sanity check */ + ASSERT(This->Pin.Descriptor); + + /* get current irp stack */ + IoStack = IoGetCurrentIrpStackLocation(Irp); + + + if (This->Pin.Descriptor->AutomationTable) + { + /* use available driver property sets */ + PropertySetsCount = This->Pin.Descriptor->AutomationTable->PropertySetsCount; + PropertySets = This->Pin.Descriptor->AutomationTable->PropertySets; + PropertyItemSize = This->Pin.Descriptor->AutomationTable->PropertyItemSize; + } + + + /* try driver provided property sets */ + Status = KspPropertyHandler(Irp, + PropertySetsCount, + PropertySets, + NULL, + PropertyItemSize); + + if (Status != STATUS_NOT_FOUND) + { + /* property was handled by driver */ + if (Status != STATUS_PENDING) + { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + return Status; + } + + /* try our properties */ + Status = KspPropertyHandler(Irp, + sizeof(PinPropertySet) / sizeof(KSPROPERTY_SET), + PinPropertySet, + NULL, + 0); + + if (Status != STATUS_NOT_FOUND) + { + /* property was handled by driver */ + if (Status != STATUS_PENDING) + { + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + return Status; + } + + /* property was not handled */ + Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; + + RtlStringFromGUID(&Property->Set, &GuidString); + DPRINT("IKsPin_DispatchKsProperty Unhandled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags); + RtlFreeUnicodeString(&GuidString); + + Irp->IoStatus.Status = STATUS_NOT_FOUND; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_NOT_FOUND; + +} + NTSTATUS NTAPI IKsPin_DispatchDeviceIoControl( @@ -897,7 +1881,6 @@ IKsPin_DispatchDeviceIoControl( PIO_STACK_LOCATION IoStack; PKSIOBJECT_HEADER ObjectHeader; IKsPinImpl * This; - NTSTATUS Status = STATUS_SUCCESS; /* get current irp stack */ IoStack = IoGetCurrentIrpStackLocation(Irp); @@ -909,40 +1892,26 @@ IKsPin_DispatchDeviceIoControl( /* get the object header */ ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2; - /* locate ks pin implemention fro KSPIN offset */ + /* locate ks pin implemention from KSPIN offset */ This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin); - if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_WRITE_STREAM && IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM) + if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY) { - UNIMPLEMENTED; - Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; - Irp->IoStatus.Information = 0; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_NOT_IMPLEMENTED; + /* handle ks properties */ + return IKsPin_DispatchKsProperty(DeviceObject, Irp, This); } - /* mark irp as pending */ - IoMarkIrpPending(Irp); - - /* add irp to cancelable queue */ - KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL /* FIXME */); - - if (This->Pin.Descriptor->Dispatch->Process) + if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM || + IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM) { - /* it is a pin centric avstream */ - Status = This->Pin.Descriptor->Dispatch->Process(&This->Pin); - - /* TODO */ - } - else - { - /* TODO - * filter-centric avstream - */ - UNIMPLEMENTED + /* handle ks properties */ + return IKsPin_DispatchKsStream(DeviceObject, Irp, This); } - return Status; + UNIMPLEMENTED; + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_NOT_IMPLEMENTED; } NTSTATUS @@ -970,7 +1939,7 @@ IKsPin_Close( This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin); /* acquire filter control mutex */ - KsFilterAcquireControl(This->BasicHeader.Parent.KsFilter); + KsFilterAcquireControl(&This->Pin); if (This->Pin.Descriptor->Dispatch->Close) { @@ -995,6 +1964,9 @@ IKsPin_Close( } } + /* release filter control mutex */ + KsFilterReleaseControl(&This->Pin); + return Status; } @@ -1017,11 +1989,80 @@ IKsPin_DispatchCreateClock( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - UNIMPLEMENTED; + PKSPIN Pin; + NTSTATUS Status = STATUS_SUCCESS; + IKsPinImpl * This; + KSRESOLUTION Resolution; + PKSRESOLUTION pResolution = NULL; + PKSOBJECT_CREATE_ITEM CreateItem; - Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + DPRINT("IKsPin_DispatchCreateClock\n"); + + /* get the create item */ + CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp); + + /* sanity check */ + ASSERT(CreateItem); + + /* get the pin object */ + Pin = (PKSPIN)CreateItem->Context; + + /* sanity check */ + ASSERT(Pin); + + /* locate ks pin implemention fro KSPIN offset */ + This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin); + + /* sanity check */ + ASSERT(This->BasicHeader.Type == KsObjectTypePin); + ASSERT(This->BasicHeader.ControlMutex); + + /* acquire control mutex */ + KsAcquireControl(Pin); + + if ((This->Pin.Descriptor->PinDescriptor.Communication != KSPIN_COMMUNICATION_NONE && + This->Pin.Descriptor->Dispatch) || + (This->Pin.Descriptor->Flags & KSPIN_FLAG_IMPLEMENT_CLOCK)) + { + if (!This->DefaultClock) + { + if (This->Pin.Descriptor->Dispatch && This->Pin.Descriptor->Dispatch->Clock) + { + if (This->Pin.Descriptor->Dispatch->Clock->Resolution) + { + This->Pin.Descriptor->Dispatch->Clock->Resolution(&This->Pin, &Resolution); + pResolution = &Resolution; + } + + Status = KsAllocateDefaultClockEx(&This->DefaultClock, + (PVOID)&This->Pin, + (PFNKSSETTIMER)This->Pin.Descriptor->Dispatch->Clock->SetTimer, + (PFNKSCANCELTIMER)This->Pin.Descriptor->Dispatch->Clock->CancelTimer, + (PFNKSCORRELATEDTIME)This->Pin.Descriptor->Dispatch->Clock->CorrelatedTime, + pResolution, + 0); + } + else + { + Status = KsAllocateDefaultClockEx(&This->DefaultClock, (PVOID)&This->Pin, NULL, NULL, NULL, NULL, 0); + } + } + + if (NT_SUCCESS(Status)) + { + Status = KsCreateDefaultClock(Irp, This->DefaultClock); + } + } + + DPRINT("IKsPin_DispatchCreateClock %lx\n", Status); + + /* release control mutex */ + KsReleaseControl(Pin); + + /* done */ + Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_NOT_IMPLEMENTED; + return Status; } NTSTATUS @@ -1054,7 +2095,7 @@ static KSDISPATCH_TABLE PinDispatchTable = NTSTATUS KspCreatePin( IN PDEVICE_OBJECT DeviceObject, - IN PIRP Irp, + IN PIRP Irp, IN PKSDEVICE KsDevice, IN IKsFilterFactory * FilterFactory, IN IKsFilter* Filter, @@ -1067,10 +2108,16 @@ KspCreatePin( PDEVICE_EXTENSION DeviceExtension; PKSOBJECT_CREATE_ITEM CreateItem; NTSTATUS Status; + PKSDATAFORMAT DataFormat; + PKSBASIC_HEADER BasicHeader; /* sanity checks */ ASSERT(Descriptor->Dispatch); - ASSERT(Descriptor->Dispatch->Create); + + DPRINT("KspCreatePin PinId %lu Flags %x\n", Connect->PinId, Descriptor->Flags); + +//Output Pin: KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY +//Input Pin: KSPIN_FLAG_FIXED_FORMAT|KSPIN_FLAG_DO_NOT_USE_STANDARD_TRANSPORT|KSPIN_FLAG_FRAMES_NOT_REQUIRED_FOR_PROCESSING /* get current irp stack */ IoStack = IoGetCurrentIrpStackLocation(Irp); @@ -1095,6 +2142,7 @@ KspCreatePin( { /* not enough memory */ FreeItem(This); + DPRINT("KspCreatePin OutOfMemory\n"); return STATUS_INSUFFICIENT_RESOURCES; } @@ -1102,21 +2150,28 @@ KspCreatePin( This->BasicHeader.KsDevice = KsDevice; This->BasicHeader.Type = KsObjectTypePin; This->BasicHeader.Parent.KsFilter = Filter->lpVtbl->GetStruct(Filter); - KeInitializeMutex(&This->BasicHeader.ControlMutex, 0); + + ASSERT(This->BasicHeader.Parent.KsFilter); + + BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)This->BasicHeader.Parent.KsFilter - sizeof(KSBASIC_HEADER)); + + This->BasicHeader.ControlMutex = BasicHeader->ControlMutex; + ASSERT(This->BasicHeader.ControlMutex); + + InitializeListHead(&This->BasicHeader.EventList); KeInitializeSpinLock(&This->BasicHeader.EventListLock); /* initialize pin */ This->lpVtbl = &vt_IKsPin; + This->lpVtblReferenceClock = &vt_ReferenceClock; This->ref = 1; This->FileObject = IoStack->FileObject; + This->Filter = Filter; KeInitializeMutex(&This->ProcessingMutex, 0); InitializeListHead(&This->IrpList); KeInitializeSpinLock(&This->IrpListLock); - /* initialize ks pin descriptor */ - This->Pin.Descriptor = Descriptor; - This->Pin.Id = Connect->PinId; /* allocate object bag */ This->Pin.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG)); @@ -1129,14 +2184,35 @@ KspCreatePin( } /* initialize object bag */ - Device->lpVtbl->InitializeObjectBag(Device, This->Pin.Bag, &This->BasicHeader.ControlMutex); /* is using control mutex right? */ + Device->lpVtbl->InitializeObjectBag(Device, This->Pin.Bag, NULL); + /* get format */ + DataFormat = (PKSDATAFORMAT)(Connect + 1); + + /* initialize pin descriptor */ + This->Pin.Descriptor = Descriptor; + This->Pin.Context = NULL; + This->Pin.Id = Connect->PinId; This->Pin.Communication = Descriptor->PinDescriptor.Communication; - This->Pin.ConnectionIsExternal = FALSE; /* FIXME */ - //FIXME This->Pin.ConnectionInterface = Descriptor->PinDescriptor.Interfaces; - //FIXME This->Pin.ConnectionMedium = Descriptor->PinDescriptor.Mediums; - //FIXME This->Pin.ConnectionPriority = KSPRIORITY_NORMAL; - This->Pin.ConnectionFormat = (PKSDATAFORMAT) (Connect + 1); + This->Pin.ConnectionIsExternal = FALSE; //FIXME + RtlMoveMemory(&This->Pin.ConnectionInterface, &Connect->Interface, sizeof(KSPIN_INTERFACE)); + RtlMoveMemory(&This->Pin.ConnectionMedium, &Connect->Medium, sizeof(KSPIN_MEDIUM)); + RtlMoveMemory(&This->Pin.ConnectionPriority, &Connect->Priority, sizeof(KSPRIORITY)); + + /* allocate format */ + Status = _KsEdit(This->Pin.Bag, (PVOID*)&This->Pin.ConnectionFormat, DataFormat->FormatSize, DataFormat->FormatSize, 0); + if (!NT_SUCCESS(Status)) + { + /* failed to allocate format */ + KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag); + FreeItem(This); + FreeItem(CreateItem); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* copy format */ + RtlMoveMemory((PVOID)This->Pin.ConnectionFormat, DataFormat, DataFormat->FormatSize); + This->Pin.AttributeList = NULL; //FIXME This->Pin.StreamHeaderSize = sizeof(KSSTREAM_HEADER); This->Pin.DataFlow = Descriptor->PinDescriptor.DataFlow; @@ -1145,19 +2221,19 @@ KspCreatePin( This->Pin.ClientState = KSSTATE_STOP; /* intialize allocator create item */ - CreateItem[0].Context = (PVOID)This; + CreateItem[0].Context = (PVOID)&This->Pin; CreateItem[0].Create = IKsPin_DispatchCreateAllocator; CreateItem[0].Flags = KSCREATE_ITEM_FREEONSTOP; RtlInitUnicodeString(&CreateItem[0].ObjectClass, KSSTRING_Allocator); /* intialize clock create item */ - CreateItem[1].Context = (PVOID)This; + CreateItem[1].Context = (PVOID)&This->Pin; CreateItem[1].Create = IKsPin_DispatchCreateClock; CreateItem[1].Flags = KSCREATE_ITEM_FREEONSTOP; RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_Clock); /* intialize topology node create item */ - CreateItem[2].Context = (PVOID)This; + CreateItem[2].Context = (PVOID)&This->Pin; CreateItem[2].Create = IKsPin_DispatchCreateNode; CreateItem[2].Flags = KSCREATE_ITEM_FREEONSTOP; RtlInitUnicodeString(&CreateItem[2].ObjectClass, KSSTRING_TopologyNode); @@ -1167,6 +2243,7 @@ KspCreatePin( if (!NT_SUCCESS(Status)) { /* failed to create object header */ + DPRINT("KspCreatePin KsAllocateObjectHeader failed %lx\n", Status); KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag); FreeItem(This); FreeItem(CreateItem); @@ -1180,37 +2257,93 @@ KspCreatePin( This->ObjectHeader->Unknown = (PUNKNOWN)&This->lpVtbl; This->ObjectHeader->ObjectType = (PVOID)&This->Pin; - /* setup process pin */ - This->ProcessPin.Pin = &This->Pin; - This->ProcessPin.StreamPointer = (PKSSTREAM_POINTER)This->LeadingEdgeStreamPointer; - if (!Descriptor->Dispatch || !Descriptor->Dispatch->Process) { /* the pin is part of filter-centric processing filter * add process pin to filter */ + This->ProcessPin.BytesAvailable = 0; + This->ProcessPin.BytesUsed = 0; + This->ProcessPin.CopySource = NULL; + This->ProcessPin.Data = NULL; + This->ProcessPin.DelegateBranch = NULL; + This->ProcessPin.Flags = 0; + This->ProcessPin.InPlaceCounterpart = NULL; + This->ProcessPin.Pin = &This->Pin; + This->ProcessPin.StreamPointer = (PKSSTREAM_POINTER)This->LeadingEdgeStreamPointer; + This->ProcessPin.Terminate = FALSE; Status = Filter->lpVtbl->AddProcessPin(Filter, &This->ProcessPin); + DPRINT("KspCreatePin AddProcessPin %lx\n", Status); + if (!NT_SUCCESS(Status)) { /* failed to add process pin */ KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag); KsFreeObjectHeader(&This->ObjectHeader); - + FreeItem(This); + FreeItem(CreateItem); /* return failure code */ return Status; } } + else if (Descriptor->Dispatch && Descriptor->Dispatch->Process) + { + /* pin centric processing filter */ + + /* allocate leading stream pointer */ + Status = _KsEdit(This->Pin.Bag, (PVOID*)&This->LeadingEdgeStreamPointer, sizeof(KSISTREAM_POINTER), sizeof(KSISTREAM_POINTER), 0); + + /* FIXME cleanup */ + ASSERT(Status == STATUS_SUCCESS); + + /* FIXME cleanup */ + ASSERT(Status == STATUS_SUCCESS); + + /* setup stream pointer offset */ + This->LeadingEdgeStreamPointer->StreamPointer.Offset = &This->LeadingEdgeStreamPointer->StreamPointer.OffsetOut; + + /* initialize work item */ + ExInitializeWorkItem(&This->PinWorkQueueItem, IKsPin_PinCentricWorker, (PVOID)This); + + /* allocate counted work item */ + Status = KsRegisterCountedWorker(HyperCriticalWorkQueue, &This->PinWorkQueueItem, &This->PinWorker); + + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed to register Worker %lx\n", Status); + KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag); + KsFreeObjectHeader(&This->ObjectHeader); + FreeItem(This); + FreeItem(CreateItem); + return Status; + } + + KeInitializeEvent(&This->FrameComplete, NotificationEvent, FALSE); + + } /* FIXME add pin instance to filter instance */ + + if (Descriptor->Dispatch && Descriptor->Dispatch->SetDataFormat) + { + Status = Descriptor->Dispatch->SetDataFormat(&This->Pin, NULL, NULL, This->Pin.ConnectionFormat, NULL); + DPRINT("KspCreatePin SetDataFormat %lx\n", Status); + } + + /* does the driver have a pin dispatch */ if (Descriptor->Dispatch && Descriptor->Dispatch->Create) { /* now inform the driver to create a new pin */ Status = Descriptor->Dispatch->Create(&This->Pin, Irp); + DPRINT("KspCreatePin DispatchCreate %lx\n", Status); } + + DPRINT("KspCreatePin Status %lx\n", Status); + if (!NT_SUCCESS(Status) && Status != STATUS_PENDING) { /* failed to create pin, release resources */ diff --git a/drivers/ksfilter/ks/priv.h b/drivers/ksfilter/ks/priv.h index cc0b8f95fef..86ea4ebba64 100644 --- a/drivers/ksfilter/ks/priv.h +++ b/drivers/ksfilter/ks/priv.h @@ -35,3 +35,24 @@ DEFINE_KSPROPERTY_TABLE(PinSet) {\ DEFINE_KSPROPERTY_ITEM_PIN_CONSTRAINEDDATARANGES(PropGeneral),\ DEFINE_KSPROPERTY_ITEM_PIN_PROPOSEDATAFORMAT(PropGeneral)\ } + +#define DEFINE_KSPROPERTY_CONNECTIONSET(PinSet,\ + PropStateHandler, PropDataFormatHandler, PropAllocatorFraming)\ +DEFINE_KSPROPERTY_TABLE(PinSet) {\ + DEFINE_KSPROPERTY_ITEM_CONNECTION_STATE(PropStateHandler, PropStateHandler),\ + DEFINE_KSPROPERTY_ITEM_CONNECTION_DATAFORMAT(PropDataFormatHandler, PropDataFormatHandler),\ + DEFINE_KSPROPERTY_ITEM_CONNECTION_ALLOCATORFRAMING(PropAllocatorFraming)\ +} + + +#define DEFINE_KSPROPERTY_STREAMSET(PinSet,\ + PropStreamAllocator, PropMasterClock, PropPipeId)\ +DEFINE_KSPROPERTY_TABLE(PinSet) {\ + DEFINE_KSPROPERTY_ITEM_STREAM_ALLOCATOR(PropStreamAllocator, PropStreamAllocator),\ + DEFINE_KSPROPERTY_ITEM_STREAM_MASTERCLOCK(PropMasterClock, PropMasterClock),\ + DEFINE_KSPROPERTY_ITEM_STREAM_PIPE_ID(PropPipeId, PropPipeId)\ +} + + + + diff --git a/drivers/ksfilter/ks/property.c b/drivers/ksfilter/ks/property.c index a2e759ca07a..b1a17e3ed09 100644 --- a/drivers/ksfilter/ks/property.c +++ b/drivers/ksfilter/ks/property.c @@ -137,7 +137,7 @@ KspPropertyHandler( /* get input property request */ Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; - DPRINT("KspPropertyHandler Irp %p PropertySetsCount %u PropertySet %p Allocator %p PropertyItemSize %u ExpectedPropertyItemSize %u\n", Irp, PropertySetsCount, PropertySet, Allocator, PropertyItemSize, sizeof(KSPROPERTY_ITEM)); +// DPRINT("KspPropertyHandler Irp %p PropertySetsCount %u PropertySet %p Allocator %p PropertyItemSize %u ExpectedPropertyItemSize %u\n", Irp, PropertySetsCount, PropertySet, Allocator, PropertyItemSize, sizeof(KSPROPERTY_ITEM)); /* sanity check */ ASSERT(PropertyItemSize == 0 || PropertyItemSize == sizeof(KSPROPERTY_ITEM)); diff --git a/drivers/multimedia/bdasup/bdasup.c b/drivers/multimedia/bdasup/bdasup.c index f2589c18b34..9e24f929867 100644 --- a/drivers/multimedia/bdasup/bdasup.c +++ b/drivers/multimedia/bdasup/bdasup.c @@ -261,19 +261,36 @@ BdaCreateFilterFactoryEx( PBDA_FILTER_INSTANCE_ENTRY FilterInstance; KIRQL OldLevel; NTSTATUS Status; - KSFILTER_DESCRIPTOR FilterDescriptor; + PKSFILTER_DESCRIPTOR FilterDescriptor; DPRINT("BdaCreateFilterFactoryEx\n"); - /* backup filter descriptor */ - RtlMoveMemory(&FilterDescriptor, pFilterDescriptor, sizeof(KSFILTER_DESCRIPTOR)); + + FilterDescriptor = AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR)); + if (!FilterDescriptor) + { + /* no memory */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* copy filter descriptor template */ + RtlMoveMemory(FilterDescriptor, pFilterDescriptor, sizeof(KSFILTER_DESCRIPTOR)); + + /* erase pin / nodes / connections from filter descriptor */ + FilterDescriptor->PinDescriptorsCount = 0; + FilterDescriptor->PinDescriptors = NULL; + FilterDescriptor->NodeDescriptorsCount = 0; + FilterDescriptor->NodeDescriptors = NULL; + FilterDescriptor->ConnectionsCount = 0; + FilterDescriptor->Connections = NULL; /* merge the automation tables */ - Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&FilterDescriptor.AutomationTable, (PKSAUTOMATION_TABLE)pFilterDescriptor->AutomationTable, &FilterAutomationTable, NULL); + Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&FilterDescriptor->AutomationTable, (PKSAUTOMATION_TABLE)pFilterDescriptor->AutomationTable, &FilterAutomationTable, NULL); /* check for success */ if (!NT_SUCCESS(Status)) { DPRINT1("KsMergeAutomationTables failed with %lx\n", Status); + FreeItem(FilterDescriptor); return Status; } @@ -282,25 +299,31 @@ BdaCreateFilterFactoryEx( if (!FilterInstance) { /* not enough memory */ + FreeItem(FilterDescriptor); return STATUS_INSUFFICIENT_RESOURCES; } /* create the filter factory */ - Status = KsCreateFilterFactory(pKSDevice->FunctionalDeviceObject, &FilterDescriptor, NULL, NULL, 0, NULL, NULL, &FilterFactory); + Status = KsCreateFilterFactory(pKSDevice->FunctionalDeviceObject, FilterDescriptor, NULL, NULL, 0, NULL, NULL, &FilterFactory); /* check for success */ if (NT_SUCCESS(Status)) { - - /* add the item to filter object bag */ - Status = KsAddItemToObjectBag(FilterFactory->Bag, FilterInstance, FreeFilterInstance); - if (!NT_SUCCESS(Status)) + if (FilterDescriptor->AutomationTable != &FilterAutomationTable) { - /* destroy filter instance */ - DPRINT1("KsAddItemToObjectBag failed with %lx\n", Status); - FreeItem(FilterInstance); - KsDeleteFilterFactory(FilterFactory); - return Status; + /* add the item to filter object bag */ + KsAddItemToObjectBag(FilterFactory->Bag, (PVOID)FilterDescriptor->AutomationTable, FreeFilterInstance); + } + else + { + /* make sure the automation table is not-read only */ + Status = _KsEdit(FilterFactory->Bag, (PVOID*)&FilterDescriptor->AutomationTable, sizeof(KSAUTOMATION_TABLE), sizeof(KSAUTOMATION_TABLE), 0); + + /* sanity check */ + ASSERT(Status == STATUS_SUCCESS); + + /* add to object bag */ + KsAddItemToObjectBag(FilterFactory->Bag, (PVOID)FilterDescriptor->AutomationTable, FreeFilterInstance); } /* initialize filter instance entry */ @@ -327,7 +350,7 @@ BdaCreateFilterFactoryEx( { /* failed to create filter factory */ FreeItem(FilterInstance); - DPRINT1("KsCreateFilterFactory failed with %lx\n", Status); + FreeItem(FilterDescriptor); } /* done */ @@ -350,7 +373,7 @@ BdaCreatePin( PBDA_FILTER_INSTANCE_ENTRY InstanceEntry; NTSTATUS Status; ULONG PinId; - KSPIN_DESCRIPTOR_EX NewPinDescriptor; + PKSPIN_DESCRIPTOR_EX NewPinDescriptor; DPRINT("BdaCreatePin\n"); @@ -380,6 +403,7 @@ BdaCreatePin( if (!InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount) { /* no pins supported */ + DPRINT("BdaCreatePin NoPins supported\n"); return STATUS_UNSUCCESSFUL; } @@ -387,6 +411,7 @@ BdaCreatePin( if (InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount <= ulPinType) { /* pin request is out of bounds */ + DPRINT("BdaCreatePin ulPinType %lu >= PinDescriptorCount %lu\n", ulPinType, InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount); return STATUS_INVALID_PARAMETER; } @@ -396,17 +421,26 @@ BdaCreatePin( /* get pin descriptor */ PinDescriptor = (PKSPIN_DESCRIPTOR_EX)&InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptors[ulPinType]; + /* allocate pin descriptor */ + NewPinDescriptor = AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR_EX)); + if (!NewPinDescriptor) + { + /* no memory */ + DPRINT("BdaCreatePin OutOfMemory\n"); + return STATUS_INSUFFICIENT_RESOURCES; + } + /* make a copy of the pin descriptor */ - RtlMoveMemory(&NewPinDescriptor, PinDescriptor, sizeof(KSPIN_DESCRIPTOR_EX)); + RtlMoveMemory(NewPinDescriptor, PinDescriptor, sizeof(KSPIN_DESCRIPTOR_EX)); /* merge the automation tables */ - Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&NewPinDescriptor.AutomationTable, (PKSAUTOMATION_TABLE)PinDescriptor->AutomationTable, &PinAutomationTable, pKSFilter->Bag); + Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&NewPinDescriptor->AutomationTable, (PKSAUTOMATION_TABLE)PinDescriptor->AutomationTable, &PinAutomationTable, pKSFilter->Bag); /* check for success */ if (NT_SUCCESS(Status)) { /* create the pin factory */ - Status = KsFilterCreatePinFactory(pKSFilter, &NewPinDescriptor, &PinId); + Status = KsFilterCreatePinFactory(pKSFilter, NewPinDescriptor, &PinId); /* check for success */ if (NT_SUCCESS(Status)) @@ -417,7 +451,7 @@ BdaCreatePin( } - DPRINT("BdaCreatePin Result %x\n", Status); + DPRINT("BdaCreatePin Result %x PinId %u\n", Status, PinId); return Status; } @@ -470,7 +504,7 @@ BdaInitFilter( ULONG Index, PinId; NTSTATUS Status = STATUS_SUCCESS; - DPRINT("BdaInitFilter\n"); + DPRINT("BdaInitFilter %p\n", pBdaFilterTemplate); /* check input parameters */ if (!pKSFilter) @@ -487,7 +521,12 @@ BdaInitFilter( /* sanity check */ ASSERT(InstanceEntry); - ASSERT(InstanceEntry->FilterTemplate == pBdaFilterTemplate); + + if (!pBdaFilterTemplate) + { + /* use template from BdaCreateFilterFactoryEx */ + pBdaFilterTemplate = InstanceEntry->FilterTemplate; + } /* now create the pins */ for(Index = 0; Index < pBdaFilterTemplate->pFilterDescriptor->PinDescriptorsCount; Index++) diff --git a/drivers/multimedia/bdasup/precomp.h b/drivers/multimedia/bdasup/precomp.h index 927bc960af2..db581728221 100644 --- a/drivers/multimedia/bdasup/precomp.h +++ b/drivers/multimedia/bdasup/precomp.h @@ -7,7 +7,7 @@ #include #include -#define NDEBUG +#define YDEBUG #include diff --git a/drivers/storage/ide/uniata/id_ata.cpp b/drivers/storage/ide/uniata/id_ata.cpp index 1cace8bd488..fb2bb028e87 100644 --- a/drivers/storage/ide/uniata/id_ata.cpp +++ b/drivers/storage/ide/uniata/id_ata.cpp @@ -537,10 +537,10 @@ WaitOnBaseBusy( { ULONG i; UCHAR Status; - for (i=0; i<200; i++) { + for (i=0; i<20000; i++) { GetBaseStatus(chan, Status); if (Status & IDE_STATUS_BUSY) { - AtapiStallExecution(10); + AtapiStallExecution(150); continue; } else { break; @@ -640,11 +640,11 @@ WaitForDrq( for (i=0; i<1000; i++) { GetStatus(chan, Status); if (Status & IDE_STATUS_BUSY) { - AtapiStallExecution(10); + AtapiStallExecution(100); } else if (Status & IDE_STATUS_DRQ) { break; } else { - AtapiStallExecution(10); + AtapiStallExecution(200); } } return Status; @@ -661,11 +661,11 @@ WaitShortForDrq( for (i=0; i<2; i++) { GetStatus(chan, Status); if (Status & IDE_STATUS_BUSY) { - AtapiStallExecution(10); + AtapiStallExecution(100); } else if (Status & IDE_STATUS_DRQ) { break; } else { - AtapiStallExecution(10); + AtapiStallExecution(100); } } return Status; diff --git a/drivers/usb/usbehci/fdo.c b/drivers/usb/usbehci/fdo.c index eebc0c0905a..b1ec5503cb6 100644 --- a/drivers/usb/usbehci/fdo.c +++ b/drivers/usb/usbehci/fdo.c @@ -100,9 +100,9 @@ EhciDefferedRoutine(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVO tmp = READ_REGISTER_ULONG((PULONG)((Base + EHCI_PORTSC) + (4 * i))); - DPRINT("port tmp %x\n", tmp); GetDeviceDescriptor(FdoDeviceExtension, 0, 0, FALSE); PdoDeviceExtension->ChildDeviceCount++; + PdoDeviceExtension->Ports[i].PortStatus |= USB_PORT_STATUS_HIGH_SPEED | USB_PORT_STATUS_CONNECT | USB_PORT_STATUS_ENABLE; WorkItemData = ExAllocatePool(NonPagedPool, sizeof(WORKITEM_DATA)); if (!WorkItemData) ASSERT(FALSE); WorkItemData->IoWorkItem = IoAllocateWorkItem(PdoDeviceExtension->DeviceObject); diff --git a/drivers/usb/usbehci/irp.c b/drivers/usb/usbehci/irp.c index 29af1f92ce7..06d7c50ab08 100644 --- a/drivers/usb/usbehci/irp.c +++ b/drivers/usb/usbehci/irp.c @@ -88,35 +88,65 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) if (UsbDevice == NULL) UsbDevice = DeviceExtension->UsbDevices[0]; + /* Assume URB success */ + Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; + /* Set the DeviceHandle to the Internal Device */ + Urb->UrbHeader.UsbdDeviceHandle = UsbDevice; + switch (Urb->UrbHeader.Function) { case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER: { - /* Are we suppose to only return on this request when a device is connected - or is it the RootHubInitNotification Callback */ DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:\n"); DPRINT1("--->TransferBufferLength %x\n",Urb->UrbBulkOrInterruptTransfer.TransferBufferLength); DPRINT1("--->TransferBuffer %x\n",Urb->UrbBulkOrInterruptTransfer.TransferBuffer); DPRINT1("--->PipeHandle %x\n",Urb->UrbBulkOrInterruptTransfer.PipeHandle); + DPRINT1("---->(PVOID)&UsbDevice->EndPointDescriptor %x\n", (PVOID)&UsbDevice->EndPointDescriptor); DPRINT1("--->TransferFlags %x\n", Urb->UrbBulkOrInterruptTransfer.TransferFlags); - /* FIXME */ + RtlZeroMemory(Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength); - ((PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 1; - /* Turn off Irp handling as nothing is handled beyond this */ - DeviceExtension->HaltUrbHandling = TRUE; + if (UsbDevice == DeviceExtension->UsbDevices[0]) + { + if (Urb->UrbBulkOrInterruptTransfer.TransferFlags & (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK)) + { + LONG i; + for (i = 0; i < 8; i++) + { + if (DeviceExtension->Ports[i].PortChange) + { + DPRINT1("Inform hub driver that port %d has changed\n", i+1); + ((PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 1 << (i + 1); + } + } + } + else + { + Urb->UrbHeader.Status = USBD_STATUS_INVALID_PARAMETER; + Status = STATUS_UNSUCCESSFUL; + } + } break; } case URB_FUNCTION_GET_STATUS_FROM_DEVICE: { - DPRINT1("Get Status from Device\n"); + DPRINT("Get Status from Device\n"); + DPRINT("Index : %d\n", Urb->UrbControlGetStatusRequest.Index); + + /* Copied from pvdrivers */ + if (Urb->UrbControlGetStatusRequest.Index == 0) + { + *(PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer = USB_PORT_STATUS_CONNECT | USB_PORT_STATUS_ENABLE; + } + else + { + DPRINT1("Uknown identifier\n"); + Urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION; + Status = STATUS_UNSUCCESSFUL; + } break; } case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE: { - Urb->UrbHeader.Function = 0x08; - Urb->UrbHeader.UsbdFlags = 0; - Urb->UrbHeader.UsbdDeviceHandle = UsbDevice; - switch(Urb->UrbControlDescriptorRequest.DescriptorType) { case USB_DEVICE_DESCRIPTOR_TYPE: @@ -130,9 +160,6 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, &UsbDevice->DeviceDescriptor, Urb->UrbControlDescriptorRequest.TransferBufferLength); - - Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; - break; } case USB_CONFIGURATION_DESCRIPTOR_TYPE: @@ -150,9 +177,6 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer, &UsbDevice->ConfigurationDescriptor, Urb->UrbControlDescriptorRequest.TransferBufferLength); - - Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; - break; } case USB_STRING_DESCRIPTOR_TYPE: @@ -232,10 +256,6 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) } InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)((PUCHAR)InterfaceInfo + InterfaceInfo->Length); } - - Urb->UrbHeader.UsbdDeviceHandle = UsbDevice; - Urb->UrbHeader.UsbdFlags = 0; - Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; } else { @@ -252,7 +272,6 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags); DPRINT1("Urb->UrbControlVendorClassRequest.Value %x\n", Urb->UrbControlVendorClassRequest.Value); - switch (Urb->UrbControlVendorClassRequest.Value >> 8) { case USB_DEVICE_CLASS_AUDIO: @@ -328,10 +347,16 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) DPRINT1("Unknown UrbControlVendorClassRequest Value\n"); } } - Urb->UrbHeader.Function = 0x08; - Urb->UrbHeader.Status = USBD_STATUS_SUCCESS; - Urb->UrbHeader.UsbdDeviceHandle = UsbDevice; - Urb->UrbHeader.UsbdFlags = 0; + break; + } + case USB_REQUEST_GET_STATUS: + { + DPRINT1("DEVICE: USB_REQUEST_GET_STATUS for port %d\n", Urb->UrbControlVendorClassRequest.Index); + + if (Urb->UrbControlVendorClassRequest.Index == 1) + { + ((PULONG)Urb->UrbControlVendorClassRequest.TransferBuffer)[0] = 0; + } break; } default: @@ -348,22 +373,51 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) { case USB_REQUEST_GET_STATUS: { - DPRINT1("USB_REQUEST_GET_STATUS\n"); + DPRINT1("OTHER: USB_REQUEST_GET_STATUS for port %d\n", Urb->UrbControlVendorClassRequest.Index); + + ((PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer)[0] = DeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus; + ((PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer)[1] = DeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange; break; } case USB_REQUEST_CLEAR_FEATURE: { - DPRINT1("USB_REQUEST_CLEAR_FEATURE\n"); + DPRINT1("USB_REQUEST_CLEAR_FEATURE Port %d, value %x\n", Urb->UrbControlVendorClassRequest.Index, + Urb->UrbControlVendorClassRequest.Value); + switch (Urb->UrbControlVendorClassRequest.Value) + { + case C_PORT_CONNECTION: + DeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange &= ~USB_PORT_STATUS_CONNECT; + break; + case C_PORT_RESET: + DeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange &= ~USB_PORT_STATUS_RESET; + break; + default: + DPRINT1("Unknown Value for Clear Feature %x \n", Urb->UrbControlVendorClassRequest.Value); + break; + } break; } case USB_REQUEST_SET_FEATURE: { - DPRINT1("USB_REQUEST_SET_FEATURE value %x\n", Urb->UrbControlVendorClassRequest.Value); + DPRINT1("USB_REQUEST_SET_FEATURE Port %d, value %x\n", Urb->UrbControlVendorClassRequest.Index, + Urb->UrbControlVendorClassRequest.Value); + switch(Urb->UrbControlVendorClassRequest.Value) { - /* FIXME: Needs research */ - case 0x01: + case PORT_RESET: { + DeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange |= USB_PORT_STATUS_RESET; + break; + } + case PORT_ENABLE: + { + DPRINT1("Unhandled Set Feature\n"); + break; + } + default: + { + DPRINT1("Unknown Set Feature!\n"); + break; } } break; @@ -371,6 +425,7 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) case USB_REQUEST_SET_ADDRESS: { DPRINT1("USB_REQUEST_SET_ADDRESS\n"); + ASSERT(FALSE); break; } case USB_REQUEST_GET_DESCRIPTOR: @@ -408,6 +463,12 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) DPRINT1("USB_REQUEST_SYNC_FRAME\n"); break; } + default: + { + DPRINT1("Unknown Function Class Unknown request\n"); + ASSERT(FALSE); + break; + } } break; } @@ -415,6 +476,7 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) { DPRINT1("Unhandled URB %x\n", Urb->UrbHeader.Function); Urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION; + ASSERT(FALSE); } } @@ -424,6 +486,13 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension) Irp->IoStatus.Status = Status; Irp->IoStatus.Information = Information; + if (Urb->UrbHeader.Status == USBD_STATUS_SUCCESS) + { + /* Fake a successful Control Transfer */ + Urb->UrbHeader.Function = 0x08; + Urb->UrbHeader.UsbdFlags = 0; + } + IoCompleteRequest(Irp, IO_NO_INCREMENT); KeAcquireSpinLock(&DeviceExtension->IrpQueueLock, &oldIrql); } diff --git a/drivers/usb/usbehci/pdo.c b/drivers/usb/usbehci/pdo.c index 3ab717f0f56..6a0d735e851 100644 --- a/drivers/usb/usbehci/pdo.c +++ b/drivers/usb/usbehci/pdo.c @@ -172,18 +172,24 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) } case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE: { - DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n"); + DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %x\n", IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE); + if (Stack->Parameters.Others.Argument1) + { + /* Return the root hubs devicehandle */ + *(PVOID *)Stack->Parameters.Others.Argument1 = (PVOID)PdoDeviceExtension->UsbDevices[0]; + } + else + Status = STATUS_INVALID_DEVICE_REQUEST; break; } case IOCTL_INTERNAL_USB_GET_HUB_COUNT: { - DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n"); - + DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT %x\n", IOCTL_INTERNAL_USB_GET_HUB_COUNT); if (Stack->Parameters.Others.Argument1) { /* FIXME: Determine the number of hubs between the usb device and root hub */ - /* For now return 0 */ - *(PVOID *)Stack->Parameters.Others.Argument1 = 0; + /* For now return 1, the root hub */ + *(PVOID *)Stack->Parameters.Others.Argument1 = (PVOID)1; } break; } @@ -216,9 +222,8 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) if (Stack->Parameters.Others.Argument2) *(PVOID *)Stack->Parameters.Others.Argument2 = IoGetAttachedDevice(FdoDeviceExtension->DeviceObject); - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_SUCCESS; - return STATUS_SUCCESS; + Information = 0; + Status = STATUS_SUCCESS; break; } case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION: @@ -287,7 +292,6 @@ PdoQueryId(PDEVICE_OBJECT DeviceObject, PIRP Irp, ULONG_PTR* Information) } } - /* Lifted from hpoussin */ Status = DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &SourceString, &String); @@ -350,6 +354,7 @@ PdoDispatchPnp( PPDO_DEVICE_EXTENSION PdoDeviceExtension; PFDO_DEVICE_EXTENSION FdoDeviceExtension; UNICODE_STRING InterfaceSymLinkName; + LONG i; PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->ControllerFdo->DeviceExtension; @@ -357,6 +362,12 @@ PdoDispatchPnp( /* Create the root hub */ RootHubDevice = InternalCreateUsbDevice(1, 0, NULL, TRUE); + for (i = 0; i < 8; i++) + { + PdoDeviceExtension->Ports[i].PortStatus = USB_PORT_STATUS_ENABLE; + PdoDeviceExtension->Ports[i].PortChange = 0; + } + RtlCopyMemory(&RootHubDevice->DeviceDescriptor, ROOTHUB2_DEVICE_DESCRIPTOR, sizeof(ROOTHUB2_DEVICE_DESCRIPTOR)); @@ -409,8 +420,16 @@ PdoDispatchPnp( break; } case BusRelations: + DPRINT1("BusRelations!!!!!\n"); case RemovalRelations: case EjectionRelations: + { + /* Ignore the request */ + Information = Irp->IoStatus.Information; + Status = Irp->IoStatus.Status; + break; + + } default: { DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unhandled type 0x%lx\n", @@ -534,7 +553,8 @@ PdoDispatchPnp( else { DPRINT1("Not Supported\n"); - Status = STATUS_NOT_SUPPORTED; + Status = Irp->IoStatus.Status; + Information = Irp->IoStatus.Information; } break; } diff --git a/drivers/usb/usbehci/usbehci.h b/drivers/usb/usbehci/usbehci.h index f4c440df616..13bfabb3657 100644 --- a/drivers/usb/usbehci/usbehci.h +++ b/drivers/usb/usbehci/usbehci.h @@ -75,6 +75,25 @@ OR with QUEUE_TRANSFER_DESCRIPTOR Token.SplitTransactionState */ #define PING_STATE_DO_OUT 0x00 #define PING_STATE_DO_PING 0x01 +#define C_HUB_LOCAL_POWER 0 +#define C_HUB_OVER_CURRENT 1 +#define PORT_CONNECTION 0 +#define PORT_ENABLE 1 +#define PORT_SUSPEND 2 +#define PORT_OVER_CURRENT 3 +#define PORT_RESET 4 +#define PORT_POWER 8 +#define PORT_LOW_SPEED 9 +#define PORT_HIGH_SPEED 9 +#define C_PORT_CONNECTION 16 +#define C_PORT_ENABLE 17 +#define C_PORT_SUSPEND 18 +#define C_PORT_OVER_CURRENT 19 +#define C_PORT_RESET 20 +#define PORT_TEST 21 +#define PORT_INDICATOR 22 +#define USB_PORT_STATUS_CHANGE 0x4000 + /* QUEUE ELEMENT TRANSFER DESCRIPTOR TOKEN */ typedef struct _QETD_TOKEN_BITS { @@ -273,16 +292,16 @@ typedef struct _EHCI_HCC_CONTENT } EHCI_HCC_CONTENT, *PEHCI_HCC_CONTENT; typedef struct _EHCI_CAPS { - UCHAR Length; - UCHAR Reserved; - USHORT HCIVersion; + UCHAR Length; + UCHAR Reserved; + USHORT HCIVersion; union { - EHCI_HCS_CONTENT HCSParams; - ULONG HCSParamsLong; + EHCI_HCS_CONTENT HCSParams; + ULONG HCSParamsLong; }; - ULONG HCCParams; - UCHAR PortRoute [8]; + ULONG HCCParams; + UCHAR PortRoute [8]; } EHCI_CAPS, *PEHCI_CAPS; typedef struct _COMMON_DEVICE_EXTENSION @@ -292,6 +311,14 @@ typedef struct _COMMON_DEVICE_EXTENSION PDEVICE_OBJECT DeviceObject; } COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION; +typedef struct _EHCIPORTS +{ + ULONG PortNumber; + ULONG PortType; + USHORT PortStatus; + USHORT PortChange; +} EHCIPORTS, *PEHCIPORTS; + typedef struct _FDO_DEVICE_EXTENSION { COMMON_DEVICE_EXTENSION Common; @@ -333,8 +360,8 @@ typedef struct _FDO_DEVICE_EXTENSION PULONG PeriodicFramList; PULONG AsyncListQueueHeadPtr; - PHYSICAL_ADDRESS PeriodicFramListPhysAddr; - PHYSICAL_ADDRESS AsyncListQueueHeadPtrPhysAddr; + PHYSICAL_ADDRESS PeriodicFramListPhysAddr; + PHYSICAL_ADDRESS AsyncListQueueHeadPtrPhysAddr; BOOLEAN AsyncComplete; @@ -356,6 +383,8 @@ typedef struct _PDO_DEVICE_EXTENSION BOOLEAN HaltUrbHandling; PVOID CallbackContext; PRH_INIT_CALLBACK CallbackRoutine; + ULONG NumberOfPorts; + EHCIPORTS Ports[32]; } PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION; typedef struct _WORKITEM_DATA diff --git a/hal/halx86/directory.rbuild b/hal/halx86/directory.rbuild index abedef8ea1c..7cea4c006fa 100644 --- a/hal/halx86/directory.rbuild +++ b/hal/halx86/directory.rbuild @@ -5,7 +5,9 @@ - + + + diff --git a/hal/halx86/generic/acpi/halacpi.c b/hal/halx86/generic/acpi/halacpi.c index f9fe8731dcc..1efee7996a4 100644 --- a/hal/halx86/generic/acpi/halacpi.c +++ b/hal/halx86/generic/acpi/halacpi.c @@ -37,6 +37,13 @@ LIST_ENTRY HalpAcpiTableMatchList; ULONG HalpInvalidAcpiTable; +ULONG HalpPicVectorRedirect[] = {0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15}; + +/* This determines the HAL type */ +BOOLEAN HalDisableFirmwareMapper = TRUE; +PWCHAR HalHardwareIdString = L"acpipic_up"; +PWCHAR HalName = L"ACPI Compatible Eisa/Isa HAL"; + /* PRIVATE FUNCTIONS **********************************************************/ PDESCRIPTION_HEADER @@ -861,4 +868,179 @@ HalpSetupAcpiPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock) return STATUS_SUCCESS; } +VOID +NTAPI +HalpInitializePciBus(VOID) +{ + /* Setup the PCI stub support */ + HalpInitializePciStubs(); + + /* Set the NMI crash flag */ + HalpGetNMICrashFlag(); +} + +VOID +NTAPI +HalpBuildAddressMap(VOID) +{ + /* ACPI is magic baby */ +} + +BOOLEAN +NTAPI +HalpGetDebugPortTable(VOID) +{ + return ((HalpDebugPortTable) && + (HalpDebugPortTable->BaseAddress.AddressSpaceID == 1)); +} + +ULONG +NTAPI +HalpIs16BitPortDecodeSupported(VOID) +{ + /* All ACPI systems are at least "EISA" so they support this */ + return CM_RESOURCE_PORT_16_BIT_DECODE; +} + +VOID +NTAPI +HalpAcpiDetectResourceListSize(OUT PULONG ListSize) +{ + PAGED_CODE(); + + /* One element if there is a SCI */ + *ListSize = HalpFixedAcpiDescTable.sci_int_vector ? 1: 0; +} + +NTSTATUS +NTAPI +HalpBuildAcpiResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceList) +{ + ULONG Interrupt; + PAGED_CODE(); + ASSERT(ResourceList != NULL); + + /* Initialize the list */ + ResourceList->BusNumber = -1; + ResourceList->AlternativeLists = 1; + ResourceList->InterfaceType = PNPBus; + ResourceList->List[0].Version = 1; + ResourceList->List[0].Revision = 1; + + /* Is there a SCI? */ + if (HalpFixedAcpiDescTable.sci_int_vector) + { + /* Fill out the entry for it */ + ResourceList->List[0].Descriptors[0].Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; + ResourceList->List[0].Descriptors[0].Type = CmResourceTypeInterrupt; + ResourceList->List[0].Descriptors[0].ShareDisposition = CmResourceShareShared; + + /* Get the interrupt number */ + Interrupt = HalpPicVectorRedirect[HalpFixedAcpiDescTable.sci_int_vector]; + ResourceList->List[0].Descriptors[0].u.Interrupt.MinimumVector = Interrupt; + ResourceList->List[0].Descriptors[0].u.Interrupt.MaximumVector = Interrupt; + + /* One more */ + ++ResourceList->List[0].Count; + } + + /* All good */ + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +HalpQueryAcpiResourceRequirements(OUT PIO_RESOURCE_REQUIREMENTS_LIST *Requirements) +{ + PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; + ULONG Count = 0, ListSize; + NTSTATUS Status; + PAGED_CODE(); + + /* Get ACPI resources */ + HalpAcpiDetectResourceListSize(&Count); + + /* Compute size of the list and allocate it */ + ListSize = sizeof(IO_RESOURCE_LIST) * (Count - 1) + + sizeof(IO_RESOURCE_REQUIREMENTS_LIST); + RequirementsList = ExAllocatePoolWithTag(PagedPool, ListSize, ' laH'); + if (RequirementsList) + { + /* Initialize it */ + RtlZeroMemory(RequirementsList, ListSize); + RequirementsList->ListSize = ListSize; + + /* Build it */ + Status = HalpBuildAcpiResourceList(RequirementsList); + if (NT_SUCCESS(Status)) + { + /* It worked, return it */ + *Requirements = RequirementsList; + } + else + { + /* Fail */ + ExFreePoolWithTag(RequirementsList, 0); + Status = STATUS_NO_SUCH_DEVICE; + } + } + else + { + /* Not enough memory */ + Status = STATUS_INSUFFICIENT_RESOURCES; + } + + /* Return the status */ + return Status; +} + +/* + * @implemented + */ +VOID +NTAPI +HalReportResourceUsage(VOID) +{ + INTERFACE_TYPE InterfaceType; + UNICODE_STRING HalString; + + /* FIXME: Initialize DMA 64-bit support */ + + /* FIXME: Initialize MCA bus */ + + /* Initialize PCI bus. */ + HalpInitializePciBus(); + + /* What kind of bus is this? */ + switch (HalpBusType) + { + /* ISA Machine */ + case MACHINE_TYPE_ISA: + InterfaceType = Isa; + break; + + /* EISA Machine */ + case MACHINE_TYPE_EISA: + InterfaceType = Eisa; + break; + + /* MCA Machine */ + case MACHINE_TYPE_MCA: + InterfaceType = MicroChannel; + break; + + /* Unknown */ + default: + InterfaceType = Internal; + break; + } + + /* Build HAL usage */ + RtlInitUnicodeString(&HalString, HalName); + HalpReportResourceUsage(&HalString, InterfaceType); + + /* Setup PCI debugging and Hibernation */ + HalpRegisterPciDebuggingDeviceInfo(); +} + /* EOF */ diff --git a/hal/halx86/generic/acpi/halpnpdd.c b/hal/halx86/generic/acpi/halpnpdd.c index 81bed5539c9..ca85188bcaf 100644 --- a/hal/halx86/generic/acpi/halpnpdd.c +++ b/hal/halx86/generic/acpi/halpnpdd.c @@ -47,57 +47,9 @@ typedef struct _PDO_EXTENSION /* GLOBALS ********************************************************************/ PDRIVER_OBJECT HalpDriverObject; -BOOLEAN HalDisableFirmwareMapper = TRUE; -PWCHAR HalHardwareIdString = L"acpipic_up"; /* PRIVATE FUNCTIONS **********************************************************/ -NTSTATUS -NTAPI -HalpMarkAcpiHal(VOID) -{ - NTSTATUS Status; - UNICODE_STRING KeyString; - HANDLE KeyHandle; - HANDLE Handle; - - /* Open the control set key */ - RtlInitUnicodeString(&KeyString, - L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"); - Status = HalpOpenRegistryKey(&Handle, 0, &KeyString, KEY_ALL_ACCESS, FALSE); - if (NT_SUCCESS(Status)) - { - /* Open the PNP key */ - RtlInitUnicodeString(&KeyString, L"Control\\Pnp"); - Status = HalpOpenRegistryKey(&KeyHandle, - Handle, - &KeyString, - KEY_ALL_ACCESS, - TRUE); - /* Close root key */ - ZwClose(Handle); - - /* Check if PNP BIOS key exists */ - if (NT_SUCCESS(Status)) - { - /* Set the disable value to false -- we need the mapper */ - RtlInitUnicodeString(&KeyString, L"DisableFirmwareMapper"); - Status = ZwSetValueKey(KeyHandle, - &KeyString, - 0, - REG_DWORD, - &HalDisableFirmwareMapper, - sizeof(HalDisableFirmwareMapper)); - - /* Close subkey */ - ZwClose(KeyHandle); - } - } - - /* Return status */ - return Status; -} - NTSTATUS NTAPI HalpAddDevice(IN PDRIVER_OBJECT DriverObject, @@ -379,9 +331,95 @@ NTAPI HalpQueryResources(IN PDEVICE_OBJECT DeviceObject, OUT PCM_RESOURCE_LIST *Resources) { - UNIMPLEMENTED; - while (TRUE); - return STATUS_NO_SUCH_DEVICE; + PPDO_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + NTSTATUS Status; + PCM_RESOURCE_LIST ResourceList; + PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; + PIO_RESOURCE_DESCRIPTOR Descriptor; + PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDesc; + ULONG i; + PAGED_CODE(); + + /* Only the ACPI PDO has requirements */ + if (DeviceExtension->PdoType == AcpiPdo) + { + /* Query ACPI requirements */ + Status = HalpQueryAcpiResourceRequirements(&RequirementsList); + ASSERT(RequirementsList->AlternativeLists == 1); + if (!NT_SUCCESS(Status)) return Status; + + /* Allocate the resourcel ist */ + ResourceList = ExAllocatePoolWithTag(PagedPool, + sizeof(CM_RESOURCE_LIST), + ' laH'); + if (!ResourceList ) + { + /* Fail, no memory */ + Status = STATUS_INSUFFICIENT_RESOURCES; + ExFreePoolWithTag(RequirementsList, 0); + return Status; + } + + /* Initialize it */ + RtlZeroMemory(ResourceList, sizeof(CM_RESOURCE_LIST)); + ResourceList->Count = 1; + + /* Setup the list fields */ + ResourceList->List[0].BusNumber = -1; + ResourceList->List[0].InterfaceType = PNPBus; + ResourceList->List[0].PartialResourceList.Version = 1; + ResourceList->List[0].PartialResourceList.Revision = 1; + ResourceList->List[0].PartialResourceList.Count = 1; + + /* Setup the first descriptor */ + PartialDesc = ResourceList->List[0].PartialResourceList.PartialDescriptors; + PartialDesc->Type = CmResourceTypeInterrupt; + + /* Find the requirement descriptor for the SCI */ + for (i = 0; i < RequirementsList->List[0].Count; i++) + { + /* Get this descriptor */ + Descriptor = &RequirementsList->List[0].Descriptors[i]; + if (Descriptor->Type == CmResourceTypeInterrupt) break; + Descriptor = NULL; + } + + /* Make sure we found the descriptor */ + if (Descriptor) + { + /* Copy requirements descriptor into resource descriptor */ + PartialDesc->ShareDisposition = Descriptor->ShareDisposition; + PartialDesc->Flags = Descriptor->Flags; + ASSERT(Descriptor->u.Interrupt.MinimumVector == + Descriptor->u.Interrupt.MaximumVector); + PartialDesc->u.Interrupt.Vector = Descriptor->u.Interrupt.MinimumVector; + PartialDesc->u.Interrupt.Level = Descriptor->u.Interrupt.MinimumVector; + PartialDesc->u.Interrupt.Affinity = 0xFFFFFFFF; + + /* Return resources and success */ + *Resources = ResourceList; + ExFreePoolWithTag(RequirementsList, 0); + return STATUS_SUCCESS; + } + + /* Free memory and fail */ + ExFreePoolWithTag(RequirementsList, 0); + ExFreePoolWithTag(ResourceList, 0); + Status = STATUS_NOT_FOUND; + } + else if (DeviceExtension->PdoType == WdPdo) + { + /* Watchdog doesn't */ + return STATUS_NOT_SUPPORTED; + } + else + { + /* This shouldn't happen */ + return STATUS_UNSUCCESSFUL; + } + + /* Return the status */ + return Status; } NTSTATUS @@ -389,9 +427,29 @@ NTAPI HalpQueryResourceRequirements(IN PDEVICE_OBJECT DeviceObject, OUT PIO_RESOURCE_REQUIREMENTS_LIST *Requirements) { - UNIMPLEMENTED; - while (TRUE); - return STATUS_NO_SUCH_DEVICE; + PPDO_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + NTSTATUS Status; + PAGED_CODE(); + + /* Only the ACPI PDO has requirements */ + if (DeviceExtension->PdoType == AcpiPdo) + { + /* Query ACPI requirements */ + Status = HalpQueryAcpiResourceRequirements(Requirements); + } + else if (DeviceExtension->PdoType == WdPdo) + { + /* Watchdog doesn't */ + return STATUS_NOT_SUPPORTED; + } + else + { + /* This shouldn't happen */ + return STATUS_UNSUCCESSFUL; + } + + /* Return the status */ + return Status; } NTSTATUS diff --git a/hal/halx86/generic/bus/pcibus.c b/hal/halx86/generic/bus/pcibus.c index 50f1add18d8..2440cd4182b 100644 --- a/hal/halx86/generic/bus/pcibus.c +++ b/hal/halx86/generic/bus/pcibus.c @@ -14,6 +14,8 @@ /* GLOBALS *******************************************************************/ +PCI_TYPE1_CFG_CYCLE_BITS HalpPciDebuggingDevice[2] = {{{{0}}}}; + BOOLEAN HalpPCIConfigInitialized; ULONG HalpMinPciBus, HalpMaxPciBus; KSPIN_LOCK HalpPCIConfigLock; @@ -521,6 +523,34 @@ HalpReleasePciDeviceForDebugging(IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice) return STATUS_NOT_IMPLEMENTED; } +VOID +NTAPI +HalpRegisterPciDebuggingDeviceInfo(VOID) +{ + BOOLEAN Found = FALSE; + ULONG i; + PAGED_CODE(); + + /* Loop PCI debugging devices */ + for (i = 0; i < 2; i++) + { + /* Reserved bit is set if we found one */ + if (HalpPciDebuggingDevice[i].u.bits.Reserved1) + { + Found = TRUE; + break; + } + } + + /* Bail out if there aren't any */ + if (!Found) return; + + /* FIXME: TODO */ + DPRINT1("You have implemented the KD routines for searching PCI debugger" + "devices, but you have forgotten to implement this routine\n"); + while (TRUE); +} + static ULONG NTAPI PciSize(ULONG Base, ULONG Mask) { @@ -1026,9 +1056,3 @@ HalpInitializePciStubs(VOID) HalpPCIConfigInitialized = TRUE; } -VOID -NTAPI -HalpInitializePciBus(VOID) -{ - /* FIXME: Initialize NMI Crash Flag */ -} diff --git a/hal/halx86/generic/legacy/halpcat.c b/hal/halx86/generic/legacy/halpcat.c index bbabb9c7aa2..ea16403676e 100644 --- a/hal/halx86/generic/legacy/halpcat.c +++ b/hal/halx86/generic/legacy/halpcat.c @@ -14,6 +14,11 @@ /* GLOBALS ********************************************************************/ +/* This determines the HAL type */ +BOOLEAN HalDisableFirmwareMapper = FALSE; +PWCHAR HalHardwareIdString = L"e_isa_up"; +PWCHAR HalName = L"PC Compatible Eisa/Isa HAL"; + /* PRIVATE FUNCTIONS **********************************************************/ NTSTATUS @@ -24,4 +29,94 @@ HalpSetupAcpiPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock) return STATUS_NO_SUCH_DEVICE; } +VOID +NTAPI +HalpInitializePciBus(VOID) +{ + /* FIXME: Should do legacy PCI bus detection */ + + /* FIXME: Should detect chipset hacks */ + + /* FIXME: Should detect broken PCI hardware and apply hacks */ + + /* FIXME: Should build resource ranges */ +} + +VOID +NTAPI +HalpBuildAddressMap(VOID) +{ + /* FIXME: Inherit ROM blocks from the registry */ + //HalpInheritROMBlocks(); + + /* FIXME: Add the ROM blocks to our ranges */ + //HalpAddROMRanges(); +} + +BOOLEAN +NTAPI +HalpGetDebugPortTable(VOID) +{ + /* No ACPI */ + return FALSE; +} + +ULONG +NTAPI +HalpIs16BitPortDecodeSupported(VOID) +{ + /* Only EISA systems support this */ + return (HalpBusType == MACHINE_TYPE_EISA) ? CM_RESOURCE_PORT_16_BIT_DECODE : 0; +} + +/* + * @implemented + */ +VOID +NTAPI +HalReportResourceUsage(VOID) +{ + INTERFACE_TYPE InterfaceType; + UNICODE_STRING HalString; + + /* FIXME: Initialize MCA bus */ + + /* Initialize PCI bus. */ + HalpInitializePciBus(); + + /* Initialize the stubs */ + HalpInitializePciStubs(); + + /* What kind of bus is this? */ + switch (HalpBusType) + { + /* ISA Machine */ + case MACHINE_TYPE_ISA: + InterfaceType = Isa; + break; + + /* EISA Machine */ + case MACHINE_TYPE_EISA: + InterfaceType = Eisa; + break; + + /* MCA Machine */ + case MACHINE_TYPE_MCA: + InterfaceType = MicroChannel; + break; + + /* Unknown */ + default: + InterfaceType = Internal; + break; + } + + /* Build HAL usage */ + RtlInitUnicodeString(&HalString, HalName); + HalpReportResourceUsage(&HalString, InterfaceType); + + /* Setup PCI debugging and Hibernation */ + HalpRegisterPciDebuggingDeviceInfo(); +} + /* EOF */ diff --git a/hal/halx86/generic/misc.c b/hal/halx86/generic/misc.c index 3e4d0c9a55f..f138e5f9871 100644 --- a/hal/halx86/generic/misc.c +++ b/hal/halx86/generic/misc.c @@ -16,9 +16,88 @@ BOOLEAN HalpNMIInProgress; +UCHAR HalpSerialLen; +CHAR HalpSerialNumber[31]; + /* PRIVATE FUNCTIONS **********************************************************/ #ifndef _MINIHAL_ +VOID +NTAPI +HalpReportSerialNumber(VOID) +{ + NTSTATUS Status; + UNICODE_STRING KeyString; + HANDLE Handle; + + /* Make sure there is a serial number */ + if (!HalpSerialLen) return; + + /* Open the system key */ + RtlInitUnicodeString(&KeyString, L"\\Registry\\Machine\\Hardware\\Description\\System"); + Status = HalpOpenRegistryKey(&Handle, 0, &KeyString, KEY_ALL_ACCESS, FALSE); + if (NT_SUCCESS(Status)) + { + /* Add the serial number */ + RtlInitUnicodeString(&KeyString, L"Serial Number"); + ZwSetValueKey(Handle, + &KeyString, + 0, + REG_BINARY, + HalpSerialNumber, + HalpSerialLen); + + /* Close the handle */ + ZwClose(Handle); + } +} + +NTSTATUS +NTAPI +HalpMarkAcpiHal(VOID) +{ + NTSTATUS Status; + UNICODE_STRING KeyString; + HANDLE KeyHandle; + HANDLE Handle; + + /* Open the control set key */ + RtlInitUnicodeString(&KeyString, + L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET"); + Status = HalpOpenRegistryKey(&Handle, 0, &KeyString, KEY_ALL_ACCESS, FALSE); + if (NT_SUCCESS(Status)) + { + /* Open the PNP key */ + RtlInitUnicodeString(&KeyString, L"Control\\Pnp"); + Status = HalpOpenRegistryKey(&KeyHandle, + Handle, + &KeyString, + KEY_ALL_ACCESS, + TRUE); + /* Close root key */ + ZwClose(Handle); + + /* Check if PNP BIOS key exists */ + if (NT_SUCCESS(Status)) + { + /* Set the disable value to false -- we need the mapper */ + RtlInitUnicodeString(&KeyString, L"DisableFirmwareMapper"); + Status = ZwSetValueKey(KeyHandle, + &KeyString, + 0, + REG_DWORD, + &HalDisableFirmwareMapper, + sizeof(HalDisableFirmwareMapper)); + + /* Close subkey */ + ZwClose(KeyHandle); + } + } + + /* Return status */ + return Status; +} + NTSTATUS NTAPI HalpOpenRegistryKey(IN PHANDLE KeyHandle, diff --git a/hal/halx86/generic/usage.c b/hal/halx86/generic/usage.c index d35a3e3a964..02c86e2a046 100644 --- a/hal/halx86/generic/usage.c +++ b/hal/halx86/generic/usage.c @@ -14,25 +14,45 @@ /* GLOBALS ********************************************************************/ +BOOLEAN HalpGetInfoFromACPI; +BOOLEAN HalpNMIDumpFlag; PUCHAR KdComPortInUse; PADDRESS_USAGE HalpAddressUsageList; IDTUsageFlags HalpIDTUsageFlags[MAXIMUM_IDTVECTOR]; IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR]; +USHORT HalpComPortIrqMapping[5][2] = +{ + {0x3F8, 4}, + {0x2F8, 3}, + {0x3E8, 4}, + {0x2E8, 3}, + {0, 0} +}; + +ADDRESS_USAGE HalpComIoSpace = +{ + NULL, CmResourceTypePort, IDT_INTERNAL, + { + {0x2F8, 0x8}, /* COM 1 */ + {0,0}, + } +}; + ADDRESS_USAGE HalpDefaultIoSpace = { NULL, CmResourceTypePort, IDT_INTERNAL, { - {0x2000, 0xC000}, /* PIC?? */ + {0x2000, 0xC000}, /* Everything */ {0xC000, 0x1000}, /* DMA 2 */ {0x8000, 0x1000}, /* DMA 1 */ {0x2000, 0x200}, /* PIC 1 */ {0xA000, 0x200}, /* PIC 2 */ {0x4000, 0x400}, /* PIT 1 */ {0x4800, 0x400}, /* PIT 2 */ - {0x9200, 0x100}, /* ????? */ + {0x9200, 0x100}, /* System Control Port A */ {0x7000, 0x200}, /* CMOS */ - {0xF000, 0x1000}, /* ????? */ + {0xF000, 0x1000}, /* x87 Coprocessor */ {0xCF800, 0x800}, /* PCI 0 */ {0,0}, } @@ -40,13 +60,429 @@ ADDRESS_USAGE HalpDefaultIoSpace = /* FUNCTIONS ******************************************************************/ +#ifndef _MINIHAL_ +VOID +NTAPI +HalpGetResourceSortValue(IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor, + OUT PULONG Scale, + OUT PLARGE_INTEGER Value) +{ + /* Sorting depends on resource type */ + switch (Descriptor->Type) + { + case CmResourceTypeInterrupt: + + /* Interrupt goes by level */ + *Scale = 0; + *Value = RtlConvertUlongToLargeInteger(Descriptor->u.Interrupt.Level); + break; + + case CmResourceTypePort: + + /* Port goes by port address */ + *Scale = 1; + *Value = Descriptor->u.Port.Start; + break; + + case CmResourceTypeMemory: + + /* Memory goes by base address */ + *Scale = 2; + *Value = Descriptor->u.Memory.Start; + break; + + default: + + /* Anything else */ + *Scale = 4; + *Value = RtlConvertUlongToLargeInteger(0); + break; + } +} + +VOID +NTAPI +HalpBuildPartialFromIdt(IN ULONG Entry, + IN PCM_PARTIAL_RESOURCE_DESCRIPTOR RawDescriptor, + IN PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedDescriptor) +{ + /* Exclusive interrupt entry */ + RawDescriptor->Type = CmResourceTypeInterrupt; + RawDescriptor->ShareDisposition = CmResourceShareDriverExclusive; + + /* Check the interrupt type */ + if (HalpIDTUsageFlags[Entry].Flags & IDT_LATCHED) + { + /* Latched */ + RawDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED; + } + else + { + /* Level */ + RawDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; + } + + /* Get vector and level from IDT usage */ + RawDescriptor->u.Interrupt.Vector = HalpIDTUsage[Entry].BusReleativeVector; + RawDescriptor->u.Interrupt.Level = HalpIDTUsage[Entry].BusReleativeVector; + + /* Affinity is all the CPUs */ + RawDescriptor->u.Interrupt.Affinity = HalpActiveProcessors; + + /* The translated copy is identical */ + RtlCopyMemory(TranslatedDescriptor, RawDescriptor, sizeof(TranslatedDescriptor)); + + /* But the vector and IRQL must be set correctly */ + TranslatedDescriptor->u.Interrupt.Vector = Entry; + TranslatedDescriptor->u.Interrupt.Level = HalpIDTUsage[Entry].Irql; +} + +VOID +NTAPI +HalpBuildPartialFromAddress(IN INTERFACE_TYPE Interface, + IN PADDRESS_USAGE CurrentAddress, + IN ULONG Element, + IN PCM_PARTIAL_RESOURCE_DESCRIPTOR RawDescriptor, + IN PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedDescriptor) +{ + ULONG AddressSpace; + + /* Set the type and make it exclusive */ + RawDescriptor->Type = CurrentAddress->Type; + RawDescriptor->ShareDisposition = CmResourceShareDriverExclusive; + + /* Check what this is */ + if (RawDescriptor->Type == CmResourceTypePort) + { + /* Write out port data */ + AddressSpace = 1; + RawDescriptor->Flags = CM_RESOURCE_PORT_IO; + RawDescriptor->u.Port.Start.HighPart = 0; + RawDescriptor->u.Port.Start.LowPart = CurrentAddress->Element[Element].Start; + RawDescriptor->u.Port.Length = CurrentAddress->Element[Element].Length; + + /* Determine if 16-bit port addresses are allowed */ + RawDescriptor->Flags |= HalpIs16BitPortDecodeSupported(); + } + else + { + /* Write out memory data */ + AddressSpace = 0; + RawDescriptor->Flags = (CurrentAddress->Flags & IDT_READ_ONLY) ? + CM_RESOURCE_MEMORY_READ_ONLY : + CM_RESOURCE_MEMORY_READ_WRITE; + RawDescriptor->u.Memory.Start.HighPart = 0; + RawDescriptor->u.Memory.Start.LowPart = CurrentAddress->Element[Element].Start; + RawDescriptor->u.Memory.Length = CurrentAddress->Element[Element].Length; + } + + /* Make an identical copy to begin with */ + RtlCopyMemory(TranslatedDescriptor, RawDescriptor, sizeof(TranslatedDescriptor)); + + /* Check what this is */ + if (RawDescriptor->Type == CmResourceTypePort) + { + /* Translate the port */ + HalTranslateBusAddress(Interface, + 0, + RawDescriptor->u.Port.Start, + &AddressSpace, + &TranslatedDescriptor->u.Port.Start); + + /* If it turns out this is memory once translated, flag it */ + if (AddressSpace == 0) TranslatedDescriptor->Flags = CM_RESOURCE_PORT_MEMORY; + + } + else + { + /* Translate the memory */ + HalTranslateBusAddress(Interface, + 0, + RawDescriptor->u.Memory.Start, + &AddressSpace, + &TranslatedDescriptor->u.Memory.Start); + } +} + VOID NTAPI HalpReportResourceUsage(IN PUNICODE_STRING HalName, IN INTERFACE_TYPE InterfaceType) { - DbgPrint("%wZ has been initialized\n", HalName); + PCM_RESOURCE_LIST RawList, TranslatedList; + PCM_FULL_RESOURCE_DESCRIPTOR RawFull, TranslatedFull; + PCM_PARTIAL_RESOURCE_DESCRIPTOR CurrentRaw, CurrentTranslated, SortedRaw, SortedTranslated; + CM_PARTIAL_RESOURCE_DESCRIPTOR RawPartial, TranslatedPartial; + PCM_PARTIAL_RESOURCE_LIST RawPartialList = NULL, TranslatedPartialList = NULL; + INTERFACE_TYPE Interface; + ULONG i, j, k, ListSize, Count, Port, Element, CurrentScale, SortScale, ReportType, FlagMatch; + ADDRESS_USAGE *CurrentAddress; + LARGE_INTEGER CurrentSortValue, SortValue; + DbgPrint("%wZ Detected\n", HalName); + + /* Check if KD is using a COM port */ + if (KdComPortInUse) + { + /* Enter it into the I/O space */ + HalpComIoSpace.Element[0].Start = (ULONG_PTR)KdComPortInUse; + HalpComIoSpace.Next = HalpAddressUsageList; + HalpAddressUsageList = &HalpComIoSpace; + + /* Use the debug port table if we have one */ + HalpGetInfoFromACPI = HalpGetDebugPortTable(); + + /* Check if we're using ACPI */ + if (!HalpGetInfoFromACPI) + { + /* No, so use our local table */ + Port = HalpComPortIrqMapping[0][0]; + for (i = 0; Port; i++) + { + /* Is this the port we want? */ + if (Port == (ULONG_PTR)KdComPortInUse) + { + /* Register it */ + HalpRegisterVector(IDT_DEVICE | IDT_LATCHED, + HalpComPortIrqMapping[i][1], + HalpComPortIrqMapping[i][1] + + PRIMARY_VECTOR_BASE, + HIGH_LEVEL); + } + + /* Next port */ + Port = HalpComPortIrqMapping[i][0]; + } + } + } + + /* On non-ACPI systems, we need to build an address map */ + HalpBuildAddressMap(); + + /* Allocate the master raw and translated lists */ + RawList = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE * 2, ' laH'); + TranslatedList = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE * 2, ' laH'); + if (!(RawList) || !(TranslatedList)) + { + /* Bugcheck the system */ + KeBugCheckEx(HAL_MEMORY_ALLOCATION, + 4 * PAGE_SIZE, + 1, + (ULONG_PTR)__FILE__, + __LINE__); + } + + /* Zero out the lists */ + RtlZeroMemory(RawList, PAGE_SIZE * 2); + RtlZeroMemory(TranslatedList, PAGE_SIZE * 2); + + /* Set the interface type to begin with */ + RawList->List[0].InterfaceType = InterfaceTypeUndefined; + + /* Loop all IDT entries that are not IRQs */ + for (i = 0; i < PRIMARY_VECTOR_BASE; i++) + { + /* Check if the IDT isn't owned */ + if (!(HalpIDTUsageFlags[i].Flags & IDT_REGISTERED)) + { + /* Then register it for internal usage */ + HalpIDTUsageFlags[i].Flags = IDT_INTERNAL; + HalpIDTUsage[i].BusReleativeVector = i; + } + } + + /* Our full raw descriptors start here */ + RawFull = RawList->List; + + /* Keep track of the current partial raw and translated descriptors */ + CurrentRaw = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)RawList->List; + CurrentTranslated = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)TranslatedList->List; + + /* Do two passes */ + for (ReportType = 0; ReportType < 2; ReportType++) + { + /* Pass 0 is for device usage */ + if (ReportType == 0) + { + FlagMatch = IDT_DEVICE & ~IDT_REGISTERED; + Interface = InterfaceType; + } + else + { + /* Past 1 is for internal HAL usage */ + FlagMatch = IDT_INTERNAL & ~IDT_REGISTERED; + Interface = Internal; + } + + /* Reset loop variables */ + i = Element = 0; + + /* Start looping our address uage list and interrupts */ + CurrentAddress = HalpAddressUsageList; + while (TRUE) + { + /* Check for valid vector number */ + if (i <= MAXIMUM_IDTVECTOR) + { + /* Check if this entry should be parsed */ + if ((HalpIDTUsageFlags[i].Flags & FlagMatch)) + { + /* Parse it */ + HalpBuildPartialFromIdt(i, &RawPartial, &TranslatedPartial); + i++; + } + else + { + /* Skip this entry */ + i++; + continue; + } + } + else + { + /* This is an address instead */ + if (!CurrentAddress) break; + + /* Check if the address should be reported */ + if (!(CurrentAddress->Flags & FlagMatch) || + !(CurrentAddress->Element[Element].Length)) + { + /* Nope, skip it */ + Element = 0; + CurrentAddress = CurrentAddress->Next; + continue; + } + + /* Otherwise, parse the entry */ + HalpBuildPartialFromAddress(Interface, + CurrentAddress, + Element, + &RawPartial, + &TranslatedPartial); + Element++; + } + + /* Check for interface change */ + if (RawFull->InterfaceType != Interface) + { + /* We need to add another full descriptor */ + RawList->Count++; + TranslatedList->Count++; + + /* The full descriptor follows wherever we were */ + RawFull = (PCM_FULL_RESOURCE_DESCRIPTOR)CurrentRaw; + TranslatedFull = (PCM_FULL_RESOURCE_DESCRIPTOR)CurrentTranslated; + + /* And it is of this new interface type */ + RawFull->InterfaceType = Interface; + TranslatedFull->InterfaceType = Interface; + + /* And its partial descriptors begin here */ + RawPartialList = &RawFull->PartialResourceList; + TranslatedPartialList = &TranslatedFull->PartialResourceList; + + /* And our next full descriptor should follow here */ + CurrentRaw = RawFull->PartialResourceList.PartialDescriptors; + CurrentTranslated = TranslatedFull->PartialResourceList.PartialDescriptors; + } + + /* We have written a new partial descriptor */ + RawPartialList->Count++; + TranslatedPartialList->Count++; + + /* Copy our local descriptors into the actual list */ + RtlCopyMemory(CurrentRaw, &RawPartial, sizeof(RawPartial)); + RtlCopyMemory(CurrentTranslated, &TranslatedPartial, sizeof(TranslatedPartial)); + + /* Move to the next partial descriptor */ + CurrentRaw++; + CurrentTranslated++; + } + } + + /* Get the final list of the size for the kernel call later */ + ListSize = (ULONG_PTR)CurrentRaw - (ULONG_PTR)RawList; + + /* Now reset back to the first full descriptor */ + RawFull = RawList->List; + TranslatedFull = TranslatedList->List; + + /* And loop all the full descriptors */ + for (i = 0; i < RawList->Count; i++) + { + /* Get the first partial descriptor in this list */ + CurrentRaw = RawFull->PartialResourceList.PartialDescriptors; + CurrentTranslated = TranslatedFull->PartialResourceList.PartialDescriptors; + + /* Get the count of partials in this list */ + Count = RawFull->PartialResourceList.Count; + + /* Loop all the partials in this list */ + for (j = 0; j < Count; j++) + { + /* Get the sort value at this point */ + HalpGetResourceSortValue(CurrentRaw, &CurrentScale, &CurrentSortValue); + + /* Save the current sort pointer */ + SortedRaw = CurrentRaw; + SortedTranslated = CurrentTranslated; + + /* Loop all descriptors starting from this one */ + for (k = j; k < Count; k++) + { + /* Get the sort value at the sort point */ + HalpGetResourceSortValue(SortedRaw, &SortScale, &SortValue); + + /* Check if a swap needs to occur */ + if ((SortScale < CurrentScale) || + ((SortScale == CurrentScale) && + (SortValue.QuadPart <= CurrentSortValue.QuadPart))) + { + /* Swap raw partial with the sort location partial */ + RtlCopyMemory(&RawPartial, CurrentRaw, sizeof(RawPartial)); + RtlCopyMemory(CurrentRaw, SortedRaw, sizeof(RawPartial)); + RtlCopyMemory(SortedRaw, &RawPartial, sizeof(RawPartial)); + + /* Swap translated partial in the same way */ + RtlCopyMemory(&TranslatedPartial, CurrentTranslated, sizeof(TranslatedPartial)); + RtlCopyMemory(CurrentTranslated, SortedTranslated, sizeof(TranslatedPartial)); + RtlCopyMemory(SortedTranslated, &TranslatedPartial, sizeof(TranslatedPartial)); + + /* Update the sort value at this point */ + HalpGetResourceSortValue(CurrentRaw, &CurrentScale, &CurrentSortValue); + } + + /* The sort location has been updated */ + SortedRaw++; + SortedTranslated++; + } + + /* Move to the next partial */ + CurrentRaw++; + CurrentTranslated++; + } + + /* Move to the next full descriptor */ + RawFull = (PCM_FULL_RESOURCE_DESCRIPTOR)CurrentRaw; + TranslatedFull = (PCM_FULL_RESOURCE_DESCRIPTOR)CurrentTranslated; + } + + /* Mark this is an ACPI system, if it is */ + HalpMarkAcpiHal(); + + /* Tell the kernel about all this */ + IoReportHalResourceUsage(HalName, + RawList, + TranslatedList, + ListSize); + + /* Free our lists */ + ExFreePool(RawList); + ExFreePool(TranslatedList); + + /* Get the machine's serial number */ + HalpReportSerialNumber(); } +#endif VOID NTAPI @@ -88,55 +524,56 @@ HalpEnableInterruptHandler(IN UCHAR Flags, /* Enable the interrupt */ HalEnableSystemInterrupt(SystemVector, Irql, Mode); } -#endif -/* - * @unimplemented - */ VOID NTAPI -HalReportResourceUsage(VOID) +HalpGetNMICrashFlag(VOID) { - INTERFACE_TYPE InterfaceType; - UNICODE_STRING HalString; + UNICODE_STRING ValueName; + UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\CrashControl"); + OBJECT_ATTRIBUTES ObjectAttributes; + ULONG ResultLength; + HANDLE Handle; + NTSTATUS Status; + KEY_VALUE_PARTIAL_INFORMATION KeyValueInformation; - /* FIXME: Initialize DMA 64-bit support */ + /* Set default */ + HalpNMIDumpFlag = 0; - /* FIXME: Initialize MCA bus */ - - /* Initialize PCI bus. */ - HalpInitializePciBus(); + /* Initialize attributes */ + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); - /* Initialize the stubs */ - HalpInitializePciStubs(); - - /* What kind of bus is this? */ - switch (HalpBusType) + /* Open crash key */ + Status = ZwOpenKey(&Handle, KEY_READ, &ObjectAttributes); + if (NT_SUCCESS(Status)) { - /* ISA Machine */ - case MACHINE_TYPE_ISA: - InterfaceType = Isa; - break; - - /* EISA Machine */ - case MACHINE_TYPE_EISA: - InterfaceType = Eisa; - break; - - /* MCA Machine */ - case MACHINE_TYPE_MCA: - InterfaceType = MicroChannel; - break; - - /* Unknown */ - default: - InterfaceType = Internal; - break; + /* Query key value */ + RtlInitUnicodeString(&ValueName, L"NMICrashDump"); + Status = ZwQueryValueKey(Handle, + &ValueName, + KeyValuePartialInformation, + &KeyValueInformation, + sizeof(KeyValueInformation), + &ResultLength); + if (NT_SUCCESS(Status)) + { + /* Check for valid data */ + if (ResultLength == sizeof(KEY_VALUE_PARTIAL_INFORMATION)) + { + /* Read the flag */ + HalpNMIDumpFlag = KeyValueInformation.Data[0]; + } + } + + /* We're done */ + ZwClose(Handle); } - - /* Build HAL usage */ - RtlInitUnicodeString(&HalString, L"PC Compatible Eisa/Isa HAL"); - HalpReportResourceUsage(&HalString, InterfaceType); - - /* FIXME: Setup PCI debugging and Hibernation */ } +#endif + +/* EOF */ + diff --git a/hal/halx86/hal.rbuild b/hal/halx86/hal.rbuild index b551cc3308c..17ffea9c4a0 100644 --- a/hal/halx86/hal.rbuild +++ b/hal/halx86/hal.rbuild @@ -8,7 +8,8 @@ include - hal_generic_legacy + hal_generic + hal_generic_pcat hal_generic_up ntoskrnl libcntpr diff --git a/hal/halx86/hal_generic.rbuild b/hal/halx86/hal_generic.rbuild index dccd1615c62..166bb930404 100644 --- a/hal/halx86/hal_generic.rbuild +++ b/hal/halx86/hal_generic.rbuild @@ -1,65 +1,12 @@ - + include include - - halpcat.c - - - bushndlr.c - isabus.c - halbus.c - pcibus.c - pcidata.c - sysbus.c - - beep.c - bios.c - cmos.c - display.c - dma.c - drive.c - halinit.c - misc.c - profil.c - reboot.c - sysinfo.c - timer.c - usage.c - - - portio.c - systimer.S - trap.S - - - - - x86bios.c - systimer.S - - - - - hal.h - - - - - include - include - - - - - halacpi.c - halpnpdd.c - bushndlr.c isabus.c diff --git a/hal/halx86/hal_generic_acpi.rbuild b/hal/halx86/hal_generic_acpi.rbuild new file mode 100644 index 00000000000..3784394b642 --- /dev/null +++ b/hal/halx86/hal_generic_acpi.rbuild @@ -0,0 +1,16 @@ + + + + + include + include + + + + + halacpi.c + halpnpdd.c + + + + diff --git a/hal/halx86/hal_generic_pcat.rbuild b/hal/halx86/hal_generic_pcat.rbuild new file mode 100644 index 00000000000..e00ed5bdb4e --- /dev/null +++ b/hal/halx86/hal_generic_pcat.rbuild @@ -0,0 +1,15 @@ + + + + + include + include + + + + + halpcat.c + + + + diff --git a/hal/halx86/halacpi.rbuild b/hal/halx86/halacpi.rbuild index 7d22a84b79f..d380cf6889e 100644 --- a/hal/halx86/halacpi.rbuild +++ b/hal/halx86/halacpi.rbuild @@ -8,6 +8,7 @@ include + hal_generic hal_generic_acpi hal_generic_up ntoskrnl diff --git a/hal/halx86/halamd64.rbuild b/hal/halx86/halamd64.rbuild index 6b52fdef9e5..0b60f7615dc 100644 --- a/hal/halx86/halamd64.rbuild +++ b/hal/halx86/halamd64.rbuild @@ -10,6 +10,7 @@ + hal_generic hal_generic_acpi hal_generic_up ntoskrnl diff --git a/hal/halx86/halmps.rbuild b/hal/halx86/halmps.rbuild index 2570cb84620..d76c49f39da 100644 --- a/hal/halx86/halmps.rbuild +++ b/hal/halx86/halmps.rbuild @@ -9,7 +9,8 @@ - hal_generic_legacy + hal_generic + hal_generic_pcat hal_generic_mp ntoskrnl libcntpr diff --git a/hal/halx86/halxbox.rbuild b/hal/halx86/halxbox.rbuild index 54423ab9075..ad13545b405 100644 --- a/hal/halx86/halxbox.rbuild +++ b/hal/halx86/halxbox.rbuild @@ -8,7 +8,8 @@ - hal_generic_legacy + hal_generic + hal_generic_pcat hal_generic_up ntoskrnl libcntpr diff --git a/hal/halx86/include/bus.h b/hal/halx86/include/bus.h index 3e07190f470..03840227411 100644 --- a/hal/halx86/include/bus.h +++ b/hal/halx86/include/bus.h @@ -158,6 +158,38 @@ typedef struct _PCI_REGISTRY_INFO_INTERNAL PCI_CARD_DESCRIPTOR CardList[ANYSIZE_ARRAY]; } PCI_REGISTRY_INFO_INTERNAL, *PPCI_REGISTRY_INFO_INTERNAL; +typedef struct _PCI_TYPE0_CFG_CYCLE_BITS +{ + union + { + struct + { + ULONG Reserved1:2; + ULONG RegisterNumber:6; + ULONG FunctionNumber:3; + ULONG Reserved2:21; + } bits; + ULONG AsULONG; + } u; +} PCI_TYPE0_CFG_CYCLE_BITS, *PPCI_TYPE0_CFG_CYCLE_BITS; + +typedef struct _PCI_TYPE1_CFG_CYCLE_BITS +{ + union + { + struct + { + ULONG Reserved1:2; + ULONG RegisterNumber:6; + ULONG FunctionNumber:3; + ULONG DeviceNumber:5; + ULONG BusNumber:8; + ULONG Reserved2:8; + } bits; + ULONG AsULONG; + } u; +} PCI_TYPE1_CFG_CYCLE_BITS, *PPCI_TYPE1_CFG_CYCLE_BITS; + typedef struct _ARRAY { ULONG ArraySize; @@ -359,6 +391,12 @@ HalpFindBusAddressTranslation( IN BOOLEAN NextBus ); +VOID +NTAPI +HalpRegisterPciDebuggingDeviceInfo( + VOID +); + extern ULONG HalpBusType; extern BOOLEAN HalpPCIConfigInitialized; extern BUS_HANDLER HalpFakePciBusHandler; diff --git a/hal/halx86/include/halp.h b/hal/halx86/include/halp.h index 44b81a08791..6edb85570d7 100644 --- a/hal/halx86/include/halp.h +++ b/hal/halx86/include/halp.h @@ -49,6 +49,7 @@ DECLSPEC_NORETURN /* Usage flags */ #define IDT_REGISTERED 0x01 #define IDT_LATCHED 0x02 +#define IDT_READ_ONLY 0x04 #define IDT_INTERNAL 0x11 #define IDT_DEVICE 0x21 @@ -707,6 +708,55 @@ HalpOpenRegistryKey( IN BOOLEAN Create ); +VOID +NTAPI +HalpGetNMICrashFlag( + VOID +); + +BOOLEAN +NTAPI +HalpGetDebugPortTable( + VOID +); + +VOID +NTAPI +HalpReportSerialNumber( + VOID +); + +NTSTATUS +NTAPI +HalpMarkAcpiHal( + VOID +); + +VOID +NTAPI +HalpBuildAddressMap( + VOID +); + +VOID +NTAPI +HalpReportResourceUsage( + IN PUNICODE_STRING HalName, + IN INTERFACE_TYPE InterfaceType +); + +ULONG +NTAPI +HalpIs16BitPortDecodeSupported( + VOID +); + +NTSTATUS +NTAPI +HalpQueryAcpiResourceRequirements( + OUT PIO_RESOURCE_REQUIREMENTS_LIST *Requirements +); + VOID FASTCALL KeUpdateSystemTime( @@ -735,3 +785,9 @@ extern KSPIN_LOCK HalpSystemHardwareLock; extern PADDRESS_USAGE HalpAddressUsageList; extern LARGE_INTEGER HalpPerfCounter; + +extern KAFFINITY HalpActiveProcessors; + +extern BOOLEAN HalDisableFirmwareMapper; +extern PWCHAR HalHardwareIdString; +extern PWCHAR HalName; diff --git a/hal/halx86/mp/processor_mp.c b/hal/halx86/mp/processor_mp.c index 126bccbcbf6..069a96bb269 100644 --- a/hal/halx86/mp/processor_mp.c +++ b/hal/halx86/mp/processor_mp.c @@ -18,6 +18,8 @@ #define NDEBUG #include +KAFFINITY HalpActiveProcessors; + /* PRIVATE FUNCTIONS *********************************************************/ VOID diff --git a/hal/halx86/up/processor.c b/hal/halx86/up/processor.c index 662514b19cf..2e92a2c6c86 100644 --- a/hal/halx86/up/processor.c +++ b/hal/halx86/up/processor.c @@ -12,7 +12,7 @@ #define NDEBUG #include -LONG HalpActiveProcessors; +KAFFINITY HalpActiveProcessors; KAFFINITY HalpDefaultInterruptAffinity; /* PRIVATE FUNCTIONS *********************************************************/ @@ -41,7 +41,7 @@ HalInitializeProcessor(IN ULONG ProcessorNumber, KeGetPcr()->StallScaleFactor = INITIAL_STALL_COUNT; /* Update the interrupt affinity and processor mask */ - InterlockedBitTestAndSet(&HalpActiveProcessors, ProcessorNumber); + InterlockedBitTestAndSet((PLONG)&HalpActiveProcessors, ProcessorNumber); InterlockedBitTestAndSet((PLONG)&HalpDefaultInterruptAffinity, ProcessorNumber); diff --git a/include/psdk/ks.h b/include/psdk/ks.h index f728bfb0f78..e66f130418a 100644 --- a/include/psdk/ks.h +++ b/include/psdk/ks.h @@ -744,6 +744,99 @@ typedef enum KSPROPERTY_STREAM_PIPE_ID } KSPROPERTY_STREAM; +#define DEFINE_KSPROPERTY_ITEM_STREAM_ALLOCATOR(GetHandler, SetHandler)\ + DEFINE_KSPROPERTY_ITEM(\ + KSPROPERTY_STREAM_ALLOCATOR,\ + (GetHandler),\ + sizeof(KSPROPERTY),\ + sizeof(HANDLE),\ + (SetHandler),\ + NULL, 0, NULL, NULL, 0) + +#define DEFINE_KSPROPERTY_ITEM_STREAM_QUALITY(Handler)\ + DEFINE_KSPROPERTY_ITEM(\ + KSPROPERTY_STREAM_QUALITY,\ + (Handler),\ + sizeof(KSPROPERTY),\ + sizeof(KSQUALITY_MANAGER),\ + NULL, NULL, 0, NULL, NULL, 0) + +#define DEFINE_KSPROPERTY_ITEM_STREAM_DEGRADATION(GetHandler, SetHandler)\ + DEFINE_KSPROPERTY_ITEM(\ + KSPROPERTY_STREAM_DEGRADATION,\ + (GetHandler),\ + sizeof(KSPROPERTY),\ + 0,\ + (SetHandler),\ + NULL, 0, NULL, NULL, 0) + +#define DEFINE_KSPROPERTY_ITEM_STREAM_MASTERCLOCK(GetHandler, SetHandler)\ + DEFINE_KSPROPERTY_ITEM(\ + KSPROPERTY_STREAM_MASTERCLOCK,\ + (GetHandler),\ + sizeof(KSPROPERTY),\ + sizeof(HANDLE),\ + (SetHandler),\ + NULL, 0, NULL, NULL, 0) + +#define DEFINE_KSPROPERTY_ITEM_STREAM_TIMEFORMAT(Handler)\ + DEFINE_KSPROPERTY_ITEM(\ + KSPROPERTY_STREAM_TIMEFORMAT,\ + (Handler),\ + sizeof(KSPROPERTY),\ + sizeof(GUID),\ + NULL, NULL, 0, NULL, NULL, 0) + +#define DEFINE_KSPROPERTY_ITEM_STREAM_PRESENTATIONTIME(GetHandler, SetHandler)\ + DEFINE_KSPROPERTY_ITEM(\ + KSPROPERTY_STREAM_PRESENTATIONTIME,\ + (GetHandler),\ + sizeof(KSPROPERTY),\ + sizeof(KSTIME),\ + (SetHandler),\ + NULL, 0, NULL, NULL, 0) + +#define DEFINE_KSPROPERTY_ITEM_STREAM_PRESENTATIONEXTENT(Handler)\ + DEFINE_KSPROPERTY_ITEM(\ + KSPROPERTY_STREAM_PRESENTATIONEXTENT,\ + (Handler),\ + sizeof(KSPROPERTY),\ + sizeof(LONGLONG),\ + NULL, NULL, 0, NULL, NULL, 0) + +#define DEFINE_KSPROPERTY_ITEM_STREAM_FRAMETIME(Handler)\ + DEFINE_KSPROPERTY_ITEM(\ + KSPROPERTY_STREAM_FRAMETIME,\ + (Handler),\ + sizeof(KSPROPERTY),\ + sizeof(KSFRAMETIME),\ + NULL, NULL, 0, NULL, NULL, 0) + +#define DEFINE_KSPROPERTY_ITEM_STREAM_RATECAPABILITY(Handler)\ + DEFINE_KSPROPERTY_ITEM(\ + KSPROPERTY_STREAM_RATECAPABILITY,\ + (Handler),\ + sizeof(KSRATE_CAPABILITY),\ + sizeof(KSRATE),\ + NULL, NULL, 0, NULL, NULL, 0) + +#define DEFINE_KSPROPERTY_ITEM_STREAM_RATE(GetHandler, SetHandler)\ + DEFINE_KSPROPERTY_ITEM(\ + KSPROPERTY_STREAM_RATE,\ + (GetHandler),\ + sizeof(KSPROPERTY),\ + sizeof(KSRATE),\ + (SetHandler),\ + NULL, 0, NULL, NULL, 0) + +#define DEFINE_KSPROPERTY_ITEM_STREAM_PIPE_ID(GetHandler, SetHandler)\ + DEFINE_KSPROPERTY_ITEM(\ + KSPROPERTY_STREAM_PIPE_ID,\ + (GetHandler),\ + sizeof(KSPROPERTY),\ + sizeof(HANDLE),\ + (SetHandler),\ + NULL, 0, NULL, NULL, 0) /* =============================================================== StreamAllocator diff --git a/include/reactos/win32k/ntgdityp.h b/include/reactos/win32k/ntgdityp.h index 2e710ca6bdf..1aedf765dbc 100644 --- a/include/reactos/win32k/ntgdityp.h +++ b/include/reactos/win32k/ntgdityp.h @@ -523,10 +523,7 @@ typedef struct _GDIBSEXTSELCLPRGN { GDIBATCHHDR gbHdr; int fnMode; - LONG right; - LONG bottom; - LONG left; - LONG top; + RECTL; } GDIBSEXTSELCLPRGN, *PGDIBSEXTSELCLPRGN; // // Use with GdiBCSelObj, GdiBCDelObj and GdiBCDelRgn. diff --git a/lib/cmlib/cmlib.h b/lib/cmlib/cmlib.h index fae049507d2..c6823b06a47 100644 --- a/lib/cmlib/cmlib.h +++ b/lib/cmlib/cmlib.h @@ -198,6 +198,22 @@ typedef struct _CMHIVE #endif +typedef struct _HV_HIVE_CELL_PAIR +{ + PHHIVE Hive; + HCELL_INDEX Cell; +} HV_HIVE_CELL_PAIR, *PHV_HIVE_CELL_PAIR; + +#define STATIC_CELL_PAIR_COUNT 4 +typedef struct _HV_TRACK_CELL_REF +{ + USHORT Count; + USHORT Max; + PHV_HIVE_CELL_PAIR CellArray; + HV_HIVE_CELL_PAIR StaticArray[STATIC_CELL_PAIR_COUNT]; + USHORT StaticCount; +} HV_TRACK_CELL_REF, *PHV_TRACK_CELL_REF; + extern ULONG CmlibTraceLevel; /* @@ -272,6 +288,12 @@ HvIsCellDirty( IN HCELL_INDEX Cell ); +BOOLEAN +CMAPI +HvHiveWillShrink( + IN PHHIVE RegistryHive +); + BOOLEAN CMAPI HvSyncHive( PHHIVE RegistryHive); @@ -288,6 +310,21 @@ CmCreateRootNode( VOID CMAPI CmPrepareHive( PHHIVE RegistryHive); + + +BOOLEAN +CMAPI +HvTrackCellRef( + PHV_TRACK_CELL_REF CellRef, + PHHIVE Hive, + HCELL_INDEX Cell +); + +VOID +CMAPI +HvReleaseFreeCellRefArray( + PHV_TRACK_CELL_REF CellRef +); /* * Private functions. diff --git a/lib/cmlib/hivecell.c b/lib/cmlib/hivecell.c index 994ca98170d..815165182a5 100644 --- a/lib/cmlib/hivecell.c +++ b/lib/cmlib/hivecell.c @@ -113,7 +113,7 @@ HvMarkCellDirty( __FUNCTION__, RegistryHive, CellIndex, HoldingLock); if ((CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT != Stable) - return FALSE; + return TRUE; CellBlock = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT; CellLastBlock = ((CellIndex + HV_BLOCK_SIZE - 1) & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT; @@ -525,3 +525,56 @@ HvFreeCell( if (CellType == Stable) HvMarkCellDirty(RegistryHive, CellIndex, FALSE); } + +BOOLEAN +CMAPI +HvTrackCellRef(PHV_TRACK_CELL_REF CellRef, + PHHIVE Hive, + HCELL_INDEX Cell) +{ + /* Sanity checks */ + ASSERT(CellRef); + ASSERT(Hive ); + ASSERT(Cell != HCELL_NIL); + + /* Less than 4? */ + if (CellRef->StaticCount < STATIC_CELL_PAIR_COUNT) + { + /* Add reference */ + CellRef->StaticArray[CellRef->StaticCount].Hive = Hive; + CellRef->StaticArray[CellRef->StaticCount].Cell = Cell; + CellRef->StaticCount++; + return TRUE; + } + + /* FIXME: TODO */ + DPRINT1("ERROR: Too many references\n"); + while (TRUE); + return FALSE; +} + +VOID +CMAPI +HvReleaseFreeCellRefArray(PHV_TRACK_CELL_REF CellRef) +{ + ULONG i; + ASSERT(CellRef); + + /* Any references? */ + if (CellRef->StaticCount > 0) + { + /* Sanity check */ + ASSERT(CellRef->StaticCount <= STATIC_CELL_PAIR_COUNT); + + /* Loop them */ + for (i = 0; i < CellRef->StaticCount;i++) + { + /* Release them */ + HvReleaseCell(CellRef->StaticArray[i].Hive, + CellRef->StaticArray[i].Cell); + } + + /* Free again */ + CellRef->StaticCount = 0; + } +} \ No newline at end of file diff --git a/lib/cmlib/hivewrt.c b/lib/cmlib/hivewrt.c index 5cc20cfe503..7ecadff2062 100644 --- a/lib/cmlib/hivewrt.c +++ b/lib/cmlib/hivewrt.c @@ -265,6 +265,14 @@ HvSyncHive( return TRUE; } +BOOLEAN +CMAPI +HvHiveWillShrink(IN PHHIVE RegistryHive) +{ + /* No shrinking yet */ + return FALSE; +} + BOOLEAN CMAPI HvWriteHive( PHHIVE RegistryHive) diff --git a/lib/drivers/sound/mmixer/wave.c b/lib/drivers/sound/mmixer/wave.c index a8b2675cac9..0ba0aae41b9 100644 --- a/lib/drivers/sound/mmixer/wave.c +++ b/lib/drivers/sound/mmixer/wave.c @@ -360,6 +360,17 @@ MMixerInitializeWaveInfo( WaveInfo->DeviceId = MixerData->DeviceId; WaveInfo->PinId = PinId; + + /* copy device name */ + if (bWaveIn) + { + wcscpy(WaveInfo->u.InCaps.szPname, DeviceName); + } + else + { + wcscpy(WaveInfo->u.OutCaps.szPname, DeviceName); + } + /* FIXME determine manufacturer / product id */ if (bWaveIn) { @@ -410,6 +421,8 @@ MMixerInitializeWaveInfo( MixerContext->Free(MultipleItem); + + if (bWaveIn) { InsertTailList(&MixerList->WaveInList, &WaveInfo->Entry); diff --git a/ntoskrnl/config/cmapi.c b/ntoskrnl/config/cmapi.c index 85f2ed9fe14..538c3e5b560 100644 --- a/ntoskrnl/config/cmapi.c +++ b/ntoskrnl/config/cmapi.c @@ -14,6 +14,67 @@ /* FUNCTIONS *****************************************************************/ +BOOLEAN +NTAPI +CmpIsHiveAlreadyLoaded(IN HANDLE KeyHandle, + IN POBJECT_ATTRIBUTES SourceFile, + OUT PCMHIVE *CmHive) +{ + NTSTATUS Status; + PCM_KEY_BODY KeyBody; + PCMHIVE Hive; + BOOLEAN Loaded = FALSE; + PAGED_CODE(); + + /* Sanity check */ + CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK(); + + /* Reference the handle */ + Status = ObReferenceObjectByHandle(KeyHandle, + 0, + CmpKeyObjectType, + KernelMode, + (PVOID)&KeyBody, + NULL); + if (!NT_SUCCESS(Status)) return Loaded; + + /* Don't touch deleted KCBs */ + if (KeyBody->KeyControlBlock->Delete) return Loaded; + + Hive = CONTAINING_RECORD(KeyBody->KeyControlBlock->KeyHive, CMHIVE, Hive); + + /* Must be the root key */ + if (!(KeyBody->KeyControlBlock->Flags & KEY_HIVE_ENTRY) || + !(Hive->FileUserName.Buffer)) + { + /* It isn't */ + ObDereferenceObject(KeyBody); + return Loaded; + } + + /* Now compare the name of the file */ + if (!RtlCompareUnicodeString(&Hive->FileUserName, + SourceFile->ObjectName, + TRUE)) + { + /* Same file found */ + Loaded = TRUE; + *CmHive = Hive; + + /* If the hive is frozen, not sure what to do */ + if (Hive->Frozen) + { + /* FIXME: TODO */ + DPRINT1("ERROR: Hive is frozen\n"); + while (TRUE); + } + } + + /* Dereference and return result */ + ObDereferenceObject(KeyBody); + return Loaded; + } + BOOLEAN NTAPI CmpDoFlushAll(IN BOOLEAN ForceFlush) @@ -39,16 +100,35 @@ CmpDoFlushAll(IN BOOLEAN ForceFlush) if (!(Hive->Hive.HiveFlags & HIVE_NOLAZYFLUSH)) { /* Acquire the flusher lock */ - ExAcquirePushLockExclusive((PVOID)&Hive->FlusherLock); + CmpLockHiveFlusherExclusive(Hive); + + /* Check for illegal state */ + if ((ForceFlush) && (Hive->UseCount)) + { + /* Registry needs to be locked down */ + CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK(); + DPRINT1("FIXME: Hive is damaged and needs fixup\n"); + while (TRUE); + } + + /* Only sync if we are forced to or if it won't cause a hive shrink */ + if ((ForceFlush) || (!HvHiveWillShrink(&Hive->Hive))) + { + /* Do the sync */ + Status = HvSyncHive(&Hive->Hive); - /* Do the sync */ - Status = HvSyncHive(&Hive->Hive); - - /* If something failed - set the flag and continue looping*/ - if (!NT_SUCCESS(Status)) Result = FALSE; + /* If something failed - set the flag and continue looping */ + if (!NT_SUCCESS(Status)) Result = FALSE; + } + else + { + /* We won't flush if the hive might shrink */ + Result = FALSE; + CmpForceForceFlush = TRUE; + } /* Release the flusher lock */ - ExReleasePushLock((PVOID)&Hive->FlusherLock); + CmpUnlockHiveFlusher(Hive); } /* Try the next entry */ @@ -81,10 +161,14 @@ CmpSetValueKeyNew(IN PHHIVE Hive, { /* Then make sure it's valid and dirty it */ ASSERT(Parent->ValueList.List != HCELL_NIL); - HvMarkCellDirty(Hive, Parent->ValueList.List, FALSE); + if (!HvMarkCellDirty(Hive, Parent->ValueList.List, FALSE)) + { + /* Fail if we're out of space for log changes */ + return STATUS_NO_LOG_SPACE; + } } - /* Allocate avalue cell */ + /* Allocate a value cell */ ValueCell = HvAllocateCell(Hive, FIELD_OFFSET(CM_KEY_VALUE, Name) + CmpNameSize(Hive, ValueName), @@ -102,16 +186,33 @@ CmpSetValueKeyNew(IN PHHIVE Hive, /* Set it up and copy the name */ CellData->u.KeyValue.Signature = CM_KEY_VALUE_SIGNATURE; - CellData->u.KeyValue.Flags = 0; - CellData->u.KeyValue.Type = Type; - CellData->u.KeyValue.NameLength = CmpCopyName(Hive, - CellData->u.KeyValue.Name, - ValueName); + _SEH2_TRY + { + /* This can crash since the name is coming from user-mode */ + CellData->u.KeyValue.NameLength = CmpCopyName(Hive, + CellData->u.KeyValue.Name, + ValueName); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Fail */ + DPRINT1("Invalid user data!\n"); + HvFreeCell(Hive, ValueCell); + _SEH2_YIELD(return _SEH2_GetExceptionCode()); + } + _SEH2_END; + + /* Check for compressed name */ if (CellData->u.KeyValue.NameLength < ValueName->Length) { /* This is a compressed name */ CellData->u.KeyValue.Flags = VALUE_COMP_NAME; } + else + { + /* No flags to set */ + CellData->u.KeyValue.Flags = 0; + } /* Check if this is a normal key */ if (DataSize > CM_KEY_VALUE_SMALL) @@ -140,6 +241,9 @@ CmpSetValueKeyNew(IN PHHIVE Hive, CellData->u.KeyValue.DataLength = DataSize + CM_KEY_VALUE_SPECIAL_SIZE; CellData->u.KeyValue.Data = SmallData; } + + /* Set the type now */ + CellData->u.KeyValue.Type = Type; /* Add this value cell to the child list */ Status = CmpAddValueToList(Hive, @@ -149,7 +253,12 @@ CmpSetValueKeyNew(IN PHHIVE Hive, &Parent->ValueList); /* If we failed, free the entire cell, including the data */ - if (!NT_SUCCESS(Status)) CmpFreeValue(Hive, ValueCell); + if (!NT_SUCCESS(Status)) + { + /* Overwrite the status with a known one */ + CmpFreeValue(Hive, ValueCell); + Status = STATUS_INSUFFICIENT_RESOURCES; + } /* Return Status */ return Status; @@ -170,9 +279,12 @@ CmpSetValueKeyExisting(IN PHHIVE Hive, PCELL_DATA CellData; ULONG Length; BOOLEAN WasSmall, IsSmall; + + /* Registry writes must be blocked */ + CMP_ASSERT_FLUSH_LOCK(Hive); /* Mark the old child cell dirty */ - HvMarkCellDirty(Hive, OldChild, FALSE); + if (!HvMarkCellDirty(Hive, OldChild, FALSE)) return STATUS_NO_LOG_SPACE; /* See if this is a small or normal key */ WasSmall = CmpIsKeyValueSmall(&Length, Value->DataLength); @@ -185,7 +297,7 @@ CmpSetValueKeyExisting(IN PHHIVE Hive, ASSERT_VALUE_BIG(Hive, DataSize); /* Mark the old value dirty */ - CmpMarkValueDataDirty(Hive, Value); + if (!CmpMarkValueDataDirty(Hive, Value)) return STATUS_NO_LOG_SPACE; /* Check if we have a small key */ if (IsSmall) @@ -203,662 +315,58 @@ CmpSetValueKeyExisting(IN PHHIVE Hive, Value->Type = Type; return STATUS_SUCCESS; } - else + + /* We have a normal key. Was the old cell also normal and had data? */ + if (!(WasSmall) && (Length > 0)) { - /* We have a normal key. Was the old cell also normal and had data? */ - if (!(WasSmall) && (Length > 0)) + /* Get the current data cell and actual data inside it */ + DataCell = Value->Data; + ASSERT(DataCell != HCELL_NIL); + CellData = HvGetCell(Hive, DataCell); + if (!CellData) return STATUS_INSUFFICIENT_RESOURCES; + + /* Immediately release the cell */ + HvReleaseCell(Hive, DataCell); + + /* Make sure that the data cell actually has a size */ + ASSERT(HvGetCellSize(Hive, CellData) > 0); + + /* Check if the previous data cell could fit our new data */ + if (DataSize <= (ULONG)(HvGetCellSize(Hive, CellData))) { - /* Get the current data cell and actual data inside it */ - DataCell = Value->Data; - ASSERT(DataCell != HCELL_NIL); - CellData = HvGetCell(Hive, DataCell); - if (!CellData) return STATUS_INSUFFICIENT_RESOURCES; - - /* Immediately release the cell */ - HvReleaseCell(Hive, DataCell); - - /* Make sure that the data cell actually has a size */ - ASSERT(HvGetCellSize(Hive, CellData) > 0); - - /* Check if the previous data cell could fit our new data */ - if (DataSize <= (ULONG)(HvGetCellSize(Hive, CellData))) - { - /* Re-use it then */ - NewCell = DataCell; - } - else - { - /* Otherwise, re-allocate the current data cell */ - NewCell = HvReallocateCell(Hive, DataCell, DataSize); - if (NewCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES; - } + /* Re-use it then */ + NewCell = DataCell; } else { - /* This was a small key, or a key with no data, allocate a cell */ - NewCell = HvAllocateCell(Hive, DataSize, StorageType, HCELL_NIL); + /* Otherwise, re-allocate the current data cell */ + NewCell = HvReallocateCell(Hive, DataCell, DataSize); if (NewCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES; } - - /* Now get the actual data for our data cell */ - CellData = HvGetCell(Hive, NewCell); - if (!CellData) ASSERT(FALSE); - - /* Release it immediately */ - HvReleaseCell(Hive, NewCell); - - /* Copy our data into the data cell's buffer, and set up the value */ - RtlCopyMemory(CellData, Data, DataSize); - Value->Data = NewCell; - Value->DataLength = DataSize; - Value->Type = Type; - - /* Return success */ - ASSERT(HvIsCellDirty(Hive, NewCell)); - return STATUS_SUCCESS; - } -} - -NTSTATUS -NTAPI -CmSetValueKey(IN PCM_KEY_CONTROL_BLOCK Kcb, - IN PUNICODE_STRING ValueName, - IN ULONG Type, - IN PVOID Data, - IN ULONG DataLength) -{ - PHHIVE Hive; - PCM_KEY_NODE Parent; - PCM_KEY_VALUE Value = NULL; - HCELL_INDEX CurrentChild, Cell; - NTSTATUS Status; - BOOLEAN Found, Result; - ULONG Count, ChildIndex, SmallData, Storage; - VALUE_SEARCH_RETURN_TYPE SearchResult; - - /* Acquire hive lock */ - CmpLockRegistry(); - CmpAcquireKcbLockShared(Kcb); - - /* Sanity check */ - ASSERT(sizeof(ULONG) == CM_KEY_VALUE_SMALL); - - /* Don't touch deleted KCBs */ -DoAgain: - if (Kcb->Delete) - { - /* Fail */ - Status = STATUS_KEY_DELETED; - goto Quickie; - } - - /* Don't let anyone mess with symlinks */ - if ((Kcb->Flags & KEY_SYM_LINK) && - ((Type != REG_LINK) || - !(ValueName) || - !(RtlEqualUnicodeString(&CmSymbolicLinkValueName, ValueName, TRUE)))) - { - /* Invalid modification of a symlink key */ - Status = STATUS_ACCESS_DENIED; - goto Quickie; - } - - /* Search for the value */ - SearchResult = CmpCompareNewValueDataAgainstKCBCache(Kcb, - ValueName, - Type, - Data, - DataLength); - if (SearchResult == SearchNeedExclusiveLock) - { - /* Try again with the exclusive lock */ - CmpConvertKcbSharedToExclusive(Kcb); - goto DoAgain; - } - else if (SearchResult == SearchSuccess) - { - /* We don't actually need to do anything! */ - Status = STATUS_SUCCESS; - goto Quickie; - } - - /* We need the exclusive KCB lock now */ - if (!(CmpIsKcbLockedExclusive(Kcb)) && !(CmpTryToConvertKcbSharedToExclusive(Kcb))) - { - /* Acquire exclusive lock */ - CmpConvertKcbSharedToExclusive(Kcb); - } - - /* Get pointer to key cell */ - Hive = Kcb->KeyHive; - Cell = Kcb->KeyCell; - - /* Prepare to scan the key node */ - Parent = (PCM_KEY_NODE)HvGetCell(Hive, Cell); - Count = Parent->ValueList.Count; - Found = FALSE; - if (Count > 0) - { - /* Try to find the existing name */ - Result = CmpFindNameInList(Hive, - &Parent->ValueList, - ValueName, - &ChildIndex, - &CurrentChild); - if (!Result) - { - /* Fail */ - Status = STATUS_INSUFFICIENT_RESOURCES; - goto Quickie; - } - - /* Check if we found something */ - if (CurrentChild != HCELL_NIL) - { - /* Get its value */ - Value = (PCM_KEY_VALUE)HvGetCell(Hive, CurrentChild); - if (!Value) - { - /* Fail */ - Status = STATUS_INSUFFICIENT_RESOURCES; - goto Quickie; - } - - /* Remember that we found it */ - Found = TRUE; - } } else { - /* No child list, we'll need to add it */ - ChildIndex = 0; - } - - /* The KCB must be locked exclusive at this point */ - ASSERT((CmpIsKcbLockedExclusive(Kcb) == TRUE) || - (CmpTestRegistryLockExclusive() == TRUE)); - - /* Mark the cell dirty */ - HvMarkCellDirty(Hive, Cell, FALSE); - - /* Get the storage type */ - Storage = HvGetCellType(Cell); - - /* Check if this is small data */ - SmallData = 0; - if ((DataLength <= CM_KEY_VALUE_SMALL) && (DataLength > 0)) - { - /* Copy it */ - RtlCopyMemory(&SmallData, Data, DataLength); + /* This was a small key, or a key with no data, allocate a cell */ + NewCell = HvAllocateCell(Hive, DataSize, StorageType, HCELL_NIL); + if (NewCell == HCELL_NIL) return STATUS_INSUFFICIENT_RESOURCES; } - /* Check if we didn't find a matching key */ - if (!Found) - { - /* Call the internal routine */ - Status = CmpSetValueKeyNew(Hive, - Parent, - ValueName, - ChildIndex, - Type, - Data, - DataLength, - Storage, - SmallData); - } - else - { - /* Call the internal routine */ - Status = CmpSetValueKeyExisting(Hive, - CurrentChild, - Value, - Type, - Data, - DataLength, - Storage, - SmallData); - } + /* Now get the actual data for our data cell */ + CellData = HvGetCell(Hive, NewCell); + if (!CellData) ASSERT(FALSE); - /* Check for success */ - if (NT_SUCCESS(Status)) - { - /* Check if the maximum value name length changed */ - ASSERT(Parent->MaxValueNameLen == Kcb->KcbMaxValueNameLen); - if (Parent->MaxValueNameLen < ValueName->Length) - { - /* Set the new values */ - Parent->MaxValueNameLen = ValueName->Length; - Kcb->KcbMaxValueNameLen = ValueName->Length; - } - - /* Check if the maximum data length changed */ - ASSERT(Parent->MaxValueDataLen == Kcb->KcbMaxValueDataLen); - if (Parent->MaxValueDataLen < DataLength) - { - /* Update it */ - Parent->MaxValueDataLen = DataLength; - Kcb->KcbMaxValueDataLen = Parent->MaxValueDataLen; - } - - /* Save the write time */ - KeQuerySystemTime(&Parent->LastWriteTime); - KeQuerySystemTime(&Kcb->KcbLastWriteTime); - - /* Check if the cell is cached */ - if ((Found) && (CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList))) - { - /* Shouldn't happen */ - ASSERT(FALSE); - } - else - { - /* Cleanup the value cache */ - CmpCleanUpKcbValueCache(Kcb); + /* Release it immediately */ + HvReleaseCell(Hive, NewCell); - /* Sanity checks */ - ASSERT(!(CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList))); - ASSERT(!(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND)); - - /* Set the value cache */ - Kcb->ValueCache.Count = Parent->ValueList.Count; - Kcb->ValueCache.ValueList = Parent->ValueList.List; - } - } - -Quickie: - /* Release the locks */ - CmpReleaseKcbLock(Kcb); - CmpUnlockRegistry(); - return Status; -} + /* Copy our data into the data cell's buffer, and set up the value */ + RtlCopyMemory(CellData, Data, DataSize); + Value->Data = NewCell; + Value->DataLength = DataSize; + Value->Type = Type; -NTSTATUS -NTAPI -CmDeleteValueKey(IN PCM_KEY_CONTROL_BLOCK Kcb, - IN UNICODE_STRING ValueName) -{ - NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND; - PHHIVE Hive; - PCM_KEY_NODE Parent; - HCELL_INDEX ChildCell, Cell; - PCHILD_LIST ChildList; - PCM_KEY_VALUE Value = NULL; - ULONG ChildIndex; - BOOLEAN Result; - - /* Acquire hive lock */ - CmpLockRegistry(); - - /* Lock KCB exclusively */ - CmpAcquireKcbLockExclusive(Kcb); - - /* Don't touch deleted keys */ - if (Kcb->Delete) - { - /* Undo everything */ - CmpReleaseKcbLock(Kcb); - CmpUnlockRegistry(); - return STATUS_KEY_DELETED; - } - - /* Get the hive and the cell index */ - Hive = Kcb->KeyHive; - Cell = Kcb->KeyCell; - - /* Get the parent key node */ - Parent = (PCM_KEY_NODE)HvGetCell(Hive, Cell); - if (!Parent) - { - /* Fail */ - Status = STATUS_INSUFFICIENT_RESOURCES; - goto Quickie; - } - - /* Get the value list and check if it has any entries */ - ChildList = &Parent->ValueList; - if (ChildList->Count) - { - /* Try to find this value */ - Result = CmpFindNameInList(Hive, - ChildList, - &ValueName, - &ChildIndex, - &ChildCell); - if (!Result) - { - /* Fail */ - Status = STATUS_INSUFFICIENT_RESOURCES; - goto Quickie; - } - - /* Value not found, return error */ - if (ChildCell == HCELL_NIL) goto Quickie; - - /* We found the value, mark all relevant cells dirty */ - HvMarkCellDirty(Hive, Cell, FALSE); - HvMarkCellDirty(Hive, Parent->ValueList.List, FALSE); - HvMarkCellDirty(Hive, ChildCell, FALSE); - - /* Get the key value */ - Value = (PCM_KEY_VALUE)HvGetCell(Hive,ChildCell); - if (!Value) ASSERT(FALSE); - - /* Mark it and all related data as dirty */ - CmpMarkValueDataDirty(Hive, Value); - - /* Ssanity checks */ - ASSERT(HvIsCellDirty(Hive, Parent->ValueList.List)); - ASSERT(HvIsCellDirty(Hive, ChildCell)); - - /* Remove the value from the child list */ - Status = CmpRemoveValueFromList(Hive, ChildIndex, ChildList); - if(!NT_SUCCESS(Status)) goto Quickie; - - /* Remove the value and its data itself */ - if (!CmpFreeValue(Hive, ChildCell)) - { - /* Failed to free the value, fail */ - Status = STATUS_INSUFFICIENT_RESOURCES; - goto Quickie; - } - - /* Set the last write time */ - KeQuerySystemTime(&Parent->LastWriteTime); - KeQuerySystemTime(&Kcb->KcbLastWriteTime); - - /* Sanity check */ - ASSERT(Parent->MaxValueNameLen == Kcb->KcbMaxValueNameLen); - ASSERT(Parent->MaxValueDataLen == Kcb->KcbMaxValueDataLen); - ASSERT(HvIsCellDirty(Hive, Cell)); - - /* Check if the value list is empty now */ - if (!Parent->ValueList.Count) - { - /* Then clear key node data */ - Parent->MaxValueNameLen = 0; - Parent->MaxValueDataLen = 0; - Kcb->KcbMaxValueNameLen = 0; - Kcb->KcbMaxValueDataLen = 0; - } - - /* Cleanup the value cache */ - CmpCleanUpKcbValueCache(Kcb); - - /* Sanity checks */ - ASSERT(!(CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList))); - ASSERT(!(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND)); - - /* Set the value cache */ - Kcb->ValueCache.Count = ChildList->Count; - Kcb->ValueCache.ValueList = ChildList->List; - - /* Change default Status to success */ - Status = STATUS_SUCCESS; - } - -Quickie: - /* Release the parent cell, if any */ - if (Parent) HvReleaseCell(Hive, Cell); - - /* Check if we had a value */ - if (Value) - { - /* Release the child cell */ - ASSERT(ChildCell != HCELL_NIL); - HvReleaseCell(Hive, ChildCell); - } - - /* Release locks */ - CmpReleaseKcbLock(Kcb); - CmpUnlockRegistry(); - return Status; -} - -NTSTATUS -NTAPI -CmQueryValueKey(IN PCM_KEY_CONTROL_BLOCK Kcb, - IN UNICODE_STRING ValueName, - IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, - IN PVOID KeyValueInformation, - IN ULONG Length, - IN PULONG ResultLength) -{ - NTSTATUS Status; - PCM_KEY_VALUE ValueData; - ULONG Index; - BOOLEAN ValueCached = FALSE; - PCM_CACHED_VALUE *CachedValue; - HCELL_INDEX CellToRelease; - VALUE_SEARCH_RETURN_TYPE Result; - PHHIVE Hive; - PAGED_CODE(); - - /* Acquire hive lock */ - CmpLockRegistry(); - - /* Lock the KCB shared */ - CmpAcquireKcbLockShared(Kcb); - - /* Don't touch deleted keys */ -DoAgain: - if (Kcb->Delete) - { - /* Undo everything */ - CmpReleaseKcbLock(Kcb); - CmpUnlockRegistry(); - return STATUS_KEY_DELETED; - } - - /* We don't deal with this yet */ - if (Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND) - { - /* Shouldn't happen */ - ASSERT(FALSE); - } - - /* Get the hive */ - Hive = Kcb->KeyHive; - - /* Find the key value */ - Result = CmpFindValueByNameFromCache(Kcb, - &ValueName, - &CachedValue, - &Index, - &ValueData, - &ValueCached, - &CellToRelease); - if (Result == SearchNeedExclusiveLock) - { - /* Check if we need an exclusive lock */ - ASSERT(CellToRelease == HCELL_NIL); - ASSERT(ValueData == NULL); - - /* Try with exclusive KCB lock */ - CmpConvertKcbSharedToExclusive(Kcb); - goto DoAgain; - } - - if (Result == SearchSuccess) - { - /* Sanity check */ - ASSERT(ValueData != NULL); - - /* Query the information requested */ - Result = CmpQueryKeyValueData(Kcb, - CachedValue, - ValueData, - ValueCached, - KeyValueInformationClass, - KeyValueInformation, - Length, - ResultLength, - &Status); - if (Result == SearchNeedExclusiveLock) - { - /* Try with exclusive KCB lock */ - CmpConvertKcbSharedToExclusive(Kcb); - goto DoAgain; - } - } - else - { - /* Failed to find the value */ - Status = STATUS_OBJECT_NAME_NOT_FOUND; - } - - /* If we have a cell to release, do so */ - if (CellToRelease != HCELL_NIL) HvReleaseCell(Hive, CellToRelease); - - /* Release locks */ - CmpReleaseKcbLock(Kcb); - CmpUnlockRegistry(); - return Status; -} - -NTSTATUS -NTAPI -CmEnumerateValueKey(IN PCM_KEY_CONTROL_BLOCK Kcb, - IN ULONG Index, - IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, - IN PVOID KeyValueInformation, - IN ULONG Length, - IN PULONG ResultLength) -{ - NTSTATUS Status; - PHHIVE Hive; - PCM_KEY_NODE Parent; - HCELL_INDEX CellToRelease = HCELL_NIL, CellToRelease2 = HCELL_NIL; - VALUE_SEARCH_RETURN_TYPE Result; - BOOLEAN IndexIsCached, ValueIsCached = FALSE; - PCELL_DATA CellData; - PCM_CACHED_VALUE *CachedValue; - PCM_KEY_VALUE ValueData = NULL; - PAGED_CODE(); - - /* Acquire hive lock */ - CmpLockRegistry(); - - /* Lock the KCB shared */ - CmpAcquireKcbLockShared(Kcb); - - /* Don't touch deleted keys */ -DoAgain: - if (Kcb->Delete) - { - /* Undo everything */ - CmpReleaseKcbLock(Kcb); - CmpUnlockRegistry(); - return STATUS_KEY_DELETED; - } - - /* Get the hive and parent */ - Hive = Kcb->KeyHive; - Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell); - if (!Parent) - { - /* Fail */ - Status = STATUS_INSUFFICIENT_RESOURCES; - goto Quickie; - } - - /* Make sure the index is valid */ - //if (Index >= Kcb->ValueCache.Count) - if (Index >= Parent->ValueList.Count) - { - /* Release the cell and fail */ - HvReleaseCell(Hive, Kcb->KeyCell); - Status = STATUS_NO_MORE_ENTRIES; - goto Quickie; - } - - /* We don't deal with this yet */ - if (Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND) - { - /* Shouldn't happen */ - ASSERT(FALSE); - } - - /* Find the value list */ - Result = CmpGetValueListFromCache(Kcb, - &CellData, - &IndexIsCached, - &CellToRelease); - if (Result == SearchNeedExclusiveLock) - { - /* Check if we need an exclusive lock */ - ASSERT(CellToRelease == HCELL_NIL); - ASSERT(ValueData == NULL); - - /* Try with exclusive KCB lock */ - CmpConvertKcbSharedToExclusive(Kcb); - goto DoAgain; - } - else if (Result != SearchSuccess) - { - /* Sanity check */ - ASSERT(CellData == NULL); - - /* Release the cell and fail */ - Status = STATUS_INSUFFICIENT_RESOURCES; - goto Quickie; - } - - /* Now get the key value */ - Result = CmpGetValueKeyFromCache(Kcb, - CellData, - Index, - &CachedValue, - &ValueData, - IndexIsCached, - &ValueIsCached, - &CellToRelease2); - if (Result == SearchNeedExclusiveLock) - { - /* Try with exclusive KCB lock */ - CmpConvertKcbSharedToExclusive(Kcb); - goto DoAgain; - } - else if (Result != SearchSuccess) - { - /* Sanity check */ - ASSERT(ValueData == NULL); - - /* Release the cells and fail */ - Status = STATUS_INSUFFICIENT_RESOURCES; - goto Quickie; - } - - /* Query the information requested */ - Result = CmpQueryKeyValueData(Kcb, - CachedValue, - ValueData, - ValueIsCached, - KeyValueInformationClass, - KeyValueInformation, - Length, - ResultLength, - &Status); - if (Result == SearchNeedExclusiveLock) - { - /* Try with exclusive KCB lock */ - CmpConvertKcbSharedToExclusive(Kcb); - goto DoAgain; - } - -Quickie: - /* If we have a cell to release, do so */ - if (CellToRelease != HCELL_NIL) HvReleaseCell(Hive, CellToRelease); - - /* Release the parent cell */ - HvReleaseCell(Hive, Kcb->KeyCell); - - /* If we have a cell to release, do so */ - if (CellToRelease2 != HCELL_NIL) HvReleaseCell(Hive, CellToRelease2); - - /* Release locks */ - CmpReleaseKcbLock(Kcb); - CmpUnlockRegistry(); - return Status; + /* Return success */ + ASSERT(HvIsCellDirty(Hive, NewCell)); + return STATUS_SUCCESS; } NTSTATUS @@ -1076,6 +584,725 @@ CmpQueryKeyData(IN PHHIVE Hive, return Status; } +NTSTATUS +NTAPI +CmSetValueKey(IN PCM_KEY_CONTROL_BLOCK Kcb, + IN PUNICODE_STRING ValueName, + IN ULONG Type, + IN PVOID Data, + IN ULONG DataLength) +{ + PHHIVE Hive = NULL; + PCM_KEY_NODE Parent; + PCM_KEY_VALUE Value = NULL; + HCELL_INDEX CurrentChild, Cell; + NTSTATUS Status; + BOOLEAN Found, Result; + ULONG Count, ChildIndex, SmallData, Storage; + VALUE_SEARCH_RETURN_TYPE SearchResult; + BOOLEAN FirstTry = TRUE, FlusherLocked = FALSE; + HCELL_INDEX ParentCell = HCELL_NIL, ChildCell = HCELL_NIL; + + /* Acquire hive and KCB lock */ + CmpLockRegistry(); + CmpAcquireKcbLockShared(Kcb); + + /* Sanity check */ + ASSERT(sizeof(ULONG) == CM_KEY_VALUE_SMALL); + + /* Don't touch deleted KCBs */ +DoAgain: + if (Kcb->Delete) + { + /* Fail */ + Status = STATUS_KEY_DELETED; + goto Quickie; + } + + /* Don't let anyone mess with symlinks */ + if ((Kcb->Flags & KEY_SYM_LINK) && + ((Type != REG_LINK) || + !(ValueName) || + !(RtlEqualUnicodeString(&CmSymbolicLinkValueName, ValueName, TRUE)))) + { + /* Invalid modification of a symlink key */ + Status = STATUS_ACCESS_DENIED; + goto Quickie; + } + + /* Check if this is the first attempt */ + if (FirstTry) + { + /* Search for the value in the cache */ + SearchResult = CmpCompareNewValueDataAgainstKCBCache(Kcb, + ValueName, + Type, + Data, + DataLength); + if (SearchResult == SearchNeedExclusiveLock) + { + /* Try again with the exclusive lock */ + CmpConvertKcbSharedToExclusive(Kcb); + goto DoAgain; + } + else if (SearchResult == SearchSuccess) + { + /* We don't actually need to do anything! */ + Status = STATUS_SUCCESS; + goto Quickie; + } + + /* We need the exclusive KCB lock now */ + if (!(CmpIsKcbLockedExclusive(Kcb)) && + !(CmpTryToConvertKcbSharedToExclusive(Kcb))) + { + /* Acquire exclusive lock */ + CmpConvertKcbSharedToExclusive(Kcb); + } + + /* Cache lookup failed, so don't try it next time */ + FirstTry = FALSE; + + /* Now grab the flush lock since the key will be modified */ + ASSERT(FlusherLocked == FALSE); + CmpLockHiveFlusherShared((PCMHIVE)Kcb->KeyHive); + FlusherLocked = TRUE; + goto DoAgain; + } + else + { + /* Get pointer to key cell */ + Hive = Kcb->KeyHive; + Cell = Kcb->KeyCell; + + /* Get the parent */ + Parent = (PCM_KEY_NODE)HvGetCell(Hive, Cell); + ASSERT(Parent); + ParentCell = Cell; + + /* Prepare to scan the key node */ + Count = Parent->ValueList.Count; + Found = FALSE; + if (Count > 0) + { + /* Try to find the existing name */ + Result = CmpFindNameInList(Hive, + &Parent->ValueList, + ValueName, + &ChildIndex, + &CurrentChild); + if (!Result) + { + /* Fail */ + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Quickie; + } + + /* Check if we found something */ + if (CurrentChild != HCELL_NIL) + { + /* Release existing child */ + if (ChildCell != HCELL_NIL) + { + HvReleaseCell(Hive, ChildCell); + ChildCell = HCELL_NIL; + } + + /* Get its value */ + Value = (PCM_KEY_VALUE)HvGetCell(Hive, CurrentChild); + if (!Value) + { + /* Fail */ + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Quickie; + } + + /* Remember that we found it */ + ChildCell = CurrentChild; + Found = TRUE; + } + } + else + { + /* No child list, we'll need to add it */ + ChildIndex = 0; + } + } + + /* Should only get here on the second pass */ + ASSERT(FirstTry == FALSE); + + /* The KCB must be locked exclusive at this point */ + CMP_ASSERT_KCB_LOCK(Kcb); + + /* Mark the cell dirty */ + if (!HvMarkCellDirty(Hive, Cell, FALSE)) + { + /* Not enough log space, fail */ + Status = STATUS_NO_LOG_SPACE; + goto Quickie; + } + + /* Get the storage type */ + Storage = HvGetCellType(Cell); + + /* Check if this is small data */ + SmallData = 0; + if ((DataLength <= CM_KEY_VALUE_SMALL) && (DataLength > 0)) + { + /* Need SEH because user data may be invalid */ + _SEH2_TRY + { + /* Copy it */ + RtlCopyMemory(&SmallData, Data, DataLength); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Return failure code */ + Status = _SEH2_GetExceptionCode(); + _SEH2_YIELD(goto Quickie); + } + _SEH2_END; + } + + /* Check if we didn't find a matching key */ + if (!Found) + { + /* Call the internal routine */ + Status = CmpSetValueKeyNew(Hive, + Parent, + ValueName, + ChildIndex, + Type, + Data, + DataLength, + Storage, + SmallData); + } + else + { + /* Call the internal routine */ + Status = CmpSetValueKeyExisting(Hive, + CurrentChild, + Value, + Type, + Data, + DataLength, + Storage, + SmallData); + } + + /* Check for success */ + if (NT_SUCCESS(Status)) + { + /* Check if the maximum value name length changed */ + ASSERT(Parent->MaxValueNameLen == Kcb->KcbMaxValueNameLen); + if (Parent->MaxValueNameLen < ValueName->Length) + { + /* Set the new values */ + Parent->MaxValueNameLen = ValueName->Length; + Kcb->KcbMaxValueNameLen = ValueName->Length; + } + + /* Check if the maximum data length changed */ + ASSERT(Parent->MaxValueDataLen == Kcb->KcbMaxValueDataLen); + if (Parent->MaxValueDataLen < DataLength) + { + /* Update it */ + Parent->MaxValueDataLen = DataLength; + Kcb->KcbMaxValueDataLen = Parent->MaxValueDataLen; + } + + /* Save the write time */ + KeQuerySystemTime(&Parent->LastWriteTime); + Kcb->KcbLastWriteTime = Parent->LastWriteTime; + + /* Check if the cell is cached */ + if ((Found) && (CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList))) + { + /* Shouldn't happen */ + ASSERT(FALSE); + } + else + { + /* Cleanup the value cache */ + CmpCleanUpKcbValueCache(Kcb); + + /* Sanity checks */ + ASSERT(!(CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList))); + ASSERT(!(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND)); + + /* Set the value cache */ + Kcb->ValueCache.Count = Parent->ValueList.Count; + Kcb->ValueCache.ValueList = Parent->ValueList.List; + } + + /* Notify registered callbacks */ + CmpReportNotify(Kcb, + Hive, + Kcb->KeyCell, + REG_NOTIFY_CHANGE_LAST_SET); + } + + /* Release the cells */ +Quickie: + if ((ParentCell != HCELL_NIL) && (Hive)) HvReleaseCell(Hive, ParentCell); + if ((ChildCell != HCELL_NIL) && (Hive)) HvReleaseCell(Hive, ChildCell); + + /* Release the locks */ + if (FlusherLocked) CmpUnlockHiveFlusher((PCMHIVE)Hive); + CmpReleaseKcbLock(Kcb); + CmpUnlockRegistry(); + return Status; +} + +NTSTATUS +NTAPI +CmDeleteValueKey(IN PCM_KEY_CONTROL_BLOCK Kcb, + IN UNICODE_STRING ValueName) +{ + NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND; + PHHIVE Hive; + PCM_KEY_NODE Parent; + HCELL_INDEX ChildCell, Cell; + PCHILD_LIST ChildList; + PCM_KEY_VALUE Value = NULL; + ULONG ChildIndex; + BOOLEAN Result; + + /* Acquire hive lock */ + CmpLockRegistry(); + + /* Lock KCB exclusively */ + CmpAcquireKcbLockExclusive(Kcb); + + /* Don't touch deleted keys */ + if (Kcb->Delete) + { + /* Undo everything */ + CmpReleaseKcbLock(Kcb); + CmpUnlockRegistry(); + return STATUS_KEY_DELETED; + } + + /* Get the hive and the cell index */ + Hive = Kcb->KeyHive; + Cell = Kcb->KeyCell; + + /* Lock flushes */ + CmpLockHiveFlusherShared((PCMHIVE)Hive); + + /* Get the parent key node */ + Parent = (PCM_KEY_NODE)HvGetCell(Hive, Cell); + ASSERT(Parent); + + /* Get the value list and check if it has any entries */ + ChildList = &Parent->ValueList; + if (ChildList->Count) + { + /* Try to find this value */ + Result = CmpFindNameInList(Hive, + ChildList, + &ValueName, + &ChildIndex, + &ChildCell); + if (!Result) + { + /* Fail */ + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Quickie; + } + + /* Value not found, return error */ + if (ChildCell == HCELL_NIL) goto Quickie; + + /* We found the value, mark all relevant cells dirty */ + if (!((HvMarkCellDirty(Hive, Cell, FALSE)) && + (HvMarkCellDirty(Hive, Parent->ValueList.List, FALSE)) && + (HvMarkCellDirty(Hive, ChildCell, FALSE)))) + { + /* Not enough log space, fail */ + Status = STATUS_NO_LOG_SPACE; + goto Quickie; + } + + /* Get the key value */ + Value = (PCM_KEY_VALUE)HvGetCell(Hive,ChildCell); + ASSERT(Value); + + /* Mark it and all related data as dirty */ + if (!CmpMarkValueDataDirty(Hive, Value)) + { + /* Not enough log space, fail */ + Status = STATUS_NO_LOG_SPACE; + goto Quickie; + } + + /* Ssanity checks */ + ASSERT(HvIsCellDirty(Hive, Parent->ValueList.List)); + ASSERT(HvIsCellDirty(Hive, ChildCell)); + + /* Remove the value from the child list */ + Status = CmpRemoveValueFromList(Hive, ChildIndex, ChildList); + if (!NT_SUCCESS(Status)) + { + /* Set known error */ + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Quickie; + } + + /* Remove the value and its data itself */ + if (!CmpFreeValue(Hive, ChildCell)) + { + /* Failed to free the value, fail */ + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Quickie; + } + + /* Set the last write time */ + KeQuerySystemTime(&Parent->LastWriteTime); + Kcb->KcbLastWriteTime = Parent->LastWriteTime; + + /* Sanity check */ + ASSERT(Parent->MaxValueNameLen == Kcb->KcbMaxValueNameLen); + ASSERT(Parent->MaxValueDataLen == Kcb->KcbMaxValueDataLen); + ASSERT(HvIsCellDirty(Hive, Cell)); + + /* Check if the value list is empty now */ + if (!Parent->ValueList.Count) + { + /* Then clear key node data */ + Parent->MaxValueNameLen = 0; + Parent->MaxValueDataLen = 0; + Kcb->KcbMaxValueNameLen = 0; + Kcb->KcbMaxValueDataLen = 0; + } + + /* Cleanup the value cache */ + CmpCleanUpKcbValueCache(Kcb); + + /* Sanity checks */ + ASSERT(!(CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList))); + ASSERT(!(Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND)); + + /* Set the value cache */ + Kcb->ValueCache.Count = ChildList->Count; + Kcb->ValueCache.ValueList = ChildList->List; + + /* Notify registered callbacks */ + CmpReportNotify(Kcb, Hive, Cell, REG_NOTIFY_CHANGE_LAST_SET); + + /* Change default Status to success */ + Status = STATUS_SUCCESS; + } + +Quickie: + /* Release the parent cell, if any */ + if (Parent) HvReleaseCell(Hive, Cell); + + /* Check if we had a value */ + if (Value) + { + /* Release the child cell */ + ASSERT(ChildCell != HCELL_NIL); + HvReleaseCell(Hive, ChildCell); + } + + /* Release locks */ + CmpUnlockHiveFlusher((PCMHIVE)Hive); + CmpReleaseKcbLock(Kcb); + CmpUnlockRegistry(); + return Status; +} + +NTSTATUS +NTAPI +CmQueryValueKey(IN PCM_KEY_CONTROL_BLOCK Kcb, + IN UNICODE_STRING ValueName, + IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + IN PVOID KeyValueInformation, + IN ULONG Length, + IN PULONG ResultLength) +{ + NTSTATUS Status; + PCM_KEY_VALUE ValueData; + ULONG Index; + BOOLEAN ValueCached = FALSE; + PCM_CACHED_VALUE *CachedValue; + HCELL_INDEX CellToRelease; + VALUE_SEARCH_RETURN_TYPE Result; + PHHIVE Hive; + PAGED_CODE(); + + /* Acquire hive lock */ + CmpLockRegistry(); + + /* Lock the KCB shared */ + CmpAcquireKcbLockShared(Kcb); + + /* Don't touch deleted keys */ +DoAgain: + if (Kcb->Delete) + { + /* Undo everything */ + CmpReleaseKcbLock(Kcb); + CmpUnlockRegistry(); + return STATUS_KEY_DELETED; + } + + /* We don't deal with this yet */ + if (Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND) + { + /* Shouldn't happen */ + ASSERT(FALSE); + } + + /* Get the hive */ + Hive = Kcb->KeyHive; + + /* Find the key value */ + Result = CmpFindValueByNameFromCache(Kcb, + &ValueName, + &CachedValue, + &Index, + &ValueData, + &ValueCached, + &CellToRelease); + if (Result == SearchNeedExclusiveLock) + { + /* Check if we need an exclusive lock */ + ASSERT(CellToRelease == HCELL_NIL); + ASSERT(ValueData == NULL); + + /* Try with exclusive KCB lock */ + CmpConvertKcbSharedToExclusive(Kcb); + goto DoAgain; + } + + if (Result == SearchSuccess) + { + /* Sanity check */ + ASSERT(ValueData != NULL); + + /* User data, protect against exceptions */ + _SEH2_TRY + { + /* Query the information requested */ + Result = CmpQueryKeyValueData(Kcb, + CachedValue, + ValueData, + ValueCached, + KeyValueInformationClass, + KeyValueInformation, + Length, + ResultLength, + &Status); + if (Result == SearchNeedExclusiveLock) + { + /* Release the value cell */ + if (CellToRelease != HCELL_NIL) + { + HvReleaseCell(Hive, CellToRelease); + CellToRelease = HCELL_NIL; + } + + /* Try with exclusive KCB lock */ + CmpConvertKcbSharedToExclusive(Kcb); + goto DoAgain; + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + } + else + { + /* Failed to find the value */ + Status = STATUS_OBJECT_NAME_NOT_FOUND; + } + + /* If we have a cell to release, do so */ + if (CellToRelease != HCELL_NIL) HvReleaseCell(Hive, CellToRelease); + + /* Release locks */ + CmpReleaseKcbLock(Kcb); + CmpUnlockRegistry(); + return Status; +} + +NTSTATUS +NTAPI +CmEnumerateValueKey(IN PCM_KEY_CONTROL_BLOCK Kcb, + IN ULONG Index, + IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, + IN PVOID KeyValueInformation, + IN ULONG Length, + IN PULONG ResultLength) +{ + NTSTATUS Status; + PHHIVE Hive; + PCM_KEY_NODE Parent; + HCELL_INDEX CellToRelease = HCELL_NIL, CellToRelease2 = HCELL_NIL; + VALUE_SEARCH_RETURN_TYPE Result; + BOOLEAN IndexIsCached, ValueIsCached = FALSE; + PCELL_DATA CellData; + PCM_CACHED_VALUE *CachedValue; + PCM_KEY_VALUE ValueData = NULL; + PAGED_CODE(); + + /* Acquire hive lock */ + CmpLockRegistry(); + + /* Lock the KCB shared */ + CmpAcquireKcbLockShared(Kcb); + + /* Don't touch deleted keys */ +DoAgain: + if (Kcb->Delete) + { + /* Undo everything */ + CmpReleaseKcbLock(Kcb); + CmpUnlockRegistry(); + return STATUS_KEY_DELETED; + } + + /* Get the hive and parent */ + Hive = Kcb->KeyHive; + Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell); + ASSERT(Parent); + + /* FIXME: Lack of cache? */ + if (Kcb->ValueCache.Count != Parent->ValueList.Count) + { + DPRINT1("HACK: Overriding value cache count\n"); + Kcb->ValueCache.Count = Parent->ValueList.Count; + } + + /* Make sure the index is valid */ + if (Index >= Kcb->ValueCache.Count) + { + /* Release the cell and fail */ + HvReleaseCell(Hive, Kcb->KeyCell); + Status = STATUS_NO_MORE_ENTRIES; + goto Quickie; + } + + /* We don't deal with this yet */ + if (Kcb->ExtFlags & CM_KCB_SYM_LINK_FOUND) + { + /* Shouldn't happen */ + ASSERT(FALSE); + } + + /* Find the value list */ + Result = CmpGetValueListFromCache(Kcb, + &CellData, + &IndexIsCached, + &CellToRelease); + if (Result == SearchNeedExclusiveLock) + { + /* Check if we need an exclusive lock */ + ASSERT(CellToRelease == HCELL_NIL); + HvReleaseCell(Hive, Kcb->KeyCell); + + /* Try with exclusive KCB lock */ + CmpConvertKcbSharedToExclusive(Kcb); + goto DoAgain; + } + else if (Result != SearchSuccess) + { + /* Sanity check */ + ASSERT(CellData == NULL); + + /* Release the cell and fail */ + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Quickie; + } + + /* Now get the key value */ + Result = CmpGetValueKeyFromCache(Kcb, + CellData, + Index, + &CachedValue, + &ValueData, + IndexIsCached, + &ValueIsCached, + &CellToRelease2); + if (Result == SearchNeedExclusiveLock) + { + /* Cleanup state */ + ASSERT(CellToRelease2 == HCELL_NIL); + if (CellToRelease) + { + HvReleaseCell(Hive, CellToRelease); + CellToRelease = HCELL_NIL; + } + HvReleaseCell(Hive, Kcb->KeyCell); + + /* Try with exclusive KCB lock */ + CmpConvertKcbSharedToExclusive(Kcb); + goto DoAgain; + } + else if (Result != SearchSuccess) + { + /* Sanity check */ + ASSERT(ValueData == NULL); + + /* Release the cells and fail */ + Status = STATUS_INSUFFICIENT_RESOURCES; + goto Quickie; + } + + /* User data, need SEH */ + _SEH2_TRY + { + /* Query the information requested */ + Result = CmpQueryKeyValueData(Kcb, + CachedValue, + ValueData, + ValueIsCached, + KeyValueInformationClass, + KeyValueInformation, + Length, + ResultLength, + &Status); + if (Result == SearchNeedExclusiveLock) + { + /* Cleanup state */ + if (CellToRelease2) HvReleaseCell(Hive, CellToRelease2); + HvReleaseCell(Hive, Kcb->KeyCell); + if (CellToRelease) HvReleaseCell(Hive, CellToRelease); + + /* Try with exclusive KCB lock */ + CmpConvertKcbSharedToExclusive(Kcb); + goto DoAgain; + } + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Get exception code */ + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + +Quickie: + /* If we have a cell to release, do so */ + if (CellToRelease != HCELL_NIL) HvReleaseCell(Hive, CellToRelease); + + /* Release the parent cell */ + HvReleaseCell(Hive, Kcb->KeyCell); + + /* If we have a cell to release, do so */ + if (CellToRelease2 != HCELL_NIL) HvReleaseCell(Hive, CellToRelease2); + + /* Release locks */ + CmpReleaseKcbLock(Kcb); + CmpUnlockRegistry(); + return Status; +} + NTSTATUS NTAPI CmQueryKey(IN PCM_KEY_CONTROL_BLOCK Kcb, @@ -1087,6 +1314,7 @@ CmQueryKey(IN PCM_KEY_CONTROL_BLOCK Kcb, NTSTATUS Status; PHHIVE Hive; PCM_KEY_NODE Parent; + HV_TRACK_CELL_REF CellReferences = {0}; /* Acquire hive lock */ CmpLockRegistry(); @@ -1094,16 +1322,6 @@ CmQueryKey(IN PCM_KEY_CONTROL_BLOCK Kcb, /* Lock KCB shared */ CmpAcquireKcbLockShared(Kcb); - /* Get the hive and parent */ - Hive = Kcb->KeyHive; - Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell); - if (!Parent) - { - /* Fail */ - Status = STATUS_INSUFFICIENT_RESOURCES; - goto Quickie; - } - /* Don't touch deleted keys */ if (Kcb->Delete) { @@ -1120,13 +1338,27 @@ CmQueryKey(IN PCM_KEY_CONTROL_BLOCK Kcb, case KeyBasicInformation: case KeyNodeInformation: - /* Call the internal API */ - Status = CmpQueryKeyData(Hive, - Parent, - KeyInformationClass, - KeyInformation, - Length, - ResultLength); + /* Get the hive and parent */ + Hive = Kcb->KeyHive; + Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell); + ASSERT(Parent); + + /* Track cell references */ + if (!HvTrackCellRef(&CellReferences, Hive, Kcb->KeyCell)) + { + /* Not enough memory to track references */ + Status = STATUS_INSUFFICIENT_RESOURCES; + } + else + { + /* Call the internal API */ + Status = CmpQueryKeyData(Hive, + Parent, + KeyInformationClass, + KeyInformation, + Length, + ResultLength); + } break; /* Unsupported classes for now */ @@ -1149,6 +1381,9 @@ CmQueryKey(IN PCM_KEY_CONTROL_BLOCK Kcb, } Quickie: + /* Release references */ + HvReleaseFreeCellRefArray(&CellReferences); + /* Release locks */ CmpReleaseKcbLock(Kcb); CmpUnlockRegistry(); @@ -1168,6 +1403,7 @@ CmEnumerateKey(IN PCM_KEY_CONTROL_BLOCK Kcb, PHHIVE Hive; PCM_KEY_NODE Parent, Child; HCELL_INDEX ChildCell; + HV_TRACK_CELL_REF CellReferences = {0}; /* Acquire hive lock */ CmpLockRegistry(); @@ -1179,20 +1415,14 @@ CmEnumerateKey(IN PCM_KEY_CONTROL_BLOCK Kcb, if (Kcb->Delete) { /* Undo everything */ - CmpReleaseKcbLock(Kcb); - CmpUnlockRegistry(); - return STATUS_KEY_DELETED; + Status = STATUS_KEY_DELETED; + goto Quickie; } /* Get the hive and parent */ Hive = Kcb->KeyHive; Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell); - if (!Parent) - { - /* Fail */ - Status = STATUS_INSUFFICIENT_RESOURCES; - goto Quickie; - } + ASSERT(Parent); /* Get the child cell */ ChildCell = CmpFindSubKeyByNumber(Hive, Parent, Index); @@ -1210,22 +1440,39 @@ CmEnumerateKey(IN PCM_KEY_CONTROL_BLOCK Kcb, /* Now get the actual child node */ Child = (PCM_KEY_NODE)HvGetCell(Hive, ChildCell); - if (!Child) + ASSERT(Child); + + /* Track references */ + if (!HvTrackCellRef(&CellReferences, Hive, ChildCell)) { - /* Fail */ + /* Can't allocate memory for tracking */ Status = STATUS_INSUFFICIENT_RESOURCES; goto Quickie; } - /* Query the data requested */ - Status = CmpQueryKeyData(Hive, - Child, - KeyInformationClass, - KeyInformation, - Length, - ResultLength); + /* Data can be user-mode, use SEH */ + _SEH2_TRY + { + /* Query the data requested */ + Status = CmpQueryKeyData(Hive, + Child, + KeyInformationClass, + KeyInformation, + Length, + ResultLength); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Fail with exception code */ + Status = _SEH2_GetExceptionCode(); + _SEH2_YIELD(goto Quickie); + } + _SEH2_END; Quickie: + /* Release references */ + HvReleaseFreeCellRefArray(&CellReferences); + /* Release locks */ CmpReleaseKcbLock(Kcb); CmpUnlockRegistry(); @@ -1271,14 +1518,12 @@ CmDeleteKey(IN PCM_KEY_BODY KeyBody) Hive = Kcb->KeyHive; Cell = Kcb->KeyCell; + /* Lock flushes */ + CmpLockHiveFlusherShared((PCMHIVE)Hive); + /* Get the key node */ Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell); - if (!Node) - { - /* Fail */ - Status = STATUS_INSUFFICIENT_RESOURCES; - goto Quickie; - } + ASSERT(Node); /* Sanity check */ ASSERT(Node->Flags == Kcb->Flags); @@ -1287,11 +1532,17 @@ CmDeleteKey(IN PCM_KEY_BODY KeyBody) if (!(Node->SubKeyCounts[Stable] + Node->SubKeyCounts[Volatile]) && !(Node->Flags & KEY_NO_DELETE)) { + /* Send notification to registered callbacks */ + CmpReportNotify(Kcb, Hive, Cell, REG_NOTIFY_CHANGE_NAME); + /* Get the parent and free the cell */ ParentCell = Node->Parent; Status = CmpFreeKeyByCell(Hive, Cell, TRUE); if (NT_SUCCESS(Status)) { + /* Flush any notifications */ + CmpFlushNotifiesOnKeyBodyList(Kcb, FALSE); + /* Clean up information we have on the subkey */ CmpCleanUpSubKeyInfo(Kcb->ParentKcb); @@ -1327,10 +1578,12 @@ CmDeleteKey(IN PCM_KEY_BODY KeyBody) Status = STATUS_CANNOT_DELETE; } -Quickie: /* Release the cell */ HvReleaseCell(Hive, Cell); - + + /* Release flush lock */ + CmpUnlockHiveFlusher((PCMHIVE)Hive); + /* Release the KCB locks */ Quickie2: CmpReleaseTwoKcbLockByKey(Kcb->ConvKey, Kcb->ParentKcb->ConvKey); @@ -1364,12 +1617,36 @@ CmFlushKey(IN PCM_KEY_CONTROL_BLOCK Kcb, } else { + /* Don't touch the hive */ + CmpLockHiveFlusherExclusive(CmHive); + ASSERT(CmHive->ViewLock); + KeAcquireGuardedMutex(CmHive->ViewLock); + CmHive->ViewLockOwner = KeGetCurrentThread(); + + /* Will the hive shrink? */ + if (HvHiveWillShrink(Hive)) + { + /* I don't believe the current Hv does shrinking */ + ASSERT(FALSE); + } + else + { + /* Now we can release views */ + ASSERT(CmHive->ViewLock); + CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK_OR_LOADING(CmHive); + ASSERT(KeGetCurrentThread() == CmHive->ViewLockOwner); + KeReleaseGuardedMutex(CmHive->ViewLock); + } + /* Flush only this hive */ if (!HvSyncHive(Hive)) { /* Fail */ Status = STATUS_REGISTRY_IO_FAILED; } + + /* Release the flush lock */ + CmpUnlockHiveFlusher((PCMHIVE)Hive); } /* Return the status */ @@ -1387,8 +1664,9 @@ CmLoadKey(IN POBJECT_ATTRIBUTES TargetKey, SECURITY_CLIENT_CONTEXT ClientSecurityContext; HANDLE KeyHandle; BOOLEAN Allocate = TRUE; - PCMHIVE CmHive; + PCMHIVE CmHive, LoadedHive; NTSTATUS Status; + CM_PARSE_CONTEXT ParseContext; /* Check if we have a trust key */ if (KeyBody) @@ -1415,9 +1693,21 @@ CmLoadKey(IN POBJECT_ATTRIBUTES TargetKey, } /* Open the target key */ +#if 0 Status = ZwOpenKey(&KeyHandle, KEY_READ, TargetKey); +#else + RtlZeroMemory(&ParseContext, sizeof(ParseContext)); + ParseContext.CreateOperation = FALSE; + Status = ObOpenObjectByName(TargetKey, + CmpKeyObjectType, + KernelMode, + NULL, + KEY_READ, + &ParseContext, + &KeyHandle); +#endif if (!NT_SUCCESS(Status)) KeyHandle = NULL; - + /* Open the hive */ Status = CmpCmdHiveOpen(SourceFile, &ClientSecurityContext, @@ -1437,21 +1727,29 @@ CmLoadKey(IN POBJECT_ATTRIBUTES TargetKey, /* Lock the registry */ CmpLockRegistryExclusive(); - /* FIXME: Check if we are already loaded */ - + /* Check if we are already loaded */ + if (CmpIsHiveAlreadyLoaded(KeyHandle, SourceFile, &LoadedHive)) + { + /* That's okay then */ + ASSERT(LoadedHive); + Status = STATUS_SUCCESS; + } + /* Release the registry */ CmpUnlockRegistry(); } /* Close the key handle if we had one */ if (KeyHandle) ZwClose(KeyHandle); - DPRINT1("Failed: %lx\n", Status); return Status; } /* Lock the registry shared */ CmpLockRegistry(); + /* Lock loading */ + ExAcquirePushLockExclusive(&CmpLoadHiveLock); + /* Lock the hive to this thread */ CmHive->Hive.HiveFlags |= HIVE_IS_UNLOADING; CmHive->CreatorOwner = KeGetCurrentThread(); @@ -1467,23 +1765,37 @@ CmLoadKey(IN POBJECT_ATTRIBUTES TargetKey, TargetKey->SecurityDescriptor); if (NT_SUCCESS(Status)) { - /* FIXME: Add to HiveList key */ + /* Add to HiveList key */ + CmpAddToHiveFileList(CmHive); /* Sync the hive if necessary */ if (Allocate) { - /* Sync it */ + /* Sync it under the flusher lock */ + CmpLockHiveFlusherExclusive(CmHive); HvSyncHive(&CmHive->Hive); + CmpUnlockHiveFlusher(CmHive); } /* Release the hive */ CmHive->Hive.HiveFlags &= ~HIVE_IS_UNLOADING; CmHive->CreatorOwner = NULL; + + /* Allow loads */ + ExReleasePushLock(&CmpLoadHiveLock); } else { /* FIXME: TODO */ - + ASSERT(FALSE); + } + + /* Is this first profile load? */ + if (!(CmpProfileLoaded) && !(CmpWasSetupBoot)) + { + /* User is now logged on, set quotas */ + CmpProfileLoaded = TRUE; + CmpSetGlobalQuotaAllowed(); } /* Unlock the registry */ diff --git a/ntoskrnl/config/cmboot.c b/ntoskrnl/config/cmboot.c index f1dcc347a20..50c6815866f 100644 --- a/ntoskrnl/config/cmboot.c +++ b/ntoskrnl/config/cmboot.c @@ -1,20 +1,19 @@ /* * PROJECT: ReactOS Kernel - * LICENSE: GPL - See COPYING in the top level directory + * LICENSE: BSD - See COPYING.ARM in the top level directory * FILE: ntoskrnl/config/cmboot.c * PURPOSE: Configuration Manager - Boot Initialization - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + * PROGRAMMERS: ReactOS Portable Systems Group + * Alex Ionescu (alex.ionescu@reactos.org) */ -/* INCLUDES ******************************************************************/ +/* INCLUDES *******************************************************************/ #include "ntoskrnl.h" #define NDEBUG #include "debug.h" - -/* GLOBALS *******************************************************************/ - -/* FUNCTIONS *****************************************************************/ + +/* FUNCTIONS ******************************************************************/ HCELL_INDEX NTAPI @@ -124,3 +123,559 @@ CmpFindControlSet(IN PHHIVE SystemHive, /* Return the CCS Cell */ return ControlSetCell; } + +ULONG +NTAPI +CmpFindTagIndex(IN PHHIVE Hive, + IN HCELL_INDEX TagCell, + IN HCELL_INDEX GroupOrderCell, + IN PUNICODE_STRING GroupName) +{ + PCM_KEY_VALUE TagValue, Value; + HCELL_INDEX OrderCell; + PULONG TagOrder, DriverTag; + ULONG CurrentTag, Length; + PCM_KEY_NODE Node; + BOOLEAN BufferAllocated; + ASSERT(Hive->ReleaseCellRoutine == NULL); + + /* Get the tag */ + Value = HvGetCell(Hive, TagCell); + ASSERT(Value); + DriverTag = (PULONG)CmpValueToData(Hive, Value, &Length); + ASSERT(DriverTag); + + /* Get the order array */ + Node = HvGetCell(Hive, GroupOrderCell); + ASSERT(Node); + OrderCell = CmpFindValueByName(Hive, Node, GroupName); + if (OrderCell == HCELL_NIL) return -2; + + /* And read it */ + TagValue = HvGetCell(Hive, OrderCell); + CmpGetValueData(Hive, TagValue, &Length, (PVOID*)&TagOrder, &BufferAllocated, &OrderCell); + ASSERT(TagOrder); + + /* Parse each tag */ + for (CurrentTag = 1; CurrentTag <= TagOrder[0]; CurrentTag++) + { + /* Find a match */ + if (TagOrder[CurrentTag] == *DriverTag) + { + /* Found it -- return the tag */ + if (BufferAllocated) ExFreePool(TagOrder); + return CurrentTag; + } + } + + /* No matches, so assume next to last ordering */ + if (BufferAllocated) ExFreePool(TagOrder); + return -2; +} + +BOOLEAN +NTAPI +CmpAddDriverToList(IN PHHIVE Hive, + IN HCELL_INDEX DriverCell, + IN HCELL_INDEX GroupOrderCell, + IN PUNICODE_STRING RegistryPath, + IN PLIST_ENTRY BootDriverListHead) +{ + PBOOT_DRIVER_NODE DriverNode; + PBOOT_DRIVER_LIST_ENTRY DriverEntry; + PCM_KEY_NODE Node; + ULONG NameLength, Length; + HCELL_INDEX ValueCell, TagCell; + PCM_KEY_VALUE Value; + PUNICODE_STRING FileName, RegistryString; + UNICODE_STRING UnicodeString; + PULONG ErrorControl; + PWCHAR Buffer; + ASSERT(Hive->ReleaseCellRoutine == NULL); + + /* Allocate a driver node and initialize it */ + DriverNode = CmpAllocate(sizeof(BOOT_DRIVER_NODE), FALSE, TAG_CM); + if (!DriverNode) return FALSE; + DriverEntry = &DriverNode->ListEntry; + DriverEntry->RegistryPath.Buffer = NULL; + DriverEntry->FilePath.Buffer = NULL; + + /* Get the driver cell */ + Node = HvGetCell(Hive, DriverCell); + ASSERT(Node); + + /* Get the name from the cell */ + DriverNode->Name.Length = Node->Flags & KEY_COMP_NAME ? + CmpCompressedNameSize(Node->Name, Node->NameLength) : + Node->NameLength; + DriverNode->Name.MaximumLength = DriverNode->Name.Length; + NameLength = DriverNode->Name.Length; + + /* Now allocate the buffer for it and copy the name */ + DriverNode->Name.Buffer = CmpAllocate(NameLength, FALSE, TAG_CM); + if (!DriverNode->Name.Buffer) return FALSE; + if (Node->Flags & KEY_COMP_NAME) + { + /* Compressed name */ + CmpCopyCompressedName(DriverNode->Name.Buffer, + DriverNode->Name.Length, + Node->Name, + Node->NameLength); + } + else + { + /* Normal name */ + RtlCopyMemory(DriverNode->Name.Buffer, Node->Name, Node->NameLength); + } + + /* Now find the image path */ + RtlInitUnicodeString(&UnicodeString, L"ImagePath"); + ValueCell = CmpFindValueByName(Hive, Node, &UnicodeString); + if (ValueCell == HCELL_NIL) + { + /* Couldn't find it, so assume the drivers path */ + Length = sizeof(L"System32\\Drivers\\") + NameLength + sizeof(L".sys"); + + /* Allocate the path name */ + FileName = &DriverEntry->FilePath; + FileName->Length = 0; + FileName->MaximumLength = Length; + FileName->Buffer = CmpAllocate(Length, FALSE,TAG_CM); + if (!FileName->Buffer) return FALSE; + + /* Write the path name */ + RtlAppendUnicodeToString(FileName, L"System32\\Drivers\\"); + RtlAppendUnicodeStringToString(FileName, &DriverNode->Name); + RtlAppendUnicodeToString(FileName, L".sys"); + } + else + { + /* Path name exists, so grab it */ + Value = HvGetCell(Hive, ValueCell); + ASSERT(Value); + + /* Allocate and setup the path name */ + FileName = &DriverEntry->FilePath; + Buffer = (PWCHAR)CmpValueToData(Hive, Value, &Length); + FileName->MaximumLength = FileName->Length = Length; + FileName->Buffer = CmpAllocate(Length, FALSE, TAG_CM); + + /* Transfer the data */ + if (!(FileName->Buffer) || !(Buffer)) return FALSE; + RtlCopyMemory(FileName->Buffer, Buffer, Length); + } + + /* Now build the registry path */ + RegistryString = &DriverEntry->RegistryPath; + RegistryString->Length = 0; + RegistryString->MaximumLength = RegistryPath->Length + NameLength; + RegistryString->Buffer = CmpAllocate(RegistryString->MaximumLength, FALSE, TAG_CM); + if (!RegistryString->Buffer) return FALSE; + + /* Add the driver name to it */ + RtlAppendUnicodeStringToString(RegistryString, RegistryPath); + RtlAppendUnicodeStringToString(RegistryString, &DriverNode->Name); + + /* The entry is done, add it */ + InsertHeadList(BootDriverListHead, &DriverEntry->Link); + + /* Now find error control settings */ + RtlInitUnicodeString(&UnicodeString, L"ErrorControl"); + ValueCell = CmpFindValueByName(Hive, Node, &UnicodeString); + if (ValueCell == HCELL_NIL) + { + /* Couldn't find it, so assume default */ + DriverNode->ErrorControl = NormalError; + } + else + { + /* Otherwise, read whatever the data says */ + Value = HvGetCell(Hive, ValueCell); + ASSERT(Value); + ErrorControl = (PULONG)CmpValueToData(Hive, Value, &Length); + ASSERT(ErrorControl); + DriverNode->ErrorControl = *ErrorControl; + } + + /* Next, get the group cell */ + RtlInitUnicodeString(&UnicodeString, L"group"); + ValueCell = CmpFindValueByName(Hive, Node, &UnicodeString); + if (ValueCell == HCELL_NIL) + { + /* Couldn't find, so set an empty string */ + RtlInitEmptyUnicodeString(&DriverNode->Group, NULL, 0); + } + else + { + /* Found it, read the group value */ + Value = HvGetCell(Hive, ValueCell); + ASSERT(Value); + + /* Copy it into the node */ + DriverNode->Group.Buffer = (PWCHAR)CmpValueToData(Hive, Value, &Length); + if (!DriverNode->Group.Buffer) return FALSE; + DriverNode->Group.Length = Length - sizeof(UNICODE_NULL); + DriverNode->Group.MaximumLength = DriverNode->Group.Length; + } + + /* Finally, find the tag */ + RtlInitUnicodeString(&UnicodeString, L"Tag"); + TagCell = CmpFindValueByName(Hive, Node, &UnicodeString); + if (TagCell == HCELL_NIL) + { + /* No tag, so load last */ + DriverNode->Tag = -1; + } + else + { + /* Otherwise, decode it based on tag order */ + DriverNode->Tag = CmpFindTagIndex(Hive, + TagCell, + GroupOrderCell, + &DriverNode->Group); + } + + /* All done! */ + return TRUE; +} + +BOOLEAN +NTAPI +CmpIsLoadType(IN PHHIVE Hive, + IN HCELL_INDEX Cell, + IN SERVICE_LOAD_TYPE LoadType) +{ + PCM_KEY_NODE Node; + HCELL_INDEX ValueCell; + UNICODE_STRING ValueString = RTL_CONSTANT_STRING(L"Start"); + PCM_KEY_VALUE Value; + ULONG Length; + PLONG Data; + ASSERT(Hive->ReleaseCellRoutine == NULL); + + /* Open the start cell */ + Node = HvGetCell(Hive, Cell); + ASSERT(Node); + ValueCell = CmpFindValueByName(Hive, Node, &ValueString); + if (ValueCell == HCELL_NIL) return FALSE; + + /* Read the start value */ + Value = HvGetCell(Hive, ValueCell); + ASSERT(Value); + Data = (PLONG)CmpValueToData(Hive, Value, &Length); + ASSERT(Data); + + /* Return if the type matches */ + return (*Data == LoadType); +} + +BOOLEAN +NTAPI +CmpFindDrivers(IN PHHIVE Hive, + IN HCELL_INDEX ControlSet, + IN SERVICE_LOAD_TYPE LoadType, + IN PWCHAR BootFileSystem OPTIONAL, + IN PLIST_ENTRY DriverListHead) +{ + HCELL_INDEX ServicesCell, ControlCell, GroupOrderCell, DriverCell; + UNICODE_STRING Name; + ULONG i; + WCHAR Buffer[128]; + UNICODE_STRING UnicodeString, KeyPath; + PBOOT_DRIVER_NODE FsNode; + PCM_KEY_NODE ControlNode, ServicesNode, Node; + ASSERT(Hive->ReleaseCellRoutine == NULL); + + /* Open the control set key */ + ControlNode = HvGetCell(Hive, ControlSet); + ASSERT(ControlNode); + + /* Get services cell */ + RtlInitUnicodeString(&Name, L"Services"); + ServicesCell = CmpFindSubKeyByName(Hive, ControlNode, &Name); + if (ServicesCell == HCELL_NIL) return FALSE; + + /* Open services key */ + ServicesNode = HvGetCell(Hive, ServicesCell); + ASSERT(ServicesNode); + + /* Get control cell */ + RtlInitUnicodeString(&Name, L"Control"); + ControlCell = CmpFindSubKeyByName(Hive, ControlNode, &Name); + if (ControlCell == HCELL_NIL) return FALSE; + + /* Get the group order cell and read it */ + RtlInitUnicodeString(&Name, L"GroupOrderList"); + Node = HvGetCell(Hive, ControlCell); + ASSERT(Node); + GroupOrderCell = CmpFindSubKeyByName(Hive, Node, &Name); + if (GroupOrderCell == HCELL_NIL) return FALSE; + + /* Build the root registry path */ + RtlInitEmptyUnicodeString(&KeyPath, Buffer, sizeof(Buffer)); + RtlAppendUnicodeToString(&KeyPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); + + /* Find the first subkey (ie: the first driver or service) */ + i = 0; + DriverCell = CmpFindSubKeyByNumber(Hive, ServicesNode, i); + while (DriverCell != HCELL_NIL) + { + /* Make sure it's a driver of this start type */ + if (CmpIsLoadType(Hive, DriverCell, LoadType)) + { + /* Add it to the list */ + CmpAddDriverToList(Hive, + DriverCell, + GroupOrderCell, + &KeyPath, + DriverListHead); + + } + + /* Try the next subkey */ + DriverCell = CmpFindSubKeyByNumber(Hive, ServicesNode, ++i); + } + + /* Check if we have a boot file system */ + if (BootFileSystem) + { + /* Find it */ + RtlInitUnicodeString(&UnicodeString, BootFileSystem); + DriverCell = CmpFindSubKeyByName(Hive, ServicesNode, &UnicodeString); + if (DriverCell != HCELL_NIL) + { + /* Always add it to the list */ + CmpAddDriverToList(Hive, + DriverCell, + GroupOrderCell, + &KeyPath, + DriverListHead); + + /* Mark it as critical so it always loads */ + FsNode = CONTAINING_RECORD(DriverListHead->Flink, + BOOT_DRIVER_NODE, + ListEntry.Link); + FsNode->ErrorControl = SERVICE_ERROR_CRITICAL; + } + } + + /* We're done! */ + return TRUE; +} + +BOOLEAN +NTAPI +CmpDoSort(IN PLIST_ENTRY DriverListHead, + IN PUNICODE_STRING OrderList) +{ + PWCHAR Current, End = NULL; + PLIST_ENTRY NextEntry; + UNICODE_STRING GroupName; + PBOOT_DRIVER_NODE CurrentNode; + + /* We're going from end to start, so get to the last group and keep going */ + Current = &OrderList->Buffer[OrderList->Length / sizeof(WCHAR)]; + while (Current > OrderList->Buffer) + { + /* Scan the current string */ + do + { + if (*Current == UNICODE_NULL) End = Current; + } while ((*(--Current - 1) != UNICODE_NULL) && (Current != OrderList->Buffer)); + + /* This is our cleaned up string for this specific group */ + ASSERT(End != NULL); + GroupName.Length = (End - Current) * sizeof(WCHAR); + GroupName.MaximumLength = GroupName.Length; + GroupName.Buffer = Current; + + /* Now loop the driver list */ + NextEntry = DriverListHead->Flink; + while (NextEntry != DriverListHead) + { + /* Get this node */ + CurrentNode = CONTAINING_RECORD(NextEntry, + BOOT_DRIVER_NODE, + ListEntry.Link); + + /* Get the next entry now since we'll do a relink */ + NextEntry = CurrentNode->ListEntry.Link.Flink; + + /* Is there a group name and does it match the current group? */ + if ((CurrentNode->Group.Buffer) && + (RtlEqualUnicodeString(&GroupName, &CurrentNode->Group, TRUE))) + { + /* Remove from this location and re-link in the new one */ + RemoveEntryList(&CurrentNode->ListEntry.Link); + InsertHeadList(DriverListHead, &CurrentNode->ListEntry.Link); + } + } + + /* Move on */ + Current--; + } + + /* All done */ + return TRUE; +} + +BOOLEAN +NTAPI +CmpSortDriverList(IN PHHIVE Hive, + IN HCELL_INDEX ControlSet, + IN PLIST_ENTRY DriverListHead) +{ + HCELL_INDEX Controls, GroupOrder, ListCell; + UNICODE_STRING Name, DependList; + PCM_KEY_VALUE ListNode; + ULONG Length; + PCM_KEY_NODE Node; + ASSERT(Hive->ReleaseCellRoutine == NULL); + + /* Open the control key */ + Node = HvGetCell(Hive, ControlSet); + ASSERT(Node); + RtlInitUnicodeString(&Name, L"Control"); + Controls = CmpFindSubKeyByName(Hive, Node, &Name); + if (Controls == HCELL_NIL) return FALSE; + + /* Open the service group order */ + Node = HvGetCell(Hive, Controls); + ASSERT(Node); + RtlInitUnicodeString(&Name, L"ServiceGroupOrder"); + GroupOrder = CmpFindSubKeyByName(Hive, Node, &Name); + if (GroupOrder == HCELL_NIL) return FALSE; + + /* Open the list key */ + Node = HvGetCell(Hive, GroupOrder); + ASSERT(Node); + RtlInitUnicodeString(&Name, L"list"); + ListCell = CmpFindValueByName(Hive, Node, &Name); + if (ListCell == HCELL_NIL) return FALSE; + + /* Now read the actual list */ + ListNode = HvGetCell(Hive, ListCell); + ASSERT(ListNode); + if (ListNode->Type != REG_MULTI_SZ) return FALSE; + + /* Copy it into a buffer */ + DependList.Buffer = (PWCHAR)CmpValueToData(Hive, ListNode, &Length); + if (!DependList.Buffer) return FALSE; + DependList.Length = DependList.MaximumLength = Length - sizeof(UNICODE_NULL); + + /* And start the recurive sort algorithm */ + return CmpDoSort(DriverListHead, &DependList); +} + +BOOLEAN +NTAPI +CmpOrderGroup(IN PBOOT_DRIVER_NODE StartNode, + IN PBOOT_DRIVER_NODE EndNode) +{ + PBOOT_DRIVER_NODE CurrentNode, PreviousNode; + PLIST_ENTRY ListEntry; + + /* Base case, nothing to do */ + if (StartNode == EndNode) return TRUE; + + /* Loop the nodes */ + CurrentNode = StartNode; + do + { + /* Save this as the previous node */ + PreviousNode = CurrentNode; + + /* And move to the next one */ + ListEntry = CurrentNode->ListEntry.Link.Flink; + CurrentNode = CONTAINING_RECORD(ListEntry, + BOOT_DRIVER_NODE, + ListEntry.Link); + + /* Check if the previous driver had a bigger tag */ + if (PreviousNode->Tag > CurrentNode->Tag) + { + /* Check if we need to update the tail */ + if (CurrentNode == EndNode) + { + /* Update the tail */ + ListEntry = CurrentNode->ListEntry.Link.Blink; + EndNode = CONTAINING_RECORD(ListEntry, + BOOT_DRIVER_NODE, + ListEntry.Link); + } + + /* Remove this driver since we need to move it */ + RemoveEntryList(&CurrentNode->ListEntry.Link); + + /* Keep looping until we find a driver with a lower tag than ours */ + while ((PreviousNode->Tag > CurrentNode->Tag) && (PreviousNode != StartNode)) + { + /* We'll be re-inserted at this spot */ + ListEntry = PreviousNode->ListEntry.Link.Blink; + PreviousNode = CONTAINING_RECORD(ListEntry, + BOOT_DRIVER_NODE, + ListEntry.Link); + } + + /* Do the insert in the new location */ + InsertTailList(&PreviousNode->ListEntry.Link, &CurrentNode->ListEntry.Link); + + /* Update the head, if needed */ + if (PreviousNode == StartNode) StartNode = CurrentNode; + } + } while (CurrentNode != EndNode); + + /* All done */ + return TRUE; +} + +BOOLEAN +NTAPI +CmpResolveDriverDependencies(IN PLIST_ENTRY DriverListHead) +{ + PLIST_ENTRY NextEntry; + PBOOT_DRIVER_NODE StartNode, EndNode, CurrentNode; + + /* Loop the list */ + NextEntry = DriverListHead->Flink; + while (NextEntry != DriverListHead) + { + /* Find the first entry */ + StartNode = CONTAINING_RECORD(NextEntry, + BOOT_DRIVER_NODE, + ListEntry.Link); + do + { + /* Find the last entry */ + EndNode = CONTAINING_RECORD(NextEntry, + BOOT_DRIVER_NODE, + ListEntry.Link); + + /* Get the next entry */ + NextEntry = NextEntry->Flink; + CurrentNode = CONTAINING_RECORD(NextEntry, + BOOT_DRIVER_NODE, + ListEntry.Link); + + /* If the next entry is back to the top, break out */ + if (NextEntry == DriverListHead) break; + + /* Otherwise, check if this entry is equal */ + if (!RtlEqualUnicodeString(&StartNode->Group, + &CurrentNode->Group, + TRUE)) + { + /* It is, so we've detected a cycle, break out */ + break; + } + } while (NextEntry != DriverListHead); + + /* Now we have the correct start and end pointers, so do the sort */ + CmpOrderGroup(StartNode, EndNode); + } + + /* We're done */ + return TRUE; +} + +/* EOF */ diff --git a/ntoskrnl/config/cmhvlist.c b/ntoskrnl/config/cmhvlist.c index f4e97814bbd..8fb2636f3dc 100644 --- a/ntoskrnl/config/cmhvlist.c +++ b/ntoskrnl/config/cmhvlist.c @@ -14,4 +14,11 @@ /* FUNCTIONS *****************************************************************/ +NTSTATUS +NTAPI +CmpAddToHiveFileList(IN PCMHIVE Hive) +{ + return STATUS_SUCCESS; +} + /* EOF */ \ No newline at end of file diff --git a/ntoskrnl/config/cminit.c b/ntoskrnl/config/cminit.c index 154ba1530b6..be7efc1660f 100644 --- a/ntoskrnl/config/cminit.c +++ b/ntoskrnl/config/cminit.c @@ -119,12 +119,10 @@ CmpInitializeHive(OUT PCMHIVE *RegistryHive, if (!Hive->ViewLock) return STATUS_INSUFFICIENT_RESOURCES; /* Allocate the flush lock */ -#if 0 Hive->FlusherLock = ExAllocatePoolWithTag(NonPagedPool, sizeof(ERESOURCE), TAG_CM); if (!Hive->FlusherLock) return STATUS_INSUFFICIENT_RESOURCES; -#endif /* Setup the handles */ Hive->FileHandles[HFILE_TYPE_PRIMARY] = Primary; @@ -136,7 +134,7 @@ CmpInitializeHive(OUT PCMHIVE *RegistryHive, Hive->ViewLockOwner = NULL; /* Initialize the flush lock */ - ExInitializePushLock((PULONG_PTR)&Hive->FlusherLock); + ExInitializeResourceLite(Hive->FlusherLock); /* Setup hive locks */ ExInitializePushLock((PULONG_PTR)&Hive->HiveLock); @@ -193,9 +191,7 @@ CmpInitializeHive(OUT PCMHIVE *RegistryHive, { /* Clear allocations and fail */ ExFreePool(Hive->ViewLock); -#if 0 ExFreePool(Hive->FlusherLock); -#endif ExFreePool(Hive); return Status; } @@ -211,9 +207,7 @@ CmpInitializeHive(OUT PCMHIVE *RegistryHive, { /* Free all alocations */ ExFreePool(Hive->ViewLock); -#if 0 ExFreePool(Hive->FlusherLock); -#endif ExFreePool(Hive); return STATUS_REGISTRY_CORRUPT; } diff --git a/ntoskrnl/config/cmkcbncb.c b/ntoskrnl/config/cmkcbncb.c index 5e7060d61c4..a26de07cf1b 100644 --- a/ntoskrnl/config/cmkcbncb.c +++ b/ntoskrnl/config/cmkcbncb.c @@ -1135,3 +1135,62 @@ DelistKeyBodyFromKCB(IN PCM_KEY_BODY KeyBody, /* Unlock it it if we did a manual lock */ if (!LockHeld) CmpReleaseKcbLock(KeyBody->KeyControlBlock); } + +VOID +NTAPI +CmpFlushNotifiesOnKeyBodyList(IN PCM_KEY_CONTROL_BLOCK Kcb, + IN BOOLEAN LockHeld) +{ + PLIST_ENTRY NextEntry, ListHead; + PCM_KEY_BODY KeyBody; + + /* Sanity check */ + LockHeld ? CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK() : CmpIsKcbLockedExclusive(Kcb); + while (TRUE) + { + /* Is the list empty? */ + ListHead = &Kcb->KeyBodyListHead; + if (!IsListEmpty(ListHead)) + { + /* Loop the list */ + NextEntry = ListHead->Flink; + while (NextEntry != ListHead) + { + /* Get the key body */ + KeyBody = CONTAINING_RECORD(NextEntry, CM_KEY_BODY, KeyBodyList); + ASSERT(KeyBody->Type == '20yk'); + + /* Check for notifications */ + if (KeyBody->NotifyBlock) + { + /* Is the lock held? */ + if (LockHeld) + { + /* Flush it */ + CmpFlushNotify(KeyBody, LockHeld); + ASSERT(KeyBody->NotifyBlock == NULL); + continue; + } + + /* Lock isn't held, so we need to take a reference */ + if (ObReferenceObjectSafe(KeyBody)) + { + /* Now we can flush */ + CmpFlushNotify(KeyBody, LockHeld); + ASSERT(KeyBody->NotifyBlock == NULL); + + /* Release the reference we took */ + ObDereferenceObjectDeferDelete(KeyBody); + continue; + } + } + + /* Try the next entry */ + NextEntry = NextEntry->Flink; + } + } + + /* List has been parsed, exit */ + break; + } +} diff --git a/ntoskrnl/config/cmparse.c b/ntoskrnl/config/cmparse.c index 42d737908a0..82635445dda 100644 --- a/ntoskrnl/config/cmparse.c +++ b/ntoskrnl/config/cmparse.c @@ -414,15 +414,6 @@ CmpDoCreate(IN PHHIVE Hive, LARGE_INTEGER TimeStamp; PCM_KEY_NODE KeyNode; - /* Sanity check */ -#if 0 - ASSERT((CmpIsKcbLockedExclusive(ParentKcb) == TRUE) || - (CmpTestRegistryLockExclusive() == TRUE)); -#endif - - /* Acquire the flusher lock */ - ExAcquirePushLockShared((PVOID)&((PCMHIVE)Hive)->FlusherLock); - /* Check if the parent is being deleted */ if (ParentKcb->Delete) { @@ -555,7 +546,6 @@ CmpDoCreate(IN PHHIVE Hive, Exit: /* Release the flusher lock and return status */ - ExReleasePushLock((PVOID)&((PCMHIVE)Hive)->FlusherLock); return Status; } @@ -747,9 +737,6 @@ CmpCreateLinkNode(IN PHHIVE Hive, LARGE_INTEGER TimeStamp; PCM_KEY_NODE KeyNode; PCM_KEY_CONTROL_BLOCK Kcb = ParentKcb; -#if 0 - CMP_ASSERT_REGISTRY_LOCK(); -#endif /* Link nodes only allowed on the master */ if (Hive != &CmiVolatileHive->Hive) @@ -759,10 +746,6 @@ CmpCreateLinkNode(IN PHHIVE Hive, return STATUS_ACCESS_DENIED; } - /* Acquire the flusher locks */ - ExAcquirePushLockShared((PVOID)&((PCMHIVE)Hive)->FlusherLock); - ExAcquirePushLockShared((PVOID)&((PCMHIVE)Context->ChildHive.KeyHive)->FlusherLock); - /* Check if the parent is being deleted */ if (ParentKcb->Delete) { @@ -964,8 +947,6 @@ CmpCreateLinkNode(IN PHHIVE Hive, Exit: /* Release the flusher locks and return status */ - ExReleasePushLock((PVOID)&((PCMHIVE)Context->ChildHive.KeyHive)->FlusherLock); - ExReleasePushLock((PVOID)&((PCMHIVE)Hive)->FlusherLock); return Status; } diff --git a/ntoskrnl/config/cmsysini.c b/ntoskrnl/config/cmsysini.c index 0326e88e619..3587efe7326 100644 --- a/ntoskrnl/config/cmsysini.c +++ b/ntoskrnl/config/cmsysini.c @@ -1,12 +1,13 @@ /* * PROJECT: ReactOS Kernel - * LICENSE: GPL - See COPYING in the top level directory + * LICENSE: BSD - See COPYING.ARM in the top level directory * FILE: ntoskrnl/config/cmsysini.c * PURPOSE: Configuration Manager - System Initialization Code - * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + * PROGRAMMERS: ReactOS Portable Systems Group + * Alex Ionescu (alex.ionescu@reactos.org) */ -/* INCLUDES ******************************************************************/ +/* INCLUDES *******************************************************************/ #include "ntoskrnl.h" #define NDEBUG @@ -33,7 +34,7 @@ ULONG CmpTraceLevel = 0; extern LONG CmpFlushStarveWriters; extern BOOLEAN CmFirstTime; -/* FUNCTIONS *****************************************************************/ +/* FUNCTIONS ******************************************************************/ VOID NTAPI @@ -1574,6 +1575,162 @@ CmInitSystem1(VOID) return TRUE; } +VOID +NTAPI +CmpFreeDriverList(IN PHHIVE Hive, + IN PLIST_ENTRY DriverList) +{ + PLIST_ENTRY NextEntry, OldEntry; + PBOOT_DRIVER_NODE DriverNode; + PAGED_CODE(); + + /* Parse the current list */ + NextEntry = DriverList->Flink; + while (NextEntry != DriverList) + { + /* Get the driver node */ + DriverNode = CONTAINING_RECORD(NextEntry, BOOT_DRIVER_NODE, ListEntry.Link); + + /* Get the next entry now, since we're going to free it later */ + OldEntry = NextEntry; + NextEntry = NextEntry->Flink; + + /* Was there a name? */ + if (DriverNode->Name.Buffer) + { + /* Free it */ + CmpFree(DriverNode->Name.Buffer, DriverNode->Name.Length); + } + + /* Was there a registry path? */ + if (DriverNode->ListEntry.RegistryPath.Buffer) + { + /* Free it */ + CmpFree(DriverNode->ListEntry.RegistryPath.Buffer, + DriverNode->ListEntry.RegistryPath.MaximumLength); + } + + /* Was there a file path? */ + if (DriverNode->ListEntry.FilePath.Buffer) + { + /* Free it */ + CmpFree(DriverNode->ListEntry.FilePath.Buffer, + DriverNode->ListEntry.FilePath.MaximumLength); + } + + /* Now free the node, and move on */ + CmpFree(OldEntry, sizeof(BOOT_DRIVER_NODE)); + } +} + +PUNICODE_STRING* +NTAPI +CmGetSystemDriverList(VOID) +{ + LIST_ENTRY DriverList; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + PCM_KEY_BODY KeyBody; + PHHIVE Hive; + HCELL_INDEX RootCell, ControlCell; + HANDLE KeyHandle; + UNICODE_STRING KeyName; + PLIST_ENTRY NextEntry; + ULONG i; + PUNICODE_STRING* ServicePath = NULL; + BOOLEAN Success, AutoSelect; + PBOOT_DRIVER_LIST_ENTRY DriverEntry; + PAGED_CODE(); + + /* Initialize the driver list */ + InitializeListHead(&DriverList); + + /* Open the system hive key */ + RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\System"); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes); + if (!NT_SUCCESS(Status)) return NULL; + + /* Reference the key object to get the root hive/cell to access directly */ + Status = ObReferenceObjectByHandle(KeyHandle, + KEY_QUERY_VALUE, + CmpKeyObjectType, + KernelMode, + (PVOID*)&KeyBody, + NULL); + if (!NT_SUCCESS(Status)) + { + /* Fail */ + NtClose(KeyHandle); + return NULL; + } + + /* Do all this under the registry lock */ + CmpLockRegistryExclusive(); + + /* Get the hive and key cell */ + Hive = KeyBody->KeyControlBlock->KeyHive; + RootCell = KeyBody->KeyControlBlock->KeyCell; + + /* Open the current control set key */ + RtlInitUnicodeString(&KeyName, L"Current"); + ControlCell = CmpFindControlSet(Hive, RootCell, &KeyName, &AutoSelect); + if (ControlCell == HCELL_NIL) goto EndPath; + + /* Find all system drivers */ + Success = CmpFindDrivers(Hive, ControlCell, SystemLoad, NULL, &DriverList); + if (!Success) goto EndPath; + + /* Sort by group/tag */ + if (!CmpSortDriverList(Hive, ControlCell, &DriverList)) goto EndPath; + + /* Remove circular dependencies (cycles) and sort */ + if (!CmpResolveDriverDependencies(&DriverList)) goto EndPath; + + /* Loop the list to count drivers */ + for (i = 0, NextEntry = DriverList.Flink; + NextEntry != &DriverList; + i++, NextEntry = NextEntry->Flink); + + /* Allocate the array */ + ServicePath = ExAllocatePool(NonPagedPool, (i + 1) * sizeof(PUNICODE_STRING)); + if (!ServicePath) KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 2, 1, 0, 0); + + /* Loop the driver list */ + for (i = 0, NextEntry = DriverList.Flink; + NextEntry != &DriverList; + i++, NextEntry = NextEntry->Flink) + { + /* Get the entry */ + DriverEntry = CONTAINING_RECORD(NextEntry, BOOT_DRIVER_LIST_ENTRY, Link); + + /* Allocate the path for the caller and duplicate the registry path */ + ServicePath[i] = ExAllocatePool(NonPagedPool, sizeof(UNICODE_STRING)); + RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, + &DriverEntry->RegistryPath, + ServicePath[i]); + } + + /* Terminate the list */ + ServicePath[i] = NULL; + +EndPath: + /* Free the driver list if we had one */ + if (!IsListEmpty(&DriverList)) CmpFreeDriverList(Hive, &DriverList); + + /* Unlock the registry */ + CmpUnlockRegistry(); + + /* Close the key handle and dereference the object, then return the path */ + ObDereferenceObject(KeyBody); + NtClose(KeyHandle); + return ServicePath; +} + VOID NTAPI CmpLockRegistryExclusive(VOID) @@ -1771,3 +1928,5 @@ CmShutdownSystem(VOID) if (!CmFirstTime) CmpShutdownWorkers(); CmpDoFlushAll(TRUE); } + +/* EOF */ diff --git a/ntoskrnl/include/internal/cm.h b/ntoskrnl/include/internal/cm.h index 4880dc08026..62f4010f20b 100644 --- a/ntoskrnl/include/internal/cm.h +++ b/ntoskrnl/include/internal/cm.h @@ -1522,6 +1522,40 @@ CmSetLazyFlushState( IN BOOLEAN Enable ); +// +// Driver List Routines +// +PUNICODE_STRING* +NTAPI +CmGetSystemDriverList( + VOID +); + +BOOLEAN +NTAPI +CmpFindDrivers( + IN PHHIVE Hive, + IN HCELL_INDEX ControlSet, + IN SERVICE_LOAD_TYPE LoadType, + IN PWSTR BootFileSystem OPTIONAL, + IN PLIST_ENTRY DriverListHead +); + + +BOOLEAN +NTAPI +CmpSortDriverList( + IN PHHIVE Hive, + IN HCELL_INDEX ControlSet, + IN PLIST_ENTRY DriverListHead +); + +BOOLEAN +NTAPI +CmpResolveDriverDependencies( + IN PLIST_ENTRY DriverListHead +); + // // Global variables accessible from all of Cm // diff --git a/ntoskrnl/include/internal/io.h b/ntoskrnl/include/internal/io.h index c8b671693af..dc80ff249a5 100644 --- a/ntoskrnl/include/internal/io.h +++ b/ntoskrnl/include/internal/io.h @@ -395,6 +395,33 @@ typedef struct _LOAD_UNLOAD_PARAMS PDRIVER_OBJECT DriverObject; } LOAD_UNLOAD_PARAMS, *PLOAD_UNLOAD_PARAMS; +// +// Boot Driver List Entry +// +typedef struct _DRIVER_INFORMATION +{ + LIST_ENTRY Link; + PDRIVER_OBJECT DriverObject; + PBOOT_DRIVER_LIST_ENTRY DataTableEntry; + HANDLE ServiceHandle; + USHORT TagPosition; + ULONG Failed; + ULONG Processed; + NTSTATUS Status; +} DRIVER_INFORMATION, *PDRIVER_INFORMATION; + +// +// Boot Driver Node +// +typedef struct _BOOT_DRIVER_NODE +{ + BOOT_DRIVER_LIST_ENTRY ListEntry; + UNICODE_STRING Group; + UNICODE_STRING Name; + ULONG Tag; + ULONG ErrorControl; +} BOOT_DRIVER_NODE, *PBOOT_DRIVER_NODE; + // // List of Bus Type GUIDs // @@ -605,6 +632,43 @@ IopGetRegistryValue(IN HANDLE Handle, OUT PKEY_VALUE_FULL_INFORMATION *Information); +// +// PnP Routines +// +NTSTATUS +NTAPI +PiInitCacheGroupInformation( + VOID +); + +USHORT +NTAPI +PpInitGetGroupOrderIndex( + IN HANDLE ServiceHandle +); + +USHORT +NTAPI +PipGetDriverTagPriority( + IN HANDLE ServiceHandle +); + +NTSTATUS +NTAPI +PnpRegMultiSzToUnicodeStrings( + IN PKEY_VALUE_FULL_INFORMATION KeyValueInformation, + OUT PUNICODE_STRING *UnicodeStringList, + OUT PULONG UnicodeStringCount +); + +BOOLEAN +NTAPI +PnpRegSzToString( + IN PWCHAR RegSzData, + IN ULONG RegSzLength, + OUT PUSHORT StringLength OPTIONAL +); + // // Initialization Routines // @@ -852,7 +916,8 @@ PnpRootDriverEntry( NTSTATUS PnpRootCreateDevice( IN PUNICODE_STRING ServiceName, - IN OUT PDEVICE_OBJECT *PhysicalDeviceObject + OUT PDEVICE_OBJECT *PhysicalDeviceObject, + OUT OPTIONAL PUNICODE_STRING FullInstancePath ); // diff --git a/ntoskrnl/io/iomgr/deviface.c b/ntoskrnl/io/iomgr/deviface.c index cc6d5444de3..d5b2246f31f 100644 --- a/ntoskrnl/io/iomgr/deviface.c +++ b/ntoskrnl/io/iomgr/deviface.c @@ -50,7 +50,159 @@ IoOpenDeviceInterfaceRegistryKey(IN PUNICODE_STRING SymbolicLinkName, IN ACCESS_MASK DesiredAccess, OUT PHANDLE DeviceInterfaceKey) { - return STATUS_NOT_IMPLEMENTED; + WCHAR StrBuff[MAX_PATH], PathBuff[MAX_PATH]; + PWCHAR Guid, RefString; + UNICODE_STRING DevParamU = RTL_CONSTANT_STRING(L"\\Device Parameters"); + UNICODE_STRING PrefixU = RTL_CONSTANT_STRING(L"\\??\\"); + UNICODE_STRING KeyPath, KeyName; + UNICODE_STRING MatchableGuid; + UNICODE_STRING GuidString; + HANDLE GuidKey, hInterfaceKey; + ULONG Index = 0; + PKEY_BASIC_INFORMATION KeyInformation; + ULONG KeyInformationLength; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + ULONG RequiredLength; + + swprintf(StrBuff, L"##?#%s", &SymbolicLinkName->Buffer[PrefixU.Length / sizeof(WCHAR)]); + + RefString = wcsstr(StrBuff, L"\\"); + if (RefString) + { + RefString[0] = 0; + } + + RtlInitUnicodeString(&MatchableGuid, StrBuff); + + Guid = wcsstr(StrBuff, L"{"); + if (!Guid) + return STATUS_OBJECT_NAME_NOT_FOUND; + + KeyPath.Buffer = PathBuff; + KeyPath.Length = 0; + KeyPath.MaximumLength = MAX_PATH * sizeof(WCHAR); + + GuidString.Buffer = Guid; + GuidString.Length = GuidString.MaximumLength = 38 * sizeof(WCHAR); + + RtlAppendUnicodeToString(&KeyPath, BaseKeyString); + RtlAppendUnicodeStringToString(&KeyPath, &GuidString); + + InitializeObjectAttributes(&ObjectAttributes, + &KeyPath, + OBJ_CASE_INSENSITIVE, + 0, + NULL); + + Status = ZwOpenKey(&GuidKey, KEY_CREATE_SUB_KEY, &ObjectAttributes); + if (!NT_SUCCESS(Status)) + return Status; + + while (TRUE) + { + Status = ZwEnumerateKey(GuidKey, + Index, + KeyBasicInformation, + NULL, + 0, + &RequiredLength); + if (Status == STATUS_NO_MORE_ENTRIES) + break; + else if (Status == STATUS_BUFFER_TOO_SMALL) + { + KeyInformationLength = RequiredLength; + KeyInformation = ExAllocatePool(PagedPool, KeyInformationLength); + if (!KeyInformation) + { + ZwClose(GuidKey); + return STATUS_INSUFFICIENT_RESOURCES; + } + + Status = ZwEnumerateKey(GuidKey, + Index, + KeyBasicInformation, + KeyInformation, + KeyInformationLength, + &RequiredLength); + } + else + { + ZwClose(GuidKey); + return STATUS_OBJECT_PATH_NOT_FOUND; + } + Index++; + + if (!NT_SUCCESS(Status)) + { + ZwClose(GuidKey); + return Status; + } + + KeyName.Length = KeyName.MaximumLength = KeyInformation->NameLength; + KeyName.Buffer = KeyInformation->Name; + + if (!RtlEqualUnicodeString(&KeyName, &MatchableGuid, TRUE)) + { + ExFreePool(KeyInformation); + continue; + } + + KeyPath.Length = 0; + RtlAppendUnicodeStringToString(&KeyPath, &KeyName); + RtlAppendUnicodeToString(&KeyPath, L"\\"); + + /* check for presence of a reference string */ + if (RefString) + { + /* append reference string */ + RefString[0] = L'#'; + RtlInitUnicodeString(&KeyName, RefString); + } + else + { + /* no reference string */ + RtlInitUnicodeString(&KeyName, L"#"); + } + RtlAppendUnicodeStringToString(&KeyPath, &KeyName); + + /* initialize reference string attributes */ + InitializeObjectAttributes(&ObjectAttributes, + &KeyPath, + OBJ_CASE_INSENSITIVE, + GuidKey, + NULL); + + /* now open device interface key */ + Status = ZwOpenKey(&hInterfaceKey, KEY_CREATE_SUB_KEY, &ObjectAttributes); + + if (NT_SUCCESS(Status)) + { + /* check if it provides a DeviceParameters key */ + InitializeObjectAttributes(&ObjectAttributes, &DevParamU, OBJ_CASE_INSENSITIVE, hInterfaceKey, NULL); + + Status = ZwCreateKey(DeviceInterfaceKey, DesiredAccess, &ObjectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, NULL); + + if (NT_SUCCESS(Status)) + { + /* DeviceParameters key present */ + ZwClose(hInterfaceKey); + } + else + { + /* fall back to device interface */ + *DeviceInterfaceKey = hInterfaceKey; + Status = STATUS_SUCCESS; + } + } + + /* close class key */ + ZwClose(GuidKey); + ExFreePool(KeyInformation); + return Status; + } + + return STATUS_OBJECT_PATH_NOT_FOUND; } /*++ @@ -909,6 +1061,7 @@ IoRegisterDeviceInterface(IN PDEVICE_OBJECT PhysicalDeviceObject, RtlAppendUnicodeStringToString(SymbolicLinkName, ReferenceString); } SymbolicLinkName->Buffer[SymbolicLinkName->Length/sizeof(WCHAR)] = L'\0'; + SymbolicLinkName->Length += sizeof(WCHAR); /* Write symbolic link name in registry */ SymbolicLinkName->Buffer[1] = '\\'; diff --git a/ntoskrnl/io/iomgr/driver.c b/ntoskrnl/io/iomgr/driver.c index ef1b78969fb..18202bfd5e4 100644 --- a/ntoskrnl/io/iomgr/driver.c +++ b/ntoskrnl/io/iomgr/driver.c @@ -34,6 +34,9 @@ POBJECT_TYPE IoDriverObjectType = NULL; extern BOOLEAN ExpInTextModeSetup; extern BOOLEAN PnpSystemInit; +USHORT IopGroupIndex; +PLIST_ENTRY IopGroupTable; + /* PRIVATE FUNCTIONS **********************************************************/ NTSTATUS NTAPI @@ -197,6 +200,7 @@ IopDisplayLoadingMessage(PUNICODE_STRING ServiceName) UNICODE_STRING DotSys = RTL_CONSTANT_STRING(L".SYS"); if (ExpInTextModeSetup) return; + if (!KeLoaderBlock) return; RtlUpcaseUnicodeString(ServiceName, ServiceName, FALSE); snprintf(TextBuffer, sizeof(TextBuffer), "%s%sSystem32\\Drivers\\%wZ%s\n", @@ -880,14 +884,17 @@ VOID FASTCALL IopInitializeBootDrivers(VOID) { - PLIST_ENTRY ListHead, NextEntry; + PLIST_ENTRY ListHead, NextEntry, NextEntry2; PLDR_DATA_TABLE_ENTRY LdrEntry; PDEVICE_NODE DeviceNode; PDRIVER_OBJECT DriverObject; LDR_DATA_TABLE_ENTRY ModuleObject; NTSTATUS Status; UNICODE_STRING DriverName; - + ULONG i, Index; + PDRIVER_INFORMATION DriverInfo, DriverInfoTag; + HANDLE KeyHandle; + PBOOT_DRIVER_LIST_ENTRY BootEntry; DPRINT("IopInitializeBootDrivers()\n"); /* Use IopRootDeviceNode for now */ @@ -931,6 +938,19 @@ IopInitializeBootDrivers(VOID) return; } + /* Get highest group order index */ + IopGroupIndex = PpInitGetGroupOrderIndex(NULL); + if (IopGroupIndex == 0xFFFF) ASSERT(FALSE); + + /* Allocate the group table */ + IopGroupTable = ExAllocatePoolWithTag(PagedPool, + IopGroupIndex * sizeof(LIST_ENTRY), + TAG_IO); + if (IopGroupTable == NULL) ASSERT(FALSE); + + /* Initialize the group table lists */ + for (i = 0; i < IopGroupIndex; i++) InitializeListHead(&IopGroupTable[i]); + /* Loop the boot modules */ ListHead = &KeLoaderBlock->LoadOrderListHead; NextEntry = ListHead->Flink; @@ -940,19 +960,83 @@ IopInitializeBootDrivers(VOID) LdrEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); - - /* - * HACK: Make sure we're loading a driver - * (we should be using BootDriverListHead!) - */ - if (wcsstr(_wcsupr(LdrEntry->BaseDllName.Buffer), L".SYS")) + + /* Check if the DLL needs to be initialized */ + if (LdrEntry->Flags & LDRP_DRIVER_DEPENDENT_DLL) { - /* Make sure we didn't load this driver already */ - if (!(LdrEntry->Flags & LDRP_ENTRY_INSERTED)) + /* Call its entrypoint */ + MmCallDllInitialize(LdrEntry, NULL); + } + + /* Go to the next driver */ + NextEntry = NextEntry->Flink; + } + + /* Loop the boot drivers */ + ListHead = &KeLoaderBlock->BootDriverListHead; + NextEntry = ListHead->Flink; + while (ListHead != NextEntry) + { + /* Get the entry */ + BootEntry = CONTAINING_RECORD(NextEntry, + BOOT_DRIVER_LIST_ENTRY, + Link); + + /* Get the driver loader entry */ + LdrEntry = BootEntry->LdrEntry; + + /* Allocate our internal accounting structure */ + DriverInfo = ExAllocatePoolWithTag(PagedPool, + sizeof(DRIVER_INFORMATION), + TAG_IO); + if (DriverInfo) + { + /* Zero it and initialize it */ + RtlZeroMemory(DriverInfo, sizeof(DRIVER_INFORMATION)); + InitializeListHead(&DriverInfo->Link); + DriverInfo->DataTableEntry = BootEntry; + + /* Open the registry key */ + Status = IopOpenRegistryKeyEx(&KeyHandle, + NULL, + &BootEntry->RegistryPath, + KEY_READ); + if ((NT_SUCCESS(Status)) || /* ReactOS HACK for SETUPLDR */ + ((KeLoaderBlock->SetupLdrBlock) && (KeyHandle = (PVOID)1))) { - DPRINT("Initializing bootdriver %wZ\n", &LdrEntry->BaseDllName); - /* Initialize it */ - IopInitializeBuiltinDriver(LdrEntry); + /* Save the handle */ + DriverInfo->ServiceHandle = KeyHandle; + + /* Get the group oder index */ + Index = PpInitGetGroupOrderIndex(KeyHandle); + + /* Get the tag position */ + DriverInfo->TagPosition = PipGetDriverTagPriority(KeyHandle); + + /* Insert it into the list, at the right place */ + ASSERT(Index < IopGroupIndex); + NextEntry2 = IopGroupTable[Index].Flink; + while (NextEntry2 != &IopGroupTable[Index]) + { + /* Get the driver info */ + DriverInfoTag = CONTAINING_RECORD(NextEntry2, + DRIVER_INFORMATION, + Link); + + /* Check if we found the right tag position */ + if (DriverInfoTag->TagPosition > DriverInfo->TagPosition) + { + /* We're done */ + break; + } + + /* Next entry */ + NextEntry2 = NextEntry2->Flink; + } + + /* Insert us right before the next entry */ + NextEntry2 = NextEntry2->Blink; + InsertHeadList(NextEntry2, &DriverInfo->Link); } } @@ -960,10 +1044,65 @@ IopInitializeBootDrivers(VOID) NextEntry = NextEntry->Flink; } + /* Loop each group index */ + for (i = 0; i < IopGroupIndex; i++) + { + /* Loop each group table */ + NextEntry = IopGroupTable[i].Flink; + while (NextEntry != &IopGroupTable[i]) + { + /* Get the entry */ + DriverInfo = CONTAINING_RECORD(NextEntry, + DRIVER_INFORMATION, + Link); + + /* Get the driver loader entry */ + LdrEntry = DriverInfo->DataTableEntry->LdrEntry; + + /* Initialize it */ + IopInitializeBuiltinDriver(LdrEntry); + + /* Next entry */ + NextEntry = NextEntry->Flink; + } + } + /* In old ROS, the loader list became empty after this point. Simulate. */ InitializeListHead(&KeLoaderBlock->LoadOrderListHead); } +VOID +FASTCALL +IopInitializeSystemDrivers(VOID) +{ + PUNICODE_STRING *DriverList, *SavedList; + + /* No system drivers on the boot cd */ + if (KeLoaderBlock->SetupLdrBlock) return; + + /* Get the driver list */ + SavedList = DriverList = CmGetSystemDriverList(); + ASSERT(DriverList); + + /* Loop it */ + while (*DriverList) + { + /* Load the driver */ + ZwLoadDriver(*DriverList); + + /* Free the entry */ + RtlFreeUnicodeString(*DriverList); + ExFreePool(*DriverList); + + /* Next entry */ + InbvIndicateProgress(); + DriverList++; + } + + /* Free the list */ + ExFreePool(SavedList); +} + /* * IopUnloadDriver * @@ -1685,6 +1824,8 @@ IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams) cur--; } + IopDisplayLoadingMessage(&ServiceName); + /* * Get service type. */ diff --git a/ntoskrnl/io/iomgr/drvrlist.c b/ntoskrnl/io/iomgr/drvrlist.c deleted file mode 100644 index e15aab2a2cd..00000000000 --- a/ntoskrnl/io/iomgr/drvrlist.c +++ /dev/null @@ -1,561 +0,0 @@ -/* - * PROJECT: ReactOS Kernel - * LICENSE: GPL - See COPYING in the top level directory - * FILE: ntoskrnl/io/iomgr/drvrlist.c - * PURPOSE: Driver List support for Grouping, Tagging, Sorting, etc. - * PROGRAMMERS: - */ - -/* INCLUDES *******************************************************************/ - -#include -#define NDEBUG -#include - -typedef struct _SERVICE_GROUP -{ - LIST_ENTRY GroupListEntry; - UNICODE_STRING GroupName; - BOOLEAN ServicesRunning; - ULONG TagCount; - PULONG TagArray; -} SERVICE_GROUP, *PSERVICE_GROUP; - -typedef struct _SERVICE -{ - LIST_ENTRY ServiceListEntry; - UNICODE_STRING ServiceName; - UNICODE_STRING RegistryPath; - UNICODE_STRING ServiceGroup; - UNICODE_STRING ImagePath; - - ULONG Start; - ULONG Type; - ULONG ErrorControl; - ULONG Tag; - -/* BOOLEAN ServiceRunning;*/ // needed ?? -} SERVICE, *PSERVICE; - -#define TAG_RTLREGISTRY 'vrqR' - -/* GLOBALS ********************************************************************/ - -LIST_ENTRY GroupListHead = {NULL, NULL}; -LIST_ENTRY ServiceListHead = {NULL, NULL}; -extern BOOLEAN NoGuiBoot; - -VOID -FASTCALL -INIT_FUNCTION -IopDisplayLoadingMessage(PUNICODE_STRING ServiceName); - -/* PRIVATE FUNCTIONS **********************************************************/ - -static NTSTATUS NTAPI -IopGetGroupOrderList(PWSTR ValueName, - ULONG ValueType, - PVOID ValueData, - ULONG ValueLength, - PVOID Context, - PVOID EntryContext) -{ - PSERVICE_GROUP Group; - - DPRINT("IopGetGroupOrderList(%S, %x, 0x%p, %x, 0x%p, 0x%p)\n", - ValueName, ValueType, ValueData, ValueLength, Context, EntryContext); - - if (ValueType == REG_BINARY && - ValueData != NULL && - ValueLength >= sizeof(ULONG) && - ValueLength >= (*(PULONG)ValueData + 1) * sizeof(ULONG)) - { - Group = (PSERVICE_GROUP)Context; - Group->TagCount = ((PULONG)ValueData)[0]; - if (Group->TagCount > 0) - { - if (ValueLength >= (Group->TagCount + 1) * sizeof(ULONG)) - { - Group->TagArray = ExAllocatePool(NonPagedPool, Group->TagCount * sizeof(ULONG)); - if (Group->TagArray == NULL) - { - Group->TagCount = 0; - return STATUS_INSUFFICIENT_RESOURCES; - } - memcpy(Group->TagArray, (PULONG)ValueData + 1, Group->TagCount * sizeof(ULONG)); - } - else - { - Group->TagCount = 0; - return STATUS_UNSUCCESSFUL; - } - } - } - return STATUS_SUCCESS; -} - -static NTSTATUS NTAPI -IopCreateGroupListEntry(PWSTR ValueName, - ULONG ValueType, - PVOID ValueData, - ULONG ValueLength, - PVOID Context, - PVOID EntryContext) -{ - PSERVICE_GROUP Group; - RTL_QUERY_REGISTRY_TABLE QueryTable[2]; - NTSTATUS Status; - - - if (ValueType == REG_SZ) - { - DPRINT("GroupName: '%S'\n", (PWCHAR)ValueData); - - Group = ExAllocatePool(NonPagedPool, - sizeof(SERVICE_GROUP)); - if (Group == NULL) - { - return(STATUS_INSUFFICIENT_RESOURCES); - } - - RtlZeroMemory(Group, sizeof(SERVICE_GROUP)); - - if (!RtlCreateUnicodeString(&Group->GroupName, (PWSTR)ValueData)) - { - ExFreePool(Group); - return(STATUS_INSUFFICIENT_RESOURCES); - } - - RtlZeroMemory(&QueryTable, sizeof(QueryTable)); - QueryTable[0].Name = (PWSTR)ValueData; - QueryTable[0].QueryRoutine = IopGetGroupOrderList; - - Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, - L"GroupOrderList", - QueryTable, - (PVOID)Group, - NULL); - DPRINT("%x %d %S\n", Status, Group->TagCount, (PWSTR)ValueData); - - InsertTailList(&GroupListHead, - &Group->GroupListEntry); - } - - return(STATUS_SUCCESS); -} - - -static NTSTATUS NTAPI -IopCreateServiceListEntry(PUNICODE_STRING ServiceName) -{ - RTL_QUERY_REGISTRY_TABLE QueryTable[7]; - PSERVICE Service; - NTSTATUS Status; - ULONG DefaultTag = MAXULONG; - - DPRINT("ServiceName: '%wZ'\n", ServiceName); - - /* Allocate service entry */ - Service = (PSERVICE)ExAllocatePool(NonPagedPool, sizeof(SERVICE)); - if (Service == NULL) - { - DPRINT1("ExAllocatePool() failed\n"); - return(STATUS_INSUFFICIENT_RESOURCES); - } - RtlZeroMemory(Service, sizeof(SERVICE)); - - /* Get service data */ - RtlZeroMemory(&QueryTable, - sizeof(QueryTable)); - - QueryTable[0].Name = L"Start"; - QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; - QueryTable[0].EntryContext = &Service->Start; - - QueryTable[1].Name = L"Type"; - QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; - QueryTable[1].EntryContext = &Service->Type; - - QueryTable[2].Name = L"ErrorControl"; - QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; - QueryTable[2].EntryContext = &Service->ErrorControl; - - QueryTable[3].Name = L"Group"; - QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT; - QueryTable[3].EntryContext = &Service->ServiceGroup; - - QueryTable[4].Name = L"ImagePath"; - QueryTable[4].Flags = RTL_QUERY_REGISTRY_DIRECT; - QueryTable[4].EntryContext = &Service->ImagePath; - - QueryTable[5].Name = L"Tag"; - QueryTable[5].Flags = RTL_QUERY_REGISTRY_DIRECT; - QueryTable[5].EntryContext = &Service->Tag; - QueryTable[5].DefaultData = &DefaultTag; - QueryTable[5].DefaultType = REG_DWORD; - QueryTable[5].DefaultLength = sizeof(DefaultTag); - - Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES, - ServiceName->Buffer, - QueryTable, - NULL, - NULL); - if (!NT_SUCCESS(Status) || Service->Start > 1) - { - /* - * If something goes wrong during RtlQueryRegistryValues - * it'll just drop everything on the floor and return, - * so you have to check if the buffers were filled. - * Luckily we zerofilled the Service. - */ - if (Service->ServiceGroup.Buffer) - { - ExFreePoolWithTag(Service->ServiceGroup.Buffer, TAG_RTLREGISTRY); - } - if (Service->ImagePath.Buffer) - { - ExFreePoolWithTag(Service->ImagePath.Buffer, TAG_RTLREGISTRY); - } - ExFreePool(Service); - return(Status); - } - - /* Copy service name */ - Service->ServiceName.Length = ServiceName->Length; - Service->ServiceName.MaximumLength = ServiceName->Length + sizeof(WCHAR); - Service->ServiceName.Buffer = ExAllocatePool(NonPagedPool, - Service->ServiceName.MaximumLength); - RtlCopyMemory(Service->ServiceName.Buffer, - ServiceName->Buffer, - ServiceName->Length); - Service->ServiceName.Buffer[ServiceName->Length / sizeof(WCHAR)] = 0; - - /* Build registry path */ - Service->RegistryPath.MaximumLength = MAX_PATH * sizeof(WCHAR); - Service->RegistryPath.Buffer = ExAllocatePool(NonPagedPool, - MAX_PATH * sizeof(WCHAR)); - wcscpy(Service->RegistryPath.Buffer, - L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); - wcscat(Service->RegistryPath.Buffer, - Service->ServiceName.Buffer); - Service->RegistryPath.Length = wcslen(Service->RegistryPath.Buffer) * sizeof(WCHAR); - - DPRINT("ServiceName: '%wZ'\n", &Service->ServiceName); - DPRINT("RegistryPath: '%wZ'\n", &Service->RegistryPath); - DPRINT("ServiceGroup: '%wZ'\n", &Service->ServiceGroup); - DPRINT("ImagePath: '%wZ'\n", &Service->ImagePath); - DPRINT("Start %lx Type %lx Tag %lx ErrorControl %lx\n", - Service->Start, Service->Type, Service->Tag, Service->ErrorControl); - - /* Append service entry */ - InsertTailList(&ServiceListHead, - &Service->ServiceListEntry); - - return(STATUS_SUCCESS); -} - - -NTSTATUS INIT_FUNCTION -IoCreateDriverList(VOID) -{ - RTL_QUERY_REGISTRY_TABLE QueryTable[2]; - PKEY_BASIC_INFORMATION KeyInfo = NULL; - OBJECT_ATTRIBUTES ObjectAttributes; - UNICODE_STRING ServicesKeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services"); - UNICODE_STRING SubKeyName; - HANDLE KeyHandle; - NTSTATUS Status; - ULONG Index; - - ULONG KeyInfoLength = 0; - ULONG ReturnedLength; - - DPRINT("IoCreateDriverList() called\n"); - - /* Initialize basic variables */ - InitializeListHead(&GroupListHead); - InitializeListHead(&ServiceListHead); - - /* Build group order list */ - RtlZeroMemory(&QueryTable, - sizeof(QueryTable)); - - QueryTable[0].Name = L"List"; - QueryTable[0].QueryRoutine = IopCreateGroupListEntry; - - Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, - L"ServiceGroupOrder", - QueryTable, - NULL, - NULL); - if (!NT_SUCCESS(Status)) - return(Status); - - /* Enumerate services and create the service list */ - InitializeObjectAttributes(&ObjectAttributes, - &ServicesKeyName, - OBJ_CASE_INSENSITIVE, - NULL, - NULL); - - Status = ZwOpenKey(&KeyHandle, - KEY_ENUMERATE_SUB_KEYS, - &ObjectAttributes); - if (!NT_SUCCESS(Status)) - { - return(Status); - } - - KeyInfoLength = sizeof(KEY_BASIC_INFORMATION) + MAX_PATH * sizeof(WCHAR); - KeyInfo = ExAllocatePool(NonPagedPool, KeyInfoLength); - if (KeyInfo == NULL) - { - ZwClose(KeyHandle); - return(STATUS_INSUFFICIENT_RESOURCES); - } - - Index = 0; - while (TRUE) - { - Status = ZwEnumerateKey(KeyHandle, - Index, - KeyBasicInformation, - KeyInfo, - KeyInfoLength, - &ReturnedLength); - if (NT_SUCCESS(Status)) - { - if (KeyInfo->NameLength < MAX_PATH * sizeof(WCHAR)) - { - - SubKeyName.Length = (USHORT)KeyInfo->NameLength; - SubKeyName.MaximumLength = (USHORT)KeyInfo->NameLength + sizeof(WCHAR); - SubKeyName.Buffer = KeyInfo->Name; - SubKeyName.Buffer[SubKeyName.Length / sizeof(WCHAR)] = 0; - - DPRINT("KeyName: '%wZ'\n", &SubKeyName); - IopCreateServiceListEntry(&SubKeyName); - } - } - - if (!NT_SUCCESS(Status)) - break; - - Index++; - } - - ExFreePool(KeyInfo); - ZwClose(KeyHandle); - - DPRINT("IoCreateDriverList() done\n"); - - return(STATUS_SUCCESS); -} - -NTSTATUS INIT_FUNCTION -IoDestroyDriverList(VOID) -{ - PSERVICE_GROUP CurrentGroup; - PSERVICE CurrentService; - PLIST_ENTRY NextEntry, TempEntry; - - DPRINT("IoDestroyDriverList() called\n"); - - /* Destroy the Group List */ - for (NextEntry = GroupListHead.Flink, TempEntry = NextEntry->Flink; - NextEntry != &GroupListHead; - NextEntry = TempEntry, TempEntry = NextEntry->Flink) - { - /* Get the entry */ - CurrentGroup = CONTAINING_RECORD(NextEntry, - SERVICE_GROUP, - GroupListEntry); - - /* Remove it from the list */ - RemoveEntryList(&CurrentGroup->GroupListEntry); - - /* Free buffers */ - ExFreePool(CurrentGroup->GroupName.Buffer); - if (CurrentGroup->TagArray) - ExFreePool(CurrentGroup->TagArray); - ExFreePool(CurrentGroup); - } - - /* Destroy the Service List */ - for (NextEntry = ServiceListHead.Flink, TempEntry = NextEntry->Flink; - NextEntry != &ServiceListHead; - NextEntry = TempEntry, TempEntry = NextEntry->Flink) - { - /* Get the entry */ - CurrentService = CONTAINING_RECORD(NextEntry, - SERVICE, - ServiceListEntry); - - /* Remove it from the list */ - RemoveEntryList(&CurrentService->ServiceListEntry); - - /* Free buffers */ - ExFreePool(CurrentService->ServiceName.Buffer); - ExFreePool(CurrentService->RegistryPath.Buffer); - if (CurrentService->ServiceGroup.Buffer) - ExFreePool(CurrentService->ServiceGroup.Buffer); - if (CurrentService->ImagePath.Buffer) - ExFreePool(CurrentService->ImagePath.Buffer); - ExFreePool(CurrentService); - } - - DPRINT("IoDestroyDriverList() done\n"); - - /* Return success */ - return STATUS_SUCCESS; -} - -static INIT_FUNCTION NTSTATUS -IopLoadDriver(PSERVICE Service) -{ - NTSTATUS Status = STATUS_UNSUCCESSFUL; - PUNICODE_STRING ImagePath = &Service->ImagePath; - PWCHAR ImageName; - UNICODE_STRING ImageNameU; - - ImageName = wcsrchr(ImagePath->Buffer, L'\\'); - if (!ImageName) - ImageName = ImagePath->Buffer; - else - ImageName++; - - RtlInitUnicodeString(&ImageNameU, ImageName); - - IopDisplayLoadingMessage(&ImageNameU); - - Status = ZwLoadDriver(&Service->RegistryPath); - IopBootLog(&Service->ImagePath, NT_SUCCESS(Status) ? TRUE : FALSE); - if (!NT_SUCCESS(Status)) - { - DPRINT("IopLoadDriver() failed (Status %lx)\n", Status); -#if 0 - if (Service->ErrorControl == 1) - { - /* Log error */ - } - else if (Service->ErrorControl == 2) - { - if (IsLastKnownGood == FALSE) - { - /* Boot last known good configuration */ - } - } - else if (Service->ErrorControl == 3) - { - if (IsLastKnownGood == FALSE) - { - /* Boot last known good configuration */ - } - else - { - /* BSOD! */ - } - } -#endif - } - return Status; -} - -/* - * IopInitializeSystemDrivers - * - * Load drivers marked as system start. - * - * Parameters - * None - * - * Return Value - * None - */ -VOID -FASTCALL -IopInitializeSystemDrivers(VOID) -{ - PSERVICE_GROUP CurrentGroup; - PSERVICE CurrentService; - NTSTATUS Status; - ULONG i; - PLIST_ENTRY NextGroupEntry, NextServiceEntry; - - DPRINT("IopInitializeSystemDrivers()\n"); - - /* Start looping */ - for (NextGroupEntry = GroupListHead.Flink; - NextGroupEntry != &GroupListHead; - NextGroupEntry = NextGroupEntry->Flink) - { - /* Get the entry */ - CurrentGroup = CONTAINING_RECORD(NextGroupEntry, - SERVICE_GROUP, - GroupListEntry); - - DPRINT("Group: %wZ\n", &CurrentGroup->GroupName); - - /* Load all drivers with a valid tag */ - for (i = 0; i < CurrentGroup->TagCount; i++) - { - /* Start looping */ - for (NextServiceEntry = ServiceListHead.Flink; - NextServiceEntry != &ServiceListHead; - NextServiceEntry = NextServiceEntry->Flink) - { - /* Get the entry */ - CurrentService = CONTAINING_RECORD(NextServiceEntry, - SERVICE, - ServiceListEntry); - - if ((!RtlCompareUnicodeString(&CurrentGroup->GroupName, - &CurrentService->ServiceGroup, - TRUE)) && - (CurrentService->Start == SERVICE_SYSTEM_START) && - (CurrentService->Tag == CurrentGroup->TagArray[i])) - - { - DPRINT(" Path: %wZ\n", &CurrentService->RegistryPath); - Status = IopLoadDriver(CurrentService); - InbvIndicateProgress(); - } - } - } - - /* Load all drivers without a tag or with an invalid tag */ - for (NextServiceEntry = ServiceListHead.Flink; - NextServiceEntry != &ServiceListHead; - NextServiceEntry = NextServiceEntry->Flink) - { - /* Get the entry */ - CurrentService = CONTAINING_RECORD(NextServiceEntry, - SERVICE, - ServiceListEntry); - - if ((!RtlCompareUnicodeString(&CurrentGroup->GroupName, - &CurrentService->ServiceGroup, - TRUE)) && - (CurrentService->Start == SERVICE_SYSTEM_START)) - { - for (i = 0; i < CurrentGroup->TagCount; i++) - { - if (CurrentGroup->TagArray[i] == CurrentService->Tag) - { - break; - } - } - - if (i >= CurrentGroup->TagCount) - { - DPRINT(" Path: %wZ\n", &CurrentService->RegistryPath); - Status = IopLoadDriver(CurrentService); - InbvIndicateProgress(); - } - - } - } - } - - DPRINT("IopInitializeSystemDrivers() done\n"); -} diff --git a/ntoskrnl/io/iomgr/iomgr.c b/ntoskrnl/io/iomgr/iomgr.c index cb32297d25c..e52f2fe54ab 100644 --- a/ntoskrnl/io/iomgr/iomgr.c +++ b/ntoskrnl/io/iomgr/iomgr.c @@ -489,9 +489,9 @@ IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock) /* Initialize PnP manager */ PnpInit(); - - /* Create the group driver list */ - IoCreateDriverList(); + + /* Setup the group cache */ + if (!NT_SUCCESS(PiInitCacheGroupInformation())) return FALSE; /* Load boot start drivers */ IopInitializeBootDrivers(); @@ -530,9 +530,6 @@ IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock) IopInitializeSystemDrivers(); PnpSystemInit = TRUE; - /* Destroy the group driver list */ - IoDestroyDriverList(); - /* Reinitialize drivers that requested it */ IopReinitializeDrivers(); diff --git a/ntoskrnl/io/pnpmgr/pnpinit.c b/ntoskrnl/io/pnpmgr/pnpinit.c new file mode 100644 index 00000000000..8c5607289a6 --- /dev/null +++ b/ntoskrnl/io/pnpmgr/pnpinit.c @@ -0,0 +1,222 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: ntoskrnl/io/pnpmgr/pnpinit.c + * PURPOSE: PnP Initialization Code + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +PUNICODE_STRING PiInitGroupOrderTable; +ULONG PiInitGroupOrderTableCount; + +/* FUNCTIONS ******************************************************************/ + +NTSTATUS +NTAPI +PiInitCacheGroupInformation(VOID) +{ + HANDLE KeyHandle; + NTSTATUS Status; + PKEY_VALUE_FULL_INFORMATION KeyValueInformation; + PUNICODE_STRING GroupTable; + ULONG Count; + UNICODE_STRING GroupString = + RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet" + L"\\Control\\ServiceGroupOrder"); + + /* ReactOS HACK for SETUPLDR */ + if (KeLoaderBlock->SetupLdrBlock) + { + /* Bogus data */ + PiInitGroupOrderTableCount = 0; + PiInitGroupOrderTable = (PVOID)0xBABEB00B; + return STATUS_SUCCESS; + } + + /* Open the registry key */ + Status = IopOpenRegistryKeyEx(&KeyHandle, + NULL, + &GroupString, + KEY_READ); + if (NT_SUCCESS(Status)) + { + /* Get the list */ + Status = IopGetRegistryValue(KeyHandle, L"List", &KeyValueInformation); + ZwClose(KeyHandle); + + /* Make sure we got it */ + if (NT_SUCCESS(Status)) + { + /* Make sure it's valid */ + if ((KeyValueInformation->Type == REG_MULTI_SZ) && + (KeyValueInformation->DataLength)) + { + /* Convert it to unicode strings */ + Status = PnpRegMultiSzToUnicodeStrings(KeyValueInformation, + &GroupTable, + &Count); + + /* Cache it for later */ + PiInitGroupOrderTable = GroupTable; + PiInitGroupOrderTableCount = Count; + } + else + { + /* Fail */ + Status = STATUS_UNSUCCESSFUL; + } + + /* Free the information */ + ExFreePool(KeyValueInformation); + } + } + + /* Return status */ + return Status; +} + +USHORT +NTAPI +PpInitGetGroupOrderIndex(IN HANDLE ServiceHandle) +{ + NTSTATUS Status; + PKEY_VALUE_FULL_INFORMATION KeyValueInformation; + ULONG i; + PVOID Buffer; + UNICODE_STRING Group; + PAGED_CODE(); + + /* Make sure we have a cache */ + if (!PiInitGroupOrderTable) return -1; + + /* If we don't have a handle, the rest is easy -- return the count */ + if (!ServiceHandle) return PiInitGroupOrderTableCount + 1; + + /* Otherwise, get the group value */ + Status = IopGetRegistryValue(ServiceHandle, L"Group", &KeyValueInformation); + if (!NT_SUCCESS(Status)) return PiInitGroupOrderTableCount; + + /* Make sure we have a valid string */ + ASSERT(KeyValueInformation->Type == REG_SZ); + ASSERT(KeyValueInformation->DataLength); + + /* Convert to unicode string */ + Buffer = (PVOID)((ULONG_PTR)KeyValueInformation + KeyValueInformation->DataOffset); + PnpRegSzToString(Buffer, KeyValueInformation->DataLength, &Group.Length); + Group.MaximumLength = KeyValueInformation->DataLength; + Group.Buffer = Buffer; + + /* Loop the groups */ + for (i = 0; i < PiInitGroupOrderTableCount; i++) + { + /* Try to find a match */ + if (RtlEqualUnicodeString(&Group, &PiInitGroupOrderTable[i], TRUE)) break; + } + + /* We're done */ + ExFreePool(KeyValueInformation); + return i; +} + +USHORT +NTAPI +PipGetDriverTagPriority(IN HANDLE ServiceHandle) +{ + NTSTATUS Status; + HANDLE KeyHandle = NULL; + PKEY_VALUE_FULL_INFORMATION KeyValueInformation = NULL; + PKEY_VALUE_FULL_INFORMATION KeyValueInformationTag; + PKEY_VALUE_FULL_INFORMATION KeyValueInformationGroupOrderList; + PVOID Buffer; + UNICODE_STRING Group; + PULONG GroupOrder; + ULONG i = -1, Count, Tag = 0; + UNICODE_STRING GroupString = + RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet" + L"\\Control\\ServiceGroupOrder"); + + /* Open the key */ + Status = IopOpenRegistryKeyEx(&KeyHandle, NULL, &GroupString, KEY_READ); + if (!NT_SUCCESS(Status)) goto Quickie; + + /* Read the group */ + Status = IopGetRegistryValue(ServiceHandle, L"Group", &KeyValueInformation); + if (!NT_SUCCESS(Status)) goto Quickie; + + /* Make sure we have a group */ + if ((KeyValueInformation->Type == REG_SZ) && + (KeyValueInformation->DataLength)) + { + /* Convert to unicode string */ + Buffer = (PVOID)((ULONG_PTR)KeyValueInformation + KeyValueInformation->DataOffset); + PnpRegSzToString(Buffer, KeyValueInformation->DataLength, &Group.Length); + Group.MaximumLength = KeyValueInformation->DataLength; + Group.Buffer = Buffer; + } + + /* Now read the tag */ + Status = IopGetRegistryValue(ServiceHandle, L"Tag", &KeyValueInformationTag); + if (!NT_SUCCESS(Status)) goto Quickie; + + /* Make sure we have a tag */ + if ((KeyValueInformationTag->Type == REG_DWORD) && + (KeyValueInformationTag->DataLength)) + { + /* Read it */ + Tag = *(PULONG)((ULONG_PTR)KeyValueInformationTag + + KeyValueInformationTag->DataOffset); + } + + /* We can get rid of this now */ + ExFreePool(KeyValueInformationTag); + + /* Now let's read the group's tag order */ + Status = IopGetRegistryValue(KeyHandle, + Group.Buffer, + &KeyValueInformationGroupOrderList); + + /* We can get rid of this now */ +Quickie: + if (KeyValueInformation) ExFreePool(KeyValueInformation); + if (KeyHandle) NtClose(KeyHandle); + if (!NT_SUCCESS(Status)) return -1; + + /* We're on the success path -- validate the tag order*/ + if ((KeyValueInformationGroupOrderList->Type == REG_BINARY) && + (KeyValueInformationGroupOrderList->DataLength)) + { + /* Get the order array */ + GroupOrder = (PULONG)((ULONG_PTR)KeyValueInformationGroupOrderList + + KeyValueInformationGroupOrderList->DataOffset); + + /* Get the count */ + Count = *GroupOrder; + ASSERT(((Count + 1) * sizeof(ULONG)) <= + KeyValueInformationGroupOrderList->DataLength); + + /* Now loop each tag */ + GroupOrder++; + for (i = 1; i <= Count; i++) + { + /* If we found it, we're out */ + if (Tag == *GroupOrder) break; + + /* Try the next one */ + GroupOrder++; + } + } + + /* Last buffer to free */ + ExFreePool(KeyValueInformationGroupOrderList); + return i; +} + +/* EOF */ diff --git a/ntoskrnl/io/pnpmgr/pnpmgr.c b/ntoskrnl/io/pnpmgr/pnpmgr.c index 502787fc41f..0213d04d13e 100644 --- a/ntoskrnl/io/pnpmgr/pnpmgr.c +++ b/ntoskrnl/io/pnpmgr/pnpmgr.c @@ -46,15 +46,25 @@ typedef struct _INVALIDATE_DEVICE_RELATION_DATA /* FUNCTIONS *****************************************************************/ -static NTSTATUS +NTSTATUS IopAssignDeviceResources( IN PDEVICE_NODE DeviceNode, OUT ULONG *pRequiredSize); -static NTSTATUS + +NTSTATUS IopTranslateDeviceResources( IN PDEVICE_NODE DeviceNode, IN ULONG RequiredSize); +NTSTATUS +IopUpdateResourceMapForPnPDevice( + IN PDEVICE_NODE DeviceNode); + +NTSTATUS +NTAPI +IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath, + OUT PHANDLE Handle); + PDEVICE_NODE FASTCALL IopGetDeviceNode(PDEVICE_OBJECT DeviceObject) @@ -136,6 +146,9 @@ IopStartDevice( IO_STACK_LOCATION Stack; ULONG RequiredLength; NTSTATUS Status; + HANDLE InstanceHandle, ControlHandle; + UNICODE_STRING KeyName; + OBJECT_ATTRIBUTES ObjectAttributes; IopDeviceNodeSetFlag(DeviceNode, DNF_ASSIGNING_RESOURCES); DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n"); @@ -150,7 +163,10 @@ IopStartDevice( DPRINT("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n"); return Status; } - DeviceNode->ResourceRequirements = (PIO_RESOURCE_REQUIREMENTS_LIST)IoStatusBlock.Information; + else if (NT_SUCCESS(Status)) + { + DeviceNode->ResourceRequirements = (PIO_RESOURCE_REQUIREMENTS_LIST)IoStatusBlock.Information; + } Status = IopAssignDeviceResources(DeviceNode, &RequiredLength); if (NT_SUCCESS(Status)) @@ -158,7 +174,11 @@ IopStartDevice( Status = IopTranslateDeviceResources(DeviceNode, RequiredLength); if (NT_SUCCESS(Status)) { - IopDeviceNodeSetFlag(DeviceNode, DNF_RESOURCE_ASSIGNED); + Status = IopUpdateResourceMapForPnPDevice(DeviceNode); + if (!NT_SUCCESS(Status)) + { + DPRINT("IopUpdateResourceMap() failed (Status 0x%08lx)\n", Status); + } } else { @@ -206,9 +226,32 @@ IopStartDevice( } } + Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, &InstanceHandle); + if (!NT_SUCCESS(Status)) + return Status; + + RtlInitUnicodeString(&KeyName, L"Control"); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + InstanceHandle, + NULL); + Status = ZwCreateKey(&ControlHandle, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL); + if (!NT_SUCCESS(Status)) + { + ZwClose(InstanceHandle); + return Status; + } + + RtlInitUnicodeString(&KeyName, L"ActiveService"); + Status = ZwSetValueKey(ControlHandle, &KeyName, 0, REG_SZ, DeviceNode->ServiceName.Buffer, DeviceNode->ServiceName.Length); + if (NT_SUCCESS(Status)) IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED); + ZwClose(ControlHandle); + ZwClose(InstanceHandle); + return Status; } @@ -361,6 +404,10 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode, PDEVICE_NODE Node; NTSTATUS Status; KIRQL OldIrql; + UNICODE_STRING FullServiceName; + UNICODE_STRING LegacyPrefix = RTL_CONSTANT_STRING(L"LEGACY_"); + UNICODE_STRING UnknownDeviceName = RTL_CONSTANT_STRING(L"UNKNOWN"); + HANDLE TempHandle; DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n", ParentNode, PhysicalDeviceObject, ServiceName); @@ -373,9 +420,24 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode, RtlZeroMemory(Node, sizeof(DEVICE_NODE)); + if (!ServiceName) + ServiceName = &UnknownDeviceName; + if (!PhysicalDeviceObject) { - Status = PnpRootCreateDevice(ServiceName, &PhysicalDeviceObject); + FullServiceName.MaximumLength = LegacyPrefix.Length + ServiceName->Length; + FullServiceName.Length = 0; + FullServiceName.Buffer = ExAllocatePool(PagedPool, FullServiceName.MaximumLength); + if (!FullServiceName.Buffer) + { + ExFreePool(Node); + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlAppendUnicodeStringToString(&FullServiceName, &LegacyPrefix); + RtlAppendUnicodeStringToString(&FullServiceName, ServiceName); + + Status = PnpRootCreateDevice(&FullServiceName, &PhysicalDeviceObject, &Node->InstancePath); if (!NT_SUCCESS(Status)) { DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status); @@ -383,6 +445,13 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode, return Status; } + /* Create the device key for legacy drivers */ + Status = IopCreateDeviceKeyPath(&Node->InstancePath, &TempHandle); + if (NT_SUCCESS(Status)) + ZwClose(TempHandle); + + ExFreePool(FullServiceName.Buffer); + /* This is for drivers passed on the command line to ntoskrnl.exe */ IopDeviceNodeSetFlag(Node, DNF_STARTED); IopDeviceNodeSetFlag(Node, DNF_LEGACY_DRIVER); @@ -708,8 +777,135 @@ IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath, return STATUS_UNSUCCESSFUL; } +NTSTATUS +IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode, PWCHAR Level1Key, PWCHAR Level2Key) +{ + NTSTATUS Status; + ULONG Disposition; + HANDLE PnpMgrLevel1, PnpMgrLevel2, ResourceMapKey; + UNICODE_STRING KeyName; + OBJECT_ATTRIBUTES ObjectAttributes; + + RtlInitUnicodeString(&KeyName, + L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP"); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE | OBJ_OPENIF, + 0, + NULL); + Status = ZwCreateKey(&ResourceMapKey, + KEY_ALL_ACCESS, + &ObjectAttributes, + 0, + NULL, + REG_OPTION_VOLATILE, + &Disposition); + if (!NT_SUCCESS(Status)) + return Status; + + RtlInitUnicodeString(&KeyName, Level1Key); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE | OBJ_OPENIF, + ResourceMapKey, + NULL); + Status = ZwCreateKey(&PnpMgrLevel1, + KEY_ALL_ACCESS, + &ObjectAttributes, + 0, + NULL, + REG_OPTION_VOLATILE, + &Disposition); + ZwClose(ResourceMapKey); + if (!NT_SUCCESS(Status)) + return Status; + + RtlInitUnicodeString(&KeyName, Level2Key); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE | OBJ_OPENIF, + PnpMgrLevel1, + NULL); + Status = ZwCreateKey(&PnpMgrLevel2, + KEY_ALL_ACCESS, + &ObjectAttributes, + 0, + NULL, + REG_OPTION_VOLATILE, + &Disposition); + ZwClose(PnpMgrLevel1); + if (!NT_SUCCESS(Status)) + return Status; + + if (DeviceNode->ResourceList) + { + WCHAR NameBuff[256]; + UNICODE_STRING NameU; + UNICODE_STRING Suffix; + ULONG OldLength; + + ASSERT(DeviceNode->ResourceListTranslated); + + NameU.Buffer = NameBuff; + NameU.Length = 0; + NameU.MaximumLength = 256 * sizeof(WCHAR); + + Status = IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject, + DevicePropertyPhysicalDeviceObjectName, + NameU.MaximumLength, + NameU.Buffer, + &OldLength); + ASSERT(Status == STATUS_SUCCESS); + + NameU.Length = (USHORT)OldLength; + + RtlInitUnicodeString(&Suffix, L".Raw"); + RtlAppendUnicodeStringToString(&NameU, &Suffix); + + Status = ZwSetValueKey(PnpMgrLevel2, + &NameU, + 0, + REG_RESOURCE_LIST, + DeviceNode->ResourceList, + CM_RESOURCE_LIST_SIZE(DeviceNode->ResourceList)); + if (!NT_SUCCESS(Status)) + { + ZwClose(PnpMgrLevel2); + return Status; + } + + /* "Remove" the suffix by setting the length back to what it used to be */ + NameU.Length = (USHORT)OldLength; + + RtlInitUnicodeString(&Suffix, L".Translated"); + RtlAppendUnicodeStringToString(&NameU, &Suffix); + + Status = ZwSetValueKey(PnpMgrLevel2, + &NameU, + 0, + REG_RESOURCE_LIST, + DeviceNode->ResourceListTranslated, + CM_RESOURCE_LIST_SIZE(DeviceNode->ResourceListTranslated)); + ZwClose(PnpMgrLevel2); + if (!NT_SUCCESS(Status)) + return Status; + } + else + { + ZwClose(PnpMgrLevel2); + } + + IopDeviceNodeSetFlag(DeviceNode, DNF_RESOURCE_ASSIGNED); + + return STATUS_SUCCESS; +} + +NTSTATUS +IopUpdateResourceMapForPnPDevice(IN PDEVICE_NODE DeviceNode) +{ + return IopUpdateResourceMap(DeviceNode, L"PnP Manager", L"PnpManager"); +} -static NTSTATUS IopSetDeviceInstanceData(HANDLE InstanceKey, PDEVICE_NODE DeviceNode) @@ -720,6 +916,7 @@ IopSetDeviceInstanceData(HANDLE InstanceKey, ULONG ResCount; ULONG ListSize, ResultLength; NTSTATUS Status; + HANDLE ControlHandle; DPRINT("IopSetDeviceInstanceData() called\n"); @@ -793,24 +990,718 @@ IopSetDeviceInstanceData(HANDLE InstanceKey, sizeof(DefaultConfigFlags)); } + /* Create the 'Control' key */ + RtlInitUnicodeString(&KeyName, L"Control"); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + InstanceKey, + NULL); + Status = ZwCreateKey(&ControlHandle, 0, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL); + + if (NT_SUCCESS(Status)) + ZwClose(ControlHandle); + DPRINT("IopSetDeviceInstanceData() done\n"); - return STATUS_SUCCESS; + return Status; +} + +BOOLEAN +IopCheckResourceDescriptor( + IN PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc, + IN PCM_RESOURCE_LIST ResourceList, + IN BOOLEAN Silent, + OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor) +{ + ULONG i, ii; + BOOLEAN Result = FALSE; + + if (ResDesc->ShareDisposition == CmResourceShareShared) + return FALSE; + + for (i = 0; i < ResourceList->Count; i++) + { + PCM_PARTIAL_RESOURCE_LIST ResList = &ResourceList->List[i].PartialResourceList; + for (ii = 0; ii < ResList->Count; ii++) + { + PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc2 = &ResList->PartialDescriptors[ii]; + + /* We don't care about shared resources */ + if (ResDesc->ShareDisposition == CmResourceShareShared && + ResDesc2->ShareDisposition == CmResourceShareShared) + continue; + + /* Make sure we're comparing the same types */ + if (ResDesc->Type != ResDesc2->Type) + continue; + + switch (ResDesc->Type) + { + case CmResourceTypeMemory: + if ((ResDesc->u.Memory.Start.QuadPart < ResDesc2->u.Memory.Start.QuadPart && + ResDesc->u.Memory.Start.QuadPart + ResDesc->u.Memory.Length > + ResDesc2->u.Memory.Start.QuadPart) || (ResDesc2->u.Memory.Start.QuadPart < + ResDesc->u.Memory.Start.QuadPart && ResDesc2->u.Memory.Start.QuadPart + + ResDesc2->u.Memory.Length > ResDesc->u.Memory.Start.QuadPart)) + { + if (!Silent) + { + DPRINT1("Resource conflict: Memory (0x%x to 0x%x vs. 0x%x to 0x%x)\n", + ResDesc->u.Memory.Start.QuadPart, ResDesc->u.Memory.Start.QuadPart + + ResDesc->u.Memory.Length, ResDesc2->u.Memory.Start.QuadPart, + ResDesc2->u.Memory.Start.QuadPart + ResDesc2->u.Memory.Length); + } + + Result = TRUE; + + goto ByeBye; + } + break; + + case CmResourceTypePort: + if ((ResDesc->u.Port.Start.QuadPart < ResDesc2->u.Port.Start.QuadPart && + ResDesc->u.Port.Start.QuadPart + ResDesc->u.Port.Length > + ResDesc2->u.Port.Start.QuadPart) || (ResDesc2->u.Port.Start.QuadPart < + ResDesc->u.Port.Start.QuadPart && ResDesc2->u.Port.Start.QuadPart + + ResDesc2->u.Port.Length > ResDesc->u.Port.Start.QuadPart)) + { + if (!Silent) + { + DPRINT1("Resource conflict: Port (0x%x to 0x%x vs. 0x%x to 0x%x)\n", + ResDesc->u.Port.Start.QuadPart, ResDesc->u.Port.Start.QuadPart + + ResDesc->u.Port.Length, ResDesc2->u.Port.Start.QuadPart, + ResDesc2->u.Port.Start.QuadPart + ResDesc2->u.Port.Length); + } + + Result = TRUE; + + goto ByeBye; + } + break; + + case CmResourceTypeInterrupt: + if (ResDesc->u.Interrupt.Vector == ResDesc2->u.Interrupt.Vector) + { + if (!Silent) + { + DPRINT1("Resource conflict: IRQ (0x%x 0x%x vs. 0x%x 0x%x)\n", + ResDesc->u.Interrupt.Vector, ResDesc->u.Interrupt.Level, + ResDesc2->u.Interrupt.Vector, ResDesc2->u.Interrupt.Level); + } + + Result = TRUE; + + goto ByeBye; + } + break; + + case CmResourceTypeBusNumber: + if ((ResDesc->u.BusNumber.Start < ResDesc2->u.BusNumber.Start && + ResDesc->u.BusNumber.Start + ResDesc->u.BusNumber.Length > + ResDesc2->u.BusNumber.Start) || (ResDesc2->u.BusNumber.Start < + ResDesc->u.BusNumber.Start && ResDesc2->u.BusNumber.Start + + ResDesc2->u.BusNumber.Length > ResDesc->u.BusNumber.Start)) + { + if (!Silent) + { + DPRINT1("Resource conflict: Bus number (0x%x to 0x%x vs. 0x%x to 0x%x)\n", + ResDesc->u.BusNumber.Start, ResDesc->u.BusNumber.Start + + ResDesc->u.BusNumber.Length, ResDesc2->u.BusNumber.Start, + ResDesc2->u.BusNumber.Start + ResDesc2->u.BusNumber.Length); + } + + Result = TRUE; + + goto ByeBye; + } + break; + + case CmResourceTypeDma: + if (ResDesc->u.Dma.Channel == ResDesc2->u.Dma.Channel) + { + if (!Silent) + { + DPRINT1("Resource conflict: Dma (0x%x 0x%x vs. 0x%x 0x%x)\n", + ResDesc->u.Dma.Channel, ResDesc->u.Dma.Port, + ResDesc2->u.Dma.Channel, ResDesc2->u.Dma.Port); + } + + Result = TRUE; + + goto ByeBye; + } + break; + } + } + } + +ByeBye: + + if (Result && ConflictingDescriptor) + { + RtlCopyMemory(ConflictingDescriptor, + ResDesc, + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)); + } + + return Result; } -static NTSTATUS +BOOLEAN +IopCheckForResourceConflict( + IN PCM_RESOURCE_LIST ResourceList1, + IN PCM_RESOURCE_LIST ResourceList2, + IN BOOLEAN Silent, + OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor) +{ + ULONG i, ii; + BOOLEAN Result = FALSE; + + for (i = 0; i < ResourceList1->Count; i++) + { + PCM_PARTIAL_RESOURCE_LIST ResList = &ResourceList1->List[i].PartialResourceList; + for (ii = 0; ii < ResList->Count; ii++) + { + PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc = &ResList->PartialDescriptors[ii]; + + Result = IopCheckResourceDescriptor(ResDesc, + ResourceList2, + Silent, + ConflictingDescriptor); + if (Result) goto ByeBye; + } + } + + +ByeBye: + + return Result; +} + +NTSTATUS +IopDetectResourceConflict( + IN PCM_RESOURCE_LIST ResourceList, + IN BOOLEAN Silent, + OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor) +{ + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING KeyName; + HANDLE ResourceMapKey = INVALID_HANDLE_VALUE, ChildKey2 = INVALID_HANDLE_VALUE, ChildKey3 = INVALID_HANDLE_VALUE; + ULONG KeyInformationLength, RequiredLength, KeyValueInformationLength, KeyNameInformationLength; + PKEY_BASIC_INFORMATION KeyInformation; + PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation; + PKEY_VALUE_BASIC_INFORMATION KeyNameInformation; + ULONG ChildKeyIndex1 = 0, ChildKeyIndex2 = 0, ChildKeyIndex3 = 0; + NTSTATUS Status; + + RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP"); + InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, 0, NULL); + Status = ZwOpenKey(&ResourceMapKey, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + /* The key is missing which means we are the first device */ + return STATUS_SUCCESS; + } + + while (TRUE) + { + Status = ZwEnumerateKey(ResourceMapKey, + ChildKeyIndex1, + KeyBasicInformation, + NULL, + 0, + &RequiredLength); + if (Status == STATUS_NO_MORE_ENTRIES) + break; + else if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL) + { + KeyInformationLength = RequiredLength; + KeyInformation = ExAllocatePool(PagedPool, KeyInformationLength); + if (!KeyInformation) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + + Status = ZwEnumerateKey(ResourceMapKey, + ChildKeyIndex1, + KeyBasicInformation, + KeyInformation, + KeyInformationLength, + &RequiredLength); + } + else + goto cleanup; + ChildKeyIndex1++; + if (!NT_SUCCESS(Status)) + goto cleanup; + + KeyName.Buffer = KeyInformation->Name; + KeyName.MaximumLength = KeyName.Length = KeyInformation->NameLength; + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + ResourceMapKey, + NULL); + Status = ZwOpenKey(&ChildKey2, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &ObjectAttributes); + ExFreePool(KeyInformation); + if (!NT_SUCCESS(Status)) + goto cleanup; + + while (TRUE) + { + Status = ZwEnumerateKey(ChildKey2, + ChildKeyIndex2, + KeyBasicInformation, + NULL, + 0, + &RequiredLength); + if (Status == STATUS_NO_MORE_ENTRIES) + break; + else if (Status == STATUS_BUFFER_TOO_SMALL) + { + KeyInformationLength = RequiredLength; + KeyInformation = ExAllocatePool(PagedPool, KeyInformationLength); + if (!KeyInformation) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + + Status = ZwEnumerateKey(ChildKey2, + ChildKeyIndex2, + KeyBasicInformation, + KeyInformation, + KeyInformationLength, + &RequiredLength); + } + else + goto cleanup; + ChildKeyIndex2++; + if (!NT_SUCCESS(Status)) + goto cleanup; + + KeyName.Buffer = KeyInformation->Name; + KeyName.MaximumLength = KeyName.Length = KeyInformation->NameLength; + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + ChildKey2, + NULL); + Status = ZwOpenKey(&ChildKey3, KEY_QUERY_VALUE, &ObjectAttributes); + ExFreePool(KeyInformation); + if (!NT_SUCCESS(Status)) + goto cleanup; + + while (TRUE) + { + Status = ZwEnumerateValueKey(ChildKey3, + ChildKeyIndex3, + KeyValuePartialInformation, + NULL, + 0, + &RequiredLength); + if (Status == STATUS_NO_MORE_ENTRIES) + break; + else if (Status == STATUS_BUFFER_TOO_SMALL) + { + KeyValueInformationLength = RequiredLength; + KeyValueInformation = ExAllocatePool(PagedPool, KeyValueInformationLength); + if (!KeyValueInformation) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + + Status = ZwEnumerateValueKey(ChildKey3, + ChildKeyIndex3, + KeyValuePartialInformation, + KeyValueInformation, + KeyValueInformationLength, + &RequiredLength); + } + else + goto cleanup; + if (!NT_SUCCESS(Status)) + goto cleanup; + + Status = ZwEnumerateValueKey(ChildKey3, + ChildKeyIndex3, + KeyValueBasicInformation, + NULL, + 0, + &RequiredLength); + if (Status == STATUS_BUFFER_TOO_SMALL) + { + KeyNameInformationLength = RequiredLength; + KeyNameInformation = ExAllocatePool(PagedPool, KeyNameInformationLength + sizeof(WCHAR)); + if (!KeyNameInformation) + { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + + Status = ZwEnumerateValueKey(ChildKey3, + ChildKeyIndex3, + KeyValueBasicInformation, + KeyNameInformation, + KeyNameInformationLength, + &RequiredLength); + } + else + goto cleanup; + + ChildKeyIndex3++; + + if (!NT_SUCCESS(Status)) + goto cleanup; + + KeyNameInformation->Name[KeyNameInformation->NameLength / sizeof(WCHAR)] = UNICODE_NULL; + + /* Skip translated entries */ + if (wcsstr(KeyNameInformation->Name, L".Translated")) + { + ExFreePool(KeyNameInformation); + continue; + } + + ExFreePool(KeyNameInformation); + + if (IopCheckForResourceConflict(ResourceList, + (PCM_RESOURCE_LIST)KeyValueInformation->Data, + Silent, + ConflictingDescriptor)) + { + ExFreePool(KeyValueInformation); + Status = STATUS_CONFLICTING_ADDRESSES; + goto cleanup; + } + + ExFreePool(KeyValueInformation); + } + } + } + +cleanup: + if (ResourceMapKey != INVALID_HANDLE_VALUE) + ZwClose(ResourceMapKey); + if (ChildKey2 != INVALID_HANDLE_VALUE) + ZwClose(ChildKey2); + if (ChildKey3 != INVALID_HANDLE_VALUE) + ZwClose(ChildKey3); + + if (Status == STATUS_NO_MORE_ENTRIES) + Status = STATUS_SUCCESS; + + return Status; +} + +BOOLEAN +IopCheckDescriptorForConflict(PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc, OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor) +{ + CM_RESOURCE_LIST CmList; + NTSTATUS Status; + + CmList.Count = 1; + CmList.List[0].InterfaceType = InterfaceTypeUndefined; + CmList.List[0].BusNumber = 0; + CmList.List[0].PartialResourceList.Version = 1; + CmList.List[0].PartialResourceList.Revision = 1; + CmList.List[0].PartialResourceList.Count = 1; + CmList.List[0].PartialResourceList.PartialDescriptors[0] = *CmDesc; + + Status = IopDetectResourceConflict(&CmList, TRUE, ConflictingDescriptor); + if (Status == STATUS_CONFLICTING_ADDRESSES) + return TRUE; + + return FALSE; +} + +BOOLEAN +IopFindBusNumberResource( + IN PIO_RESOURCE_DESCRIPTOR IoDesc, + OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc) +{ + ULONG Start; + CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc; + + ASSERT(IoDesc->Type == CmDesc->Type); + ASSERT(IoDesc->Type == CmResourceTypeBusNumber); + + for (Start = IoDesc->u.BusNumber.MinBusNumber; + Start < IoDesc->u.BusNumber.MaxBusNumber; + Start++) + { + CmDesc->u.BusNumber.Length = IoDesc->u.BusNumber.Length; + CmDesc->u.BusNumber.Start = Start; + + if (IopCheckDescriptorForConflict(CmDesc, &ConflictingDesc)) + { + Start += ConflictingDesc.u.BusNumber.Start + ConflictingDesc.u.BusNumber.Length; + } + else + { + return TRUE; + } + } + + return FALSE; +} + +BOOLEAN +IopFindMemoryResource( + IN PIO_RESOURCE_DESCRIPTOR IoDesc, + OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc) +{ + ULONGLONG Start; + CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc; + + ASSERT(IoDesc->Type == CmDesc->Type); + ASSERT(IoDesc->Type == CmResourceTypeMemory); + + for (Start = IoDesc->u.Memory.MinimumAddress.QuadPart; + Start < IoDesc->u.Memory.MaximumAddress.QuadPart; + Start++) + { + CmDesc->u.Memory.Length = IoDesc->u.Memory.Length; + CmDesc->u.Memory.Start.QuadPart = Start; + + if (IopCheckDescriptorForConflict(CmDesc, &ConflictingDesc)) + { + Start += ConflictingDesc.u.Memory.Start.QuadPart + ConflictingDesc.u.Memory.Length; + } + else + { + return TRUE; + } + } + + return FALSE; +} + +BOOLEAN +IopFindPortResource( + IN PIO_RESOURCE_DESCRIPTOR IoDesc, + OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc) +{ + ULONGLONG Start; + CM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDesc; + + ASSERT(IoDesc->Type == CmDesc->Type); + ASSERT(IoDesc->Type == CmResourceTypePort); + + for (Start = IoDesc->u.Port.MinimumAddress.QuadPart; + Start < IoDesc->u.Port.MaximumAddress.QuadPart; + Start++) + { + CmDesc->u.Port.Length = IoDesc->u.Port.Length; + CmDesc->u.Port.Start.QuadPart = Start; + + if (IopCheckDescriptorForConflict(CmDesc, &ConflictingDesc)) + { + Start += ConflictingDesc.u.Port.Start.QuadPart + ConflictingDesc.u.Port.Length; + } + else + { + return TRUE; + } + } + + return FALSE; +} + +BOOLEAN +IopFindDmaResource( + IN PIO_RESOURCE_DESCRIPTOR IoDesc, + OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc) +{ + ULONG Channel; + + ASSERT(IoDesc->Type == CmDesc->Type); + ASSERT(IoDesc->Type == CmResourceTypeDma); + + for (Channel = IoDesc->u.Dma.MinimumChannel; + Channel < IoDesc->u.Dma.MaximumChannel; + Channel++) + { + CmDesc->u.Dma.Channel = Channel; + CmDesc->u.Dma.Port = 0; + + if (!IopCheckDescriptorForConflict(CmDesc, NULL)) + return TRUE; + } + + return FALSE; +} + +BOOLEAN +IopFindInterruptResource( + IN PIO_RESOURCE_DESCRIPTOR IoDesc, + OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc) +{ + ULONG Vector; + + ASSERT(IoDesc->Type == CmDesc->Type); + ASSERT(IoDesc->Type == CmResourceTypeInterrupt); + + for (Vector = IoDesc->u.Interrupt.MinimumVector; + Vector < IoDesc->u.Interrupt.MaximumVector; + Vector++) + { + CmDesc->u.Interrupt.Vector = Vector; + CmDesc->u.Interrupt.Level = Vector; + CmDesc->u.Interrupt.Affinity = (KAFFINITY)-1; + + if (!IopCheckDescriptorForConflict(CmDesc, NULL)) + return TRUE; + } + + return FALSE; +} + +NTSTATUS +IopCreateResourceListFromRequirements( + IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList, + OUT PCM_RESOURCE_LIST *ResourceList) +{ + ULONG i, ii, Size; + PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc; + + Size = FIELD_OFFSET(CM_RESOURCE_LIST, List); + for (i = 0; i < RequirementsList->AlternativeLists; i++) + { + PIO_RESOURCE_LIST ResList = &RequirementsList->List[i]; + Size += FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList.PartialDescriptors) + + ResList->Count * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); + } + + *ResourceList = ExAllocatePool(PagedPool, Size); + if (!*ResourceList) + return STATUS_INSUFFICIENT_RESOURCES; + + (*ResourceList)->Count = 1; + (*ResourceList)->List[0].BusNumber = RequirementsList->BusNumber; + (*ResourceList)->List[0].InterfaceType = RequirementsList->InterfaceType; + (*ResourceList)->List[0].PartialResourceList.Version = 1; + (*ResourceList)->List[0].PartialResourceList.Revision = 1; + (*ResourceList)->List[0].PartialResourceList.Count = 0; + + ResDesc = &(*ResourceList)->List[0].PartialResourceList.PartialDescriptors[0]; + + for (i = 0; i < RequirementsList->AlternativeLists; i++) + { + PIO_RESOURCE_LIST ResList = &RequirementsList->List[i]; + for (ii = 0; ii < ResList->Count; ii++) + { + PIO_RESOURCE_DESCRIPTOR ReqDesc = &ResList->Descriptors[ii]; + + /* FIXME: Handle alternate ranges */ + if (ReqDesc->Option == IO_RESOURCE_ALTERNATIVE) + continue; + + ResDesc->Type = ReqDesc->Type; + ResDesc->Flags = ReqDesc->Flags; + ResDesc->ShareDisposition = ReqDesc->ShareDisposition; + + switch (ReqDesc->Type) + { + case CmResourceTypeInterrupt: + if (!IopFindInterruptResource(ReqDesc, ResDesc)) + { + DPRINT1("Failed to find an available interrupt resource (0x%x to 0x%x)\n", + ReqDesc->u.Interrupt.MinimumVector, ReqDesc->u.Interrupt.MaximumVector); + + if (ReqDesc->Option == 0) + { + ExFreePool(*ResourceList); + return STATUS_CONFLICTING_ADDRESSES; + } + } + break; + + case CmResourceTypePort: + if (!IopFindPortResource(ReqDesc, ResDesc)) + { + DPRINT1("Failed to find an available port resource (0x%x to 0x%x length: 0x%x)\n", + ReqDesc->u.Port.MinimumAddress.QuadPart, ReqDesc->u.Port.MaximumAddress.QuadPart, + ReqDesc->u.Port.Length); + + if (ReqDesc->Option == 0) + { + ExFreePool(*ResourceList); + return STATUS_CONFLICTING_ADDRESSES; + } + } + break; + + case CmResourceTypeMemory: + if (!IopFindMemoryResource(ReqDesc, ResDesc)) + { + DPRINT1("Failed to find an available memory resource (0x%x to 0x%x length: 0x%x)\n", + ReqDesc->u.Memory.MinimumAddress.QuadPart, ReqDesc->u.Memory.MaximumAddress.QuadPart, + ReqDesc->u.Memory.Length); + + if (ReqDesc->Option == 0) + { + ExFreePool(*ResourceList); + return STATUS_CONFLICTING_ADDRESSES; + } + } + break; + + case CmResourceTypeBusNumber: + if (!IopFindBusNumberResource(ReqDesc, ResDesc)) + { + DPRINT1("Failed to find an available bus number resource (0x%x to 0x%x length: 0x%x)\n", + ReqDesc->u.BusNumber.MinBusNumber, ReqDesc->u.BusNumber.MaxBusNumber, + ReqDesc->u.BusNumber.Length); + + if (ReqDesc->Option == 0) + { + ExFreePool(*ResourceList); + return STATUS_CONFLICTING_ADDRESSES; + } + } + break; + + case CmResourceTypeDma: + if (!IopFindDmaResource(ReqDesc, ResDesc)) + { + DPRINT1("Failed to find an available dma resource (0x%x to 0x%x)\n", + ReqDesc->u.Dma.MinimumChannel, ReqDesc->u.Dma.MaximumChannel); + + if (ReqDesc->Option == 0) + { + ExFreePool(*ResourceList); + return STATUS_CONFLICTING_ADDRESSES; + } + } + break; + + default: + DPRINT1("Unsupported resource type: %x\n", ReqDesc->Type); + break; + } + + (*ResourceList)->List[0].PartialResourceList.Count++; + ResDesc++; + } + } + + return STATUS_SUCCESS; +} + +NTSTATUS IopAssignDeviceResources( IN PDEVICE_NODE DeviceNode, OUT ULONG *pRequiredSize) { - PIO_RESOURCE_LIST ResourceList; - PIO_RESOURCE_DESCRIPTOR ResourceDescriptor; - PCM_PARTIAL_RESOURCE_DESCRIPTOR DescriptorRaw; PCM_PARTIAL_RESOURCE_LIST pPartialResourceList; - ULONG NumberOfResources = 0; ULONG Size; - ULONG i, j; + ULONG i; + ULONG j; NTSTATUS Status; if (!DeviceNode->BootResources && !DeviceNode->ResourceRequirements) @@ -823,7 +1714,7 @@ IopAssignDeviceResources( /* Fill DeviceNode->ResourceList * FIXME: the PnP arbiter should go there! - * Actually, use the BootResources if provided, else the resource list #0 + * Actually, use the BootResources if provided, else the resource requirements */ if (DeviceNode->BootResources) @@ -850,155 +1741,40 @@ IopAssignDeviceResources( } RtlCopyMemory(DeviceNode->ResourceList, DeviceNode->BootResources, Size); - *pRequiredSize = Size; - return STATUS_SUCCESS; - } - - /* Ok, here, we have to use the device requirement list */ - ResourceList = &DeviceNode->ResourceRequirements->List[0]; - if (ResourceList->Version != 1 || ResourceList->Revision != 1) - { - Status = STATUS_REVISION_MISMATCH; - goto ByeBye; - } - - Size = sizeof(CM_RESOURCE_LIST) + ResourceList->Count * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); - DeviceNode->ResourceList = ExAllocatePool(PagedPool, Size); - if (!DeviceNode->ResourceList) - { - Status = STATUS_NO_MEMORY; - goto ByeBye; - } - - DeviceNode->ResourceList->Count = 1; - DeviceNode->ResourceList->List[0].InterfaceType = DeviceNode->ResourceRequirements->InterfaceType; - DeviceNode->ResourceList->List[0].BusNumber = DeviceNode->ResourceRequirements->BusNumber; - DeviceNode->ResourceList->List[0].PartialResourceList.Version = 1; - DeviceNode->ResourceList->List[0].PartialResourceList.Revision = 1; - - for (i = 0; i < ResourceList->Count; i++) - { - ResourceDescriptor = &ResourceList->Descriptors[i]; - - if (ResourceDescriptor->Option == 0 || ResourceDescriptor->Option == IO_RESOURCE_PREFERRED) + Status = IopDetectResourceConflict(DeviceNode->ResourceList, FALSE, NULL); + if (NT_SUCCESS(Status) || !DeviceNode->ResourceRequirements) { - DescriptorRaw = &DeviceNode->ResourceList->List[0].PartialResourceList.PartialDescriptors[NumberOfResources]; - NumberOfResources++; + if (!NT_SUCCESS(Status) && !DeviceNode->ResourceRequirements) + { + DPRINT1("Using conflicting boot resources because no requirements were supplied!\n"); + } - /* Copy ResourceDescriptor to DescriptorRaw and DescriptorTranslated */ - DescriptorRaw->Type = ResourceDescriptor->Type; - DescriptorRaw->ShareDisposition = ResourceDescriptor->ShareDisposition; - DescriptorRaw->Flags = ResourceDescriptor->Flags; - switch (ResourceDescriptor->Type) - { - case CmResourceTypePort: - { - DescriptorRaw->u.Port.Start = ResourceDescriptor->u.Port.MinimumAddress; - DescriptorRaw->u.Port.Length = ResourceDescriptor->u.Port.Length; - break; - } - case CmResourceTypeInterrupt: - { - INTERFACE_TYPE BusType; - ULONG SlotNumber; - ULONG ret; - UCHAR Irq; - - DescriptorRaw->u.Interrupt.Level = 0; - DescriptorRaw->u.Interrupt.Vector = ResourceDescriptor->u.Interrupt.MinimumVector; - /* FIXME: HACK: if we have a PCI device, we try - * to keep the IRQ assigned by the BIOS */ - if (NT_SUCCESS(IoGetDeviceProperty( - DeviceNode->PhysicalDeviceObject, - DevicePropertyLegacyBusType, - sizeof(INTERFACE_TYPE), - &BusType, - &ret)) && BusType == PCIBus) - { - /* We have a PCI bus */ - if (NT_SUCCESS(IoGetDeviceProperty( - DeviceNode->PhysicalDeviceObject, - DevicePropertyAddress, - sizeof(ULONG), - &SlotNumber, - &ret)) && SlotNumber > 0) - { - /* We have a good slot number */ - ret = HalGetBusDataByOffset(PCIConfiguration, - DeviceNode->ResourceRequirements->BusNumber, - SlotNumber, - &Irq, - 0x3c /* PCI_INTERRUPT_LINE */, - sizeof(UCHAR)); - if (ret != 0 && ret != 2 - && ResourceDescriptor->u.Interrupt.MinimumVector <= Irq - && ResourceDescriptor->u.Interrupt.MaximumVector >= Irq) - { - /* The device already has an assigned IRQ */ - DescriptorRaw->u.Interrupt.Vector = Irq; - } - else - { - DPRINT1("Trying to assign IRQ 0x%lx to %wZ\n", - DescriptorRaw->u.Interrupt.Vector, - &DeviceNode->InstancePath); - Irq = (UCHAR)DescriptorRaw->u.Interrupt.Vector; - ret = HalSetBusDataByOffset(PCIConfiguration, - DeviceNode->ResourceRequirements->BusNumber, - SlotNumber, - &Irq, - 0x3c /* PCI_INTERRUPT_LINE */, - sizeof(UCHAR)); - if (ret == 0 || ret == 2) - ASSERT(FALSE); - } - } - } - break; - } - case CmResourceTypeMemory: - { - DescriptorRaw->u.Memory.Start = ResourceDescriptor->u.Memory.MinimumAddress; - DescriptorRaw->u.Memory.Length = ResourceDescriptor->u.Memory.Length; - break; - } - case CmResourceTypeDma: - { - DescriptorRaw->u.Dma.Channel = ResourceDescriptor->u.Dma.MinimumChannel; - DescriptorRaw->u.Dma.Port = 0; /* FIXME */ - DescriptorRaw->u.Dma.Reserved1 = 0; - break; - } - case CmResourceTypeBusNumber: - { - DescriptorRaw->u.BusNumber.Start = ResourceDescriptor->u.BusNumber.MinBusNumber; - DescriptorRaw->u.BusNumber.Length = ResourceDescriptor->u.BusNumber.Length; - DescriptorRaw->u.BusNumber.Reserved = ResourceDescriptor->u.BusNumber.Reserved; - break; - } - /*CmResourceTypeDevicePrivate: - case CmResourceTypePcCardConfig: - case CmResourceTypeMfCardConfig: - { - RtlCopyMemory( - &DescriptorRaw->u.DevicePrivate, - &ResourceDescriptor->u.DevicePrivate, - sizeof(ResourceDescriptor->u.DevicePrivate)); - RtlCopyMemory( - &DescriptorTranslated->u.DevicePrivate, - &ResourceDescriptor->u.DevicePrivate, - sizeof(ResourceDescriptor->u.DevicePrivate)); - break; - }*/ - default: - DPRINT1("IopAssignDeviceResources(): unknown resource descriptor type 0x%x\n", ResourceDescriptor->Type); - NumberOfResources--; - } + *pRequiredSize = Size; + return STATUS_SUCCESS; + } + else + { + DPRINT1("Boot resources for %wZ cause a resource conflict!\n", &DeviceNode->InstancePath); + ExFreePool(DeviceNode->ResourceList); } - } - DeviceNode->ResourceList->List[0].PartialResourceList.Count = NumberOfResources; + Status = IopCreateResourceListFromRequirements(DeviceNode->ResourceRequirements, + &DeviceNode->ResourceList); + if (!NT_SUCCESS(Status)) + goto ByeBye; + + Size = FIELD_OFFSET(CM_RESOURCE_LIST, List); + for (i = 0; i < DeviceNode->ResourceList->Count; i++) + { + pPartialResourceList = &DeviceNode->ResourceList->List[i].PartialResourceList; + Size += FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList.PartialDescriptors) + + pPartialResourceList->Count * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR); + } + + Status = IopDetectResourceConflict(DeviceNode->ResourceList, FALSE, NULL); + if (!NT_SUCCESS(Status)) + goto ByeBye; *pRequiredSize = Size; return STATUS_SUCCESS; @@ -1014,7 +1790,7 @@ ByeBye: } -static NTSTATUS +NTSTATUS IopTranslateDeviceResources( IN PDEVICE_NODE DeviceNode, IN ULONG RequiredSize) @@ -2140,7 +2916,6 @@ IopEnumerateDetectedDevices( IN ULONG ParentBootResourcesLength) { UNICODE_STRING IdentifierU = RTL_CONSTANT_STRING(L"Identifier"); - UNICODE_STRING DeviceDescU = RTL_CONSTANT_STRING(L"DeviceDesc"); UNICODE_STRING HardwareIDU = RTL_CONSTANT_STRING(L"HardwareID"); UNICODE_STRING ConfigurationDataU = RTL_CONSTANT_STRING(L"Configuration Data"); UNICODE_STRING BootConfigU = RTL_CONSTANT_STRING(L"BootConfig"); @@ -2187,7 +2962,8 @@ IopEnumerateDetectedDevices( UNICODE_STRING HardwareIdKey; PUNICODE_STRING pHardwareId; ULONG DeviceIndex = 0; - BOOLEAN IsDeviceDesc; + PUCHAR CmResourceList; + ULONG ListCount; if (RelativePath) { @@ -2302,7 +3078,7 @@ IopEnumerateDetectedDevices( DPRINT("ExAllocatePool() failed\n"); goto nextdevice; } - if (ParentBootResourcesLength == 0) + if (ParentBootResourcesLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) { RtlCopyMemory(BootResources, pValueInformation->Data, pValueInformation->DataLength); } @@ -2414,31 +3190,26 @@ IopEnumerateDetectedDevices( { pHardwareId = &HardwareIdSerial; DeviceIndex = DeviceIndexSerial++; - IsDeviceDesc = TRUE; } else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierKeyboard, FALSE) == 0) { pHardwareId = &HardwareIdKeyboard; DeviceIndex = DeviceIndexKeyboard++; - IsDeviceDesc = FALSE; } else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierMouse, FALSE) == 0) { pHardwareId = &HardwareIdMouse; DeviceIndex = DeviceIndexMouse++; - IsDeviceDesc = FALSE; } else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierParallel, FALSE) == 0) { pHardwareId = &HardwareIdParallel; DeviceIndex = DeviceIndexParallel++; - IsDeviceDesc = FALSE; } else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierFloppy, FALSE) == 0) { pHardwareId = &HardwareIdFloppy; DeviceIndex = DeviceIndexFloppy++; - IsDeviceDesc = FALSE; } else if (NT_SUCCESS(Status)) { @@ -2447,13 +3218,11 @@ IopEnumerateDetectedDevices( { pHardwareId = &HardwareIdPci; DeviceIndex = DeviceIndexPci++; - IsDeviceDesc = FALSE; } else if (RtlCompareUnicodeString(&ValueName, &IdentifierIsa, FALSE) == 0) { pHardwareId = &HardwareIdIsa; DeviceIndex = DeviceIndexIsa++; - IsDeviceDesc = FALSE; } else { @@ -2505,16 +3274,6 @@ IopEnumerateDetectedDevices( goto nextdevice; } DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName, DeviceIndex, &HardwareIdKey); - if (IsDeviceDesc) - { - Status = ZwSetValueKey(hLevel2Key, &DeviceDescU, 0, REG_SZ, ValueName.Buffer, ValueName.MaximumLength); - if (!NT_SUCCESS(Status)) - { - DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); - ZwDeleteKey(hLevel2Key); - goto nextdevice; - } - } Status = ZwSetValueKey(hLevel2Key, &HardwareIDU, 0, REG_MULTI_SZ, pHardwareId->Buffer, pHardwareId->MaximumLength); if (!NT_SUCCESS(Status)) { @@ -2538,10 +3297,29 @@ IopEnumerateDetectedDevices( ZwDeleteKey(hLevel2Key); goto nextdevice; } - if (BootResourcesLength > 0) + if (BootResourcesLength >= sizeof(CM_FULL_RESOURCE_DESCRIPTOR)) { + CmResourceList = ExAllocatePool(PagedPool, BootResourcesLength + sizeof(ULONG)); + if (!CmResourceList) + { + ZwClose(hLogConf); + ZwDeleteKey(hLevel2Key); + goto nextdevice; + } + + /* Add the list count (1st member of CM_RESOURCE_LIST) */ + ListCount = 1; + RtlCopyMemory(CmResourceList, + &ListCount, + sizeof(ULONG)); + + /* Now add the actual list (2nd member of CM_RESOURCE_LIST) */ + RtlCopyMemory(CmResourceList + sizeof(ULONG), + BootResources, + BootResourcesLength); + /* Save boot resources to 'LogConf\BootConfig' */ - Status = ZwSetValueKey(hLogConf, &BootConfigU, 0, REG_FULL_RESOURCE_DESCRIPTOR, BootResources, BootResourcesLength); + Status = ZwSetValueKey(hLogConf, &BootConfigU, 0, REG_RESOURCE_LIST, CmResourceList, BootResourcesLength + sizeof(ULONG)); if (!NT_SUCCESS(Status)) { DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); @@ -2554,7 +3332,10 @@ IopEnumerateDetectedDevices( nextdevice: if (BootResources && BootResources != ParentBootResources) + { ExFreePool(BootResources); + BootResources = NULL; + } if (hLevel2Key) { ZwClose(hLevel2Key); @@ -3052,7 +3833,7 @@ PpInitSystem(VOID) /* PUBLIC FUNCTIONS **********************************************************/ /* - * @unimplemented + * @implemented */ NTSTATUS NTAPI @@ -3068,6 +3849,8 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject, PVOID Data = NULL; PWSTR Ptr; NTSTATUS Status; + POBJECT_NAME_INFORMATION ObjectNameInfo = NULL; + ULONG RequiredLength, ObjectNameInfoLength; DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject, DeviceProperty); @@ -3281,9 +4064,36 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject, break; case DevicePropertyPhysicalDeviceObjectName: - /* InstancePath buffer is NULL terminated, so we can do this */ - Length = DeviceNode->InstancePath.MaximumLength; - Data = DeviceNode->InstancePath.Buffer; + Status = ObQueryNameString(DeviceNode->PhysicalDeviceObject, + NULL, + 0, + &RequiredLength); + if (Status == STATUS_SUCCESS) + { + Length = 0; + Data = L""; + } + else if (Status == STATUS_INFO_LENGTH_MISMATCH) + { + ObjectNameInfoLength = RequiredLength; + ObjectNameInfo = ExAllocatePool(PagedPool, ObjectNameInfoLength); + if (!ObjectNameInfo) + return STATUS_INSUFFICIENT_RESOURCES; + + Status = ObQueryNameString(DeviceNode->PhysicalDeviceObject, + ObjectNameInfo, + ObjectNameInfoLength, + &RequiredLength); + if (NT_SUCCESS(Status)) + { + Length = ObjectNameInfo->Name.Length; + Data = ObjectNameInfo->Name.Buffer; + } + else + return Status; + } + else + return Status; break; default: @@ -3293,13 +4103,22 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject, /* Prepare returned values */ *ResultLength = Length; if (BufferLength < Length) + { + if (ObjectNameInfo != NULL) + ExFreePool(ObjectNameInfo); + return STATUS_BUFFER_TOO_SMALL; + } RtlCopyMemory(PropertyBuffer, Data, Length); /* NULL terminate the string (if required) */ - if (DeviceProperty == DevicePropertyEnumeratorName) + if (DeviceProperty == DevicePropertyEnumeratorName || + DeviceProperty == DevicePropertyPhysicalDeviceObjectName) ((LPWSTR)PropertyBuffer)[Length / sizeof(WCHAR)] = UNICODE_NULL; + if (ObjectNameInfo != NULL) + ExFreePool(ObjectNameInfo); + return STATUS_SUCCESS; } diff --git a/ntoskrnl/io/pnpmgr/pnpreport.c b/ntoskrnl/io/pnpmgr/pnpreport.c index e11c4b0263e..c75e566b0d4 100644 --- a/ntoskrnl/io/pnpmgr/pnpreport.c +++ b/ntoskrnl/io/pnpmgr/pnpreport.c @@ -3,7 +3,7 @@ * COPYRIGHT: GPL - See COPYING in the top level directory * FILE: ntoskrnl/io/pnpmgr/pnpreport.c * PURPOSE: Device Changes Reporting Functions - * PROGRAMMERS: Filip Navara (xnavara@volny.cz) + * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org) */ /* INCLUDES ******************************************************************/ @@ -12,6 +12,98 @@ #define NDEBUG #include +NTSTATUS +NTAPI +IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath, + OUT PHANDLE Handle); + +NTSTATUS +IopAssignDeviceResources( + IN PDEVICE_NODE DeviceNode, + OUT ULONG *pRequiredSize); + +NTSTATUS +IopSetDeviceInstanceData(HANDLE InstanceKey, + PDEVICE_NODE DeviceNode); + +NTSTATUS +IopTranslateDeviceResources( + IN PDEVICE_NODE DeviceNode, + IN ULONG RequiredSize); + +NTSTATUS +IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode, + PVOID Context); + +NTSTATUS +IopUpdateResourceMapForPnPDevice( + IN PDEVICE_NODE DeviceNode); + +NTSTATUS +IopDetectResourceConflict( + IN PCM_RESOURCE_LIST ResourceList); + +/* PRIVATE FUNCTIONS *********************************************************/ + +PWCHAR +IopGetInterfaceTypeString(INTERFACE_TYPE IfType) +{ + switch (IfType) + { + case Internal: + return L"Internal"; + + case Isa: + return L"Isa"; + + case Eisa: + return L"Eisa"; + + case MicroChannel: + return L"MicroChannel"; + + case TurboChannel: + return L"TurboChannel"; + + case PCIBus: + return L"PCIBus"; + + case VMEBus: + return L"VMEBus"; + + case NuBus: + return L"NuBus"; + + case PCMCIABus: + return L"PCMCIABus"; + + case CBus: + return L"CBus"; + + case MPIBus: + return L"MPIBus"; + + case MPSABus: + return L"MPSABus"; + + case ProcessorInternal: + return L"ProcessorInternal"; + + case PNPISABus: + return L"PNPISABus"; + + case PNPBus: + return L"PNPBus"; + + case Vmcs: + return L"Vmcs"; + + default: + DPRINT1("Invalid bus type: %d\n", IfType); + return NULL; + } +} + /* PUBLIC FUNCTIONS **********************************************************/ /* @@ -30,29 +122,57 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject, { PDEVICE_NODE DeviceNode; PDEVICE_OBJECT Pdo; - NTSTATUS Status = STATUS_SUCCESS; + NTSTATUS Status; + HANDLE InstanceKey; + ULONG RequiredLength; + UNICODE_STRING ValueName, ServiceName; + WCHAR HardwareId[256]; + PWCHAR IfString; + ULONG IdLength; - DPRINT("__FUNCTION__ (DeviceObject %p, *DeviceObject %p)\n", + DPRINT("IoReportDetectedDevice (DeviceObject %p, *DeviceObject %p)\n", DeviceObject, DeviceObject ? *DeviceObject : NULL); - /* if *DeviceObject is not NULL, we must use it as a PDO, and don't create a new one */ + /* Create the service name (eg. ACPI_HAL) */ + ServiceName.Buffer = DriverObject->DriverName.Buffer + + sizeof(DRIVER_ROOT_NAME) / sizeof(WCHAR) - 1; + ServiceName.Length = DriverObject->DriverName.Length - + sizeof(DRIVER_ROOT_NAME) + sizeof(WCHAR); + ServiceName.MaximumLength = ServiceName.Length; + + /* If the interface type is unknown, treat it as internal */ + if (LegacyBusType == InterfaceTypeUndefined) + LegacyBusType = Internal; + + /* Get the string equivalent of the interface type */ + IfString = IopGetInterfaceTypeString(LegacyBusType); + + /* If NULL is returned then it's a bad type */ + if (!IfString) + return STATUS_INVALID_PARAMETER; + + /* We use the caller's PDO if they supplied one */ if (DeviceObject && *DeviceObject) { Pdo = *DeviceObject; + DeviceNode = IopGetDeviceNode(*DeviceObject); } else { - UNICODE_STRING ServiceName; - ServiceName.Buffer = DriverObject->DriverName.Buffer + - sizeof(DRIVER_ROOT_NAME) / sizeof(WCHAR) - 1; - ServiceName.Length = DriverObject->DriverName.Length - - sizeof(DRIVER_ROOT_NAME) + sizeof(WCHAR); - ServiceName.MaximumLength = ServiceName.Length; + /* Create the PDO */ + Status = PnpRootCreateDevice(&ServiceName, + &Pdo, + NULL); + if (!NT_SUCCESS(Status)) + { + DPRINT("PnpRootCreateDevice() failed (Status 0x%08lx)\n", Status); + return Status; + } - /* create a new PDO and return it in *DeviceObject */ + /* Create the device node for the new PDO */ Status = IopCreateDeviceNode(IopRootDeviceNode, + Pdo, NULL, - &ServiceName, &DeviceNode); if (!NT_SUCCESS(Status)) @@ -60,17 +180,133 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject, DPRINT("IopCreateDeviceNode() failed (Status 0x%08lx)\n", Status); return Status; } + } - Pdo = DeviceNode->PhysicalDeviceObject; - if (DeviceObject) *DeviceObject = Pdo; - } + /* We don't call AddDevice for devices reported this way */ + IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED); - /* we don't need to call AddDevice and send IRP_MN_START_DEVICE */ - return Status; + /* We don't send IRP_MN_START_DEVICE */ + IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED); + + /* This is a legacy driver for this device */ + IopDeviceNodeSetFlag(DeviceNode, DNF_LEGACY_DRIVER); + + /* Perform a manual configuration of our device */ + IopActionInterrogateDeviceStack(DeviceNode, DeviceNode->Parent); + IopActionConfigureChildServices(DeviceNode, DeviceNode->Parent); + + /* Open a handle to the instance path key */ + Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, &InstanceKey); + if (!NT_SUCCESS(Status)) + return Status; + + /* Add DETECTEDInterfaceType\DriverName */ + IdLength = 0; + IdLength += swprintf(&HardwareId[IdLength], + L"DETECTED%ls\\%wZ", + IfString, + &ServiceName); + HardwareId[IdLength++] = UNICODE_NULL; + + /* Add DETECTED\DriverName */ + IdLength += swprintf(&HardwareId[IdLength], + L"DETECTED\\%wZ", + &ServiceName); + HardwareId[IdLength++] = UNICODE_NULL; + + /* Terminate the string with another null */ + HardwareId[IdLength] = UNICODE_NULL; + + /* Store the value for CompatibleIDs */ + RtlInitUnicodeString(&ValueName, L"CompatibleIDs"); + Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_MULTI_SZ, HardwareId, IdLength * sizeof(WCHAR)); + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed to write the compatible IDs: 0x%x\n", Status); + ZwClose(InstanceKey); + return Status; + } + + /* Add a hardware ID if the driver didn't report one */ + RtlInitUnicodeString(&ValueName, L"HardwareID"); + if (ZwQueryValueKey(InstanceKey, &ValueName, KeyValueBasicInformation, NULL, 0, &RequiredLength) == STATUS_OBJECT_NAME_NOT_FOUND) + { + /* Just use our most specific compatible ID */ + IdLength = 0; + IdLength += swprintf(&HardwareId[IdLength], + L"DETECTED%ls\\%wZ", + IfString, + &ServiceName); + HardwareId[++IdLength] = UNICODE_NULL; + + /* Write the value to the registry */ + Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_SZ, HardwareId, IdLength * sizeof(WCHAR)); + if (!NT_SUCCESS(Status)) + { + DPRINT("Failed to write the hardware ID: 0x%x\n", Status); + ZwClose(InstanceKey); + return Status; + } + } + + /* Assign the resources to the device node */ + DeviceNode->BootResources = ResourceList; + DeviceNode->ResourceRequirements = ResourceRequirements; + + /* Set appropriate flags */ + if (DeviceNode->BootResources) + IopDeviceNodeSetFlag(DeviceNode, DNF_HAS_BOOT_CONFIG); + + if (DeviceNode->ResourceRequirements) + IopDeviceNodeSetFlag(DeviceNode, DNF_RESOURCE_REPORTED); + else + IopDeviceNodeSetFlag(DeviceNode, DNF_NO_RESOURCE_REQUIRED); + + /* Write the resource information to the registry */ + IopSetDeviceInstanceData(InstanceKey, DeviceNode); + + /* Close the instance key handle */ + ZwClose(InstanceKey); + + /* If the caller didn't get the resources assigned for us, do it now */ + if (!ResourceAssigned) + { + IopDeviceNodeSetFlag(DeviceNode, DNF_ASSIGNING_RESOURCES); + Status = IopAssignDeviceResources(DeviceNode, &RequiredLength); + if (NT_SUCCESS(Status)) + { + Status = IopTranslateDeviceResources(DeviceNode, RequiredLength); + if (NT_SUCCESS(Status)) + Status = IopUpdateResourceMapForPnPDevice(DeviceNode); + } + IopDeviceNodeClearFlag(DeviceNode, DNF_ASSIGNING_RESOURCES); + + /* See if we failed */ + if (!NT_SUCCESS(Status)) + { + DPRINT("Assigning resources failed: 0x%x\n", Status); + return Status; + } + } + + /* Report the device's enumeration to umpnpmgr */ + IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED, + &DeviceNode->InstancePath); + + /* Report the device's arrival to umpnpmgr */ + IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL, + &DeviceNode->InstancePath); + + DPRINT1("Reported device: %S (%wZ)\n", HardwareId, &DeviceNode->InstancePath); + + /* Return the PDO */ + if (DeviceObject) *DeviceObject = Pdo; + + return STATUS_SUCCESS; } /* - * @unimplemented + * @halfplemented */ NTSTATUS NTAPI @@ -82,23 +318,35 @@ IoReportResourceForDetection(IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceListSize OPTIONAL, OUT PBOOLEAN ConflictDetected) { - static int warned = 0; - if (!warned) - { - DPRINT1("IoReportResourceForDetection partly implemented\n"); - warned = 1; - } + PCM_RESOURCE_LIST ResourceList; + NTSTATUS Status; *ConflictDetected = FALSE; - if (PopSystemPowerDeviceNode && DriverListSize > 0) + if (!DriverList && !DeviceList) + return STATUS_INVALID_PARAMETER; + + /* Find the real list */ + if (!DriverList) + ResourceList = DeviceList; + else + ResourceList = DriverList; + + /* Look for a resource conflict */ + Status = IopDetectResourceConflict(ResourceList); + if (Status == STATUS_CONFLICTING_ADDRESSES) { - /* We hope legacy devices will be enumerated by ACPI */ + /* Oh noes */ *ConflictDetected = TRUE; - return STATUS_CONFLICTING_ADDRESSES; + } + else if (NT_SUCCESS(Status)) + { + /* Looks like we're good to go */ + + /* TODO: Claim the resources in the ResourceMap */ } - return STATUS_SUCCESS; + return Status; } VOID diff --git a/ntoskrnl/io/pnpmgr/pnproot.c b/ntoskrnl/io/pnpmgr/pnproot.c index 5a5bf85c3eb..63a3dd59c70 100644 --- a/ntoskrnl/io/pnpmgr/pnproot.c +++ b/ntoskrnl/io/pnpmgr/pnproot.c @@ -33,7 +33,6 @@ typedef struct _PNPROOT_DEVICE UNICODE_STRING DeviceDescription; // Resource requirement list PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList; - ULONG ResourceRequirementsListSize; // Associated resource list PCM_RESOURCE_LIST ResourceList; ULONG ResourceListSize; @@ -131,30 +130,25 @@ LocateChildDevice( NTSTATUS PnpRootCreateDevice( IN PUNICODE_STRING ServiceName, - IN PDEVICE_OBJECT *PhysicalDeviceObject) + OUT PDEVICE_OBJECT *PhysicalDeviceObject, + OUT OPTIONAL PUNICODE_STRING FullInstancePath) { PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension; - UNICODE_STRING UnknownServiceName = RTL_CONSTANT_STRING(L"UNKNOWN"); - PUNICODE_STRING LocalServiceName; PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension; WCHAR DevicePath[MAX_PATH + 1]; WCHAR InstancePath[5]; PPNPROOT_DEVICE Device = NULL; NTSTATUS Status; ULONG i; + UNICODE_STRING PathSep = RTL_CONSTANT_STRING(L"\\"); DeviceExtension = PnpRootDeviceObject->DeviceExtension; KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock); - if (ServiceName) - LocalServiceName = ServiceName; - else - LocalServiceName = &UnknownServiceName; - - DPRINT("Creating a PnP root device for service '%wZ'\n", LocalServiceName); + DPRINT("Creating a PnP root device for service '%wZ'\n", ServiceName); /* Search for a free instance ID */ - _snwprintf(DevicePath, sizeof(DevicePath) / sizeof(WCHAR), L"%s\\LEGACY_%wZ", REGSTR_KEY_ROOTENUM, LocalServiceName); + _snwprintf(DevicePath, sizeof(DevicePath) / sizeof(WCHAR), L"%s\\%wZ", REGSTR_KEY_ROOTENUM, ServiceName); for (i = 0; i < 9999; i++) { _snwprintf(InstancePath, sizeof(InstancePath) / sizeof(WCHAR), L"%04lu", i); @@ -164,7 +158,7 @@ PnpRootCreateDevice( } if (i == 9999) { - DPRINT1("Too much legacy devices reported for service '%wZ'\n", &LocalServiceName); + DPRINT1("Too much legacy devices reported for service '%wZ'\n", ServiceName); Status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } @@ -189,6 +183,22 @@ PnpRootCreateDevice( goto cleanup; } + if (FullInstancePath) + { + FullInstancePath->MaximumLength = Device->DeviceID.Length + PathSep.Length + Device->InstanceID.Length; + FullInstancePath->Length = 0; + FullInstancePath->Buffer = ExAllocatePool(PagedPool, FullInstancePath->MaximumLength); + if (!FullInstancePath->Buffer) + { + Status = STATUS_NO_MEMORY; + goto cleanup; + } + + RtlAppendUnicodeStringToString(FullInstancePath, &Device->DeviceID); + RtlAppendUnicodeStringToString(FullInstancePath, &PathSep); + RtlAppendUnicodeStringToString(FullInstancePath, &Device->InstanceID); + } + /* Initialize a device object */ Status = IoCreateDevice( PnpRootDeviceObject->DriverObject, @@ -666,24 +676,27 @@ PnpRootFdoPnpControl( if (NT_SUCCESS(Status)) DeviceExtension->State = dsStarted; } - break; + + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; case IRP_MN_STOP_DEVICE: DPRINT("IRP_MJ_PNP / IRP_MN_STOP_DEVICE\n"); /* Root device cannot be stopped */ - Status = STATUS_NOT_SUPPORTED; - break; + Irp->IoStatus.Status = Status = STATUS_INVALID_DEVICE_REQUEST; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; default: DPRINT("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp->MinorFunction); - Status = STATUS_NOT_IMPLEMENTED; break; } if (Status != STATUS_PENDING) { - Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + Irp->IoStatus.Status = Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); } return Status; @@ -696,48 +709,25 @@ PdoQueryDeviceRelations( IN PIO_STACK_LOCATION IrpSp) { PDEVICE_RELATIONS Relations; - DEVICE_RELATION_TYPE RelationType; NTSTATUS Status = Irp->IoStatus.Status; - RelationType = IrpSp->Parameters.QueryDeviceRelations.Type; + if (IrpSp->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation) + return Status; - switch (RelationType) + DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n"); + Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS)); + if (!Relations) { - /* FIXME: remove */ - case BusRelations: - { - if (IoGetAttachedDevice(DeviceObject) != DeviceObject) - { - /* We're not alone in the stack */ - DPRINT1("PnP is misbehaving ; don't know how to handle IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n"); - } - break; - } - - case TargetDeviceRelation: - { - DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n"); - Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS)); - if (!Relations) - { - DPRINT("ExAllocatePoolWithTag() failed\n"); - Status = STATUS_NO_MEMORY; - } - else - { - ObReferenceObject(DeviceObject); - Relations->Count = 1; - Relations->Objects[0] = DeviceObject; - Status = STATUS_SUCCESS; - Irp->IoStatus.Information = (ULONG_PTR)Relations; - } - break; - } - - default: - { - DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / unknown relation type 0x%lx\n", RelationType); - } + DPRINT("ExAllocatePoolWithTag() failed\n"); + Status = STATUS_NO_MEMORY; + } + else + { + ObReferenceObject(DeviceObject); + Relations->Count = 1; + Relations->Objects[0] = DeviceObject; + Status = STATUS_SUCCESS; + Irp->IoStatus.Information = (ULONG_PTR)Relations; } return Status; @@ -775,35 +765,29 @@ PdoQueryResources( DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - if (DeviceExtension->DeviceInfo->ResourceList == NULL) - { - /* Create an empty resource list */ - ResourceList = ExAllocatePool(PagedPool, sizeof(CM_RESOURCE_LIST)); - if (!ResourceList) - return STATUS_NO_MEMORY; - - ResourceList->Count = 0; - - Irp->IoStatus.Information = (ULONG_PTR)ResourceList; - } - else + if (DeviceExtension->DeviceInfo->ResourceList) { /* Copy existing resource requirement list */ ResourceList = ExAllocatePool( PagedPool, - FIELD_OFFSET(CM_RESOURCE_LIST, List) + DeviceExtension->DeviceInfo->ResourceListSize); + DeviceExtension->DeviceInfo->ResourceListSize); if (!ResourceList) return STATUS_NO_MEMORY; - ResourceList->Count = 1; RtlCopyMemory( - &ResourceList->List, + ResourceList, DeviceExtension->DeviceInfo->ResourceList, DeviceExtension->DeviceInfo->ResourceListSize); - Irp->IoStatus.Information = (ULONG_PTR)ResourceList; - } - return STATUS_SUCCESS; + Irp->IoStatus.Information = (ULONG_PTR)ResourceList; + + return STATUS_SUCCESS; + } + else + { + /* No resources so just return without changing the status */ + return Irp->IoStatus.Status; + } } static NTSTATUS @@ -814,23 +798,10 @@ PdoQueryResourceRequirements( { PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension; PIO_RESOURCE_REQUIREMENTS_LIST ResourceList; - ULONG ResourceListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List); DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; - if (DeviceExtension->DeviceInfo->ResourceRequirementsList == NULL) - { - /* Create an empty resource list */ - ResourceList = ExAllocatePool(PagedPool, ResourceListSize); - if (!ResourceList) - return STATUS_NO_MEMORY; - - RtlZeroMemory(ResourceList, ResourceListSize); - ResourceList->ListSize = ResourceListSize; - - Irp->IoStatus.Information = (ULONG_PTR)ResourceList; - } - else + if (DeviceExtension->DeviceInfo->ResourceRequirementsList) { /* Copy existing resource requirement list */ ResourceList = ExAllocatePool(PagedPool, DeviceExtension->DeviceInfo->ResourceRequirementsList->ListSize); @@ -841,10 +812,16 @@ PdoQueryResourceRequirements( ResourceList, DeviceExtension->DeviceInfo->ResourceRequirementsList, DeviceExtension->DeviceInfo->ResourceRequirementsList->ListSize); - Irp->IoStatus.Information = (ULONG_PTR)ResourceList; - } - return STATUS_SUCCESS; + Irp->IoStatus.Information = (ULONG_PTR)ResourceList; + + return STATUS_SUCCESS; + } + else + { + /* No resource requirements so just return without changing the status */ + return Irp->IoStatus.Status; + } } static NTSTATUS diff --git a/ntoskrnl/io/pnpmgr/pnputil.c b/ntoskrnl/io/pnpmgr/pnputil.c new file mode 100644 index 00000000000..f274f3db679 --- /dev/null +++ b/ntoskrnl/io/pnpmgr/pnputil.c @@ -0,0 +1,185 @@ +/* + * PROJECT: ReactOS Kernel + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: ntoskrnl/io/pnpmgr/pnputil.c + * PURPOSE: PnP Utility Code + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +/* FUNCTIONS ******************************************************************/ + +VOID +NTAPI +PnpFreeUnicodeStringList(IN PUNICODE_STRING UnicodeStringList, + IN ULONG StringCount) +{ + ULONG i; + + /* Go through the list */ + if (UnicodeStringList) + { + /* Go through each string */ + for (i = 0; i < StringCount; i++) + { + /* Check if it exists */ + if (UnicodeStringList[i].Buffer) + { + /* Free it */ + ExFreePool(UnicodeStringList[i].Buffer); + } + } + + /* Free the whole list */ + ExFreePool(UnicodeStringList); + } +} + +NTSTATUS +NTAPI +PnpRegMultiSzToUnicodeStrings(IN PKEY_VALUE_FULL_INFORMATION KeyValueInformation, + OUT PUNICODE_STRING *UnicodeStringList, + OUT PULONG UnicodeStringCount) +{ + PWCHAR p, pp, ps; + ULONG i = 0, n; + ULONG Count = 0; + + /* Validate the key information */ + if (KeyValueInformation->Type != REG_MULTI_SZ) return STATUS_INVALID_PARAMETER; + + /* Set the pointers */ + p = (PWCHAR)((ULONG_PTR)KeyValueInformation + + KeyValueInformation->DataOffset); + pp = (PWCHAR)((ULONG_PTR)p + KeyValueInformation->DataLength); + + /* Loop the data */ + while (p != pp) + { + /* If we find a NULL, that means one string is done */ + if (!*p) + { + /* Add to our string count */ + Count++; + + /* Check for a double-NULL, which means we're done */ + if (((p + 1) == pp) || !(*(p + 1))) break; + } + + /* Go to the next character */ + p++; + } + + /* If we looped the whole list over, we missed increment a string, do it */ + if (p == pp) Count++; + + /* Allocate the list now that we know how big it is */ + *UnicodeStringList = ExAllocatePoolWithTag(PagedPool, + sizeof(UNICODE_STRING) * Count, + 'sUpP'); + if (!(*UnicodeStringList)) return STATUS_INSUFFICIENT_RESOURCES; + + /* Set pointers for second loop */ + ps = p = (PWCHAR)((ULONG_PTR)KeyValueInformation + + KeyValueInformation->DataOffset); + + /* Loop again, to do the copy this time */ + while (p != pp) + { + /* If we find a NULL, that means one string is done */ + if (!*p) + { + /* Check how long this string is */ + n = (ULONG_PTR)p - (ULONG_PTR)ps + sizeof(UNICODE_NULL); + + /* Allocate the buffer */ + (*UnicodeStringList)[i].Buffer = ExAllocatePoolWithTag(PagedPool, + n, + 'sUpP'); + if (!(*UnicodeStringList)[i].Buffer) + { + /* Back out of everything */ + PnpFreeUnicodeStringList(*UnicodeStringList, i); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Copy the string into the buffer */ + RtlCopyMemory((*UnicodeStringList)[i].Buffer, ps, n); + + /* Set the lengths */ + (*UnicodeStringList)[i].MaximumLength = n; + (*UnicodeStringList)[i].Length = n - sizeof(UNICODE_NULL); + + /* One more entry done */ + i++; + + /* Check for a double-NULL, which means we're done */ + if (((p + 1) == pp) || !(*(p + 1))) break; + + /* New string */ + ps = p + 1; + } + + /* New string */ + p++; + } + + /* Check if we've reached the last string */ + if (p == pp) + { + /* Calculate the string length */ + n = (ULONG_PTR)p - (ULONG_PTR)ps; + + /* Allocate the buffer for it */ + (*UnicodeStringList)[i].Buffer = ExAllocatePoolWithTag(PagedPool, + n + + sizeof(UNICODE_NULL), + 'sUpP'); + if (!(*UnicodeStringList)[i].Buffer) + { + /* Back out of everything */ + PnpFreeUnicodeStringList(*UnicodeStringList, i); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* Make sure there's an actual string here */ + if (n) RtlCopyMemory((*UnicodeStringList)[i].Buffer, ps, n); + + /* Null-terminate the string ourselves */ + (*UnicodeStringList)[i].Buffer[n / sizeof(WCHAR)] = UNICODE_NULL; + + /* Set the lenghts */ + (*UnicodeStringList)[i].Length = n; + (*UnicodeStringList)[i].MaximumLength = n + sizeof(UNICODE_NULL); + } + + /* And we're done */ + *UnicodeStringCount = Count; + return STATUS_SUCCESS; +} + +BOOLEAN +NTAPI +PnpRegSzToString(IN PWCHAR RegSzData, + IN ULONG RegSzLength, + OUT PUSHORT StringLength OPTIONAL) +{ + PWCHAR p, pp; + + /* Find the end */ + pp = RegSzData + RegSzLength; + for (p = RegSzData; p < pp; p++) if (!*p) break; + + /* Return it */ + if (StringLength) *StringLength = p - RegSzData; + return TRUE; +} + +/* EOF */ diff --git a/ntoskrnl/ntoskrnl-generic.rbuild b/ntoskrnl/ntoskrnl-generic.rbuild index a605ee1b147..a349f887312 100644 --- a/ntoskrnl/ntoskrnl-generic.rbuild +++ b/ntoskrnl/ntoskrnl-generic.rbuild @@ -244,7 +244,6 @@ device.c deviface.c driver.c - drvrlist.c error.c file.c iocomp.c @@ -267,10 +266,12 @@ plugplay.c pnpdma.c + pnpinit.c pnpmgr.c pnpnotify.c pnpreport.c pnproot.c + pnputil.c diff --git a/ntoskrnl/se/semgr.c b/ntoskrnl/se/semgr.c index d06fb04bbb6..0cb0da49e07 100644 --- a/ntoskrnl/se/semgr.c +++ b/ntoskrnl/se/semgr.c @@ -314,6 +314,31 @@ SepSidInToken(PACCESS_TOKEN _Token, return FALSE; } +static BOOLEAN +SepTokenIsOwner(PACCESS_TOKEN Token, + PSECURITY_DESCRIPTOR SecurityDescriptor) +{ + NTSTATUS Status; + PSID Sid = NULL; + BOOLEAN Defaulted; + + Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor, + &Sid, + &Defaulted); + if (!NT_SUCCESS(Status)) + { + DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status); + return FALSE; + } + + if (Sid == NULL) + { + DPRINT1("Owner Sid is NULL\n"); + return FALSE; + } + + return SepSidInToken(Token, Sid); +} VOID NTAPI SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation, @@ -364,7 +389,10 @@ SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, OUT PNTSTATUS AccessStatus) { LUID_AND_ATTRIBUTES Privilege; - ACCESS_MASK CurrentAccess, AccessMask; + ACCESS_MASK RemainingAccess; + ACCESS_MASK TempAccess; + ACCESS_MASK TempGrantedAccess = 0; + ACCESS_MASK TempDeniedAccess = 0; PACCESS_TOKEN Token; ULONG i; PACL Dacl; @@ -398,15 +426,42 @@ SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, if (PreviouslyGrantedAccess) RtlMapGenericMask(&PreviouslyGrantedAccess, GenericMapping); - - - CurrentAccess = PreviouslyGrantedAccess; - - + /* Initialize remaining access rights */ + RemainingAccess = DesiredAccess; Token = SubjectSecurityContext->ClientToken ? SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken; + /* Check for system security access */ + if (RemainingAccess & ACCESS_SYSTEM_SECURITY) + { + Privilege.Luid = SeSecurityPrivilege; + Privilege.Attributes = SE_PRIVILEGE_ENABLED; + + /* Fail if we do not the SeSecurityPrivilege */ + if (!SepPrivilegeCheck(Token, + &Privilege, + 1, + PRIVILEGE_SET_ALL_NECESSARY, + AccessMode)) + { + *AccessStatus = STATUS_PRIVILEGE_NOT_HELD; + return FALSE; + } + + /* Adjust access rights */ + RemainingAccess &= ~ACCESS_SYSTEM_SECURITY; + PreviouslyGrantedAccess |= ACCESS_SYSTEM_SECURITY; + + /* Succeed if there are no more rights to grant */ + if (RemainingAccess == 0) + { + *GrantedAccess = PreviouslyGrantedAccess; + *AccessStatus = STATUS_SUCCESS; + return TRUE; + } + } + /* Get the DACL */ Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor, &Present, @@ -435,57 +490,47 @@ SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, return TRUE; } - CurrentAccess = PreviouslyGrantedAccess; - /* RULE 2: Check token for 'take ownership' privilege */ - Privilege.Luid = SeTakeOwnershipPrivilege; - Privilege.Attributes = SE_PRIVILEGE_ENABLED; - - if (SepPrivilegeCheck(Token, - &Privilege, - 1, - PRIVILEGE_SET_ALL_NECESSARY, - AccessMode)) + if (DesiredAccess & WRITE_OWNER) { - CurrentAccess |= WRITE_OWNER; - if ((DesiredAccess & ~VALID_INHERIT_FLAGS) == - (CurrentAccess & ~VALID_INHERIT_FLAGS)) + Privilege.Luid = SeTakeOwnershipPrivilege; + Privilege.Attributes = SE_PRIVILEGE_ENABLED; + + if (SepPrivilegeCheck(Token, + &Privilege, + 1, + PRIVILEGE_SET_ALL_NECESSARY, + AccessMode)) { - *GrantedAccess = CurrentAccess; - *AccessStatus = STATUS_SUCCESS; - return TRUE; + /* Adjust access rights */ + RemainingAccess &= ~WRITE_OWNER; + PreviouslyGrantedAccess |= WRITE_OWNER; + + /* Succeed if there are no more rights to grant */ + if (RemainingAccess == 0) + { + *GrantedAccess = PreviouslyGrantedAccess; + *AccessStatus = STATUS_SUCCESS; + return TRUE; + } } } /* Deny access if the DACL is empty */ if (Dacl->AceCount == 0) { - *GrantedAccess = 0; - *AccessStatus = STATUS_ACCESS_DENIED; - return FALSE; - } - - /* RULE 3: Check whether the token is the owner */ - Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor, - &Sid, - &Defaulted); - if (!NT_SUCCESS(Status)) - { - DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status); - *AccessStatus = Status; - return FALSE; - } - - if (Sid && SepSidInToken(Token, Sid)) - { - CurrentAccess |= (READ_CONTROL | WRITE_DAC); - if ((DesiredAccess & ~VALID_INHERIT_FLAGS) == - (CurrentAccess & ~VALID_INHERIT_FLAGS)) + if (RemainingAccess == MAXIMUM_ALLOWED && PreviouslyGrantedAccess != 0) { - *GrantedAccess = CurrentAccess; + *GrantedAccess = PreviouslyGrantedAccess; *AccessStatus = STATUS_SUCCESS; return TRUE; } + else + { + *GrantedAccess = 0; + *AccessStatus = STATUS_ACCESS_DENIED; + return FALSE; + } } /* Fail if DACL is absent */ @@ -496,63 +541,139 @@ SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, return FALSE; } + /* Determine the MAXIMUM_ALLOWED access rights according to the DACL */ + if (DesiredAccess & MAXIMUM_ALLOWED) + { + CurrentAce = (PACE)(Dacl + 1); + for (i = 0; i < Dacl->AceCount; i++) + { + if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE)) + { + Sid = (PSID)(CurrentAce + 1); + if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE) + { + if (SepSidInToken(Token, Sid)) + { + /* Map access rights from the ACE */ + TempAccess = CurrentAce->AccessMask; + RtlMapGenericMask(&TempAccess, GenericMapping); + + /* Deny access rights that have not been granted yet */ + TempDeniedAccess |= (TempAccess & ~TempGrantedAccess); + } + } + else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) + { + if (SepSidInToken(Token, Sid)) + { + /* Map access rights from the ACE */ + TempAccess = CurrentAce->AccessMask; + RtlMapGenericMask(&TempAccess, GenericMapping); + + /* Grant access rights that have not been denied yet */ + TempGrantedAccess |= (TempAccess & ~TempDeniedAccess); + } + } + else + { + DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType); + } + } + + /* Get the next ACE */ + CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize); + } + + /* Fail if some rights have not been granted */ + RemainingAccess &= ~(MAXIMUM_ALLOWED | TempGrantedAccess); + if (RemainingAccess != 0) + { + *GrantedAccess = 0; + *AccessStatus = STATUS_ACCESS_DENIED; + return FALSE; + } + + /* Set granted access right and access status */ + *GrantedAccess = TempGrantedAccess | PreviouslyGrantedAccess; + if (*GrantedAccess != 0) + { + *AccessStatus = STATUS_SUCCESS; + return TRUE; + } + else + { + *AccessStatus = STATUS_ACCESS_DENIED; + return FALSE; + } + } + /* RULE 4: Grant rights according to the DACL */ CurrentAce = (PACE)(Dacl + 1); for (i = 0; i < Dacl->AceCount; i++) { - Sid = (PSID)(CurrentAce + 1); - if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE) + if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE)) { - if (SepSidInToken(Token, Sid)) + Sid = (PSID)(CurrentAce + 1); + if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE) { - *GrantedAccess = 0; - *AccessStatus = STATUS_ACCESS_DENIED; - return FALSE; + if (SepSidInToken(Token, Sid)) + { + /* Map access rights from the ACE */ + TempAccess = CurrentAce->AccessMask; + RtlMapGenericMask(&TempAccess, GenericMapping); + + /* Leave if a remaining right must be denied */ + if (RemainingAccess & TempAccess) + break; + } + } + else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) + { + if (SepSidInToken(Token, Sid)) + { + /* Map access rights from the ACE */ + TempAccess = CurrentAce->AccessMask; + RtlMapGenericMask(&TempAccess, GenericMapping); + + /* Remove granted rights */ + RemainingAccess &= ~TempAccess; + } + } + else + { + DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType); } } - else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE) - { - if (SepSidInToken(Token, Sid)) - { - AccessMask = CurrentAce->AccessMask; - RtlMapGenericMask(&AccessMask, GenericMapping); - CurrentAccess |= AccessMask; - } - } - else - { - DPRINT1("Unknown Ace type 0x%lx\n", CurrentAce->Header.AceType); - } + /* Get the next ACE */ CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize); } - DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n", - CurrentAccess, DesiredAccess); + DPRINT("DesiredAccess %08lx\nPreviouslyGrantedAccess %08lx\nRemainingAccess %08lx\n", + DesiredAccess, PreviouslyGrantedAccess, RemainingAccess); - *GrantedAccess = CurrentAccess & DesiredAccess; + /* Fail if some rights have not been granted */ + if (RemainingAccess != 0) + { + *GrantedAccess = 0; + *AccessStatus = STATUS_ACCESS_DENIED; + return FALSE; + } - if (DesiredAccess & MAXIMUM_ALLOWED) + /* Set granted access rights */ + *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess; + + DPRINT("GrantedAccess %08lx\n", *GrantedAccess); + + /* Fail if no rights have been granted */ + if (*GrantedAccess == 0) { - *GrantedAccess = CurrentAccess; - *AccessStatus = STATUS_SUCCESS; - return TRUE; - } - else if ((*GrantedAccess & ~VALID_INHERIT_FLAGS) == - (DesiredAccess & ~VALID_INHERIT_FLAGS)) - { - *AccessStatus = STATUS_SUCCESS; - return TRUE; - } - else - { - DPRINT1("HACK: Should deny access for caller: granted 0x%lx, desired 0x%lx (generic mapping %p).\n", - *GrantedAccess, DesiredAccess, GenericMapping); - //*AccessStatus = STATUS_ACCESS_DENIED; - //return FALSE; - *AccessStatus = STATUS_SUCCESS; - return TRUE; + *AccessStatus = STATUS_ACCESS_DENIED; + return FALSE; } + + *AccessStatus = STATUS_SUCCESS; + return TRUE; } static PSID @@ -649,16 +770,43 @@ SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, if (!SubjectContextLocked) SeLockSubjectContext(SubjectSecurityContext); - /* Call the internal function */ - ret = SepAccessCheck(SecurityDescriptor, - SubjectSecurityContext, - DesiredAccess, - PreviouslyGrantedAccess, - Privileges, - GenericMapping, - AccessMode, - GrantedAccess, - AccessStatus); + /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */ + if (DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED)) + { + PACCESS_TOKEN Token = SubjectSecurityContext->ClientToken ? + SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken; + + if (SepTokenIsOwner(Token, + SecurityDescriptor)) + { + if (DesiredAccess & MAXIMUM_ALLOWED) + PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL); + else + PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL)); + + DesiredAccess &= ~(WRITE_DAC | READ_CONTROL); + } + } + + if (DesiredAccess == 0) + { + *GrantedAccess = PreviouslyGrantedAccess; + *AccessStatus = STATUS_SUCCESS; + ret = TRUE; + } + else + { + /* Call the internal function */ + ret = SepAccessCheck(SecurityDescriptor, + SubjectSecurityContext, + DesiredAccess, + PreviouslyGrantedAccess, + Privileges, + GenericMapping, + AccessMode, + GrantedAccess, + AccessStatus); + } /* Release the lock if needed */ if (!SubjectContextLocked) @@ -686,6 +834,7 @@ NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, PSECURITY_DESCRIPTOR CapturedSecurityDescriptor = NULL; SECURITY_SUBJECT_CONTEXT SubjectSecurityContext; KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + ACCESS_MASK PreviouslyGrantedAccess = 0; PTOKEN Token; NTSTATUS Status; PAGED_CODE(); @@ -801,16 +950,38 @@ NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor, SubjectSecurityContext.ProcessAuditId = NULL; SeLockSubjectContext(&SubjectSecurityContext); - /* Now perform the access check */ - SepAccessCheck(SecurityDescriptor, // FIXME: use CapturedSecurityDescriptor - &SubjectSecurityContext, - DesiredAccess, - 0, - &PrivilegeSet, //FIXME - GenericMapping, - PreviousMode, - GrantedAccess, - AccessStatus); + /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */ + if (DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED)) + { + if (SepTokenIsOwner(Token, SecurityDescriptor)) // FIXME: use CapturedSecurityDescriptor + { + if (DesiredAccess & MAXIMUM_ALLOWED) + PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL); + else + PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL)); + + DesiredAccess &= ~(WRITE_DAC | READ_CONTROL); + } + } + + if (DesiredAccess == 0) + { + *GrantedAccess = PreviouslyGrantedAccess; + *AccessStatus = STATUS_SUCCESS; + } + else + { + /* Now perform the access check */ + SepAccessCheck(SecurityDescriptor, // FIXME: use CapturedSecurityDescriptor + &SubjectSecurityContext, + DesiredAccess, + PreviouslyGrantedAccess, + &PrivilegeSet, //FIXME + GenericMapping, + PreviousMode, + GrantedAccess, + AccessStatus); + } /* Unlock subject context */ SeUnlockSubjectContext(&SubjectSecurityContext); diff --git a/subsystems/win32/win32k/eng/pdevobj.c b/subsystems/win32/win32k/eng/pdevobj.c index d1d52e5f2b9..61bc0756692 100644 --- a/subsystems/win32/win32k/eng/pdevobj.c +++ b/subsystems/win32/win32k/eng/pdevobj.c @@ -786,3 +786,20 @@ NtGdiGetDhpdev( return dhpdev; } + +PSIZEL +FASTCALL +PDEVOBJ_sizl(PPDEVOBJ ppdev, PSIZEL psizl) +{ + if (ppdev->flFlags & PDEV_META_DEVICE) + { + psizl->cx = ppdev->ulHorzRes; + psizl->cy = ppdev->ulVertRes; + } + else + { + psizl->cx = ppdev->gdiinfo.ulHorzRes; + psizl->cy = ppdev->gdiinfo.ulVertRes; + } + return psizl; +} diff --git a/subsystems/win32/win32k/include/dc.h b/subsystems/win32/win32k/include/dc.h index a209ff28adb..8578f8e7070 100644 --- a/subsystems/win32/win32k/include/dc.h +++ b/subsystems/win32/win32k/include/dc.h @@ -245,6 +245,8 @@ VOID FASTCALL IntGdiUnreferencePdev(PPDEVOBJ pPDev, DWORD CleanUpType); HDC FASTCALL IntGdiCreateDisplayDC(HDEV hDev, ULONG DcType, BOOL EmptyDC); BOOL FASTCALL IntGdiCleanDC(HDC hDC); VOID FASTCALL IntvGetDeviceCaps(PPDEVOBJ, PDEVCAPS); +BOOL FASTCALL MakeInfoDC(PDC,BOOL); +BOOL FASTCALL IntSetDefaultRegion(PDC); VOID FORCEINLINE diff --git a/subsystems/win32/win32k/include/pdevobj.h b/subsystems/win32/win32k/include/pdevobj.h index 0e868a7006a..076e8d8d3dc 100644 --- a/subsystems/win32/win32k/include/pdevobj.h +++ b/subsystems/win32/win32k/include/pdevobj.h @@ -48,7 +48,7 @@ typedef struct { DWORD dwFlags; PDEVMODEW pdm; - + } DEVMODEENTRY, *PDEVMODEENTRY; typedef struct _GRAPHICS_DEVICE @@ -104,8 +104,8 @@ typedef struct _PDEVOBJ // PVOID TypeOneInfo; PVOID pvGammaRamp; /* Gamma ramp pointer. */ // PVOID RemoteTypeOne; -// ULONG ulHorzRes; -// ULONG ulVertRes; + ULONG ulHorzRes; + ULONG ulVertRes; // PFN_DrvSetPointerShape pfnDrvSetPointerShape; // PFN_DrvMovePointer pfnDrvMovePointer; PFN_DrvMovePointer pfnMovePointer; @@ -123,7 +123,7 @@ typedef struct _PDEVOBJ // HANDLE hSpooler; /* Handle to spooler, if spooler dev driver. */ // PVOID pDesktopId; PGRAPHICS_DEVICE pGraphicsDevice; -// POINTL ptlOrigion; + POINTL ptlOrigion; PDEVMODEW pdmwDev; /* Ptr->DEVMODEW.dmSize + dmDriverExtra == alloc size. */ // DWORD Unknown3; FLONG DxDd_Flags; /* DxDD active status flags. */ @@ -186,4 +186,8 @@ BOOL NTAPI InitDeviceImpl(); +PSIZEL +FASTCALL +PDEVOBJ_sizl(PPDEVOBJ, PSIZEL); + #endif /* !__WIN32K_PDEVOBJ_H */ diff --git a/subsystems/win32/win32k/include/surface.h b/subsystems/win32/win32k/include/surface.h index 57a5ec24f85..3fe90540467 100644 --- a/subsystems/win32/win32k/include/surface.h +++ b/subsystems/win32/win32k/include/surface.h @@ -3,6 +3,8 @@ #include "win32.h" #include "gdiobj.h" +#define PDEV_SURFACE 0x80000000 + /* GDI surface object */ typedef struct _SURFACE { diff --git a/subsystems/win32/win32k/ntuser/display.c b/subsystems/win32/win32k/ntuser/display.c index 4f627d6727a..89b926aa449 100644 --- a/subsystems/win32/win32k/ntuser/display.c +++ b/subsystems/win32/win32k/ntuser/display.c @@ -772,9 +772,6 @@ UserChangeDisplaySettings( pdesk = IntGetActiveDesktop(); IntHideDesktop(pdesk); - co_IntShowDesktop(pdesk, ppdev->gdiinfo.ulHorzRes, ppdev->gdiinfo.ulVertRes); - - UserRedrawDesktop(); /* Send WM_DISPLAYCHANGE to all toplevel windows */ co_IntSendMessageTimeout(HWND_BROADCAST, @@ -784,6 +781,10 @@ UserChangeDisplaySettings( SMTO_NORMAL, 100, &ulResult); + + co_IntShowDesktop(pdesk, ppdev->gdiinfo.ulHorzRes, ppdev->gdiinfo.ulVertRes); + + UserRedrawDesktop(); } leave: diff --git a/subsystems/win32/win32k/objects/dclife.c b/subsystems/win32/win32k/objects/dclife.c index d7342846562..9e6b5b0f192 100644 --- a/subsystems/win32/win32k/objects/dclife.c +++ b/subsystems/win32/win32k/objects/dclife.c @@ -733,14 +733,74 @@ NtGdiDeleteObjectApp(HANDLE DCHandle) return IntGdiDeleteDC(DCHandle, FALSE); } +BOOL +FASTCALL +MakeInfoDC(PDC pdc, BOOL bSet) +{ + PSURFACE pSurface; + SIZEL sizl; + + /* Can not be a display DC. */ + if (pdc->fs & DC_FLAG_DISPLAY) return FALSE; + if (bSet) + { + if (pdc->fs & DC_FLAG_TEMPINFODC || pdc->dctype == DC_TYPE_DIRECT) + return FALSE; + + pSurface = pdc->dclevel.pSurface; + pdc->fs |= DC_FLAG_TEMPINFODC; + pdc->pSurfInfo = pSurface; + pdc->dctype = DC_TYPE_INFO; + pdc->dclevel.pSurface = NULL; + + PDEVOBJ_sizl(pdc->ppdev, &sizl); + + if ( sizl.cx == pdc->dclevel.sizl.cx && + sizl.cy == pdc->dclevel.sizl.cy ) + return TRUE; + + pdc->dclevel.sizl.cx = sizl.cx; + pdc->dclevel.sizl.cy = sizl.cy; + } + else + { + if (!(pdc->fs & DC_FLAG_TEMPINFODC) || pdc->dctype != DC_TYPE_INFO) + return FALSE; + + pSurface = pdc->pSurfInfo; + pdc->fs &= ~DC_FLAG_TEMPINFODC; + pdc->dclevel.pSurface = pSurface; + pdc->dctype = DC_TYPE_DIRECT; + pdc->pSurfInfo = NULL; + + if ( !pSurface || + (pSurface->SurfObj.sizlBitmap.cx == pdc->dclevel.sizl.cx && + pSurface->SurfObj.sizlBitmap.cy == pdc->dclevel.sizl.cy) ) + return TRUE; + + pdc->dclevel.sizl.cx = pSurface->SurfObj.sizlBitmap.cx; + pdc->dclevel.sizl.cy = pSurface->SurfObj.sizlBitmap.cy; + } + return IntSetDefaultRegion(pdc); +} + +/* +* @implemented +*/ BOOL APIENTRY NtGdiMakeInfoDC( IN HDC hdc, IN BOOL bSet) { - UNIMPLEMENTED; - ASSERT(FALSE); + BOOL Ret; + PDC pdc = DC_LockDc(hdc); + if (pdc) + { + Ret = MakeInfoDC(pdc, bSet); + DC_UnlockDc(pdc); + return Ret; + } return FALSE; } diff --git a/subsystems/win32/win32k/objects/dcutil.c b/subsystems/win32/win32k/objects/dcutil.c index 9721af3147f..a8c28ecb348 100644 --- a/subsystems/win32/win32k/objects/dcutil.c +++ b/subsystems/win32/win32k/objects/dcutil.c @@ -125,6 +125,71 @@ IntIsPrimarySurface(SURFOBJ *SurfObj) } #endif +BOOL +FASTCALL +IntSetDefaultRegion(PDC pdc) +{ + PSURFACE pSurface; + PROSRGNDATA prgn; + RECTL rclWnd, rclClip; + + IntGdiReleaseRaoRgn(pdc); + + rclWnd.left = 0; + rclWnd.top = 0; + rclWnd.right = pdc->dclevel.sizl.cx; + rclWnd.bottom = pdc->dclevel.sizl.cy; + rclClip = rclWnd; + +// EngAcquireSemaphoreShared(pdc->ppdev->hsemDevLock); + if (pdc->ppdev->flFlags & PDEV_META_DEVICE) + { + pSurface = pdc->dclevel.pSurface; + if (pSurface && pSurface->flFlags & PDEV_SURFACE) + { + rclClip.left += pdc->ppdev->ptlOrigion.x; + rclClip.top += pdc->ppdev->ptlOrigion.y; + rclClip.right += pdc->ppdev->ptlOrigion.x; + rclClip.bottom += pdc->ppdev->ptlOrigion.y; + } + } +// EngReleaseSemaphore(pdc->ppdev->hsemDevLock); + + prgn = pdc->prgnVis; + + if (prgn && prgn != prgnDefault) + { + REGION_SetRectRgn( prgn, + rclClip.left, + rclClip.top, + rclClip.right , + rclClip.bottom ); + } + else + { + prgn = IntSysCreateRectpRgn( rclClip.left, + rclClip.top, + rclClip.right , + rclClip.bottom ); + pdc->prgnVis = prgn; + } + + if (prgn) + { + pdc->ptlDCOrig.x = 0; + pdc->ptlDCOrig.y = 0; + pdc->erclWindow = rclWnd; + pdc->erclClip = rclClip; + /* Might be an InitDC or DCE....*/ + pdc->ptlFillOrigin.x = pdc->dcattr.VisRectRegion.Rect.right; + pdc->ptlFillOrigin.y = pdc->dcattr.VisRectRegion.Rect.bottom; + return TRUE; + } + + pdc->prgnVis = prgnDefault; + return FALSE; +} + BOOL APIENTRY NtGdiCancelDC(HDC hDC)