Sync with trunk (aka 'I want my virtualbox mouse integration too')
authorJérôme Gardou <jerome.gardou@reactos.org>
Mon, 5 Apr 2010 09:59:21 +0000 (09:59 +0000)
committerJérôme Gardou <jerome.gardou@reactos.org>
Mon, 5 Apr 2010 09:59:21 +0000 (09:59 +0000)
svn path=/branches/reactos-yarotows/; revision=46732

170 files changed:
base/applications/taskmgr/taskmgr.c
base/shell/cmd/console.c
base/shell/cmd/filecomp.c
base/shell/explorer/utility/window.cpp
base/system/format/format.c
boot/bootdata/packages/reactos.dff
boot/bootdata/txtsetup.sif
boot/freeldr/freeldr/arch/i386/hardware.c
dll/directx/devenum/createdevenum.c
dll/directx/devenum/devenum_private.h
dll/directx/devenum/mediacatenum.c
dll/directx/ksproxy/enumpins.cpp
dll/directx/ksproxy/input_pin.cpp
dll/directx/ksproxy/mediasample.cpp
dll/directx/ksproxy/output_pin.cpp
dll/directx/ksproxy/precomp.h
dll/directx/ksproxy/proxy.cpp
dll/directx/msdvbnp/enumpins.cpp
dll/directx/msdvbnp/msdvbnp.cpp
dll/directx/msdvbnp/networkprovider.cpp
dll/directx/msdvbnp/pin.cpp
dll/win32/gdi32/objects/region.c
dll/win32/shell32/dialogs.c
dll/win32/shell32/lang/bg-BG.rc
dll/win32/shell32/lang/ca-ES.rc
dll/win32/shell32/lang/cs-CZ.rc
dll/win32/shell32/lang/da-DK.rc
dll/win32/shell32/lang/de-DE.rc
dll/win32/shell32/lang/el-GR.rc
dll/win32/shell32/lang/en-GB.rc
dll/win32/shell32/lang/en-US.rc
dll/win32/shell32/lang/es-ES.rc
dll/win32/shell32/lang/fi-FI.rc
dll/win32/shell32/lang/fr-FR.rc
dll/win32/shell32/lang/hu-HU.rc
dll/win32/shell32/lang/it-IT.rc
dll/win32/shell32/lang/ja-JP.rc
dll/win32/shell32/lang/ko-KR.rc
dll/win32/shell32/lang/nl-NL.rc
dll/win32/shell32/lang/no-NO.rc
dll/win32/shell32/lang/pl-PL.rc
dll/win32/shell32/lang/pt-BR.rc
dll/win32/shell32/lang/pt-PT.rc
dll/win32/shell32/lang/ro-RO.rc
dll/win32/shell32/lang/ru-RU.rc
dll/win32/shell32/lang/sk-SK.rc
dll/win32/shell32/lang/sl-SI.rc
dll/win32/shell32/lang/sv-SE.rc
dll/win32/shell32/lang/tr-TR.rc
dll/win32/shell32/lang/uk-UA.rc
dll/win32/shell32/lang/zh-CN.rc
dll/win32/shell32/lang/zh-TW.rc
dll/win32/shell32/shresdef.h
drivers/battery/cmbatt/cmbatt.c [deleted file]
drivers/battery/cmbatt/cmbatt.h [deleted file]
drivers/battery/cmbatt/cmbatt.rbuild [deleted file]
drivers/battery/cmbatt/cmbatt.rc [deleted file]
drivers/battery/cmbatt/miniclass.c [deleted file]
drivers/battery/directory.rbuild
drivers/bus/acpi/cmbatt/cmbatt.rbuild
drivers/bus/directory.rbuild
drivers/bus/pci/pdo.c
drivers/bus/pcix/arb/ar_busno.c [new file with mode: 0644]
drivers/bus/pcix/arb/ar_memio.c [new file with mode: 0644]
drivers/bus/pcix/arb/arb_comn.c [new file with mode: 0644]
drivers/bus/pcix/arb/tr_irq.c [new file with mode: 0644]
drivers/bus/pcix/debug.c [new file with mode: 0644]
drivers/bus/pcix/device.c [new file with mode: 0644]
drivers/bus/pcix/dispatch.c [new file with mode: 0644]
drivers/bus/pcix/enum.c [new file with mode: 0644]
drivers/bus/pcix/fdo.c [new file with mode: 0644]
drivers/bus/pcix/guid.c [new file with mode: 0644]
drivers/bus/pcix/hookhal.c [new file with mode: 0644]
drivers/bus/pcix/init.c [new file with mode: 0644]
drivers/bus/pcix/intrface/agpintrf.c [new file with mode: 0644]
drivers/bus/pcix/intrface/busintrf.c [new file with mode: 0644]
drivers/bus/pcix/intrface/cardbus.c [new file with mode: 0644]
drivers/bus/pcix/intrface/ideintrf.c [new file with mode: 0644]
drivers/bus/pcix/intrface/intrface.c [new file with mode: 0644]
drivers/bus/pcix/intrface/lddintrf.c [new file with mode: 0644]
drivers/bus/pcix/intrface/locintrf.c [new file with mode: 0644]
drivers/bus/pcix/intrface/pmeintf.c [new file with mode: 0644]
drivers/bus/pcix/intrface/routintf.c [new file with mode: 0644]
drivers/bus/pcix/pci.h [new file with mode: 0644]
drivers/bus/pcix/pci.rc [new file with mode: 0644]
drivers/bus/pcix/pci/busno.c [new file with mode: 0644]
drivers/bus/pcix/pci/config.c [new file with mode: 0644]
drivers/bus/pcix/pci/devhere.c [new file with mode: 0644]
drivers/bus/pcix/pci/id.c [new file with mode: 0644]
drivers/bus/pcix/pci/ppbridge.c [new file with mode: 0644]
drivers/bus/pcix/pci/romimage.c [new file with mode: 0644]
drivers/bus/pcix/pci/state.c [new file with mode: 0644]
drivers/bus/pcix/pcivrify.c [new file with mode: 0644]
drivers/bus/pcix/pcix.rbuild [new file with mode: 0644]
drivers/bus/pcix/pdo.c [new file with mode: 0644]
drivers/bus/pcix/power.c [new file with mode: 0644]
drivers/bus/pcix/usage.c [new file with mode: 0644]
drivers/bus/pcix/utils.c [new file with mode: 0644]
drivers/ksfilter/ks/api.c
drivers/ksfilter/ks/bag.c
drivers/ksfilter/ks/clocks.c
drivers/ksfilter/ks/connectivity.c
drivers/ksfilter/ks/device.c
drivers/ksfilter/ks/deviceinterface.c
drivers/ksfilter/ks/driver.c
drivers/ksfilter/ks/filter.c
drivers/ksfilter/ks/filterfactory.c
drivers/ksfilter/ks/kstypes.h
drivers/ksfilter/ks/pin.c
drivers/ksfilter/ks/priv.h
drivers/ksfilter/ks/property.c
drivers/multimedia/bdasup/bdasup.c
drivers/multimedia/bdasup/precomp.h
drivers/storage/ide/uniata/id_ata.cpp
drivers/usb/usbehci/fdo.c
drivers/usb/usbehci/irp.c
drivers/usb/usbehci/pdo.c
drivers/usb/usbehci/usbehci.h
hal/halx86/directory.rbuild
hal/halx86/generic/acpi/halacpi.c
hal/halx86/generic/acpi/halpnpdd.c
hal/halx86/generic/bus/pcibus.c
hal/halx86/generic/legacy/halpcat.c
hal/halx86/generic/misc.c
hal/halx86/generic/usage.c
hal/halx86/hal.rbuild
hal/halx86/hal_generic.rbuild
hal/halx86/hal_generic_acpi.rbuild [new file with mode: 0644]
hal/halx86/hal_generic_pcat.rbuild [new file with mode: 0644]
hal/halx86/halacpi.rbuild
hal/halx86/halamd64.rbuild
hal/halx86/halmps.rbuild
hal/halx86/halxbox.rbuild
hal/halx86/include/bus.h
hal/halx86/include/halp.h
hal/halx86/mp/processor_mp.c
hal/halx86/up/processor.c
include/psdk/ks.h
include/reactos/win32k/ntgdityp.h
lib/cmlib/cmlib.h
lib/cmlib/hivecell.c
lib/cmlib/hivewrt.c
lib/drivers/sound/mmixer/wave.c
ntoskrnl/config/cmapi.c
ntoskrnl/config/cmboot.c
ntoskrnl/config/cmhvlist.c
ntoskrnl/config/cminit.c
ntoskrnl/config/cmkcbncb.c
ntoskrnl/config/cmparse.c
ntoskrnl/config/cmsysini.c
ntoskrnl/include/internal/cm.h
ntoskrnl/include/internal/io.h
ntoskrnl/io/iomgr/deviface.c
ntoskrnl/io/iomgr/driver.c
ntoskrnl/io/iomgr/drvrlist.c [deleted file]
ntoskrnl/io/iomgr/iomgr.c
ntoskrnl/io/pnpmgr/pnpinit.c [new file with mode: 0644]
ntoskrnl/io/pnpmgr/pnpmgr.c
ntoskrnl/io/pnpmgr/pnpreport.c
ntoskrnl/io/pnpmgr/pnproot.c
ntoskrnl/io/pnpmgr/pnputil.c [new file with mode: 0644]
ntoskrnl/ntoskrnl-generic.rbuild
ntoskrnl/se/semgr.c
subsystems/win32/win32k/eng/pdevobj.c
subsystems/win32/win32k/include/dc.h
subsystems/win32/win32k/include/pdevobj.h
subsystems/win32/win32k/include/surface.h
subsystems/win32/win32k/ntuser/display.c
subsystems/win32/win32k/objects/dclife.c
subsystems/win32/win32k/objects/dcutil.c

index 3f8bcbd..c409f80 100644 (file)
@@ -869,6 +869,7 @@ void TaskManager_OnTabWndSelChange(void)
     HMENU  hViewMenu;
     HMENU  hSubMenu;
     WCHAR  szTemp[256];
+    SYSTEM_INFO sysInfo;
 
     hMenu = GetMenu(hMainWnd);
     hViewMenu = GetSubMenu(hMenu, 2);
@@ -947,16 +948,28 @@ void TaskManager_OnTabWndSelChange(void)
             DeleteMenu(hMenu, 3, MF_BYPOSITION);
             DrawMenuBar(hMainWnd);
         }
-        hSubMenu = CreatePopupMenu();
 
-        LoadStringW(hInst, IDS_MENU_ONEGRAPHALLCPUS, szTemp, 256);
-        AppendMenuW(hSubMenu, MF_STRING, ID_VIEW_CPUHISTORY_ONEGRAPHALL, szTemp);
+        GetSystemInfo(&sysInfo);
 
-        LoadStringW(hInst, IDS_MENU_ONEGRAPHPERCPU, szTemp, 256);
-        AppendMenuW(hSubMenu, MF_STRING, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, szTemp);
+        /* Hide CPU graph options on single CPU systems */
+        if (sysInfo.dwNumberOfProcessors > 1)
+        {
+            hSubMenu = CreatePopupMenu();
+
+            LoadStringW(hInst, IDS_MENU_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);
@@ -965,10 +978,7 @@ void TaskManager_OnTabWndSelChange(void)
             CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_CHECKED);
         else
             CheckMenuItem(hViewMenu, ID_VIEW_SHOWKERNELTIMES, MF_BYCOMMAND|MF_UNCHECKED);
-        if (TaskManagerSettings.CPUHistory_OneGraphPerCPU)
-            CheckMenuRadioItem(hSubMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, MF_BYCOMMAND);
-        else
-            CheckMenuRadioItem(hSubMenu, ID_VIEW_CPUHISTORY_ONEGRAPHALL, ID_VIEW_CPUHISTORY_ONEGRAPHPERCPU, ID_VIEW_CPUHISTORY_ONEGRAPHALL, MF_BYCOMMAND);
+
         /*
          * Give the tab control focus
          */
index 18541bf..8184af7 100644 (file)
@@ -166,7 +166,7 @@ VOID ConOutChar (TCHAR c)
 VOID ConPuts(LPTSTR szText, DWORD nStdHandle)
 {
        ConWrite(szText, _tcslen(szText), nStdHandle);
-       ConWrite(_T("\n"), 1, nStdHandle);
+       ConWrite(_T("\r\n"), 2, nStdHandle);
 }
 
 VOID ConOutResPaging(BOOL NewPage, UINT resID)
index 4ca8b83..7cb99a7 100644 (file)
@@ -703,7 +703,7 @@ VOID CompleteFilename (LPTSTR strIN, BOOL bNext, LPTSTR strOut, UINT cusor)
                                LastSpace = i;
 
                }
-               /* insert the quoation and move things around */
+               /* insert the quotation and move things around */
                if(szPrefix[LastSpace + 1] != _T('\"') && LastSpace != -1)
                {
                        memmove ( &szPrefix[LastSpace+1], &szPrefix[LastSpace], (_tcslen(szPrefix)-LastSpace+1) * sizeof(TCHAR) );
@@ -712,14 +712,17 @@ VOID CompleteFilename (LPTSTR strIN, BOOL bNext, LPTSTR strOut, UINT cusor)
                        {
                                _tcscat(szPrefix,_T("\""));
                        }
-                               szPrefix[LastSpace + 1] = _T('\"');
+                       szPrefix[LastSpace + 1] = _T('\"');
                }
                else if(LastSpace == -1)
                {
-                       _tcscpy(szBaseWord,_T("\""));
-                       _tcscat(szBaseWord,szPrefix);
-                       _tcscpy(szPrefix,szBaseWord);
-
+                       /* Add quotation only if none exists already */
+                       if (szPrefix[0] != _T('\"'))
+                       {
+                               _tcscpy(szBaseWord,_T("\""));
+                               _tcscat(szBaseWord,szPrefix);
+                               _tcscpy(szPrefix,szBaseWord);
+                       }
                }
        }
 
index cfbce1d..296f3ce 100644 (file)
@@ -268,7 +268,7 @@ LRESULT CALLBACK Window::WindowWndProc(HWND hwnd, UINT nmsg, WPARAM wparam, LPAR
                  case WM_CREATE:
                        return pThis->Init((LPCREATESTRUCT)lparam);
 
-                 case WM_NCDESTROY:
+          case WM_NCDESTROY:
                        delete pThis;
                        return 0;
 
index 59f9f30..ba9f42b 100755 (executable)
@@ -363,6 +363,12 @@ _tmain(int argc, TCHAR *argv[])
                PrintWin32Error( szMsg, GetLastError());
                return -1;
        }
+       else if ( driveType == 1 )
+       {
+               LoadString( GetModuleHandle(NULL), STRING_NO_VOLUME, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
+               PrintWin32Error( szMsg, GetLastError());
+               return -1;
+       }
 
        if( driveType != DRIVE_FIXED ) {
                LoadString( GetModuleHandle(NULL), STRING_INSERT_DISK, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
index 49d33a7..e4caa7b 100644 (file)
@@ -487,11 +487,13 @@ drivers\base\beep\beep.sys                          2
 drivers\base\null\null.sys                          2
 drivers\base\nmidebug\nmidebug.sys                  2
 
-drivers\battery\cmbatt\cmbatt.sys                   2
 drivers\battery\battc\battc.sys                     2
 
 drivers\bus\isapnp\isapnp.sys                       2
 
+drivers\bus\acpi\cmbatt\cmbatt.sys                  2
+drivers\bus\acpi\compbatt\compbatt.sys              2
+
 drivers\directx\dxapi\dxapi.sys                     2
 drivers\directx\dxg\dxg.sys                         2
 drivers\directx\dxgthk\dxgthk.sys                   2
index 7977e44..870c0d2 100644 (file)
@@ -76,7 +76,7 @@ hal.dll=,,,,,,,,,,,,2
 
 [Files.pci_mp]
 ntkrnlmp.exe=,,,,,,,,,,ntoskrnl.exe,,2
-halmp.dll=,,,,,,,,,,hal.dll,,2
+halmps.dll=,,,,,,,,,,hal.dll,,2
 
 [Display]
 ;<id> = <user friendly name>,<spare>,<service key name>,<hight>,<width>,<bpp>
index d4654cc..1dff167 100644 (file)
@@ -1419,10 +1419,10 @@ DetectSerialPorts(PCONFIGURATION_COMPONENT_DATA BusKey)
       /* Set Interrupt */
       PartialDescriptor = &PartialResourceList->PartialDescriptors[1];
       PartialDescriptor->Type = CmResourceTypeInterrupt;
-      PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
+      PartialDescriptor->ShareDisposition = CmResourceShareShared;
       PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
       PartialDescriptor->u.Interrupt.Level = Irq[i];
-      PartialDescriptor->u.Interrupt.Vector = 0;
+      PartialDescriptor->u.Interrupt.Vector = Irq[i];
       PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
 
       /* Set serial data (device specific) */
@@ -1529,7 +1529,7 @@ DetectParallelPorts(PCONFIGURATION_COMPONENT_DATA BusKey)
          PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
          PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
          PartialDescriptor->u.Interrupt.Level = Irq[i];
-         PartialDescriptor->u.Interrupt.Vector = 0;
+         PartialDescriptor->u.Interrupt.Vector = Irq[i];
          PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
        }
 
@@ -1715,7 +1715,7 @@ DetectKeyboardController(PCONFIGURATION_COMPONENT_DATA BusKey)
   PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
   PartialDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
   PartialDescriptor->u.Interrupt.Level = 1;
-  PartialDescriptor->u.Interrupt.Vector = 0;
+  PartialDescriptor->u.Interrupt.Vector = 1;
   PartialDescriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
 
   /* Set IO Port 0x60 */
@@ -1887,7 +1887,7 @@ DetectPS2Mouse(PCONFIGURATION_COMPONENT_DATA BusKey)
       PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareUndetermined;
       PartialResourceList.PartialDescriptors[0].Flags = CM_RESOURCE_INTERRUPT_LATCHED;
       PartialResourceList.PartialDescriptors[0].u.Interrupt.Level = 12;
-      PartialResourceList.PartialDescriptors[0].u.Interrupt.Vector = 0;
+      PartialResourceList.PartialDescriptors[0].u.Interrupt.Vector = 12;
       PartialResourceList.PartialDescriptors[0].u.Interrupt.Affinity = 0xFFFFFFFF;
 
       /* Create controller key */
index bded705..19b41c9 100644 (file)
@@ -48,6 +48,7 @@
 
 #include "wine/debug.h"
 #include "mmddk.h"
+#include <regstr.h>
 
 WINE_DEFAULT_DEBUG_CHANNEL(devenum);
 
@@ -124,6 +125,7 @@ HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(
     WCHAR wszRegKey[MAX_PATH];
     HKEY hkey;
     HKEY hbasekey;
+    BOOL bInterface = FALSE;
     CreateDevEnumImpl *This = (CreateDevEnumImpl *)iface;
 
     TRACE("(%p)->(%s, %p, %lx)\n\tDeviceClass:\t%s\n", This, debugstr_guid(clsidDeviceClass), ppEnumMoniker, dwFlags, debugstr_guid(clsidDeviceClass));
@@ -174,12 +176,23 @@ HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(
         }
         else
         {
-            FIXME("Category %s not found\n", debugstr_guid(clsidDeviceClass));
-            return S_FALSE;
+             wcscpy(wszRegKey, REGSTR_PATH_DEVICE_CLASSES);
+             wcscat(wszRegKey, L"\\");
+
+            if (!StringFromGUID2(clsidDeviceClass, wszRegKey + wcslen(wszRegKey), MAX_PATH - CLSID_STR_LEN))
+                return E_OUTOFMEMORY;
+
+            if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszRegKey, 0, KEY_READ, &hkey) != ERROR_SUCCESS)
+            {
+                FIXME("Category %s not found\n", debugstr_guid(clsidDeviceClass));
+                return S_FALSE;
+            }
+
+            bInterface = TRUE;
         }
     }
 
-    return DEVENUM_IEnumMoniker_Construct(hkey, ppEnumMoniker);
+    return DEVENUM_IEnumMoniker_Construct(hkey, ppEnumMoniker, bInterface);
 }
 
 /**********************************************************************
index 9ec3b58..8914aef 100644 (file)
@@ -71,6 +71,7 @@ typedef struct
     LONG ref;
     DWORD index;
     HKEY hkey;
+    BOOL bInterface;
 } EnumMonikerImpl;
 
 typedef struct
@@ -79,10 +80,11 @@ typedef struct
 
     LONG ref;
     HKEY hkey;
+    BOOL bInterface;
 } MediaCatMoniker;
 
 MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct(void);
-HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, IEnumMoniker ** ppEnumMoniker);
+HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, IEnumMoniker ** ppEnumMoniker, BOOL bInterface);
 HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(
     ICreateDevEnum * iface,
     REFCLSID clsidDeviceClass,
index b8c5074..d14cd9a 100644 (file)
@@ -42,6 +42,7 @@ typedef struct
     IPropertyBagVtbl *lpVtbl;
     LONG ref;
     HKEY hkey;
+    BOOL bInterface;
 } RegPropBagImpl;
 
 
@@ -108,13 +109,31 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Read(
     RegPropBagImpl *This = (RegPropBagImpl *)iface;
     HRESULT res = S_OK;
     LONG reswin32;
+    WCHAR buffer[MAX_PATH];
+    HKEY hkey;
+    LPCOLESTR pszName;
 
     TRACE("(%p)->(%s, %p, %p)\n", This, debugstr_w(pszPropName), pVar, pErrorLog);
 
     if (!pszPropName || !pVar)
         return E_POINTER;
 
-    reswin32 = RegQueryValueExW(This->hkey, pszPropName, NULL, NULL, NULL, &received);
+    hkey = This->hkey;
+    pszName = pszPropName;
+    if (This->bInterface)
+    {
+        buffer[0] = 0;
+        received = sizeof(buffer)/sizeof(WCHAR);
+        reswin32 = RegEnumKeyEx(This->hkey, 0, buffer, &received, NULL, NULL, NULL, NULL);
+
+        reswin32 = RegOpenKeyExW(This->hkey, buffer, 0, KEY_READ, &hkey);
+
+        if (!wcsicmp(pszPropName, L"DevicePath"))
+            pszName = L"SymbolicLink";
+
+    }
+
+    reswin32 = RegQueryValueExW(hkey, pszName, NULL, NULL, NULL, &received);
     res = HRESULT_FROM_WIN32(reswin32);
 
     if (SUCCEEDED(res))
@@ -122,7 +141,7 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Read(
         pData = HeapAlloc(GetProcessHeap(), 0, received);
 
         /* work around a GCC bug that occurs here unless we use the reswin32 variable as well */
-        reswin32 = RegQueryValueExW(This->hkey, pszPropName, NULL, &type, pData, &received);
+        reswin32 = RegQueryValueExW(hkey, pszName, NULL, &type, pData, &received);
         res = HRESULT_FROM_WIN32(reswin32);
     }
 
@@ -201,6 +220,9 @@ static HRESULT WINAPI DEVENUM_IPropertyBag_Read(
     if (pData)
         HeapFree(GetProcessHeap(), 0, pData);
 
+    if (This->bInterface)
+        RegCloseKey(hkey);
+
     TRACE("<- %lx\n", res);
     return res;
 }
@@ -270,7 +292,7 @@ static IPropertyBagVtbl IPropertyBag_Vtbl =
     DEVENUM_IPropertyBag_Write
 };
 
-static HRESULT DEVENUM_IPropertyBag_Construct(HANDLE hkey, IPropertyBag **ppBag)
+static HRESULT DEVENUM_IPropertyBag_Construct(HANDLE hkey, IPropertyBag **ppBag, BOOL bInterface)
 {
     RegPropBagImpl * rpb = CoTaskMemAlloc(sizeof(RegPropBagImpl));
     if (!rpb)
@@ -278,6 +300,8 @@ static HRESULT DEVENUM_IPropertyBag_Construct(HANDLE hkey, IPropertyBag **ppBag)
     rpb->lpVtbl = &IPropertyBag_Vtbl;
     rpb->ref = 1;
     rpb->hkey = hkey;
+    rpb->bInterface = bInterface;
+
     *ppBag = (IPropertyBag*)rpb;
     DEVENUM_LockModule();
     return S_OK;
@@ -393,6 +417,7 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToObject(
 {
     IUnknown * pObj = NULL;
     IPropertyBag * pProp = NULL;
+    IPersistPropertyBag * pBag;
     CLSID clsID;
     VARIANT var;
     HRESULT res = E_FAIL;
@@ -430,6 +455,15 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToObject(
 
     if (pObj!=NULL)
     {
+        if (This->bInterface)
+        {
+            res = IUnknown_QueryInterface(pObj, &IID_IPersistPropertyBag, (void**)&pBag);
+            if (SUCCEEDED(res))
+            {
+                res = IPersistPropertyBag_Load(pBag, pProp, NULL); /* FIXME */
+                IPersistPropertyBag_Release(pBag);
+            }
+        }
         /* get the requested interface from the loaded class */
         res= IUnknown_QueryInterface(pObj,riidResult,ppvResult);
     }
@@ -463,7 +497,7 @@ static HRESULT WINAPI DEVENUM_IMediaCatMoniker_BindToStorage(
     {
         HANDLE hkey;
         DuplicateHandle(GetCurrentProcess(), This->hkey, GetCurrentProcess(), &hkey, 0, 0, DUPLICATE_SAME_ACCESS);
-        return DEVENUM_IPropertyBag_Construct(hkey, (IPropertyBag**)ppvObj);
+        return DEVENUM_IPropertyBag_Construct(hkey, (IPropertyBag**)ppvObj, This->bInterface);
     }
 
     return MK_E_NOSTORAGE;
@@ -679,6 +713,7 @@ MediaCatMoniker * DEVENUM_IMediaCatMoniker_Construct()
     pMoniker->lpVtbl = &IMoniker_Vtbl;
     pMoniker->ref = 0;
     pMoniker->hkey = NULL;
+    pMoniker->bInterface = FALSE;
 
     DEVENUM_IMediaCatMoniker_AddRef((LPMONIKER)pMoniker);
 
@@ -764,6 +799,7 @@ static HRESULT WINAPI DEVENUM_IEnumMoniker_Next(LPENUMMONIKER iface, ULONG celt,
         if (!pMoniker)
             return E_OUTOFMEMORY;
 
+        pMoniker->bInterface = This->bInterface;
         if (RegOpenKeyW(This->hkey, buffer, &pMoniker->hkey) != ERROR_SUCCESS)
         {
             DEVENUM_IMediaCatMoniker_Release((LPMONIKER)pMoniker);
@@ -829,7 +865,7 @@ static IEnumMonikerVtbl IEnumMoniker_Vtbl =
     DEVENUM_IEnumMoniker_Clone
 };
 
-HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, IEnumMoniker ** ppEnumMoniker)
+HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, IEnumMoniker ** ppEnumMoniker, BOOL bInterface)
 {
     EnumMonikerImpl * pEnumMoniker = CoTaskMemAlloc(sizeof(EnumMonikerImpl));
     if (!pEnumMoniker)
@@ -839,6 +875,7 @@ HRESULT DEVENUM_IEnumMoniker_Construct(HKEY hkey, IEnumMoniker ** ppEnumMoniker)
     pEnumMoniker->ref = 1;
     pEnumMoniker->index = 0;
     pEnumMoniker->hkey = hkey;
+    pEnumMoniker->bInterface = bInterface;
 
     *ppEnumMoniker = (IEnumMoniker *)pEnumMoniker;
 
index a6c3bdf..da07796 100644 (file)
@@ -71,7 +71,6 @@ CEnumPins::QueryInterface(
     OutputDebugStringW(Buffer);
     CoTaskMemFree(lpstr);
 
-DebugBreak();
     return E_NOINTERFACE;
 }
 
index 51b7872..e56eacb 100644 (file)
@@ -700,7 +700,6 @@ CInputPin::Receive(IMediaSample *pSample)
 {
 #ifdef KSPROXY_TRACE
     OutputDebugStringW(L"CInputPin::Receive NotImplemented\n");
-    DebugBreak();
 #endif
 
     return E_NOTIMPL;
@@ -712,7 +711,6 @@ CInputPin::ReceiveMultiple(IMediaSample **pSamples, long nSamples, long *nSample
 {
 #ifdef KSPROXY_TRACE
     OutputDebugStringW(L"CInputPin::ReceiveMultiple NotImplemented\n");
-    DebugBreak();
 #endif
 
     return E_NOTIMPL;
@@ -724,7 +722,6 @@ CInputPin::ReceiveCanBlock( void)
 {
 #ifdef KSPROXY_TRACE
     OutputDebugStringW(L"CInputPin::ReceiveCanBlock NotImplemented\n");
-    DebugBreak();
 #endif
 
     return S_FALSE;
@@ -923,7 +920,6 @@ CInputPin::KsQualityNotify(
     OutputDebugStringW(L"CInputPin::KsQualityNotify NotImplemented\n");
 #endif
 
-    DebugBreak();
     return E_NOTIMPL;
 }
 
@@ -1114,7 +1110,6 @@ CInputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
 {
 #ifdef KSPROXY_TRACE
     OutputDebugStringW(L"CInputPin::Connect NotImplemented\n");
-    DebugBreak();
 #endif
     return NOERROR;
 }
@@ -1199,7 +1194,6 @@ CInputPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
 
 #ifdef KSPROXY_TRACE
     OutputDebugStringW(L"CInputPin::ConnectionMediaType NotImplemented\n");
-    DebugBreak();
 #endif
 
     return E_NOTIMPL;
@@ -1496,7 +1490,6 @@ CInputPin::CreatePin(
         WCHAR Buffer[100];
         swprintf(Buffer, L"CInputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName);
         OutputDebugStringW(Buffer);
-        DebugBreak();
 #endif
         hr = E_FAIL;
     }
@@ -1629,7 +1622,6 @@ CInputPin::CreatePinHandle(
         {
 #ifdef KSPROXY_TRACE
             OutputDebugStringW(L"CInputPin::CreatePinHandle GetSupportedSets failed\n");
-            DebugBreak();
 #endif
             return hr;
         }
@@ -1640,7 +1632,6 @@ CInputPin::CreatePinHandle(
         {
 #ifdef KSPROXY_TRACE
             OutputDebugStringW(L"CInputPin::CreatePinHandle LoadProxyPlugins failed\n");
-            DebugBreak();
 #endif
             return hr;
         }
@@ -1783,7 +1774,6 @@ CInputPin::LoadProxyPlugins(
         {
             // store plugin
             m_Plugins.push_back(pUnknown);
-DebugBreak();
         }
         // close key
         RegCloseKey(hSubKey);
index e041193..28270cd 100644 (file)
@@ -21,7 +21,6 @@ public:
     STDMETHODIMP_(ULONG) Release()
     {
         InterlockedDecrement(&m_Ref);
-        DebugBreak();
         if (!m_Ref)
         {
             if (m_Allocator)
@@ -280,7 +279,6 @@ STDMETHODCALLTYPE
 CMediaSample::SetMediaType(AM_MEDIA_TYPE *pMediaType)
 {
     OutputDebugStringW(L"CMediaSample::SetMediaType NotImplemented\n");
-    DebugBreak();
     return E_NOTIMPL;
 }
 
index 17f0780..f9f3772 100644 (file)
@@ -1548,7 +1548,6 @@ COutputPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
         OutputDebugStringW(L"COutputPin::Connect no IMemInputPin interface\n");
 #endif
 
-        DebugBreak();
         return hr;
     }
 
@@ -1946,13 +1945,26 @@ COutputPin::CreatePin(
     // query for pin medium
     hr = KsQueryMediums(&MediumList);
     if (FAILED(hr))
+    {
+#ifdef KSPROXY_TRACE
+        WCHAR Buffer[100];
+        swprintf(Buffer, L"COutputPin::CreatePin KsQueryMediums failed %lx\n", hr);
+        OutputDebugStringW(Buffer);
+#endif
         return hr;
+    }
 
     // query for pin interface
     hr = KsQueryInterfaces(&InterfaceList);
     if (FAILED(hr))
     {
         // failed
+#ifdef KSPROXY_TRACE
+        WCHAR Buffer[100];
+        swprintf(Buffer, L"COutputPin::CreatePin KsQueryInterfaces failed %lx\n", hr);
+        OutputDebugStringW(Buffer);
+#endif
+
         CoTaskMemFree(MediumList);
         return hr;
     }
@@ -2003,6 +2015,12 @@ COutputPin::CreatePin(
                 CoTaskMemFree(MediumList);
                 CoTaskMemFree(InterfaceList);
 
+#ifdef KSPROXY_TRACE
+                WCHAR Buffer[100];
+                swprintf(Buffer, L"COutputPin::CreatePin failed to create interface handler %lx\n", hr);
+                OutputDebugStringW(Buffer);
+#endif
+
                 return hr;
             }
 
@@ -2010,7 +2028,12 @@ COutputPin::CreatePin(
             hr = InterfaceHandler->KsSetPin((IKsPin*)this);
             if (FAILED(hr))
             {
-                // failed to load interface handler plugin
+                // failed to initialize interface handler plugin
+#ifdef KSPROXY_TRACE
+                WCHAR Buffer[100];
+                swprintf(Buffer, L"COutputPin::CreatePin failed to initialize interface handler %lx\n", hr);
+                OutputDebugStringW(Buffer);
+#endif
                 InterfaceHandler->Release();
                 CoTaskMemFree(MediumList);
                 CoTaskMemFree(InterfaceList);
@@ -2027,7 +2050,6 @@ COutputPin::CreatePin(
         WCHAR Buffer[100];
         swprintf(Buffer, L"COutputPin::CreatePin unexpected communication %u %s\n", m_Communication, m_PinName);
         OutputDebugStringW(Buffer);
-        DebugBreak();
 #endif
 
         hr = E_FAIL;
@@ -2037,6 +2059,12 @@ COutputPin::CreatePin(
     CoTaskMemFree(MediumList);
     CoTaskMemFree(InterfaceList);
 
+#ifdef KSPROXY_TRACE
+    WCHAR Buffer[100];
+    swprintf(Buffer, L"COutputPin::CreatePin Result %lx\n", hr);
+    OutputDebugStringW(Buffer);
+#endif
+
     return hr;
 }
 
@@ -2058,6 +2086,8 @@ COutputPin::CreatePinHandle(
     //KSPROPERTY Property;
     //ULONG BytesReturned;
 
+    OutputDebugStringW(L"COutputPin::CreatePinHandle\n");
+
     if (m_hPin != INVALID_HANDLE_VALUE)
     {
         // pin already exists
@@ -2173,7 +2203,6 @@ COutputPin::CreatePinHandle(
         if (FAILED(InitializeIOThread()))
         {
             OutputDebugStringW(L"COutputPin::CreatePinHandle failed to initialize i/o thread\n");
-            DebugBreak();
         }
 
         LPGUID pGuid;
@@ -2184,8 +2213,7 @@ COutputPin::CreatePinHandle(
         if (FAILED(hr))
         {
 #ifdef KSPROXY_TRACE
-            OutputDebugStringW(L"CInputPin::CreatePinHandle GetSupportedSets failed\n");
-            DebugBreak();
+            OutputDebugStringW(L"COutputPin::CreatePinHandle GetSupportedSets failed\n");
 #endif
             return hr;
         }
@@ -2195,8 +2223,7 @@ COutputPin::CreatePinHandle(
         if (FAILED(hr))
         {
 #ifdef KSPROXY_TRACE
-            OutputDebugStringW(L"CInputPin::CreatePinHandle LoadProxyPlugins failed\n");
-            DebugBreak();
+            OutputDebugStringW(L"COutputPin::CreatePinHandle LoadProxyPlugins failed\n");
 #endif
             return hr;
         }
@@ -2338,7 +2365,6 @@ COutputPin::LoadProxyPlugins(
         {
             // store plugin
             m_Plugins.push_back(pUnknown);
-DebugBreak();
         }
         // close key
         RegCloseKey(hSubKey);
index eae5de0..f7268b1 100644 (file)
@@ -3,7 +3,7 @@
 #define _FORCENAMELESSUNION
 #define BUILDING_KS
 #define _KSDDK_
-//#define KSPROXY_TRACE
+#define KSPROXY_TRACE
 #include <dshow.h>
 //#include <streams.h>
 #include <ks.h>
index bd34ec8..175eff2 100644 (file)
@@ -1954,7 +1954,6 @@ CKsProxy::IsDirty()
 {
 #ifdef KSPROXY_TRACE
     OutputDebugStringW(L"CKsProxy::IsDirty Notimplemented\n");
-    DebugBreak();
 #endif
     return E_NOTIMPL;
 }
@@ -2035,7 +2034,6 @@ CKsProxy::Load(
 
     }while(Length > 0);
 
-    DebugBreak();
     return S_OK;
 }
 
@@ -2059,7 +2057,6 @@ CKsProxy::GetSizeMax(
 {
 #ifdef KSPROXY_TRACE
     OutputDebugStringW(L"CKsProxy::GetSizeMax Notimplemented\n");
-    DebugBreak();
 #endif
 
     return E_NOTIMPL;
@@ -2480,23 +2477,50 @@ CKsProxy::CreatePins()
         // query current instance count
         hr = GetPinInstanceCount(Index, &Instances);
         if (FAILED(hr))
+        {
+#ifdef KSPROXY_TRACE
+            WCHAR Buffer[100];
+            swprintf(Buffer, L"CKsProxy::CreatePins GetPinInstanceCount failed with %lx\n", hr);
+            OutputDebugStringW(Buffer);
+#endif
             continue;
+        }
+
 
         // query pin communication;
         hr = GetPinCommunication(Index, &Communication);
         if (FAILED(hr))
+        {
+#ifdef KSPROXY_TRACE
+            WCHAR Buffer[100];
+            swprintf(Buffer, L"CKsProxy::CreatePins GetPinCommunication failed with %lx\n", hr);
+            OutputDebugStringW(Buffer);
+#endif
             continue;
+        }
 
         if (Instances.CurrentCount == Instances.PossibleCount)
         {
             // already maximum reached for this pin
+#ifdef KSPROXY_TRACE
+            WCHAR Buffer[100];
+            swprintf(Buffer, L"CKsProxy::CreatePins Instances.CurrentCount == Instances.PossibleCount\n");
+            OutputDebugStringW(Buffer);
+#endif
             continue;
         }
 
         // get direction of pin
         hr = GetPinDataflow(Index, &DataFlow);
         if (FAILED(hr))
+        {
+#ifdef KSPROXY_TRACE
+            WCHAR Buffer[100];
+            swprintf(Buffer, L"CKsProxy::CreatePins GetPinDataflow failed with %lx\n", hr);
+            OutputDebugStringW(Buffer);
+#endif
             continue;
+        }
 
         if (DataFlow == KSPIN_DATAFLOW_IN)
             hr = GetPinName(Index, DataFlow, InputPin, &PinName);
@@ -2504,7 +2528,14 @@ CKsProxy::CreatePins()
             hr = GetPinName(Index, DataFlow, OutputPin, &PinName);
 
         if (FAILED(hr))
+        {
+#ifdef KSPROXY_TRACE
+            WCHAR Buffer[100];
+            swprintf(Buffer, L"CKsProxy::CreatePins GetPinName failed with %lx\n", hr);
+            OutputDebugStringW(Buffer);
+#endif
             continue;
+        }
 
         // construct the pins
         if (DataFlow == KSPIN_DATAFLOW_IN)
@@ -2512,6 +2543,11 @@ CKsProxy::CreatePins()
             hr = CInputPin_Constructor((IBaseFilter*)this, PinName, m_hDevice, Index, Communication, IID_IPin, (void**)&pPin);
             if (FAILED(hr))
             {
+#ifdef KSPROXY_TRACE
+                WCHAR Buffer[100];
+                swprintf(Buffer, L"CKsProxy::CreatePins CInputPin_Constructor failed with %lx\n", hr);
+                OutputDebugStringW(Buffer);
+#endif
                 CoTaskMemFree(PinName);
                 continue;
             }
@@ -2522,6 +2558,11 @@ CKsProxy::CreatePins()
             hr = COutputPin_Constructor((IBaseFilter*)this, PinName, Index, Communication, IID_IPin, (void**)&pPin);
             if (FAILED(hr))
             {
+#ifdef KSPROXY_TRACE
+                WCHAR Buffer[100];
+                swprintf(Buffer, L"CKsProxy::CreatePins COutputPin_Constructor failed with %lx\n", hr);
+                OutputDebugStringW(Buffer);
+#endif
                 CoTaskMemFree(PinName);
                 continue;
             }
@@ -2627,9 +2668,12 @@ CKsProxy::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog)
     hr = LoadProxyPlugins(pGuid, NumGuids);
     if (FAILED(hr))
     {
+#if 0 //HACK
         CloseHandle(m_hDevice);
         m_hDevice = NULL;
         return hr;
+#endif
+        OutputDebugStringW(L"CKsProxy::LoadProxyPlugins failed!\n");
     }
 
     // free sets
@@ -2638,6 +2682,14 @@ CKsProxy::Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog)
     // now create the input / output pins
     hr = CreatePins();
 
+#ifdef KSPROXY_TRACE
+    swprintf(Buffer, L"CKsProxy::Load CreatePins %lx\n", hr);
+    OutputDebugStringW(Buffer);
+#endif
+
+    //HACK
+    hr = S_OK;
+
     return hr;
 }
 
@@ -2986,10 +3038,6 @@ STDMETHODCALLTYPE
 CKsProxy::EnumPins(
     IEnumPins **ppEnum)
 {
-#ifdef KSPROXY_TRACE
-    OutputDebugStringW(L"CKsProxy::EnumPins\n");
-#endif
-
     return CEnumPins_fnConstructor(m_Pins, IID_IEnumPins, (void**)ppEnum);
 }
 
index 5677059..9466aaa 100644 (file)
@@ -155,14 +155,6 @@ CEnumPins_fnConstructor(
 {
     CEnumPins * handler = new CEnumPins(NumPins, pins);
 
-#ifdef MSDVBNP_TRACE
-    WCHAR Buffer[MAX_PATH];
-    LPOLESTR lpstr;
-    StringFromCLSID(riid, &lpstr);
-    swprintf(Buffer, L"CEnumPins_fnConstructor riid %s pUnknown %p\n", lpstr, pUnknown);
-    OutputDebugStringW(Buffer);
-#endif
-
     if (!handler)
         return E_OUTOFMEMORY;
 
index 2da8108..b67f232 100644 (file)
@@ -122,7 +122,7 @@ DllGetClassObject(
 {
     UINT i;
     HRESULT hres = E_OUTOFMEMORY;
-    IClassFactory * pcf = NULL;        
+    IClassFactory * pcf = NULL;
 
     if (!ppv)
         return E_INVALIDARG;
@@ -138,7 +138,7 @@ DllGetClassObject(
         }
     }
 
-    if (!pcf) 
+    if (!pcf)
     {
         return CLASS_E_CLASSNOTAVAILABLE;
     }
index 7dea366..0ac050d 100644 (file)
@@ -201,7 +201,6 @@ CNetworkProvider::QueryInterface(
     swprintf(Buffer, L"CNetworkProvider::QueryInterface: NoInterface for %s !!!\n", lpstr);
     OutputDebugStringW(Buffer);
     CoTaskMemFree(lpstr);
-    DebugBreak();
 
     return E_NOINTERFACE;
 }
index e2acef0..b53ba43 100644 (file)
@@ -51,7 +51,7 @@ public:
     HRESULT STDMETHODCALLTYPE EndFlush();
     HRESULT STDMETHODCALLTYPE NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate);
 
-    CPin(IBaseFilter * ParentFilter) : m_Ref(0), m_ParentFilter(ParentFilter){};
+    CPin(IBaseFilter * ParentFilter);
     virtual ~CPin(){};
 
     static LPCWSTR PIN_ID;
@@ -59,11 +59,31 @@ public:
 protected:
     LONG m_Ref;
     IBaseFilter * m_ParentFilter;
+    AM_MEDIA_TYPE m_MediaType;
+    IPin * m_Pin;
 };
 
 
 LPCWSTR CPin::PIN_ID = L"Antenna Out";
 
+
+CPin::CPin(
+    IBaseFilter * ParentFilter) : m_Ref(0),
+                                  m_ParentFilter(ParentFilter),
+                                  m_Pin(0)
+{
+    m_MediaType.majortype = KSDATAFORMAT_TYPE_BDA_ANTENNA;
+    m_MediaType.subtype = MEDIASUBTYPE_None;
+    m_MediaType.formattype = FORMAT_None;
+    m_MediaType.bFixedSizeSamples = true;
+    m_MediaType.bTemporalCompression = false;
+    m_MediaType.lSampleSize = sizeof(CHAR);
+    m_MediaType.pUnk = NULL;
+    m_MediaType.cbFormat = 0;
+    m_MediaType.pbFormat = NULL;
+}
+
+
 HRESULT
 STDMETHODCALLTYPE
 CPin::QueryInterface(
@@ -100,36 +120,97 @@ HRESULT
 STDMETHODCALLTYPE
 CPin::Connect(IPin *pReceivePin, const AM_MEDIA_TYPE *pmt)
 {
+    HRESULT hr;
     OutputDebugStringW(L"CPin::Connect called\n");
-    return E_NOTIMPL;
+
+    if (pmt)
+    {
+        hr = pReceivePin->QueryAccept(pmt);
+        if (FAILED(hr))
+        {
+            OutputDebugStringW(L"CPin::Connect QueryAccept failed\n");
+            return hr;
+        }
+    }
+    else
+    {
+        // query accept
+        hr = pReceivePin->QueryAccept(&m_MediaType);
+        if (FAILED(hr))
+        {
+            OutputDebugStringW(L"CPin::Connect QueryAccept pmt default failed\n");
+            return hr;
+        }
+
+         pmt = &m_MediaType;
+    }
+
+    // receive connection;
+    hr = pReceivePin->ReceiveConnection((IPin*)this, pmt);
+    if (SUCCEEDED(hr))
+    {
+        // increment reference count
+        pReceivePin->AddRef();
+        m_Pin = pReceivePin;
+        OutputDebugStringW(L"CPin::Connect success\n");
+    }
+
+    return hr;
 }
 
 HRESULT
 STDMETHODCALLTYPE
 CPin::ReceiveConnection(IPin *pConnector, const AM_MEDIA_TYPE *pmt)
 {
-    OutputDebugStringW(L"CPin::ReceiveConnection called\n");
-    return E_NOTIMPL;
+    return E_UNEXPECTED;
 }
+
 HRESULT
 STDMETHODCALLTYPE
 CPin::Disconnect( void)
 {
-    OutputDebugStringW(L"CPin::Disconnect called\n");
-    return E_NOTIMPL;
+#ifdef MSDVBNP_TRACE
+   OutputDebugStringW(L"CPin::Disconnect\n");
+#endif
+
+    if (!m_Pin)
+    {
+        // pin was not connected
+        return S_FALSE;
+    }
+
+    m_Pin->Release();
+    m_Pin = NULL;
+
+    return S_OK;
 }
 HRESULT
 STDMETHODCALLTYPE
 CPin::ConnectedTo(IPin **pPin)
 {
-    OutputDebugStringW(L"CPin::ConnectedTo called\n");
+#ifdef MSDVBNP_TRACE
+   OutputDebugStringW(L"CPin::ConnectedTo\n");
+#endif
+
+    if (!pPin)
+        return E_POINTER;
+
+    if (m_Pin)
+    {
+        // increment reference count
+        m_Pin->AddRef();
+        *pPin = m_Pin;
+        return S_OK;
+    }
+
+    *pPin = NULL;
     return VFW_E_NOT_CONNECTED;
 }
 HRESULT
 STDMETHODCALLTYPE
 CPin::ConnectionMediaType(AM_MEDIA_TYPE *pmt)
 {
-    OutputDebugStringW(L"CPin::ConnectionMediaType called\n");
+    OutputDebugStringW(L"CPin::ConnectionMediaType NotImplemented\n");
     return E_NOTIMPL;
 }
 HRESULT
@@ -170,7 +251,7 @@ HRESULT
 STDMETHODCALLTYPE
 CPin::QueryAccept(const AM_MEDIA_TYPE *pmt)
 {
-    OutputDebugStringW(L"CPin::QueryAccept called\n");
+    OutputDebugStringW(L"CPin::QueryAccept NotImplemented\n");
     return E_NOTIMPL;
 }
 HRESULT
@@ -200,35 +281,35 @@ HRESULT
 STDMETHODCALLTYPE
 CPin::QueryInternalConnections(IPin **apPin, ULONG *nPin)
 {
-    OutputDebugStringW(L"CPin::QueryInternalConnections called\n");
+    OutputDebugStringW(L"CPin::QueryInternalConnections NotImplemented\n");
     return E_NOTIMPL;
 }
 HRESULT
 STDMETHODCALLTYPE
 CPin::EndOfStream( void)
 {
-    OutputDebugStringW(L"CPin::EndOfStream called\n");
+    OutputDebugStringW(L"CPin::EndOfStream NotImplemented\n");
     return E_NOTIMPL;
 }
 HRESULT
 STDMETHODCALLTYPE
 CPin::BeginFlush( void)
 {
-    OutputDebugStringW(L"CPin::BeginFlush called\n");
+    OutputDebugStringW(L"CPin::BeginFlush NotImplemented\n");
     return E_NOTIMPL;
 }
 HRESULT
 STDMETHODCALLTYPE
 CPin::EndFlush( void)
 {
-    OutputDebugStringW(L"CPin::EndFlush called\n");
+    OutputDebugStringW(L"CPin::EndFlush NotImplemented\n");
     return E_NOTIMPL;
 }
 HRESULT
 STDMETHODCALLTYPE
 CPin::NewSegment(REFERENCE_TIME tStart, REFERENCE_TIME tStop, double dRate)
 {
-    OutputDebugStringW(L"CPin::NewSegment called\n");
+    OutputDebugStringW(L"CPin::NewSegment NotImplemented\n");
     return E_NOTIMPL;
 }
 
index e1f187a..3e2b7fe 100644 (file)
@@ -104,7 +104,6 @@ BOOL
 FASTCALL
 DeleteRegion( HRGN hRgn )
 {
-//#if 0
   PRGN_ATTR Rgn_Attr;
 
   if ((GdiGetHandleUserData((HGDIOBJ) hRgn, GDI_OBJECT_TYPE_REGION, (PVOID) &Rgn_Attr)) &&
@@ -128,7 +127,6 @@ DeleteRegion( HRGN hRgn )
         }
      }
   }
-//#endif
   return NtGdiDeleteObjectApp((HGDIOBJ) hRgn);
 }
 
@@ -581,8 +579,110 @@ INT
 WINAPI
 ExtSelectClipRgn( IN HDC hdc, IN HRGN hrgn, IN INT iMode)
 {
-    /* FIXME some part need be done on user mode size */
-    return NtGdiExtSelectClipRgn(hdc,hrgn, iMode);
+  INT Ret;
+  HRGN NewRgn = NULL;
+
+#if 0
+// Handle something other than a normal dc object.
+  if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
+  {
+    if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
+      return MFDRV_ExtSelectClipRgn( hdc, );
+    else
+    {
+      PLDC pLDC = GdiGetLDC(hdc);
+      if ( pLDC )
+      {
+         if (pLDC->iType != LDC_EMFLDC || EMFDRV_ExtSelectClipRgn( hdc, ))
+             return NtGdiExtSelectClipRgn(hdc, );
+      }
+      else
+        SetLastError(ERROR_INVALID_HANDLE);
+      return ERROR;
+    }
+  }
+#endif
+#if 0
+  if ( hrgn )
+  {
+     if ( GetLayout(hdc) & LAYOUT_RTL )
+     {
+        if ( MirrorRgnDC(hdc, hrgn, &NewRgn) )
+        {
+           if ( NewRgn ) hrgn = NewRgn;
+        }
+     }
+  }
+#endif
+  /* Batch handles RGN_COPY only! */
+  if (iMode == RGN_COPY)
+  {
+#if 0
+     PDC_ATTR pDc_Attr;
+     PRGN_ATTR pRgn_Attr = NULL;
+
+     /* hrgn can be NULL unless the RGN_COPY mode is specified. */
+     if (hrgn)
+        GdiGetHandleUserData((HGDIOBJ) hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &pRgn_Attr);
+
+     if ( GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &pDc_Attr) &&
+          pDc_Attr )
+     {
+        PGDI_TABLE_ENTRY pEntry = GdiHandleTable + GDI_HANDLE_GET_INDEX(hdc);
+        PTEB pTeb = NtCurrentTeb();
+        
+        if ( pTeb->Win32ThreadInfo != NULL &&
+             pTeb->GdiTebBatch.HDC == hdc &&
+            !(pDc_Attr->ulDirty_ & DC_DIBSECTION) &&
+            !(pEntry->Flags & GDI_ENTRY_VALIDATE_VIS) )
+        {
+           if (!hrgn ||
+                (hrgn && pRgn_Attr && pRgn_Attr->Flags <= SIMPLEREGION) )
+           {
+              if ((pTeb->GdiTebBatch.Offset + sizeof(GDIBSEXTSELCLPRGN)) <= GDIBATCHBUFSIZE)
+              {
+                 PGDIBSEXTSELCLPRGN pgO = (PGDIBSEXTSELCLPRGN)(&pTeb->GdiTebBatch.Buffer[0] +
+                                                      pTeb->GdiTebBatch.Offset);
+                 pgO->gbHdr.Cmd = GdiBCExtSelClipRgn;
+                 pgO->gbHdr.Size = sizeof(GDIBSEXTSELCLPRGN);
+                 pgO->fnMode = iMode;
+
+                 if ( hrgn && pRgn_Attr )
+                 {
+                    Ret = pRgn_Attr->Flags;
+
+                    if ( pDc_Attr->VisRectRegion.Rect.left   >= pRgn_Attr->Rect.right  ||
+                         pDc_Attr->VisRectRegion.Rect.top    >= pRgn_Attr->Rect.bottom ||
+                         pDc_Attr->VisRectRegion.Rect.right  <= pRgn_Attr->Rect.left   ||
+                         pDc_Attr->VisRectRegion.Rect.bottom <= pRgn_Attr->Rect.top )
+                       Ret = NULLREGION;
+
+                    pgO->left   = pRgn_Attr->Rect.left;
+                    pgO->top    = pRgn_Attr->Rect.top;
+                    pgO->right  = pRgn_Attr->Rect.right;
+                    pgO->bottom = pRgn_Attr->Rect.bottom;
+                 }
+                 else
+                 {
+                    Ret = pDc_Attr->VisRectRegion.Flags;
+                    pgO->fnMode |= 0x80000000; // Set no hrgn mode.
+                 }
+                 pTeb->GdiTebBatch.Offset += sizeof(GDIBSEXTSELCLPRGN);
+                 pTeb->GdiBatchCount++;
+                 if (pTeb->GdiBatchCount >= GDI_BatchLimit) NtGdiFlush();
+                 if ( NewRgn ) DeleteObject(NewRgn);
+                 return Ret;
+              }
+           }
+        }
+     }
+#endif
+  }
+  Ret = NtGdiExtSelectClipRgn(hdc, hrgn, iMode);
+
+  if ( NewRgn ) DeleteObject(NewRgn);
+
+  return Ret;
 }
 
 /*
index e5aa28f..792ed62 100644 (file)
@@ -612,9 +612,11 @@ int WINAPI RestartDialogEx(HWND hWndOwner, LPCWSTR lpwstrReason, DWORD uFlags, D
 
 int WINAPI LogoffWindowsDialog(HWND hWndOwner)
 {
-   UNIMPLEMENTED;
-   ExitWindowsEx(EWX_LOGOFF, 0);
-   return 0;
+    if (ConfirmDialog(hWndOwner, IDS_LOGOFF_PROMPT, IDS_LOGOFF_TITLE))
+    {
+        ExitWindowsEx(EWX_LOGOFF, 0);
+    }
+    return 0;
 }
 
 /*************************************************************************
index fea6d98..5cda676 100644 (file)
@@ -666,6 +666,8 @@ BEGIN
        IDS_RESTART_PROMPT          "Èñêàòå ëè äà ïðåçàïóñíåòå ñèñòåìàòà?"
        IDS_SHUTDOWN_TITLE          "Èçêëþ÷âàíå"
        IDS_SHUTDOWN_PROMPT         "Èñêàòå ëè äà èçêëþ÷èòå êîìïþòúðà?"
+       IDS_LOGOFF_TITLE            "Log Off"
+       IDS_LOGOFF_PROMPT           "Do you want to log off?"
 
        // shell folder path default values 
        IDS_PROGRAMS                "Ïóñêîâ èçáîðíèê\\Ïðèëîæåíèÿ"
index df5cb9e..a26fab0 100644 (file)
@@ -665,6 +665,8 @@ BEGIN
        IDS_RESTART_PROMPT          "Do you want to restart the system?"
        IDS_SHUTDOWN_TITLE          "Shutdown"
        IDS_SHUTDOWN_PROMPT         "Do you want to shutdown?"
+       IDS_LOGOFF_TITLE            "Log Off"
+       IDS_LOGOFF_PROMPT           "Do you want to log off?"
 
        /* shell folder path default values */
        IDS_PROGRAMS                "Start Menu\\Programs"
index b08beea..f2652e6 100644 (file)
@@ -666,6 +666,8 @@ BEGIN
        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"
index 40e1eab..b9cf521 100644 (file)
@@ -654,6 +654,8 @@ BEGIN
        IDS_RESTART_PROMPT          "Ønsker du at Genstarte Systemet?"
        IDS_SHUTDOWN_TITLE          "Luk Ned"
        IDS_SHUTDOWN_PROMPT         "Ønsker du at Lukke Ned?"
+       IDS_LOGOFF_TITLE            "Log Off"
+       IDS_LOGOFF_PROMPT           "Do you want to log off?"
 
        /* shell folder path default values */
        IDS_PROGRAMS                "Start Menu\\Programmer"
index db0fa82..09f6559 100644 (file)
@@ -669,6 +669,8 @@ BEGIN
        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"
index 6b35ec3..0821f01 100644 (file)
@@ -666,6 +666,8 @@ BEGIN
        IDS_RESTART_PROMPT          "Åßóôå óßãïõñïé üôé èÝëåôå íá åðáíåêêéíÞóåôå ôïí õðïëïãéóôÞ óáò;"
        IDS_SHUTDOWN_TITLE          "Áðåíåñãïðïßçóç"
        IDS_SHUTDOWN_PROMPT         "Åßóôå óßãïõñïé üôé èÝëåôå íá áðåíåñãïðïéÞóåôå ôïí õðïëïãéóôÞ óáò;"
+       IDS_LOGOFF_TITLE            "Log Off"
+       IDS_LOGOFF_PROMPT           "Do you want to log off?"
 
        /* shell folder path default values */
        IDS_PROGRAMS                "Start Menu\\Programs"
index 38203c2..3dfbfd9 100644 (file)
@@ -665,6 +665,8 @@ BEGIN
        IDS_RESTART_PROMPT          "Do you want to restart the system?"
        IDS_SHUTDOWN_TITLE          "Shutdown"
        IDS_SHUTDOWN_PROMPT         "Do you want to shutdown?"
+       IDS_LOGOFF_TITLE            "Log Off"
+       IDS_LOGOFF_PROMPT           "Do you want to log off?"
 
        /* shell folder path default values */
        IDS_PROGRAMS                "Start Menu\\Programs"
index 63d38cb..200c97a 100644 (file)
@@ -665,6 +665,8 @@ BEGIN
        IDS_RESTART_PROMPT          "Do you want to restart the system?"
        IDS_SHUTDOWN_TITLE          "Shutdown"
        IDS_SHUTDOWN_PROMPT         "Do you want to shutdown?"
+       IDS_LOGOFF_TITLE            "Log Off"
+       IDS_LOGOFF_PROMPT           "Do you want to log off?"
 
        /* shell folder path default values */
        IDS_PROGRAMS                "Start Menu\\Programs"
index 0e20abc..a0dacf6 100644 (file)
@@ -668,6 +668,8 @@ BEGIN
        IDS_RESTART_PROMPT          "¿Desea reiniciar el equipo?"
        IDS_SHUTDOWN_TITLE          "Apagar"
        IDS_SHUTDOWN_PROMPT         "¿Desea apagar el equipo?"
+       IDS_LOGOFF_TITLE            "Log Off"
+       IDS_LOGOFF_PROMPT           "Do you want to log off?"
 
        /* shell folder path default values */
        IDS_PROGRAMS                "Menú Inicio\\Programas"
index 2620c2b..778576a 100644 (file)
@@ -665,6 +665,8 @@ BEGIN
        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"
index 98cd95f..3f712a6 100644 (file)
@@ -669,6 +669,8 @@ BEGIN
        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"
index 7016d50..22a2603 100644 (file)
@@ -668,6 +668,8 @@ BEGIN
        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"
index 986ecfe..4407298 100644 (file)
@@ -666,6 +666,8 @@ BEGIN
        IDS_RESTART_PROMPT          "Volete riavviare il sistema?"
        IDS_SHUTDOWN_TITLE          "Termina sessione"
        IDS_SHUTDOWN_PROMPT         "Volete terminare la sessione di ReactOS?"
+       IDS_LOGOFF_TITLE            "Log Off"
+       IDS_LOGOFF_PROMPT           "Do you want to log off?"
 
        /* shell folder path default values */
        IDS_PROGRAMS                "Menu Avvio\\Programmi"
index 47c5bfb..12f24d3 100644 (file)
@@ -665,6 +665,8 @@ BEGIN
        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[\83\83\81\83j\83\85\81[\\\83v\83\8d\83O\83\89\83\80"
index e9e67b7..9d7ad80 100644 (file)
@@ -665,6 +665,8 @@ BEGIN
        IDS_RESTART_PROMPT          "Do you want to restart the system?"
        IDS_SHUTDOWN_TITLE          "Shutdown"
        IDS_SHUTDOWN_PROMPT         "Do you want to shutdown?"
+       IDS_LOGOFF_TITLE            "Log Off"
+       IDS_LOGOFF_PROMPT           "Do you want to log off?"
 
        /* shell folder path default values */
        IDS_PROGRAMS                "Start Menu\\Programs"
index 5ff6c83..b0e1c91 100644 (file)
@@ -665,6 +665,8 @@ BEGIN
        IDS_RESTART_PROMPT          "Do you want to restart the system?"
        IDS_SHUTDOWN_TITLE          "Shutdown"
        IDS_SHUTDOWN_PROMPT         "Do you want to shutdown?"
+       IDS_LOGOFF_TITLE            "Log Off"
+       IDS_LOGOFF_PROMPT           "Do you want to log off?"
 
        /* shell folder path default values */
        IDS_PROGRAMS                "Start Menu\\Programs"
index 90dc27d..43c637f 100644 (file)
@@ -668,6 +668,8 @@ BEGIN
        IDS_RESTART_PROMPT          "Vil du starte datamaskinen på nytt?"
        IDS_SHUTDOWN_TITLE          "Avslutt"
        IDS_SHUTDOWN_PROMPT         "Vil du slå av datamaskinen?"
+       IDS_LOGOFF_TITLE            "Log Off"
+       IDS_LOGOFF_PROMPT           "Do you want to log off?"
 
        /* shell folder path default values */
        IDS_PROGRAMS                "Start-meny\\Programmer"
index b6d33a6..a0d3682 100644 (file)
@@ -672,6 +672,8 @@ BEGIN
        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"
index 048d4c3..5bcee21 100644 (file)
@@ -667,6 +667,8 @@ BEGIN
        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"
index c20e670..dbf3fe2 100644 (file)
@@ -667,6 +667,8 @@ BEGIN
        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"
index 656bc41..efbff85 100644 (file)
@@ -668,6 +668,8 @@ BEGIN
        IDS_RESTART_PROMPT          "Vreți să reporniți sistemul?"
        IDS_SHUTDOWN_TITLE          "Închidere"
        IDS_SHUTDOWN_PROMPT         "Vreți să închideți computerul?"
+       IDS_LOGOFF_TITLE            "Log Off"
+       IDS_LOGOFF_PROMPT           "Do you want to log off?"
 
        /* shell folder path default values */
        IDS_PROGRAMS                "Meniu Start\\Programe"
index 7d6e1e1..6c3f488 100644 (file)
@@ -664,6 +664,8 @@ BEGIN
        IDS_RESTART_PROMPT          "Âû äåéñòâèòåëüíî õîòèòå ïåðåçàãðóçèòü ReactOS?"
        IDS_SHUTDOWN_TITLE          "Âûêëþ÷èòü ïèòàíèå"
        IDS_SHUTDOWN_PROMPT         "Çàêîí÷èòü ðàáîòó ñ ReactOS?"
+       IDS_LOGOFF_TITLE            "Log Off"
+       IDS_LOGOFF_PROMPT           "Do you want to log off?"
 
        /* shell folder path default values */
        IDS_PROGRAMS                "Ãëàâíîå ìåíþ\\Ïðîãðàììû"
index 2ec58ec..e45b141 100644 (file)
@@ -671,6 +671,8 @@ BEGIN
        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"
index 876be4b..5038af1 100644 (file)
@@ -665,6 +665,8 @@ BEGIN
        IDS_RESTART_PROMPT          "Do you want to restart the system?"
        IDS_SHUTDOWN_TITLE          "Shutdown"
        IDS_SHUTDOWN_PROMPT         "Do you want to shutdown?"
+       IDS_LOGOFF_TITLE            "Log Off"
+       IDS_LOGOFF_PROMPT           "Do you want to log off?"
 
        /* shell folder path default values */
        IDS_PROGRAMS                "Start Menu\\Programs"
index e7a520f..08a6f59 100644 (file)
@@ -665,6 +665,8 @@ BEGIN
        IDS_RESTART_PROMPT          "Do you want to restart the system?"
        IDS_SHUTDOWN_TITLE          "Shutdown"
        IDS_SHUTDOWN_PROMPT         "Do you want to shutdown?"
+       IDS_LOGOFF_TITLE            "Log Off"
+       IDS_LOGOFF_PROMPT           "Do you want to log off?"
 
        /* shell folder path default values */
        IDS_PROGRAMS                "Start Menu\\Programs"
index 49a154c..3ab92cb 100644 (file)
@@ -665,6 +665,8 @@ BEGIN
        IDS_RESTART_PROMPT          "Do you want to restart the system?"
        IDS_SHUTDOWN_TITLE          "Oturumu Kapat"
        IDS_SHUTDOWN_PROMPT         "Do you want to shutdown?"
+       IDS_LOGOFF_TITLE            "Log Off"
+       IDS_LOGOFF_PROMPT           "Do you want to log off?"
 
        /* shell folder path default values */
        IDS_PROGRAMS                "Start Menu\\Programlar"
index 3846965..cf2847e 100644 (file)
@@ -666,6 +666,8 @@ BEGIN
        IDS_RESTART_PROMPT          "Âè õî÷åòå ïåðåçàâàíòàæèòè ñèñòåìó?"
        IDS_SHUTDOWN_TITLE          "Âèìêíóòè"
        IDS_SHUTDOWN_PROMPT         "Âè õî÷åòå âèìêíóòè êîìï'þòåð?"
+       IDS_LOGOFF_TITLE            "Log Off"
+       IDS_LOGOFF_PROMPT           "Do you want to log off?"
 
        /* shell folder path default values */
        IDS_PROGRAMS                "Start Menu\\Programs"
index 5180db5..18c4d54 100644 (file)
@@ -654,6 +654,8 @@ BEGIN
        IDS_RESTART_PROMPT          "ÊÇ·ñÖØÐÂÆô¶¯ÏµÍ³?"
        IDS_SHUTDOWN_TITLE          "¹Ø»ú"
        IDS_SHUTDOWN_PROMPT         "ÊÇ·ñ¹Ø±Õϵͳ?"
+       IDS_LOGOFF_TITLE            "Log Off"
+       IDS_LOGOFF_PROMPT           "Do you want to log off?"
 
        /* shell folder path default values */
        IDS_PROGRAMS                "Start Menu\\Programs"
index fc76bf1..f7c59a2 100644 (file)
@@ -666,6 +666,8 @@ BEGIN
        IDS_RESTART_PROMPT          "Do you want to restart the system?"
        IDS_SHUTDOWN_TITLE          "Shutdown"
        IDS_SHUTDOWN_PROMPT         "Do you want to shutdown?"
+       IDS_LOGOFF_TITLE            "Log Off"
+       IDS_LOGOFF_PROMPT           "Do you want to log off?"
 
        /* shell folder path default values */
        IDS_PROGRAMS                "Start Menu\\Programs"
index e28efb0..981e17f 100644 (file)
@@ -90,6 +90,9 @@
 #define IDS_FONTS                   76
 #define IDS_PRINTERS                77
 
+#define IDS_LOGOFF_TITLE            78
+#define IDS_LOGOFF_PROMPT           79
+
 #define IDS_CREATEFOLDER_DENIED     128
 #define IDS_CREATEFOLDER_CAPTION    129
 #define IDS_DELETEITEM_CAPTION      130
diff --git a/drivers/battery/cmbatt/cmbatt.c b/drivers/battery/cmbatt/cmbatt.c
deleted file mode 100644 (file)
index b85f3eb..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * PROJECT:         ReactOS Kernel
- * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            drivers/battery/cmbatt/cmbatt.c
- * PURPOSE:         Control Method Battery Miniclass Driver
- * PROGRAMMERS:     Cameron Gutman (cameron.gutman@reactos.org)
- */
-
-#include <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;
-}
diff --git a/drivers/battery/cmbatt/cmbatt.h b/drivers/battery/cmbatt/cmbatt.h
deleted file mode 100644 (file)
index e70b561..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
-* PROJECT:         ReactOS Kernel
-* LICENSE:         GPL - See COPYING in the top level directory
-* FILE:            drivers/battery/cmbatt/cmbatt.h
-* PURPOSE:         Control Method Battery Miniclass Driver
-* PROGRAMMERS:     Cameron Gutman (cameron.gutman@reactos.org)
-*/
-
-#pragma once
-
-#include <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);
diff --git a/drivers/battery/cmbatt/cmbatt.rbuild b/drivers/battery/cmbatt/cmbatt.rbuild
deleted file mode 100644 (file)
index c41a072..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<?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>
diff --git a/drivers/battery/cmbatt/cmbatt.rc b/drivers/battery/cmbatt/cmbatt.rc
deleted file mode 100644 (file)
index 2fd6bc7..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#define REACTOS_VERSION_DLL
-#define REACTOS_STR_FILE_DESCRIPTION   "Control Method Battery Miniclass Driver\0"
-#define REACTOS_STR_INTERNAL_NAME      "cmbatt\0"
-#define REACTOS_STR_ORIGINAL_FILENAME  "cmbatt.sys\0"
-#include <reactos/version.rc>
diff --git a/drivers/battery/cmbatt/miniclass.c b/drivers/battery/cmbatt/miniclass.c
deleted file mode 100644 (file)
index bb75d9a..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * PROJECT:         ReactOS Kernel
- * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            drivers/battery/cmbatt/miniclass.c
- * PURPOSE:         Control Method Battery Miniclass Driver
- * PROGRAMMERS:     Cameron Gutman (cameron.gutman@reactos.org)
- */
-
-#include <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;
-}
index 2da9fe0..ee79df9 100644 (file)
@@ -4,7 +4,4 @@
 <directory name="battc">
        <xi:include href="battc/battc.rbuild" />
 </directory>
-<directory name="cmbatt">
-       <xi:include href="cmbatt/cmbatt.rbuild" />
-</directory>
 </group>
index 34c85ad..1af50b4 100644 (file)
@@ -1,6 +1,6 @@
 <?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>
index a6904a2..11a8fbe 100644 (file)
@@ -10,4 +10,7 @@
 <directory name="pci">
        <xi:include href="pci/pci.rbuild" />
 </directory>
+<directory name="pcix">
+       <xi:include href="pcix/pcix.rbuild" />
+</directory>
 </group>
index f19e45c..6fde92e 100644 (file)
@@ -775,7 +775,7 @@ PdoQueryResources(
       Descriptor->ShareDisposition = CmResourceShareShared;
       Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
       Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine;
-      Descriptor->u.Interrupt.Vector = 0;
+      Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine;
       Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
     }
   }
@@ -1186,6 +1186,49 @@ PdoQueryInterface(
   return Status;
 }
 
+static NTSTATUS
+PdoStartDevice(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PIRP Irp,
+  PIO_STACK_LOCATION IrpSp)
+{
+  PCM_RESOURCE_LIST RawResList = IrpSp->Parameters.StartDevice.AllocatedResources;
+  PCM_FULL_RESOURCE_DESCRIPTOR RawFullDesc;
+  PCM_PARTIAL_RESOURCE_DESCRIPTOR RawPartialDesc;
+  ULONG i, ii;
+  PPDO_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+  UCHAR Irq;
+
+  /* TODO: Assign the other resources we get to the card */
+
+  for (i = 0; i < RawResList->Count; i++)
+  {
+      RawFullDesc = &RawResList->List[i];
+
+      for (ii = 0; ii < RawFullDesc->PartialResourceList.Count; ii++)
+      {
+          RawPartialDesc = &RawFullDesc->PartialResourceList.PartialDescriptors[ii];
+
+          if (RawPartialDesc->Type == CmResourceTypeInterrupt)
+          {
+              DPRINT1("Assigning IRQ %x to PCI device (%x, %x)\n",
+                      RawPartialDesc->u.Interrupt.Vector,
+                      DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
+                      DeviceExtension->PciDevice->BusNumber);
+
+              Irq = (UCHAR)RawPartialDesc->u.Interrupt.Vector;
+              HalSetBusDataByOffset(PCIConfiguration,
+                                    DeviceExtension->PciDevice->BusNumber,
+                                    DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
+                                    &Irq,
+                                    0x3c /* PCI_INTERRUPT_LINE */,
+                                    sizeof(UCHAR));
+          }
+      }
+   }
+
+   return STATUS_SUCCESS;
+}
 
 static NTSTATUS
 PdoReadConfig(
@@ -1247,6 +1290,33 @@ PdoWriteConfig(
   return STATUS_SUCCESS;
 }
 
+static NTSTATUS
+PdoQueryDeviceRelations(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PIRP Irp,
+  PIO_STACK_LOCATION IrpSp)
+{
+  PDEVICE_RELATIONS DeviceRelations;
+
+  /* We only support TargetDeviceRelation for child PDOs */
+  if (IrpSp->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
+      return Irp->IoStatus.Status;
+
+  /* We can do this because we only return 1 PDO for TargetDeviceRelation */
+  DeviceRelations = ExAllocatePool(PagedPool, sizeof(*DeviceRelations));
+  if (!DeviceRelations)
+      return STATUS_INSUFFICIENT_RESOURCES;
+
+  DeviceRelations->Count = 1;
+  DeviceRelations->Objects[0] = DeviceObject;
+
+  /* The PnP manager will remove this when it is done with the PDO */
+  ObReferenceObject(DeviceObject);
+
+  Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
+
+  return STATUS_SUCCESS;
+}
 
 static NTSTATUS
 PdoSetPower(
@@ -1319,8 +1389,7 @@ PdoPnpControl(
     break;
 
   case IRP_MN_QUERY_DEVICE_RELATIONS:
-    /* FIXME: Possibly handle for RemovalRelations */
-    DPRINT("Unimplemented IRP_MN_QUERY_DEVICE_RELATIONS received\n");
+    Status = PdoQueryDeviceRelations(DeviceObject, Irp, IrpSp);
     break;
 
   case IRP_MN_QUERY_DEVICE_TEXT:
@@ -1352,6 +1421,9 @@ PdoPnpControl(
     break;
 
   case IRP_MN_START_DEVICE:
+    Status = PdoStartDevice(DeviceObject, Irp, IrpSp);
+    break;
+
   case IRP_MN_QUERY_STOP_DEVICE:
   case IRP_MN_CANCEL_STOP_DEVICE:
   case IRP_MN_STOP_DEVICE:
diff --git a/drivers/bus/pcix/arb/ar_busno.c b/drivers/bus/pcix/arb/ar_busno.c
new file mode 100644 (file)
index 0000000..5086357
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/arb/ar_busno.c
+ * PURPOSE:         Bus Number Arbitration
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/arb/ar_memio.c b/drivers/bus/pcix/arb/ar_memio.c
new file mode 100644 (file)
index 0000000..47d6e07
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/arb/ar_memiono.c
+ * PURPOSE:         Memory and I/O Port Resource Arbitration
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/arb/arb_comn.c b/drivers/bus/pcix/arb/arb_comn.c
new file mode 100644 (file)
index 0000000..3759169
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/arb/arb_comn.c
+ * PURPOSE:         Common Arbitration Code
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/arb/tr_irq.c b/drivers/bus/pcix/arb/tr_irq.c
new file mode 100644 (file)
index 0000000..7d27173
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/arb/tr_irq.c
+ * PURPOSE:         IRQ Resource Translation
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/debug.c b/drivers/bus/pcix/debug.c
new file mode 100644 (file)
index 0000000..2185b02
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/debug.c
+ * PURPOSE:         Debug Helpers
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/device.c b/drivers/bus/pcix/device.c
new file mode 100644 (file)
index 0000000..7f08dcf
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/device.c
+ * PURPOSE:         Device Management
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/dispatch.c b/drivers/bus/pcix/dispatch.c
new file mode 100644 (file)
index 0000000..e69416d
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/dispatch.c
+ * PURPOSE:         WDM Dispatch Routines
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/enum.c b/drivers/bus/pcix/enum.c
new file mode 100644 (file)
index 0000000..d67db28
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/enum.c
+ * PURPOSE:         PCI Bus/Device Enumeration
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/fdo.c b/drivers/bus/pcix/fdo.c
new file mode 100644 (file)
index 0000000..f4d3095
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/fdo.c
+ * PURPOSE:         FDO Device Management
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/guid.c b/drivers/bus/pcix/guid.c
new file mode 100644 (file)
index 0000000..7dd27e9
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/guid.c
+ * PURPOSE:         GUID Data
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/hookhal.c b/drivers/bus/pcix/hookhal.c
new file mode 100644 (file)
index 0000000..786add8
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/hookhal.c
+ * PURPOSE:         HAL Bus Handler Dispatch Routine Support
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/init.c b/drivers/bus/pcix/init.c
new file mode 100644 (file)
index 0000000..18cbed0
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/init.c
+ * PURPOSE:         Driver Initialization
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <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 */
diff --git a/drivers/bus/pcix/intrface/agpintrf.c b/drivers/bus/pcix/intrface/agpintrf.c
new file mode 100644 (file)
index 0000000..351ae57
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/intrface/agpintrf.c
+ * PURPOSE:         AGP Interface
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/intrface/busintrf.c b/drivers/bus/pcix/intrface/busintrf.c
new file mode 100644 (file)
index 0000000..468d9ed
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/intrface/busintrf.c
+ * PURPOSE:         Bus Interface
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/intrface/cardbus.c b/drivers/bus/pcix/intrface/cardbus.c
new file mode 100644 (file)
index 0000000..a36f2d8
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/intrface/cardbus.c
+ * PURPOSE:         CardBus Interface
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/intrface/ideintrf.c b/drivers/bus/pcix/intrface/ideintrf.c
new file mode 100644 (file)
index 0000000..ec2ff82
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/intrface/ideintrf.c
+ * PURPOSE:         IDE Interface
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/intrface/intrface.c b/drivers/bus/pcix/intrface/intrface.c
new file mode 100644 (file)
index 0000000..e8d0dd5
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/intrface/intrface.c
+ * PURPOSE:         Common Interface Support Routines
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/intrface/lddintrf.c b/drivers/bus/pcix/intrface/lddintrf.c
new file mode 100644 (file)
index 0000000..4322455
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/intrface/lddintrf.c
+ * PURPOSE:         Legacy Device Detection Interface
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/intrface/locintrf.c b/drivers/bus/pcix/intrface/locintrf.c
new file mode 100644 (file)
index 0000000..a633d98
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/intrface/locintrf.c
+ * PURPOSE:         Location Interface
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/intrface/pmeintf.c b/drivers/bus/pcix/intrface/pmeintf.c
new file mode 100644 (file)
index 0000000..ecb3b6e
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/intrface/pmeintf.c
+ * PURPOSE:         Power Management Event# Signal Interface
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/intrface/routintf.c b/drivers/bus/pcix/intrface/routintf.c
new file mode 100644 (file)
index 0000000..6332953
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/intrface/routinf.c
+ * PURPOSE:         Routing Interface
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/pci.h b/drivers/bus/pcix/pci.h
new file mode 100644 (file)
index 0000000..6343211
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/pci.h
+ * PURPOSE:         Main Header File
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+#include <ntddk.h>
+
+/* EOF */
diff --git a/drivers/bus/pcix/pci.rc b/drivers/bus/pcix/pci.rc
new file mode 100644 (file)
index 0000000..001529b
--- /dev/null
@@ -0,0 +1,5 @@
+#define REACTOS_VERSION_DLL
+#define REACTOS_STR_FILE_DESCRIPTION   "PCI Bus Driver\0"
+#define REACTOS_STR_INTERNAL_NAME      "pci\0"
+#define REACTOS_STR_ORIGINAL_FILENAME  "pci.sys\0"
+#include <reactos/version.rc>
diff --git a/drivers/bus/pcix/pci/busno.c b/drivers/bus/pcix/pci/busno.c
new file mode 100644 (file)
index 0000000..e5a9816
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/pci/busno.c
+ * PURPOSE:         Bus Number Management
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/pci/config.c b/drivers/bus/pcix/pci/config.c
new file mode 100644 (file)
index 0000000..9bdbb0f
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/pci/config.c
+ * PURPOSE:         PCI Configuration Space Routines
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/pci/devhere.c b/drivers/bus/pcix/pci/devhere.c
new file mode 100644 (file)
index 0000000..4a666b9
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/pci/devhere.c
+ * PURPOSE:         PCI Device Detection and Location
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/pci/id.c b/drivers/bus/pcix/pci/id.c
new file mode 100644 (file)
index 0000000..d4fd910
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/pci/id.c
+ * PURPOSE:         PCI Device Identification
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/pci/ppbridge.c b/drivers/bus/pcix/pci/ppbridge.c
new file mode 100644 (file)
index 0000000..738b5c0
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/pci/ppbridge.c
+ * PURPOSE:         PCI-to-PCI Bridge Support
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/pci/romimage.c b/drivers/bus/pcix/pci/romimage.c
new file mode 100644 (file)
index 0000000..96575f3
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/pci/romimage.c
+ * PURPOSE:         PCI ROM Image Support
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/pci/state.c b/drivers/bus/pcix/pci/state.c
new file mode 100644 (file)
index 0000000..d2f3048
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/pci/state.c
+ * PURPOSE:         Bus/Device State Support
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/pcivrify.c b/drivers/bus/pcix/pcivrify.c
new file mode 100644 (file)
index 0000000..15ed1b6
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/pcivrify.c
+ * PURPOSE:         PCI Driver Verifier Support
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/pcix.rbuild b/drivers/bus/pcix/pcix.rbuild
new file mode 100644 (file)
index 0000000..257387b
--- /dev/null
@@ -0,0 +1,49 @@
+<?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>
diff --git a/drivers/bus/pcix/pdo.c b/drivers/bus/pcix/pdo.c
new file mode 100644 (file)
index 0000000..b54dda4
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/pdo.c
+ * PURPOSE:         PDO Device Management
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/power.c b/drivers/bus/pcix/power.c
new file mode 100644 (file)
index 0000000..71a745b
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/power.c
+ * PURPOSE:         Bus/Device Power Management
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/usage.c b/drivers/bus/pcix/usage.c
new file mode 100644 (file)
index 0000000..b317439
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/usage.c
+ * PURPOSE:         Bus/Device Usage Reporting
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
diff --git a/drivers/bus/pcix/utils.c b/drivers/bus/pcix/utils.c
new file mode 100644 (file)
index 0000000..a73b0de
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * PROJECT:         ReactOS PCI Bus Driver
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            drivers/bus/pci/utils.c
+ * PURPOSE:         Utility/Helper Support Code
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <pci.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+/* FUNCTIONS ******************************************************************/
+
+/* EOF */
index af9fd81..f1ac9a8 100644 (file)
@@ -94,6 +94,8 @@ KsReleaseDeviceSecurityLock(
 {
     PKSIDEVICE_HEADER Header = (PKSIDEVICE_HEADER)DevHeader;
 
+    DPRINT("KsReleaseDevice\n");
+
     ExReleaseResourceLite(&Header->SecurityLock);
     KeLeaveCriticalRegion();
 }
@@ -1589,7 +1591,7 @@ KsAcquireControl(
     /* sanity check */
     ASSERT(BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
 
-    KeWaitForSingleObject(&BasicHeader->ControlMutex, Executive, KernelMode, FALSE, NULL);
+    KeWaitForSingleObject(BasicHeader->ControlMutex, Executive, KernelMode, FALSE, NULL);
 
 }
 
@@ -1606,7 +1608,7 @@ KsReleaseControl(
     /* sanity check */
     ASSERT(BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
 
-    KeReleaseMutex(&BasicHeader->ControlMutex, FALSE);
+    KeReleaseMutex(BasicHeader->ControlMutex, FALSE);
 }
 
 
@@ -1621,7 +1623,10 @@ KsAcquireDevice(
     IN PKSDEVICE Device)
 {
     IKsDevice *KsDevice;
-    PKSIDEVICE_HEADER DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice);
+    PKSIDEVICE_HEADER DeviceHeader;
+
+    DPRINT("KsAcquireDevice\n");
+    DeviceHeader = (PKSIDEVICE_HEADER)CONTAINING_RECORD(Device, KSIDEVICE_HEADER, KsDevice);
 
     /* get device interface*/
     KsDevice = (IKsDevice*)&DeviceHeader->lpVtblIKsDevice;
index 1b7eec9..d0b76cc 100644 (file)
@@ -89,6 +89,8 @@ KsAddItemToObjectBag(
     PKSIOBJECT_BAG Bag;
     PKSIOBJECT_BAG_ENTRY BagEntry;
 
+    DPRINT("KsAddItemToObjectBag\n");
+
     /* get real object bag */
     Bag = (PKSIOBJECT_BAG)ObjectBag;
 
@@ -363,6 +365,8 @@ _KsEdit(
     PVOID Item;
     NTSTATUS Status;
 
+    DPRINT("_KsEdit\n");
+
     /* get real object bag */
     Bag = (PKSIOBJECT_BAG)ObjectBag;
 
index 3961193..f3e7d7a 100644 (file)
@@ -98,10 +98,10 @@ IKsClock_DispatchDeviceIoControl(
 {
     UNIMPLEMENTED
 
-    Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
+    Irp->IoStatus.Status = STATUS_SUCCESS;
     IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
-    return STATUS_NOT_IMPLEMENTED;
+    return STATUS_SUCCESS;
 }
 
 NTSTATUS
index ae9200b..7c9b822 100644 (file)
@@ -392,34 +392,18 @@ KsPinPropertyHandler(
                 break;
             }
 
-            /* calculate size */
-            Size = sizeof(KSMULTIPLE_ITEM);
-            Size += max(1, Descriptor[Pin->PinId].InterfacesCount) * sizeof(KSPIN_INTERFACE);
-
-            if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < Size)
+            if (Descriptor[Pin->PinId].Interfaces)
             {
-                Irp->IoStatus.Information = Size;
-                Status = STATUS_MORE_ENTRIES;
-                break;
-            }
-
-            Item = (KSMULTIPLE_ITEM*)Buffer;
-            Item->Size = Size;
-
-            if (Descriptor[Pin->PinId].InterfacesCount)
-            {
-                Item->Count = Descriptor[Pin->PinId].InterfacesCount;
-                RtlMoveMemory((PVOID)(Item + 1), Descriptor[Pin->PinId].Interfaces, Descriptor[Pin->PinId].InterfacesCount * sizeof(KSPIN_INTERFACE));
+                /* use mediums provided by driver */
+                return KsHandleSizedListQuery(Irp, Descriptor[Pin->PinId].InterfacesCount, sizeof(KSPIN_MEDIUM), Descriptor[Pin->PinId].Interfaces);
             }
             else
             {
-                Item->Count = 1;
-                RtlMoveMemory((PVOID)(Item + 1), &StandardPinInterface, sizeof(KSPIN_INTERFACE));
+                /* use standard medium */
+                return KsHandleSizedListQuery(Irp, 1, sizeof(KSPIN_INTERFACE), &StandardPinInterface);
             }
-
-            Status = STATUS_SUCCESS;
-            Irp->IoStatus.Information = Size;
             break;
+
         case KSPROPERTY_PIN_MEDIUMS:
             Pin = (KSP_PIN*)Property;
             if (Pin->PinId >= DescriptorsCount)
index 345689f..cf1d3f7 100644 (file)
@@ -492,7 +492,7 @@ IKsDevice_Pnp(
         }
         case IRP_MN_QUERY_INTERFACE:
         {
-            Status = STATUS_SUCCESS;
+            Status = STATUS_UNSUCCESSFUL;
             /* check for pnp notification support */
             if (Dispatch)
             {
@@ -508,6 +508,7 @@ IKsDevice_Pnp(
             if (NT_SUCCESS(Status))
             {
                 /* driver supports a private interface */
+                DPRINT1("IRP_MN_QUERY_INTERFACE Device supports interface\n");
                 Irp->IoStatus.Status = Status;
                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
                 return Status;
index b1e74cd..cd0ffe2 100644 (file)
@@ -18,7 +18,7 @@ KspSetDeviceInterfacesState(
         /* set device interface state */
         Status = IoSetDeviceInterfaceState(&SymEntry->SymbolicLink, Enable);
 
-        DPRINT("KspSetDeviceInterfacesState SymbolicLink %S Status %lx\n", SymEntry->SymbolicLink.Buffer, Status, Enable);
+        DPRINT("KspSetDeviceInterfacesState SymbolicLink '%S' Status %lx\n", SymEntry->SymbolicLink.Buffer, Status, Enable);
 
         /* check for success */
         if (!NT_SUCCESS(Status))
index f6ace30..0b6cf43 100644 (file)
@@ -37,11 +37,14 @@ NTAPI
 KsGetDevice(
     IN PVOID Object)
 {
-    PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)(ULONG_PTR)Object - sizeof(KSBASIC_HEADER);
+    PKSBASIC_HEADER BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)Object - sizeof(KSBASIC_HEADER));
 
-    DPRINT("KsGetDevice %p\n", Object);
+    DPRINT("KsGetDevice\n");
 
-    ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory || BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == BasicHeader->Type);
+    ASSERT(BasicHeader->Type == KsObjectTypeFilterFactory || BasicHeader->Type == KsObjectTypeFilter || BasicHeader->Type == KsObjectTypePin);
+    ASSERT(BasicHeader->KsDevice);
+    ASSERT(BasicHeader->KsDevice->Started);
+    ASSERT(BasicHeader->KsDevice->PhysicalDeviceObject);
 
     return BasicHeader->KsDevice;
 }
@@ -151,6 +154,8 @@ KsInitializeDriver(
     PKS_DRIVER_EXTENSION DriverObjectExtension;
     NTSTATUS Status = STATUS_SUCCESS;
 
+    DPRINT("KsInitializeDriver\n");
+
     if (Descriptor)
     {
         Status = IoAllocateDriverObjectExtension(DriverObject, (PVOID)KsInitializeDriver, sizeof(KS_DRIVER_EXTENSION), (PVOID*)&DriverObjectExtension);
index 7a8e5b2..2fb6997 100644 (file)
@@ -21,10 +21,12 @@ typedef struct
 
     PKSIOBJECT_HEADER ObjectHeader;
     KSTOPOLOGY Topology;
+    KSPIN_DESCRIPTOR_EX * PinDescriptorsEx;
     KSPIN_DESCRIPTOR * PinDescriptors;
     ULONG PinDescriptorCount;
     PKSFILTERFACTORY Factory;
     PFILE_OBJECT FileObject;
+    KMUTEX ControlMutex;
     KMUTEX ProcessingMutex;
 
 
@@ -33,7 +35,7 @@ typedef struct
 
     ULONG *PinInstanceCount;
     PKSPIN * FirstPin;
-    KSPROCESSPIN_INDEXENTRY ProcessPinIndex;
+    PKSPROCESSPIN_INDEXENTRY ProcessPinIndex;
 
 }IKsFilterImpl;
 
@@ -287,43 +289,32 @@ IKsFilter_fnAddProcessPin(
     IKsFilter * iface,
     IN PKSPROCESSPIN ProcessPin)
 {
-    PKSPROCESSPIN *Pins;
+    NTSTATUS Status;
     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl);
 
     /* first acquire processing mutex */
     KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
 
-    /* allocate new pins array */
-    Pins = AllocateItem(NonPagedPool, sizeof(PKSPROCESSPIN) * (This->ProcessPinIndex.Count + 1));
-
-    /* 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
@@ -333,25 +324,39 @@ IKsFilter_fnRemoveProcessPin(
     IN PKSPROCESSPIN ProcessPin)
 {
     ULONG Index;
+    ULONG Count;
+    PKSPROCESSPIN * Pins;
+
     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl);
 
     /* first acquire processing mutex */
     KeWaitForSingleObject(&This->ProcessingMutex, Executive, KernelMode, FALSE, NULL);
 
-    /* iterate through process pin index array and search for the process pin to be removed */
-    for(Index = 0; Index < This->ProcessPinIndex.Count; Index++)
+    /* sanity check */
+    ASSERT(ProcessPin->Pin);
+    ASSERT(ProcessPin->Pin->Id);
+
+    Count = This->ProcessPinIndex[ProcessPin->Pin->Id].Count;
+    Pins =  This->ProcessPinIndex[ProcessPin->Pin->Id].Pins;
+
+    /* search for current process pin */
+    for(Index = 0; Index < Count; Index++)
     {
-        if (This->ProcessPinIndex.Pins[Index] == ProcessPin)
+        if (Pins[Index] == ProcessPin)
         {
-            /* found process pin */
-            if (Index + 1 < This->ProcessPinIndex.Count)
-            {
-                /* erase entry */
-                RtlMoveMemory(&This->ProcessPinIndex.Pins[Index], &This->ProcessPinIndex.Pins[Index+1], This->ProcessPinIndex.Count - Index - 1);
-            }
-            /* decrement process pin count */
-            This->ProcessPinIndex.Count--;
+            RtlMoveMemory(&Pins[Index], &Pins[Index + 1], (Count - (Index + 1)) * sizeof(PKSPROCESSPIN));
+            break;
         }
+
+    }
+
+    /* decrement pin count */
+    This->ProcessPinIndex[ProcessPin->Pin->Id].Count--;
+
+    if (!This->ProcessPinIndex[ProcessPin->Pin->Id].Count)
+    {
+        /* clear entry object bag will delete it */
+       This->ProcessPinIndex[ProcessPin->Pin->Id].Pins = NULL;
     }
 
     /* release process mutex */
@@ -406,8 +411,9 @@ NTAPI
 IKsFilter_fnGetProcessDispatch(
     IKsFilter * iface)
 {
-    UNIMPLEMENTED
-    return NULL;
+    IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(iface, IKsFilterImpl, lpVtbl);
+
+    return This->ProcessPinIndex;
 }
 
 static IKsFilterVtbl vt_IKsFilter =
@@ -529,7 +535,7 @@ KspHandlePropertyInstances(
     KSPIN_CINSTANCES * Instances;
     KSP_PIN * Pin = (KSP_PIN*)Request;
 
-    if (!This->Factory->FilterDescriptor || !This->Factory->FilterDescriptor->PinDescriptorsCount)
+    if (!This->Factory->FilterDescriptor || !This->PinDescriptorCount)
     {
         /* no filter / pin descriptor */
         IoStatus->Status = STATUS_NOT_IMPLEMENTED;
@@ -538,11 +544,11 @@ KspHandlePropertyInstances(
 
     /* ignore custom structs for now */
     ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); 
-    ASSERT(This->Factory->FilterDescriptor->PinDescriptorsCount > Pin->PinId);
+    ASSERT(This->PinDescriptorCount > Pin->PinId);
 
     Instances = (KSPIN_CINSTANCES*)Data;
     /* max instance count */
-    Instances->PossibleCount = This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].InstancesPossible;
+    Instances->PossibleCount = This->PinDescriptorsEx[Pin->PinId].InstancesPossible;
     /* current instance count */
     Instances->CurrentCount = This->PinInstanceCount[Pin->PinId];
 
@@ -561,7 +567,7 @@ KspHandleNecessaryPropertyInstances(
     PULONG Result;
     KSP_PIN * Pin = (KSP_PIN*)Request;
 
-    if (!This->Factory->FilterDescriptor || !This->Factory->FilterDescriptor->PinDescriptorsCount)
+    if (!This->Factory->FilterDescriptor || !This->PinDescriptorCount)
     {
         /* no filter / pin descriptor */
         IoStatus->Status = STATUS_NOT_IMPLEMENTED;
@@ -570,10 +576,10 @@ KspHandleNecessaryPropertyInstances(
 
     /* ignore custom structs for now */
     ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); 
-    ASSERT(This->Factory->FilterDescriptor->PinDescriptorsCount > Pin->PinId);
+    ASSERT(This->PinDescriptorCount > Pin->PinId);
 
     Result = (PULONG)Data;
-    *Result = This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].InstancesNecessary;
+    *Result = This->PinDescriptorsEx[Pin->PinId].InstancesNecessary;
 
     IoStatus->Information = sizeof(ULONG);
     IoStatus->Status = STATUS_SUCCESS;
@@ -599,7 +605,7 @@ KspHandleDataIntersection(
     MultipleItem = (PKSMULTIPLE_ITEM)(Pin + 1);
     DataRange = (PKSDATARANGE)(MultipleItem + 1);
 
-    if (!This->Factory->FilterDescriptor || !This->Factory->FilterDescriptor->PinDescriptorsCount)
+    if (!This->Factory->FilterDescriptor || !This->PinDescriptorCount)
     {
         /* no filter / pin descriptor */
         IoStatus->Status = STATUS_NOT_IMPLEMENTED;
@@ -608,11 +614,11 @@ KspHandleDataIntersection(
 
     /* ignore custom structs for now */
     ASSERT(This->Factory->FilterDescriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX)); 
-    ASSERT(This->Factory->FilterDescriptor->PinDescriptorsCount > Pin->PinId);
+    ASSERT(This->PinDescriptorCount > Pin->PinId);
 
-    if (This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].IntersectHandler == NULL ||
-        This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges == NULL ||
-        This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRangesCount == 0)
+    if (This->PinDescriptorsEx[Pin->PinId].IntersectHandler == NULL ||
+        This->PinDescriptors[Pin->PinId].DataRanges == NULL ||
+        This->PinDescriptors[Pin->PinId].DataRangesCount == 0)
     {
         /* no driver supported intersect handler / no provided data ranges */
         IoStatus->Status = STATUS_NOT_IMPLEMENTED;
@@ -622,16 +628,16 @@ KspHandleDataIntersection(
     for(Index = 0; Index < MultipleItem->Count; Index++)
     {
         /* Call miniport's properitary handler */
-        Status = This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].IntersectHandler(NULL, /* context */
-                                                                                              Irp,
-                                                                                              Pin,
-                                                                                              DataRange,
-                                                                                              (PKSDATAFORMAT)This->Factory->FilterDescriptor->PinDescriptors[Pin->PinId].PinDescriptor.DataRanges,
-                                                                                              DataLength,
-                                                                                              Data,
-                                                                                              &Length);
-
-        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;
@@ -695,6 +701,8 @@ KspPinPropertyHandler(
             UNIMPLEMENTED
             Status = STATUS_UNSUCCESSFUL;
     }
+    DPRINT("KspPinPropertyHandler Pins %lu Request->Id %lu Status %lx\n", This->PinDescriptorCount, Request->Id, Status);
+
 
     return Status;
 }
@@ -736,6 +744,7 @@ IKsFilter_DispatchDeviceIoControl(
     }
 
     /* call property handler supported by ks */
+    KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (KSPROPERTY_ITEM*)This;
     Status = KspPropertyHandler(Irp, 2, FilterPropertySet, NULL, sizeof(KSPROPERTY_ITEM));
 
     if (Status == STATUS_NOT_FOUND)
@@ -755,8 +764,11 @@ IKsFilter_DispatchDeviceIoControl(
         }
     }
 
-    Irp->IoStatus.Status = Status;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    if (Status != STATUS_PENDING)
+    {
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    }
 
     /* done */
     return Status;
@@ -783,75 +795,134 @@ IKsFilter_CreateDescriptors(
     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;
 }
@@ -861,72 +932,24 @@ IKsFilter_CopyFilterDescriptor(
     IKsFilterImpl * This,
     const KSFILTER_DESCRIPTOR* FilterDescriptor)
 {
-    This->Filter.Descriptor = (const KSFILTER_DESCRIPTOR*)AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR));
+    NTSTATUS Status;
+
+    This->Filter.Descriptor = AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR));
     if (!This->Filter.Descriptor)
         return STATUS_INSUFFICIENT_RESOURCES;
 
-    /* copy all fields */
-    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;
 }
 
 
@@ -984,24 +1007,40 @@ IKsFilter_DispatchCreatePin(
     PKSPIN_CONNECT Connect;
     NTSTATUS Status;
 
+    DPRINT("IKsFilter_DispatchCreatePin\n");
+
     /* get the create item */
     CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
 
     /* get the filter object */
     This = (IKsFilterImpl*)CreateItem->Context;
 
+    /* sanity check */
+    ASSERT(This->Header.Type == KsObjectTypeFilter);
+
     /* acquire control mutex */
-    KeWaitForSingleObject(&This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL);
+    KeWaitForSingleObject(This->Header.ControlMutex, Executive, KernelMode, FALSE, NULL);
 
     /* now validate the connect request */
     Status = KsValidateConnectRequest(Irp, This->PinDescriptorCount, This->PinDescriptors, &Connect);
 
+    DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest %lx\n", Status);
+
     if (NT_SUCCESS(Status))
     {
-        if (This->PinInstanceCount[Connect->PinId] < This->Filter.Descriptor->PinDescriptors[Connect->PinId].InstancesPossible)
+        /* sanity check */
+        ASSERT(Connect->PinId < This->PinDescriptorCount);
+
+        DPRINT("IKsFilter_DispatchCreatePin KsValidateConnectRequest PinId %lu CurrentInstanceCount %lu MaxPossible %lu\n", Connect->PinId, 
+               This->PinInstanceCount[Connect->PinId],
+               This->PinDescriptorsEx[Connect->PinId].InstancesPossible);
+
+        if (This->PinInstanceCount[Connect->PinId] < This->PinDescriptorsEx[Connect->PinId].InstancesPossible)
         {
             /* create the pin */
-            Status = KspCreatePin(DeviceObject, Irp, This->Header.KsDevice, This->FilterFactory, (IKsFilter*)&This->lpVtbl, Connect, (KSPIN_DESCRIPTOR_EX*)&This->Filter.Descriptor->PinDescriptors[Connect->PinId]);
+            Status = KspCreatePin(DeviceObject, Irp, This->Header.KsDevice, This->FilterFactory, (IKsFilter*)&This->lpVtbl, Connect, &This->PinDescriptorsEx[Connect->PinId]);
+
+            DPRINT("IKsFilter_DispatchCreatePin  KspCreatePin %lx\n", Status);
 
             if (NT_SUCCESS(Status))
             {
@@ -1013,11 +1052,12 @@ IKsFilter_DispatchCreatePin(
         {
             /* maximum instance count reached, bye-bye */
             Status = STATUS_UNSUCCESSFUL;
+            DPRINT("IKsFilter_DispatchCreatePin  MaxInstance %lu CurInstance %lu %lx\n", This->PinDescriptorsEx[Connect->PinId].InstancesPossible, This->PinInstanceCount[Connect->PinId]);
         }
     }
 
     /* release control mutex */
-    KeReleaseMutex(&This->Header.ControlMutex, FALSE);
+    KeReleaseMutex(This->Header.ControlMutex, FALSE);
 
     if (Status != STATUS_PENDING)
     {
@@ -1025,7 +1065,9 @@ IKsFilter_DispatchCreatePin(
         Irp->IoStatus.Status = Status;
         IoCompleteRequest(Irp, IO_NO_INCREMENT);
     }
+
     /* done */
+    DPRINT("IKsFilter_DispatchCreatePin Result %lx\n", Status);
     return Status;
 }
 
@@ -1118,40 +1160,52 @@ KspCreateFilter(
     }
 
     /* allocate filter instance */
-    This = AllocateItem(NonPagedPool, sizeof(IKsFilterFactory));
+    This = AllocateItem(NonPagedPool, sizeof(IKsFilterImpl));
     if (!This)
+    {
+        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;
@@ -1164,9 +1218,6 @@ KspCreateFilter(
     RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_TopologyNode);
 
 
-    KsDevice = (IKsDevice*)&DeviceExtension->DeviceHeader->lpVtblIKsDevice;
-    KsDevice->lpVtbl->InitializeObjectBag(KsDevice, (PKSIOBJECT_BAG)This->Filter.Bag, NULL);
-
     /* initialize filter instance */
     This->ref = 1;
     This->lpVtbl = &vt_IKsFilter;
@@ -1181,7 +1232,8 @@ KspCreateFilter(
     This->Header.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
     This->Header.Parent.KsFilterFactory = iface->lpVtbl->GetStruct(iface);
     This->Header.Type = KsObjectTypeFilter;
-    KeInitializeMutex(&This->Header.ControlMutex, 0);
+    This->Header.ControlMutex = &This->ControlMutex;
+    KeInitializeMutex(This->Header.ControlMutex, 0);
     InitializeListHead(&This->Header.EventList);
     KeInitializeSpinLock(&This->Header.EventListLock);
 
@@ -1192,6 +1244,7 @@ KspCreateFilter(
         /* what can go wrong, goes wrong */
         FreeItem(This);
         FreeItem(CreateItem);
+        DPRINT("IKsFilter_CreateDescriptors failed with %lx\n", Status);
         return Status;
     }
 
@@ -1202,6 +1255,9 @@ KspCreateFilter(
         if (Factory->FilterDescriptor->Dispatch->Create)
         {
             /* now let driver initialize the filter instance */
+
+            ASSERT(This->Header.KsDevice);
+            ASSERT(This->Header.KsDevice->Started);
             Status = Factory->FilterDescriptor->Dispatch->Create(&This->Filter, Irp);
 
             if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
@@ -1236,6 +1292,7 @@ KspCreateFilter(
     IKsFilter_AttachFilterToFilterFactory(This, This->Header.Parent.KsFilterFactory);
 
     /* completed initialization */
+    DPRINT("KspCreateFilter done %lx\n", Status);
     return Status;
 }
 
@@ -1355,77 +1412,68 @@ KsFilterCreatePinFactory (
     OUT PULONG PinID)
 {
     ULONG Count;
-    ULONG *PinInstanceCount;
-    KSPIN_DESCRIPTOR_EX * PinDescriptorsEx;
-    KSPIN_DESCRIPTOR * PinDescriptors;
-    PKSPIN *FirstPin;
+    NTSTATUS Status;
     IKsFilterImpl * This = (IKsFilterImpl*)CONTAINING_RECORD(Filter, IKsFilterImpl, Filter);
 
-    /* calculate existing count */
+    DPRINT("KsFilterCreatePinFactory\n");
+
+    /* calculate new count */
     Count = This->PinDescriptorCount + 1;
 
-    /* allocate pin descriptors array */
-    PinDescriptorsEx = AllocateItem(NonPagedPool, max(This->Filter.Descriptor->PinDescriptorSize, sizeof(KSPIN_DESCRIPTOR_EX)) * Count);
-    if (!PinDescriptorsEx)
-        return STATUS_INSUFFICIENT_RESOURCES;
+    /* sanity check */
+    ASSERT(This->Filter.Descriptor->PinDescriptorSize == sizeof(KSPIN_DESCRIPTOR_EX));
 
-    /* allocate pin instance count array */
-    PinInstanceCount = AllocateItem(NonPagedPool, sizeof(ULONG) * Count);
-    if (!PinInstanceCount)
+    /* allocate pin descriptors ex array */
+    Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinDescriptorsEx, Count * sizeof(KSPIN_DESCRIPTOR_EX), This->PinDescriptorCount * sizeof(KSPIN_DESCRIPTOR_EX), 0);
+    if (!NT_SUCCESS(Status))
     {
-        /* not enough memory */
-        FreeItem(PinDescriptorsEx);
-        return STATUS_INSUFFICIENT_RESOURCES;
+        /* failed */
+        DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
+        return Status;
     }
 
-    /* allocate pin descriptor array for pin property handling */
-    PinDescriptors = AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * Count);
-    if (!PinDescriptors)
+    /* allocate pin descriptors array */
+    Status = _KsEdit(This->Filter.Bag, (PVOID*)&This->PinDescriptors, Count * sizeof(KSPIN_DESCRIPTOR), This->PinDescriptorCount * sizeof(KSPIN_DESCRIPTOR), 0);
+    if (!NT_SUCCESS(Status))
     {
-        /* not enough memory */
-        FreeItem(PinDescriptorsEx);
-        FreeItem(PinInstanceCount);
-        return STATUS_INSUFFICIENT_RESOURCES;
+        /* failed */
+        DPRINT("KsFilterCreatePinFactory _KsEdit failed with %lx\n", Status);
+        return Status;
     }
 
-    /* allocate 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;
@@ -1433,6 +1481,8 @@ KsFilterCreatePinFactory (
     /* increment pin descriptor count */
     This->PinDescriptorCount++;
 
+
+    DPRINT("KsFilterCreatePinFactory done\n");
     return STATUS_SUCCESS;
 
 }
@@ -1522,6 +1572,8 @@ KsGetFilterFromIrp(
     PIO_STACK_LOCATION IoStack;
     PKSIOBJECT_HEADER ObjectHeader;
 
+    DPRINT("KsGetFilterFromIrp\n");
+
     /* get current irp stack location */
     IoStack = IoGetCurrentIrpStackLocation(Irp);
 
index dc48f3c..18b2147 100644 (file)
@@ -21,6 +21,8 @@ typedef struct
     PFNKSFILTERFACTORYPOWER WakeCallback;
 
     LIST_ENTRY SymbolicLinkList;
+    KMUTEX ControlMutex;
+
 }IKsFilterFactoryImpl;
 
 VOID
@@ -41,6 +43,7 @@ IKsFilterFactory_Create(
     IN PIRP Irp)
 {
     PKSOBJECT_CREATE_ITEM CreateItem;
+    IKsFilterFactoryImpl * Factory;
     IKsFilterFactory * iface;
     NTSTATUS Status;
 
@@ -53,7 +56,10 @@ IKsFilterFactory_Create(
     }
 
     /* get filter factory interface */
-    iface = (IKsFilterFactory*)CONTAINING_RECORD(CreateItem->Context, IKsFilterFactoryImpl, FilterFactory);
+    Factory = (IKsFilterFactoryImpl*)CONTAINING_RECORD(CreateItem->Context, IKsFilterFactoryImpl, FilterFactory);
+
+    /* get interface */
+    iface = (IKsFilterFactory*)&Factory->lpVtbl;
 
     /* create a filter instance */
     Status = KspCreateFilter(DeviceObject, Irp, iface);
@@ -221,17 +227,16 @@ IKsFilterFactory_fnInitialize(
     This->Header.Parent.KsDevice = &DeviceExtension->DeviceHeader->KsDevice;
     This->DeviceHeader = DeviceExtension->DeviceHeader;
 
+    /* initialize filter factory control mutex */
+    This->Header.ControlMutex = &This->ControlMutex;
+    KeInitializeMutex(This->Header.ControlMutex, 0);
+
     /* unused fields */
-    KeInitializeMutex(&This->Header.ControlMutex, 0);
     InitializeListHead(&This->Header.EventList);
     KeInitializeSpinLock(&This->Header.EventListLock);
 
-
     InitializeListHead(&This->SymbolicLinkList);
 
-    /* initialize filter factory control mutex */
-    KeInitializeMutex(&This->Header.ControlMutex, 0);
-
     /* does the device use a reference string */
     if (RefString || !Descriptor->ReferenceGuid)
     {
@@ -253,6 +258,8 @@ IKsFilterFactory_fnInitialize(
         FreeString = TRUE;
     }
 
+    DPRINT("IKsFilterFactory_fnInitialize CategoriesCount %u ReferenceString '%S'\n", Descriptor->CategoriesCount,ReferenceString.Buffer);
+
     /* now register the device interface */
     Status = KspRegisterDeviceInterfaces(DeviceExtension->DeviceHeader->KsDevice.PhysicalDeviceObject,
                                          Descriptor->CategoriesCount,
@@ -365,6 +372,10 @@ KspCreateFilterFactory(
     }
 
     /* return result */
+    DPRINT("KsCreateFilterFactory %x\n", Status);
+    /* sanity check */
+    ASSERT(Status == STATUS_SUCCESS);
+
     return Status;
 }
 
index 4bdc04c..d5c7588 100644 (file)
@@ -58,7 +58,7 @@ typedef struct
 {
     KSOBJECTTYPE Type;
     PKSDEVICE KsDevice;
-    KMUTEX ControlMutex;
+    PRKMUTEX ControlMutex;
     LIST_ENTRY EventList;
     KSPIN_LOCK EventListLock;
     union
index 431fb26..a4cc63b 100644 (file)
 
 typedef struct _KSISTREAM_POINTER
 {
-    KSSTREAM_POINTER StreamPointer;
     PFNKSSTREAMPOINTER Callback;
     PIRP Irp;
     KTIMER Timer;
     KDPC TimerDpc;
     struct _KSISTREAM_POINTER *Next;
-
+    PKSPIN Pin;
+    KSSTREAM_POINTER StreamPointer;
 }KSISTREAM_POINTER, *PKSISTREAM_POINTER;
 
 typedef struct
@@ -29,8 +29,9 @@ typedef struct
     LIST_ENTRY Entry;
 
     IKsPinVtbl *lpVtbl;
-
     LONG ref;
+
+    IKsFilter * Filter;
     KMUTEX ProcessingMutex;
     PFILE_OBJECT FileObject;
 
@@ -50,8 +51,363 @@ typedef struct
     PFNKSPINFRAMERETURN  FrameReturn;
     PFNKSPINIRPCOMPLETION  IrpCompletion;
 
+    KSCLOCK_FUNCTIONTABLE ClockTable;
+    PFILE_OBJECT ClockFileObject;
+    IKsReferenceClockVtbl * lpVtblReferenceClock;
+    PKSDEFAULTCLOCK DefaultClock;
+
+    PKSWORKER PinWorker;
+    WORK_QUEUE_ITEM PinWorkQueueItem;
+    IRP * Irp;
+    KEVENT FrameComplete;
+
+
 }IKsPinImpl;
 
+NTSTATUS NTAPI IKsPin_PinStatePropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
+NTSTATUS NTAPI IKsPin_PinDataFormatPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
+NTSTATUS NTAPI IKsPin_PinAllocatorFramingPropertyHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
+NTSTATUS NTAPI IKsPin_PinStreamAllocator(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
+NTSTATUS NTAPI IKsPin_PinMasterClock(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
+NTSTATUS NTAPI IKsPin_PinPipeId(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
+
+
+
+DEFINE_KSPROPERTY_CONNECTIONSET(PinConnectionSet, IKsPin_PinStatePropertyHandler, IKsPin_PinDataFormatPropertyHandler, IKsPin_PinAllocatorFramingPropertyHandler);
+DEFINE_KSPROPERTY_STREAMSET(PinStreamSet, IKsPin_PinStreamAllocator, IKsPin_PinMasterClock, IKsPin_PinPipeId);
+
+//TODO
+// KSPROPSETID_Connection
+//    KSPROPERTY_CONNECTION_ACQUIREORDERING
+// KSPROPSETID_StreamInterface
+//     KSPROPERTY_STREAMINTERFACE_HEADERSIZE
+
+KSPROPERTY_SET PinPropertySet[] =
+{
+    {
+        &KSPROPSETID_Connection,
+        sizeof(PinConnectionSet) / sizeof(KSPROPERTY_ITEM),
+        (const KSPROPERTY_ITEM*)&PinConnectionSet,
+        0,
+        NULL
+    },
+    {
+        &KSPROPSETID_Stream,
+        sizeof(PinStreamSet) / sizeof(KSPROPERTY_ITEM),
+        (const KSPROPERTY_ITEM*)&PinStreamSet,
+        0,
+        NULL
+    }
+};
+
+const GUID KSPROPSETID_Connection              = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
+const GUID KSPROPSETID_Stream                  = {0x65aaba60L, 0x98ae, 0x11cf, {0xa1, 0x0d, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4}};
+const GUID KSPROPSETID_Clock                   = {0xDF12A4C0L, 0xAC17, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
+
+NTSTATUS
+NTAPI
+IKsPin_PinStreamAllocator(
+    IN PIRP Irp,
+    IN PKSIDENTIFIER Request,
+    IN OUT PVOID Data)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+IKsPin_PinMasterClock(
+    IN PIRP Irp,
+    IN PKSIDENTIFIER Request,
+    IN OUT PVOID Data)
+{
+    PIO_STACK_LOCATION IoStack;
+    PKSIOBJECT_HEADER ObjectHeader;
+    IKsPinImpl * This;
+    NTSTATUS Status = STATUS_SUCCESS;
+    PHANDLE Handle;
+    PFILE_OBJECT FileObject;
+    KPROCESSOR_MODE Mode;
+    KSPROPERTY Property;
+    ULONG BytesReturned;
+
+    /* get current irp stack */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    DPRINT("IKsPin_PinMasterClock\n");
+
+    /* sanity check */
+    ASSERT(IoStack->FileObject);
+    ASSERT(IoStack->FileObject->FsContext2);
+
+    /* get the object header */
+    ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
+
+    /* locate ks pin implemention from KSPIN offset */
+    This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
+
+    /* acquire control mutex */
+    KeWaitForSingleObject(This->BasicHeader.ControlMutex, Executive, KernelMode, FALSE, NULL);
+
+    Handle = (PHANDLE)Data;
+
+    if (Request->Flags & KSPROPERTY_TYPE_GET)
+    {
+        if (This->Pin.Descriptor->PinDescriptor.Communication != KSPIN_COMMUNICATION_NONE &&
+            This->Pin.Descriptor->Dispatch &&
+            (This->Pin.Descriptor->Flags & KSPIN_FLAG_IMPLEMENT_CLOCK))
+        {
+            *Handle = NULL;
+            Status = STATUS_SUCCESS;
+        }
+        else
+        {
+            /* no clock available */
+            Status = STATUS_UNSUCCESSFUL;
+        }
+    }
+    else if (Request->Flags & KSPROPERTY_TYPE_SET)
+    {
+        if (This->Pin.ClientState != KSSTATE_STOP)
+        {
+            /* can only set in stopped state */
+            Status = STATUS_INVALID_DEVICE_STATE;
+        }
+        else
+        {
+            if (*Handle)
+            {
+                Mode = ExGetPreviousMode();
+
+                Status = ObReferenceObjectByHandle(*Handle, SYNCHRONIZE | DIRECTORY_QUERY, IoFileObjectType, Mode, (PVOID*)&FileObject, NULL);
+
+                DPRINT("IKsPin_PinMasterClock ObReferenceObjectByHandle %lx\n", Status);
+                if (NT_SUCCESS(Status))
+                {
+                    Property.Set = KSPROPSETID_Clock;
+                    Property.Id = KSPROPERTY_CLOCK_FUNCTIONTABLE;
+                    Property.Flags = KSPROPERTY_TYPE_GET;
+
+                    Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), &This->ClockTable, sizeof(KSCLOCK_FUNCTIONTABLE), &BytesReturned);
+
+                    DPRINT("IKsPin_PinMasterClock KSPROPERTY_CLOCK_FUNCTIONTABLE %lx\n", Status);
+
+                    if (NT_SUCCESS(Status))
+                    {
+                        This->ClockFileObject = FileObject;
+                    }
+                    else
+                    {
+                        ObDereferenceObject(FileObject);
+                    }
+                }
+            }
+            else
+            {
+                /* zeroing clock handle */
+                RtlZeroMemory(&This->ClockTable, sizeof(KSCLOCK_FUNCTIONTABLE));
+                Status = STATUS_SUCCESS;
+                if (This->ClockFileObject)
+                {
+                    FileObject = This->ClockFileObject;
+                    This->ClockFileObject = NULL;
+
+                    ObDereferenceObject(This->ClockFileObject);
+                }
+            }
+        }
+    }
+
+    /* release processing mutex */
+    KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE);
+
+    DPRINT("IKsPin_PinStatePropertyHandler Status %lx\n", Status);
+    return Status;
+}
+
+
+
+NTSTATUS
+NTAPI
+IKsPin_PinPipeId(
+    IN PIRP Irp,
+    IN PKSIDENTIFIER Request,
+    IN OUT PVOID Data)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+
+NTSTATUS
+NTAPI
+IKsPin_PinStatePropertyHandler(
+    IN PIRP Irp,
+    IN PKSIDENTIFIER Request,
+    IN OUT PVOID Data)
+{
+    PIO_STACK_LOCATION IoStack;
+    PKSIOBJECT_HEADER ObjectHeader;
+    IKsPinImpl * This;
+    NTSTATUS Status = STATUS_SUCCESS;
+    KSSTATE OldState;
+    PKSSTATE NewState;
+
+    /* get current irp stack */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    DPRINT("IKsPin_PinStatePropertyHandler\n");
+
+    /* sanity check */
+    ASSERT(IoStack->FileObject);
+    ASSERT(IoStack->FileObject->FsContext2);
+
+    /* get the object header */
+    ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
+
+    /* locate ks pin implemention from KSPIN offset */
+    This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
+
+    /* acquire control mutex */
+    KeWaitForSingleObject(This->BasicHeader.ControlMutex, Executive, KernelMode, FALSE, NULL);
+
+    /* grab state */
+    NewState = (PKSSTATE)Data;
+
+    if (Request->Flags & KSPROPERTY_TYPE_GET)
+    {
+        *NewState = This->Pin.DeviceState;
+        Irp->IoStatus.Information = sizeof(KSSTATE);
+    }
+    else if (Request->Flags & KSPROPERTY_TYPE_SET)
+    {
+        if (This->Pin.Descriptor->Dispatch->SetDeviceState)
+        {
+            /* backup old state */
+            OldState = This->Pin.ClientState;
+
+            /* set new state */
+            This->Pin.ClientState  = *NewState;
+            This->Pin.DeviceState = *NewState;
+
+            /* check if it supported */
+            Status = This->Pin.Descriptor->Dispatch->SetDeviceState(&This->Pin, *NewState, OldState);
+
+            DPRINT("IKsPin_PinStatePropertyHandler NewState %lu Result %lx\n", *NewState, Status);
+
+            if (!NT_SUCCESS(Status))
+            {
+                /* revert to old state */
+                This->Pin.ClientState = OldState;
+                This->Pin.DeviceState = OldState;
+                DbgBreakPoint();
+            }
+            else
+            {
+                /* update device state */
+                This->Pin.DeviceState = *NewState;
+            }
+        }
+        else
+        {
+            /* just set new state */
+            This->Pin.DeviceState = *NewState;
+            This->Pin.ClientState = *NewState;
+        }
+    }
+
+    /* release processing mutex */
+    KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE);
+
+    DPRINT("IKsPin_PinStatePropertyHandler Status %lx\n", Status);
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+IKsPin_PinAllocatorFramingPropertyHandler(
+    IN PIRP Irp,
+    IN PKSIDENTIFIER Request,
+    IN OUT PVOID Data)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+NTAPI
+IKsPin_PinDataFormatPropertyHandler(
+    IN PIRP Irp,
+    IN PKSPROPERTY Request,
+    IN OUT PVOID Data)
+{
+    PIO_STACK_LOCATION IoStack;
+    PKSIOBJECT_HEADER ObjectHeader;
+    IKsPinImpl * This;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    /* get current irp stack */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    DPRINT("IKsPin_PinDataFormatPropertyHandler\n");
+
+    /* sanity check */
+    ASSERT(IoStack->FileObject);
+    ASSERT(IoStack->FileObject->FsContext2);
+
+    /* get the object header */
+    ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
+
+    /* locate ks pin implemention from KSPIN offset */
+    This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
+
+    /* acquire control mutex */
+    KeWaitForSingleObject(This->BasicHeader.ControlMutex, Executive, KernelMode, FALSE, NULL);
+
+    if (Request->Flags & KSPROPERTY_TYPE_GET)
+    {
+        if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < This->Pin.ConnectionFormat->FormatSize)
+        {
+            /* buffer too small */
+            Irp->IoStatus.Information = This->Pin.ConnectionFormat->FormatSize;
+            Status = STATUS_BUFFER_TOO_SMALL;
+        }
+        else
+        {
+            /* copy format */
+            RtlMoveMemory(Data, This->Pin.ConnectionFormat, This->Pin.ConnectionFormat->FormatSize);
+        }
+    }
+    else if (Request->Flags & KSPROPERTY_TYPE_SET)
+    {
+        /* set format */
+        if (This->Pin.Descriptor->Flags & KSPIN_FLAG_FIXED_FORMAT)
+        {
+            /* format cannot be changed */
+            Status = STATUS_INVALID_DEVICE_REQUEST;
+        }
+        else
+        {
+            /* FIXME check if the format is supported */
+            Status = _KsEdit(This->Pin.Bag, (PVOID*)&This->Pin.ConnectionFormat, IoStack->Parameters.DeviceIoControl.OutputBufferLength, This->Pin.ConnectionFormat->FormatSize, 0);
+
+            if (NT_SUCCESS(Status))
+            {
+                /* store new format */
+                RtlMoveMemory(This->Pin.ConnectionFormat, Data, IoStack->Parameters.DeviceIoControl.OutputBufferLength);
+            }
+        }
+    }
+
+    /* release processing mutex */
+    KeReleaseMutex(This->BasicHeader.ControlMutex, FALSE);
+
+    DPRINT("IKsPin_PinDataFormatPropertyHandler Status %lx\n", Status);
+
+    return Status;
+}
+
 NTSTATUS
 NTAPI
 IKsPin_fnQueryInterface(
@@ -67,6 +423,7 @@ IKsPin_fnQueryInterface(
         _InterlockedIncrement(&This->ref);
         return STATUS_SUCCESS;
     }
+    DbgBreakPoint();
     return STATUS_UNSUCCESSFUL;
 }
 
@@ -270,6 +627,209 @@ static IKsPinVtbl vt_IKsPin =
 
 //==============================================================
 
+NTSTATUS
+NTAPI
+IKsReferenceClock_fnQueryInterface(
+    IKsReferenceClock * iface,
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
+
+    return IKsPin_fnQueryInterface((IKsPin*)&This->lpVtbl, refiid, Output);
+}
+
+ULONG
+NTAPI
+IKsReferenceClock_fnAddRef(
+    IKsReferenceClock * iface)
+{
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
+
+    return IKsPin_fnAddRef((IKsPin*)&This->lpVtbl);
+}
+
+ULONG
+NTAPI
+IKsReferenceClock_fnRelease(
+    IKsReferenceClock * iface)
+{
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
+
+    return IKsPin_fnRelease((IKsPin*)&This->lpVtbl);
+}
+
+LONGLONG
+NTAPI
+IKsReferenceClock_fnGetTime(
+    IKsReferenceClock * iface)
+{
+    LONGLONG Result;
+
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
+
+    if (!This->ClockFileObject || !This->ClockTable.GetTime)
+    {
+        Result = 0;
+    }
+    else
+    {
+        Result = This->ClockTable.GetTime(This->ClockFileObject);
+    }
+
+    return Result;
+}
+
+LONGLONG
+NTAPI
+IKsReferenceClock_fnGetPhysicalTime(
+    IKsReferenceClock * iface)
+{
+    LONGLONG Result;
+
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
+
+    if (!This->ClockFileObject || !This->ClockTable.GetPhysicalTime)
+    {
+        Result = 0;
+    }
+    else
+    {
+        Result = This->ClockTable.GetPhysicalTime(This->ClockFileObject);
+    }
+
+    return Result;
+}
+
+
+LONGLONG
+NTAPI
+IKsReferenceClock_fnGetCorrelatedTime(
+    IKsReferenceClock * iface,
+    OUT PLONGLONG SystemTime)
+{
+    LONGLONG Result;
+
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
+
+    if (!This->ClockFileObject || !This->ClockTable.GetCorrelatedTime)
+    {
+        Result = 0;
+    }
+    else
+    {
+        Result = This->ClockTable.GetCorrelatedTime(This->ClockFileObject, SystemTime);
+    }
+
+    return Result;
+}
+
+
+LONGLONG
+NTAPI
+IKsReferenceClock_fnGetCorrelatedPhysicalTime(
+    IKsReferenceClock * iface,
+    OUT PLONGLONG SystemTime)
+{
+    LONGLONG Result;
+
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
+
+    if (!This->ClockFileObject || !This->ClockTable.GetCorrelatedPhysicalTime)
+    {
+        Result = 0;
+    }
+    else
+    {
+        Result = This->ClockTable.GetCorrelatedPhysicalTime(This->ClockFileObject, SystemTime);
+    }
+
+    return Result;
+}
+
+NTSTATUS
+NTAPI
+IKsReferenceClock_fnGetResolution(
+    IKsReferenceClock * iface,
+    OUT PKSRESOLUTION Resolution)
+{
+    KSPROPERTY Property;
+    ULONG BytesReturned;
+
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
+
+    DPRINT1("IKsReferenceClock_fnGetResolution\n");
+
+    if (!This->ClockFileObject)
+    {
+        Resolution->Error = 0;
+        Resolution->Granularity = 1;
+        DPRINT1("IKsReferenceClock_fnGetResolution Using HACK\n");
+        return STATUS_SUCCESS;
+    }
+
+
+    if (!This->ClockFileObject)
+        return STATUS_DEVICE_NOT_READY;
+
+
+    Property.Set = KSPROPSETID_Clock;
+    Property.Id = KSPROPERTY_CLOCK_RESOLUTION;
+    Property.Flags = KSPROPERTY_TYPE_GET;
+
+    return KsSynchronousIoControlDevice(This->ClockFileObject, KernelMode, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), Resolution, sizeof(KSRESOLUTION), &BytesReturned);
+
+}
+
+NTSTATUS
+NTAPI
+IKsReferenceClock_fnGetState(
+    IKsReferenceClock * iface,
+     OUT PKSSTATE State)
+{
+    KSPROPERTY Property;
+    ULONG BytesReturned;
+
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(iface, IKsPinImpl, lpVtblReferenceClock);
+
+    DPRINT1("IKsReferenceClock_fnGetState\n");
+
+    if (!This->ClockFileObject)
+    {
+        *State = This->Pin.ClientState;
+        DPRINT1("IKsReferenceClock_fnGetState Using HACK\n");
+        return STATUS_SUCCESS;
+    }
+
+
+    if (!This->ClockFileObject)
+        return STATUS_DEVICE_NOT_READY;
+
+
+    Property.Set = KSPROPSETID_Clock;
+    Property.Id = KSPROPERTY_CLOCK_RESOLUTION;
+    Property.Flags = KSPROPERTY_TYPE_GET;
+
+    return KsSynchronousIoControlDevice(This->ClockFileObject, KernelMode, IOCTL_KS_PROPERTY, &Property, sizeof(KSPROPERTY), State, sizeof(KSSTATE), &BytesReturned);
+}
+
+static IKsReferenceClockVtbl vt_ReferenceClock =
+{
+    IKsReferenceClock_fnQueryInterface,
+    IKsReferenceClock_fnAddRef,
+    IKsReferenceClock_fnRelease,
+    IKsReferenceClock_fnGetTime,
+    IKsReferenceClock_fnGetPhysicalTime,
+    IKsReferenceClock_fnGetCorrelatedTime,
+    IKsReferenceClock_fnGetCorrelatedPhysicalTime,
+    IKsReferenceClock_fnGetResolution,
+    IKsReferenceClock_fnGetState
+};
+
+
+//==============================================================
+
+
 /*
     @implemented
 */
@@ -339,6 +899,8 @@ KsPinAttemptProcessing(
     IN PKSPIN  Pin,
     IN BOOLEAN  Asynchronous)
 {
+    DPRINT("KsPinAttemptProcessing\n");
+    DbgBreakPoint();
     UNIMPLEMENTED
 }
 
@@ -447,7 +1009,7 @@ KsPinGetParentFilter(
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 NTSTATUS
 NTAPI
@@ -455,8 +1017,22 @@ NTAPI
     IN PKSPIN  Pin,
     OUT PIKSREFERENCECLOCK*  Interface)
 {
-    UNIMPLEMENTED
-    return STATUS_UNSUCCESSFUL;
+    NTSTATUS Status = STATUS_DEVICE_NOT_READY;
+    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
+
+    if (This->ClockFileObject)
+    {
+        /* clock is available */
+        *Interface = (PIKSREFERENCECLOCK)&This->lpVtblReferenceClock;
+        Status = STATUS_SUCCESS;
+    }
+//HACK
+        *Interface = (PIKSREFERENCECLOCK)&This->lpVtblReferenceClock;
+        Status = STATUS_SUCCESS;
+
+    DPRINT("KsPinGetReferenceClockInterface Pin %p Interface %p Status %x\n", Pin, Interface, Status);
+
+    return Status;
 }
 
 /*
@@ -545,13 +1121,26 @@ KsGetPinFromIrp(
     IN PIRP Irp)
 {
     PKSIOBJECT_HEADER ObjectHeader;
+    PKSPIN Pin;
+    PKSBASIC_HEADER Header;
     PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(Irp);
 
+    DPRINT("KsGetPinFromIrp\n");
+
     /* get object header */
     ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
-    /* return object type */
-    return (PKSPIN)ObjectHeader->ObjectType;
 
+    if (!ObjectHeader)
+        return NULL;
+
+    Pin = (PKSPIN)ObjectHeader->ObjectType;
+    Header = (PKSBASIC_HEADER)((ULONG_PTR)Pin - sizeof(KSBASIC_HEADER));
+
+    /* sanity check */
+    ASSERT(Header->Type == KsObjectTypePin);
+
+    /* return object type */
+    return Pin;
 }
 
 
@@ -623,8 +1212,33 @@ KsPinGetLeadingEdgeStreamPointer(
     IN PKSPIN Pin,
     IN KSSTREAM_POINTER_STATE State)
 {
-    UNIMPLEMENTED
-    return NULL;
+    IKsPinImpl * This;
+
+    This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
+
+    DPRINT("KsPinGetLeadingEdgeStreamPointer Pin %p State %x Count %lu Remaining %lu\n", Pin, State, 
+           This->LeadingEdgeStreamPointer->StreamPointer.Offset->Count,
+           This->LeadingEdgeStreamPointer->StreamPointer.Offset->Remaining);
+
+    /* sanity check */
+    ASSERT(This->LeadingEdgeStreamPointer);
+    ASSERT(State == KSSTREAM_POINTER_STATE_LOCKED);
+
+    if (State == KSSTREAM_POINTER_STATE_LOCKED)
+    {
+        /* do we have an irp packet */
+        if (!This->Irp)
+        {
+            /* run out of packets */
+            return NULL;
+        }
+
+        if (!This->LeadingEdgeStreamPointer->StreamPointer.Offset->Remaining)
+            return NULL;
+     }
+     DPRINT("LeadingEdge %p\n", &This->LeadingEdgeStreamPointer->StreamPointer);
+     This->LeadingEdgeStreamPointer->Pin = &This->Pin;
+    return &This->LeadingEdgeStreamPointer->StreamPointer;
 }
 
 /*
@@ -679,6 +1293,8 @@ KsStreamPointerUnlock(
     IN BOOLEAN Eject)
 {
     UNIMPLEMENTED
+    DPRINT("KsStreamPointerUnlock Eject %lu\n", Eject);
+    DbgBreakPoint();
 }
 
 /*
@@ -693,6 +1309,8 @@ KsStreamPointerAdvanceOffsetsAndUnlock(
     IN ULONG OutUsed,
     IN BOOLEAN Eject)
 {
+    DPRINT("KsStreamPointerAdvanceOffsets InUsed %lu OutUsed %lu Eject %lu\n", InUsed, OutUsed, Eject);
+    DbgBreakPoint();
     UNIMPLEMENTED
 }
 
@@ -707,7 +1325,9 @@ KsStreamPointerDelete(
 {
     IKsPinImpl * This;
     PKSISTREAM_POINTER Cur, Last;
-    PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)StreamPointer;
+    PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
+
+    DPRINT("KsStreamPointerDelete %p\n", Pointer);
 
     This = (IKsPinImpl*)CONTAINING_RECORD(Pointer->StreamPointer.Pin, IKsPinImpl, Pin);
 
@@ -743,7 +1363,7 @@ KsStreamPointerDelete(
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 KSDDKAPI
 NTSTATUS
@@ -754,12 +1374,57 @@ KsStreamPointerClone(
     IN ULONG ContextSize,
     OUT PKSSTREAM_POINTER* CloneStreamPointer)
 {
-    UNIMPLEMENTED
-    return STATUS_NOT_IMPLEMENTED;
+    IKsPinImpl * This;
+    PKSISTREAM_POINTER CurFrame;
+    PKSISTREAM_POINTER NewFrame;
+    ULONG RefCount;
+    ULONG Size;
+
+    DPRINT("KsStreamPointerClone StreamPointer %p CancelCallback %p ContextSize %p CloneStreamPointer %p\n", StreamPointer, CancelCallback, ContextSize, CloneStreamPointer);
+
+    /* get stream pointer */
+    CurFrame = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
+
+    /* calculate context size */
+    Size = sizeof(KSISTREAM_POINTER) + ContextSize;
+
+    /* allocate new stream pointer */
+    NewFrame = (PKSISTREAM_POINTER)ExAllocatePool(NonPagedPool, Size);
+
+    if (!NewFrame)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    /* get current irp stack location */
+    RefCount = (ULONG)CurFrame->Irp->Tail.Overlay.DriverContext[0];
+
+    /* increment reference count */
+    RefCount++;
+    CurFrame->Irp->Tail.Overlay.DriverContext[0] = (PVOID)RefCount;
+
+    /* copy stream pointer */
+    RtlMoveMemory(NewFrame, CurFrame, sizeof(KSISTREAM_POINTER));
+
+    if (ContextSize)
+        NewFrame->StreamPointer.Context = (NewFrame + 1);
+
+    /* locate pin */
+    This = (IKsPinImpl*)CONTAINING_RECORD(CurFrame->Pin, IKsPinImpl, Pin);
+
+    NewFrame->StreamPointer.Pin = &This->Pin;
+
+    ASSERT(NewFrame->StreamPointer.Pin);
+    ASSERT(NewFrame->StreamPointer.Context);
+    ASSERT(NewFrame->StreamPointer.Offset);
+    ASSERT(NewFrame->StreamPointer.StreamHeader);
+
+    /* store result */
+    *CloneStreamPointer = &NewFrame->StreamPointer;
+
+    return STATUS_SUCCESS;
 }
 
 /*
-    @unimplemented
+    @implemented
 */
 KSDDKAPI
 NTSTATUS
@@ -770,8 +1435,58 @@ KsStreamPointerAdvanceOffsets(
     IN ULONG OutUsed,
     IN BOOLEAN Eject)
 {
-    UNIMPLEMENTED
-    return STATUS_NOT_IMPLEMENTED;
+    PKSISTREAM_POINTER CurFrame;
+    IKsPinImpl * This;
+
+    DPRINT("KsStreamPointerAdvanceOffsets      InUsed %lu OutUsed %lu Eject %lu\n", InUsed, OutUsed, Eject);
+
+    /* get stream pointer */
+    CurFrame = (PKSISTREAM_POINTER)CONTAINING_RECORD(StreamPointer, KSISTREAM_POINTER, StreamPointer);
+
+    CurFrame->StreamPointer.OffsetIn.Remaining -= InUsed;
+    CurFrame->StreamPointer.OffsetOut.Remaining -= OutUsed;
+    CurFrame->StreamPointer.OffsetIn.Count -= InUsed;
+    CurFrame->StreamPointer.OffsetOut.Count -= OutUsed;
+    CurFrame->StreamPointer.OffsetIn.Data = (PVOID)((ULONG_PTR)CurFrame->StreamPointer.OffsetIn.Data + InUsed);
+    CurFrame->StreamPointer.OffsetOut.Data = (PVOID)((ULONG_PTR)CurFrame->StreamPointer.OffsetOut.Data + OutUsed);
+
+    if (!CurFrame->StreamPointer.OffsetIn.Remaining)
+        CurFrame->StreamPointer.OffsetIn.Data = NULL;
+
+    if (!CurFrame->StreamPointer.OffsetOut.Remaining)
+        CurFrame->StreamPointer.OffsetOut.Data = NULL;
+
+    /* locate pin */
+    This = (IKsPinImpl*)CONTAINING_RECORD(CurFrame->Pin, IKsPinImpl, Pin);
+
+    if (This->Pin.Descriptor->PinDescriptor.DataFlow == KSPIN_DATAFLOW_IN)
+    {
+        if (CurFrame->StreamPointer.OffsetIn.Remaining == 0)
+        {
+            /* get next mapping */
+            This->Irp = KsRemoveIrpFromCancelableQueue(&This->IrpList, &This->IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem);
+            if (!This->Irp)
+                return STATUS_DEVICE_NOT_READY;
+
+            /* FIXME handle me */
+            ASSERT(0);
+        }
+    }
+    else
+    {
+        if (CurFrame->StreamPointer.OffsetOut.Remaining == 0)
+        {
+            /* get next mapping */
+            This->Irp = KsRemoveIrpFromCancelableQueue(&This->IrpList, &This->IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem);
+            if (!This->Irp)
+                return STATUS_DEVICE_NOT_READY;
+
+            /* FIXME handle me */
+            ASSERT(0);
+        }
+    }
+
+    return STATUS_SUCCESS;
 }
 
 /*
@@ -864,7 +1579,11 @@ NTAPI
 KsPinGetFirstCloneStreamPointer(
     IN PKSPIN Pin)
 {
-    IKsPinImpl * This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
+    IKsPinImpl * This;
+
+    DPRINT("KsPinGetFirstCloneStreamPointer %p\n", Pin);
+    DbgBreakPoint();
+    This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
     /* return first cloned stream pointer */
     return &This->ClonedStreamPointer->StreamPointer;
 }
@@ -880,6 +1599,8 @@ KsStreamPointerGetNextClone(
 {
     PKSISTREAM_POINTER Pointer = (PKSISTREAM_POINTER)StreamPointer;
 
+    DPRINT("KsStreamPointerGetNextClone\n");
+    DbgBreakPoint();
     /* is there a another cloned stream pointer */
     if (!Pointer->Next)
         return NULL;
@@ -888,6 +1609,269 @@ KsStreamPointerGetNextClone(
     return &Pointer->Next->StreamPointer;
 }
 
+VOID
+NTAPI
+IKsPin_PinCentricWorker(
+    IN PVOID Parameter)
+{
+    PIO_STACK_LOCATION IoStack;
+    PKSSTREAM_HEADER Header;
+    ULONG NumHeaders;
+    NTSTATUS Status;
+    PIRP Irp;
+    IKsPinImpl * This = (IKsPinImpl*)Parameter;
+
+    DPRINT("IKsPin_PinCentricWorker\n");
+
+    /* sanity checks */
+    ASSERT(This);
+    ASSERT(This->Pin.Descriptor);
+    ASSERT(This->Pin.Descriptor->Dispatch);
+    ASSERT(This->Pin.Descriptor->Dispatch->Process);
+    ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
+    ASSERT(!(This->Pin.Descriptor->Flags & KSPIN_FLAG_DISPATCH_LEVEL_PROCESSING));
+    ASSERT(This->LeadingEdgeStreamPointer);
+
+    do
+    {
+        /* do we have an irp packet */
+        if (!This->Irp)
+        {
+            /* fetch new irp packet */
+            This->Irp = KsRemoveIrpFromCancelableQueue(&This->IrpList, &This->IrpListLock, KsListEntryHead, KsAcquireAndRemoveOnlySingleItem);
+
+            if (!This->Irp)
+            {
+                /* reached last packet */
+                break;
+            }
+        }
+
+        /* get current irp stack location */
+        IoStack = IoGetCurrentIrpStackLocation(This->Irp);
+
+       if (This->Irp->RequestorMode == UserMode)
+           This->LeadingEdgeStreamPointer->StreamPointer.StreamHeader = Header = (PKSSTREAM_HEADER)This->Irp->AssociatedIrp.SystemBuffer;
+       else
+           This->LeadingEdgeStreamPointer->StreamPointer.StreamHeader = Header = (PKSSTREAM_HEADER)This->Irp->UserBuffer;
+
+        /* calculate num headers */
+        NumHeaders = IoStack->Parameters.DeviceIoControl.OutputBufferLength / Header->Size;
+
+        /* assume headers of same length */
+        ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength % Header->Size == 0);
+
+        /* FIXME support multiple stream headers */
+       ASSERT(NumHeaders == 1);
+
+        if (This->Irp->RequestorMode == UserMode)
+        {
+            /* prepare header */
+            Header->Data = MmGetSystemAddressForMdlSafe(This->Irp->MdlAddress, NormalPagePriority);
+        }
+
+        /* set up stream pointer */
+        This->LeadingEdgeStreamPointer->Irp = Irp = This->Irp;
+        This->LeadingEdgeStreamPointer->StreamPointer.Context = NULL;
+        This->LeadingEdgeStreamPointer->StreamPointer.Pin = &This->Pin;
+        This->LeadingEdgeStreamPointer->StreamPointer.OffsetOut.Count = max(Header->DataUsed, Header->FrameExtent);
+        This->LeadingEdgeStreamPointer->StreamPointer.OffsetOut.Data = Header->Data;
+        This->LeadingEdgeStreamPointer->StreamPointer.OffsetOut.Count = max(Header->DataUsed, Header->FrameExtent);
+        This->LeadingEdgeStreamPointer->StreamPointer.OffsetOut.Remaining = max(Header->DataUsed, Header->FrameExtent);
+        This->LeadingEdgeStreamPointer->Pin = &This->Pin;
+
+        DPRINT("IKsPin_PinCentricWorker calling Pin Process Routine\n");
+
+            Status = This->Pin.Descriptor->Dispatch->Process(&This->Pin);
+            DPRINT("IKsPin_PinCentricWorker Status %lx, Count %lu Remaining %lu\n", Status,
+                   This->LeadingEdgeStreamPointer->StreamPointer.Offset->Count,
+                   This->LeadingEdgeStreamPointer->StreamPointer.Offset->Remaining);
+
+        ASSERT(Status != STATUS_PENDING);
+
+        // HACK complete irp
+        Irp->IoStatus.Information = max(Header->DataUsed, Header->FrameExtent);
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        KsDecrementCountedWorker(This->PinWorker);
+
+
+        break;
+
+    }while(TRUE);
+}
+
+NTSTATUS
+NTAPI
+IKsPin_DispatchKsStream(
+    PDEVICE_OBJECT DeviceObject,
+    PIRP Irp,
+    IKsPinImpl * This)
+{
+    PKSPROCESSPIN_INDEXENTRY ProcessPinIndex;
+    PKSFILTER Filter;
+    PIO_STACK_LOCATION IoStack;
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    DPRINT("IKsPin_DispatchKsStream\n");
+
+    /* FIXME handle reset states */
+    ASSERT(This->Pin.ResetState == KSRESET_END);
+
+    /* get current stack location */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+    if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_WRITE_STREAM)
+        Status = KsProbeStreamIrp(Irp, KSSTREAM_WRITE | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, This->Pin.StreamHeaderSize);
+    else
+        Status = KsProbeStreamIrp(Irp, KSSTREAM_READ  | KSPROBE_ALLOCATEMDL | KSPROBE_PROBEANDLOCK | KSPROBE_SYSTEMADDRESS, This->Pin.StreamHeaderSize);
+
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("KsProbeStreamIrp failed with %x\n", Status);
+
+        Irp->IoStatus.Status = Status;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        return Status;
+    }
+
+    if (This->Pin.Descriptor->Dispatch->Process)
+    {
+        /* it is a pin centric avstream */
+
+        /* mark irp as pending */
+        IoMarkIrpPending(Irp);
+
+        /* add irp to cancelable queue */
+        KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL /* FIXME */);
+
+        /* sanity checks */
+        ASSERT(!(This->Pin.Descriptor->Flags & KSPIN_FLAG_DISPATCH_LEVEL_PROCESSING));
+        ASSERT(This->PinWorker);
+
+        /* start the processing loop */
+        KsIncrementCountedWorker(This->PinWorker);
+
+        Status = STATUS_PENDING;
+    }
+    else
+    {
+        /* filter-centric avstream */
+        ASSERT(This->Filter);
+
+        ProcessPinIndex = This->Filter->lpVtbl->GetProcessDispatch(This->Filter);
+        Filter = This->Filter->lpVtbl->GetStruct(This->Filter);
+
+        ASSERT(ProcessPinIndex);
+        ASSERT(Filter);
+        ASSERT(Filter->Descriptor);
+        ASSERT(Filter->Descriptor->Dispatch);
+
+        if (!Filter->Descriptor->Dispatch->Process)
+        {
+            /* invalid device request */
+            DPRINT("Filter Centric Processing No Process Routine\n");
+            Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            return STATUS_UNSUCCESSFUL;
+        }
+
+        /* mark irp as pending */
+        IoMarkIrpPending(Irp);
+
+        /* add irp to cancelable queue */
+        KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL /* FIXME */);
+
+
+        Status = Filter->Descriptor->Dispatch->Process(Filter, ProcessPinIndex);
+
+        DPRINT("IKsPin_DispatchKsStream FilterCentric: Status %lx \n", Status);
+
+    }
+
+    return Status;
+}
+
+
+NTSTATUS
+IKsPin_DispatchKsProperty(
+    PDEVICE_OBJECT DeviceObject,
+    PIRP Irp,
+    IKsPinImpl * This)
+{
+    NTSTATUS Status;
+    PKSPROPERTY Property;
+    PIO_STACK_LOCATION IoStack;
+    UNICODE_STRING GuidString;
+    ULONG PropertySetsCount = 0, PropertyItemSize = 0;
+    const KSPROPERTY_SET* PropertySets = NULL;
+
+    /* sanity check */
+    ASSERT(This->Pin.Descriptor);
+
+    /* get current irp stack */
+    IoStack = IoGetCurrentIrpStackLocation(Irp);
+
+
+    if (This->Pin.Descriptor->AutomationTable)
+    {
+        /* use available driver property sets */
+        PropertySetsCount = This->Pin.Descriptor->AutomationTable->PropertySetsCount;
+        PropertySets = This->Pin.Descriptor->AutomationTable->PropertySets;
+        PropertyItemSize = This->Pin.Descriptor->AutomationTable->PropertyItemSize;
+    }
+
+
+    /* try driver provided property sets */
+    Status = KspPropertyHandler(Irp,
+                                PropertySetsCount,
+                                PropertySets,
+                                NULL,
+                                PropertyItemSize);
+
+    if (Status != STATUS_NOT_FOUND)
+    {
+        /* property was handled by driver */
+        if (Status != STATUS_PENDING)
+        {
+            Irp->IoStatus.Status = Status;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        }
+        return Status;
+    }
+
+    /* try our properties */
+    Status = KspPropertyHandler(Irp,
+                                sizeof(PinPropertySet) / sizeof(KSPROPERTY_SET),
+                                PinPropertySet,
+                                NULL,
+                                0);
+
+    if (Status != STATUS_NOT_FOUND)
+    {
+        /* property was handled by driver */
+        if (Status != STATUS_PENDING)
+        {
+            Irp->IoStatus.Status = Status;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        }
+        return Status;
+    }
+
+    /* property was not handled */
+    Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
+
+    RtlStringFromGUID(&Property->Set, &GuidString);
+    DPRINT("IKsPin_DispatchKsProperty Unhandled property Set |%S| Id %u Flags %x\n", GuidString.Buffer, Property->Id, Property->Flags);
+    RtlFreeUnicodeString(&GuidString);
+
+    Irp->IoStatus.Status = STATUS_NOT_FOUND;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return STATUS_NOT_FOUND;
+
+}
+
 NTSTATUS
 NTAPI
 IKsPin_DispatchDeviceIoControl(
@@ -897,7 +1881,6 @@ IKsPin_DispatchDeviceIoControl(
     PIO_STACK_LOCATION IoStack;
     PKSIOBJECT_HEADER ObjectHeader;
     IKsPinImpl * This;
-    NTSTATUS Status = STATUS_SUCCESS;
 
     /* get current irp stack */
     IoStack = IoGetCurrentIrpStackLocation(Irp);
@@ -909,40 +1892,26 @@ IKsPin_DispatchDeviceIoControl(
     /* get the object header */
     ObjectHeader = (PKSIOBJECT_HEADER)IoStack->FileObject->FsContext2;
 
-    /* locate ks pin implemention fro KSPIN offset */
+    /* locate ks pin implemention from KSPIN offset */
     This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
 
-    if (IoStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_KS_WRITE_STREAM && IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_READ_STREAM)
+    if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
     {
-        UNIMPLEMENTED;
-        Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
-        Irp->IoStatus.Information = 0;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
-        return STATUS_NOT_IMPLEMENTED;
+        /* handle ks properties */
+        return IKsPin_DispatchKsProperty(DeviceObject, Irp, This);
     }
 
-    /* mark irp as pending */
-    IoMarkIrpPending(Irp);
-
-    /* add irp to cancelable queue */
-    KsAddIrpToCancelableQueue(&This->IrpList, &This->IrpListLock, Irp, KsListEntryTail, NULL /* FIXME */);
-
-    if (This->Pin.Descriptor->Dispatch->Process)
-    {
-        /* 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
@@ -970,7 +1939,7 @@ IKsPin_Close(
     This = (IKsPinImpl*)CONTAINING_RECORD(ObjectHeader->ObjectType, IKsPinImpl, Pin);
 
     /* acquire filter control mutex */
-    KsFilterAcquireControl(This->BasicHeader.Parent.KsFilter);
+    KsFilterAcquireControl(&This->Pin);
 
     if (This->Pin.Descriptor->Dispatch->Close)
     {
@@ -995,6 +1964,9 @@ IKsPin_Close(
         }
     }
 
+    /* release filter control mutex */
+    KsFilterReleaseControl(&This->Pin);
+
     return Status;
 }
 
@@ -1017,11 +1989,80 @@ IKsPin_DispatchCreateClock(
     IN PDEVICE_OBJECT DeviceObject,
     IN PIRP Irp)
 {
-    UNIMPLEMENTED;
+    PKSPIN Pin;
+    NTSTATUS Status = STATUS_SUCCESS;
+    IKsPinImpl * This;
+    KSRESOLUTION Resolution;
+    PKSRESOLUTION pResolution = NULL;
+    PKSOBJECT_CREATE_ITEM CreateItem;
 
-    Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
+    DPRINT("IKsPin_DispatchCreateClock\n");
+
+    /* get the create item */
+    CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp);
+
+    /* sanity check */
+    ASSERT(CreateItem);
+
+    /* get the pin object */
+    Pin = (PKSPIN)CreateItem->Context;
+
+    /* sanity check */
+    ASSERT(Pin);
+
+    /* locate ks pin implemention fro KSPIN offset */
+    This = (IKsPinImpl*)CONTAINING_RECORD(Pin, IKsPinImpl, Pin);
+
+    /* sanity check */
+    ASSERT(This->BasicHeader.Type == KsObjectTypePin);
+    ASSERT(This->BasicHeader.ControlMutex);
+
+    /* acquire control mutex */
+    KsAcquireControl(Pin);
+
+    if ((This->Pin.Descriptor->PinDescriptor.Communication != KSPIN_COMMUNICATION_NONE &&
+        This->Pin.Descriptor->Dispatch) ||
+        (This->Pin.Descriptor->Flags & KSPIN_FLAG_IMPLEMENT_CLOCK))
+    {
+        if (!This->DefaultClock)
+        {
+            if (This->Pin.Descriptor->Dispatch && This->Pin.Descriptor->Dispatch->Clock)
+            {
+                if (This->Pin.Descriptor->Dispatch->Clock->Resolution)
+                {
+                   This->Pin.Descriptor->Dispatch->Clock->Resolution(&This->Pin, &Resolution);
+                   pResolution = &Resolution;
+                }
+
+                Status = KsAllocateDefaultClockEx(&This->DefaultClock, 
+                                                  (PVOID)&This->Pin,
+                                                  (PFNKSSETTIMER)This->Pin.Descriptor->Dispatch->Clock->SetTimer,
+                                                  (PFNKSCANCELTIMER)This->Pin.Descriptor->Dispatch->Clock->CancelTimer,
+                                                  (PFNKSCORRELATEDTIME)This->Pin.Descriptor->Dispatch->Clock->CorrelatedTime,
+                                                  pResolution,
+                                                  0);
+            }
+            else
+            {
+                Status = KsAllocateDefaultClockEx(&This->DefaultClock, (PVOID)&This->Pin, NULL, NULL, NULL, NULL, 0);
+            }
+        }
+
+        if (NT_SUCCESS(Status))
+        {
+            Status = KsCreateDefaultClock(Irp, This->DefaultClock);
+        }
+    }
+
+    DPRINT("IKsPin_DispatchCreateClock %lx\n", Status);
+
+    /* release control mutex */
+    KsReleaseControl(Pin);
+
+    /* done */
+    Irp->IoStatus.Status = Status;
     IoCompleteRequest(Irp, IO_NO_INCREMENT);
-    return STATUS_NOT_IMPLEMENTED;
+    return Status;
 }
 
 NTSTATUS
@@ -1054,7 +2095,7 @@ static KSDISPATCH_TABLE PinDispatchTable =
 NTSTATUS
 KspCreatePin(
     IN PDEVICE_OBJECT DeviceObject,
-    IN PIRP Irp, 
+    IN PIRP Irp,
     IN PKSDEVICE KsDevice,
     IN IKsFilterFactory * FilterFactory,
     IN IKsFilter* Filter,
@@ -1067,10 +2108,16 @@ KspCreatePin(
     PDEVICE_EXTENSION DeviceExtension;
     PKSOBJECT_CREATE_ITEM CreateItem;
     NTSTATUS Status;
+    PKSDATAFORMAT DataFormat;
+    PKSBASIC_HEADER BasicHeader;
 
     /* sanity checks */
     ASSERT(Descriptor->Dispatch);
-    ASSERT(Descriptor->Dispatch->Create);
+
+    DPRINT("KspCreatePin PinId %lu Flags %x\n", Connect->PinId, Descriptor->Flags);
+
+//Output Pin: KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY
+//Input Pin: KSPIN_FLAG_FIXED_FORMAT|KSPIN_FLAG_DO_NOT_USE_STANDARD_TRANSPORT|KSPIN_FLAG_FRAMES_NOT_REQUIRED_FOR_PROCESSING
 
     /* get current irp stack */
     IoStack = IoGetCurrentIrpStackLocation(Irp);
@@ -1095,6 +2142,7 @@ KspCreatePin(
     {
         /* not enough memory */
         FreeItem(This);
+        DPRINT("KspCreatePin OutOfMemory\n");
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
@@ -1102,21 +2150,28 @@ KspCreatePin(
     This->BasicHeader.KsDevice = KsDevice;
     This->BasicHeader.Type = KsObjectTypePin;
     This->BasicHeader.Parent.KsFilter = Filter->lpVtbl->GetStruct(Filter);
-    KeInitializeMutex(&This->BasicHeader.ControlMutex, 0);
+
+    ASSERT(This->BasicHeader.Parent.KsFilter);
+
+    BasicHeader = (PKSBASIC_HEADER)((ULONG_PTR)This->BasicHeader.Parent.KsFilter - sizeof(KSBASIC_HEADER));
+
+    This->BasicHeader.ControlMutex = BasicHeader->ControlMutex;
+    ASSERT(This->BasicHeader.ControlMutex);
+
+
     InitializeListHead(&This->BasicHeader.EventList);
     KeInitializeSpinLock(&This->BasicHeader.EventListLock);
 
     /* initialize pin */
     This->lpVtbl = &vt_IKsPin;
+    This->lpVtblReferenceClock = &vt_ReferenceClock;
     This->ref = 1;
     This->FileObject = IoStack->FileObject;
+    This->Filter = Filter;
     KeInitializeMutex(&This->ProcessingMutex, 0);
     InitializeListHead(&This->IrpList);
     KeInitializeSpinLock(&This->IrpListLock);
 
-    /* initialize ks pin descriptor */
-    This->Pin.Descriptor = Descriptor;
-    This->Pin.Id = Connect->PinId;
 
     /* allocate object bag */
     This->Pin.Bag = AllocateItem(NonPagedPool, sizeof(KSIOBJECT_BAG));
@@ -1129,14 +2184,35 @@ KspCreatePin(
     }
 
     /* initialize object bag */
-    Device->lpVtbl->InitializeObjectBag(Device, This->Pin.Bag, &This->BasicHeader.ControlMutex); /* is using control mutex right? */
+    Device->lpVtbl->InitializeObjectBag(Device, This->Pin.Bag, NULL);
 
+    /* get format */
+    DataFormat = (PKSDATAFORMAT)(Connect + 1);
+
+    /* initialize pin descriptor */
+    This->Pin.Descriptor = Descriptor;
+    This->Pin.Context = NULL;
+    This->Pin.Id = Connect->PinId;
     This->Pin.Communication = Descriptor->PinDescriptor.Communication;
-    This->Pin.ConnectionIsExternal = FALSE; /* FIXME */
-    //FIXME This->Pin.ConnectionInterface = Descriptor->PinDescriptor.Interfaces;
-    //FIXME This->Pin.ConnectionMedium = Descriptor->PinDescriptor.Mediums;
-    //FIXME This->Pin.ConnectionPriority = KSPRIORITY_NORMAL;
-    This->Pin.ConnectionFormat = (PKSDATAFORMAT) (Connect + 1);
+    This->Pin.ConnectionIsExternal = FALSE; //FIXME
+    RtlMoveMemory(&This->Pin.ConnectionInterface, &Connect->Interface, sizeof(KSPIN_INTERFACE));
+    RtlMoveMemory(&This->Pin.ConnectionMedium, &Connect->Medium, sizeof(KSPIN_MEDIUM));
+    RtlMoveMemory(&This->Pin.ConnectionPriority, &Connect->Priority, sizeof(KSPRIORITY));
+
+    /* allocate format */
+    Status = _KsEdit(This->Pin.Bag, (PVOID*)&This->Pin.ConnectionFormat, DataFormat->FormatSize, DataFormat->FormatSize, 0);
+    if (!NT_SUCCESS(Status))
+    {
+        /* failed to allocate format */
+        KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
+        FreeItem(This);
+        FreeItem(CreateItem);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* copy format */
+    RtlMoveMemory((PVOID)This->Pin.ConnectionFormat, DataFormat, DataFormat->FormatSize);
+
     This->Pin.AttributeList = NULL; //FIXME
     This->Pin.StreamHeaderSize = sizeof(KSSTREAM_HEADER);
     This->Pin.DataFlow = Descriptor->PinDescriptor.DataFlow;
@@ -1145,19 +2221,19 @@ KspCreatePin(
     This->Pin.ClientState = KSSTATE_STOP;
 
     /* intialize allocator create item */
-    CreateItem[0].Context = (PVOID)This;
+    CreateItem[0].Context = (PVOID)&This->Pin;
     CreateItem[0].Create = IKsPin_DispatchCreateAllocator;
     CreateItem[0].Flags = KSCREATE_ITEM_FREEONSTOP;
     RtlInitUnicodeString(&CreateItem[0].ObjectClass, KSSTRING_Allocator);
 
     /* intialize clock create item */
-    CreateItem[1].Context = (PVOID)This;
+    CreateItem[1].Context = (PVOID)&This->Pin;
     CreateItem[1].Create = IKsPin_DispatchCreateClock;
     CreateItem[1].Flags = KSCREATE_ITEM_FREEONSTOP;
     RtlInitUnicodeString(&CreateItem[1].ObjectClass, KSSTRING_Clock);
 
     /* intialize topology node create item */
-    CreateItem[2].Context = (PVOID)This;
+    CreateItem[2].Context = (PVOID)&This->Pin;
     CreateItem[2].Create = IKsPin_DispatchCreateNode;
     CreateItem[2].Flags = KSCREATE_ITEM_FREEONSTOP;
     RtlInitUnicodeString(&CreateItem[2].ObjectClass, KSSTRING_TopologyNode);
@@ -1167,6 +2243,7 @@ KspCreatePin(
     if (!NT_SUCCESS(Status))
     {
         /* failed to create object header */
+        DPRINT("KspCreatePin KsAllocateObjectHeader failed %lx\n", Status);
         KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
         FreeItem(This);
         FreeItem(CreateItem);
@@ -1180,37 +2257,93 @@ KspCreatePin(
     This->ObjectHeader->Unknown = (PUNKNOWN)&This->lpVtbl;
     This->ObjectHeader->ObjectType = (PVOID)&This->Pin;
 
-    /* setup process pin */
-    This->ProcessPin.Pin = &This->Pin;
-    This->ProcessPin.StreamPointer = (PKSSTREAM_POINTER)This->LeadingEdgeStreamPointer;
-
     if (!Descriptor->Dispatch || !Descriptor->Dispatch->Process)
     {
         /* the pin is part of filter-centric processing filter
          * add process pin to filter
          */
+        This->ProcessPin.BytesAvailable = 0;
+        This->ProcessPin.BytesUsed = 0;
+        This->ProcessPin.CopySource = NULL;
+        This->ProcessPin.Data = NULL;
+        This->ProcessPin.DelegateBranch = NULL;
+        This->ProcessPin.Flags = 0;
+        This->ProcessPin.InPlaceCounterpart = NULL;
+        This->ProcessPin.Pin = &This->Pin;
+        This->ProcessPin.StreamPointer = (PKSSTREAM_POINTER)This->LeadingEdgeStreamPointer;
+        This->ProcessPin.Terminate = FALSE;
 
         Status = Filter->lpVtbl->AddProcessPin(Filter, &This->ProcessPin);
+        DPRINT("KspCreatePin AddProcessPin %lx\n", Status);
+
         if (!NT_SUCCESS(Status))
         {
             /* failed to add process pin */
             KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
             KsFreeObjectHeader(&This->ObjectHeader);
-
+            FreeItem(This);
+            FreeItem(CreateItem);
             /* return failure code */
             return Status;
         }
     }
+    else if (Descriptor->Dispatch && Descriptor->Dispatch->Process)
+    {
+        /* pin centric processing filter */
+
+        /* allocate leading stream pointer */
+        Status = _KsEdit(This->Pin.Bag, (PVOID*)&This->LeadingEdgeStreamPointer, sizeof(KSISTREAM_POINTER), sizeof(KSISTREAM_POINTER), 0);
+
+        /* FIXME cleanup */
+        ASSERT(Status == STATUS_SUCCESS);
+
+        /* FIXME cleanup */
+        ASSERT(Status == STATUS_SUCCESS);
+
+        /* setup stream pointer offset */
+         This->LeadingEdgeStreamPointer->StreamPointer.Offset = &This->LeadingEdgeStreamPointer->StreamPointer.OffsetOut;
+
+        /* initialize work item */
+        ExInitializeWorkItem(&This->PinWorkQueueItem, IKsPin_PinCentricWorker, (PVOID)This);
+
+        /* allocate counted work item */
+        Status = KsRegisterCountedWorker(HyperCriticalWorkQueue, &This->PinWorkQueueItem, &This->PinWorker);
+
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT("Failed to register Worker %lx\n", Status);
+            KsFreeObjectBag((KSOBJECT_BAG)This->Pin.Bag);
+            KsFreeObjectHeader(&This->ObjectHeader);
+            FreeItem(This);
+            FreeItem(CreateItem);
+            return Status;
+        }
+
+        KeInitializeEvent(&This->FrameComplete, NotificationEvent, FALSE);
+
+    }
 
     /* FIXME add pin instance to filter instance */
 
+
+    if (Descriptor->Dispatch && Descriptor->Dispatch->SetDataFormat)
+    {
+        Status = Descriptor->Dispatch->SetDataFormat(&This->Pin, NULL, NULL, This->Pin.ConnectionFormat, NULL);
+        DPRINT("KspCreatePin SetDataFormat %lx\n", Status);
+    }
+
+
     /* does the driver have a pin dispatch */
     if (Descriptor->Dispatch && Descriptor->Dispatch->Create)
     {
         /*  now inform the driver to create a new pin */
         Status = Descriptor->Dispatch->Create(&This->Pin, Irp);
+        DPRINT("KspCreatePin DispatchCreate %lx\n", Status);
     }
 
+
+    DPRINT("KspCreatePin Status %lx\n", Status);
+
     if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
     {
         /* failed to create pin, release resources */
index cc0b8f9..86ea4eb 100644 (file)
@@ -35,3 +35,24 @@ DEFINE_KSPROPERTY_TABLE(PinSet) {\
     DEFINE_KSPROPERTY_ITEM_PIN_CONSTRAINEDDATARANGES(PropGeneral),\
     DEFINE_KSPROPERTY_ITEM_PIN_PROPOSEDATAFORMAT(PropGeneral)\
 }
+
+#define DEFINE_KSPROPERTY_CONNECTIONSET(PinSet,\
+    PropStateHandler, PropDataFormatHandler, PropAllocatorFraming)\
+DEFINE_KSPROPERTY_TABLE(PinSet) {\
+    DEFINE_KSPROPERTY_ITEM_CONNECTION_STATE(PropStateHandler, PropStateHandler),\
+    DEFINE_KSPROPERTY_ITEM_CONNECTION_DATAFORMAT(PropDataFormatHandler, PropDataFormatHandler),\
+    DEFINE_KSPROPERTY_ITEM_CONNECTION_ALLOCATORFRAMING(PropAllocatorFraming)\
+}
+
+
+#define DEFINE_KSPROPERTY_STREAMSET(PinSet,\
+    PropStreamAllocator, PropMasterClock, PropPipeId)\
+DEFINE_KSPROPERTY_TABLE(PinSet) {\
+    DEFINE_KSPROPERTY_ITEM_STREAM_ALLOCATOR(PropStreamAllocator, PropStreamAllocator),\
+    DEFINE_KSPROPERTY_ITEM_STREAM_MASTERCLOCK(PropMasterClock, PropMasterClock),\
+    DEFINE_KSPROPERTY_ITEM_STREAM_PIPE_ID(PropPipeId, PropPipeId)\
+}
+
+
+
+
index a2e759c..b1a17e3 100644 (file)
@@ -137,7 +137,7 @@ KspPropertyHandler(
     /* get input property request */
     Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
 
-    DPRINT("KspPropertyHandler Irp %p PropertySetsCount %u PropertySet %p Allocator %p PropertyItemSize %u ExpectedPropertyItemSize %u\n", Irp, PropertySetsCount, PropertySet, Allocator, PropertyItemSize, sizeof(KSPROPERTY_ITEM));
+//    DPRINT("KspPropertyHandler Irp %p PropertySetsCount %u PropertySet %p Allocator %p PropertyItemSize %u ExpectedPropertyItemSize %u\n", Irp, PropertySetsCount, PropertySet, Allocator, PropertyItemSize, sizeof(KSPROPERTY_ITEM));
 
     /* sanity check */
     ASSERT(PropertyItemSize == 0 || PropertyItemSize == sizeof(KSPROPERTY_ITEM));
index f2589c1..9e24f92 100644 (file)
@@ -261,19 +261,36 @@ BdaCreateFilterFactoryEx(
     PBDA_FILTER_INSTANCE_ENTRY FilterInstance;
     KIRQL OldLevel;
     NTSTATUS Status;
-    KSFILTER_DESCRIPTOR FilterDescriptor;
+    PKSFILTER_DESCRIPTOR FilterDescriptor;
 
     DPRINT("BdaCreateFilterFactoryEx\n");
-    /* backup filter descriptor */
-    RtlMoveMemory(&FilterDescriptor, pFilterDescriptor, sizeof(KSFILTER_DESCRIPTOR));
+
+    FilterDescriptor = AllocateItem(NonPagedPool, sizeof(KSFILTER_DESCRIPTOR));
+    if (!FilterDescriptor)
+    {
+        /* no memory */
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* copy filter descriptor template */
+    RtlMoveMemory(FilterDescriptor, pFilterDescriptor, sizeof(KSFILTER_DESCRIPTOR));
+
+    /* erase pin / nodes / connections from filter descriptor */
+    FilterDescriptor->PinDescriptorsCount = 0;
+    FilterDescriptor->PinDescriptors = NULL;
+    FilterDescriptor->NodeDescriptorsCount = 0;
+    FilterDescriptor->NodeDescriptors = NULL;
+    FilterDescriptor->ConnectionsCount = 0;
+    FilterDescriptor->Connections = NULL;
 
     /* merge the automation tables */
-    Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&FilterDescriptor.AutomationTable, (PKSAUTOMATION_TABLE)pFilterDescriptor->AutomationTable, &FilterAutomationTable, NULL);
+    Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&FilterDescriptor->AutomationTable, (PKSAUTOMATION_TABLE)pFilterDescriptor->AutomationTable, &FilterAutomationTable, NULL);
 
     /* check for success */
     if (!NT_SUCCESS(Status))
     {
         DPRINT1("KsMergeAutomationTables failed with %lx\n", Status);
+        FreeItem(FilterDescriptor);
         return Status;
     }
 
@@ -282,25 +299,31 @@ BdaCreateFilterFactoryEx(
     if (!FilterInstance)
     {
         /* not enough memory */
+        FreeItem(FilterDescriptor);
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
     /* create the filter factory */
-    Status = KsCreateFilterFactory(pKSDevice->FunctionalDeviceObject, &FilterDescriptor, NULL, NULL, 0, NULL, NULL, &FilterFactory);
+    Status = KsCreateFilterFactory(pKSDevice->FunctionalDeviceObject, FilterDescriptor, NULL, NULL, 0, NULL, NULL, &FilterFactory);
 
     /* check for success */
     if (NT_SUCCESS(Status))
     {
-
-        /* add the item to filter object bag */
-        Status = KsAddItemToObjectBag(FilterFactory->Bag, FilterInstance, FreeFilterInstance);
-        if (!NT_SUCCESS(Status))
+        if (FilterDescriptor->AutomationTable != &FilterAutomationTable)
         {
-            /* destroy filter instance */
-            DPRINT1("KsAddItemToObjectBag failed with %lx\n", Status);
-            FreeItem(FilterInstance);
-            KsDeleteFilterFactory(FilterFactory);
-            return Status;
+            /* add the item to filter object bag */
+            KsAddItemToObjectBag(FilterFactory->Bag, (PVOID)FilterDescriptor->AutomationTable, FreeFilterInstance);
+        }
+        else
+        {
+            /* make sure the automation table is not-read only */
+            Status = _KsEdit(FilterFactory->Bag, (PVOID*)&FilterDescriptor->AutomationTable, sizeof(KSAUTOMATION_TABLE), sizeof(KSAUTOMATION_TABLE), 0);
+
+            /* sanity check */
+            ASSERT(Status == STATUS_SUCCESS);
+
+            /* add to object bag */
+            KsAddItemToObjectBag(FilterFactory->Bag, (PVOID)FilterDescriptor->AutomationTable, FreeFilterInstance);
         }
 
         /* initialize filter instance entry */
@@ -327,7 +350,7 @@ BdaCreateFilterFactoryEx(
     {
         /* failed to create filter factory */
         FreeItem(FilterInstance);
-        DPRINT1("KsCreateFilterFactory failed with %lx\n", Status);
+        FreeItem(FilterDescriptor);
     }
 
     /* done */
@@ -350,7 +373,7 @@ BdaCreatePin(
     PBDA_FILTER_INSTANCE_ENTRY InstanceEntry;
     NTSTATUS Status;
     ULONG PinId;
-    KSPIN_DESCRIPTOR_EX NewPinDescriptor;
+    PKSPIN_DESCRIPTOR_EX NewPinDescriptor;
 
     DPRINT("BdaCreatePin\n");
 
@@ -380,6 +403,7 @@ BdaCreatePin(
     if (!InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount)
     {
         /* no pins supported */
+        DPRINT("BdaCreatePin NoPins supported\n");
         return STATUS_UNSUCCESSFUL;
     }
 
@@ -387,6 +411,7 @@ BdaCreatePin(
     if (InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount <= ulPinType)
     {
         /* pin request is out of bounds */
+        DPRINT("BdaCreatePin ulPinType %lu >= PinDescriptorCount %lu\n", ulPinType, InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptorsCount);
         return STATUS_INVALID_PARAMETER;
     }
 
@@ -396,17 +421,26 @@ BdaCreatePin(
     /* get pin descriptor */
     PinDescriptor = (PKSPIN_DESCRIPTOR_EX)&InstanceEntry->FilterTemplate->pFilterDescriptor->PinDescriptors[ulPinType];
 
+    /* allocate pin descriptor */
+    NewPinDescriptor = AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR_EX));
+    if (!NewPinDescriptor)
+    {
+        /* no memory */
+        DPRINT("BdaCreatePin OutOfMemory\n");
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
    /* make a copy of the pin descriptor */
-   RtlMoveMemory(&NewPinDescriptor, PinDescriptor, sizeof(KSPIN_DESCRIPTOR_EX));
+   RtlMoveMemory(NewPinDescriptor, PinDescriptor, sizeof(KSPIN_DESCRIPTOR_EX));
 
     /* merge the automation tables */
-    Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&NewPinDescriptor.AutomationTable, (PKSAUTOMATION_TABLE)PinDescriptor->AutomationTable, &PinAutomationTable, pKSFilter->Bag);
+    Status = KsMergeAutomationTables((PKSAUTOMATION_TABLE*)&NewPinDescriptor->AutomationTable, (PKSAUTOMATION_TABLE)PinDescriptor->AutomationTable, &PinAutomationTable, pKSFilter->Bag);
 
     /* check for success */
     if (NT_SUCCESS(Status))
     {
         /* create the pin factory */
-        Status = KsFilterCreatePinFactory(pKSFilter, &NewPinDescriptor, &PinId);
+        Status = KsFilterCreatePinFactory(pKSFilter, NewPinDescriptor, &PinId);
 
         /* check for success */
         if (NT_SUCCESS(Status))
@@ -417,7 +451,7 @@ BdaCreatePin(
     }
 
 
-    DPRINT("BdaCreatePin Result %x\n", Status);
+    DPRINT("BdaCreatePin Result %x PinId %u\n", Status, PinId);
     return Status;
 }
 
@@ -470,7 +504,7 @@ BdaInitFilter(
     ULONG Index, PinId;
     NTSTATUS Status = STATUS_SUCCESS;
 
-    DPRINT("BdaInitFilter\n");
+    DPRINT("BdaInitFilter %p\n", pBdaFilterTemplate);
 
     /* check input parameters */
     if (!pKSFilter)
@@ -487,7 +521,12 @@ BdaInitFilter(
 
     /* sanity check */
     ASSERT(InstanceEntry);
-    ASSERT(InstanceEntry->FilterTemplate == pBdaFilterTemplate);
+
+    if (!pBdaFilterTemplate)
+    {
+        /* use template from BdaCreateFilterFactoryEx */
+        pBdaFilterTemplate = InstanceEntry->FilterTemplate;
+    }
 
     /* now create the pins */
     for(Index = 0; Index < pBdaFilterTemplate->pFilterDescriptor->PinDescriptorsCount; Index++)
index 927bc96..db58172 100644 (file)
@@ -7,7 +7,7 @@
 #include <bdamedia.h>
 #include <bdasup.h>
 
-#define NDEBUG
+#define YDEBUG
 #include <debug.h>
 
 
index 1cace8b..fb2bb02 100644 (file)
@@ -537,10 +537,10 @@ WaitOnBaseBusy(
 {
     ULONG i;
     UCHAR Status;
-    for (i=0; i<200; i++) {
+    for (i=0; i<20000; i++) {
         GetBaseStatus(chan, Status);
         if (Status & IDE_STATUS_BUSY) {
-            AtapiStallExecution(10);
+            AtapiStallExecution(150);
             continue;
         } else {
             break;
@@ -640,11 +640,11 @@ WaitForDrq(
     for (i=0; i<1000; i++) {
         GetStatus(chan, Status);
         if (Status & IDE_STATUS_BUSY) {
-            AtapiStallExecution(10);
+            AtapiStallExecution(100);
         } else if (Status & IDE_STATUS_DRQ) {
             break;
         } else {
-            AtapiStallExecution(10);
+            AtapiStallExecution(200);
         }
     }
     return Status;
@@ -661,11 +661,11 @@ WaitShortForDrq(
     for (i=0; i<2; i++) {
         GetStatus(chan, Status);
         if (Status & IDE_STATUS_BUSY) {
-            AtapiStallExecution(10);
+            AtapiStallExecution(100);
         } else if (Status & IDE_STATUS_DRQ) {
             break;
         } else {
-            AtapiStallExecution(10);
+            AtapiStallExecution(100);
         }
     }
     return Status;
index eebc0c0..b1ec550 100644 (file)
@@ -100,9 +100,9 @@ EhciDefferedRoutine(PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVO
 
                     tmp = READ_REGISTER_ULONG((PULONG)((Base + EHCI_PORTSC) + (4 * i)));
 
-                    DPRINT("port tmp %x\n", tmp);
                     GetDeviceDescriptor(FdoDeviceExtension, 0, 0, FALSE);
                     PdoDeviceExtension->ChildDeviceCount++;
+                    PdoDeviceExtension->Ports[i].PortStatus |= USB_PORT_STATUS_HIGH_SPEED | USB_PORT_STATUS_CONNECT | USB_PORT_STATUS_ENABLE;
                     WorkItemData = ExAllocatePool(NonPagedPool, sizeof(WORKITEM_DATA));
                     if (!WorkItemData) ASSERT(FALSE);
                     WorkItemData->IoWorkItem = IoAllocateWorkItem(PdoDeviceExtension->DeviceObject);
index 29af1f9..06d7c50 100644 (file)
@@ -88,35 +88,65 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
         if (UsbDevice == NULL)
             UsbDevice = DeviceExtension->UsbDevices[0];
 
+        /* Assume URB success */
+        Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
+        /* Set the DeviceHandle to the Internal Device */
+        Urb->UrbHeader.UsbdDeviceHandle = UsbDevice;
+
         switch (Urb->UrbHeader.Function)
         {
             case URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:
             {
-                /* Are we suppose to only return on this request when a device is connected
-                   or is it the RootHubInitNotification Callback */
                 DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER:\n");
                 DPRINT1("--->TransferBufferLength %x\n",Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
                 DPRINT1("--->TransferBuffer %x\n",Urb->UrbBulkOrInterruptTransfer.TransferBuffer);
                 DPRINT1("--->PipeHandle %x\n",Urb->UrbBulkOrInterruptTransfer.PipeHandle);
+                DPRINT1("---->(PVOID)&UsbDevice->EndPointDescriptor %x\n", (PVOID)&UsbDevice->EndPointDescriptor);
                 DPRINT1("--->TransferFlags %x\n", Urb->UrbBulkOrInterruptTransfer.TransferFlags);
-                /* FIXME */
+
                 RtlZeroMemory(Urb->UrbBulkOrInterruptTransfer.TransferBuffer, Urb->UrbBulkOrInterruptTransfer.TransferBufferLength);
-                ((PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 1;
-                /* Turn off Irp handling as nothing is handled beyond this */
-                DeviceExtension->HaltUrbHandling = TRUE;
+                if (UsbDevice == DeviceExtension->UsbDevices[0])
+                {
+                    if (Urb->UrbBulkOrInterruptTransfer.TransferFlags & (USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK))
+                    {
+                        LONG i;
+                        for (i = 0; i < 8; i++)
+                        {
+                            if (DeviceExtension->Ports[i].PortChange)
+                            {
+                                DPRINT1("Inform hub driver that port %d has changed\n", i+1);
+                                ((PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 1 << (i + 1);
+                            }
+                        }
+                    }
+                    else
+                    {
+                        Urb->UrbHeader.Status = USBD_STATUS_INVALID_PARAMETER;
+                        Status = STATUS_UNSUCCESSFUL;
+                    }
+                }
                 break;
             }
             case URB_FUNCTION_GET_STATUS_FROM_DEVICE:
             {
-                DPRINT1("Get Status from Device\n");
+                DPRINT("Get Status from Device\n");
+                DPRINT("Index : %d\n", Urb->UrbControlGetStatusRequest.Index);
+
+                /* Copied from pvdrivers */
+                if (Urb->UrbControlGetStatusRequest.Index == 0)
+                {
+                    *(PUSHORT)Urb->UrbControlGetStatusRequest.TransferBuffer = USB_PORT_STATUS_CONNECT | USB_PORT_STATUS_ENABLE;
+                }
+                else
+                {
+                    DPRINT1("Uknown identifier\n");
+                    Urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION;
+                    Status = STATUS_UNSUCCESSFUL;
+                }
                 break;
             }
             case URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE:
             {
-                Urb->UrbHeader.Function = 0x08;
-                Urb->UrbHeader.UsbdFlags = 0;
-                Urb->UrbHeader.UsbdDeviceHandle = UsbDevice;
-
                 switch(Urb->UrbControlDescriptorRequest.DescriptorType)
                 {
                     case USB_DEVICE_DESCRIPTOR_TYPE:
@@ -130,9 +160,6 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
                         RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer,
                                       &UsbDevice->DeviceDescriptor,
                                       Urb->UrbControlDescriptorRequest.TransferBufferLength);
-
-                        Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
-
                         break;
                     }
                     case USB_CONFIGURATION_DESCRIPTOR_TYPE:
@@ -150,9 +177,6 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
                         RtlCopyMemory(Urb->UrbControlDescriptorRequest.TransferBuffer,
                                       &UsbDevice->ConfigurationDescriptor,
                                       Urb->UrbControlDescriptorRequest.TransferBufferLength);
-
-                        Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
-
                         break;
                     }
                     case USB_STRING_DESCRIPTOR_TYPE:
@@ -232,10 +256,6 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
                         }
                         InterfaceInfo = (PUSBD_INTERFACE_INFORMATION)((PUCHAR)InterfaceInfo + InterfaceInfo->Length);
                     }
-
-                    Urb->UrbHeader.UsbdDeviceHandle = UsbDevice;
-                    Urb->UrbHeader.UsbdFlags = 0;
-                    Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
                 }
                 else
                 {
@@ -252,7 +272,6 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
                         DPRINT1("TransferFlags %x\n", Urb->UrbControlVendorClassRequest.TransferFlags);
                         DPRINT1("Urb->UrbControlVendorClassRequest.Value %x\n", Urb->UrbControlVendorClassRequest.Value);
 
-
                         switch (Urb->UrbControlVendorClassRequest.Value >> 8)
                         {
                             case USB_DEVICE_CLASS_AUDIO:
@@ -328,10 +347,16 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
                                 DPRINT1("Unknown UrbControlVendorClassRequest Value\n");
                             }
                         }
-                        Urb->UrbHeader.Function = 0x08;
-                        Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
-                        Urb->UrbHeader.UsbdDeviceHandle = UsbDevice;
-                        Urb->UrbHeader.UsbdFlags = 0;
+                        break;
+                    }
+                    case USB_REQUEST_GET_STATUS:
+                    {
+                        DPRINT1("DEVICE: USB_REQUEST_GET_STATUS for port %d\n", Urb->UrbControlVendorClassRequest.Index);
+
+                        if (Urb->UrbControlVendorClassRequest.Index == 1)
+                        {
+                            ((PULONG)Urb->UrbControlVendorClassRequest.TransferBuffer)[0] = 0;
+                        }
                         break;
                     }
                     default:
@@ -348,22 +373,51 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
                 {
                     case USB_REQUEST_GET_STATUS:
                     {
-                        DPRINT1("USB_REQUEST_GET_STATUS\n");
+                        DPRINT1("OTHER: USB_REQUEST_GET_STATUS for port %d\n", Urb->UrbControlVendorClassRequest.Index);
+
+                        ((PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer)[0] = DeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortStatus;
+                        ((PUSHORT)Urb->UrbControlVendorClassRequest.TransferBuffer)[1] = DeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange;
                         break;
                     }
                     case USB_REQUEST_CLEAR_FEATURE:
                     {
-                        DPRINT1("USB_REQUEST_CLEAR_FEATURE\n");
+                        DPRINT1("USB_REQUEST_CLEAR_FEATURE Port %d, value %x\n", Urb->UrbControlVendorClassRequest.Index,
+                            Urb->UrbControlVendorClassRequest.Value);
+                        switch (Urb->UrbControlVendorClassRequest.Value)
+                        {
+                            case C_PORT_CONNECTION:
+                                DeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange &= ~USB_PORT_STATUS_CONNECT;
+                                break;
+                            case C_PORT_RESET:
+                                DeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange &= ~USB_PORT_STATUS_RESET;
+                                break;
+                            default:
+                                DPRINT1("Unknown Value for Clear Feature %x \n", Urb->UrbControlVendorClassRequest.Value);
+                                break;
+                        }
                         break;
                     }
                     case USB_REQUEST_SET_FEATURE:
                     {
-                        DPRINT1("USB_REQUEST_SET_FEATURE value %x\n", Urb->UrbControlVendorClassRequest.Value);
+                        DPRINT1("USB_REQUEST_SET_FEATURE Port %d, value %x\n", Urb->UrbControlVendorClassRequest.Index,
+                            Urb->UrbControlVendorClassRequest.Value);
+
                         switch(Urb->UrbControlVendorClassRequest.Value)
                         {
-                            /* FIXME: Needs research */
-                            case 0x01:
+                            case PORT_RESET:
                             {
+                                DeviceExtension->Ports[Urb->UrbControlVendorClassRequest.Index-1].PortChange |= USB_PORT_STATUS_RESET;
+                                break;
+                            }
+                            case PORT_ENABLE:
+                            {
+                                DPRINT1("Unhandled Set Feature\n");
+                                break;
+                            }
+                            default:
+                            {
+                                DPRINT1("Unknown Set Feature!\n");
+                                break;
                             }
                         }
                         break;
@@ -371,6 +425,7 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
                     case USB_REQUEST_SET_ADDRESS:
                     {
                         DPRINT1("USB_REQUEST_SET_ADDRESS\n");
+                        ASSERT(FALSE);
                         break;
                     }
                     case USB_REQUEST_GET_DESCRIPTOR:
@@ -408,6 +463,12 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
                         DPRINT1("USB_REQUEST_SYNC_FRAME\n");
                         break;
                     }
+                    default:
+                    {
+                        DPRINT1("Unknown Function Class Unknown request\n");
+                        ASSERT(FALSE);
+                        break;
+                    }
                 }
                 break;
             }
@@ -415,6 +476,7 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
             {
                 DPRINT1("Unhandled URB %x\n", Urb->UrbHeader.Function);
                 Urb->UrbHeader.Status = USBD_STATUS_INVALID_URB_FUNCTION;
+                ASSERT(FALSE);
             }
 
         }
@@ -424,6 +486,13 @@ CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension)
         Irp->IoStatus.Status = Status;
         Irp->IoStatus.Information = Information;
 
+        if (Urb->UrbHeader.Status == USBD_STATUS_SUCCESS)
+        {
+            /* Fake a successful Control Transfer */
+            Urb->UrbHeader.Function = 0x08;
+            Urb->UrbHeader.UsbdFlags = 0;
+        }
+
         IoCompleteRequest(Irp, IO_NO_INCREMENT);
         KeAcquireSpinLock(&DeviceExtension->IrpQueueLock, &oldIrql);
     }
index 3ab717f..6a0d735 100644 (file)
@@ -172,18 +172,24 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
         }
         case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
         {
-            DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE\n");
+            DPRINT1("IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %x\n", IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE);
+            if (Stack->Parameters.Others.Argument1)
+            {
+                /* Return the root hubs devicehandle */
+                *(PVOID *)Stack->Parameters.Others.Argument1 = (PVOID)PdoDeviceExtension->UsbDevices[0];
+            }
+            else
+                Status = STATUS_INVALID_DEVICE_REQUEST;
             break;
         }
         case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
         {
-            DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT\n");
-
+            DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_COUNT %x\n", IOCTL_INTERNAL_USB_GET_HUB_COUNT);
             if (Stack->Parameters.Others.Argument1)
             {
                 /* FIXME: Determine the number of hubs between the usb device and root hub */
-                /* For now return 0 */
-                *(PVOID *)Stack->Parameters.Others.Argument1 = 0;
+                /* For now return 1, the root hub */
+                *(PVOID *)Stack->Parameters.Others.Argument1 = (PVOID)1;
             }
             break;
         }
@@ -216,9 +222,8 @@ PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
             if (Stack->Parameters.Others.Argument2)
                 *(PVOID *)Stack->Parameters.Others.Argument2 = IoGetAttachedDevice(FdoDeviceExtension->DeviceObject);
 
-            Irp->IoStatus.Information = 0;
-            Irp->IoStatus.Status = STATUS_SUCCESS;
-            return STATUS_SUCCESS;
+            Information = 0;
+            Status = STATUS_SUCCESS;
             break;
         }
         case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
@@ -287,7 +292,6 @@ PdoQueryId(PDEVICE_OBJECT DeviceObject, PIRP Irp, ULONG_PTR* Information)
         }
     }
 
-    /* Lifted from hpoussin */
     Status = DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
                                     &SourceString,
                                     &String);
@@ -350,6 +354,7 @@ PdoDispatchPnp(
             PPDO_DEVICE_EXTENSION PdoDeviceExtension;
             PFDO_DEVICE_EXTENSION FdoDeviceExtension;
             UNICODE_STRING InterfaceSymLinkName;
+            LONG i;
 
             PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
             FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->ControllerFdo->DeviceExtension;
@@ -357,6 +362,12 @@ PdoDispatchPnp(
             /* Create the root hub */
             RootHubDevice = InternalCreateUsbDevice(1, 0, NULL, TRUE);
 
+            for (i = 0; i < 8; i++)
+            {
+                PdoDeviceExtension->Ports[i].PortStatus = USB_PORT_STATUS_ENABLE;
+                PdoDeviceExtension->Ports[i].PortChange = 0;
+            }
+
             RtlCopyMemory(&RootHubDevice->DeviceDescriptor,
                           ROOTHUB2_DEVICE_DESCRIPTOR,
                           sizeof(ROOTHUB2_DEVICE_DESCRIPTOR));
@@ -409,8 +420,16 @@ PdoDispatchPnp(
                     break;
                 }
                 case BusRelations:
+                    DPRINT1("BusRelations!!!!!\n");
                 case RemovalRelations:
                 case EjectionRelations:
+                {
+                    /* Ignore the request */
+                    Information = Irp->IoStatus.Information;
+                    Status = Irp->IoStatus.Status;
+                    break;
+
+                }
                 default:
                 {
                     DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unhandled type 0x%lx\n",
@@ -534,7 +553,8 @@ PdoDispatchPnp(
             else
             {
                 DPRINT1("Not Supported\n");
-                Status = STATUS_NOT_SUPPORTED;
+                Status = Irp->IoStatus.Status;
+                Information = Irp->IoStatus.Information;
             }
             break;
         }
index f4c440d..13bfabb 100644 (file)
@@ -75,6 +75,25 @@ OR with QUEUE_TRANSFER_DESCRIPTOR Token.SplitTransactionState */
 #define PING_STATE_DO_OUT              0x00
 #define PING_STATE_DO_PING             0x01
 
+#define C_HUB_LOCAL_POWER   0
+#define C_HUB_OVER_CURRENT  1
+#define PORT_CONNECTION     0
+#define PORT_ENABLE         1
+#define PORT_SUSPEND        2
+#define PORT_OVER_CURRENT   3
+#define PORT_RESET          4
+#define PORT_POWER          8
+#define PORT_LOW_SPEED      9
+#define PORT_HIGH_SPEED     9
+#define C_PORT_CONNECTION   16
+#define C_PORT_ENABLE       17
+#define C_PORT_SUSPEND      18
+#define C_PORT_OVER_CURRENT 19
+#define C_PORT_RESET        20
+#define PORT_TEST           21
+#define PORT_INDICATOR      22
+#define USB_PORT_STATUS_CHANGE 0x4000
+
 /* QUEUE ELEMENT TRANSFER DESCRIPTOR TOKEN */
 typedef struct _QETD_TOKEN_BITS
 {
@@ -273,16 +292,16 @@ typedef struct _EHCI_HCC_CONTENT
 } EHCI_HCC_CONTENT, *PEHCI_HCC_CONTENT;
 
 typedef struct _EHCI_CAPS {
-    UCHAR        Length;
-    UCHAR        Reserved;
-    USHORT        HCIVersion;
+    UCHAR Length;
+    UCHAR Reserved;
+    USHORT HCIVersion;
     union
     {
-        EHCI_HCS_CONTENT        HCSParams;
-        ULONG    HCSParamsLong;
+        EHCI_HCS_CONTENT HCSParams;
+        ULONG HCSParamsLong;
     };
-    ULONG        HCCParams;
-    UCHAR        PortRoute [8];
+    ULONG HCCParams;
+    UCHAR PortRoute [8];
 } EHCI_CAPS, *PEHCI_CAPS;
 
 typedef struct _COMMON_DEVICE_EXTENSION
@@ -292,6 +311,14 @@ typedef struct _COMMON_DEVICE_EXTENSION
     PDEVICE_OBJECT DeviceObject;
 } COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
 
+typedef struct _EHCIPORTS
+{
+    ULONG PortNumber;
+    ULONG PortType;
+    USHORT PortStatus;
+    USHORT PortChange;
+} EHCIPORTS, *PEHCIPORTS;
+
 typedef struct _FDO_DEVICE_EXTENSION
 {
     COMMON_DEVICE_EXTENSION Common;
@@ -333,8 +360,8 @@ typedef struct _FDO_DEVICE_EXTENSION
 
     PULONG PeriodicFramList;
     PULONG AsyncListQueueHeadPtr;
-    PHYSICAL_ADDRESS    PeriodicFramListPhysAddr;
-    PHYSICAL_ADDRESS    AsyncListQueueHeadPtrPhysAddr;
+    PHYSICAL_ADDRESS PeriodicFramListPhysAddr;
+    PHYSICAL_ADDRESS AsyncListQueueHeadPtrPhysAddr;
 
     BOOLEAN AsyncComplete;
 
@@ -356,6 +383,8 @@ typedef struct _PDO_DEVICE_EXTENSION
     BOOLEAN HaltUrbHandling;
     PVOID CallbackContext;
     PRH_INIT_CALLBACK CallbackRoutine;
+    ULONG NumberOfPorts;
+    EHCIPORTS Ports[32];
 } PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
 
 typedef struct _WORKITEM_DATA
index abedef8..7cea4c0 100644 (file)
@@ -5,7 +5,9 @@
        <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" />
index f9fe873..1efee79 100644 (file)
@@ -37,6 +37,13 @@ LIST_ENTRY HalpAcpiTableMatchList;
 
 ULONG HalpInvalidAcpiTable;
 
+ULONG HalpPicVectorRedirect[] = {0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15};
+
+/* This determines the HAL type */
+BOOLEAN HalDisableFirmwareMapper = TRUE;
+PWCHAR HalHardwareIdString = L"acpipic_up";
+PWCHAR HalName = L"ACPI Compatible Eisa/Isa HAL";
+
 /* PRIVATE FUNCTIONS **********************************************************/
 
 PDESCRIPTION_HEADER
@@ -861,4 +868,179 @@ HalpSetupAcpiPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
     return STATUS_SUCCESS;
 }
 
+VOID
+NTAPI
+HalpInitializePciBus(VOID)
+{
+    /* Setup the PCI stub support */
+    HalpInitializePciStubs();
+    
+    /* Set the NMI crash flag */
+    HalpGetNMICrashFlag();
+}
+
+VOID
+NTAPI
+HalpBuildAddressMap(VOID)
+{
+    /* ACPI is magic baby */
+}
+
+BOOLEAN
+NTAPI
+HalpGetDebugPortTable(VOID)
+{
+    return ((HalpDebugPortTable) &&
+            (HalpDebugPortTable->BaseAddress.AddressSpaceID == 1));
+}
+
+ULONG
+NTAPI
+HalpIs16BitPortDecodeSupported(VOID)
+{
+    /* All ACPI systems are at least "EISA" so they support this */
+    return CM_RESOURCE_PORT_16_BIT_DECODE;
+}
+
+VOID
+NTAPI
+HalpAcpiDetectResourceListSize(OUT PULONG ListSize)
+{
+    PAGED_CODE();
+    
+    /* One element if there is a SCI */
+    *ListSize = HalpFixedAcpiDescTable.sci_int_vector ? 1: 0;
+}
+
+NTSTATUS
+NTAPI
+HalpBuildAcpiResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceList)
+{
+    ULONG Interrupt;
+    PAGED_CODE();
+    ASSERT(ResourceList != NULL);
+
+    /* Initialize the list */
+    ResourceList->BusNumber = -1;
+    ResourceList->AlternativeLists = 1;
+    ResourceList->InterfaceType = PNPBus;
+    ResourceList->List[0].Version = 1;
+    ResourceList->List[0].Revision = 1;
+    
+    /* Is there a SCI? */
+    if (HalpFixedAcpiDescTable.sci_int_vector)
+    {
+        /* Fill out the entry for it */
+        ResourceList->List[0].Descriptors[0].Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+        ResourceList->List[0].Descriptors[0].Type = CmResourceTypeInterrupt;
+        ResourceList->List[0].Descriptors[0].ShareDisposition = CmResourceShareShared;
+        
+        /* Get the interrupt number */
+        Interrupt = HalpPicVectorRedirect[HalpFixedAcpiDescTable.sci_int_vector];
+        ResourceList->List[0].Descriptors[0].u.Interrupt.MinimumVector = Interrupt;
+        ResourceList->List[0].Descriptors[0].u.Interrupt.MaximumVector = Interrupt;
+        
+        /* One more */
+        ++ResourceList->List[0].Count;
+    }
+    
+    /* All good */
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+HalpQueryAcpiResourceRequirements(OUT PIO_RESOURCE_REQUIREMENTS_LIST *Requirements)
+{
+    PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
+    ULONG Count = 0, ListSize;
+    NTSTATUS Status;
+    PAGED_CODE();
+  
+    /* Get ACPI resources */
+    HalpAcpiDetectResourceListSize(&Count);
+    
+    /* Compute size of the list and allocate it */
+    ListSize = sizeof(IO_RESOURCE_LIST) * (Count - 1) +
+               sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
+    RequirementsList = ExAllocatePoolWithTag(PagedPool, ListSize, ' laH');
+    if (RequirementsList)
+    {
+        /* Initialize it */
+        RtlZeroMemory(RequirementsList, ListSize);
+        RequirementsList->ListSize = ListSize;
+        
+        /* Build it */
+        Status = HalpBuildAcpiResourceList(RequirementsList);
+        if (NT_SUCCESS(Status))
+        {
+            /* It worked, return it */
+            *Requirements = RequirementsList;
+        }
+        else
+        {
+            /* Fail */
+            ExFreePoolWithTag(RequirementsList, 0);
+            Status = STATUS_NO_SUCH_DEVICE;
+        }
+    }
+    else
+    {
+        /* Not enough memory */
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+    }
+    
+    /* Return the status */
+    return Status;
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+HalReportResourceUsage(VOID)
+{
+    INTERFACE_TYPE InterfaceType;
+    UNICODE_STRING HalString;
+
+    /* FIXME: Initialize DMA 64-bit support */
+
+    /* FIXME: Initialize MCA bus */
+
+    /* Initialize PCI bus. */
+    HalpInitializePciBus();
+
+    /* What kind of bus is this? */
+    switch (HalpBusType)
+    {
+        /* ISA Machine */
+        case MACHINE_TYPE_ISA:
+            InterfaceType = Isa;
+            break;
+
+        /* EISA Machine */
+        case MACHINE_TYPE_EISA:
+            InterfaceType = Eisa;
+            break;
+
+        /* MCA Machine */
+        case MACHINE_TYPE_MCA:
+            InterfaceType = MicroChannel;
+            break;
+
+        /* Unknown */
+        default:
+            InterfaceType = Internal;
+            break;
+    }
+
+    /* Build HAL usage */
+    RtlInitUnicodeString(&HalString, HalName);
+    HalpReportResourceUsage(&HalString, InterfaceType);
+
+    /* Setup PCI debugging and Hibernation */
+    HalpRegisterPciDebuggingDeviceInfo();
+}
+
 /* EOF */
index 81bed55..ca85188 100644 (file)
@@ -47,57 +47,9 @@ typedef struct _PDO_EXTENSION
 /* GLOBALS ********************************************************************/
 
 PDRIVER_OBJECT HalpDriverObject;
-BOOLEAN HalDisableFirmwareMapper = TRUE;
-PWCHAR HalHardwareIdString = L"acpipic_up";
 
 /* PRIVATE FUNCTIONS **********************************************************/
 
-NTSTATUS
-NTAPI
-HalpMarkAcpiHal(VOID)
-{
-    NTSTATUS Status;
-    UNICODE_STRING KeyString;
-    HANDLE KeyHandle;
-    HANDLE Handle;
-    
-    /* Open the control set key */
-    RtlInitUnicodeString(&KeyString,
-                         L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET");
-    Status = HalpOpenRegistryKey(&Handle, 0, &KeyString, KEY_ALL_ACCESS, FALSE);
-    if (NT_SUCCESS(Status))
-    {
-        /* Open the PNP key */
-        RtlInitUnicodeString(&KeyString, L"Control\\Pnp");
-        Status = HalpOpenRegistryKey(&KeyHandle,
-                                     Handle,
-                                     &KeyString,
-                                     KEY_ALL_ACCESS,
-                                     TRUE);
-        /* Close root key */
-        ZwClose(Handle);
-        
-        /* Check if PNP BIOS key exists */
-        if (NT_SUCCESS(Status))
-        {
-            /* Set the disable value to false -- we need the mapper */
-            RtlInitUnicodeString(&KeyString, L"DisableFirmwareMapper");
-            Status = ZwSetValueKey(KeyHandle,
-                                   &KeyString,
-                                   0,
-                                   REG_DWORD,
-                                   &HalDisableFirmwareMapper,
-                                   sizeof(HalDisableFirmwareMapper));
-            
-            /* Close subkey */
-            ZwClose(KeyHandle);
-        }
-    }
-    
-    /* Return status */
-    return Status;
-}
-
 NTSTATUS
 NTAPI
 HalpAddDevice(IN PDRIVER_OBJECT DriverObject,
@@ -379,9 +331,95 @@ NTAPI
 HalpQueryResources(IN PDEVICE_OBJECT DeviceObject,
                    OUT PCM_RESOURCE_LIST *Resources)
 {
-    UNIMPLEMENTED;
-    while (TRUE);
-    return STATUS_NO_SUCH_DEVICE;
+    PPDO_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+    NTSTATUS Status;
+    PCM_RESOURCE_LIST ResourceList;
+    PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
+    PIO_RESOURCE_DESCRIPTOR Descriptor;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDesc;
+    ULONG i;
+    PAGED_CODE();
+    
+    /* Only the ACPI PDO has requirements */
+    if (DeviceExtension->PdoType == AcpiPdo)
+    {
+        /* Query ACPI requirements */
+        Status = HalpQueryAcpiResourceRequirements(&RequirementsList);
+        ASSERT(RequirementsList->AlternativeLists == 1);
+        if (!NT_SUCCESS(Status)) return Status;
+        
+        /* Allocate the resourcel ist */
+        ResourceList = ExAllocatePoolWithTag(PagedPool,
+                                             sizeof(CM_RESOURCE_LIST),
+                                             ' laH');
+        if (!ResourceList )
+        {
+            /* Fail, no memory */
+            Status = STATUS_INSUFFICIENT_RESOURCES;
+            ExFreePoolWithTag(RequirementsList, 0);
+            return Status;
+        }
+        
+        /* Initialize it */
+        RtlZeroMemory(ResourceList, sizeof(CM_RESOURCE_LIST));
+        ResourceList->Count = 1;
+
+        /* Setup the list fields */
+        ResourceList->List[0].BusNumber = -1;
+        ResourceList->List[0].InterfaceType = PNPBus;
+        ResourceList->List[0].PartialResourceList.Version = 1;
+        ResourceList->List[0].PartialResourceList.Revision = 1;
+        ResourceList->List[0].PartialResourceList.Count = 1;
+
+        /* Setup the first descriptor */
+        PartialDesc = ResourceList->List[0].PartialResourceList.PartialDescriptors;
+        PartialDesc->Type = CmResourceTypeInterrupt;
+
+        /* Find the requirement descriptor for the SCI */
+        for (i = 0; i < RequirementsList->List[0].Count; i++)
+        {
+            /* Get this descriptor */
+            Descriptor = &RequirementsList->List[0].Descriptors[i];
+            if (Descriptor->Type == CmResourceTypeInterrupt) break;
+            Descriptor = NULL;
+        }
+        
+        /* Make sure we found the descriptor */
+        if (Descriptor)
+        { 
+            /* Copy requirements descriptor into resource descriptor */
+            PartialDesc->ShareDisposition = Descriptor->ShareDisposition;
+            PartialDesc->Flags = Descriptor->Flags;
+            ASSERT(Descriptor->u.Interrupt.MinimumVector ==
+                   Descriptor->u.Interrupt.MaximumVector);
+            PartialDesc->u.Interrupt.Vector = Descriptor->u.Interrupt.MinimumVector;
+            PartialDesc->u.Interrupt.Level = Descriptor->u.Interrupt.MinimumVector;
+            PartialDesc->u.Interrupt.Affinity = 0xFFFFFFFF;
+            
+            /* Return resources and success */
+            *Resources = ResourceList;
+            ExFreePoolWithTag(RequirementsList, 0);
+            return STATUS_SUCCESS;
+        }
+        
+        /* Free memory and fail */
+        ExFreePoolWithTag(RequirementsList, 0);
+        ExFreePoolWithTag(ResourceList, 0);
+        Status = STATUS_NOT_FOUND;
+    }
+    else if (DeviceExtension->PdoType == WdPdo)
+    {
+        /* Watchdog doesn't */
+        return STATUS_NOT_SUPPORTED;    
+    }
+    else
+    {
+        /* This shouldn't happen */
+        return STATUS_UNSUCCESSFUL;
+    }
+    
+    /* Return the status */
+    return Status;
 }
 
 NTSTATUS
@@ -389,9 +427,29 @@ NTAPI
 HalpQueryResourceRequirements(IN PDEVICE_OBJECT DeviceObject,
                               OUT PIO_RESOURCE_REQUIREMENTS_LIST *Requirements)
 {
-    UNIMPLEMENTED;
-    while (TRUE);
-    return STATUS_NO_SUCH_DEVICE;
+    PPDO_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+    NTSTATUS Status;
+    PAGED_CODE();
+    
+    /* Only the ACPI PDO has requirements */
+    if (DeviceExtension->PdoType == AcpiPdo)
+    {
+        /* Query ACPI requirements */
+        Status = HalpQueryAcpiResourceRequirements(Requirements);
+    }
+    else if (DeviceExtension->PdoType == WdPdo)
+    {
+        /* Watchdog doesn't */
+        return STATUS_NOT_SUPPORTED;    
+    }
+    else
+    {
+        /* This shouldn't happen */
+        return STATUS_UNSUCCESSFUL;
+    }
+    
+    /* Return the status */
+    return Status;
 }
 
 NTSTATUS
index 50f1add..2440cd4 100644 (file)
@@ -14,6 +14,8 @@
 
 /* GLOBALS *******************************************************************/
 
+PCI_TYPE1_CFG_CYCLE_BITS HalpPciDebuggingDevice[2] = {{{{0}}}};
+
 BOOLEAN HalpPCIConfigInitialized;
 ULONG HalpMinPciBus, HalpMaxPciBus;
 KSPIN_LOCK HalpPCIConfigLock;
@@ -521,6 +523,34 @@ HalpReleasePciDeviceForDebugging(IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice)
     return STATUS_NOT_IMPLEMENTED;
 }
 
+VOID
+NTAPI
+HalpRegisterPciDebuggingDeviceInfo(VOID)
+{
+    BOOLEAN Found = FALSE;
+    ULONG i;
+    PAGED_CODE();
+
+    /* Loop PCI debugging devices */
+    for (i = 0; i < 2; i++)
+    {
+        /* Reserved bit is set if we found one */
+        if (HalpPciDebuggingDevice[i].u.bits.Reserved1)
+        {
+            Found = TRUE;
+            break;
+        }
+    }
+
+    /* Bail out if there aren't any */
+    if (!Found) return;
+    
+    /* FIXME: TODO */
+    DPRINT1("You have implemented the KD routines for searching PCI debugger"
+            "devices, but you have forgotten to implement this routine\n");
+    while (TRUE);
+}
+
 static ULONG NTAPI
 PciSize(ULONG Base, ULONG Mask)
 {
@@ -1026,9 +1056,3 @@ HalpInitializePciStubs(VOID)
     HalpPCIConfigInitialized = TRUE;
 }
 
-VOID
-NTAPI
-HalpInitializePciBus(VOID)
-{
-    /* FIXME: Initialize NMI Crash Flag */
-}
index bbabb9c..ea16403 100644 (file)
 
 /* GLOBALS ********************************************************************/
 
+/* This determines the HAL type */
+BOOLEAN HalDisableFirmwareMapper = FALSE;
+PWCHAR HalHardwareIdString = L"e_isa_up";
+PWCHAR HalName = L"PC Compatible Eisa/Isa HAL";
+
 /* PRIVATE FUNCTIONS **********************************************************/
 
 NTSTATUS
@@ -24,4 +29,94 @@ HalpSetupAcpiPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
     return STATUS_NO_SUCH_DEVICE;
 }
 
+VOID
+NTAPI
+HalpInitializePciBus(VOID)
+{
+    /* FIXME: Should do legacy PCI bus detection */
+    
+    /* FIXME: Should detect chipset hacks */
+    
+    /* FIXME: Should detect broken PCI hardware and apply hacks */
+    
+    /* FIXME: Should build resource ranges */
+}
+
+VOID
+NTAPI
+HalpBuildAddressMap(VOID)
+{
+    /* FIXME: Inherit ROM blocks from the registry */
+    //HalpInheritROMBlocks();
+    
+    /* FIXME: Add the ROM blocks to our ranges */
+    //HalpAddROMRanges();
+}
+
+BOOLEAN
+NTAPI
+HalpGetDebugPortTable(VOID)
+{
+    /* No ACPI */
+    return FALSE;
+}
+
+ULONG
+NTAPI
+HalpIs16BitPortDecodeSupported(VOID)
+{
+    /* Only EISA systems support this */
+    return (HalpBusType == MACHINE_TYPE_EISA) ? CM_RESOURCE_PORT_16_BIT_DECODE : 0;
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+HalReportResourceUsage(VOID)
+{
+    INTERFACE_TYPE InterfaceType;
+    UNICODE_STRING HalString;
+
+    /* FIXME: Initialize MCA bus */
+
+    /* Initialize PCI bus. */
+    HalpInitializePciBus();
+
+    /* Initialize the stubs */
+    HalpInitializePciStubs();
+
+    /* What kind of bus is this? */
+    switch (HalpBusType)
+    {
+        /* ISA Machine */
+        case MACHINE_TYPE_ISA:
+            InterfaceType = Isa;
+            break;
+
+        /* EISA Machine */
+        case MACHINE_TYPE_EISA:
+            InterfaceType = Eisa;
+            break;
+
+        /* MCA Machine */
+        case MACHINE_TYPE_MCA:
+            InterfaceType = MicroChannel;
+            break;
+
+        /* Unknown */
+        default:
+            InterfaceType = Internal;
+            break;
+    }
+
+    /* Build HAL usage */
+    RtlInitUnicodeString(&HalString, HalName);
+    HalpReportResourceUsage(&HalString, InterfaceType);
+
+    /* Setup PCI debugging and Hibernation */
+    HalpRegisterPciDebuggingDeviceInfo();
+}
+
 /* EOF */
index 3e4d0c9..f138e5f 100644 (file)
 
 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,
index d35a3e3..02c86e2 100644 (file)
 
 /* GLOBALS ********************************************************************/
 
+BOOLEAN HalpGetInfoFromACPI;
+BOOLEAN HalpNMIDumpFlag;
 PUCHAR KdComPortInUse;
 PADDRESS_USAGE HalpAddressUsageList;
 IDTUsageFlags HalpIDTUsageFlags[MAXIMUM_IDTVECTOR];
 IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
 
+USHORT HalpComPortIrqMapping[5][2] =
+{
+    {0x3F8, 4},
+    {0x2F8, 3},
+    {0x3E8, 4},
+    {0x2E8, 3},
+    {0, 0}
+};
+
+ADDRESS_USAGE HalpComIoSpace =
+{
+    NULL, CmResourceTypePort, IDT_INTERNAL,
+    {
+        {0x2F8,   0x8},     /* COM 1 */
+        {0,0},
+    }
+};
+
 ADDRESS_USAGE HalpDefaultIoSpace =
 {
     NULL, CmResourceTypePort, IDT_INTERNAL,
     {
-        {0x2000,  0xC000}, /* PIC?? */
+        {0x2000,  0xC000}, /* Everything */
         {0xC000,  0x1000}, /* DMA 2 */
         {0x8000,  0x1000}, /* DMA 1 */
         {0x2000,  0x200},  /* PIC 1 */
         {0xA000,  0x200},  /* PIC 2 */
         {0x4000,  0x400},  /* PIT 1 */
         {0x4800,  0x400},  /* PIT 2 */
-        {0x9200,  0x100},  /* ????? */
+        {0x9200,  0x100},  /* System Control Port A */
         {0x7000,  0x200},  /* CMOS  */
-        {0xF000,  0x1000}, /* ????? */
+        {0xF000,  0x1000}, /* x87 Coprocessor */
         {0xCF800, 0x800},  /* PCI 0 */
         {0,0},
     }
@@ -40,13 +60,429 @@ ADDRESS_USAGE HalpDefaultIoSpace =
 
 /* FUNCTIONS ******************************************************************/
 
+#ifndef _MINIHAL_
+VOID
+NTAPI
+HalpGetResourceSortValue(IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
+                         OUT PULONG Scale,
+                         OUT PLARGE_INTEGER Value)
+{
+    /* Sorting depends on resource type */
+    switch (Descriptor->Type)
+    {
+        case CmResourceTypeInterrupt:
+            
+            /* Interrupt goes by level */
+            *Scale = 0;
+            *Value = RtlConvertUlongToLargeInteger(Descriptor->u.Interrupt.Level);
+            break;
+            
+        case CmResourceTypePort:
+            
+            /* Port goes by port address */
+            *Scale = 1;
+            *Value = Descriptor->u.Port.Start;
+            break;
+            
+        case CmResourceTypeMemory:
+            
+            /* Memory goes by base address */
+            *Scale = 2;
+            *Value = Descriptor->u.Memory.Start;
+            break;
+            
+        default:
+            
+            /* Anything else */
+            *Scale = 4;
+            *Value = RtlConvertUlongToLargeInteger(0);
+            break;
+    }
+}
+
+VOID
+NTAPI
+HalpBuildPartialFromIdt(IN ULONG Entry,
+                        IN PCM_PARTIAL_RESOURCE_DESCRIPTOR RawDescriptor,
+                        IN PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedDescriptor)
+{
+    /* Exclusive interrupt entry */
+    RawDescriptor->Type = CmResourceTypeInterrupt;
+    RawDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
+    
+    /* Check the interrupt type */
+    if (HalpIDTUsageFlags[Entry].Flags & IDT_LATCHED)
+    {
+        /* Latched */
+        RawDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
+    }
+    else
+    {
+        /* Level */
+        RawDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+    }
+
+    /* Get vector and level from IDT usage */
+    RawDescriptor->u.Interrupt.Vector = HalpIDTUsage[Entry].BusReleativeVector;
+    RawDescriptor->u.Interrupt.Level = HalpIDTUsage[Entry].BusReleativeVector;
+    
+    /* Affinity is all the CPUs */
+    RawDescriptor->u.Interrupt.Affinity = HalpActiveProcessors;
+    
+    /* The translated copy is identical */
+    RtlCopyMemory(TranslatedDescriptor, RawDescriptor, sizeof(TranslatedDescriptor));
+    
+    /* But the vector and IRQL must be set correctly */
+    TranslatedDescriptor->u.Interrupt.Vector = Entry;
+    TranslatedDescriptor->u.Interrupt.Level = HalpIDTUsage[Entry].Irql;
+}
+
+VOID
+NTAPI
+HalpBuildPartialFromAddress(IN INTERFACE_TYPE Interface,
+                            IN PADDRESS_USAGE CurrentAddress,
+                            IN ULONG Element,
+                            IN PCM_PARTIAL_RESOURCE_DESCRIPTOR RawDescriptor,
+                            IN PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedDescriptor)
+{
+    ULONG AddressSpace;
+    
+    /* Set the type and make it exclusive */
+    RawDescriptor->Type = CurrentAddress->Type;
+    RawDescriptor->ShareDisposition = CmResourceShareDriverExclusive;
+    
+    /* Check what this is */
+    if (RawDescriptor->Type == CmResourceTypePort)
+    {
+        /* Write out port data */
+        AddressSpace = 1;
+        RawDescriptor->Flags = CM_RESOURCE_PORT_IO;
+        RawDescriptor->u.Port.Start.HighPart = 0;
+        RawDescriptor->u.Port.Start.LowPart = CurrentAddress->Element[Element].Start;
+        RawDescriptor->u.Port.Length = CurrentAddress->Element[Element].Length;
+        
+        /* Determine if 16-bit port addresses are allowed */
+        RawDescriptor->Flags |= HalpIs16BitPortDecodeSupported();
+    }
+    else
+    {
+        /* Write out memory data */
+        AddressSpace = 0;
+        RawDescriptor->Flags = (CurrentAddress->Flags & IDT_READ_ONLY) ?
+                                CM_RESOURCE_MEMORY_READ_ONLY :
+                                CM_RESOURCE_MEMORY_READ_WRITE;
+        RawDescriptor->u.Memory.Start.HighPart = 0;
+        RawDescriptor->u.Memory.Start.LowPart = CurrentAddress->Element[Element].Start;
+        RawDescriptor->u.Memory.Length = CurrentAddress->Element[Element].Length;
+    }
+    
+    /* Make an identical copy to begin with */
+    RtlCopyMemory(TranslatedDescriptor, RawDescriptor, sizeof(TranslatedDescriptor));
+    
+    /* Check what this is */
+    if (RawDescriptor->Type == CmResourceTypePort)
+    {
+        /* Translate the port */
+        HalTranslateBusAddress(Interface,
+                               0,
+                               RawDescriptor->u.Port.Start,
+                               &AddressSpace,
+                               &TranslatedDescriptor->u.Port.Start);
+        
+        /* If it turns out this is memory once translated, flag it */
+        if (AddressSpace == 0) TranslatedDescriptor->Flags = CM_RESOURCE_PORT_MEMORY;
+
+    }
+    else
+    {
+        /* Translate the memory */
+        HalTranslateBusAddress(Interface,
+                               0,
+                               RawDescriptor->u.Memory.Start,
+                               &AddressSpace,
+                               &TranslatedDescriptor->u.Memory.Start);
+    }
+}
+
 VOID
 NTAPI
 HalpReportResourceUsage(IN PUNICODE_STRING HalName,
                         IN INTERFACE_TYPE InterfaceType)
 {
-    DbgPrint("%wZ has been initialized\n", HalName);
+    PCM_RESOURCE_LIST RawList, TranslatedList;
+    PCM_FULL_RESOURCE_DESCRIPTOR RawFull, TranslatedFull;
+    PCM_PARTIAL_RESOURCE_DESCRIPTOR CurrentRaw, CurrentTranslated, SortedRaw, SortedTranslated;
+    CM_PARTIAL_RESOURCE_DESCRIPTOR RawPartial, TranslatedPartial;
+    PCM_PARTIAL_RESOURCE_LIST RawPartialList = NULL, TranslatedPartialList = NULL;
+    INTERFACE_TYPE Interface;
+    ULONG i, j, k, ListSize, Count, Port, Element, CurrentScale, SortScale, ReportType, FlagMatch;
+    ADDRESS_USAGE *CurrentAddress;
+    LARGE_INTEGER CurrentSortValue, SortValue;
+    DbgPrint("%wZ Detected\n", HalName);
+    
+    /* Check if KD is using a COM port */
+    if (KdComPortInUse)
+    {
+        /* Enter it into the I/O space */
+        HalpComIoSpace.Element[0].Start = (ULONG_PTR)KdComPortInUse;
+        HalpComIoSpace.Next = HalpAddressUsageList;
+        HalpAddressUsageList = &HalpComIoSpace;
+        
+        /* Use the debug port table if we have one */
+        HalpGetInfoFromACPI = HalpGetDebugPortTable();
+        
+        /* Check if we're using ACPI */
+        if (!HalpGetInfoFromACPI)
+        {
+            /* No, so use our local table */
+            Port = HalpComPortIrqMapping[0][0];
+            for (i = 0; Port; i++)
+            {
+                /* Is this the port we want? */
+                if (Port == (ULONG_PTR)KdComPortInUse)
+                {
+                    /* Register it */
+                    HalpRegisterVector(IDT_DEVICE | IDT_LATCHED,
+                                       HalpComPortIrqMapping[i][1],
+                                       HalpComPortIrqMapping[i][1] +
+                                       PRIMARY_VECTOR_BASE,
+                                       HIGH_LEVEL);
+                }
+                
+                /* Next port */
+                Port = HalpComPortIrqMapping[i][0];
+            }
+        }
+    }
+    
+    /* On non-ACPI systems, we need to build an address map */
+    HalpBuildAddressMap();
+    
+    /* Allocate the master raw and translated lists */
+    RawList = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE * 2, ' laH');
+    TranslatedList = ExAllocatePoolWithTag(NonPagedPool, PAGE_SIZE * 2, ' laH');
+    if (!(RawList) || !(TranslatedList))
+    {
+        /* Bugcheck the system */
+        KeBugCheckEx(HAL_MEMORY_ALLOCATION,
+                     4 * PAGE_SIZE,
+                     1,
+                     (ULONG_PTR)__FILE__,
+                     __LINE__);
+    }
+    
+    /* Zero out the lists */
+    RtlZeroMemory(RawList, PAGE_SIZE * 2);
+    RtlZeroMemory(TranslatedList, PAGE_SIZE * 2);
+
+    /* Set the interface type to begin with */
+    RawList->List[0].InterfaceType = InterfaceTypeUndefined;
+    
+    /* Loop all IDT entries that are not IRQs */
+    for (i = 0; i < PRIMARY_VECTOR_BASE; i++)
+    {
+        /* Check if the IDT isn't owned */
+        if (!(HalpIDTUsageFlags[i].Flags & IDT_REGISTERED))
+        {
+            /* Then register it for internal usage */
+            HalpIDTUsageFlags[i].Flags = IDT_INTERNAL;
+            HalpIDTUsage[i].BusReleativeVector = i;
+        }
+    }
+    
+    /* Our full raw descriptors start here */
+    RawFull = RawList->List;
+    
+    /* Keep track of the current partial raw and translated descriptors */
+    CurrentRaw = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)RawList->List;
+    CurrentTranslated = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)TranslatedList->List;
+    
+    /* Do two passes */
+    for (ReportType = 0; ReportType < 2; ReportType++)
+    {
+        /* Pass 0 is for device usage */
+        if (ReportType == 0)
+        {           
+            FlagMatch = IDT_DEVICE & ~IDT_REGISTERED;
+            Interface = InterfaceType;
+        }
+        else
+        {
+            /* Past 1 is for internal HAL usage */
+            FlagMatch = IDT_INTERNAL & ~IDT_REGISTERED;
+            Interface = Internal;
+        }
+        
+        /* Reset loop variables */
+        i = Element = 0;
+        
+        /* Start looping our address uage list and interrupts */
+        CurrentAddress = HalpAddressUsageList;
+        while (TRUE)
+        {
+            /* Check for valid vector number */
+            if (i <= MAXIMUM_IDTVECTOR)
+            {
+                /* Check if this entry should be parsed */
+                if ((HalpIDTUsageFlags[i].Flags & FlagMatch))
+                {
+                    /* Parse it */
+                    HalpBuildPartialFromIdt(i, &RawPartial, &TranslatedPartial);
+                    i++;
+                }
+                else
+                {
+                    /* Skip this entry */
+                    i++;
+                    continue;
+                }
+            }
+            else
+            {
+                /* This is an address instead */
+                if (!CurrentAddress) break;
+                
+                /* Check if the address should be reported */
+                if (!(CurrentAddress->Flags & FlagMatch) ||
+                    !(CurrentAddress->Element[Element].Length))
+                {
+                    /* Nope, skip it */
+                    Element = 0;
+                    CurrentAddress = CurrentAddress->Next;
+                    continue;
+                }
+                
+                /* Otherwise, parse the entry */
+                HalpBuildPartialFromAddress(Interface,
+                                            CurrentAddress,
+                                            Element,
+                                            &RawPartial,
+                                            &TranslatedPartial);
+                Element++;
+            }
+            
+            /* Check for interface change */
+            if (RawFull->InterfaceType != Interface)
+            {
+                /* We need to add another full descriptor */
+                RawList->Count++;
+                TranslatedList->Count++;
+
+                /* The full descriptor follows wherever we were */
+                RawFull = (PCM_FULL_RESOURCE_DESCRIPTOR)CurrentRaw;
+                TranslatedFull = (PCM_FULL_RESOURCE_DESCRIPTOR)CurrentTranslated;
+                
+                /* And it is of this new interface type */
+                RawFull->InterfaceType = Interface;
+                TranslatedFull->InterfaceType = Interface;
+                
+                /* And its partial descriptors begin here */
+                RawPartialList = &RawFull->PartialResourceList;
+                TranslatedPartialList = &TranslatedFull->PartialResourceList;
+                
+                /* And our next full descriptor should follow here */
+                CurrentRaw = RawFull->PartialResourceList.PartialDescriptors;
+                CurrentTranslated = TranslatedFull->PartialResourceList.PartialDescriptors;
+            }
+            
+            /* We have written a new partial descriptor */
+            RawPartialList->Count++;
+            TranslatedPartialList->Count++;
+            
+            /* Copy our local descriptors into the actual list */
+            RtlCopyMemory(CurrentRaw, &RawPartial, sizeof(RawPartial));
+            RtlCopyMemory(CurrentTranslated, &TranslatedPartial, sizeof(TranslatedPartial));
+            
+            /* Move to the next partial descriptor */
+            CurrentRaw++;
+            CurrentTranslated++;
+        }
+    }
+    
+    /* Get the final list of the size for the kernel call later */
+    ListSize = (ULONG_PTR)CurrentRaw - (ULONG_PTR)RawList;
+    
+    /* Now reset back to the first full descriptor */
+    RawFull = RawList->List;
+    TranslatedFull = TranslatedList->List;
+    
+    /* And loop all the full descriptors */
+    for (i = 0; i < RawList->Count; i++)
+    {
+        /* Get the first partial descriptor in this list */
+        CurrentRaw = RawFull->PartialResourceList.PartialDescriptors;
+        CurrentTranslated = TranslatedFull->PartialResourceList.PartialDescriptors;
+        
+        /* Get the count of partials in this list */
+        Count = RawFull->PartialResourceList.Count;
+        
+        /* Loop all the partials in this list */
+        for (j = 0; j < Count; j++)
+        {
+            /* Get the sort value at this point */
+            HalpGetResourceSortValue(CurrentRaw, &CurrentScale, &CurrentSortValue);
+            
+            /* Save the current sort pointer */
+            SortedRaw = CurrentRaw;
+            SortedTranslated = CurrentTranslated;
+            
+            /* Loop all descriptors starting from this one */
+            for (k = j; k < Count; k++)
+            {
+                /* Get the sort value at the sort point */
+                HalpGetResourceSortValue(SortedRaw, &SortScale, &SortValue);
+                
+                /* Check if a swap needs to occur */
+                if ((SortScale < CurrentScale) ||
+                    ((SortScale == CurrentScale) &&
+                     (SortValue.QuadPart <= CurrentSortValue.QuadPart)))
+                {
+                    /* Swap raw partial with the sort location partial */
+                    RtlCopyMemory(&RawPartial, CurrentRaw, sizeof(RawPartial));
+                    RtlCopyMemory(CurrentRaw, SortedRaw, sizeof(RawPartial));
+                    RtlCopyMemory(SortedRaw, &RawPartial, sizeof(RawPartial));
+                    
+                    /* Swap translated partial in the same way */
+                    RtlCopyMemory(&TranslatedPartial, CurrentTranslated, sizeof(TranslatedPartial));
+                    RtlCopyMemory(CurrentTranslated, SortedTranslated, sizeof(TranslatedPartial));
+                    RtlCopyMemory(SortedTranslated, &TranslatedPartial, sizeof(TranslatedPartial));
+                    
+                    /* Update the sort value at this point */
+                    HalpGetResourceSortValue(CurrentRaw, &CurrentScale, &CurrentSortValue);
+                }
+                
+                /* The sort location has been updated */
+                SortedRaw++;
+                SortedTranslated++;
+            }
+            
+            /* Move to the next partial */
+            CurrentRaw++;
+            CurrentTranslated++;
+        }
+        
+        /* Move to the next full descriptor */
+        RawFull = (PCM_FULL_RESOURCE_DESCRIPTOR)CurrentRaw;
+        TranslatedFull = (PCM_FULL_RESOURCE_DESCRIPTOR)CurrentTranslated;
+    }
+    
+    /* Mark this is an ACPI system, if it is */
+    HalpMarkAcpiHal();
+    
+    /* Tell the kernel about all this */
+    IoReportHalResourceUsage(HalName,
+                             RawList,
+                             TranslatedList,
+                             ListSize);
+    
+    /* Free our lists */
+    ExFreePool(RawList);
+    ExFreePool(TranslatedList);
+    
+    /* Get the machine's serial number */
+    HalpReportSerialNumber();
 }
+#endif
 
 VOID
 NTAPI
@@ -88,55 +524,56 @@ HalpEnableInterruptHandler(IN UCHAR Flags,
     /* Enable the interrupt */
     HalEnableSystemInterrupt(SystemVector, Irql, Mode);
 }
-#endif
 
-/*
- * @unimplemented
- */
 VOID
 NTAPI
-HalReportResourceUsage(VOID)
+HalpGetNMICrashFlag(VOID)
 {
-    INTERFACE_TYPE InterfaceType;
-    UNICODE_STRING HalString;
-
-    /* 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 */
-}
index b551cc3..17ffea9 100644 (file)
@@ -8,7 +8,8 @@
                <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>
index dccd161..166bb93 100644 (file)
@@ -1,65 +1,12 @@
 <?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>
diff --git a/hal/halx86/hal_generic_acpi.rbuild b/hal/halx86/hal_generic_acpi.rbuild
new file mode 100644 (file)
index 0000000..3784394
--- /dev/null
@@ -0,0 +1,16 @@
+<?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>
diff --git a/hal/halx86/hal_generic_pcat.rbuild b/hal/halx86/hal_generic_pcat.rbuild
new file mode 100644 (file)
index 0000000..e00ed5b
--- /dev/null
@@ -0,0 +1,15 @@
+<?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>
index 7d22a84..d380cf6 100644 (file)
@@ -8,6 +8,7 @@
                <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>
index 6b52fde..0b60f76 100644 (file)
@@ -10,6 +10,7 @@
        <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>
index 2570cb8..d76c49f 100644 (file)
@@ -9,7 +9,8 @@
                <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>
index 54423ab..ad13545 100644 (file)
@@ -8,7 +8,8 @@
                <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>
index 3e07190..0384022 100644 (file)
@@ -158,6 +158,38 @@ typedef struct _PCI_REGISTRY_INFO_INTERNAL
     PCI_CARD_DESCRIPTOR CardList[ANYSIZE_ARRAY];
 } PCI_REGISTRY_INFO_INTERNAL, *PPCI_REGISTRY_INFO_INTERNAL;
 
+typedef struct _PCI_TYPE0_CFG_CYCLE_BITS
+{
+    union
+    {
+        struct
+        {
+            ULONG Reserved1:2;
+            ULONG RegisterNumber:6;
+            ULONG FunctionNumber:3;
+            ULONG Reserved2:21;
+        } bits;
+        ULONG AsULONG;
+    } u;
+} PCI_TYPE0_CFG_CYCLE_BITS, *PPCI_TYPE0_CFG_CYCLE_BITS;
+
+typedef struct _PCI_TYPE1_CFG_CYCLE_BITS
+{
+    union
+    {
+        struct
+        {
+            ULONG Reserved1:2;
+            ULONG RegisterNumber:6;
+            ULONG FunctionNumber:3;
+            ULONG DeviceNumber:5;
+            ULONG BusNumber:8;
+            ULONG Reserved2:8;
+        } bits;
+        ULONG AsULONG;
+    } u;
+} PCI_TYPE1_CFG_CYCLE_BITS, *PPCI_TYPE1_CFG_CYCLE_BITS;
+
 typedef struct _ARRAY
 {
     ULONG ArraySize;
@@ -359,6 +391,12 @@ HalpFindBusAddressTranslation(
     IN BOOLEAN NextBus
 );
 
+VOID
+NTAPI
+HalpRegisterPciDebuggingDeviceInfo(
+    VOID
+);
+
 extern ULONG HalpBusType;
 extern BOOLEAN HalpPCIConfigInitialized;
 extern BUS_HANDLER HalpFakePciBusHandler;
index 44b81a0..6edb855 100644 (file)
@@ -49,6 +49,7 @@ DECLSPEC_NORETURN
 /* Usage flags */
 #define IDT_REGISTERED          0x01
 #define IDT_LATCHED             0x02
+#define IDT_READ_ONLY           0x04
 #define IDT_INTERNAL            0x11
 #define IDT_DEVICE              0x21
 
@@ -707,6 +708,55 @@ HalpOpenRegistryKey(
     IN BOOLEAN Create
 );
 
+VOID
+NTAPI
+HalpGetNMICrashFlag(
+    VOID
+);
+
+BOOLEAN
+NTAPI
+HalpGetDebugPortTable(
+    VOID
+);
+
+VOID
+NTAPI
+HalpReportSerialNumber(
+    VOID
+);
+
+NTSTATUS
+NTAPI
+HalpMarkAcpiHal(
+    VOID
+);
+
+VOID
+NTAPI
+HalpBuildAddressMap(
+    VOID
+);
+
+VOID
+NTAPI
+HalpReportResourceUsage(
+    IN PUNICODE_STRING HalName,
+    IN INTERFACE_TYPE InterfaceType
+);
+
+ULONG
+NTAPI
+HalpIs16BitPortDecodeSupported(
+    VOID
+);
+
+NTSTATUS
+NTAPI
+HalpQueryAcpiResourceRequirements(
+    OUT PIO_RESOURCE_REQUIREMENTS_LIST *Requirements
+);
+
 VOID
 FASTCALL
 KeUpdateSystemTime(
@@ -735,3 +785,9 @@ extern KSPIN_LOCK HalpSystemHardwareLock;
 extern PADDRESS_USAGE HalpAddressUsageList;
 
 extern LARGE_INTEGER HalpPerfCounter;
+
+extern KAFFINITY HalpActiveProcessors;
+
+extern BOOLEAN HalDisableFirmwareMapper;
+extern PWCHAR HalHardwareIdString;
+extern PWCHAR HalName;
index 126bccb..069a96b 100644 (file)
@@ -18,6 +18,8 @@
 #define NDEBUG
 #include <debug.h>
 
+KAFFINITY HalpActiveProcessors;
 /* PRIVATE FUNCTIONS *********************************************************/
 
 VOID
index 662514b..2e92a2c 100644 (file)
@@ -12,7 +12,7 @@
 #define NDEBUG
 #include <debug.h>
 
-LONG HalpActiveProcessors;
+KAFFINITY HalpActiveProcessors;
 KAFFINITY HalpDefaultInterruptAffinity;
 
 /* PRIVATE FUNCTIONS *********************************************************/
@@ -41,7 +41,7 @@ HalInitializeProcessor(IN ULONG ProcessorNumber,
     KeGetPcr()->StallScaleFactor = INITIAL_STALL_COUNT;
 
     /* Update the interrupt affinity and processor mask */
-    InterlockedBitTestAndSet(&HalpActiveProcessors, ProcessorNumber);
+    InterlockedBitTestAndSet((PLONG)&HalpActiveProcessors, ProcessorNumber);
     InterlockedBitTestAndSet((PLONG)&HalpDefaultInterruptAffinity,
                              ProcessorNumber);
 
index f728bfb..e66f130 100644 (file)
@@ -744,6 +744,99 @@ typedef enum
     KSPROPERTY_STREAM_PIPE_ID
 } KSPROPERTY_STREAM;
 
+#define DEFINE_KSPROPERTY_ITEM_STREAM_ALLOCATOR(GetHandler, SetHandler)\
+    DEFINE_KSPROPERTY_ITEM(\
+        KSPROPERTY_STREAM_ALLOCATOR,\
+        (GetHandler),\
+        sizeof(KSPROPERTY),\
+        sizeof(HANDLE),\
+        (SetHandler),\
+        NULL, 0, NULL, NULL, 0)
+
+#define DEFINE_KSPROPERTY_ITEM_STREAM_QUALITY(Handler)\
+    DEFINE_KSPROPERTY_ITEM(\
+        KSPROPERTY_STREAM_QUALITY,\
+        (Handler),\
+        sizeof(KSPROPERTY),\
+        sizeof(KSQUALITY_MANAGER),\
+        NULL, NULL, 0, NULL, NULL, 0)
+
+#define DEFINE_KSPROPERTY_ITEM_STREAM_DEGRADATION(GetHandler, SetHandler)\
+    DEFINE_KSPROPERTY_ITEM(\
+        KSPROPERTY_STREAM_DEGRADATION,\
+        (GetHandler),\
+        sizeof(KSPROPERTY),\
+        0,\
+        (SetHandler),\
+        NULL, 0, NULL, NULL, 0)
+
+#define DEFINE_KSPROPERTY_ITEM_STREAM_MASTERCLOCK(GetHandler, SetHandler)\
+    DEFINE_KSPROPERTY_ITEM(\
+        KSPROPERTY_STREAM_MASTERCLOCK,\
+        (GetHandler),\
+        sizeof(KSPROPERTY),\
+        sizeof(HANDLE),\
+        (SetHandler),\
+        NULL, 0, NULL, NULL, 0)
+
+#define DEFINE_KSPROPERTY_ITEM_STREAM_TIMEFORMAT(Handler)\
+    DEFINE_KSPROPERTY_ITEM(\
+        KSPROPERTY_STREAM_TIMEFORMAT,\
+        (Handler),\
+        sizeof(KSPROPERTY),\
+        sizeof(GUID),\
+        NULL, NULL, 0, NULL, NULL, 0)
+
+#define DEFINE_KSPROPERTY_ITEM_STREAM_PRESENTATIONTIME(GetHandler, SetHandler)\
+    DEFINE_KSPROPERTY_ITEM(\
+        KSPROPERTY_STREAM_PRESENTATIONTIME,\
+        (GetHandler),\
+        sizeof(KSPROPERTY),\
+        sizeof(KSTIME),\
+        (SetHandler),\
+        NULL, 0, NULL, NULL, 0)
+
+#define DEFINE_KSPROPERTY_ITEM_STREAM_PRESENTATIONEXTENT(Handler)\
+    DEFINE_KSPROPERTY_ITEM(\
+        KSPROPERTY_STREAM_PRESENTATIONEXTENT,\
+        (Handler),\
+        sizeof(KSPROPERTY),\
+        sizeof(LONGLONG),\
+        NULL, NULL, 0, NULL, NULL, 0)
+
+#define DEFINE_KSPROPERTY_ITEM_STREAM_FRAMETIME(Handler)\
+    DEFINE_KSPROPERTY_ITEM(\
+        KSPROPERTY_STREAM_FRAMETIME,\
+        (Handler),\
+        sizeof(KSPROPERTY),\
+        sizeof(KSFRAMETIME),\
+        NULL, NULL, 0, NULL, NULL, 0)
+
+#define DEFINE_KSPROPERTY_ITEM_STREAM_RATECAPABILITY(Handler)\
+    DEFINE_KSPROPERTY_ITEM(\
+        KSPROPERTY_STREAM_RATECAPABILITY,\
+        (Handler),\
+        sizeof(KSRATE_CAPABILITY),\
+        sizeof(KSRATE),\
+        NULL, NULL, 0, NULL, NULL, 0)
+
+#define DEFINE_KSPROPERTY_ITEM_STREAM_RATE(GetHandler, SetHandler)\
+    DEFINE_KSPROPERTY_ITEM(\
+        KSPROPERTY_STREAM_RATE,\
+        (GetHandler),\
+        sizeof(KSPROPERTY),\
+        sizeof(KSRATE),\
+        (SetHandler),\
+        NULL, 0, NULL, NULL, 0)
+
+#define DEFINE_KSPROPERTY_ITEM_STREAM_PIPE_ID(GetHandler, SetHandler)\
+    DEFINE_KSPROPERTY_ITEM(\
+        KSPROPERTY_STREAM_PIPE_ID,\
+        (GetHandler),\
+        sizeof(KSPROPERTY),\
+        sizeof(HANDLE),\
+        (SetHandler),\
+        NULL, 0, NULL, NULL, 0)
 
 /* ===============================================================
     StreamAllocator
index 2e710ca..1aedf76 100644 (file)
@@ -523,10 +523,7 @@ typedef struct _GDIBSEXTSELCLPRGN
 {
   GDIBATCHHDR gbHdr;
   int fnMode;
-  LONG right;
-  LONG bottom;
-  LONG left;
-  LONG top;
+  RECTL;
 } GDIBSEXTSELCLPRGN, *PGDIBSEXTSELCLPRGN;
 //
 //   Use with GdiBCSelObj, GdiBCDelObj and GdiBCDelRgn.
index fae0495..c6823b0 100644 (file)
@@ -198,6 +198,22 @@ typedef struct _CMHIVE
 
 #endif
 
+typedef struct _HV_HIVE_CELL_PAIR
+{
+    PHHIVE Hive;
+    HCELL_INDEX Cell;
+} HV_HIVE_CELL_PAIR, *PHV_HIVE_CELL_PAIR;
+
+#define STATIC_CELL_PAIR_COUNT 4
+typedef struct _HV_TRACK_CELL_REF
+{
+    USHORT Count;
+    USHORT Max;
+    PHV_HIVE_CELL_PAIR CellArray;
+    HV_HIVE_CELL_PAIR StaticArray[STATIC_CELL_PAIR_COUNT];
+    USHORT StaticCount;
+} HV_TRACK_CELL_REF, *PHV_TRACK_CELL_REF;
+
 extern ULONG CmlibTraceLevel;
 
 /*
@@ -272,6 +288,12 @@ HvIsCellDirty(
     IN HCELL_INDEX Cell
 );
 
+BOOLEAN
+CMAPI
+HvHiveWillShrink(
+    IN PHHIVE RegistryHive
+);
+
 BOOLEAN CMAPI
 HvSyncHive(
    PHHIVE RegistryHive);
@@ -288,6 +310,21 @@ CmCreateRootNode(
 VOID CMAPI
 CmPrepareHive(
    PHHIVE RegistryHive);
+   
+   
+BOOLEAN
+CMAPI
+HvTrackCellRef(
+    PHV_TRACK_CELL_REF CellRef,
+    PHHIVE Hive,
+    HCELL_INDEX Cell
+);
+
+VOID
+CMAPI
+HvReleaseFreeCellRefArray(
+    PHV_TRACK_CELL_REF CellRef
+);
 
 /*
  * Private functions.
index 994ca98..8151651 100644 (file)
@@ -113,7 +113,7 @@ HvMarkCellDirty(
        __FUNCTION__, RegistryHive, CellIndex, HoldingLock);
 
    if ((CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT != Stable)
-      return FALSE;
+      return TRUE;
 
    CellBlock = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
    CellLastBlock = ((CellIndex + HV_BLOCK_SIZE - 1) & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
@@ -525,3 +525,56 @@ HvFreeCell(
    if (CellType == Stable)
       HvMarkCellDirty(RegistryHive, CellIndex, FALSE);
 }
+
+BOOLEAN
+CMAPI
+HvTrackCellRef(PHV_TRACK_CELL_REF CellRef,
+               PHHIVE Hive,
+               HCELL_INDEX Cell)
+{
+    /* Sanity checks */
+    ASSERT(CellRef);
+    ASSERT(Hive );
+    ASSERT(Cell != HCELL_NIL);
+
+    /* Less than 4? */
+    if (CellRef->StaticCount < STATIC_CELL_PAIR_COUNT)
+    {
+        /* Add reference */
+        CellRef->StaticArray[CellRef->StaticCount].Hive = Hive;
+        CellRef->StaticArray[CellRef->StaticCount].Cell = Cell;
+        CellRef->StaticCount++;
+        return TRUE;
+    }
+    
+    /* FIXME: TODO */
+    DPRINT1("ERROR: Too many references\n");
+    while (TRUE);
+    return FALSE;
+}
+
+VOID
+CMAPI
+HvReleaseFreeCellRefArray(PHV_TRACK_CELL_REF CellRef)
+{
+    ULONG i;
+    ASSERT(CellRef);
+
+    /* Any references? */
+    if (CellRef->StaticCount > 0)
+    { 
+        /* Sanity check */
+        ASSERT(CellRef->StaticCount <= STATIC_CELL_PAIR_COUNT);
+        
+        /* Loop them */
+        for (i = 0; i < CellRef->StaticCount;i++)
+        {
+            /* Release them */
+            HvReleaseCell(CellRef->StaticArray[i].Hive,
+                          CellRef->StaticArray[i].Cell);
+        }
+
+        /* Free again */
+        CellRef->StaticCount = 0;
+    }
+}
\ No newline at end of file
index 5cc20cf..7ecadff 100644 (file)
@@ -265,6 +265,14 @@ HvSyncHive(
    return TRUE;
 }
 
+BOOLEAN
+CMAPI
+HvHiveWillShrink(IN PHHIVE RegistryHive)
+{
+    /* No shrinking yet */
+    return FALSE;
+}
+
 BOOLEAN CMAPI
 HvWriteHive(
    PHHIVE RegistryHive)
index a8b2675..0ba0aae 100644 (file)
@@ -360,6 +360,17 @@ MMixerInitializeWaveInfo(
     WaveInfo->DeviceId = MixerData->DeviceId;
     WaveInfo->PinId = PinId;
 
+
+    /* copy device name */
+    if (bWaveIn)
+    {
+        wcscpy(WaveInfo->u.InCaps.szPname, DeviceName);
+    }
+    else
+    {
+        wcscpy(WaveInfo->u.OutCaps.szPname, DeviceName);
+    }
+
     /* FIXME determine manufacturer / product id */
     if (bWaveIn)
     {
@@ -410,6 +421,8 @@ MMixerInitializeWaveInfo(
     MixerContext->Free(MultipleItem);
 
 
+
+
     if (bWaveIn)
     {
         InsertTailList(&MixerList->WaveInList, &WaveInfo->Entry);
index 85f2ed9..538c3e5 100644 (file)
 
 /* FUNCTIONS *****************************************************************/
 
+BOOLEAN
+NTAPI
+CmpIsHiveAlreadyLoaded(IN HANDLE KeyHandle,
+                       IN POBJECT_ATTRIBUTES SourceFile,
+                       OUT PCMHIVE *CmHive)
+{
+    NTSTATUS Status;
+    PCM_KEY_BODY KeyBody;
+    PCMHIVE Hive;
+    BOOLEAN Loaded = FALSE;
+    PAGED_CODE();
+
+    /* Sanity check */
+    CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK();
+
+    /* Reference the handle */
+    Status = ObReferenceObjectByHandle(KeyHandle,
+                                       0,
+                                       CmpKeyObjectType,
+                                       KernelMode,
+                                       (PVOID)&KeyBody,
+                                       NULL);
+    if (!NT_SUCCESS(Status)) return Loaded;
+
+    /* Don't touch deleted KCBs */
+    if (KeyBody->KeyControlBlock->Delete) return Loaded;
+
+    Hive = CONTAINING_RECORD(KeyBody->KeyControlBlock->KeyHive, CMHIVE, Hive);
+
+    /* Must be the root key */
+    if (!(KeyBody->KeyControlBlock->Flags & KEY_HIVE_ENTRY) ||
+        !(Hive->FileUserName.Buffer))
+    {
+        /* It isn't */
+        ObDereferenceObject(KeyBody);
+        return Loaded;
+    }
+
+    /* Now compare the name of the file */
+    if (!RtlCompareUnicodeString(&Hive->FileUserName,
+                                 SourceFile->ObjectName,
+                                 TRUE))
+    {
+        /* Same file found */
+        Loaded = TRUE;
+        *CmHive = Hive;
+        
+        /* If the hive is frozen, not sure what to do */
+        if (Hive->Frozen)
+        {
+            /* FIXME: TODO */
+            DPRINT1("ERROR: Hive is frozen\n");
+            while (TRUE);
+        }
+     }
+
+     /* Dereference and return result */
+     ObDereferenceObject(KeyBody);
+     return Loaded;
+ }
 BOOLEAN
 NTAPI
 CmpDoFlushAll(IN BOOLEAN ForceFlush)
@@ -39,16 +100,35 @@ CmpDoFlushAll(IN BOOLEAN ForceFlush)
         if (!(Hive->Hive.HiveFlags & HIVE_NOLAZYFLUSH))
         {
             /* Acquire the flusher lock */
-            ExAcquirePushLockExclusive((PVOID)&Hive->FlusherLock);
-
-            /* 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 */
@@ -81,10 +161,14 @@ CmpSetValueKeyNew(IN PHHIVE Hive,
     {
         /* Then make sure it's valid and dirty it */
         ASSERT(Parent->ValueList.List != HCELL_NIL);
-        HvMarkCellDirty(Hive, Parent->ValueList.List, FALSE);
+        if (!HvMarkCellDirty(Hive, Parent->ValueList.List, FALSE))
+        {
+            /* Fail if we're out of space for log changes */
+            return STATUS_NO_LOG_SPACE;
+        }
     }
 
-    /* Allocate  avalue cell */
+    /* Allocate value cell */
     ValueCell = HvAllocateCell(Hive,
                                FIELD_OFFSET(CM_KEY_VALUE, Name) +
                                CmpNameSize(Hive, ValueName),
@@ -102,16 +186,33 @@ CmpSetValueKeyNew(IN PHHIVE Hive,
 
     /* Set it up and copy the name */
     CellData->u.KeyValue.Signature = CM_KEY_VALUE_SIGNATURE;
-    CellData->u.KeyValue.Flags = 0;
-    CellData->u.KeyValue.Type = Type;
-    CellData->u.KeyValue.NameLength = CmpCopyName(Hive,
-                                                  CellData->u.KeyValue.Name,
-                                                  ValueName);
+    _SEH2_TRY
+    {
+        /* This can crash since the name is coming from user-mode */
+        CellData->u.KeyValue.NameLength = CmpCopyName(Hive,
+                                                      CellData->u.KeyValue.Name,
+                                                      ValueName);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        /* Fail */
+        DPRINT1("Invalid user data!\n");
+        HvFreeCell(Hive, ValueCell);
+        _SEH2_YIELD(return _SEH2_GetExceptionCode());
+    }
+    _SEH2_END;
+
+    /* Check for compressed name */
     if (CellData->u.KeyValue.NameLength < ValueName->Length)
     {
         /* This is a compressed name */
         CellData->u.KeyValue.Flags = VALUE_COMP_NAME;
     }
+    else
+    {
+        /* No flags to set */
+        CellData->u.KeyValue.Flags = 0;
+    }
 
     /* Check if this is a normal key */
     if (DataSize > CM_KEY_VALUE_SMALL)
@@ -140,6 +241,9 @@ CmpSetValueKeyNew(IN PHHIVE Hive,
         CellData->u.KeyValue.DataLength = DataSize + CM_KEY_VALUE_SPECIAL_SIZE;
         CellData->u.KeyValue.Data = SmallData;
     }
+    
+    /* Set the type now */
+    CellData->u.KeyValue.Type = Type;
 
     /* Add this value cell to the child list */
     Status = CmpAddValueToList(Hive,
@@ -149,7 +253,12 @@ CmpSetValueKeyNew(IN PHHIVE Hive,
                                &Parent->ValueList);
 
     /* If we failed, free the entire cell, including the data */
-    if (!NT_SUCCESS(Status)) CmpFreeValue(Hive, ValueCell);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Overwrite the status with a known one */
+        CmpFreeValue(Hive, ValueCell);
+        Status = STATUS_INSUFFICIENT_RESOURCES;
+    }
 
     /* Return Status */
     return Status;
@@ -170,9 +279,12 @@ CmpSetValueKeyExisting(IN PHHIVE Hive,
     PCELL_DATA CellData;
     ULONG Length;
     BOOLEAN WasSmall, IsSmall;
+    
+    /* Registry writes must be blocked */
+    CMP_ASSERT_FLUSH_LOCK(Hive);
 
     /* Mark the old child cell dirty */
-    HvMarkCellDirty(Hive, OldChild, FALSE);
+    if (!HvMarkCellDirty(Hive, OldChild, FALSE)) return STATUS_NO_LOG_SPACE;
 
     /* See if this is a small or normal key */
     WasSmall = CmpIsKeyValueSmall(&Length, Value->DataLength);
@@ -185,7 +297,7 @@ CmpSetValueKeyExisting(IN PHHIVE Hive,
     ASSERT_VALUE_BIG(Hive, DataSize);
 
     /* Mark the old value dirty */
-    CmpMarkValueDataDirty(Hive, Value);
+    if (!CmpMarkValueDataDirty(Hive, Value)) return STATUS_NO_LOG_SPACE;
 
     /* Check if we have a small key */
     if (IsSmall)
@@ -203,246 +315,507 @@ CmpSetValueKeyExisting(IN PHHIVE Hive,
         Value->Type = Type;
         return STATUS_SUCCESS;
     }
-    else
+    
+    /* We have a normal key. Was the old cell also normal and had data? */
+    if (!(WasSmall) && (Length > 0))
     {
-        /* We have a normal key. Was the old cell also normal and had data? */
-        if (!(WasSmall) && (Length > 0))
-        {
-            /* Get the current data cell and actual data inside it */
-            DataCell = Value->Data;
-            ASSERT(DataCell != HCELL_NIL);
-            CellData = HvGetCell(Hive, DataCell);
-            if (!CellData) return STATUS_INSUFFICIENT_RESOURCES;
+        /* 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)))
@@ -463,10 +836,21 @@ DoAgain:
             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;
@@ -504,15 +888,13 @@ CmDeleteValueKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
     /* 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;
@@ -535,16 +917,26 @@ CmDeleteValueKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
         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));
@@ -552,7 +944,12 @@ CmDeleteValueKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
 
         /* 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))
@@ -564,7 +961,7 @@ CmDeleteValueKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
 
         /* Set the last write time */
         KeQuerySystemTime(&Parent->LastWriteTime);
-        KeQuerySystemTime(&Kcb->KcbLastWriteTime);
+        Kcb->KcbLastWriteTime = Parent->LastWriteTime;
 
         /* Sanity check */
         ASSERT(Parent->MaxValueNameLen == Kcb->KcbMaxValueNameLen);
@@ -591,6 +988,9 @@ CmDeleteValueKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
         /* 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;
@@ -609,6 +1009,7 @@ Quickie:
     }
 
     /* Release locks */
+    CmpUnlockHiveFlusher((PCMHIVE)Hive);
     CmpReleaseKcbLock(Kcb);
     CmpUnlockRegistry();
     return Status;
@@ -683,22 +1084,38 @@ DoAgain:
         /* 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
     {
@@ -735,344 +1152,154 @@ CmEnumerateValueKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
     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;
 }
 
@@ -1087,6 +1314,7 @@ CmQueryKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
     NTSTATUS Status;
     PHHIVE Hive;
     PCM_KEY_NODE Parent;
+    HV_TRACK_CELL_REF CellReferences = {0};
 
     /* Acquire hive lock */
     CmpLockRegistry();
@@ -1094,16 +1322,6 @@ CmQueryKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
     /* Lock KCB shared */
     CmpAcquireKcbLockShared(Kcb);
 
-    /* Get the hive and parent */
-    Hive = Kcb->KeyHive;
-    Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
-    if (!Parent)
-    {
-        /* Fail */
-        Status = STATUS_INSUFFICIENT_RESOURCES;
-        goto Quickie;
-    }
-    
     /* Don't touch deleted keys */
     if (Kcb->Delete)
     {
@@ -1120,13 +1338,27 @@ CmQueryKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
         case KeyBasicInformation:
         case KeyNodeInformation:
 
-            /* Call the internal API */
-            Status = CmpQueryKeyData(Hive,
-                                     Parent,
-                                     KeyInformationClass,
-                                     KeyInformation,
-                                     Length,
-                                     ResultLength);
+            /* Get the hive and parent */
+            Hive = Kcb->KeyHive;
+            Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
+            ASSERT(Parent);
+            
+            /* Track cell references */
+            if (!HvTrackCellRef(&CellReferences, Hive, Kcb->KeyCell))
+            {
+                /* Not enough memory to track references */
+                Status = STATUS_INSUFFICIENT_RESOURCES;
+            }
+            else
+            {
+                /* Call the internal API */
+                Status = CmpQueryKeyData(Hive,
+                                         Parent,
+                                         KeyInformationClass,
+                                         KeyInformation,
+                                         Length,
+                                         ResultLength);
+            }
             break;
 
         /* Unsupported classes for now */
@@ -1149,6 +1381,9 @@ CmQueryKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
     }
 
 Quickie:
+    /* Release references */
+    HvReleaseFreeCellRefArray(&CellReferences);
+
     /* Release locks */
     CmpReleaseKcbLock(Kcb);
     CmpUnlockRegistry();
@@ -1168,6 +1403,7 @@ CmEnumerateKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
     PHHIVE Hive;
     PCM_KEY_NODE Parent, Child;
     HCELL_INDEX ChildCell;
+    HV_TRACK_CELL_REF CellReferences = {0};
 
     /* Acquire hive lock */
     CmpLockRegistry();
@@ -1179,20 +1415,14 @@ CmEnumerateKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
     if (Kcb->Delete)
     {
         /* Undo everything */
-        CmpReleaseKcbLock(Kcb);
-        CmpUnlockRegistry();
-        return STATUS_KEY_DELETED;
+        Status = STATUS_KEY_DELETED;
+        goto Quickie;
     }
 
     /* Get the hive and parent */
     Hive = Kcb->KeyHive;
     Parent = (PCM_KEY_NODE)HvGetCell(Hive, Kcb->KeyCell);
-    if (!Parent)
-    {
-        /* Fail */
-        Status = STATUS_INSUFFICIENT_RESOURCES;
-        goto Quickie;
-    }
+    ASSERT(Parent);
 
     /* Get the child cell */
     ChildCell = CmpFindSubKeyByNumber(Hive, Parent, Index);
@@ -1210,22 +1440,39 @@ CmEnumerateKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
 
     /* Now get the actual child node */
     Child = (PCM_KEY_NODE)HvGetCell(Hive, ChildCell);
-    if (!Child)
+    ASSERT(Child);
+    
+    /* Track references */
+    if (!HvTrackCellRef(&CellReferences, Hive, ChildCell))
     {
-        /* Fail */
+        /* Can't allocate memory for tracking */
         Status = STATUS_INSUFFICIENT_RESOURCES;
         goto Quickie;
     }
 
-    /* Query the data requested */
-    Status = CmpQueryKeyData(Hive,
-                             Child,
-                             KeyInformationClass,
-                             KeyInformation,
-                             Length,
-                             ResultLength);
+    /* Data can be user-mode, use SEH */
+    _SEH2_TRY
+    {
+        /* Query the data requested */
+        Status = CmpQueryKeyData(Hive,
+                                 Child,
+                                 KeyInformationClass,
+                                 KeyInformation,
+                                 Length,
+                                 ResultLength);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        /* Fail with exception code */
+        Status = _SEH2_GetExceptionCode();
+        _SEH2_YIELD(goto Quickie);
+    }
+    _SEH2_END;
 
 Quickie:
+    /* Release references */
+    HvReleaseFreeCellRefArray(&CellReferences);
+
     /* Release locks */
     CmpReleaseKcbLock(Kcb);
     CmpUnlockRegistry();
@@ -1271,14 +1518,12 @@ CmDeleteKey(IN PCM_KEY_BODY KeyBody)
     Hive = Kcb->KeyHive;
     Cell = Kcb->KeyCell;
     
+    /* Lock flushes */
+    CmpLockHiveFlusherShared((PCMHIVE)Hive);
+    
     /* Get the key node */
     Node = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
-    if (!Node)
-    {
-        /* Fail */
-        Status = STATUS_INSUFFICIENT_RESOURCES;
-        goto Quickie;
-    }
+    ASSERT(Node);
    
     /* Sanity check */
     ASSERT(Node->Flags == Kcb->Flags);
@@ -1287,11 +1532,17 @@ CmDeleteKey(IN PCM_KEY_BODY KeyBody)
     if (!(Node->SubKeyCounts[Stable] + Node->SubKeyCounts[Volatile]) &&
         !(Node->Flags & KEY_NO_DELETE))
     {
+        /* Send notification to registered callbacks */
+        CmpReportNotify(Kcb, Hive, Cell, REG_NOTIFY_CHANGE_NAME);
+        
         /* Get the parent and free the cell */
         ParentCell = Node->Parent;
         Status = CmpFreeKeyByCell(Hive, Cell, TRUE);
         if (NT_SUCCESS(Status))
         {
+            /* Flush any notifications */
+            CmpFlushNotifiesOnKeyBodyList(Kcb, FALSE);
+            
             /* Clean up information we have on the subkey */
             CmpCleanUpSubKeyInfo(Kcb->ParentKcb);
 
@@ -1327,10 +1578,12 @@ CmDeleteKey(IN PCM_KEY_BODY KeyBody)
         Status = STATUS_CANNOT_DELETE;
     }
     
-Quickie:
     /* Release the cell */
     HvReleaseCell(Hive, Cell);
-    
+
+    /* Release flush lock */
+    CmpUnlockHiveFlusher((PCMHIVE)Hive);
+
     /* Release the KCB locks */
 Quickie2:
     CmpReleaseTwoKcbLockByKey(Kcb->ConvKey, Kcb->ParentKcb->ConvKey);
@@ -1364,12 +1617,36 @@ CmFlushKey(IN PCM_KEY_CONTROL_BLOCK Kcb,
     }
     else
     {
+        /* Don't touch the hive */
+        CmpLockHiveFlusherExclusive(CmHive);
+        ASSERT(CmHive->ViewLock);
+        KeAcquireGuardedMutex(CmHive->ViewLock);
+        CmHive->ViewLockOwner = KeGetCurrentThread();
+        
+        /* Will the hive shrink? */
+        if (HvHiveWillShrink(Hive))
+        {
+            /* I don't believe the current Hv does shrinking */
+            ASSERT(FALSE);
+        }
+        else
+        {
+            /* Now we can release views */
+            ASSERT(CmHive->ViewLock);
+            CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK_OR_LOADING(CmHive);
+            ASSERT(KeGetCurrentThread() == CmHive->ViewLockOwner);
+            KeReleaseGuardedMutex(CmHive->ViewLock);
+        }
+        
         /* Flush only this hive */
         if (!HvSyncHive(Hive))
         {
             /* Fail */
             Status = STATUS_REGISTRY_IO_FAILED;
         }
+        
+        /* Release the flush lock */
+        CmpUnlockHiveFlusher((PCMHIVE)Hive);
     }
 
     /* Return the status */
@@ -1387,8 +1664,9 @@ CmLoadKey(IN POBJECT_ATTRIBUTES TargetKey,
     SECURITY_CLIENT_CONTEXT ClientSecurityContext;
     HANDLE KeyHandle;
     BOOLEAN Allocate = TRUE;
-    PCMHIVE CmHive;
+    PCMHIVE CmHive, LoadedHive;
     NTSTATUS Status;
+    CM_PARSE_CONTEXT ParseContext;
     
     /* Check if we have a trust key */
     if (KeyBody)
@@ -1415,9 +1693,21 @@ CmLoadKey(IN POBJECT_ATTRIBUTES TargetKey,
     }
     
     /* Open the target key */
+#if 0
     Status = ZwOpenKey(&KeyHandle, KEY_READ, TargetKey);
+#else
+    RtlZeroMemory(&ParseContext, sizeof(ParseContext));
+    ParseContext.CreateOperation = FALSE;
+    Status = ObOpenObjectByName(TargetKey,
+                                CmpKeyObjectType,
+                                KernelMode,
+                                NULL,
+                                KEY_READ,
+                                &ParseContext,
+                                &KeyHandle);
+#endif
     if (!NT_SUCCESS(Status)) KeyHandle = NULL;
-    
+
     /* Open the hive */
     Status = CmpCmdHiveOpen(SourceFile,
                             &ClientSecurityContext,
@@ -1437,21 +1727,29 @@ CmLoadKey(IN POBJECT_ATTRIBUTES TargetKey,
             /* Lock the registry */
             CmpLockRegistryExclusive();
             
-            /* FIXME: Check if we are already loaded */
-            
+            /* Check if we are already loaded */
+            if (CmpIsHiveAlreadyLoaded(KeyHandle, SourceFile, &LoadedHive))
+            {
+                /* That's okay then */
+                ASSERT(LoadedHive);
+                Status = STATUS_SUCCESS;
+            }
+
             /* Release the registry */
             CmpUnlockRegistry();
         }
         
         /* Close the key handle if we had one */
         if (KeyHandle) ZwClose(KeyHandle);
-        DPRINT1("Failed: %lx\n", Status);
         return Status;
     }
     
     /* Lock the registry shared */
     CmpLockRegistry();
     
+    /* Lock loading */
+    ExAcquirePushLockExclusive(&CmpLoadHiveLock);
+    
     /* Lock the hive to this thread */
     CmHive->Hive.HiveFlags |= HIVE_IS_UNLOADING;
     CmHive->CreatorOwner = KeGetCurrentThread();
@@ -1467,23 +1765,37 @@ CmLoadKey(IN POBJECT_ATTRIBUTES TargetKey,
                                  TargetKey->SecurityDescriptor);
     if (NT_SUCCESS(Status))
     {
-        /* FIXME: Add to HiveList key */
+        /* Add to HiveList key */
+        CmpAddToHiveFileList(CmHive);
         
         /* Sync the hive if necessary */
         if (Allocate)
         {
-            /* Sync it */
+            /* Sync it under the flusher lock */
+            CmpLockHiveFlusherExclusive(CmHive);
             HvSyncHive(&CmHive->Hive);
+            CmpUnlockHiveFlusher(CmHive);
         }
         
         /* Release the hive */
         CmHive->Hive.HiveFlags &= ~HIVE_IS_UNLOADING;
         CmHive->CreatorOwner = NULL;
+        
+        /* Allow loads */
+        ExReleasePushLock(&CmpLoadHiveLock);
     }
     else
     {
         /* FIXME: TODO */
-        
+        ASSERT(FALSE);
+    }
+    
+    /* Is this first profile load? */
+    if (!(CmpProfileLoaded) && !(CmpWasSetupBoot))
+    {
+        /* User is now logged on, set quotas */
+        CmpProfileLoaded = TRUE;
+        CmpSetGlobalQuotaAllowed();
     }
     
     /* Unlock the registry */
index f1dcc34..50c6815 100644 (file)
@@ -1,20 +1,19 @@
 /*
  * PROJECT:         ReactOS Kernel
- * LICENSE:         GPL - See COPYING in the top level directory
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
  * FILE:            ntoskrnl/config/cmboot.c
  * PURPOSE:         Configuration Manager - Boot Initialization
- * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ *                  Alex Ionescu (alex.ionescu@reactos.org)
  */
 
-/* INCLUDES ******************************************************************/
+/* INCLUDES *******************************************************************/
 
 #include "ntoskrnl.h"
 #define NDEBUG
 #include "debug.h"
-
-/* GLOBALS *******************************************************************/
-
-/* FUNCTIONS *****************************************************************/
+/* FUNCTIONS ******************************************************************/
 
 HCELL_INDEX
 NTAPI
@@ -124,3 +123,559 @@ CmpFindControlSet(IN PHHIVE SystemHive,
     /* Return the CCS Cell */
     return ControlSetCell;
 }
+
+ULONG
+NTAPI
+CmpFindTagIndex(IN PHHIVE Hive,
+                IN HCELL_INDEX TagCell,
+                IN HCELL_INDEX GroupOrderCell,
+                IN PUNICODE_STRING GroupName)
+{
+    PCM_KEY_VALUE TagValue, Value;
+    HCELL_INDEX OrderCell;
+    PULONG TagOrder, DriverTag;
+    ULONG CurrentTag, Length;
+    PCM_KEY_NODE Node;
+    BOOLEAN BufferAllocated;
+    ASSERT(Hive->ReleaseCellRoutine == NULL);
+    
+    /* Get the tag */
+    Value = HvGetCell(Hive, TagCell);
+    ASSERT(Value);
+    DriverTag = (PULONG)CmpValueToData(Hive, Value, &Length);
+    ASSERT(DriverTag);
+
+    /* Get the order array */
+    Node = HvGetCell(Hive, GroupOrderCell);
+    ASSERT(Node);
+    OrderCell = CmpFindValueByName(Hive, Node, GroupName);
+    if (OrderCell == HCELL_NIL) return -2;
+    
+    /* And read it */
+    TagValue = HvGetCell(Hive, OrderCell);
+    CmpGetValueData(Hive, TagValue, &Length, (PVOID*)&TagOrder, &BufferAllocated, &OrderCell);
+    ASSERT(TagOrder);
+    
+    /* Parse each tag */
+    for (CurrentTag = 1; CurrentTag <= TagOrder[0]; CurrentTag++)
+    {
+        /* Find a match */
+        if (TagOrder[CurrentTag] == *DriverTag)
+        {
+            /* Found it -- return the tag */
+            if (BufferAllocated) ExFreePool(TagOrder);
+            return CurrentTag;
+        }
+    }
+    
+    /* No matches, so assume next to last ordering */
+    if (BufferAllocated) ExFreePool(TagOrder);
+    return -2;
+}
+
+BOOLEAN
+NTAPI
+CmpAddDriverToList(IN PHHIVE Hive,
+                   IN HCELL_INDEX DriverCell,
+                   IN HCELL_INDEX GroupOrderCell,
+                   IN PUNICODE_STRING RegistryPath,
+                   IN PLIST_ENTRY BootDriverListHead)
+{
+    PBOOT_DRIVER_NODE DriverNode;
+    PBOOT_DRIVER_LIST_ENTRY DriverEntry;
+    PCM_KEY_NODE Node;
+    ULONG NameLength, Length;
+    HCELL_INDEX ValueCell, TagCell;    
+    PCM_KEY_VALUE Value;
+    PUNICODE_STRING FileName, RegistryString;
+    UNICODE_STRING UnicodeString;
+    PULONG ErrorControl;
+    PWCHAR Buffer;
+    ASSERT(Hive->ReleaseCellRoutine == NULL);
+    
+    /* Allocate a driver node and initialize it */
+    DriverNode = CmpAllocate(sizeof(BOOT_DRIVER_NODE), FALSE, TAG_CM);
+    if (!DriverNode) return FALSE;
+    DriverEntry = &DriverNode->ListEntry;
+    DriverEntry->RegistryPath.Buffer = NULL;
+    DriverEntry->FilePath.Buffer = NULL;
+    
+    /* Get the driver cell */
+    Node = HvGetCell(Hive, DriverCell);
+    ASSERT(Node);
+    
+    /* Get the name from the cell */
+    DriverNode->Name.Length = Node->Flags & KEY_COMP_NAME ? 
+                              CmpCompressedNameSize(Node->Name, Node->NameLength) :
+                              Node->NameLength;
+    DriverNode->Name.MaximumLength = DriverNode->Name.Length;
+    NameLength = DriverNode->Name.Length;
+    
+    /* Now allocate the buffer for it and copy the name */
+    DriverNode->Name.Buffer = CmpAllocate(NameLength, FALSE, TAG_CM);
+    if (!DriverNode->Name.Buffer) return FALSE;
+    if (Node->Flags & KEY_COMP_NAME)
+    {
+        /* Compressed name */
+        CmpCopyCompressedName(DriverNode->Name.Buffer,
+                              DriverNode->Name.Length,
+                              Node->Name,
+                              Node->NameLength);
+    }
+    else
+    {
+        /* Normal name */
+        RtlCopyMemory(DriverNode->Name.Buffer, Node->Name, Node->NameLength);
+    }
+    
+    /* Now find the image path */
+    RtlInitUnicodeString(&UnicodeString, L"ImagePath");
+    ValueCell = CmpFindValueByName(Hive, Node, &UnicodeString);
+    if (ValueCell == HCELL_NIL)
+    {
+        /* Couldn't find it, so assume the drivers path */
+        Length = sizeof(L"System32\\Drivers\\") + NameLength + sizeof(L".sys");
+        
+        /* Allocate the path name */
+        FileName = &DriverEntry->FilePath;
+        FileName->Length = 0;
+        FileName->MaximumLength = Length;
+        FileName->Buffer = CmpAllocate(Length, FALSE,TAG_CM);
+        if (!FileName->Buffer) return FALSE;
+
+        /* Write the path name */
+        RtlAppendUnicodeToString(FileName, L"System32\\Drivers\\");
+        RtlAppendUnicodeStringToString(FileName, &DriverNode->Name);
+        RtlAppendUnicodeToString(FileName, L".sys");        
+    }
+    else
+    {
+        /* Path name exists, so grab it */
+        Value = HvGetCell(Hive, ValueCell);
+        ASSERT(Value);
+
+        /* Allocate and setup the path name */
+        FileName = &DriverEntry->FilePath;
+        Buffer = (PWCHAR)CmpValueToData(Hive, Value, &Length);
+        FileName->MaximumLength = FileName->Length = Length;
+        FileName->Buffer = CmpAllocate(Length, FALSE, TAG_CM);
+        
+        /* Transfer the data */  
+        if (!(FileName->Buffer) || !(Buffer)) return FALSE;        
+        RtlCopyMemory(FileName->Buffer, Buffer, Length);
+    }
+    
+    /* Now build the registry path */
+    RegistryString = &DriverEntry->RegistryPath;
+    RegistryString->Length = 0;
+    RegistryString->MaximumLength = RegistryPath->Length + NameLength;
+    RegistryString->Buffer = CmpAllocate(RegistryString->MaximumLength, FALSE, TAG_CM);
+    if (!RegistryString->Buffer) return FALSE;
+    
+    /* Add the driver name to it */
+    RtlAppendUnicodeStringToString(RegistryString, RegistryPath);
+    RtlAppendUnicodeStringToString(RegistryString, &DriverNode->Name);
+    
+    /* The entry is done, add it */
+    InsertHeadList(BootDriverListHead, &DriverEntry->Link);
+    
+    /* Now find error control settings */    
+    RtlInitUnicodeString(&UnicodeString, L"ErrorControl");
+    ValueCell = CmpFindValueByName(Hive, Node, &UnicodeString);
+    if (ValueCell == HCELL_NIL)
+    {
+        /* Couldn't find it, so assume default */
+        DriverNode->ErrorControl = NormalError;
+    }
+    else
+    {
+        /* Otherwise, read whatever the data says */
+        Value = HvGetCell(Hive, ValueCell);
+        ASSERT(Value);
+        ErrorControl = (PULONG)CmpValueToData(Hive, Value, &Length);
+        ASSERT(ErrorControl);
+        DriverNode->ErrorControl = *ErrorControl;
+    }
+    
+    /* Next, get the group cell */
+    RtlInitUnicodeString(&UnicodeString, L"group");
+    ValueCell = CmpFindValueByName(Hive, Node, &UnicodeString);
+    if (ValueCell == HCELL_NIL)
+    {
+        /* Couldn't find, so set an empty string */
+        RtlInitEmptyUnicodeString(&DriverNode->Group, NULL, 0);
+    }
+    else
+    {
+        /* Found it, read the group value */
+        Value = HvGetCell(Hive, ValueCell);
+        ASSERT(Value);
+        
+        /* Copy it into the node */
+        DriverNode->Group.Buffer = (PWCHAR)CmpValueToData(Hive, Value, &Length);
+        if (!DriverNode->Group.Buffer) return FALSE;
+        DriverNode->Group.Length = Length - sizeof(UNICODE_NULL);
+        DriverNode->Group.MaximumLength = DriverNode->Group.Length;
+    }
+    
+    /* Finally, find the tag */
+    RtlInitUnicodeString(&UnicodeString, L"Tag");
+    TagCell = CmpFindValueByName(Hive, Node, &UnicodeString);
+    if (TagCell == HCELL_NIL)
+    {
+        /* No tag, so load last */
+        DriverNode->Tag = -1;
+    }
+    else
+    {
+        /* Otherwise, decode it based on tag order */
+        DriverNode->Tag = CmpFindTagIndex(Hive,
+                                          TagCell,
+                                          GroupOrderCell,
+                                          &DriverNode->Group);
+    }
+    
+    /* All done! */
+    return TRUE;
+}
+
+BOOLEAN
+NTAPI
+CmpIsLoadType(IN PHHIVE Hive,
+              IN HCELL_INDEX Cell,
+              IN SERVICE_LOAD_TYPE LoadType)
+{
+    PCM_KEY_NODE Node;
+    HCELL_INDEX ValueCell;
+    UNICODE_STRING ValueString = RTL_CONSTANT_STRING(L"Start");
+    PCM_KEY_VALUE Value;
+    ULONG Length;
+    PLONG Data;
+    ASSERT(Hive->ReleaseCellRoutine == NULL);
+
+    /* Open the start cell */
+    Node = HvGetCell(Hive, Cell);
+    ASSERT(Node);
+    ValueCell = CmpFindValueByName(Hive, Node, &ValueString);
+    if (ValueCell == HCELL_NIL) return FALSE;
+    
+    /* Read the start value */
+    Value = HvGetCell(Hive, ValueCell);
+    ASSERT(Value);
+    Data = (PLONG)CmpValueToData(Hive, Value, &Length);
+    ASSERT(Data);
+    
+    /* Return if the type matches */
+    return (*Data == LoadType);
+}
+
+BOOLEAN
+NTAPI
+CmpFindDrivers(IN PHHIVE Hive,
+               IN HCELL_INDEX ControlSet,
+               IN SERVICE_LOAD_TYPE LoadType,
+               IN PWCHAR BootFileSystem OPTIONAL,
+               IN PLIST_ENTRY DriverListHead)
+{
+    HCELL_INDEX ServicesCell, ControlCell, GroupOrderCell, DriverCell;
+    UNICODE_STRING Name;
+    ULONG i;
+    WCHAR Buffer[128];
+    UNICODE_STRING UnicodeString, KeyPath;
+    PBOOT_DRIVER_NODE FsNode;
+    PCM_KEY_NODE ControlNode, ServicesNode, Node;
+    ASSERT(Hive->ReleaseCellRoutine == NULL);
+    
+    /* Open the control set key */
+    ControlNode = HvGetCell(Hive, ControlSet);
+    ASSERT(ControlNode);
+    
+    /* Get services cell */
+    RtlInitUnicodeString(&Name, L"Services");
+    ServicesCell = CmpFindSubKeyByName(Hive, ControlNode, &Name);
+    if (ServicesCell == HCELL_NIL) return FALSE;
+
+    /* Open services key */
+    ServicesNode = HvGetCell(Hive, ServicesCell);
+    ASSERT(ServicesNode);
+    
+    /* Get control cell */
+    RtlInitUnicodeString(&Name, L"Control");
+    ControlCell = CmpFindSubKeyByName(Hive, ControlNode, &Name);
+    if (ControlCell == HCELL_NIL) return FALSE;
+    
+    /* Get the group order cell and read it */
+    RtlInitUnicodeString(&Name, L"GroupOrderList");
+    Node = HvGetCell(Hive, ControlCell);
+    ASSERT(Node);
+    GroupOrderCell = CmpFindSubKeyByName(Hive, Node, &Name);
+    if (GroupOrderCell == HCELL_NIL) return FALSE;
+
+    /* Build the root registry path */
+    RtlInitEmptyUnicodeString(&KeyPath, Buffer, sizeof(Buffer));
+    RtlAppendUnicodeToString(&KeyPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
+    
+    /* Find the first subkey (ie: the first driver or service) */
+    i = 0;
+    DriverCell = CmpFindSubKeyByNumber(Hive, ServicesNode, i);
+    while (DriverCell != HCELL_NIL)
+    {
+        /* Make sure it's a driver of this start type */
+        if (CmpIsLoadType(Hive, DriverCell, LoadType))
+        {
+            /* Add it to the list */
+            CmpAddDriverToList(Hive,
+                               DriverCell,
+                               GroupOrderCell,
+                               &KeyPath,
+                               DriverListHead);
+            
+        }
+        
+        /* Try the next subkey */
+        DriverCell = CmpFindSubKeyByNumber(Hive, ServicesNode, ++i);
+    }
+    
+    /* Check if we have a boot file system */
+    if (BootFileSystem)
+    {
+        /* Find it */
+        RtlInitUnicodeString(&UnicodeString, BootFileSystem);
+        DriverCell = CmpFindSubKeyByName(Hive, ServicesNode, &UnicodeString);
+        if (DriverCell != HCELL_NIL)
+        {
+            /* Always add it to the list */
+            CmpAddDriverToList(Hive,
+                               DriverCell,
+                               GroupOrderCell,
+                               &KeyPath,
+                               DriverListHead);
+            
+            /* Mark it as critical so it always loads */
+            FsNode = CONTAINING_RECORD(DriverListHead->Flink,
+                                       BOOT_DRIVER_NODE,
+                                       ListEntry.Link);
+            FsNode->ErrorControl = SERVICE_ERROR_CRITICAL;
+        }
+    }
+    
+    /* We're done! */
+    return TRUE;
+}
+
+BOOLEAN
+NTAPI
+CmpDoSort(IN PLIST_ENTRY DriverListHead,
+          IN PUNICODE_STRING OrderList)
+{
+    PWCHAR Current, End = NULL;
+    PLIST_ENTRY NextEntry;
+    UNICODE_STRING GroupName;
+    PBOOT_DRIVER_NODE CurrentNode;
+    
+    /* We're going from end to start, so get to the last group and keep going */
+    Current = &OrderList->Buffer[OrderList->Length / sizeof(WCHAR)];
+    while (Current > OrderList->Buffer)
+    {
+        /* Scan the current string */
+        do
+        {
+            if (*Current == UNICODE_NULL) End = Current;
+        } while ((*(--Current - 1) != UNICODE_NULL) && (Current != OrderList->Buffer));
+
+        /* This is our cleaned up string for this specific group */
+        ASSERT(End != NULL);
+        GroupName.Length = (End - Current) * sizeof(WCHAR);
+        GroupName.MaximumLength = GroupName.Length;
+        GroupName.Buffer = Current;
+
+        /* Now loop the driver list */
+        NextEntry = DriverListHead->Flink;
+        while (NextEntry != DriverListHead)
+        {
+            /* Get this node */
+            CurrentNode = CONTAINING_RECORD(NextEntry,
+                                            BOOT_DRIVER_NODE,
+                                            ListEntry.Link);
+                                            
+            /* Get the next entry now since we'll do a relink */
+            NextEntry = CurrentNode->ListEntry.Link.Flink;
+            
+            /* Is there a group name and does it match the current group? */
+            if ((CurrentNode->Group.Buffer) &&
+                (RtlEqualUnicodeString(&GroupName, &CurrentNode->Group, TRUE)))
+            {
+                /* Remove from this location and re-link in the new one */
+                RemoveEntryList(&CurrentNode->ListEntry.Link);
+                InsertHeadList(DriverListHead, &CurrentNode->ListEntry.Link);
+            }
+        }        
+        
+        /* Move on */
+        Current--;
+    }
+    
+    /* All done */
+    return TRUE;
+}
+
+BOOLEAN
+NTAPI
+CmpSortDriverList(IN PHHIVE Hive,
+                  IN HCELL_INDEX ControlSet,
+                  IN PLIST_ENTRY DriverListHead)
+{
+    HCELL_INDEX Controls, GroupOrder, ListCell;
+    UNICODE_STRING Name, DependList;
+    PCM_KEY_VALUE ListNode;
+    ULONG Length;
+    PCM_KEY_NODE Node;
+    ASSERT(Hive->ReleaseCellRoutine == NULL);
+
+    /* Open the control key */
+    Node = HvGetCell(Hive, ControlSet);
+    ASSERT(Node);
+    RtlInitUnicodeString(&Name, L"Control");
+    Controls = CmpFindSubKeyByName(Hive, Node, &Name);
+    if (Controls == HCELL_NIL) return FALSE;
+
+    /* Open the service group order */
+    Node = HvGetCell(Hive, Controls);
+    ASSERT(Node);
+    RtlInitUnicodeString(&Name, L"ServiceGroupOrder");
+    GroupOrder = CmpFindSubKeyByName(Hive, Node, &Name);
+    if (GroupOrder == HCELL_NIL) return FALSE;
+
+    /* Open the list key */
+    Node = HvGetCell(Hive, GroupOrder);
+    ASSERT(Node);
+    RtlInitUnicodeString(&Name, L"list");
+    ListCell = CmpFindValueByName(Hive, Node, &Name);
+    if (ListCell == HCELL_NIL) return FALSE;
+    
+    /* Now read the actual list */
+    ListNode = HvGetCell(Hive, ListCell);
+    ASSERT(ListNode);
+    if (ListNode->Type != REG_MULTI_SZ) return FALSE;
+    
+    /* Copy it into a buffer */
+    DependList.Buffer = (PWCHAR)CmpValueToData(Hive, ListNode, &Length);
+    if (!DependList.Buffer) return FALSE;
+    DependList.Length = DependList.MaximumLength = Length - sizeof(UNICODE_NULL);
+    
+    /* And start the recurive sort algorithm */
+    return CmpDoSort(DriverListHead, &DependList);
+}
+
+BOOLEAN
+NTAPI
+CmpOrderGroup(IN PBOOT_DRIVER_NODE StartNode,
+              IN PBOOT_DRIVER_NODE EndNode)
+{
+    PBOOT_DRIVER_NODE CurrentNode, PreviousNode;
+    PLIST_ENTRY ListEntry;
+    
+    /* Base case, nothing to do */
+    if (StartNode == EndNode) return TRUE;
+    
+    /* Loop the nodes */
+    CurrentNode = StartNode;
+    do
+    {
+        /* Save this as the previous node */
+        PreviousNode = CurrentNode;
+        
+        /* And move to the next one */
+        ListEntry = CurrentNode->ListEntry.Link.Flink;
+        CurrentNode = CONTAINING_RECORD(ListEntry,
+                                        BOOT_DRIVER_NODE,
+                                        ListEntry.Link);
+        
+        /* Check if the previous driver had a bigger tag */
+        if (PreviousNode->Tag > CurrentNode->Tag)
+        {
+            /* Check if we need to update the tail */
+            if (CurrentNode == EndNode)
+            {
+                /* Update the tail */
+                ListEntry = CurrentNode->ListEntry.Link.Blink;
+                EndNode = CONTAINING_RECORD(ListEntry,
+                                            BOOT_DRIVER_NODE,
+                                            ListEntry.Link);
+            }
+            
+            /* Remove this driver since we need to move it */
+            RemoveEntryList(&CurrentNode->ListEntry.Link);
+            
+            /* Keep looping until we find a driver with a lower tag than ours */
+            while ((PreviousNode->Tag > CurrentNode->Tag) && (PreviousNode != StartNode))
+            {
+                /* We'll be re-inserted at this spot */
+                ListEntry = PreviousNode->ListEntry.Link.Blink;
+                PreviousNode = CONTAINING_RECORD(ListEntry,
+                                                 BOOT_DRIVER_NODE,
+                                                 ListEntry.Link);
+            }
+            
+            /* Do the insert in the new location */
+            InsertTailList(&PreviousNode->ListEntry.Link, &CurrentNode->ListEntry.Link);
+            
+            /* Update the head, if needed */
+            if (PreviousNode == StartNode) StartNode = CurrentNode;
+        }
+    } while (CurrentNode != EndNode);
+    
+    /* All done */
+    return TRUE;
+}
+
+BOOLEAN
+NTAPI
+CmpResolveDriverDependencies(IN PLIST_ENTRY DriverListHead)
+{
+    PLIST_ENTRY NextEntry;
+    PBOOT_DRIVER_NODE StartNode, EndNode, CurrentNode;
+    
+    /* Loop the list */
+    NextEntry = DriverListHead->Flink;
+    while (NextEntry != DriverListHead)
+    {
+        /* Find the first entry */
+        StartNode = CONTAINING_RECORD(NextEntry,
+                                      BOOT_DRIVER_NODE,
+                                      ListEntry.Link);
+        do
+        {
+            /* Find the last entry */
+            EndNode = CONTAINING_RECORD(NextEntry,
+                                        BOOT_DRIVER_NODE,
+                                        ListEntry.Link);
+            
+            /* Get the next entry */
+            NextEntry = NextEntry->Flink;
+            CurrentNode = CONTAINING_RECORD(NextEntry,
+                                            BOOT_DRIVER_NODE,
+                                            ListEntry.Link);
+            
+            /* If the next entry is back to the top, break out */
+            if (NextEntry == DriverListHead) break;
+            
+            /* Otherwise, check if this entry is equal */
+            if (!RtlEqualUnicodeString(&StartNode->Group,
+                                       &CurrentNode->Group,
+                                       TRUE))
+            {
+                /* It is, so we've detected a cycle, break out */
+                break;
+            }
+        } while (NextEntry != DriverListHead);
+        
+        /* Now we have the correct start and end pointers, so do the sort */
+        CmpOrderGroup(StartNode, EndNode);
+    }
+    
+    /* We're done */
+    return TRUE;
+}
+
+/* EOF */
index f4e9781..8fb2636 100644 (file)
 
 /* FUNCTIONS *****************************************************************/
 
+NTSTATUS
+NTAPI
+CmpAddToHiveFileList(IN PCMHIVE Hive)
+{
+    return STATUS_SUCCESS;
+}
+
 /* EOF */
\ No newline at end of file
index 154ba15..be7efc1 100644 (file)
@@ -119,12 +119,10 @@ CmpInitializeHive(OUT PCMHIVE *RegistryHive,
     if (!Hive->ViewLock) return STATUS_INSUFFICIENT_RESOURCES;
 
     /* Allocate the flush lock */
-#if 0
     Hive->FlusherLock = ExAllocatePoolWithTag(NonPagedPool,
                                               sizeof(ERESOURCE),
                                               TAG_CM);
     if (!Hive->FlusherLock) return STATUS_INSUFFICIENT_RESOURCES;
-#endif
 
     /* Setup the handles */
     Hive->FileHandles[HFILE_TYPE_PRIMARY] = Primary;
@@ -136,7 +134,7 @@ CmpInitializeHive(OUT PCMHIVE *RegistryHive,
     Hive->ViewLockOwner = NULL;
 
     /* Initialize the flush lock */
-    ExInitializePushLock((PULONG_PTR)&Hive->FlusherLock);
+    ExInitializeResourceLite(Hive->FlusherLock);
 
     /* Setup hive locks */
     ExInitializePushLock((PULONG_PTR)&Hive->HiveLock);
@@ -193,9 +191,7 @@ CmpInitializeHive(OUT PCMHIVE *RegistryHive,
     {
         /* Clear allocations and fail */
         ExFreePool(Hive->ViewLock);
-#if 0
         ExFreePool(Hive->FlusherLock);
-#endif
         ExFreePool(Hive);
         return Status;
     }
@@ -211,9 +207,7 @@ CmpInitializeHive(OUT PCMHIVE *RegistryHive,
         {
             /* Free all alocations */
             ExFreePool(Hive->ViewLock);
-#if 0
             ExFreePool(Hive->FlusherLock);
-#endif
             ExFreePool(Hive);
             return STATUS_REGISTRY_CORRUPT;
         }
index 5e7060d..a26de07 100644 (file)
@@ -1135,3 +1135,62 @@ DelistKeyBodyFromKCB(IN PCM_KEY_BODY KeyBody,
     /* Unlock it it if we did a manual lock */
     if (!LockHeld) CmpReleaseKcbLock(KeyBody->KeyControlBlock);
 }
+
+VOID
+NTAPI
+CmpFlushNotifiesOnKeyBodyList(IN PCM_KEY_CONTROL_BLOCK Kcb,
+                              IN BOOLEAN LockHeld)
+{
+    PLIST_ENTRY NextEntry, ListHead;
+    PCM_KEY_BODY KeyBody;
+
+    /* Sanity check */
+    LockHeld ? CMP_ASSERT_EXCLUSIVE_REGISTRY_LOCK() : CmpIsKcbLockedExclusive(Kcb);
+    while (TRUE)
+    {
+        /* Is the list empty? */
+        ListHead = &Kcb->KeyBodyListHead;
+        if (!IsListEmpty(ListHead))
+        {
+            /* Loop the list */
+            NextEntry = ListHead->Flink;
+            while (NextEntry != ListHead)
+            {
+                /* Get the key body */
+                KeyBody = CONTAINING_RECORD(NextEntry, CM_KEY_BODY, KeyBodyList);
+                ASSERT(KeyBody->Type == '20yk');
+
+                /* Check for notifications */
+                if (KeyBody->NotifyBlock)
+                {
+                    /* Is the lock held? */
+                    if (LockHeld)
+                    {
+                        /* Flush it */
+                        CmpFlushNotify(KeyBody, LockHeld);
+                        ASSERT(KeyBody->NotifyBlock == NULL);
+                        continue;
+                    }
+                    
+                    /* Lock isn't held, so we need to take a reference */
+                    if (ObReferenceObjectSafe(KeyBody))
+                    {
+                        /* Now we can flush */
+                        CmpFlushNotify(KeyBody, LockHeld);
+                        ASSERT(KeyBody->NotifyBlock == NULL);
+                        
+                        /* Release the reference we took */
+                                   ObDereferenceObjectDeferDelete(KeyBody);
+                        continue;
+                    }
+                }
+
+                /* Try the next entry */
+                NextEntry = NextEntry->Flink;
+            }
+        }
+        
+        /* List has been parsed, exit */
+        break;
+    }
+}
index 42d7379..8263544 100644 (file)
@@ -414,15 +414,6 @@ CmpDoCreate(IN PHHIVE Hive,
     LARGE_INTEGER TimeStamp;
     PCM_KEY_NODE KeyNode;
 
-    /* Sanity check */
-#if 0
-    ASSERT((CmpIsKcbLockedExclusive(ParentKcb) == TRUE) ||
-           (CmpTestRegistryLockExclusive() == TRUE));
-#endif
-
-    /* Acquire the flusher lock */
-    ExAcquirePushLockShared((PVOID)&((PCMHIVE)Hive)->FlusherLock);
-
     /* Check if the parent is being deleted */
     if (ParentKcb->Delete)
     {
@@ -555,7 +546,6 @@ CmpDoCreate(IN PHHIVE Hive,
 
 Exit:
     /* Release the flusher lock and return status */
-    ExReleasePushLock((PVOID)&((PCMHIVE)Hive)->FlusherLock);
     return Status;
 }
 
@@ -747,9 +737,6 @@ CmpCreateLinkNode(IN PHHIVE Hive,
     LARGE_INTEGER TimeStamp;
     PCM_KEY_NODE KeyNode;
     PCM_KEY_CONTROL_BLOCK Kcb = ParentKcb;
-#if 0
-    CMP_ASSERT_REGISTRY_LOCK();
-#endif
 
     /* Link nodes only allowed on the master */
     if (Hive != &CmiVolatileHive->Hive)
@@ -759,10 +746,6 @@ CmpCreateLinkNode(IN PHHIVE Hive,
         return STATUS_ACCESS_DENIED;
     }
     
-    /* Acquire the flusher locks */
-    ExAcquirePushLockShared((PVOID)&((PCMHIVE)Hive)->FlusherLock);
-    ExAcquirePushLockShared((PVOID)&((PCMHIVE)Context->ChildHive.KeyHive)->FlusherLock);
-
     /* Check if the parent is being deleted */
     if (ParentKcb->Delete)
     {
@@ -964,8 +947,6 @@ CmpCreateLinkNode(IN PHHIVE Hive,
     
 Exit:
     /* Release the flusher locks and return status */
-    ExReleasePushLock((PVOID)&((PCMHIVE)Context->ChildHive.KeyHive)->FlusherLock);
-    ExReleasePushLock((PVOID)&((PCMHIVE)Hive)->FlusherLock);
     return Status;
 }
 
index 0326e88..3587efe 100644 (file)
@@ -1,12 +1,13 @@
 /*
  * PROJECT:         ReactOS Kernel
- * LICENSE:         GPL - See COPYING in the top level directory
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
  * FILE:            ntoskrnl/config/cmsysini.c
  * PURPOSE:         Configuration Manager - System Initialization Code
- * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ *                  Alex Ionescu (alex.ionescu@reactos.org)
  */
 
-/* INCLUDES ******************************************************************/
+/* INCLUDES *******************************************************************/
 
 #include "ntoskrnl.h"
 #define NDEBUG
@@ -33,7 +34,7 @@ ULONG CmpTraceLevel = 0;
 extern LONG CmpFlushStarveWriters;
 extern BOOLEAN CmFirstTime;
 
-/* FUNCTIONS *****************************************************************/
+/* FUNCTIONS ******************************************************************/
 
 VOID
 NTAPI
@@ -1574,6 +1575,162 @@ CmInitSystem1(VOID)
     return TRUE;
 }
 
+VOID
+NTAPI
+CmpFreeDriverList(IN PHHIVE Hive,
+                  IN PLIST_ENTRY DriverList)
+{
+    PLIST_ENTRY NextEntry, OldEntry;
+    PBOOT_DRIVER_NODE DriverNode;
+    PAGED_CODE();
+    
+    /* Parse the current list */
+    NextEntry = DriverList->Flink;
+    while (NextEntry != DriverList)
+    {
+        /* Get the driver node */
+        DriverNode = CONTAINING_RECORD(NextEntry, BOOT_DRIVER_NODE, ListEntry.Link);
+        
+        /* Get the next entry now, since we're going to free it later */
+        OldEntry = NextEntry;
+        NextEntry = NextEntry->Flink;
+        
+        /* Was there a name? */
+        if (DriverNode->Name.Buffer)
+        {
+            /* Free it */
+            CmpFree(DriverNode->Name.Buffer, DriverNode->Name.Length);
+        }
+        
+        /* Was there a registry path? */
+        if (DriverNode->ListEntry.RegistryPath.Buffer)
+        {
+            /* Free it */
+            CmpFree(DriverNode->ListEntry.RegistryPath.Buffer, 
+                    DriverNode->ListEntry.RegistryPath.MaximumLength);
+        }
+        
+        /* Was there a file path? */
+        if (DriverNode->ListEntry.FilePath.Buffer)
+        {
+            /* Free it */
+            CmpFree(DriverNode->ListEntry.FilePath.Buffer,
+                    DriverNode->ListEntry.FilePath.MaximumLength);
+        }
+        
+        /* Now free the node, and move on */
+        CmpFree(OldEntry, sizeof(BOOT_DRIVER_NODE));
+    }
+}
+
+PUNICODE_STRING*
+NTAPI
+CmGetSystemDriverList(VOID)
+{
+    LIST_ENTRY DriverList;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    NTSTATUS Status;
+    PCM_KEY_BODY KeyBody;
+    PHHIVE Hive;
+    HCELL_INDEX RootCell, ControlCell;
+    HANDLE KeyHandle;
+    UNICODE_STRING KeyName;
+    PLIST_ENTRY NextEntry;
+    ULONG i;
+    PUNICODE_STRING* ServicePath = NULL;
+    BOOLEAN Success, AutoSelect;
+    PBOOT_DRIVER_LIST_ENTRY DriverEntry;
+    PAGED_CODE();
+
+    /* Initialize the driver list */
+    InitializeListHead(&DriverList);
+    
+    /* Open the system hive key */
+    RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\System");
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    Status = NtOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
+    if (!NT_SUCCESS(Status)) return NULL;
+    
+    /* Reference the key object to get the root hive/cell to access directly */
+    Status = ObReferenceObjectByHandle(KeyHandle,
+                                       KEY_QUERY_VALUE,
+                                       CmpKeyObjectType,
+                                       KernelMode,
+                                       (PVOID*)&KeyBody,
+                                       NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail */
+        NtClose(KeyHandle);
+        return NULL;
+    }
+    
+    /* Do all this under the registry lock */
+    CmpLockRegistryExclusive();
+    
+    /* Get the hive and key cell */
+    Hive = KeyBody->KeyControlBlock->KeyHive;
+    RootCell = KeyBody->KeyControlBlock->KeyCell;
+    
+    /* Open the current control set key */
+    RtlInitUnicodeString(&KeyName, L"Current");
+    ControlCell = CmpFindControlSet(Hive, RootCell, &KeyName, &AutoSelect);
+    if (ControlCell == HCELL_NIL) goto EndPath;
+    
+    /* Find all system drivers */
+    Success = CmpFindDrivers(Hive, ControlCell, SystemLoad, NULL, &DriverList);
+    if (!Success) goto EndPath;
+    
+    /* Sort by group/tag */
+    if (!CmpSortDriverList(Hive, ControlCell, &DriverList)) goto EndPath;
+    
+    /* Remove circular dependencies (cycles) and sort */
+    if (!CmpResolveDriverDependencies(&DriverList)) goto EndPath;
+    
+    /* Loop the list to count drivers */
+    for (i = 0, NextEntry = DriverList.Flink;
+         NextEntry != &DriverList;
+         i++, NextEntry = NextEntry->Flink);
+    
+    /* Allocate the array */
+    ServicePath = ExAllocatePool(NonPagedPool, (i + 1) * sizeof(PUNICODE_STRING));
+    if (!ServicePath) KeBugCheckEx(CONFIG_INITIALIZATION_FAILED, 2, 1, 0, 0);
+    
+    /* Loop the driver list */
+    for (i = 0, NextEntry = DriverList.Flink;
+         NextEntry != &DriverList;
+         i++, NextEntry = NextEntry->Flink)
+    {
+        /* Get the entry */
+        DriverEntry = CONTAINING_RECORD(NextEntry, BOOT_DRIVER_LIST_ENTRY, Link);
+
+        /* Allocate the path for the caller and duplicate the registry path */
+        ServicePath[i] = ExAllocatePool(NonPagedPool, sizeof(UNICODE_STRING));
+        RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
+                                  &DriverEntry->RegistryPath,
+                                  ServicePath[i]);
+    }
+    
+    /* Terminate the list */
+    ServicePath[i] = NULL;
+    
+EndPath:
+    /* Free the driver list if we had one */
+    if (!IsListEmpty(&DriverList)) CmpFreeDriverList(Hive, &DriverList);
+    
+    /* Unlock the registry */
+    CmpUnlockRegistry();
+    
+    /* Close the key handle and dereference the object, then return the path */
+    ObDereferenceObject(KeyBody);
+    NtClose(KeyHandle);
+    return ServicePath;
+}
+
 VOID
 NTAPI
 CmpLockRegistryExclusive(VOID)
@@ -1771,3 +1928,5 @@ CmShutdownSystem(VOID)
     if (!CmFirstTime) CmpShutdownWorkers();
     CmpDoFlushAll(TRUE);
 }
+
+/* EOF */
index 4880dc0..62f4010 100644 (file)
@@ -1522,6 +1522,40 @@ CmSetLazyFlushState(
     IN BOOLEAN Enable
 );
 
+//
+// Driver List Routines
+//
+PUNICODE_STRING*
+NTAPI
+CmGetSystemDriverList(
+    VOID
+);
+
+BOOLEAN
+NTAPI
+CmpFindDrivers(
+    IN PHHIVE Hive,
+    IN HCELL_INDEX ControlSet,
+    IN SERVICE_LOAD_TYPE LoadType,
+    IN PWSTR BootFileSystem OPTIONAL,
+    IN PLIST_ENTRY DriverListHead
+);
+
+
+BOOLEAN
+NTAPI
+CmpSortDriverList(
+    IN PHHIVE Hive,
+    IN HCELL_INDEX ControlSet,
+    IN PLIST_ENTRY DriverListHead
+);
+
+BOOLEAN
+NTAPI
+CmpResolveDriverDependencies(
+    IN PLIST_ENTRY DriverListHead
+);
+
 //
 // Global variables accessible from all of Cm
 //
index c8b6716..dc80ff2 100644 (file)
@@ -395,6 +395,33 @@ typedef struct _LOAD_UNLOAD_PARAMS
     PDRIVER_OBJECT DriverObject;
 } LOAD_UNLOAD_PARAMS, *PLOAD_UNLOAD_PARAMS;
 
+//
+// Boot Driver List Entry
+//
+typedef struct _DRIVER_INFORMATION
+{
+    LIST_ENTRY Link;
+    PDRIVER_OBJECT DriverObject;
+    PBOOT_DRIVER_LIST_ENTRY DataTableEntry;
+    HANDLE ServiceHandle;
+    USHORT TagPosition;
+    ULONG Failed;
+    ULONG Processed;
+    NTSTATUS Status;
+} DRIVER_INFORMATION, *PDRIVER_INFORMATION;
+
+//
+// Boot Driver Node
+//
+typedef struct _BOOT_DRIVER_NODE
+{
+    BOOT_DRIVER_LIST_ENTRY ListEntry;
+    UNICODE_STRING Group;
+    UNICODE_STRING Name;
+    ULONG Tag;
+    ULONG ErrorControl;
+} BOOT_DRIVER_NODE, *PBOOT_DRIVER_NODE;
 //
 // List of Bus Type GUIDs
 //
@@ -605,6 +632,43 @@ IopGetRegistryValue(IN HANDLE Handle,
                     OUT PKEY_VALUE_FULL_INFORMATION *Information);
 
 
+//
+// PnP Routines
+//
+NTSTATUS
+NTAPI
+PiInitCacheGroupInformation(
+    VOID
+);
+
+USHORT
+NTAPI
+PpInitGetGroupOrderIndex(
+    IN HANDLE ServiceHandle
+);
+
+USHORT
+NTAPI
+PipGetDriverTagPriority(
+    IN HANDLE ServiceHandle
+);
+
+NTSTATUS
+NTAPI
+PnpRegMultiSzToUnicodeStrings(
+    IN PKEY_VALUE_FULL_INFORMATION KeyValueInformation,
+    OUT PUNICODE_STRING *UnicodeStringList,
+    OUT PULONG UnicodeStringCount
+);
+
+BOOLEAN
+NTAPI
+PnpRegSzToString(
+    IN PWCHAR RegSzData,
+    IN ULONG RegSzLength,
+    OUT PUSHORT StringLength OPTIONAL
+);
+                                               
 //
 // Initialization Routines
 //
@@ -852,7 +916,8 @@ PnpRootDriverEntry(
 NTSTATUS
 PnpRootCreateDevice(
     IN PUNICODE_STRING ServiceName,
-    IN OUT PDEVICE_OBJECT *PhysicalDeviceObject
+    OUT PDEVICE_OBJECT *PhysicalDeviceObject,
+    OUT OPTIONAL PUNICODE_STRING FullInstancePath
 );
 
 //
index cc6d544..d5b2246 100644 (file)
@@ -50,7 +50,159 @@ IoOpenDeviceInterfaceRegistryKey(IN PUNICODE_STRING SymbolicLinkName,
                                  IN ACCESS_MASK DesiredAccess,
                                  OUT PHANDLE DeviceInterfaceKey)
 {
-    return STATUS_NOT_IMPLEMENTED;
+    WCHAR StrBuff[MAX_PATH], PathBuff[MAX_PATH];
+    PWCHAR Guid, RefString;
+    UNICODE_STRING DevParamU = RTL_CONSTANT_STRING(L"\\Device Parameters");
+    UNICODE_STRING PrefixU = RTL_CONSTANT_STRING(L"\\??\\");
+    UNICODE_STRING KeyPath, KeyName;
+    UNICODE_STRING MatchableGuid;
+    UNICODE_STRING GuidString;
+    HANDLE GuidKey, hInterfaceKey;
+    ULONG Index = 0;
+    PKEY_BASIC_INFORMATION KeyInformation;
+    ULONG KeyInformationLength;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    NTSTATUS Status;
+    ULONG RequiredLength;
+
+    swprintf(StrBuff, L"##?#%s", &SymbolicLinkName->Buffer[PrefixU.Length / sizeof(WCHAR)]);
+
+    RefString = wcsstr(StrBuff, L"\\");
+    if (RefString)
+    {
+        RefString[0] = 0;
+    }
+
+    RtlInitUnicodeString(&MatchableGuid, StrBuff);
+
+    Guid = wcsstr(StrBuff, L"{");
+    if (!Guid)
+        return STATUS_OBJECT_NAME_NOT_FOUND;
+
+    KeyPath.Buffer = PathBuff;
+    KeyPath.Length = 0;
+    KeyPath.MaximumLength = MAX_PATH * sizeof(WCHAR);
+
+    GuidString.Buffer = Guid;
+    GuidString.Length = GuidString.MaximumLength = 38 * sizeof(WCHAR);
+
+    RtlAppendUnicodeToString(&KeyPath, BaseKeyString);
+    RtlAppendUnicodeStringToString(&KeyPath, &GuidString);
+
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyPath,
+                               OBJ_CASE_INSENSITIVE,
+                               0,
+                               NULL);
+
+    Status = ZwOpenKey(&GuidKey, KEY_CREATE_SUB_KEY, &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+        return Status;
+
+    while (TRUE)
+    {
+        Status = ZwEnumerateKey(GuidKey,
+                                Index,
+                                KeyBasicInformation,
+                                NULL,
+                                0,
+                                &RequiredLength);
+        if (Status == STATUS_NO_MORE_ENTRIES)
+            break;
+        else if (Status == STATUS_BUFFER_TOO_SMALL)
+        {
+            KeyInformationLength = RequiredLength;
+            KeyInformation = ExAllocatePool(PagedPool, KeyInformationLength);
+            if (!KeyInformation)
+            {
+                ZwClose(GuidKey);
+                return STATUS_INSUFFICIENT_RESOURCES;
+            }
+
+            Status = ZwEnumerateKey(GuidKey,
+                                    Index,
+                                    KeyBasicInformation,
+                                    KeyInformation,
+                                    KeyInformationLength,
+                                    &RequiredLength);
+        }
+        else
+        {
+            ZwClose(GuidKey);
+            return STATUS_OBJECT_PATH_NOT_FOUND;
+        }
+        Index++;
+
+        if (!NT_SUCCESS(Status))
+        {
+            ZwClose(GuidKey);
+            return Status;
+        }
+
+        KeyName.Length = KeyName.MaximumLength = KeyInformation->NameLength;
+        KeyName.Buffer = KeyInformation->Name;
+
+        if (!RtlEqualUnicodeString(&KeyName, &MatchableGuid, TRUE))
+        {
+            ExFreePool(KeyInformation);
+            continue;
+        }
+
+        KeyPath.Length = 0;
+        RtlAppendUnicodeStringToString(&KeyPath, &KeyName);
+        RtlAppendUnicodeToString(&KeyPath, L"\\");
+
+        /* check for presence of a reference string */
+        if (RefString)
+        {
+            /* append reference string */
+            RefString[0] = L'#';
+            RtlInitUnicodeString(&KeyName, RefString);
+        }
+        else
+        {
+            /* no reference string */
+            RtlInitUnicodeString(&KeyName, L"#");
+        }
+        RtlAppendUnicodeStringToString(&KeyPath, &KeyName);
+
+        /* initialize reference string attributes */
+        InitializeObjectAttributes(&ObjectAttributes,
+                                   &KeyPath,
+                                   OBJ_CASE_INSENSITIVE,
+                                   GuidKey,
+                                   NULL);
+
+        /* now open device interface key */
+        Status = ZwOpenKey(&hInterfaceKey, KEY_CREATE_SUB_KEY, &ObjectAttributes);
+
+        if (NT_SUCCESS(Status))
+        {
+            /* check if it provides a DeviceParameters key */
+            InitializeObjectAttributes(&ObjectAttributes, &DevParamU, OBJ_CASE_INSENSITIVE, hInterfaceKey, NULL);
+
+             Status = ZwCreateKey(DeviceInterfaceKey, DesiredAccess, &ObjectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, NULL);
+
+             if (NT_SUCCESS(Status))
+             {
+                 /* DeviceParameters key present */
+                 ZwClose(hInterfaceKey);
+             }
+             else
+             {
+                 /* fall back to device interface */
+                 *DeviceInterfaceKey = hInterfaceKey;
+                 Status = STATUS_SUCCESS;
+             }
+        }
+
+        /* close class key */
+        ZwClose(GuidKey);
+        ExFreePool(KeyInformation);
+        return Status;
+    }
+
+    return STATUS_OBJECT_PATH_NOT_FOUND;
 }
 
 /*++
@@ -909,6 +1061,7 @@ IoRegisterDeviceInterface(IN PDEVICE_OBJECT PhysicalDeviceObject,
         RtlAppendUnicodeStringToString(SymbolicLinkName, ReferenceString);
     }
     SymbolicLinkName->Buffer[SymbolicLinkName->Length/sizeof(WCHAR)] = L'\0';
+    SymbolicLinkName->Length += sizeof(WCHAR);
 
     /* Write symbolic link name in registry */
     SymbolicLinkName->Buffer[1] = '\\';
index ef1b789..18202bf 100644 (file)
@@ -34,6 +34,9 @@ POBJECT_TYPE IoDriverObjectType = NULL;
 extern BOOLEAN ExpInTextModeSetup;
 extern BOOLEAN PnpSystemInit;
 
+USHORT IopGroupIndex;
+PLIST_ENTRY IopGroupTable;
+
 /* PRIVATE FUNCTIONS **********************************************************/
 
 NTSTATUS NTAPI
@@ -197,6 +200,7 @@ IopDisplayLoadingMessage(PUNICODE_STRING ServiceName)
     UNICODE_STRING DotSys = RTL_CONSTANT_STRING(L".SYS");
 
     if (ExpInTextModeSetup) return;
+    if (!KeLoaderBlock) return;
     RtlUpcaseUnicodeString(ServiceName, ServiceName, FALSE);
     snprintf(TextBuffer, sizeof(TextBuffer),
             "%s%sSystem32\\Drivers\\%wZ%s\n",
@@ -880,14 +884,17 @@ VOID
 FASTCALL
 IopInitializeBootDrivers(VOID)
 {
-    PLIST_ENTRY ListHead, NextEntry;
+    PLIST_ENTRY ListHead, NextEntry, NextEntry2;
     PLDR_DATA_TABLE_ENTRY LdrEntry;
     PDEVICE_NODE DeviceNode;
     PDRIVER_OBJECT DriverObject;
     LDR_DATA_TABLE_ENTRY ModuleObject;
     NTSTATUS Status;
     UNICODE_STRING DriverName;
-
+    ULONG i, Index;
+    PDRIVER_INFORMATION DriverInfo, DriverInfoTag;
+    HANDLE KeyHandle;
+    PBOOT_DRIVER_LIST_ENTRY BootEntry;
     DPRINT("IopInitializeBootDrivers()\n");
 
     /* Use IopRootDeviceNode for now */
@@ -931,6 +938,19 @@ IopInitializeBootDrivers(VOID)
         return;
     }
 
+    /* Get highest group order index */
+    IopGroupIndex = PpInitGetGroupOrderIndex(NULL);
+    if (IopGroupIndex == 0xFFFF) ASSERT(FALSE);
+    
+    /* Allocate the group table */
+    IopGroupTable = ExAllocatePoolWithTag(PagedPool,
+                                          IopGroupIndex * sizeof(LIST_ENTRY),
+                                          TAG_IO);
+    if (IopGroupTable == NULL) ASSERT(FALSE);
+    
+    /* Initialize the group table lists */
+    for (i = 0; i < IopGroupIndex; i++) InitializeListHead(&IopGroupTable[i]);
+    
     /* Loop the boot modules */
     ListHead = &KeLoaderBlock->LoadOrderListHead;
     NextEntry = ListHead->Flink;
@@ -940,19 +960,83 @@ IopInitializeBootDrivers(VOID)
         LdrEntry = CONTAINING_RECORD(NextEntry,
                                      LDR_DATA_TABLE_ENTRY,
                                      InLoadOrderLinks);
-
-        /*
-         * HACK: Make sure we're loading a driver
-         * (we should be using BootDriverListHead!)
-         */
-        if (wcsstr(_wcsupr(LdrEntry->BaseDllName.Buffer), L".SYS"))
+                                     
+        /* Check if the DLL needs to be initialized */
+        if (LdrEntry->Flags & LDRP_DRIVER_DEPENDENT_DLL)
+        {
+            /* 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);
             }
         }
 
@@ -960,10 +1044,65 @@ IopInitializeBootDrivers(VOID)
         NextEntry = NextEntry->Flink;
     }
 
+    /* Loop each group index */
+    for (i = 0; i < IopGroupIndex; i++)
+    {
+        /* Loop each group table */
+        NextEntry = IopGroupTable[i].Flink;
+        while (NextEntry != &IopGroupTable[i])
+        {
+            /* Get the entry */
+            DriverInfo = CONTAINING_RECORD(NextEntry,
+                                           DRIVER_INFORMATION,
+                                           Link);
+            
+            /* Get the driver loader entry */
+            LdrEntry = DriverInfo->DataTableEntry->LdrEntry;
+            
+            /* Initialize it */
+            IopInitializeBuiltinDriver(LdrEntry);
+            
+            /* Next entry */
+            NextEntry = NextEntry->Flink;
+        }
+    }
+    
     /* In old ROS, the loader list became empty after this point. Simulate. */
     InitializeListHead(&KeLoaderBlock->LoadOrderListHead);
 }
 
+VOID
+FASTCALL
+IopInitializeSystemDrivers(VOID)
+{
+    PUNICODE_STRING *DriverList, *SavedList;
+    
+    /* No system drivers on the boot cd */
+    if (KeLoaderBlock->SetupLdrBlock) return;
+    
+    /* Get the driver list */
+    SavedList = DriverList = CmGetSystemDriverList();
+    ASSERT(DriverList);
+    
+    /* Loop it */
+    while (*DriverList)
+    {
+        /* Load the driver */
+        ZwLoadDriver(*DriverList);
+        
+        /* Free the entry */
+        RtlFreeUnicodeString(*DriverList);
+        ExFreePool(*DriverList);
+        
+        /* Next entry */
+        InbvIndicateProgress();
+        DriverList++;
+    }
+
+    /* Free the list */
+    ExFreePool(SavedList);
+}
+
 /*
  * IopUnloadDriver
  *
@@ -1685,6 +1824,8 @@ IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams)
       cur--;
    }
 
+   IopDisplayLoadingMessage(&ServiceName);
+
    /*
     * Get service type.
     */
diff --git a/ntoskrnl/io/iomgr/drvrlist.c b/ntoskrnl/io/iomgr/drvrlist.c
deleted file mode 100644 (file)
index e15aab2..0000000
+++ /dev/null
@@ -1,561 +0,0 @@
-/*
- * PROJECT:         ReactOS Kernel
- * LICENSE:         GPL - See COPYING in the top level directory
- * FILE:            ntoskrnl/io/iomgr/drvrlist.c
- * PURPOSE:         Driver List support for Grouping, Tagging, Sorting, etc.
- * PROGRAMMERS:     <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");
-}
index cb32297..e52f2fe 100644 (file)
@@ -489,9 +489,9 @@ IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 
     /* Initialize PnP manager */
     PnpInit();
-
-    /* Create the group driver list */
-    IoCreateDriverList();
+    
+    /* Setup the group cache */
+    if (!NT_SUCCESS(PiInitCacheGroupInformation())) return FALSE;
 
     /* Load boot start drivers */
     IopInitializeBootDrivers();
@@ -530,9 +530,6 @@ IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
     IopInitializeSystemDrivers();
     PnpSystemInit = TRUE;
 
-    /* Destroy the group driver list */
-    IoDestroyDriverList();
-
     /* Reinitialize drivers that requested it */
     IopReinitializeDrivers();
 
diff --git a/ntoskrnl/io/pnpmgr/pnpinit.c b/ntoskrnl/io/pnpmgr/pnpinit.c
new file mode 100644 (file)
index 0000000..8c56072
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            ntoskrnl/io/pnpmgr/pnpinit.c
+ * PURPOSE:         PnP Initialization Code
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <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 */
index 502787f..0213d04 100644 (file)
@@ -46,15 +46,25 @@ typedef struct _INVALIDATE_DEVICE_RELATION_DATA
 
 /* FUNCTIONS *****************************************************************/
 
-static NTSTATUS
+NTSTATUS
 IopAssignDeviceResources(
    IN PDEVICE_NODE DeviceNode,
    OUT ULONG *pRequiredSize);
-static NTSTATUS
+
+NTSTATUS
 IopTranslateDeviceResources(
    IN PDEVICE_NODE DeviceNode,
    IN ULONG RequiredSize);
 
+NTSTATUS
+IopUpdateResourceMapForPnPDevice(
+   IN PDEVICE_NODE DeviceNode);
+
+NTSTATUS
+NTAPI
+IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath,
+                       OUT PHANDLE Handle);
+
 PDEVICE_NODE
 FASTCALL
 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject)
@@ -136,6 +146,9 @@ IopStartDevice(
    IO_STACK_LOCATION Stack;
    ULONG RequiredLength;
    NTSTATUS Status;
+   HANDLE InstanceHandle, ControlHandle;
+   UNICODE_STRING KeyName;
+   OBJECT_ATTRIBUTES ObjectAttributes;
 
    IopDeviceNodeSetFlag(DeviceNode, DNF_ASSIGNING_RESOURCES);
    DPRINT("Sending IRP_MN_FILTER_RESOURCE_REQUIREMENTS to device stack\n");
@@ -150,7 +163,10 @@ IopStartDevice(
       DPRINT("IopInitiatePnpIrp(IRP_MN_FILTER_RESOURCE_REQUIREMENTS) failed\n");
       return Status;
    }
-   DeviceNode->ResourceRequirements = (PIO_RESOURCE_REQUIREMENTS_LIST)IoStatusBlock.Information;
+   else if (NT_SUCCESS(Status))
+   {
+      DeviceNode->ResourceRequirements = (PIO_RESOURCE_REQUIREMENTS_LIST)IoStatusBlock.Information;
+   }
 
    Status = IopAssignDeviceResources(DeviceNode, &RequiredLength);
    if (NT_SUCCESS(Status))
@@ -158,7 +174,11 @@ IopStartDevice(
       Status = IopTranslateDeviceResources(DeviceNode, RequiredLength);
       if (NT_SUCCESS(Status))
       {
-         IopDeviceNodeSetFlag(DeviceNode, DNF_RESOURCE_ASSIGNED);
+         Status = IopUpdateResourceMapForPnPDevice(DeviceNode);
+         if (!NT_SUCCESS(Status))
+         {
+             DPRINT("IopUpdateResourceMap() failed (Status 0x%08lx)\n", Status);
+         }
       }
       else
       {
@@ -206,9 +226,32 @@ IopStartDevice(
       }
    }
 
+   Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, &InstanceHandle);
+   if (!NT_SUCCESS(Status))
+       return Status;
+
+   RtlInitUnicodeString(&KeyName, L"Control");
+   InitializeObjectAttributes(&ObjectAttributes,
+                              &KeyName,
+                              OBJ_CASE_INSENSITIVE,
+                              InstanceHandle,
+                              NULL);
+   Status = ZwCreateKey(&ControlHandle, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL);
+   if (!NT_SUCCESS(Status))
+   {
+       ZwClose(InstanceHandle);
+       return Status;
+   }
+
+   RtlInitUnicodeString(&KeyName, L"ActiveService");
+   Status = ZwSetValueKey(ControlHandle, &KeyName, 0, REG_SZ, DeviceNode->ServiceName.Buffer, DeviceNode->ServiceName.Length);
+
    if (NT_SUCCESS(Status))
        IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED);
 
+   ZwClose(ControlHandle);
+   ZwClose(InstanceHandle);
+
    return Status;
 }
 
@@ -361,6 +404,10 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode,
    PDEVICE_NODE Node;
    NTSTATUS Status;
    KIRQL OldIrql;
+   UNICODE_STRING FullServiceName;
+   UNICODE_STRING LegacyPrefix = RTL_CONSTANT_STRING(L"LEGACY_");
+   UNICODE_STRING UnknownDeviceName = RTL_CONSTANT_STRING(L"UNKNOWN");
+   HANDLE TempHandle;
 
    DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
       ParentNode, PhysicalDeviceObject, ServiceName);
@@ -373,9 +420,24 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode,
 
    RtlZeroMemory(Node, sizeof(DEVICE_NODE));
 
+   if (!ServiceName)
+       ServiceName = &UnknownDeviceName;
+
    if (!PhysicalDeviceObject)
    {
-      Status = PnpRootCreateDevice(ServiceName, &PhysicalDeviceObject);
+      FullServiceName.MaximumLength = LegacyPrefix.Length + ServiceName->Length;
+      FullServiceName.Length = 0;
+      FullServiceName.Buffer = ExAllocatePool(PagedPool, FullServiceName.MaximumLength);
+      if (!FullServiceName.Buffer)
+      {
+          ExFreePool(Node);
+          return STATUS_INSUFFICIENT_RESOURCES;
+      }
+
+      RtlAppendUnicodeStringToString(&FullServiceName, &LegacyPrefix);
+      RtlAppendUnicodeStringToString(&FullServiceName, ServiceName);
+
+      Status = PnpRootCreateDevice(&FullServiceName, &PhysicalDeviceObject, &Node->InstancePath);
       if (!NT_SUCCESS(Status))
       {
          DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status);
@@ -383,6 +445,13 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode,
          return Status;
       }
 
+      /* Create the device key for legacy drivers */
+      Status = IopCreateDeviceKeyPath(&Node->InstancePath, &TempHandle);
+      if (NT_SUCCESS(Status))
+          ZwClose(TempHandle);
+
+      ExFreePool(FullServiceName.Buffer);
+
       /* This is for drivers passed on the command line to ntoskrnl.exe */
       IopDeviceNodeSetFlag(Node, DNF_STARTED);
       IopDeviceNodeSetFlag(Node, DNF_LEGACY_DRIVER);
@@ -708,8 +777,135 @@ IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath,
     return STATUS_UNSUCCESSFUL;
 }
 
+NTSTATUS
+IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode, PWCHAR Level1Key, PWCHAR Level2Key)
+{
+  NTSTATUS Status;
+  ULONG Disposition;
+  HANDLE PnpMgrLevel1, PnpMgrLevel2, ResourceMapKey;
+  UNICODE_STRING KeyName;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+
+  RtlInitUnicodeString(&KeyName,
+                      L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &KeyName,
+                            OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
+                            0,
+                            NULL);
+  Status = ZwCreateKey(&ResourceMapKey,
+                      KEY_ALL_ACCESS,
+                      &ObjectAttributes,
+                      0,
+                      NULL,
+                      REG_OPTION_VOLATILE,
+                      &Disposition);
+  if (!NT_SUCCESS(Status))
+      return Status;
+
+  RtlInitUnicodeString(&KeyName, Level1Key);
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &KeyName,
+                            OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
+                            ResourceMapKey,
+                            NULL);
+  Status = ZwCreateKey(&PnpMgrLevel1,
+                       KEY_ALL_ACCESS,
+                       &ObjectAttributes,
+                       0,
+                       NULL,
+                       REG_OPTION_VOLATILE,
+                       &Disposition);
+  ZwClose(ResourceMapKey);
+  if (!NT_SUCCESS(Status))
+      return Status;
+
+  RtlInitUnicodeString(&KeyName, Level2Key);
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &KeyName,
+                            OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
+                            PnpMgrLevel1,
+                            NULL);
+  Status = ZwCreateKey(&PnpMgrLevel2,
+                       KEY_ALL_ACCESS,
+                       &ObjectAttributes,
+                       0,
+                       NULL,
+                       REG_OPTION_VOLATILE,
+                       &Disposition);
+  ZwClose(PnpMgrLevel1);
+  if (!NT_SUCCESS(Status))
+      return Status;
+
+  if (DeviceNode->ResourceList)
+  {
+      WCHAR NameBuff[256];
+      UNICODE_STRING NameU;
+      UNICODE_STRING Suffix;
+      ULONG OldLength;
+
+      ASSERT(DeviceNode->ResourceListTranslated);
+
+      NameU.Buffer = NameBuff;
+      NameU.Length = 0;
+      NameU.MaximumLength = 256 * sizeof(WCHAR);
+
+      Status = IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject,
+                                   DevicePropertyPhysicalDeviceObjectName,
+                                   NameU.MaximumLength,
+                                   NameU.Buffer,
+                                   &OldLength);
+      ASSERT(Status == STATUS_SUCCESS);
+
+      NameU.Length = (USHORT)OldLength;
+
+      RtlInitUnicodeString(&Suffix, L".Raw");
+      RtlAppendUnicodeStringToString(&NameU, &Suffix);
+
+      Status = ZwSetValueKey(PnpMgrLevel2,
+                             &NameU,
+                             0,
+                             REG_RESOURCE_LIST,
+                             DeviceNode->ResourceList,
+                             CM_RESOURCE_LIST_SIZE(DeviceNode->ResourceList));
+      if (!NT_SUCCESS(Status))
+      {
+          ZwClose(PnpMgrLevel2);
+          return Status;
+      }
+
+      /* "Remove" the suffix by setting the length back to what it used to be */
+      NameU.Length = (USHORT)OldLength;
+
+      RtlInitUnicodeString(&Suffix, L".Translated");
+      RtlAppendUnicodeStringToString(&NameU, &Suffix);
+
+      Status = ZwSetValueKey(PnpMgrLevel2,
+                             &NameU,
+                             0,
+                             REG_RESOURCE_LIST,
+                             DeviceNode->ResourceListTranslated,
+                             CM_RESOURCE_LIST_SIZE(DeviceNode->ResourceListTranslated));
+      ZwClose(PnpMgrLevel2);
+      if (!NT_SUCCESS(Status))
+          return Status;
+  }
+  else
+  {
+      ZwClose(PnpMgrLevel2);
+  }
+
+  IopDeviceNodeSetFlag(DeviceNode, DNF_RESOURCE_ASSIGNED);
+
+  return STATUS_SUCCESS;
+}
+
+NTSTATUS
+IopUpdateResourceMapForPnPDevice(IN PDEVICE_NODE DeviceNode)
+{
+  return IopUpdateResourceMap(DeviceNode, L"PnP Manager", L"PnpManager");
+}
 
-static
 NTSTATUS
 IopSetDeviceInstanceData(HANDLE InstanceKey,
                          PDEVICE_NODE DeviceNode)
@@ -720,6 +916,7 @@ IopSetDeviceInstanceData(HANDLE InstanceKey,
    ULONG ResCount;
    ULONG ListSize, ResultLength;
    NTSTATUS Status;
+   HANDLE ControlHandle;
 
    DPRINT("IopSetDeviceInstanceData() called\n");
 
@@ -793,24 +990,718 @@ IopSetDeviceInstanceData(HANDLE InstanceKey,
                            sizeof(DefaultConfigFlags));
   }
 
+   /* Create the 'Control' key */
+   RtlInitUnicodeString(&KeyName, L"Control");
+   InitializeObjectAttributes(&ObjectAttributes,
+                              &KeyName,
+                              OBJ_CASE_INSENSITIVE,
+                              InstanceKey,
+                              NULL);
+   Status = ZwCreateKey(&ControlHandle, 0, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL);
+
+   if (NT_SUCCESS(Status))
+       ZwClose(ControlHandle);
+
   DPRINT("IopSetDeviceInstanceData() done\n");
 
-  return STATUS_SUCCESS;
+  return Status;
+}
+
+BOOLEAN
+IopCheckResourceDescriptor(
+   IN PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc,
+   IN PCM_RESOURCE_LIST ResourceList,
+   IN BOOLEAN Silent,
+   OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor)
+{
+   ULONG i, ii;
+   BOOLEAN Result = FALSE;
+
+   if (ResDesc->ShareDisposition == CmResourceShareShared)
+       return FALSE;
+
+   for (i = 0; i < ResourceList->Count; i++)
+   {
+      PCM_PARTIAL_RESOURCE_LIST ResList = &ResourceList->List[i].PartialResourceList;
+      for (ii = 0; ii < ResList->Count; ii++)
+      {
+         PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc2 = &ResList->PartialDescriptors[ii];
+
+         /* We don't care about shared resources */
+         if (ResDesc->ShareDisposition == CmResourceShareShared &&
+             ResDesc2->ShareDisposition == CmResourceShareShared)
+             continue;
+
+         /* Make sure we're comparing the same types */
+         if (ResDesc->Type != ResDesc2->Type)
+             continue;
+
+         switch (ResDesc->Type)
+         {
+             case CmResourceTypeMemory:
+                 if ((ResDesc->u.Memory.Start.QuadPart < ResDesc2->u.Memory.Start.QuadPart &&
+                      ResDesc->u.Memory.Start.QuadPart + ResDesc->u.Memory.Length >
+                      ResDesc2->u.Memory.Start.QuadPart) || (ResDesc2->u.Memory.Start.QuadPart <
+                      ResDesc->u.Memory.Start.QuadPart && ResDesc2->u.Memory.Start.QuadPart +
+                      ResDesc2->u.Memory.Length > ResDesc->u.Memory.Start.QuadPart))
+                 {
+                      if (!Silent)
+                      {
+                          DPRINT1("Resource conflict: Memory (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
+                                  ResDesc->u.Memory.Start.QuadPart, ResDesc->u.Memory.Start.QuadPart +
+                                  ResDesc->u.Memory.Length, ResDesc2->u.Memory.Start.QuadPart,
+                                  ResDesc2->u.Memory.Start.QuadPart + ResDesc2->u.Memory.Length);
+                      }
+
+                      Result = TRUE;
+
+                      goto ByeBye;
+                 }
+                 break;
+
+             case CmResourceTypePort:
+                 if ((ResDesc->u.Port.Start.QuadPart < ResDesc2->u.Port.Start.QuadPart &&
+                      ResDesc->u.Port.Start.QuadPart + ResDesc->u.Port.Length >
+                      ResDesc2->u.Port.Start.QuadPart) || (ResDesc2->u.Port.Start.QuadPart <
+                      ResDesc->u.Port.Start.QuadPart && ResDesc2->u.Port.Start.QuadPart +
+                      ResDesc2->u.Port.Length > ResDesc->u.Port.Start.QuadPart))
+                 {
+                      if (!Silent)
+                      {
+                          DPRINT1("Resource conflict: Port (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
+                                  ResDesc->u.Port.Start.QuadPart, ResDesc->u.Port.Start.QuadPart +
+                                  ResDesc->u.Port.Length, ResDesc2->u.Port.Start.QuadPart,
+                                  ResDesc2->u.Port.Start.QuadPart + ResDesc2->u.Port.Length);
+                      }
+
+                      Result = TRUE;
+
+                      goto ByeBye;
+                 }
+                 break;
+
+             case CmResourceTypeInterrupt:
+                 if (ResDesc->u.Interrupt.Vector == ResDesc2->u.Interrupt.Vector)
+                 {
+                      if (!Silent)
+                      {
+                          DPRINT1("Resource conflict: IRQ (0x%x 0x%x vs. 0x%x 0x%x)\n",
+                                  ResDesc->u.Interrupt.Vector, ResDesc->u.Interrupt.Level,
+                                  ResDesc2->u.Interrupt.Vector, ResDesc2->u.Interrupt.Level);
+                      }
+
+                      Result = TRUE;
+
+                      goto ByeBye;
+                 }
+                 break;
+
+             case CmResourceTypeBusNumber:
+                 if ((ResDesc->u.BusNumber.Start < ResDesc2->u.BusNumber.Start &&
+                      ResDesc->u.BusNumber.Start + ResDesc->u.BusNumber.Length >
+                      ResDesc2->u.BusNumber.Start) || (ResDesc2->u.BusNumber.Start <
+                      ResDesc->u.BusNumber.Start && ResDesc2->u.BusNumber.Start +
+                      ResDesc2->u.BusNumber.Length > ResDesc->u.BusNumber.Start))
+                 {
+                      if (!Silent)
+                      {
+                          DPRINT1("Resource conflict: Bus number (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
+                                  ResDesc->u.BusNumber.Start, ResDesc->u.BusNumber.Start +
+                                  ResDesc->u.BusNumber.Length, ResDesc2->u.BusNumber.Start,
+                                  ResDesc2->u.BusNumber.Start + ResDesc2->u.BusNumber.Length);
+                      }
+
+                      Result = TRUE;
+
+                      goto ByeBye;
+                 }
+                 break;
+
+             case CmResourceTypeDma:
+                 if (ResDesc->u.Dma.Channel == ResDesc2->u.Dma.Channel)
+                 {
+                     if (!Silent)
+                     {
+                         DPRINT1("Resource conflict: Dma (0x%x 0x%x vs. 0x%x 0x%x)\n",
+                                 ResDesc->u.Dma.Channel, ResDesc->u.Dma.Port,
+                                 ResDesc2->u.Dma.Channel, ResDesc2->u.Dma.Port);
+                     }
+
+                     Result = TRUE;
+
+                     goto ByeBye;
+                 }
+                 break;
+         }
+      }
+   }
+
+ByeBye:
+
+   if (Result && ConflictingDescriptor)
+   {
+       RtlCopyMemory(ConflictingDescriptor,
+                     ResDesc,
+                     sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+   }
+
+   return Result;
+}
+
+
+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)
@@ -823,7 +1714,7 @@ IopAssignDeviceResources(
 
    /* Fill DeviceNode->ResourceList
     * FIXME: the PnP arbiter should go there!
-    * Actually, use the BootResources if provided, else the resource list #0
+    * Actually, use the BootResources if provided, else the resource requirements
     */
 
    if (DeviceNode->BootResources)
@@ -850,155 +1741,40 @@ IopAssignDeviceResources(
       }
       RtlCopyMemory(DeviceNode->ResourceList, DeviceNode->BootResources, Size);
 
-      *pRequiredSize = Size;
-      return STATUS_SUCCESS;
-   }
-
-   /* Ok, here, we have to use the device requirement list */
-   ResourceList = &DeviceNode->ResourceRequirements->List[0];
-   if (ResourceList->Version != 1 || ResourceList->Revision != 1)
-   {
-      Status = STATUS_REVISION_MISMATCH;
-      goto ByeBye;
-   }
+      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;
@@ -1014,7 +1790,7 @@ ByeBye:
 }
 
 
-static NTSTATUS
+NTSTATUS
 IopTranslateDeviceResources(
    IN PDEVICE_NODE DeviceNode,
    IN ULONG RequiredSize)
@@ -2140,7 +2916,6 @@ IopEnumerateDetectedDevices(
    IN ULONG ParentBootResourcesLength)
 {
    UNICODE_STRING IdentifierU = RTL_CONSTANT_STRING(L"Identifier");
-   UNICODE_STRING DeviceDescU = RTL_CONSTANT_STRING(L"DeviceDesc");
    UNICODE_STRING HardwareIDU = RTL_CONSTANT_STRING(L"HardwareID");
    UNICODE_STRING ConfigurationDataU = RTL_CONSTANT_STRING(L"Configuration Data");
    UNICODE_STRING BootConfigU = RTL_CONSTANT_STRING(L"BootConfig");
@@ -2187,7 +2962,8 @@ IopEnumerateDetectedDevices(
    UNICODE_STRING HardwareIdKey;
    PUNICODE_STRING pHardwareId;
    ULONG DeviceIndex = 0;
-   BOOLEAN IsDeviceDesc;
+   PUCHAR CmResourceList;
+   ULONG ListCount;
 
     if (RelativePath)
     {
@@ -2302,7 +3078,7 @@ IopEnumerateDetectedDevices(
             DPRINT("ExAllocatePool() failed\n");
             goto nextdevice;
          }
-         if (ParentBootResourcesLength == 0)
+         if (ParentBootResourcesLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR))
          {
             RtlCopyMemory(BootResources, pValueInformation->Data, pValueInformation->DataLength);
          }
@@ -2414,31 +3190,26 @@ IopEnumerateDetectedDevices(
       {
          pHardwareId = &HardwareIdSerial;
          DeviceIndex = DeviceIndexSerial++;
-         IsDeviceDesc = TRUE;
       }
       else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierKeyboard, FALSE) == 0)
       {
          pHardwareId = &HardwareIdKeyboard;
          DeviceIndex = DeviceIndexKeyboard++;
-         IsDeviceDesc = FALSE;
       }
       else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierMouse, FALSE) == 0)
       {
          pHardwareId = &HardwareIdMouse;
          DeviceIndex = DeviceIndexMouse++;
-         IsDeviceDesc = FALSE;
       }
       else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierParallel, FALSE) == 0)
       {
          pHardwareId = &HardwareIdParallel;
          DeviceIndex = DeviceIndexParallel++;
-         IsDeviceDesc = FALSE;
       }
       else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierFloppy, FALSE) == 0)
       {
          pHardwareId = &HardwareIdFloppy;
          DeviceIndex = DeviceIndexFloppy++;
-         IsDeviceDesc = FALSE;
       }
       else if (NT_SUCCESS(Status))
       {
@@ -2447,13 +3218,11 @@ IopEnumerateDetectedDevices(
          {
             pHardwareId = &HardwareIdPci;
             DeviceIndex = DeviceIndexPci++;
-            IsDeviceDesc = FALSE;
          }
          else if (RtlCompareUnicodeString(&ValueName, &IdentifierIsa, FALSE) == 0)
          {
             pHardwareId = &HardwareIdIsa;
             DeviceIndex = DeviceIndexIsa++;
-            IsDeviceDesc = FALSE;
          }
          else
          {
@@ -2505,16 +3274,6 @@ IopEnumerateDetectedDevices(
          goto nextdevice;
       }
       DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName, DeviceIndex, &HardwareIdKey);
-      if (IsDeviceDesc)
-      {
-         Status = ZwSetValueKey(hLevel2Key, &DeviceDescU, 0, REG_SZ, ValueName.Buffer, ValueName.MaximumLength);
-         if (!NT_SUCCESS(Status))
-         {
-            DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status);
-            ZwDeleteKey(hLevel2Key);
-            goto nextdevice;
-         }
-      }
       Status = ZwSetValueKey(hLevel2Key, &HardwareIDU, 0, REG_MULTI_SZ, pHardwareId->Buffer, pHardwareId->MaximumLength);
       if (!NT_SUCCESS(Status))
       {
@@ -2538,10 +3297,29 @@ IopEnumerateDetectedDevices(
          ZwDeleteKey(hLevel2Key);
          goto nextdevice;
       }
-      if (BootResourcesLength > 0)
+      if (BootResourcesLength >= sizeof(CM_FULL_RESOURCE_DESCRIPTOR))
       {
+         CmResourceList = ExAllocatePool(PagedPool, BootResourcesLength + sizeof(ULONG));
+         if (!CmResourceList)
+         {
+            ZwClose(hLogConf);
+            ZwDeleteKey(hLevel2Key);
+            goto nextdevice;
+         }
+
+         /* Add the list count (1st member of CM_RESOURCE_LIST) */
+         ListCount = 1;
+         RtlCopyMemory(CmResourceList,
+                       &ListCount,
+                       sizeof(ULONG));
+
+         /* Now add the actual list (2nd member of CM_RESOURCE_LIST) */
+         RtlCopyMemory(CmResourceList + sizeof(ULONG),
+                       BootResources,
+                       BootResourcesLength);
+
          /* Save boot resources to 'LogConf\BootConfig' */
-         Status = ZwSetValueKey(hLogConf, &BootConfigU, 0, REG_FULL_RESOURCE_DESCRIPTOR, BootResources, BootResourcesLength);
+         Status = ZwSetValueKey(hLogConf, &BootConfigU, 0, REG_RESOURCE_LIST, CmResourceList, BootResourcesLength + sizeof(ULONG));
          if (!NT_SUCCESS(Status))
          {
             DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status);
@@ -2554,7 +3332,10 @@ IopEnumerateDetectedDevices(
 
 nextdevice:
       if (BootResources && BootResources != ParentBootResources)
+      {
          ExFreePool(BootResources);
+         BootResources = NULL;
+      }
       if (hLevel2Key)
       {
          ZwClose(hLevel2Key);
@@ -3052,7 +3833,7 @@ PpInitSystem(VOID)
 /* PUBLIC FUNCTIONS **********************************************************/
 
 /*
- * @unimplemented
+ * @implemented
  */
 NTSTATUS
 NTAPI
@@ -3068,6 +3849,8 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject,
     PVOID Data = NULL;
     PWSTR Ptr;
     NTSTATUS Status;
+    POBJECT_NAME_INFORMATION ObjectNameInfo = NULL;
+    ULONG RequiredLength, ObjectNameInfoLength;
 
     DPRINT("IoGetDeviceProperty(0x%p %d)\n", DeviceObject, DeviceProperty);
 
@@ -3281,9 +4064,36 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject,
         break;
 
     case DevicePropertyPhysicalDeviceObjectName:
-        /* InstancePath buffer is NULL terminated, so we can do this */
-        Length = DeviceNode->InstancePath.MaximumLength;
-        Data = DeviceNode->InstancePath.Buffer;
+        Status = ObQueryNameString(DeviceNode->PhysicalDeviceObject,
+                                   NULL,
+                                   0,
+                                   &RequiredLength);
+        if (Status == STATUS_SUCCESS)
+        {
+            Length = 0;
+            Data = L"";
+        }
+        else if (Status == STATUS_INFO_LENGTH_MISMATCH)
+        {
+            ObjectNameInfoLength = RequiredLength;
+            ObjectNameInfo = ExAllocatePool(PagedPool, ObjectNameInfoLength);
+            if (!ObjectNameInfo)
+                return STATUS_INSUFFICIENT_RESOURCES;
+
+            Status = ObQueryNameString(DeviceNode->PhysicalDeviceObject,
+                                       ObjectNameInfo,
+                                       ObjectNameInfoLength,
+                                       &RequiredLength);
+            if (NT_SUCCESS(Status))
+            {
+                Length = ObjectNameInfo->Name.Length;
+                Data = ObjectNameInfo->Name.Buffer;
+            }
+            else
+                return Status;
+        }
+        else
+            return Status;
         break;
 
     default:
@@ -3293,13 +4103,22 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject,
     /* Prepare returned values */
     *ResultLength = Length;
     if (BufferLength < Length)
+    {
+        if (ObjectNameInfo != NULL)
+            ExFreePool(ObjectNameInfo);
+
         return STATUS_BUFFER_TOO_SMALL;
+    }
     RtlCopyMemory(PropertyBuffer, Data, Length);
 
     /* NULL terminate the string (if required) */
-    if (DeviceProperty == DevicePropertyEnumeratorName)
+    if (DeviceProperty == DevicePropertyEnumeratorName ||
+        DeviceProperty == DevicePropertyPhysicalDeviceObjectName)
         ((LPWSTR)PropertyBuffer)[Length / sizeof(WCHAR)] = UNICODE_NULL;
 
+    if (ObjectNameInfo != NULL)
+        ExFreePool(ObjectNameInfo);
+
     return STATUS_SUCCESS;
 }
 
index e11c4b0..c75e566 100644 (file)
@@ -3,7 +3,7 @@
  * COPYRIGHT:       GPL - See COPYING in the top level directory
  * FILE:            ntoskrnl/io/pnpmgr/pnpreport.c
  * PURPOSE:         Device Changes Reporting Functions
- * PROGRAMMERS:     Filip Navara (xnavara@volny.cz)
+ * PROGRAMMERS:     Cameron Gutman (cameron.gutman@reactos.org)
  */
 
 /* INCLUDES ******************************************************************/
 #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 **********************************************************/
 
 /*
@@ -30,29 +122,57 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject,
 {
     PDEVICE_NODE DeviceNode;
     PDEVICE_OBJECT Pdo;
-    NTSTATUS Status = STATUS_SUCCESS;
+    NTSTATUS Status;
+    HANDLE InstanceKey;
+    ULONG RequiredLength;
+    UNICODE_STRING ValueName, ServiceName;
+    WCHAR HardwareId[256];
+    PWCHAR IfString;
+    ULONG IdLength;
 
-    DPRINT("__FUNCTION__ (DeviceObject %p, *DeviceObject %p)\n",
+    DPRINT("IoReportDetectedDevice (DeviceObject %p, *DeviceObject %p)\n",
       DeviceObject, DeviceObject ? *DeviceObject : NULL);
 
-    /* if *DeviceObject is not NULL, we must use it as a PDO, and don't create a new one */
+    /* Create the service name (eg. ACPI_HAL) */
+    ServiceName.Buffer = DriverObject->DriverName.Buffer +
+       sizeof(DRIVER_ROOT_NAME) / sizeof(WCHAR) - 1;
+    ServiceName.Length = DriverObject->DriverName.Length -
+       sizeof(DRIVER_ROOT_NAME) + sizeof(WCHAR);
+    ServiceName.MaximumLength = ServiceName.Length;
+
+    /* If the interface type is unknown, treat it as internal */
+    if (LegacyBusType == InterfaceTypeUndefined)
+        LegacyBusType = Internal;
+
+    /* Get the string equivalent of the interface type */
+    IfString = IopGetInterfaceTypeString(LegacyBusType);
+
+    /* If NULL is returned then it's a bad type */
+    if (!IfString)
+        return STATUS_INVALID_PARAMETER;
+
+    /* We use the caller's PDO if they supplied one */
     if (DeviceObject && *DeviceObject)
     {
         Pdo = *DeviceObject;
+        DeviceNode = IopGetDeviceNode(*DeviceObject);
     }
     else
     {
-        UNICODE_STRING ServiceName;
-        ServiceName.Buffer = DriverObject->DriverName.Buffer +
-          sizeof(DRIVER_ROOT_NAME) / sizeof(WCHAR) - 1;
-        ServiceName.Length = DriverObject->DriverName.Length -
-          sizeof(DRIVER_ROOT_NAME) + sizeof(WCHAR);
-        ServiceName.MaximumLength = ServiceName.Length;
-
-        /* create 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))
@@ -60,17 +180,133 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject,
             DPRINT("IopCreateDeviceNode() failed (Status 0x%08lx)\n", Status);
             return Status;
         }
+    }
 
-        Pdo = DeviceNode->PhysicalDeviceObject;
-        if (DeviceObject) *DeviceObject = Pdo;
-  }
+    /* We don't call AddDevice for devices reported this way */
+    IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED);
 
-    /* we don't need to call AddDevice and send IRP_MN_START_DEVICE */
-    return Status;
+    /* We don't send IRP_MN_START_DEVICE */
+    IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED);
+
+    /* This is a legacy driver for this device */
+    IopDeviceNodeSetFlag(DeviceNode, DNF_LEGACY_DRIVER);
+
+    /* Perform a manual configuration of our device */
+    IopActionInterrogateDeviceStack(DeviceNode, DeviceNode->Parent);
+    IopActionConfigureChildServices(DeviceNode, DeviceNode->Parent);
+
+    /* Open a handle to the instance path key */
+    Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, &InstanceKey);
+    if (!NT_SUCCESS(Status))
+        return Status;
+
+    /* Add DETECTEDInterfaceType\DriverName */
+    IdLength = 0;
+    IdLength += swprintf(&HardwareId[IdLength],
+                         L"DETECTED%ls\\%wZ",
+                         IfString,
+                         &ServiceName);
+    HardwareId[IdLength++] = UNICODE_NULL;
+
+    /* Add DETECTED\DriverName */
+    IdLength += swprintf(&HardwareId[IdLength],
+                         L"DETECTED\\%wZ",
+                         &ServiceName);
+    HardwareId[IdLength++] = UNICODE_NULL;
+
+    /* Terminate the string with another null */
+    HardwareId[IdLength] = UNICODE_NULL;
+
+    /* Store the value for CompatibleIDs */
+    RtlInitUnicodeString(&ValueName, L"CompatibleIDs");
+    Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_MULTI_SZ, HardwareId, IdLength * sizeof(WCHAR));
+    if (!NT_SUCCESS(Status))
+    {
+       DPRINT("Failed to write the compatible IDs: 0x%x\n", Status);
+       ZwClose(InstanceKey);
+       return Status;
+    }
+
+    /* Add a hardware ID if the driver didn't report one */
+    RtlInitUnicodeString(&ValueName, L"HardwareID");
+    if (ZwQueryValueKey(InstanceKey, &ValueName, KeyValueBasicInformation, NULL, 0, &RequiredLength) == STATUS_OBJECT_NAME_NOT_FOUND)
+    {
+       /* Just use our most specific compatible ID */
+       IdLength = 0;
+       IdLength += swprintf(&HardwareId[IdLength],
+                            L"DETECTED%ls\\%wZ",
+                            IfString,
+                            &ServiceName);
+       HardwareId[++IdLength] = UNICODE_NULL;
+
+       /* Write the value to the registry */
+       Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_SZ, HardwareId, IdLength * sizeof(WCHAR));
+       if (!NT_SUCCESS(Status))
+       {
+          DPRINT("Failed to write the hardware ID: 0x%x\n", Status);
+          ZwClose(InstanceKey);
+          return Status;
+       }
+    }
+
+    /* Assign the resources to the device node */
+    DeviceNode->BootResources = ResourceList;
+    DeviceNode->ResourceRequirements = ResourceRequirements;
+
+    /* Set appropriate flags */
+    if (DeviceNode->BootResources)
+       IopDeviceNodeSetFlag(DeviceNode, DNF_HAS_BOOT_CONFIG);
+
+    if (DeviceNode->ResourceRequirements)
+       IopDeviceNodeSetFlag(DeviceNode, DNF_RESOURCE_REPORTED);
+    else
+       IopDeviceNodeSetFlag(DeviceNode, DNF_NO_RESOURCE_REQUIRED);
+
+    /* Write the resource information to the registry */
+    IopSetDeviceInstanceData(InstanceKey, DeviceNode);
+
+    /* Close the instance key handle */
+    ZwClose(InstanceKey);
+
+    /* If the caller didn't get the resources assigned for us, do it now */
+    if (!ResourceAssigned)
+    {
+       IopDeviceNodeSetFlag(DeviceNode, DNF_ASSIGNING_RESOURCES);
+       Status = IopAssignDeviceResources(DeviceNode, &RequiredLength);
+       if (NT_SUCCESS(Status))
+       {
+          Status = IopTranslateDeviceResources(DeviceNode, RequiredLength);
+          if (NT_SUCCESS(Status))
+              Status = IopUpdateResourceMapForPnPDevice(DeviceNode);
+       }
+       IopDeviceNodeClearFlag(DeviceNode, DNF_ASSIGNING_RESOURCES);
+
+       /* See if we failed */
+       if (!NT_SUCCESS(Status))
+       {
+           DPRINT("Assigning resources failed: 0x%x\n", Status);
+           return Status;
+       }
+    }
+
+    /* Report the device's enumeration to umpnpmgr */
+    IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED,
+                              &DeviceNode->InstancePath);
+
+    /* Report the device's arrival to umpnpmgr */
+    IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL,
+                              &DeviceNode->InstancePath);
+
+    DPRINT1("Reported device: %S (%wZ)\n", HardwareId, &DeviceNode->InstancePath);
+
+    /* Return the PDO */
+    if (DeviceObject) *DeviceObject = Pdo;
+
+    return STATUS_SUCCESS;
 }
 
 /*
- * @unimplemented
+ * @halfplemented
  */
 NTSTATUS
 NTAPI
@@ -82,23 +318,35 @@ IoReportResourceForDetection(IN PDRIVER_OBJECT DriverObject,
                              IN ULONG DeviceListSize OPTIONAL,
                              OUT PBOOLEAN ConflictDetected)
 {
-    static int warned = 0;
-    if (!warned)
-    {
-        DPRINT1("IoReportResourceForDetection partly implemented\n");
-        warned = 1;
-    }
+    PCM_RESOURCE_LIST ResourceList;
+    NTSTATUS Status;
 
     *ConflictDetected = FALSE;
 
-    if (PopSystemPowerDeviceNode && DriverListSize > 0)
+    if (!DriverList && !DeviceList)
+        return STATUS_INVALID_PARAMETER;
+
+    /* Find the real list */
+    if (!DriverList)
+        ResourceList = DeviceList;
+    else
+        ResourceList = DriverList;
+
+    /* Look for a resource conflict */
+    Status = IopDetectResourceConflict(ResourceList);
+    if (Status == STATUS_CONFLICTING_ADDRESSES)
     {
-        /* We hope legacy devices will be enumerated by ACPI */
+        /* Oh noes */
         *ConflictDetected = TRUE;
-        return STATUS_CONFLICTING_ADDRESSES;
     }
+    else if (NT_SUCCESS(Status))
+    {
+        /* Looks like we're good to go */
 
-    return STATUS_SUCCESS;
+        /* TODO: Claim the resources in the ResourceMap */
+    }
+
+    return Status;
 }
 
 VOID
index 5a5bf85..63a3dd5 100644 (file)
@@ -33,7 +33,6 @@ typedef struct _PNPROOT_DEVICE
     UNICODE_STRING DeviceDescription;
     // Resource requirement list
     PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList;
-    ULONG ResourceRequirementsListSize;
     // Associated resource list
     PCM_RESOURCE_LIST ResourceList;
     ULONG ResourceListSize;
@@ -131,30 +130,25 @@ LocateChildDevice(
 NTSTATUS
 PnpRootCreateDevice(
     IN PUNICODE_STRING ServiceName,
-    IN PDEVICE_OBJECT *PhysicalDeviceObject)
+    OUT PDEVICE_OBJECT *PhysicalDeviceObject,
+    OUT OPTIONAL PUNICODE_STRING FullInstancePath)
 {
     PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
-    UNICODE_STRING UnknownServiceName = RTL_CONSTANT_STRING(L"UNKNOWN");
-    PUNICODE_STRING LocalServiceName;
     PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension;
     WCHAR DevicePath[MAX_PATH + 1];
     WCHAR InstancePath[5];
     PPNPROOT_DEVICE Device = NULL;
     NTSTATUS Status;
     ULONG i;
+    UNICODE_STRING PathSep = RTL_CONSTANT_STRING(L"\\");
 
     DeviceExtension = PnpRootDeviceObject->DeviceExtension;
     KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock);
 
-    if (ServiceName)
-        LocalServiceName = ServiceName;
-    else
-        LocalServiceName = &UnknownServiceName;
-
-    DPRINT("Creating a PnP root device for service '%wZ'\n", LocalServiceName);
+    DPRINT("Creating a PnP root device for service '%wZ'\n", ServiceName);
 
     /* Search for a free instance ID */
-    _snwprintf(DevicePath, sizeof(DevicePath) / sizeof(WCHAR), L"%s\\LEGACY_%wZ", REGSTR_KEY_ROOTENUM, LocalServiceName);
+    _snwprintf(DevicePath, sizeof(DevicePath) / sizeof(WCHAR), L"%s\\%wZ", REGSTR_KEY_ROOTENUM, ServiceName);
     for (i = 0; i < 9999; i++)
     {
         _snwprintf(InstancePath, sizeof(InstancePath) / sizeof(WCHAR), L"%04lu", i);
@@ -164,7 +158,7 @@ PnpRootCreateDevice(
     }
     if (i == 9999)
     {
-        DPRINT1("Too much legacy devices reported for service '%wZ'\n", &LocalServiceName);
+        DPRINT1("Too much legacy devices reported for service '%wZ'\n", ServiceName);
         Status = STATUS_INSUFFICIENT_RESOURCES;
         goto cleanup;
     }
@@ -189,6 +183,22 @@ PnpRootCreateDevice(
         goto cleanup;
     }
 
+    if (FullInstancePath)
+    {
+        FullInstancePath->MaximumLength = Device->DeviceID.Length + PathSep.Length + Device->InstanceID.Length;
+        FullInstancePath->Length = 0;
+        FullInstancePath->Buffer = ExAllocatePool(PagedPool, FullInstancePath->MaximumLength);
+        if (!FullInstancePath->Buffer)
+        {
+            Status = STATUS_NO_MEMORY;
+            goto cleanup;
+        }
+
+        RtlAppendUnicodeStringToString(FullInstancePath, &Device->DeviceID);
+        RtlAppendUnicodeStringToString(FullInstancePath, &PathSep);
+        RtlAppendUnicodeStringToString(FullInstancePath, &Device->InstanceID);
+    }
+
     /* Initialize a device object */
     Status = IoCreateDevice(
         PnpRootDeviceObject->DriverObject,
@@ -666,24 +676,27 @@ PnpRootFdoPnpControl(
                 if (NT_SUCCESS(Status))
                     DeviceExtension->State = dsStarted;
             }
-            break;
+
+            Irp->IoStatus.Status = Status;
+            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+            return Status;
 
          case IRP_MN_STOP_DEVICE:
              DPRINT("IRP_MJ_PNP / IRP_MN_STOP_DEVICE\n");
              /* Root device cannot be stopped */
-             Status = STATUS_NOT_SUPPORTED;
-             break;
+             Irp->IoStatus.Status = Status = STATUS_INVALID_DEVICE_REQUEST;
+             IoCompleteRequest(Irp, IO_NO_INCREMENT);
+             return Status;
 
         default:
             DPRINT("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp->MinorFunction);
-            Status = STATUS_NOT_IMPLEMENTED;
             break;
     }
 
     if (Status != STATUS_PENDING)
     {
-        Irp->IoStatus.Status = Status;
-        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+       Irp->IoStatus.Status = Status;
+       IoCompleteRequest(Irp, IO_NO_INCREMENT);
     }
 
     return Status;
@@ -696,48 +709,25 @@ PdoQueryDeviceRelations(
     IN PIO_STACK_LOCATION IrpSp)
 {
     PDEVICE_RELATIONS Relations;
-    DEVICE_RELATION_TYPE RelationType;
     NTSTATUS Status = Irp->IoStatus.Status;
 
-    RelationType = IrpSp->Parameters.QueryDeviceRelations.Type;
+    if (IrpSp->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
+        return Status;
 
-    switch (RelationType)
+    DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n");
+    Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
+    if (!Relations)
     {
-        /* FIXME: remove */
-        case BusRelations:
-        {
-            if (IoGetAttachedDevice(DeviceObject) != DeviceObject)
-            {
-                /* We're not alone in the stack */
-                DPRINT1("PnP is misbehaving ; don't know how to handle IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
-            }
-            break;
-        }
-
-        case TargetDeviceRelation:
-        {
-            DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n");
-            Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
-            if (!Relations)
-            {
-                DPRINT("ExAllocatePoolWithTag() failed\n");
-                Status = STATUS_NO_MEMORY;
-            }
-            else
-            {
-                ObReferenceObject(DeviceObject);
-                Relations->Count = 1;
-                Relations->Objects[0] = DeviceObject;
-                Status = STATUS_SUCCESS;
-                Irp->IoStatus.Information = (ULONG_PTR)Relations;
-            }
-            break;
-        }
-
-        default:
-        {
-            DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / unknown relation type 0x%lx\n", RelationType);
-        }
+        DPRINT("ExAllocatePoolWithTag() failed\n");
+        Status = STATUS_NO_MEMORY;
+    }
+    else
+    {
+        ObReferenceObject(DeviceObject);
+        Relations->Count = 1;
+        Relations->Objects[0] = DeviceObject;
+        Status = STATUS_SUCCESS;
+        Irp->IoStatus.Information = (ULONG_PTR)Relations;
     }
 
     return Status;
@@ -775,35 +765,29 @@ PdoQueryResources(
 
     DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
 
-    if (DeviceExtension->DeviceInfo->ResourceList == NULL)
-    {
-        /* Create an empty resource list */
-        ResourceList = ExAllocatePool(PagedPool, sizeof(CM_RESOURCE_LIST));
-        if (!ResourceList)
-            return STATUS_NO_MEMORY;
-
-        ResourceList->Count = 0;
-
-        Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
-    }
-    else
+    if (DeviceExtension->DeviceInfo->ResourceList)
     {
         /* Copy existing resource requirement list */
         ResourceList = ExAllocatePool(
             PagedPool,
-            FIELD_OFFSET(CM_RESOURCE_LIST, List) + DeviceExtension->DeviceInfo->ResourceListSize);
+            DeviceExtension->DeviceInfo->ResourceListSize);
         if (!ResourceList)
             return STATUS_NO_MEMORY;
 
-        ResourceList->Count = 1;
         RtlCopyMemory(
-            &ResourceList->List,
+            ResourceList,
             DeviceExtension->DeviceInfo->ResourceList,
             DeviceExtension->DeviceInfo->ResourceListSize);
-            Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
-    }
 
-    return STATUS_SUCCESS;
+        Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
+
+        return STATUS_SUCCESS;
+    }
+    else
+    {
+        /* No resources so just return without changing the status */
+        return Irp->IoStatus.Status;
+    }
 }
 
 static NTSTATUS
@@ -814,23 +798,10 @@ PdoQueryResourceRequirements(
 {
     PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
     PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
-    ULONG ResourceListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List);
 
     DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
 
-    if (DeviceExtension->DeviceInfo->ResourceRequirementsList == NULL)
-    {
-        /* Create an empty resource list */
-        ResourceList = ExAllocatePool(PagedPool, ResourceListSize);
-        if (!ResourceList)
-            return STATUS_NO_MEMORY;
-
-        RtlZeroMemory(ResourceList, ResourceListSize);
-        ResourceList->ListSize = ResourceListSize;
-
-        Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
-    }
-    else
+    if (DeviceExtension->DeviceInfo->ResourceRequirementsList)
     {
         /* Copy existing resource requirement list */
         ResourceList = ExAllocatePool(PagedPool, DeviceExtension->DeviceInfo->ResourceRequirementsList->ListSize);
@@ -841,10 +812,16 @@ PdoQueryResourceRequirements(
             ResourceList,
             DeviceExtension->DeviceInfo->ResourceRequirementsList,
             DeviceExtension->DeviceInfo->ResourceRequirementsList->ListSize);
-            Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
-    }
 
-    return STATUS_SUCCESS;
+        Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
+
+        return STATUS_SUCCESS;
+    }
+    else
+    {
+        /* No resource requirements so just return without changing the status */
+        return Irp->IoStatus.Status;
+    }
 }
 
 static NTSTATUS
diff --git a/ntoskrnl/io/pnpmgr/pnputil.c b/ntoskrnl/io/pnpmgr/pnputil.c
new file mode 100644 (file)
index 0000000..f274f3d
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            ntoskrnl/io/pnpmgr/pnputil.c
+ * PURPOSE:         PnP Utility Code
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <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 */
index a605ee1..a349f88 100644 (file)
                        <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">
index d06fb04..0cb0da4 100644 (file)
@@ -314,6 +314,31 @@ SepSidInToken(PACCESS_TOKEN _Token,
     return FALSE;
 }
 
+static BOOLEAN
+SepTokenIsOwner(PACCESS_TOKEN Token,
+                PSECURITY_DESCRIPTOR SecurityDescriptor)
+{
+    NTSTATUS Status;
+    PSID Sid = NULL;
+    BOOLEAN Defaulted;
+
+    Status = RtlGetOwnerSecurityDescriptor(SecurityDescriptor,
+                                           &Sid,
+                                           &Defaulted);
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("RtlGetOwnerSecurityDescriptor() failed (Status %lx)\n", Status);
+        return FALSE;
+    }
+
+    if (Sid == NULL)
+    {
+        DPRINT1("Owner Sid is NULL\n");
+        return FALSE;
+    }
+
+    return SepSidInToken(Token, Sid);
+}
 
 VOID NTAPI
 SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation,
@@ -364,7 +389,10 @@ SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
                OUT PNTSTATUS AccessStatus)
 {
     LUID_AND_ATTRIBUTES Privilege;
-    ACCESS_MASK CurrentAccess, AccessMask;
+    ACCESS_MASK RemainingAccess;
+    ACCESS_MASK TempAccess;
+    ACCESS_MASK TempGrantedAccess = 0;
+    ACCESS_MASK TempDeniedAccess = 0;
     PACCESS_TOKEN Token;
     ULONG i;
     PACL Dacl;
@@ -398,14 +426,41 @@ SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
     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,
@@ -435,57 +490,47 @@ SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
         return TRUE;
     }
 
-    CurrentAccess = PreviouslyGrantedAccess;
-
     /* RULE 2: Check token for 'take ownership' privilege */
-    Privilege.Luid = SeTakeOwnershipPrivilege;
-    Privilege.Attributes = SE_PRIVILEGE_ENABLED;
-
-    if (SepPrivilegeCheck(Token,
-                          &Privilege,
-                          1,
-                          PRIVILEGE_SET_ALL_NECESSARY,
-                          AccessMode))
-    {
-        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 */
@@ -496,63 +541,139 @@ SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
         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
@@ -649,16 +770,43 @@ SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
     if (!SubjectContextLocked)
         SeLockSubjectContext(SubjectSecurityContext);
 
-    /* Call the internal function */
-    ret = SepAccessCheck(SecurityDescriptor,
-                         SubjectSecurityContext,
-                         DesiredAccess,
-                         PreviouslyGrantedAccess,
-                         Privileges,
-                         GenericMapping,
-                         AccessMode,
-                         GrantedAccess,
-                         AccessStatus);
+    /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
+    if (DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED))
+    {
+         PACCESS_TOKEN Token = SubjectSecurityContext->ClientToken ?
+             SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
+
+        if (SepTokenIsOwner(Token,
+                            SecurityDescriptor))
+        {
+            if (DesiredAccess & MAXIMUM_ALLOWED)
+                PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL);
+            else
+                PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL));
+
+            DesiredAccess &= ~(WRITE_DAC | READ_CONTROL);
+        }
+    }
+
+    if (DesiredAccess == 0)
+    {
+        *GrantedAccess = PreviouslyGrantedAccess;
+        *AccessStatus = STATUS_SUCCESS;
+        ret = TRUE;
+    }
+    else
+    {
+        /* Call the internal function */
+        ret = SepAccessCheck(SecurityDescriptor,
+                             SubjectSecurityContext,
+                             DesiredAccess,
+                             PreviouslyGrantedAccess,
+                             Privileges,
+                             GenericMapping,
+                             AccessMode,
+                             GrantedAccess,
+                             AccessStatus);
+    }
 
     /* Release the lock if needed */
     if (!SubjectContextLocked)
@@ -686,6 +834,7 @@ NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
     PSECURITY_DESCRIPTOR CapturedSecurityDescriptor = NULL;
     SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
+    ACCESS_MASK PreviouslyGrantedAccess = 0;
     PTOKEN Token;
     NTSTATUS Status;
     PAGED_CODE();
@@ -801,16 +950,38 @@ NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
     SubjectSecurityContext.ProcessAuditId = NULL;
     SeLockSubjectContext(&SubjectSecurityContext);
 
-    /* Now perform the access check */
-    SepAccessCheck(SecurityDescriptor, // FIXME: use CapturedSecurityDescriptor
-                   &SubjectSecurityContext,
-                   DesiredAccess,
-                   0,
-                   &PrivilegeSet, //FIXME
-                   GenericMapping,
-                   PreviousMode,
-                   GrantedAccess,
-                   AccessStatus);
+    /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
+    if (DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED))
+    {
+        if (SepTokenIsOwner(Token, SecurityDescriptor)) // FIXME: use CapturedSecurityDescriptor
+        {
+            if (DesiredAccess & MAXIMUM_ALLOWED)
+                PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL);
+            else
+                PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL));
+
+            DesiredAccess &= ~(WRITE_DAC | READ_CONTROL);
+        }
+    }
+
+    if (DesiredAccess == 0)
+    {
+        *GrantedAccess = PreviouslyGrantedAccess;
+        *AccessStatus = STATUS_SUCCESS;
+    }
+    else
+    {
+        /* Now perform the access check */
+        SepAccessCheck(SecurityDescriptor, // FIXME: use CapturedSecurityDescriptor
+                       &SubjectSecurityContext,
+                       DesiredAccess,
+                       PreviouslyGrantedAccess,
+                       &PrivilegeSet, //FIXME
+                       GenericMapping,
+                       PreviousMode,
+                       GrantedAccess,
+                       AccessStatus);
+    }
 
     /* Unlock subject context */
     SeUnlockSubjectContext(&SubjectSecurityContext);
index d1d52e5..61bc075 100644 (file)
@@ -786,3 +786,20 @@ NtGdiGetDhpdev(
 
     return dhpdev;
 }
+
+PSIZEL
+FASTCALL
+PDEVOBJ_sizl(PPDEVOBJ ppdev, PSIZEL psizl)
+{
+    if (ppdev->flFlags & PDEV_META_DEVICE)
+    {
+        psizl->cx = ppdev->ulHorzRes;
+        psizl->cy = ppdev->ulVertRes;
+    }
+    else
+    {
+        psizl->cx = ppdev->gdiinfo.ulHorzRes;
+        psizl->cy = ppdev->gdiinfo.ulVertRes;
+    }
+    return psizl;
+}
index a209ff2..8578f8e 100644 (file)
@@ -245,6 +245,8 @@ VOID FASTCALL IntGdiUnreferencePdev(PPDEVOBJ pPDev, DWORD CleanUpType);
 HDC FASTCALL IntGdiCreateDisplayDC(HDEV hDev, ULONG DcType, BOOL EmptyDC);
 BOOL FASTCALL IntGdiCleanDC(HDC hDC);
 VOID FASTCALL IntvGetDeviceCaps(PPDEVOBJ, PDEVCAPS);
+BOOL FASTCALL MakeInfoDC(PDC,BOOL);
+BOOL FASTCALL IntSetDefaultRegion(PDC);
 
 VOID
 FORCEINLINE
index 0e868a7..076e8d8 100644 (file)
@@ -48,7 +48,7 @@ typedef struct
 {
     DWORD dwFlags;
     PDEVMODEW pdm;
-    
+
 } DEVMODEENTRY, *PDEVMODEENTRY;
 
 typedef struct _GRAPHICS_DEVICE
@@ -104,8 +104,8 @@ typedef struct _PDEVOBJ
 //  PVOID                     TypeOneInfo;
     PVOID                     pvGammaRamp;    /* Gamma ramp pointer. */
 //  PVOID                     RemoteTypeOne;
-//  ULONG                     ulHorzRes;
-//  ULONG                     ulVertRes;
+    ULONG                     ulHorzRes;
+    ULONG                     ulVertRes;
 //  PFN_DrvSetPointerShape    pfnDrvSetPointerShape;
 //  PFN_DrvMovePointer        pfnDrvMovePointer;
     PFN_DrvMovePointer        pfnMovePointer;
@@ -123,7 +123,7 @@ typedef struct _PDEVOBJ
 //  HANDLE                    hSpooler;       /* Handle to spooler, if spooler dev driver. */
 //  PVOID                     pDesktopId;
     PGRAPHICS_DEVICE          pGraphicsDevice;
-//  POINTL                    ptlOrigion;
+    POINTL                    ptlOrigion;
     PDEVMODEW                 pdmwDev;        /* Ptr->DEVMODEW.dmSize + dmDriverExtra == alloc size. */
 //  DWORD                     Unknown3;
     FLONG                     DxDd_Flags;     /* DxDD active status flags. */
@@ -186,4 +186,8 @@ BOOL
 NTAPI
 InitDeviceImpl();
 
+PSIZEL
+FASTCALL
+PDEVOBJ_sizl(PPDEVOBJ, PSIZEL);
+
 #endif /* !__WIN32K_PDEVOBJ_H */
index 57a5ec2..3fe9054 100644 (file)
@@ -3,6 +3,8 @@
 #include "win32.h"
 #include "gdiobj.h"
 
+#define PDEV_SURFACE              0x80000000
+
 /* GDI surface object */
 typedef struct _SURFACE
 {
index 4f627d6..89b926a 100644 (file)
@@ -772,9 +772,6 @@ UserChangeDisplaySettings(
 
         pdesk = IntGetActiveDesktop();
         IntHideDesktop(pdesk);
-        co_IntShowDesktop(pdesk, ppdev->gdiinfo.ulHorzRes, ppdev->gdiinfo.ulVertRes);
-
-        UserRedrawDesktop();
 
         /* Send WM_DISPLAYCHANGE to all toplevel windows */
         co_IntSendMessageTimeout(HWND_BROADCAST,
@@ -784,6 +781,10 @@ UserChangeDisplaySettings(
                                  SMTO_NORMAL,
                                  100,
                                  &ulResult);
+
+        co_IntShowDesktop(pdesk, ppdev->gdiinfo.ulHorzRes, ppdev->gdiinfo.ulVertRes);
+
+        UserRedrawDesktop();
     }
 
 leave:
index d734284..9e6b5b0 100644 (file)
@@ -733,14 +733,74 @@ NtGdiDeleteObjectApp(HANDLE DCHandle)
     return IntGdiDeleteDC(DCHandle, FALSE);
 }
 
+BOOL
+FASTCALL
+MakeInfoDC(PDC pdc, BOOL bSet)
+{
+    PSURFACE pSurface;
+    SIZEL sizl;
+
+    /* Can not be a display DC. */
+    if (pdc->fs & DC_FLAG_DISPLAY) return FALSE;
+    if (bSet)
+    {
+        if (pdc->fs & DC_FLAG_TEMPINFODC || pdc->dctype == DC_TYPE_DIRECT)
+            return FALSE;
+
+        pSurface = pdc->dclevel.pSurface;
+        pdc->fs |= DC_FLAG_TEMPINFODC;
+        pdc->pSurfInfo = pSurface;
+        pdc->dctype = DC_TYPE_INFO;
+        pdc->dclevel.pSurface = NULL;
+
+        PDEVOBJ_sizl(pdc->ppdev, &sizl);
+
+        if ( sizl.cx == pdc->dclevel.sizl.cx &&
+             sizl.cy == pdc->dclevel.sizl.cy )
+            return TRUE;
+
+        pdc->dclevel.sizl.cx = sizl.cx;
+        pdc->dclevel.sizl.cy = sizl.cy;
+    }
+    else
+    {
+        if (!(pdc->fs & DC_FLAG_TEMPINFODC) || pdc->dctype != DC_TYPE_INFO)
+            return FALSE;
+
+        pSurface = pdc->pSurfInfo;
+        pdc->fs &= ~DC_FLAG_TEMPINFODC;
+        pdc->dclevel.pSurface = pSurface;
+        pdc->dctype = DC_TYPE_DIRECT;
+        pdc->pSurfInfo = NULL;
+
+        if ( !pSurface ||
+             (pSurface->SurfObj.sizlBitmap.cx == pdc->dclevel.sizl.cx &&
+              pSurface->SurfObj.sizlBitmap.cy == pdc->dclevel.sizl.cy) )
+            return TRUE;
+
+        pdc->dclevel.sizl.cx = pSurface->SurfObj.sizlBitmap.cx;
+        pdc->dclevel.sizl.cy = pSurface->SurfObj.sizlBitmap.cy;
+    }
+    return IntSetDefaultRegion(pdc);
+}
+
+/*
+* @implemented
+*/
 BOOL
 APIENTRY
 NtGdiMakeInfoDC(
     IN HDC hdc,
     IN BOOL bSet)
 {
-    UNIMPLEMENTED;
-    ASSERT(FALSE);
+    BOOL Ret;
+    PDC pdc = DC_LockDc(hdc);
+    if (pdc)
+    {
+        Ret = MakeInfoDC(pdc, bSet);
+        DC_UnlockDc(pdc);
+        return Ret;
+    }
     return FALSE;
 }
 
index 9721af3..a8c28ec 100644 (file)
@@ -125,6 +125,71 @@ IntIsPrimarySurface(SURFOBJ *SurfObj)
 }
 #endif
 
+BOOL
+FASTCALL
+IntSetDefaultRegion(PDC pdc)
+{
+    PSURFACE pSurface;
+    PROSRGNDATA prgn;
+    RECTL rclWnd, rclClip;
+
+    IntGdiReleaseRaoRgn(pdc);
+
+    rclWnd.left   = 0;
+    rclWnd.top    = 0;
+    rclWnd.right  = pdc->dclevel.sizl.cx;
+    rclWnd.bottom = pdc->dclevel.sizl.cy;
+    rclClip = rclWnd;
+
+//    EngAcquireSemaphoreShared(pdc->ppdev->hsemDevLock);
+    if (pdc->ppdev->flFlags & PDEV_META_DEVICE)
+    {
+        pSurface = pdc->dclevel.pSurface;
+        if (pSurface && pSurface->flFlags & PDEV_SURFACE)
+        {
+            rclClip.left   += pdc->ppdev->ptlOrigion.x;
+            rclClip.top    += pdc->ppdev->ptlOrigion.y;
+            rclClip.right  += pdc->ppdev->ptlOrigion.x;
+            rclClip.bottom += pdc->ppdev->ptlOrigion.y;
+        }
+    }
+//    EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
+
+    prgn = pdc->prgnVis;
+
+    if (prgn && prgn != prgnDefault)
+    {
+        REGION_SetRectRgn( prgn,
+                           rclClip.left,
+                           rclClip.top,
+                           rclClip.right ,
+                           rclClip.bottom );
+    }
+    else
+    {
+        prgn = IntSysCreateRectpRgn( rclClip.left,
+                                     rclClip.top,
+                                     rclClip.right ,
+                                     rclClip.bottom );
+        pdc->prgnVis = prgn;
+    }
+
+    if (prgn)
+    {
+        pdc->ptlDCOrig.x = 0;
+        pdc->ptlDCOrig.y = 0;
+        pdc->erclWindow = rclWnd;
+        pdc->erclClip = rclClip;
+        /* Might be an InitDC or DCE....*/
+        pdc->ptlFillOrigin.x = pdc->dcattr.VisRectRegion.Rect.right;
+        pdc->ptlFillOrigin.y = pdc->dcattr.VisRectRegion.Rect.bottom;
+        return TRUE;
+    }
+
+    pdc->prgnVis = prgnDefault;
+    return FALSE;
+}
+
 
 BOOL APIENTRY
 NtGdiCancelDC(HDC  hDC)