HMENU hViewMenu;
HMENU hSubMenu;
WCHAR szTemp[256];
+ SYSTEM_INFO sysInfo;
hMenu = GetMenu(hMainWnd);
hViewMenu = GetSubMenu(hMenu, 2);
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_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);
- 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);
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
*/
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)
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) );
{
_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);
+ }
}
}
case WM_CREATE:
return pThis->Init((LPCREATESTRUCT)lparam);
- case WM_NCDESTROY:
+ case WM_NCDESTROY:
delete pThis;
return 0;
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);
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
[Files.pci_mp]
ntkrnlmp.exe=,,,,,,,,,,ntoskrnl.exe,,2
-halmp.dll=,,,,,,,,,,hal.dll,,2
+halmps.dll=,,,,,,,,,,hal.dll,,2
[Display]
;<id> = <user friendly name>,<spare>,<service key name>,<hight>,<width>,<bpp>
/* 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) */
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;
}
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 */
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 */
#include "wine/debug.h"
#include "mmddk.h"
+#include <regstr.h>
WINE_DEFAULT_DEBUG_CHANNEL(devenum);
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));
}
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);
}
/**********************************************************************
LONG ref;
DWORD index;
HKEY hkey;
+ BOOL bInterface;
} EnumMonikerImpl;
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,
IPropertyBagVtbl *lpVtbl;
LONG ref;
HKEY hkey;
+ BOOL bInterface;
} RegPropBagImpl;
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))
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);
}
if (pData)
HeapFree(GetProcessHeap(), 0, pData);
+ if (This->bInterface)
+ RegCloseKey(hkey);
+
TRACE("<- %lx\n", res);
return res;
}
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)
rpb->lpVtbl = &IPropertyBag_Vtbl;
rpb->ref = 1;
rpb->hkey = hkey;
+ rpb->bInterface = bInterface;
+
*ppBag = (IPropertyBag*)rpb;
DEVENUM_LockModule();
return S_OK;
{
IUnknown * pObj = NULL;
IPropertyBag * pProp = NULL;
+ IPersistPropertyBag * pBag;
CLSID clsID;
VARIANT var;
HRESULT res = E_FAIL;
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);
}
{
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;
pMoniker->lpVtbl = &IMoniker_Vtbl;
pMoniker->ref = 0;
pMoniker->hkey = NULL;
+ pMoniker->bInterface = FALSE;
DEVENUM_IMediaCatMoniker_AddRef((LPMONIKER)pMoniker);
if (!pMoniker)
return E_OUTOFMEMORY;
+ pMoniker->bInterface = This->bInterface;
if (RegOpenKeyW(This->hkey, buffer, &pMoniker->hkey) != ERROR_SUCCESS)
{
DEVENUM_IMediaCatMoniker_Release((LPMONIKER)pMoniker);
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)
pEnumMoniker->ref = 1;
pEnumMoniker->index = 0;
pEnumMoniker->hkey = hkey;
+ pEnumMoniker->bInterface = bInterface;
*ppEnumMoniker = (IEnumMoniker *)pEnumMoniker;
OutputDebugStringW(Buffer);
CoTaskMemFree(lpstr);
-DebugBreak();
return E_NOINTERFACE;
}
{
#ifdef KSPROXY_TRACE
OutputDebugStringW(L"CInputPin::Receive NotImplemented\n");
- DebugBreak();
#endif
return E_NOTIMPL;
{
#ifdef KSPROXY_TRACE
OutputDebugStringW(L"CInputPin::ReceiveMultiple NotImplemented\n");
- DebugBreak();
#endif
return E_NOTIMPL;
{
#ifdef KSPROXY_TRACE
OutputDebugStringW(L"CInputPin::ReceiveCanBlock NotImplemented\n");
- DebugBreak();
#endif
return S_FALSE;
OutputDebugStringW(L"CInputPin::KsQualityNotify NotImplemented\n");
#endif
- DebugBreak();
return E_NOTIMPL;
}
{
#ifdef KSPROXY_TRACE
OutputDebugStringW(L"CInputPin::Connect NotImplemented\n");
- DebugBreak();
#endif
return NOERROR;
}
#ifdef KSPROXY_TRACE
OutputDebugStringW(L"CInputPin::ConnectionMediaType NotImplemented\n");
- DebugBreak();
#endif
return E_NOTIMPL;
WCHAR Buffer[100];
swprintf(Buffer, L"CInputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName);
OutputDebugStringW(Buffer);
- DebugBreak();
#endif
hr = E_FAIL;
}
{
#ifdef KSPROXY_TRACE
OutputDebugStringW(L"CInputPin::CreatePinHandle GetSupportedSets failed\n");
- DebugBreak();
#endif
return hr;
}
{
#ifdef KSPROXY_TRACE
OutputDebugStringW(L"CInputPin::CreatePinHandle LoadProxyPlugins failed\n");
- DebugBreak();
#endif
return hr;
}
{
// store plugin
m_Plugins.push_back(pUnknown);
-DebugBreak();
}
// close key
RegCloseKey(hSubKey);
STDMETHODIMP_(ULONG) Release()
{
InterlockedDecrement(&m_Ref);
- DebugBreak();
if (!m_Ref)
{
if (m_Allocator)
CMediaSample::SetMediaType(AM_MEDIA_TYPE *pMediaType)
{
OutputDebugStringW(L"CMediaSample::SetMediaType NotImplemented\n");
- DebugBreak();
return E_NOTIMPL;
}
OutputDebugStringW(L"COutputPin::Connect no IMemInputPin interface\n");
#endif
- DebugBreak();
return hr;
}
// 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;
}
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;
}
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);
WCHAR Buffer[100];
swprintf(Buffer, L"COutputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName);
OutputDebugStringW(Buffer);
- DebugBreak();
#endif
hr = E_FAIL;
CoTaskMemFree(MediumList);
CoTaskMemFree(InterfaceList);
+#ifdef KSPROXY_TRACE
+ WCHAR Buffer[100];
+ swprintf(Buffer, L"COutputPin::CreatePin Result %lx\n", hr);
+ OutputDebugStringW(Buffer);
+#endif
+
return hr;
}
//KSPROPERTY Property;
//ULONG BytesReturned;
+ OutputDebugStringW(L"COutputPin::CreatePinHandle\n");
+
if (m_hPin != INVALID_HANDLE_VALUE)
{
// pin already exists
if (FAILED(InitializeIOThread()))
{
OutputDebugStringW(L"COutputPin::CreatePinHandle failed to initialize i/o thread\n");
- DebugBreak();
}
LPGUID pGuid;
if (FAILED(hr))
{
#ifdef KSPROXY_TRACE
- OutputDebugStringW(L"CInputPin::CreatePinHandle GetSupportedSets failed\n");
- DebugBreak();
+ OutputDebugStringW(L"COutputPin::CreatePinHandle GetSupportedSets failed\n");
#endif
return hr;
}
if (FAILED(hr))
{
#ifdef KSPROXY_TRACE
- OutputDebugStringW(L"CInputPin::CreatePinHandle LoadProxyPlugins failed\n");
- DebugBreak();
+ OutputDebugStringW(L"COutputPin::CreatePinHandle LoadProxyPlugins failed\n");
#endif
return hr;
}
{
// store plugin
m_Plugins.push_back(pUnknown);
-DebugBreak();
}
// close key
RegCloseKey(hSubKey);
#define _FORCENAMELESSUNION
#define BUILDING_KS
#define _KSDDK_
-//#define KSPROXY_TRACE
+#define KSPROXY_TRACE
#include <dshow.h>
//#include <streams.h>
#include <ks.h>
{
#ifdef KSPROXY_TRACE
OutputDebugStringW(L"CKsProxy::IsDirty Notimplemented\n");
- DebugBreak();
#endif
return E_NOTIMPL;
}
}while(Length > 0);
- DebugBreak();
return S_OK;
}
{
#ifdef KSPROXY_TRACE
OutputDebugStringW(L"CKsProxy::GetSizeMax Notimplemented\n");
- DebugBreak();
#endif
return E_NOTIMPL;
// 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);
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)
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;
}
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;
}
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
// 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;
}
CKsProxy::EnumPins(
IEnumPins **ppEnum)
{
-#ifdef KSPROXY_TRACE
- OutputDebugStringW(L"CKsProxy::EnumPins\n");
-#endif
-
return CEnumPins_fnConstructor(m_Pins, IID_IEnumPins, (void**)ppEnum);
}
{
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;
{
UINT i;
HRESULT hres = E_OUTOFMEMORY;
- IClassFactory * pcf = NULL;
+ IClassFactory * pcf = NULL;
if (!ppv)
return E_INVALIDARG;
}
}
- if (!pcf)
+ if (!pcf)
{
return CLASS_E_CLASSNOTAVAILABLE;
}
swprintf(Buffer, L"CNetworkProvider::QueryInterface: NoInterface for %s !!!\n", lpstr);
OutputDebugStringW(Buffer);
CoTaskMemFree(lpstr);
- DebugBreak();
return E_NOINTERFACE;
}
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;
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(
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
STDMETHODCALLTYPE
CPin::QueryAccept(const AM_MEDIA_TYPE *pmt)
{
- OutputDebugStringW(L"CPin::QueryAccept called\n");
+ OutputDebugStringW(L"CPin::QueryAccept NotImplemented\n");
return E_NOTIMPL;
}
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;
}
FASTCALL
DeleteRegion( HRGN hRgn )
{
-//#if 0
PRGN_ATTR Rgn_Attr;
if ((GdiGetHandleUserData((HGDIOBJ) hRgn, GDI_OBJECT_TYPE_REGION, (PVOID) &Rgn_Attr)) &&
}
}
}
-//#endif
return NtGdiDeleteObjectApp((HGDIOBJ) hRgn);
}
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;
}
/*
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;
}
/*************************************************************************
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 "Ïóñêîâ èçáîðíèê\\Ïðèëîæåíèÿ"
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"
IDS_RESTART_PROMPT "Opravdu chcete restartovat systém?"
IDS_SHUTDOWN_TITLE "Vypnout"
IDS_SHUTDOWN_PROMPT "Opravdu chcete vypnout poèítaè?"
+ IDS_LOGOFF_TITLE "Log Off"
+ IDS_LOGOFF_PROMPT "Do you want to log off?"
/* shell folder path default values */
IDS_PROGRAMS "Nabídka Start\\Programy"
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"
IDS_RESTART_PROMPT "Möchten Sie das System neu starten?"
IDS_SHUTDOWN_TITLE "Herunterfahren"
IDS_SHUTDOWN_PROMPT "Möchten Sie das System herunterfahren?"
+ IDS_LOGOFF_TITLE "Ausloggen"
+ IDS_LOGOFF_PROMPT "Möchten Sie sich ausloggen?"
/* shell folder path default values */
IDS_PROGRAMS "Startmenü\\Programme"
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"
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"
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"
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"
IDS_RESTART_PROMPT "Haluatko simuloida Windows:n uudelleenkäynnistämistä?"
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 "Käynnistä\\Ohjelmat"
IDS_RESTART_PROMPT "Voulez-vous redémarrer votre ordinateur ?"
IDS_SHUTDOWN_TITLE "Arrêter"
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 Démarrer\\Programmes"
IDS_RESTART_PROMPT "Újra szeretnéd indítani a rendszert?"
IDS_SHUTDOWN_TITLE "Kikapcsolás"
IDS_SHUTDOWN_PROMPT "Kiakarod kapcsolni számítógépét?"
+ IDS_LOGOFF_TITLE "Log Off"
+ IDS_LOGOFF_PROMPT "Do you want to log off?"
/* shell folder path default values */
IDS_PROGRAMS "Start Menu\\Programs"
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"
IDS_RESTART_PROMPT "\83V\83X\83e\83\80\82ð\8dÄ\8bN\93®\82µ\82Ü\82·\82©?"
IDS_SHUTDOWN_TITLE "\83V\83\83\83b\83g\83_\83E\83\93"
IDS_SHUTDOWN_PROMPT "\83V\83\83\83b\83g\83_\83E\83\93\82µ\82Ü\82·\82©?"
+ IDS_LOGOFF_TITLE "Log Off"
+ IDS_LOGOFF_PROMPT "Do you want to log off?"
/* shell folder path default values */
IDS_PROGRAMS "\83X\83^\81[\83g \83\81\83j\83\85\81[\\\83v\83\8d\83O\83\89\83\80"
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"
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"
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"
IDS_RESTART_PROMPT "Czy chcesz zrestartowaæ system?"
IDS_SHUTDOWN_TITLE "Wy³¹cz"
IDS_SHUTDOWN_PROMPT "Czy chcesz wy³¹czyæ 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"
IDS_RESTART_PROMPT "Você quer simular a reinicialização do Windows?"
IDS_SHUTDOWN_TITLE "Desligar"
IDS_SHUTDOWN_PROMPT "Você quer finalizar a sessão 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"
IDS_RESTART_PROMPT "Deseja simular a reinicialização do Windows?"
IDS_SHUTDOWN_TITLE "Desligar"
IDS_SHUTDOWN_PROMPT "Deseja finalizar esta sessão 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"
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"
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 "Ãëàâíîå ìåíþ\\Ïðîãðàììû"
IDS_RESTART_PROMPT "Naozaj chcete re\9atartova\9d systém?"
IDS_SHUTDOWN_TITLE "Vypnú\9d"
IDS_SHUTDOWN_PROMPT "Naozaj chcete vypnú\9d poèítaè?"
+ IDS_LOGOFF_TITLE "Log Off"
+ IDS_LOGOFF_PROMPT "Do you want to log off?"
/* shell folder path default values */
IDS_PROGRAMS "Ponuka \8atart\\Programy"
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"
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"
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"
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"
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"
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"
#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
+++ /dev/null
-/*
- * 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 <cmbatt.h>
-
-#define NDEBUG
-#include <debug.h>
-
-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;
-}
+++ /dev/null
-/*
-* 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 <ntddk.h>
-#include <batclass.h>
-
-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);
+++ /dev/null
-<?xml version="1.0"?>
-<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
-<module name="cmbatt" type="kernelmodedriver" installbase="system32/drivers" installname="cmbatt.sys">
- <library>ntoskrnl</library>
- <library>hal</library>
- <library>battc</library>
- <include base="cmbatt">.</include>
- <file>cmbatt.c</file>
- <file>miniclass.c</file>
- <file>cmbatt.rc</file>
-</module>
+++ /dev/null
-#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 <reactos/version.rc>
+++ /dev/null
-/*
- * 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 <cmbatt.h>
-
-#define NDEBUG
-#include <debug.h>
-
-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;
-}
<directory name="battc">
<xi:include href="battc/battc.rbuild" />
</directory>
-<directory name="cmbatt">
- <xi:include href="cmbatt/cmbatt.rbuild" />
-</directory>
</group>
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
-<module name="cmbattx" type="kernelmodedriver" installbase="system32/drivers" installname="cmbattx.sys">
+<module name="cmbatt" type="kernelmodedriver" installbase="system32/drivers" installname="cmbatt.sys">
<library>ntoskrnl</library>
<library>hal</library>
<library>battc</library>
<directory name="pci">
<xi:include href="pci/pci.rbuild" />
</directory>
+<directory name="pcix">
+ <xi:include href="pcix/pcix.rbuild" />
+</directory>
</group>
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;
}
}
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(
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(
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:
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:
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+NTSTATUS
+NTAPI
+DriverEntry(IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath)
+{
+ DPRINT1("PCI: DriverEntry!\n");
+
+ /* FIXME: TODO */
+ return STATUS_NOT_SUPPORTED;
+}
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <ntddk.h>
+
+/* EOF */
--- /dev/null
+#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 <reactos/version.rc>
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+<?xml version="1.0"?>
+<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
+<module name="pcix" type="kernelmodedriver" installbase="system32/drivers" installname="pcix.sys">
+ <bootstrap installbase="$(CDOUTPUT)" />
+ <include base="pcix">.</include>
+ <library>ntoskrnl</library>
+ <library>hal</library>
+ <directory name="arb">
+ <file>ar_busno.c</file>
+ <file>ar_memio.c</file>
+ <file>arb_comn.c</file>
+ <file>tr_irq.c</file>
+ </directory>
+ <directory name="intrface">
+ <file>agpintrf.c</file>
+ <file>busintrf.c</file>
+ <file>cardbus.c</file>
+ <file>ideintrf.c</file>
+ <file>intrface.c</file>
+ <file>lddintrf.c</file>
+ <file>locintrf.c</file>
+ <file>pmeintf.c</file>
+ <file>routintf.c</file>
+ </directory>
+ <directory name="pci">
+ <file>busno.c</file>
+ <file>config.c</file>
+ <file>devhere.c</file>
+ <file>id.c</file>
+ <file>ppbridge.c</file>
+ <file>romimage.c</file>
+ <file>state.c</file>
+ </directory>
+ <file>debug.c</file>
+ <file>device.c</file>
+ <file>dispatch.c</file>
+ <file>enum.c</file>
+ <file>fdo.c</file>
+ <file>guid.c</file>
+ <file>hookhal.c</file>
+ <file>init.c</file>
+ <file>pcivrify.c</file>
+ <file>pdo.c</file>
+ <file>power.c</file>
+ <file>usage.c</file>
+ <file>utils.c</file>
+ <file>pci.rc</file>
+ <pch>pci.h</pch>
+</module>
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
--- /dev/null
+/*
+ * 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 <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
{
PKSIDEVICE_HEADER Header = (PKSIDEVICE_HEADER)DevHeader;
+ DPRINT("KsReleaseDevice\n");
+
ExReleaseResourceLite(&Header->SecurityLock);
KeLeaveCriticalRegion();
}
/* sanity check */
ASSERT(BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
- KeWaitForSingleObject(&BasicHeader->ControlMutex, Executive, KernelMode, FALSE, NULL);
+ KeWaitForSingleObject(BasicHeader->ControlMutex, Executive, KernelMode, FALSE, NULL);
}
/* sanity check */
ASSERT(BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
- KeReleaseMutex(&BasicHeader->ControlMutex, FALSE);
+ KeReleaseMutex(BasicHeader->ControlMutex, FALSE);
}
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;
PKSIOBJECT_BAG Bag;
PKSIOBJECT_BAG_ENTRY BagEntry;
+ DPRINT("KsAddItemToObjectBag\n");
+
/* get real object bag */
Bag = (PKSIOBJECT_BAG)ObjectBag;
PVOID Item;
NTSTATUS Status;
+ DPRINT("_KsEdit\n");
+
/* get real object bag */
Bag = (PKSIOBJECT_BAG)ObjectBag;
{
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
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)
}
case IRP_MN_QUERY_INTERFACE:
{
- Status = STATUS_SUCCESS;
+ Status = STATUS_UNSUCCESSFUL;
/* check for pnp notification support */
if (Dispatch)
{
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;
/* 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))
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;
}
PKS_DRIVER_EXTENSION DriverObjectExtension;
NTSTATUS Status = STATUS_SUCCESS;
+ DPRINT("KsInitializeDriver\n");
+
if (Descriptor)
{
Status = IoAllocateDriverObjectExtension(DriverObject, (PVOID)KsInitializeDriver, sizeof(KS_DRIVER_EXTENSION), (PVOID*)&DriverObjectExtension);
PKSIOBJECT_HEADER ObjectHeader;
KSTOPOLOGY Topology;
+ KSPIN_DESCRIPTOR_EX * PinDescriptorsEx;
KSPIN_DESCRIPTOR * PinDescriptors;
ULONG PinDescriptorCount;
PKSFILTERFACTORY Factory;
PFILE_OBJECT FileObject;
+ KMUTEX ControlMutex;
KMUTEX ProcessingMutex;
ULONG *PinInstanceCount;
PKSPIN * FirstPin;
- KSPROCESSPIN_INDEXENTRY ProcessPinIndex;
+ PKSPROCESSPIN_INDEXENTRY ProcessPinIndex;
}IKsFilterImpl;
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));
-
- /* check if allocation succeeded */
- if (Pins)
- {
- 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;
+ /* sanity check */
+ ASSERT(This->PinDescriptorCount > ProcessPin->Pin->Id);
- /* free old process pin */
- FreeItem(This->ProcessPinIndex.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);
- /* store new process pin index */
- This->ProcessPinIndex.Pins = Pins;
- This->ProcessPinIndex.Count++;
+ if (NT_SUCCESS(Status))
+ {
+ /* 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
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 */
IKsFilter_fnGetProcessDispatch(
IKsFilter * iface)
{
- UNIMPLEMENTED
- return NULL;
+ IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl);
+
+ return This->ProcessPinIndex;
}
static IKsFilterVtbl vt_IKsFilter =
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;
/* 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];
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;
/* 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;
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;
/* 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;
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);
-
- if (Status == STATUS_SUCCESS)
+ 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 || Status == STATUS_BUFFER_OVERFLOW)
{
IoStatus->Information = Length;
break;
UNIMPLEMENTED
Status = STATUS_UNSUCCESSFUL;
}
+ DPRINT("KspPinPropertyHandler Pins %lu Request->Id %lu Status %lx\n", This->PinDescriptorCount, Request->Id, Status);
+
return Status;
}
}
/* 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)
}
}
- 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;
KSFILTER_DESCRIPTOR* FilterDescriptor)
{
ULONG Index = 0;
+ NTSTATUS Status;
/* initialize pin descriptors */
+ 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;
+ This->Topology.Categories = FilterDescriptor->Categories;
+ This->Topology.TopologyNodesCount = FilterDescriptor->NodeDescriptorsCount;
+ This->Topology.TopologyConnectionsCount = FilterDescriptor->ConnectionsCount;
+ This->Topology.TopologyConnections = FilterDescriptor->Connections;
+
+ /* are there any templates */
if (FilterDescriptor->PinDescriptorsCount)
{
- /* allocate pin instance count array */
- This->PinInstanceCount = AllocateItem(NonPagedPool, sizeof(ULONG) * FilterDescriptor->PinDescriptorsCount);
- if(!This->PinDescriptors)
+ /* 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))
{
- return STATUS_INSUFFICIENT_RESOURCES;
+ DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
+ return Status;
}
- /* allocate first pin array */
- This->FirstPin = AllocateItem(NonPagedPool, sizeof(PKSPIN) * FilterDescriptor->PinDescriptorsCount);
- if(!This->FirstPin)
+ /* 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))
{
- FreeItem(This->PinDescriptors);
- return STATUS_INSUFFICIENT_RESOURCES;
+ 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);
- /* allocate pin descriptor array */
- This->PinDescriptors = AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * FilterDescriptor->PinDescriptorsCount);
- if(!This->PinDescriptors)
+ if (!NT_SUCCESS(Status))
{
- FreeItem(This->PinInstanceCount);
- return STATUS_INSUFFICIENT_RESOURCES;
+ DPRINT("IKsFilter_CreateDescriptors _KsEdit failed %lx\n", Status);
+ return Status;
}
- /* set pin count */
- This->PinDescriptorCount = FilterDescriptor->PinDescriptorsCount;
- /* now copy those pin descriptors over */
+ /* 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++)
{
- /* copy one pin per time */
RtlMoveMemory(&This->PinDescriptors[Index], &FilterDescriptor->PinDescriptors[Index].PinDescriptor, sizeof(KSPIN_DESCRIPTOR));
}
- }
- /* initialize topology descriptor */
- This->Topology.CategoriesCount = FilterDescriptor->CategoriesCount;
- This->Topology.Categories = FilterDescriptor->Categories;
- This->Topology.TopologyNodesCount = FilterDescriptor->NodeDescriptorsCount;
- This->Topology.TopologyConnectionsCount = FilterDescriptor->ConnectionsCount;
- This->Topology.TopologyConnections = FilterDescriptor->Connections;
+ /* 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;
+ }
- if (This->Topology.TopologyNodesCount > 0)
+ /* store new pin descriptor count */
+ This->PinDescriptorCount = FilterDescriptor->PinDescriptorsCount;
+
+ }
+
+ if (FilterDescriptor->NodeDescriptorsCount)
{
- This->Topology.TopologyNodes = AllocateItem(NonPagedPool, sizeof(GUID) * This->Topology.TopologyNodesCount);
+ /* 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;
}
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 */
- 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)
+ Status = KsAddItemToObjectBag(This->Filter.Bag, (PVOID)This->Filter.Descriptor, NULL);
+ if (!NT_SUCCESS(Status))
{
- 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));
+ FreeItem((PVOID)This->Filter.Descriptor);
+ This->Filter.Descriptor = NULL;
+ return STATUS_INSUFFICIENT_RESOURCES;
}
- /* 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));
- }
+ /* copy filter descriptor fields */
+ RtlMoveMemory((PVOID)This->Filter.Descriptor, FilterDescriptor, sizeof(KSFILTER_DESCRIPTOR));
- return STATUS_SUCCESS;
+ return Status;
}
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))
{
{
/* 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)
{
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
+
/* done */
+ DPRINT("IKsFilter_DispatchCreatePin Result %lx\n", Status);
return Status;
}
}
/* allocate filter instance */
- This = AllocateItem(NonPagedPool, sizeof(IKsFilterFactory));
+ This = AllocateItem(NonPagedPool, sizeof(IKsFilterImpl));
if (!This)
+ {
+ DPRINT("KspCreateFilter OutOfMemory\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* 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);
- /* initialize object bag */
- This->Filter.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
- if (!This->Filter.Bag)
- {
- /* no memory */
- FreeItem(This);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
-
/* 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;
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;
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);
/* what can go wrong, goes wrong */
FreeItem(This);
FreeItem(CreateItem);
+ DPRINT("IKsFilter_CreateDescriptors failed with %lx\n", Status);
return Status;
}
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)
IKsFilter_AttachFilterToFilterFactory(This, This->Header.Parent.KsFilterFactory);
/* completed initialization */
+ DPRINT("KspCreateFilter done %lx\n", Status);
return Status;
}
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 first pin array */
- FirstPin = AllocateItem(NonPagedPool, sizeof(PKSPIN) * Count);
- if (!FirstPin)
+
+ /* 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))
{
- /* not enough memory */
- FreeItem(PinDescriptorsEx);
- FreeItem(PinInstanceCount);
- FreeItem(PinDescriptors);
- return STATUS_INSUFFICIENT_RESOURCES;
+ /* failed */
+ DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
+ return Status;
}
- /* now copy all fields */
- if (Count > 1)
+ /* allocate first pin array */
+ Status = _KsEdit(This->Filter.Bag,(PVOID*)&This->FirstPin, sizeof(PKSPIN) * Count, sizeof(PKSPIN) * This->PinDescriptorCount, 0);
+ if (!NT_SUCCESS(Status))
{
- /* 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));
+ /* allocate process pin index */
+ Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->ProcessPinIndex, sizeof(KSPROCESSPIN_INDEXENTRY) * Count,
+ sizeof(KSPROCESSPIN_INDEXENTRY) * This->PinDescriptorCount, 0);
- This->PinDescriptors = PinDescriptors;
- This->PinInstanceCount = PinInstanceCount;
- This->FirstPin = FirstPin;
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("KsFilterCreatePinFactory _KsEdit failed %lx\n", Status);
+ return Status;
+ }
/* store new pin id */
*PinID = This->PinDescriptorCount;
/* increment pin descriptor count */
This->PinDescriptorCount++;
+
+ DPRINT("KsFilterCreatePinFactory done\n");
return STATUS_SUCCESS;
}
PIO_STACK_LOCATION IoStack;
PKSIOBJECT_HEADER ObjectHeader;
+ DPRINT("KsGetFilterFromIrp\n");
+
/* get current irp stack location */
IoStack = IoGetCurrentIrpStackLocation(Irp);
PFNKSFILTERFACTORYPOWER WakeCallback;
LIST_ENTRY SymbolicLinkList;
+ KMUTEX ControlMutex;
+
}IKsFilterFactoryImpl;
VOID
IN PIRP Irp)
{
PKSOBJECT_CREATE_ITEM CreateItem;
+ IKsFilterFactoryImpl * Factory;
IKsFilterFactory * iface;
NTSTATUS Status;
}
/* 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);
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)
{
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,
}
/* return result */
+ DPRINT("KsCreateFilterFactory %x\n", Status);
+ /* sanity check */
+ ASSERT(Status == STATUS_SUCCESS);
+
return Status;
}
{
KSOBJECTTYPE Type;
PKSDEVICE KsDevice;
- KMUTEX ControlMutex;
+ PRKMUTEX ControlMutex;
LIST_ENTRY EventList;
KSPIN_LOCK EventListLock;
union
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
LIST_ENTRY Entry;
IKsPinVtbl *lpVtbl;
-
LONG ref;
+
+ IKsFilter * Filter;
KMUTEX ProcessingMutex;
PFILE_OBJECT FileObject;
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(
_InterlockedIncrement(&This->ref);
return STATUS_SUCCESS;
}
+ DbgBreakPoint();
return STATUS_UNSUCCESSFUL;
}
//==============================================================
+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
*/
IN PKSPIN Pin,
IN BOOLEAN Asynchronous)
{
+ DPRINT("KsPinAttemptProcessing\n");
+ DbgBreakPoint();
UNIMPLEMENTED
}
}
/*
- @unimplemented
+ @implemented
*/
NTSTATUS
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;
}
/*
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;
}
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;
}
/*
IN BOOLEAN Eject)
{
UNIMPLEMENTED
+ DPRINT("KsStreamPointerUnlock Eject %lu\n", Eject);
+ DbgBreakPoint();
}
/*
IN ULONG OutUsed,
IN BOOLEAN Eject)
{
+ DPRINT("KsStreamPointerAdvanceOffsets InUsed %lu OutUsed %lu Eject %lu\n", InUsed, OutUsed, Eject);
+ DbgBreakPoint();
UNIMPLEMENTED
}
{
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);
}
/*
- @unimplemented
+ @implemented
*/
KSDDKAPI
NTSTATUS
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
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;
}
/*
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;
}
{
PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)StreamPointer;
+ DPRINT("KsStreamPointerGetNextClone\n");
+ DbgBreakPoint();
/* is there a another cloned stream pointer */
if (!Pointer->Next)
return NULL;
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(
PIO_STACK_LOCATION IoStack;
PKSIOBJECT_HEADER ObjectHeader;
IKsPinImpl * This;
- NTSTATUS Status = STATUS_SUCCESS;
/* get current irp stack */
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* 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)
- {
- /* it is a pin centric avstream */
- Status = This->Pin.Descriptor->Dispatch->Process(&This->Pin);
-
- /* TODO */
- }
- else
+ if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM ||
+ IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
{
- /* 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
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)
{
}
}
+ /* release filter control mutex */
+ KsFilterReleaseControl(&This->Pin);
+
return Status;
}
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
NTSTATUS
KspCreatePin(
IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp,
+ IN PIRP Irp,
IN PKSDEVICE KsDevice,
IN IKsFilterFactory * FilterFactory,
IN IKsFilter* Filter,
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);
{
/* not enough memory */
FreeItem(This);
+ DPRINT("KspCreatePin OutOfMemory\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
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));
}
/* 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;
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);
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);
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 */
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)\
+}
+
+
+
+
/* 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));
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;
}
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 */
{
/* failed to create filter factory */
FreeItem(FilterInstance);
- DPRINT1("KsCreateFilterFactory failed with %lx\n", Status);
+ FreeItem(FilterDescriptor);
}
/* done */
PBDA_FILTER_INSTANCE_ENTRY InstanceEntry;
NTSTATUS Status;
ULONG PinId;
- KSPIN_DESCRIPTOR_EX NewPinDescriptor;
+ PKSPIN_DESCRIPTOR_EX NewPinDescriptor;
DPRINT("BdaCreatePin\n");
if (!InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount)
{
/* no pins supported */
+ DPRINT("BdaCreatePin NoPins supported\n");
return STATUS_UNSUCCESSFUL;
}
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;
}
/* 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))
}
- DPRINT("BdaCreatePin Result %x\n", Status);
+ DPRINT("BdaCreatePin Result %x PinId %u\n", Status, PinId);
return Status;
}
ULONG Index, PinId;
NTSTATUS Status = STATUS_SUCCESS;
- DPRINT("BdaInitFilter\n");
+ DPRINT("BdaInitFilter %p\n", pBdaFilterTemplate);
/* check input parameters */
if (!pKSFilter)
/* 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++)
#include <bdamedia.h>
#include <bdasup.h>
-#define NDEBUG
+#define YDEBUG
#include <debug.h>
{
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;
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;
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;
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);
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:
RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer,
&UsbDevice->DeviceDescriptor,
Urb->UrbControlDescriptorRequest.TransferBufferLength);
-
- Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
-
break;
}
case USB_CONFIGURATION_DESCRIPTOR_TYPE:
RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer,
&UsbDevice->ConfigurationDescriptor,
Urb->UrbControlDescriptorRequest.TransferBufferLength);
-
- Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
-
break;
}
case USB_STRING_DESCRIPTOR_TYPE:
}
InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)((PUCHAR)InterfaceInfo + InterfaceInfo->Length);
}
-
- Urb->UrbHeader.UsbdDeviceHandle = UsbDevice;
- Urb->UrbHeader.UsbdFlags = 0;
- Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
}
else
{
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:
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:
{
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;
case USB_REQUEST_SET_ADDRESS:
{
DPRINT1("USB_REQUEST_SET_ADDRESS\n");
+ ASSERT(FALSE);
break;
}
case USB_REQUEST_GET_DESCRIPTOR:
DPRINT1("USB_REQUEST_SYNC_FRAME\n");
break;
}
+ default:
+ {
+ DPRINT1("Unknown Function Class Unknown request\n");
+ ASSERT(FALSE);
+ break;
+ }
}
break;
}
{
DPRINT1("Unhandled URB %x\n", Urb->UrbHeader.Function);
Urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION;
+ ASSERT(FALSE);
}
}
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);
}
}
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;
}
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:
}
}
- /* Lifted from hpoussin */
Status = DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
&SourceString,
&String);
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;
/* 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));
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",
else
{
DPRINT1("Not Supported\n");
- Status = STATUS_NOT_SUPPORTED;
+ Status = Irp->IoStatus.Status;
+ Information = Irp->IoStatus.Information;
}
break;
}
#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
{
} 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
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;
PULONG PeriodicFramList;
PULONG AsyncListQueueHeadPtr;
- PHYSICAL_ADDRESS PeriodicFramListPhysAddr;
- PHYSICAL_ADDRESS AsyncListQueueHeadPtrPhysAddr;
+ PHYSICAL_ADDRESS PeriodicFramListPhysAddr;
+ PHYSICAL_ADDRESS AsyncListQueueHeadPtrPhysAddr;
BOOLEAN AsyncComplete;
BOOLEAN HaltUrbHandling;
PVOID CallbackContext;
PRH_INIT_CALLBACK CallbackRoutine;
+ ULONG NumberOfPorts;
+ EHCIPORTS Ports[32];
} PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
typedef struct _WORKITEM_DATA
<xi:include href="hal_generic.rbuild" />
<xi:include href="hal_generic_up.rbuild" />
<xi:include href="hal_generic_mp.rbuild" />
-
+ <xi:include href="hal_generic_pcat.rbuild" />
+ <xi:include href="hal_generic_acpi.rbuild" />
+
<if property="ARCH" value="i386">
<xi:include href="hal.rbuild" />
<xi:include href="halacpi.rbuild" />
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
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 */
/* 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,
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
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
/* GLOBALS *******************************************************************/
+PCI_TYPE1_CFG_CYCLE_BITS HalpPciDebuggingDevice[2] = {{{{0}}}};
+
BOOLEAN HalpPCIConfigInitialized;
ULONG HalpMinPciBus, HalpMaxPciBus;
KSPIN_LOCK HalpPCIConfigLock;
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)
{
HalpPCIConfigInitialized = TRUE;
}
-VOID
-NTAPI
-HalpInitializePciBus(VOID)
-{
- /* FIXME: Initialize NMI Crash Flag */
-}
/* 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
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 */
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,
/* 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},
}
/* 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
/* Enable the interrupt */
HalEnableSystemInterrupt(SystemVector, Irql, Mode);
}
-#endif
-/*
- * @unimplemented
- */
VOID
NTAPI
-HalReportResourceUsage(VOID)
+HalpGetNMICrashFlag(VOID)
{
- INTERFACE_TYPE InterfaceType;
- UNICODE_STRING HalString;
-
- /* FIXME: Initialize DMA 64-bit support */
+ 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 MCA bus */
+ /* Set default */
+ HalpNMIDumpFlag = 0;
- /* 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);
}
+}
+#endif
- /* Build HAL usage */
- RtlInitUnicodeString(&HalString, L"PC Compatible Eisa/Isa HAL");
- HalpReportResourceUsage(&HalString, InterfaceType);
+/* EOF */
- /* FIXME: Setup PCI debugging and Hibernation */
-}
<include base="ntoskrnl">include</include>
<define name="_NTHALDLL_" />
<define name="_NTHAL_" />
- <library>hal_generic_legacy</library>
+ <library>hal_generic</library>
+ <library>hal_generic_pcat</library>
<library>hal_generic_up</library>
<library>ntoskrnl</library>
<library>libcntpr</library>
<?xml version="1.0"?>
<!DOCTYPE group SYSTEM "../../tools/rbuild/project.dtd">
<group>
- <module name="hal_generic_legacy" type="objectlibrary">
+ <module name="hal_generic" type="objectlibrary">
<include>include</include>
<include base="ntoskrnl">include</include>
<define name="_NTHALDLL_" />
<define name="_NTHAL_" />
<directory name="generic">
- <directory name="legacy">
- <file>halpcat.c</file>
- </directory>
- <directory name="bus">
- <file>bushndlr.c</file>
- <file>isabus.c</file>
- <file>halbus.c</file>
- <file>pcibus.c</file>
- <file>pcidata.c</file>
- <file>sysbus.c</file>
- </directory>
- <file>beep.c</file>
- <file>bios.c</file>
- <file>cmos.c</file>
- <file>display.c</file>
- <file>dma.c</file>
- <file>drive.c</file>
- <file>halinit.c</file>
- <file>misc.c</file>
- <file>profil.c</file>
- <file>reboot.c</file>
- <file>sysinfo.c</file>
- <file>timer.c</file>
- <file>usage.c</file>
- <if property="ARCH" value="i386">
- <directory name="i386">
- <file>portio.c</file>
- <file>systimer.S</file>
- <file>trap.S</file>
- </directory>
- </if>
- <if property="ARCH" value="amd64">
- <directory name="amd64">
- <file>x86bios.c</file>
- <file>systimer.S</file>
- </directory>
- </if>
- </directory>
- <directory name="include">
- <pch>hal.h</pch>
- </directory>
- </module>
-
- <module name="hal_generic_acpi" type="objectlibrary">
- <include>include</include>
- <include base="ntoskrnl">include</include>
- <define name="_NTHALDLL_" />
- <define name="_NTHAL_" />
- <directory name="generic">
- <directory name="acpi">
- <file>halacpi.c</file>
- <file>halpnpdd.c</file>
- </directory>
<directory name="bus">
<file>bushndlr.c</file>
<file>isabus.c</file>
--- /dev/null
+<?xml version="1.0"?>
+<!DOCTYPE group SYSTEM "../../tools/rbuild/project.dtd">
+<group>
+ <module name="hal_generic_acpi" type="objectlibrary">
+ <include>include</include>
+ <include base="ntoskrnl">include</include>
+ <define name="_NTHALDLL_" />
+ <define name="_NTHAL_" />
+ <directory name="generic">
+ <directory name="acpi">
+ <file>halacpi.c</file>
+ <file>halpnpdd.c</file>
+ </directory>
+ </directory>
+ </module>
+</group>
--- /dev/null
+<?xml version="1.0"?>
+<!DOCTYPE group SYSTEM "../../tools/rbuild/project.dtd">
+<group>
+ <module name="hal_generic_pcat" type="objectlibrary">
+ <include>include</include>
+ <include base="ntoskrnl">include</include>
+ <define name="_NTHALDLL_" />
+ <define name="_NTHAL_" />
+ <directory name="generic">
+ <directory name="legacy">
+ <file>halpcat.c</file>
+ </directory>
+ </directory>
+ </module>
+</group>
<include base="ntoskrnl">include</include>
<define name="_NTHALDLL_" />
<define name="_NTHAL_" />
+ <library>hal_generic</library>
<library>hal_generic_acpi</library>
<library>hal_generic_up</library>
<library>ntoskrnl</library>
<define name="_DISABLE_TIDENTS" />
<define name="_NTHAL_" />
<define name="_X86BIOS_" />
+ <library>hal_generic</library>
<library>hal_generic_acpi</library>
<library>hal_generic_up</library>
<library>ntoskrnl</library>
<define name="CONFIG_SMP" />
<define name="_NTHALDLL_" />
<define name="_NTHAL_" />
- <library>hal_generic_legacy</library>
+ <library>hal_generic</library>
+ <library>hal_generic_pcat</library>
<library>hal_generic_mp</library>
<library>ntoskrnl</library>
<library>libcntpr</library>
<define name="_NTHALDLL_" />
<define name="_NTHAL_" />
<define name="SARCH_XBOX" />
- <library>hal_generic_legacy</library>
+ <library>hal_generic</library>
+ <library>hal_generic_pcat</library>
<library>hal_generic_up</library>
<library>ntoskrnl</library>
<library>libcntpr</library>
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;
IN BOOLEAN NextBus
);
+VOID
+NTAPI
+HalpRegisterPciDebuggingDeviceInfo(
+ VOID
+);
+
extern ULONG HalpBusType;
extern BOOLEAN HalpPCIConfigInitialized;
extern BUS_HANDLER HalpFakePciBusHandler;
/* Usage flags */
#define IDT_REGISTERED 0x01
#define IDT_LATCHED 0x02
+#define IDT_READ_ONLY 0x04
#define IDT_INTERNAL 0x11
#define IDT_DEVICE 0x21
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(
extern PADDRESS_USAGE HalpAddressUsageList;
extern LARGE_INTEGER HalpPerfCounter;
+
+extern KAFFINITY HalpActiveProcessors;
+
+extern BOOLEAN HalDisableFirmwareMapper;
+extern PWCHAR HalHardwareIdString;
+extern PWCHAR HalName;
#define NDEBUG
#include <debug.h>
+KAFFINITY HalpActiveProcessors;
+
/* PRIVATE FUNCTIONS *********************************************************/
VOID
#define NDEBUG
#include <debug.h>
-LONG HalpActiveProcessors;
+KAFFINITY HalpActiveProcessors;
KAFFINITY HalpDefaultInterruptAffinity;
/* PRIVATE FUNCTIONS *********************************************************/
KeGetPcr()->StallScaleFactor = INITIAL_STALL_COUNT;
/* Update the interrupt affinity and processor mask */
- InterlockedBitTestAndSet(&HalpActiveProcessors, ProcessorNumber);
+ InterlockedBitTestAndSet((PLONG)&HalpActiveProcessors, ProcessorNumber);
InterlockedBitTestAndSet((PLONG)&HalpDefaultInterruptAffinity,
ProcessorNumber);
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
{
GDIBATCHHDR gbHdr;
int fnMode;
- LONG right;
- LONG bottom;
- LONG left;
- LONG top;
+ RECTL;
} GDIBSEXTSELCLPRGN, *PGDIBSEXTSELCLPRGN;
//
// Use with GdiBCSelObj, GdiBCDelObj and GdiBCDelRgn.
#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;
/*
IN HCELL_INDEX Cell
);
+BOOLEAN
+CMAPI
+HvHiveWillShrink(
+ IN PHHIVE RegistryHive
+);
+
BOOLEAN CMAPI
HvSyncHive(
PHHIVE RegistryHive);
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.
__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;
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
return TRUE;
}
+BOOLEAN
+CMAPI
+HvHiveWillShrink(IN PHHIVE RegistryHive)
+{
+ /* No shrinking yet */
+ return FALSE;
+}
+
BOOLEAN CMAPI
HvWriteHive(
PHHIVE RegistryHive)
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)
{
MixerContext->Free(MultipleItem);
+
+
if (bWaveIn)
{
InsertTailList(&MixerList->WaveInList, &WaveInfo->Entry);
/* 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)
if (!(Hive->Hive.HiveFlags & HIVE_NOLAZYFLUSH))
{
/* Acquire the flusher lock */
- ExAcquirePushLockExclusive((PVOID)&Hive->FlusherLock);
-
- /* Do the sync */
- Status = HvSyncHive(&Hive->Hive);
+ 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);
- /* 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 */
{
/* 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),
/* 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)
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,
&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;
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);
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)
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;
+ /* 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);
+ /* Immediately release the cell */
+ HvReleaseCell(Hive, DataCell);
- /* Make sure that the data cell actually has a size */
- ASSERT(HvGetCellSize(Hive, CellData) > 0);
+ /* 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;
- }
+ /* Check if the previous data cell could fit our new data */
+ if (DataSize <= (ULONG)(HvGetCellSize(Hive, CellData)))
+ {
+ /* 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;
}
+ }
+ else
+ {
+ /* 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;
+ }
- /* Now get the actual data for our data cell */
- CellData = HvGetCell(Hive, NewCell);
- if (!CellData) ASSERT(FALSE);
+ /* Now get the actual data for our data cell */
+ CellData = HvGetCell(Hive, NewCell);
+ if (!CellData) ASSERT(FALSE);
- /* Release it immediately */
- HvReleaseCell(Hive, NewCell);
+ /* 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;
+ /* 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;
- }
+ /* 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)
+CmpQueryKeyData(IN PHHIVE Hive,
+ IN PCM_KEY_NODE Node,
+ IN KEY_INFORMATION_CLASS KeyInformationClass,
+ IN OUT PVOID KeyInformation,
+ IN ULONG Length,
+ IN OUT PULONG ResultLength)
{
- 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;
+ ULONG Size, SizeLeft, MinimumSize;
+ PKEY_INFORMATION Info = (PKEY_INFORMATION)KeyInformation;
+ USHORT NameLength;
- /* 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)
+ /* Check if the value is compressed */
+ if (Node->Flags & KEY_COMP_NAME)
{
- /* Try again with the exclusive lock */
- CmpConvertKcbSharedToExclusive(Kcb);
- goto DoAgain;
+ /* Get the compressed name size */
+ NameLength = CmpCompressedNameSize(Node->Name, Node->NameLength);
}
- else if (SearchResult == SearchSuccess)
+ else
{
- /* We don't actually need to do anything! */
- Status = STATUS_SUCCESS;
- goto Quickie;
+ /* Get the real size */
+ NameLength = Node->NameLength;
}
- /* We need the exclusive KCB lock now */
- if (!(CmpIsKcbLockedExclusive(Kcb)) && !(CmpTryToConvertKcbSharedToExclusive(Kcb)))
+ /* Check what kind of information is being requested */
+ switch (KeyInformationClass)
{
- /* Acquire exclusive lock */
- CmpConvertKcbSharedToExclusive(Kcb);
- }
+ /* Basic information */
+ case KeyBasicInformation:
- /* Get pointer to key cell */
- Hive = Kcb->KeyHive;
- Cell = Kcb->KeyCell;
+ /* This is the size we need */
+ Size = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name) + NameLength;
- /* 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;
- }
+ /* And this is the minimum we can work with */
+ MinimumSize = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name);
- /* Check if we found something */
- if (CurrentChild != HCELL_NIL)
- {
- /* Get its value */
- Value = (PCM_KEY_VALUE)HvGetCell(Hive, CurrentChild);
- if (!Value)
+ /* Let the caller know and assume success */
+ *ResultLength = Size;
+ Status = STATUS_SUCCESS;
+
+ /* Check if the bufer we got is too small */
+ if (Length < MinimumSize)
{
- /* Fail */
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto Quickie;
+ /* Let the caller know and fail */
+ Status = STATUS_BUFFER_TOO_SMALL;
+ break;
}
- /* 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);
+ /* Copy the basic information */
+ Info->KeyBasicInformation.LastWriteTime = Node->LastWriteTime;
+ Info->KeyBasicInformation.TitleIndex = 0;
+ Info->KeyBasicInformation.NameLength = NameLength;
- /* Get the storage type */
- Storage = HvGetCellType(Cell);
+ /* Only the name is left */
+ SizeLeft = Length - MinimumSize;
+ Size = NameLength;
- /* Check if this is small data */
- SmallData = 0;
- if ((DataLength <= CM_KEY_VALUE_SMALL) && (DataLength > 0))
- {
- /* Copy it */
- RtlCopyMemory(&SmallData, Data, DataLength);
- }
+ /* Check if we don't have enough space for the name */
+ if (SizeLeft < Size)
+ {
+ /* Truncate the name we'll return, and tell the caller */
+ Size = SizeLeft;
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
- /* 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 if this is a compressed key */
+ if (Node->Flags & KEY_COMP_NAME)
+ {
+ /* Copy the compressed name */
+ CmpCopyCompressedName(Info->KeyBasicInformation.Name,
+ SizeLeft,
+ Node->Name,
+ Node->NameLength);
+ }
+ else
+ {
+ /* Otherwise, copy the raw name */
+ RtlCopyMemory(Info->KeyBasicInformation.Name,
+ Node->Name,
+ Size);
+ }
+ break;
- /* 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;
- }
+ /* Node information */
+ case KeyNodeInformation:
+
+ /* Calculate the size we need */
+ Size = FIELD_OFFSET(KEY_NODE_INFORMATION, Name) +
+ NameLength +
+ Node->ClassLength;
+
+ /* And the minimum size we can support */
+ MinimumSize = FIELD_OFFSET(KEY_NODE_INFORMATION, Name);
+
+ /* Return the size to the caller and assume succes */
+ *ResultLength = Size;
+ Status = STATUS_SUCCESS;
+
+ /* Check if the caller's buffer is too small */
+ if (Length < MinimumSize)
+ {
+ /* Let them know, and fail */
+ Status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ /* Copy the basic information */
+ Info->KeyNodeInformation.LastWriteTime = Node->LastWriteTime;
+ Info->KeyNodeInformation.TitleIndex = 0;
+ Info->KeyNodeInformation.ClassLength = Node->ClassLength;
+ Info->KeyNodeInformation.NameLength = NameLength;
+
+ /* Now the name is left */
+ SizeLeft = Length - MinimumSize;
+ Size = NameLength;
+
+ /* Check if the name can fit entirely */
+ if (SizeLeft < Size)
+ {
+ /* It can't, we'll have to truncate. Tell the caller */
+ Size = SizeLeft;
+ Status = STATUS_BUFFER_OVERFLOW;
+ }
+
+ /* Check if the key node name is compressed */
+ if (Node->Flags & KEY_COMP_NAME)
+ {
+ /* Copy the compressed name */
+ CmpCopyCompressedName(Info->KeyNodeInformation.Name,
+ SizeLeft,
+ Node->Name,
+ Node->NameLength);
+ }
+ else
+ {
+ /* It isn't, so copy the raw name */
+ RtlCopyMemory(Info->KeyNodeInformation.Name,
+ Node->Name,
+ Size);
+ }
+
+ /* Check if the node has a class */
+ if (Node->ClassLength > 0)
+ {
+ /* It does. We don't support these yet */
+ ASSERTMSG("Classes not supported\n", FALSE);
+ }
+ else
+ {
+ /* It doesn't, so set offset to -1, not 0! */
+ Info->KeyNodeInformation.ClassOffset = 0xFFFFFFFF;
+ }
+ break;
+
+ /* Full information requsted */
+ case KeyFullInformation:
+
+ /* This is the size we need */
+ Size = FIELD_OFFSET(KEY_FULL_INFORMATION, Class) +
+ Node->ClassLength;
+
+ /* This is what we can work with */
+ MinimumSize = FIELD_OFFSET(KEY_FULL_INFORMATION, Class);
+
+ /* Return it to caller and assume success */
+ *ResultLength = Size;
+ Status = STATUS_SUCCESS;
+
+ /* Check if the caller's buffer is to small */
+ if (Length < MinimumSize)
+ {
+ /* Let them know and fail */
+ Status = STATUS_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ /* Now copy all the basic information */
+ Info->KeyFullInformation.LastWriteTime = Node->LastWriteTime;
+ Info->KeyFullInformation.TitleIndex = 0;
+ Info->KeyFullInformation.ClassLength = Node->ClassLength;
+ Info->KeyFullInformation.SubKeys = Node->SubKeyCounts[Stable] +
+ Node->SubKeyCounts[Volatile];
+ Info->KeyFullInformation.Values = Node->ValueList.Count;
+ Info->KeyFullInformation.MaxNameLen = Node->MaxNameLen;
+ Info->KeyFullInformation.MaxClassLen = Node->MaxClassLen;
+ Info->KeyFullInformation.MaxValueNameLen = Node->MaxValueNameLen;
+ Info->KeyFullInformation.MaxValueDataLen = Node->MaxValueDataLen;
+
+ /* Check if we have a class */
+ if (Node->ClassLength > 0)
+ {
+ /* We do, but we currently don't support this */
+ ASSERTMSG("Classes not supported\n", FALSE);
+ }
+ else
+ {
+ /* We don't have a class, so set offset to -1, not 0! */
+ Info->KeyNodeInformation.ClassOffset = 0xFFFFFFFF;
+ }
+ break;
+
+ /* Any other class that got sent here is invalid! */
+ default:
+
+ /* Set failure code */
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ /* Return status */
+ 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);
- KeQuerySystemTime(&Kcb->KcbLastWriteTime);
+ Kcb->KcbLastWriteTime = Parent->LastWriteTime;
/* Check if the cell is cached */
if ((Found) && (CMP_IS_CELL_CACHED(Kcb->ValueCache.ValueList)))
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;
/* 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);
- if (!Parent)
- {
- /* Fail */
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto Quickie;
- }
+ ASSERT(Parent);
/* Get the value list and check if it has any entries */
ChildList = &Parent->ValueList;
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);
+ 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);
- if (!Value) ASSERT(FALSE);
+ ASSERT(Value);
/* Mark it and all related data as dirty */
- CmpMarkValueDataDirty(Hive, Value);
+ if (!CmpMarkValueDataDirty(Hive, Value))
+ {
+ /* Not enough log space, fail */
+ Status = STATUS_NO_LOG_SPACE;
+ goto Quickie;
+ }
/* Ssanity checks */
ASSERT(HvIsCellDirty(Hive, Parent->ValueList.List));
/* Remove the value from the child list */
Status = CmpRemoveValueFromList(Hive, ChildIndex, ChildList);
- if(!NT_SUCCESS(Status)) goto Quickie;
+ if (!NT_SUCCESS(Status))
+ {
+ /* Set known error */
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Quickie;
+ }
/* Remove the value and its data itself */
if (!CmpFreeValue(Hive, ChildCell))
/* Set the last write time */
KeQuerySystemTime(&Parent->LastWriteTime);
- KeQuerySystemTime(&Kcb->KcbLastWriteTime);
+ Kcb->KcbLastWriteTime = Parent->LastWriteTime;
/* Sanity check */
ASSERT(Parent->MaxValueNameLen == Kcb->KcbMaxValueNameLen);
/* 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;
}
/* Release locks */
+ CmpUnlockHiveFlusher((PCMHIVE)Hive);
CmpReleaseKcbLock(Kcb);
CmpUnlockRegistry();
return Status;
/* 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;
+ /* 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
{
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;
-}
-
-NTSTATUS
-NTAPI
-CmpQueryKeyData(IN PHHIVE Hive,
- IN PCM_KEY_NODE Node,
- IN KEY_INFORMATION_CLASS KeyInformationClass,
- IN OUT PVOID KeyInformation,
- IN ULONG Length,
- IN OUT PULONG ResultLength)
-{
- NTSTATUS Status;
- ULONG Size, SizeLeft, MinimumSize;
- PKEY_INFORMATION Info = (PKEY_INFORMATION)KeyInformation;
- USHORT NameLength;
-
- /* Check if the value is compressed */
- if (Node->Flags & KEY_COMP_NAME)
- {
- /* Get the compressed name size */
- NameLength = CmpCompressedNameSize(Node->Name, Node->NameLength);
- }
- else
- {
- /* Get the real size */
- NameLength = Node->NameLength;
- }
-
- /* Check what kind of information is being requested */
- switch (KeyInformationClass)
- {
- /* Basic information */
- case KeyBasicInformation:
-
- /* This is the size we need */
- Size = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name) + NameLength;
-
- /* And this is the minimum we can work with */
- MinimumSize = FIELD_OFFSET(KEY_BASIC_INFORMATION, Name);
-
- /* Let the caller know and assume success */
- *ResultLength = Size;
- Status = STATUS_SUCCESS;
-
- /* Check if the bufer we got is too small */
- if (Length < MinimumSize)
- {
- /* Let the caller know and fail */
- Status = STATUS_BUFFER_TOO_SMALL;
- break;
- }
-
- /* Copy the basic information */
- Info->KeyBasicInformation.LastWriteTime = Node->LastWriteTime;
- Info->KeyBasicInformation.TitleIndex = 0;
- Info->KeyBasicInformation.NameLength = NameLength;
-
- /* Only the name is left */
- SizeLeft = Length - MinimumSize;
- Size = NameLength;
-
- /* Check if we don't have enough space for the name */
- if (SizeLeft < Size)
- {
- /* Truncate the name we'll return, and tell the caller */
- Size = SizeLeft;
- Status = STATUS_BUFFER_OVERFLOW;
- }
-
- /* Check if this is a compressed key */
- if (Node->Flags & KEY_COMP_NAME)
- {
- /* Copy the compressed name */
- CmpCopyCompressedName(Info->KeyBasicInformation.Name,
- SizeLeft,
- Node->Name,
- Node->NameLength);
- }
- else
- {
- /* Otherwise, copy the raw name */
- RtlCopyMemory(Info->KeyBasicInformation.Name,
- Node->Name,
- Size);
- }
- break;
-
- /* Node information */
- case KeyNodeInformation:
-
- /* Calculate the size we need */
- Size = FIELD_OFFSET(KEY_NODE_INFORMATION, Name) +
- NameLength +
- Node->ClassLength;
-
- /* And the minimum size we can support */
- MinimumSize = FIELD_OFFSET(KEY_NODE_INFORMATION, Name);
-
- /* Return the size to the caller and assume succes */
- *ResultLength = Size;
- Status = STATUS_SUCCESS;
-
- /* Check if the caller's buffer is too small */
- if (Length < MinimumSize)
- {
- /* Let them know, and fail */
- Status = STATUS_BUFFER_TOO_SMALL;
- break;
- }
-
- /* Copy the basic information */
- Info->KeyNodeInformation.LastWriteTime = Node->LastWriteTime;
- Info->KeyNodeInformation.TitleIndex = 0;
- Info->KeyNodeInformation.ClassLength = Node->ClassLength;
- Info->KeyNodeInformation.NameLength = NameLength;
-
- /* Now the name is left */
- SizeLeft = Length - MinimumSize;
- Size = NameLength;
-
- /* Check if the name can fit entirely */
- if (SizeLeft < Size)
- {
- /* It can't, we'll have to truncate. Tell the caller */
- Size = SizeLeft;
- Status = STATUS_BUFFER_OVERFLOW;
- }
-
- /* Check if the key node name is compressed */
- if (Node->Flags & KEY_COMP_NAME)
- {
- /* Copy the compressed name */
- CmpCopyCompressedName(Info->KeyNodeInformation.Name,
- SizeLeft,
- Node->Name,
- Node->NameLength);
- }
- else
- {
- /* It isn't, so copy the raw name */
- RtlCopyMemory(Info->KeyNodeInformation.Name,
- Node->Name,
- Size);
- }
+ /* Acquire hive lock */
+ CmpLockRegistry();
+
+ /* Lock the KCB shared */
+ CmpAcquireKcbLockShared(Kcb);
- /* Check if the node has a class */
- if (Node->ClassLength > 0)
- {
- /* It does. We don't support these yet */
- ASSERTMSG("Classes not supported\n", FALSE);
- }
- else
- {
- /* It doesn't, so set offset to -1, not 0! */
- Info->KeyNodeInformation.ClassOffset = 0xFFFFFFFF;
- }
- break;
+ /* Don't touch deleted keys */
+DoAgain:
+ if (Kcb->Delete)
+ {
+ /* Undo everything */
+ CmpReleaseKcbLock(Kcb);
+ CmpUnlockRegistry();
+ return STATUS_KEY_DELETED;
+ }
- /* Full information requsted */
- case KeyFullInformation:
+ /* Get the hive and parent */
+ Hive = Kcb->KeyHive;
+ Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
+ ASSERT(Parent);
- /* This is the size we need */
- Size = FIELD_OFFSET(KEY_FULL_INFORMATION, Class) +
- Node->ClassLength;
+ /* FIXME: Lack of cache? */
+ if (Kcb->ValueCache.Count != Parent->ValueList.Count)
+ {
+ DPRINT1("HACK: Overriding value cache count\n");
+ Kcb->ValueCache.Count = Parent->ValueList.Count;
+ }
- /* This is what we can work with */
- MinimumSize = FIELD_OFFSET(KEY_FULL_INFORMATION, Class);
+ /* 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);
+ }
- /* Return it to caller and assume success */
- *ResultLength = Size;
- Status = STATUS_SUCCESS;
+ /* 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);
- /* Check if the caller's buffer is to small */
- if (Length < MinimumSize)
- {
- /* Let them know and fail */
- Status = STATUS_BUFFER_TOO_SMALL;
- break;
- }
+ /* Release the cell and fail */
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto Quickie;
+ }
- /* Now copy all the basic information */
- Info->KeyFullInformation.LastWriteTime = Node->LastWriteTime;
- Info->KeyFullInformation.TitleIndex = 0;
- Info->KeyFullInformation.ClassLength = Node->ClassLength;
- Info->KeyFullInformation.SubKeys = Node->SubKeyCounts[Stable] +
- Node->SubKeyCounts[Volatile];
- Info->KeyFullInformation.Values = Node->ValueList.Count;
- Info->KeyFullInformation.MaxNameLen = Node->MaxNameLen;
- Info->KeyFullInformation.MaxClassLen = Node->MaxClassLen;
- Info->KeyFullInformation.MaxValueNameLen = Node->MaxValueNameLen;
- Info->KeyFullInformation.MaxValueDataLen = Node->MaxValueDataLen;
+ /* 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);
- /* Check if we have a class */
- if (Node->ClassLength > 0)
- {
- /* We do, but we currently don't support this */
- ASSERTMSG("Classes not supported\n", FALSE);
- }
- else
- {
- /* We don't have a class, so set offset to -1, not 0! */
- Info->KeyNodeInformation.ClassOffset = 0xFFFFFFFF;
- }
- break;
+ /* Try with exclusive KCB lock */
+ CmpConvertKcbSharedToExclusive(Kcb);
+ goto DoAgain;
+ }
+ else if (Result != SearchSuccess)
+ {
+ /* Sanity check */
+ ASSERT(ValueData == NULL);
- /* Any other class that got sent here is invalid! */
- default:
+ /* 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);
- /* Set failure code */
- Status = STATUS_INVALID_PARAMETER;
- break;
+ /* Try with exclusive KCB lock */
+ CmpConvertKcbSharedToExclusive(Kcb);
+ goto DoAgain;
+ }
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Get exception code */
+ Status = _SEH2_GetExceptionCode();
}
+ _SEH2_END;
- /* Return status */
+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 Status;
PHHIVE Hive;
PCM_KEY_NODE Parent;
+ HV_TRACK_CELL_REF CellReferences = {0};
/* Acquire hive lock */
CmpLockRegistry();
/* 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)
{
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 */
}
Quickie:
+ /* Release references */
+ HvReleaseFreeCellRefArray(&CellReferences);
+
/* Release locks */
CmpReleaseKcbLock(Kcb);
CmpUnlockRegistry();
PHHIVE Hive;
PCM_KEY_NODE Parent, Child;
HCELL_INDEX ChildCell;
+ HV_TRACK_CELL_REF CellReferences = {0};
/* Acquire hive lock */
CmpLockRegistry();
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);
/* 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();
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);
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);
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);
}
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 */
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)
}
/* 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,
/* 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();
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 */
/*
* 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
/* 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 */
/* FUNCTIONS *****************************************************************/
+NTSTATUS
+NTAPI
+CmpAddToHiveFileList(IN PCMHIVE Hive)
+{
+ return STATUS_SUCCESS;
+}
+
/* EOF */
\ No newline at end of file
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;
Hive->ViewLockOwner = NULL;
/* Initialize the flush lock */
- ExInitializePushLock((PULONG_PTR)&Hive->FlusherLock);
+ ExInitializeResourceLite(Hive->FlusherLock);
/* Setup hive locks */
ExInitializePushLock((PULONG_PTR)&Hive->HiveLock);
{
/* Clear allocations and fail */
ExFreePool(Hive->ViewLock);
-#if 0
ExFreePool(Hive->FlusherLock);
-#endif
ExFreePool(Hive);
return Status;
}
{
/* Free all alocations */
ExFreePool(Hive->ViewLock);
-#if 0
ExFreePool(Hive->FlusherLock);
-#endif
ExFreePool(Hive);
return STATUS_REGISTRY_CORRUPT;
}
/* 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;
+ }
+}
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)
{
Exit:
/* Release the flusher lock and return status */
- ExReleasePushLock((PVOID)&((PCMHIVE)Hive)->FlusherLock);
return Status;
}
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)
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)
{
Exit:
/* Release the flusher locks and return status */
- ExReleasePushLock((PVOID)&((PCMHIVE)Context->ChildHive.KeyHive)->FlusherLock);
- ExReleasePushLock((PVOID)&((PCMHIVE)Hive)->FlusherLock);
return Status;
}
/*
* 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
extern LONG CmpFlushStarveWriters;
extern BOOLEAN CmFirstTime;
-/* FUNCTIONS *****************************************************************/
+/* FUNCTIONS ******************************************************************/
VOID
NTAPI
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)
if (!CmFirstTime) CmpShutdownWorkers();
CmpDoFlushAll(TRUE);
}
+
+/* EOF */
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
//
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
//
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
//
NTSTATUS
PnpRootCreateDevice(
IN PUNICODE_STRING ServiceName,
- IN OUT PDEVICE_OBJECT *PhysicalDeviceObject
+ OUT PDEVICE_OBJECT *PhysicalDeviceObject,
+ OUT OPTIONAL PUNICODE_STRING FullInstancePath
);
//
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;
}
/*++
RtlAppendUnicodeStringToString(SymbolicLinkName, ReferenceString);
}
SymbolicLinkName->Buffer[SymbolicLinkName->Length/sizeof(WCHAR)] = L'\0';
+ SymbolicLinkName->Length += sizeof(WCHAR);
/* Write symbolic link name in registry */
SymbolicLinkName->Buffer[1] = '\\';
extern BOOLEAN ExpInTextModeSetup;
extern BOOLEAN PnpSystemInit;
+USHORT IopGroupIndex;
+PLIST_ENTRY IopGroupTable;
+
/* PRIVATE FUNCTIONS **********************************************************/
NTSTATUS NTAPI
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",
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 */
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;
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)
+ {
+ /* 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)
{
- /* Make sure we didn't load this driver already */
- if (!(LdrEntry->Flags & LDRP_ENTRY_INSERTED))
+ /* 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);
}
}
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
*
cur--;
}
+ IopDisplayLoadingMessage(&ServiceName);
+
/*
* Get service type.
*/
+++ /dev/null
-/*
- * 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: <UNKNOWN>
- */
-
-/* INCLUDES *******************************************************************/
-
-#include <ntoskrnl.h>
-#define NDEBUG
-#include <debug.h>
-
-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");
-}
/* 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();
IopInitializeSystemDrivers();
PnpSystemInit = TRUE;
- /* Destroy the group driver list */
- IoDestroyDriverList();
-
/* Reinitialize drivers that requested it */
IopReinitializeDrivers();
--- /dev/null
+/*
+ * 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 <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
+/* 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 */
/* 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)
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");
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))
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
{
}
}
+ 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;
}
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);
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);
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);
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)
ULONG ResCount;
ULONG ListSize, ResultLength;
NTSTATUS Status;
+ HANDLE ControlHandle;
DPRINT("IopSetDeviceInstanceData() called\n");
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;
+}
+
+
+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;
+}
-static NTSTATUS
+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)
/* 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)
}
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;
- }
+ Status = IopDetectResourceConflict(DeviceNode->ResourceList, FALSE, NULL);
+ if (NT_SUCCESS(Status) || !DeviceNode->ResourceRequirements)
+ {
+ if (!NT_SUCCESS(Status) && !DeviceNode->ResourceRequirements)
+ {
+ DPRINT1("Using conflicting boot resources because no requirements were supplied!\n");
+ }
- 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;
+ *pRequiredSize = Size;
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ DPRINT1("Boot resources for %wZ cause a resource conflict!\n", &DeviceNode->InstancePath);
+ ExFreePool(DeviceNode->ResourceList);
+ }
}
- 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;
+ Status = IopCreateResourceListFromRequirements(DeviceNode->ResourceRequirements,
+ &DeviceNode->ResourceList);
+ if (!NT_SUCCESS(Status))
+ goto ByeBye;
- for (i = 0; i < ResourceList->Count; i++)
+ Size = FIELD_OFFSET(CM_RESOURCE_LIST, List);
+ for (i = 0; i < DeviceNode->ResourceList->Count; i++)
{
- ResourceDescriptor = &ResourceList->Descriptors[i];
-
- if (ResourceDescriptor->Option == 0 || ResourceDescriptor->Option == IO_RESOURCE_PREFERRED)
- {
- DescriptorRaw = &DeviceNode->ResourceList->List[0].PartialResourceList.PartialDescriptors[NumberOfResources];
- NumberOfResources++;
-
- /* 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--;
- }
- }
-
+ pPartialResourceList = &DeviceNode->ResourceList->List[i].PartialResourceList;
+ Size += FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList.PartialDescriptors)
+ + pPartialResourceList->Count * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
}
- DeviceNode->ResourceList->List[0].PartialResourceList.Count = NumberOfResources;
+ Status = IopDetectResourceConflict(DeviceNode->ResourceList, FALSE, NULL);
+ if (!NT_SUCCESS(Status))
+ goto ByeBye;
*pRequiredSize = Size;
return STATUS_SUCCESS;
}
-static NTSTATUS
+NTSTATUS
IopTranslateDeviceResources(
IN PDEVICE_NODE DeviceNode,
IN ULONG RequiredSize)
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");
UNICODE_STRING HardwareIdKey;
PUNICODE_STRING pHardwareId;
ULONG DeviceIndex = 0;
- BOOLEAN IsDeviceDesc;
+ PUCHAR CmResourceList;
+ ULONG ListCount;
if (RelativePath)
{
DPRINT("ExAllocatePool() failed\n");
goto nextdevice;
}
- if (ParentBootResourcesLength == 0)
+ if (ParentBootResourcesLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR))
{
RtlCopyMemory(BootResources, pValueInformation->Data, pValueInformation->DataLength);
}
{
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))
{
{
pHardwareId = &HardwareIdPci;
DeviceIndex = DeviceIndexPci++;
- IsDeviceDesc = FALSE;
}
else if (RtlCompareUnicodeString(&ValueName, &IdentifierIsa, FALSE) == 0)
{
pHardwareId = &HardwareIdIsa;
DeviceIndex = DeviceIndexIsa++;
- IsDeviceDesc = FALSE;
}
else
{
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))
{
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);
nextdevice:
if (BootResources && BootResources != ParentBootResources)
+ {
ExFreePool(BootResources);
+ BootResources = NULL;
+ }
if (hLevel2Key)
{
ZwClose(hLevel2Key);
/* PUBLIC FUNCTIONS **********************************************************/
/*
- * @unimplemented
+ * @implemented
*/
NTSTATUS
NTAPI
PVOID Data = NULL;
PWSTR Ptr;
NTSTATUS Status;
+ POBJECT_NAME_INFORMATION ObjectNameInfo = NULL;
+ ULONG RequiredLength, ObjectNameInfoLength;
DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject, DeviceProperty);
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:
/* 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;
}
* 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 ******************************************************************/
#define NDEBUG
#include <debug.h>
+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 **********************************************************/
/*
{
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 a new PDO and return it in *DeviceObject */
+ /* Create the PDO */
+ Status = PnpRootCreateDevice(&ServiceName,
+ &Pdo,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("PnpRootCreateDevice() failed (Status 0x%08lx)\n", Status);
+ return Status;
+ }
+
+ /* Create the device node for the new PDO */
Status = IopCreateDeviceNode(IopRootDeviceNode,
+ Pdo,
NULL,
- &ServiceName,
&DeviceNode);
if (!NT_SUCCESS(Status))
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
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 */
- return STATUS_SUCCESS;
+ /* TODO: Claim the resources in the ResourceMap */
+ }
+
+ return Status;
}
VOID
UNICODE_STRING DeviceDescription;
// Resource requirement list
PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList;
- ULONG ResourceRequirementsListSize;
// Associated resource list
PCM_RESOURCE_LIST ResourceList;
ULONG ResourceListSize;
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);
}
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;
}
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,
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;
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;
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
{
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);
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
--- /dev/null
+/*
+ * 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 <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
+/* 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 */
<file>device.c</file>
<file>deviface.c</file>
<file>driver.c</file>
- <file>drvrlist.c</file>
<file>error.c</file>
<file>file.c</file>
<file>iocomp.c</file>
<directory name="pnpmgr">
<file>plugplay.c</file>
<file>pnpdma.c</file>
+ <file>pnpinit.c</file>
<file>pnpmgr.c</file>
<file>pnpnotify.c</file>
<file>pnpreport.c</file>
<file>pnproot.c</file>
+ <file>pnputil.c</file>
</directory>
</directory>
<if property="_WINKD_" value="0">
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,
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;
if (PreviouslyGrantedAccess)
RtlMapGenericMask(&PreviouslyGrantedAccess, GenericMapping);
+ /* Initialize remaining access rights */
+ RemainingAccess = DesiredAccess;
+ Token = SubjectSecurityContext->ClientToken ?
+ SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
- CurrentAccess = PreviouslyGrantedAccess;
-
+ /* 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;
- Token = SubjectSecurityContext->ClientToken ?
- SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
+ /* 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,
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))
- {
- CurrentAccess |= WRITE_OWNER;
- if ((DesiredAccess & ~VALID_INHERIT_FLAGS) ==
- (CurrentAccess & ~VALID_INHERIT_FLAGS))
+ if (DesiredAccess & WRITE_OWNER)
+ {
+ 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 */
return FALSE;
}
- /* RULE 4: Grant rights according to the DACL */
- CurrentAce = (PACE)(Dacl + 1);
- for (i = 0; i < Dacl->AceCount; i++)
+ /* Determine the MAXIMUM_ALLOWED access rights according to the DACL */
+ if (DesiredAccess & MAXIMUM_ALLOWED)
{
- Sid = (PSID)(CurrentAce + 1);
- if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
+ CurrentAce = (PACE)(Dacl + 1);
+ for (i = 0; i < Dacl->AceCount; i++)
{
- if (SepSidInToken(Token, Sid))
+ if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE))
{
- *GrantedAccess = 0;
- *AccessStatus = STATUS_ACCESS_DENIED;
- return FALSE;
+ 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);
}
- else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
+ /* Fail if some rights have not been granted */
+ RemainingAccess &= ~(MAXIMUM_ALLOWED | TempGrantedAccess);
+ if (RemainingAccess != 0)
{
- if (SepSidInToken(Token, Sid))
- {
- AccessMask = CurrentAce->AccessMask;
- RtlMapGenericMask(&AccessMask, GenericMapping);
- CurrentAccess |= AccessMask;
- }
+ *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
{
- DPRINT1("Unknown Ace type 0x%lx\n", CurrentAce->Header.AceType);
+ *AccessStatus = STATUS_ACCESS_DENIED;
+ return FALSE;
}
- CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize);
}
- DPRINT("CurrentAccess %08lx\n DesiredAccess %08lx\n",
- CurrentAccess, DesiredAccess);
-
- *GrantedAccess = CurrentAccess & DesiredAccess;
-
- if (DesiredAccess & MAXIMUM_ALLOWED)
+ /* RULE 4: Grant rights according to the DACL */
+ CurrentAce = (PACE)(Dacl + 1);
+ for (i = 0; i < Dacl->AceCount; i++)
{
- *GrantedAccess = CurrentAccess;
- *AccessStatus = STATUS_SUCCESS;
- return TRUE;
+ 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);
+
+ /* 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);
+ }
+ }
+
+ /* Get the next ACE */
+ CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize);
}
- else if ((*GrantedAccess & ~VALID_INHERIT_FLAGS) ==
- (DesiredAccess & ~VALID_INHERIT_FLAGS))
+
+ DPRINT("DesiredAccess %08lx\nPreviouslyGrantedAccess %08lx\nRemainingAccess %08lx\n",
+ DesiredAccess, PreviouslyGrantedAccess, RemainingAccess);
+
+ /* Fail if some rights have not been granted */
+ if (RemainingAccess != 0)
{
- *AccessStatus = STATUS_SUCCESS;
- return TRUE;
+ *GrantedAccess = 0;
+ *AccessStatus = STATUS_ACCESS_DENIED;
+ return FALSE;
}
- else
+
+ /* Set granted access rights */
+ *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
+
+ DPRINT("GrantedAccess %08lx\n", *GrantedAccess);
+
+ /* Fail if no rights have been granted */
+ if (*GrantedAccess == 0)
{
- 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
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)
PSECURITY_DESCRIPTOR CapturedSecurityDescriptor = NULL;
SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+ ACCESS_MASK PreviouslyGrantedAccess = 0;
PTOKEN Token;
NTSTATUS Status;
PAGED_CODE();
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);
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;
+}
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
{
DWORD dwFlags;
PDEVMODEW pdm;
-
+
} DEVMODEENTRY, *PDEVMODEENTRY;
typedef struct _GRAPHICS_DEVICE
// 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;
// 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. */
NTAPI
InitDeviceImpl();
+PSIZEL
+FASTCALL
+PDEVOBJ_sizl(PPDEVOBJ, PSIZEL);
+
#endif /* !__WIN32K_PDEVOBJ_H */
#include "win32.h"
#include "gdiobj.h"
+#define PDEV_SURFACE 0x80000000
+
/* GDI surface object */
typedef struct _SURFACE
{
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,
SMTO_NORMAL,
100,
&ulResult);
+
+ co_IntShowDesktop(pdesk, ppdev->gdiinfo.ulHorzRes, ppdev->gdiinfo.ulVertRes);
+
+ UserRedrawDesktop();
}
leave:
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;
}
}
#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)