[CMAKE]
authorAmine Khaldi <amine.khaldi@reactos.org>
Thu, 14 Apr 2011 12:50:32 +0000 (12:50 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Thu, 14 Apr 2011 12:50:32 +0000 (12:50 +0000)
* Sync with trunk r51339.
* Move the static lib creation command from the toolchain file to gcc.cmake

svn path=/branches/cmake-bringup/; revision=51340

57 files changed:
1  2 
base/applications/cmdutils/doskey/doskey.c
base/applications/cmdutils/doskey/lang/uk-UA.rc
base/applications/cmdutils/more/lang/uk-UA.rc
base/applications/dxdiag/lang/ua-UA.rc
base/applications/fontview/lang/uk-UA.rc
base/applications/mmc/lang/uk-UA.rc
base/applications/network/ping/lang/uk-UA.rc
base/applications/sndvol32/lang/uk-UA.rc
base/applications/taskmgr/trayicon.c
base/setup/reactos/lang/bg-BG.rc
base/setup/reactos/lang/cs-CZ.rc
base/setup/reactos/lang/de-DE.rc
base/setup/reactos/lang/el-GR.rc
base/setup/reactos/lang/en-US.rc
base/setup/reactos/lang/es-ES.rc
base/setup/reactos/lang/et-EE.rc
base/setup/reactos/lang/fi-FI.rc
base/setup/reactos/lang/fr-FR.rc
base/setup/reactos/lang/hu-HU.rc
base/setup/reactos/lang/it-IT.rc
base/setup/reactos/lang/no-NO.rc
base/setup/reactos/lang/pl-PL.rc
base/setup/reactos/lang/pt-BR.rc
base/setup/reactos/lang/ro-RO.rc
base/setup/reactos/lang/ru-RU.rc
base/setup/reactos/lang/sk-SK.rc
base/setup/reactos/lang/uk-UA.rc
base/setup/vmwinst/lang/uk-UA.rc
base/shell/explorer-new/lang/uk-UA.rc
base/shell/explorer/desktop/desktop.cpp
base/shell/explorer/explorer-uk.rc
base/system/format/lang/uk-UA.rc
dll/cpl/usrmgr/lang/uk-UA.rc
dll/cpl/usrmgr/rsrc.rc
drivers/usb/CMakeLists.txt
drivers/usb/usbehci/common.c
drivers/usb/usbehci/fdo.c
drivers/usb/usbehci/hardware.c
drivers/usb/usbehci/hardware.h
drivers/usb/usbehci/hwiface.c
drivers/usb/usbehci/hwiface.h
drivers/usb/usbehci/irp.c
drivers/usb/usbehci/pdo.c
drivers/usb/usbehci/physmem.c
drivers/usb/usbehci/physmem.h
drivers/usb/usbehci/transfer.c
drivers/usb/usbehci/transfer.h
drivers/usb/usbehci/usbehci.c
drivers/usb/usbehci/usbehci.h
drivers/usb/usbehci/usbiffn.c
gcc.cmake
lib/rtl/actctx.c
subsystems/win32/csrss/win32csr/lang/uk-UA.rc
subsystems/win32/win32k/ntuser/message.c
subsystems/win32/win32k/ntuser/msgqueue.c
subsystems/win32/win32k/objects/coord.c
toolchain-mingw32.cmake

Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,36c118c..36c118c
mode 000000,100644..100644
--- /dev/null
Simple merge
index 4be624d,0000000..291a429
mode 100644,000000..100644
--- /dev/null
@@@ -1,6 -1,0 +1,6 @@@
- add_subdirectory(usbehci)
 +
 +add_subdirectory(nt4compat)
 +add_subdirectory(usbd)
++#add_subdirectory(usbehci) The USB branch has usbehci_new
 +#add_subdirectory(usbhub) Compiles, just skipped in trunk
 +#add_subdirectory(usbstor) Compiles, just skipped in trunk
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 4b33282,0000000..38829fc
mode 100644,000000..100644
--- /dev/null
@@@ -1,705 -1,0 +1,704 @@@
-     0x40,       /* bmAttributes; 
-     Bit 7: must be set,
-         6: Self-powered,
-         5: Remote wakeup,
-         4..0: reserved */
-     0x00       /* MaxPower; */
 +/*
 + * PROJECT:     ReactOS Universal Serial Bus Bulk Enhanced Host Controller Interface
 + * LICENSE:     GPL - See COPYING in the top level directory
 + * FILE:        drivers/usb/usbehci/pdo.c
 + * PURPOSE:     USB EHCI device driver.
 + * PROGRAMMERS:
 + *              Michael Martin (michael.martin@reactos.org)
 + */
 +
 +#define INITGUID
 +
 +#include "usbehci.h"
 +#include <hubbusif.h>
 +#include <usbbusif.h>
 +#include "usbiffn.h"
 +#include <wdmguid.h>
 +#include <stdio.h>
 +#include <debug.h>
 +
 +/* Lifted from Linux with slight changes */
 +const UCHAR ROOTHUB2_DEVICE_DESCRIPTOR [] =
 +{
 +    0x12,       /*  bLength; */
 +    USB_DEVICE_DESCRIPTOR_TYPE,       /*  bDescriptorType; Device */
 +    0x00, 0x20, /*  bcdUSB; v1.1 */
 +    USB_DEVICE_CLASS_HUB,       /*  bDeviceClass; HUB_CLASSCODE */
 +    0x01,       /*  bDeviceSubClass; */
 +    0x00,       /*  bDeviceProtocol; [ low/full speeds only ] */
 +    0x08,       /*  bMaxPacketSize0; 8 Bytes */
 +    /* Fill Vendor and Product in when init root hub */
 +    0x00, 0x00, /*  idVendor; */
 +    0x00, 0x00, /*  idProduct; */
 +    0x00, 0x00, /*  bcdDevice */
 +    0x00,       /*  iManufacturer; */
 +    0x00,       /*  iProduct; */
 +    0x00,       /*  iSerialNumber; */
 +    0x01        /*  bNumConfigurations; */
 +
 +};
 +
 +const UCHAR ROOTHUB2_CONFIGURATION_DESCRIPTOR [] =
 +{
 +    /* one configuration */
 +    0x09,       /* bLength; */
 +    0x02,       /* bDescriptorType; Configuration */
 +    0x19, 0x00, /* wTotalLength; */
 +    0x01,       /* bNumInterfaces; (1) */
 +    0x23,       /* bConfigurationValue; */
 +    0x00,       /* iConfiguration; */
-     0x00       /* iInterface; */
++    0x40,       /* bmAttributes; */
++    0x00        /* MaxPower; */
 +};
 +
 +const UCHAR ROOTHUB2_INTERFACE_DESCRIPTOR [] =
 +{
 +    /* one interface */
 +    0x09,       /* bLength: Interface; */
 +    0x04,       /* bDescriptorType; Interface */
 +    0x00,       /* bInterfaceNumber; */
 +    0x00,       /* bAlternateSetting; */
 +    0x01,       /* bNumEndpoints; */
 +    0x09,       /* bInterfaceClass; HUB_CLASSCODE */
 +    0x01,       /* bInterfaceSubClass; */
 +    0x00,       /* bInterfaceProtocol: */
-                 DPRINT1("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER on SCE\n");
++    0x00        /* iInterface; */
 +};
 +
 +const UCHAR ROOTHUB2_ENDPOINT_DESCRIPTOR [] =
 +{
 +    /* one endpoint (status change endpoint) */
 +    0x07,       /* bLength; */
 +    0x05,       /* bDescriptorType; Endpoint */
 +    0x81,       /* bEndpointAddress; IN Endpoint 1 */
 +    0x03,       /* bmAttributes; Interrupt */
 +    0x08, 0x00, /* wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */
 +    0xFF        /* bInterval; (255ms -- usb 2.0 spec) */
 +};
 +
 +NTSTATUS NTAPI
 +PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
 +{
 +    PPDO_DEVICE_EXTENSION PdoDeviceExtension;
 +    PFDO_DEVICE_EXTENSION FdoDeviceExtension;
 +    PIO_STACK_LOCATION Stack = NULL;
 +    NTSTATUS Status = STATUS_UNSUCCESSFUL;
 +    ULONG_PTR Information = 0;
++    PEHCI_HOST_CONTROLLER hcd;
 +
 +    PdoDeviceExtension = (PPDO_DEVICE_EXTENSION) DeviceObject->DeviceExtension;
 +    FdoDeviceExtension = (PFDO_DEVICE_EXTENSION) PdoDeviceExtension->ControllerFdo->DeviceExtension;
 +
 +    ASSERT(PdoDeviceExtension->Common.IsFdo == FALSE);
 +
++    hcd = &FdoDeviceExtension->hcd;
 +    Stack =  IoGetCurrentIrpStackLocation(Irp);
 +
 +    switch(Stack->Parameters.DeviceIoControl.IoControlCode)
 +    {
 +        case IOCTL_INTERNAL_USB_SUBMIT_URB:
 +        {
 +            PUSB_DEVICE UsbDevice = NULL;
 +            URB *Urb;
 +            ULONG i;
 +
 +            Urb = (PURB) Stack->Parameters.Others.Argument1;
 +
 +            UsbDevice = Urb->UrbHeader.UsbdDeviceHandle;
 +
++            /* If there was no device passed then this URB is for the RootHub */
 +            if (UsbDevice == NULL)
 +                UsbDevice = PdoDeviceExtension->UsbDevices[0];
 +
++            /* Check if it is a Status Change Endpoint (SCE). The Hub Driver sends this request and miniports mark the IRP pending
++               if there is no changes on any of the ports. When the DPC of miniport routine detects changes this IRP will be completed.
++               Based on XEN PV Usb Drivers */
++
 +            if ((Urb->UrbHeader.Function == URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER) &&
 +                (UsbDevice == PdoDeviceExtension->UsbDevices[0]))
 +            {
-                 /* Check if there is any connected devices */
-                 for (i = 0; i < PdoDeviceExtension->NumberOfPorts; i++)
++                DPRINT("URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER on SCE\n");
 +                if (Urb->UrbBulkOrInterruptTransfer.PipeHandle != &UsbDevice->ActiveInterface->EndPoints[0]->EndPointDescriptor)
 +                {
 +                    DPRINT1("PipeHandle doesnt match SCE PipeHandle\n");
 +                }
 +
 +                /* Queue the Irp first */
 +                QueueURBRequest(PdoDeviceExtension, Irp);
 +
-                     if (PdoDeviceExtension->Ports[i].PortChange == 0x01)
++                /* Check for port changes */
++                if (EnumControllerPorts(hcd) == FALSE)
++                {
++                    DPRINT("No port change\n");
++                    Status = STATUS_PENDING;
++                    IoMarkIrpPending(Irp);
++                    break;
++                }
++
++                /* If we reached this point then port status has changed, so check
++                   which port */
++                for (i = 0; i < hcd->ECHICaps.HCSParams.PortCount; i++)
 +                {
-                         DPRINT1("Inform hub driver that port %d has changed\n", i+1);
++                    if (hcd->Ports[i].PortChange == 0x01)
 +                    {
-                 DPRINT1("Queueing IRP\n");
++                        DPRINT1("On SCE request: Inform hub driver that port %d has changed\n", i+1);
++                        ASSERT(FALSE);
 +                        ((PUCHAR)Urb->UrbBulkOrInterruptTransfer.TransferBuffer)[0] = 1 << ((i + 1) & 7);
 +                        Information = 0;
 +                        Status = STATUS_SUCCESS;
 +                        /* Assume URB success */
 +                        Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;
 +                        /* Set the DeviceHandle to the Internal Device */
 +                        Urb->UrbHeader.UsbdDeviceHandle = UsbDevice;
 +
 +                        /* Request handled, Remove it from the queue */
 +                        RemoveUrbRequest(PdoDeviceExtension, Irp);
 +                        break;
 +                    }
 +                }
 +                if (Status == STATUS_SUCCESS) break;
-             else
-             {
-                 DPRINT1("IOCTL_INTERNAL_USB_SUBMIT_URB send to device %x\n", UsbDevice);
-             }
++
 +                IoMarkIrpPending(Irp);
 +                Status = STATUS_PENDING;
 +                break;
 +            }
-             DPRINT("Ehci: IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %x\n", Stack->Parameters.Others.Argument2);
 +
 +            Status = HandleUrbRequest(PdoDeviceExtension, Irp);
 +
 +            break;
 +        }
 +        case IOCTL_INTERNAL_USB_CYCLE_PORT:
 +        {
 +            DPRINT1("IOCTL_INTERNAL_USB_CYCLE_PORT\n");
 +            break;
 +        }
 +        case IOCTL_INTERNAL_USB_ENABLE_PORT:
 +        {
 +            DPRINT1("IOCTL_INTERNAL_USB_ENABLE_PORT\n");
 +            Information = 0;
 +            Status = STATUS_SUCCESS;
 +            break;
 +        }
 +        case IOCTL_INTERNAL_USB_GET_BUS_INFO:
 +        {
 +            DPRINT1("IOCTL_INTERNAL_USB_GET_BUS_INFO\n");
 +            break;
 +        }
 +        case IOCTL_INTERNAL_USB_GET_BUSGUID_INFO:
 +        {
 +            DPRINT1("IOCTL_INTERNAL_USB_GET_BUSGUID_INFO\n");
 +            break;
 +        }
 +        case IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME:
 +        {
 +            DPRINT1("IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME\n");
 +            break;
 +        }
 +        case IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE:
 +        {
-             DPRINT("Ehci: IOCTL_INTERNAL_USB_GET_HUB_COUNT %x\n", IOCTL_INTERNAL_USB_GET_HUB_COUNT);
++            DPRINT1("Ehci: IOCTL_INTERNAL_USB_GET_DEVICE_HANDLE %x\n", Stack->Parameters.Others.Argument2);
 +            if (Stack->Parameters.Others.Argument1)
 +            {
 +                /* Return the root hubs devicehandle */
 +                DPRINT("Returning RootHub Handle %x\n", PdoDeviceExtension->UsbDevices[0]);
 +                *(PVOID *)Stack->Parameters.Others.Argument1 = (PVOID)PdoDeviceExtension->UsbDevices[0];
 +                Status = STATUS_SUCCESS;
 +            }
 +            else
 +                Status = STATUS_INVALID_DEVICE_REQUEST;
 +
 +            break;
 +
 +        }
 +        case IOCTL_INTERNAL_USB_GET_HUB_COUNT:
 +        {
-                 /* FIXME: Determine the number of hubs between the usb device and root hub */
-                 DPRINT1("RootHubCount %x\n", *(PULONG)Stack->Parameters.Others.Argument1);
++            DPRINT1("Ehci: IOCTL_INTERNAL_USB_GET_HUB_COUNT %x\n", IOCTL_INTERNAL_USB_GET_HUB_COUNT);
 +            ASSERT(Stack->Parameters.Others.Argument1 != NULL);
 +            if (Stack->Parameters.Others.Argument1)
 +            {
-             DPRINT("Ehci: IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO Arg1 %x, Arg2 %x\n", Stack->Parameters.Others.Argument1, Stack->Parameters.Others.Argument2);
++                /* FIXME: Determine the number of hubs between the usb device and root hub. 
++                   For now we have at least one. */
 +                *(PULONG)Stack->Parameters.Others.Argument1 = 1;
 +            }
 +            Status = STATUS_SUCCESS;
 +            break;
 +        }
 +        case IOCTL_INTERNAL_USB_GET_HUB_NAME:
 +        {
 +            DPRINT1("IOCTL_INTERNAL_USB_GET_HUB_NAME\n");
 +            break;
 +        }
 +        case IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO:
 +        {
 +            DPRINT1("IOCTL_INTERNAL_USB_GET_PARENT_HUB_INFO\n");
 +            break;
 +        }
 +        case IOCTL_INTERNAL_USB_GET_PORT_STATUS:
 +        {
 +            DPRINT1("IOCTL_INTERNAL_USB_GET_PORT_STATUS\n");
 +            break;
 +        }
 +        case IOCTL_INTERNAL_USB_RESET_PORT:
 +        {
 +            DPRINT1("IOCTL_INTERNAL_USB_RESET_PORT\n");
 +            break;
 +        }
 +        case IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO:
 +        {
-             /* Windows usbehci driver gives the Pdo in both Arguments. */
++            DPRINT("IOCTL_INTERNAL_USB_GET_ROOTHUB_PDO\n");
++            /* DDK documents that both the PDO and FDO are returned. However, while writing the UsbHub driver it was determine
++               that this was not the case. Windows usbehci driver gives the Pdo in both Arguments. Which makes sense as upper level
++               drivers should not be communicating with FDO. */
 +            if (Stack->Parameters.Others.Argument1)
 +                *(PVOID *)Stack->Parameters.Others.Argument1 = FdoDeviceExtension->Pdo;
-                 //*(PVOID *)Stack->Parameters.Others.Argument2 = IoGetAttachedDeviceReference(FdoDeviceExtension->DeviceObject);
 +            if (Stack->Parameters.Others.Argument2)
 +                *(PVOID *)Stack->Parameters.Others.Argument2 = FdoDeviceExtension->Pdo;
-             DPRINT1("IdleCallback %x\n", CallBackInfo->IdleCallback);
-             DPRINT1("IdleContext %x\n", CallBackInfo->IdleContext);
 +            Information = 0;
 +            Status = STATUS_SUCCESS;
 +            break;
 +        }
 +        case IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION:
 +        {
 +            PUSB_IDLE_CALLBACK_INFO CallBackInfo;
 +            DPRINT1("Ehci: IOCTL_INTERNAL_USB_SUBMIT_IDLE_NOTIFICATION\n");
 +            /* FIXME: Set Callback for safe power down */
 +            CallBackInfo = Stack->Parameters.DeviceIoControl.Type3InputBuffer;
-             LONG i;
 +
 +            PdoDeviceExtension->IdleCallback = CallBackInfo->IdleCallback;
 +            PdoDeviceExtension->IdleContext = CallBackInfo->IdleContext;
 +
 +            Information = 0;
 +            Status = STATUS_SUCCESS;
 +            break;
 +        }
 +        default:
 +        {
 +            DPRINT1("Unhandled IoControlCode %x\n", Stack->Parameters.DeviceIoControl.IoControlCode);
 +            break;
 +        }
 +    }
 +
 +    Irp->IoStatus.Information = Information;
 +
 +    if (Status != STATUS_PENDING)
 +        IoCompleteRequest(Irp, IO_NO_INCREMENT);
 +
 +    return Status;
 +}
 +
 +NTSTATUS
 +PdoQueryId(PDEVICE_OBJECT DeviceObject, PIRP Irp, ULONG_PTR* Information)
 +{
 +    WCHAR Buffer[256];
 +    ULONG Index = 0;
 +    ULONG IdType;
 +    UNICODE_STRING SourceString;
 +    UNICODE_STRING String;
 +    NTSTATUS Status;
 +
 +    IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
 +
 +    switch (IdType)
 +    {
 +        case BusQueryDeviceID:
 +        {
 +            RtlInitUnicodeString(&SourceString, L"USB\\ROOT_HUB20");
 +            break;
 +        }
 +        case BusQueryHardwareIDs:
 +        {
++            /* FIXME: Build from Device Vendor and Device ID */
 +            Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID8086&PID265C&REV0000") + 1;
 +            Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20&VID8086&PID265C") + 1;
 +            Index += swprintf(&Buffer[Index], L"USB\\ROOT_HUB20") + 1;
 +
 +            Buffer[Index] = UNICODE_NULL;
 +            SourceString.Length = SourceString.MaximumLength = Index * sizeof(WCHAR);
 +            SourceString.Buffer = Buffer;
 +            break;
 +
 +        }
 +        case BusQueryCompatibleIDs:
 +        {
 +            /* We have none */
 +            return STATUS_SUCCESS;
 +        }
 +        case BusQueryInstanceID:
 +        {
 +            return STATUS_SUCCESS;
 +        }
 +        default:
 +        {
 +            DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
 +            return STATUS_NOT_SUPPORTED;
 +        }
 +    }
 +
 +    Status = DuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
 +                                    &SourceString,
 +                                    &String);
 +
 +    *Information = (ULONG_PTR)String.Buffer;
 +    return Status;
 +}
 +
 +NTSTATUS
 +PdoQueryDeviceRelations(PDEVICE_OBJECT DeviceObject, PDEVICE_RELATIONS* pDeviceRelations)
 +{
 +    PDEVICE_RELATIONS DeviceRelations;
 +
 +    DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
 +    if (!DeviceRelations)
 +        return STATUS_INSUFFICIENT_RESOURCES;
 +
 +    DeviceRelations->Count = 1;
 +    DeviceRelations->Objects[0] = DeviceObject;
 +    ObReferenceObject(DeviceObject);
 +
 +    *pDeviceRelations = DeviceRelations;
 +    return STATUS_SUCCESS;
 +}
 +
 +NTSTATUS NTAPI
 +PdoDispatchPnp(
 +    IN PDEVICE_OBJECT DeviceObject,
 +    IN PIRP Irp)
 +{
 +    ULONG MinorFunction;
 +    PIO_STACK_LOCATION Stack;
 +    ULONG_PTR Information = Irp->IoStatus.Information;
 +    NTSTATUS Status = Irp->IoStatus.Status;
 +    PDEVICE_CAPABILITIES DeviceCapabilities;
 +    ULONG i;
 +
 +    Stack = IoGetCurrentIrpStackLocation(Irp);
 +    MinorFunction = Stack->MinorFunction;
 +
 +    switch (MinorFunction)
 +    {
 +        case IRP_MN_QUERY_REMOVE_DEVICE:
 +        case IRP_MN_REMOVE_DEVICE:
 +        case IRP_MN_CANCEL_REMOVE_DEVICE:
 +        case IRP_MN_STOP_DEVICE:
 +        case IRP_MN_QUERY_STOP_DEVICE:
 +        case IRP_MN_CANCEL_STOP_DEVICE:
 +        case IRP_MN_QUERY_DEVICE_TEXT:
 +        case IRP_MN_SURPRISE_REMOVAL:
 +        case IRP_MN_QUERY_RESOURCES:
 +        case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
 +        case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
 +        {
 +            Status = STATUS_SUCCESS;
 +            break;
 +        }
 +
 +        case IRP_MN_START_DEVICE:
 +        {
 +            PUSB_DEVICE RootHubDevice;
 +            PPDO_DEVICE_EXTENSION PdoDeviceExtension;
 +            PFDO_DEVICE_EXTENSION FdoDeviceExtension;
 +            UNICODE_STRING InterfaceSymLinkName;
-             for (i = 0; i < PdoDeviceExtension->NumberOfPorts; i++)
-             {
-                 PdoDeviceExtension->Ports[i].PortStatus = 0x8000;
-                 PdoDeviceExtension->Ports[i].PortChange = 0;
-                 if (!FdoDeviceExtension->hcd.ECHICaps.HCSParams.PortPowerControl)
-                     PdoDeviceExtension->Ports[i].PortStatus |= USB_PORT_STATUS_POWER;
-             }
 +
 +            DPRINT1("Ehci: PDO StartDevice\n");
 +            PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
 +            FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->ControllerFdo->DeviceExtension;
 +
 +            /* Create the root hub */
 +            RootHubDevice = InternalCreateUsbDevice(1, 0, NULL, TRUE);
 +
-             /* FIXME: Do something better below */
 +            RtlCopyMemory(&RootHubDevice->DeviceDescriptor,
 +                          ROOTHUB2_DEVICE_DESCRIPTOR,
 +                          sizeof(ROOTHUB2_DEVICE_DESCRIPTOR));
 +
 +            RootHubDevice->DeviceDescriptor.idVendor = FdoDeviceExtension->VendorId;
 +            RootHubDevice->DeviceDescriptor.idProduct = FdoDeviceExtension->DeviceId;
 +
-                     DPRINT1("BusRelations!!!!!\n");
++            /* Here config, interfaces and descriptors are stored. This was duplicated from XEN PV Usb Drivers implementation.
++               Not sure that it is really needed as the information can be queueried from the device. */
 +
 +            RootHubDevice->Configs = ExAllocatePoolWithTag(NonPagedPool,
 +                                                            sizeof(PVOID) * RootHubDevice->DeviceDescriptor.bNumConfigurations,
 +                                                            USB_POOL_TAG);
 +
 +            RootHubDevice->Configs[0] = ExAllocatePoolWithTag(NonPagedPool,
 +                                                            sizeof(USB_CONFIGURATION) + sizeof(PVOID) * ROOTHUB2_CONFIGURATION_DESCRIPTOR[4],
 +                                                            USB_POOL_TAG);
 +
 +            RootHubDevice->Configs[0]->Interfaces[0] = ExAllocatePoolWithTag(NonPagedPool,
 +                                                            sizeof(USB_INTERFACE) + sizeof(PVOID) * ROOTHUB2_INTERFACE_DESCRIPTOR[4],
 +                                                            USB_POOL_TAG);
 +
 +            RootHubDevice->Configs[0]->Interfaces[0]->EndPoints[0] = ExAllocatePoolWithTag(NonPagedPool,
 +                                                            sizeof(USB_ENDPOINT),
 +                                                            USB_POOL_TAG);
 +
 +            RootHubDevice->ActiveConfig = RootHubDevice->Configs[0];
 +            RootHubDevice->ActiveInterface = RootHubDevice->ActiveConfig->Interfaces[0];
 +
 +            RtlCopyMemory(&RootHubDevice->ActiveConfig->ConfigurationDescriptor,
 +                          ROOTHUB2_CONFIGURATION_DESCRIPTOR,
 +                          sizeof(ROOTHUB2_CONFIGURATION_DESCRIPTOR));
 +
 +            RtlCopyMemory(&RootHubDevice->ActiveConfig->Interfaces[0]->InterfaceDescriptor,
 +                         ROOTHUB2_INTERFACE_DESCRIPTOR,
 +                         sizeof(ROOTHUB2_INTERFACE_DESCRIPTOR));
 +
 +            RtlCopyMemory(&RootHubDevice->ActiveConfig->Interfaces[0]->EndPoints[0]->EndPointDescriptor,
 +                         ROOTHUB2_ENDPOINT_DESCRIPTOR,
 +                         sizeof(ROOTHUB2_ENDPOINT_DESCRIPTOR));
 +            RootHubDevice->DeviceSpeed = UsbHighSpeed;
 +            RootHubDevice->DeviceType = Usb20Device;
 +
 +            PdoDeviceExtension->UsbDevices[0] = RootHubDevice;
 +
 +            Status = IoRegisterDeviceInterface(DeviceObject, &GUID_DEVINTERFACE_USB_HUB, NULL, &InterfaceSymLinkName);
 +            if (!NT_SUCCESS(Status))
 +            {
 +                DPRINT1("Failed to register interface\n");
 +                return Status;
 +            }
 +            else
 +            {
 +                Status = IoSetDeviceInterfaceState(&InterfaceSymLinkName, TRUE);
 +                if (!NT_SUCCESS(Status)) 
 +                    return Status;
 +            }
 +
 +            Status = STATUS_SUCCESS;
 +            break;
 +        }
 +        case IRP_MN_QUERY_DEVICE_RELATIONS:
 +        {
 +            DPRINT1("Ehci: PDO QueryDeviceRelations\n");
 +            switch (Stack->Parameters.QueryDeviceRelations.Type)
 +            {
 +                case TargetDeviceRelation:
 +                {
 +                    PDEVICE_RELATIONS DeviceRelations = NULL;
 +                    Status = PdoQueryDeviceRelations(DeviceObject, &DeviceRelations);
 +                    Information = (ULONG_PTR)DeviceRelations;
 +                    break;
 +                }
 +                case BusRelations:
 +                {
 +                    PPDO_DEVICE_EXTENSION PdoDeviceExtension;
 +                    PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
 +
-                        has resent this IRP and type, so leave the next SCE request pending until a new device arrives.
-                        Is there a better way to do this */
++                    DPRINT("BusRelations!!!!!\n");
 +
 +                    /* The hub driver has created the new device object and reported to pnp, as a result the pnp manager
-              /* FIXME */
++                       has sent this IRP and type, so leave the next SCE request pending until a new device arrives.
++                       Is there a better way to do this? */
 +                    ExAcquireFastMutex(&PdoDeviceExtension->ListLock);
 +                    PdoDeviceExtension->HaltQueue = TRUE;
 +                    ExReleaseFastMutex(&PdoDeviceExtension->ListLock);
 +                }
 +                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",
 +                        Stack->Parameters.QueryDeviceRelations.Type);
 +                    Status = STATUS_NOT_SUPPORTED;
 +                    break;
 +                }
 +            }
 +            break;
 +        }
 +        case IRP_MN_QUERY_CAPABILITIES:
 +        {
 +            DPRINT("Ehci: PDO Query Capabilities\n");
 +
 +            DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities;
 +
 +            DeviceCapabilities->LockSupported = FALSE;
 +            DeviceCapabilities->EjectSupported = FALSE;
 +            DeviceCapabilities->Removable = FALSE;
 +            DeviceCapabilities->DockDevice = FALSE;
 +            DeviceCapabilities->UniqueID = FALSE;
 +            DeviceCapabilities->SilentInstall = FALSE;
 +            DeviceCapabilities->RawDeviceOK = FALSE;
 +            DeviceCapabilities->SurpriseRemovalOK = FALSE;
 +            DeviceCapabilities->Address = 0;
 +            DeviceCapabilities->UINumber = 0;
 +            DeviceCapabilities->DeviceD2 = 1;
 +
++             /* FIXME: Verify these settings are correct */
 +            DeviceCapabilities->HardwareDisabled = FALSE;
 +            //DeviceCapabilities->NoDisplayInUI = FALSE;
 +            DeviceCapabilities->DeviceState[0] = PowerDeviceD0;
 +            for (i = 0; i < PowerSystemMaximum; i++)
 +                DeviceCapabilities->DeviceState[i] = PowerDeviceD3;
 +            DeviceCapabilities->DeviceWake = 0;
 +            DeviceCapabilities->D1Latency = 0;
 +            DeviceCapabilities->D2Latency = 0;
 +            DeviceCapabilities->D3Latency = 0;
 +            Information = 0;
 +            Status = STATUS_SUCCESS;
 +            break;
 +        }
 +        /*case IRP_MN_QUERY_DEVICE_TEXT:
 +        {
 +            Status = STATUS_NOT_SUPPORTED;
 +            break;
 +        }*/
 +
 +        case IRP_MN_QUERY_ID:
 +        {
 +            DPRINT("Ehci: PDO Query ID\n");
 +            Status = PdoQueryId(DeviceObject, Irp, &Information);
 +            break;
 +        }
 +        case IRP_MN_QUERY_INTERFACE:
 +        {
 +            UNICODE_STRING GuidString;
 +            PUSB_BUS_INTERFACE_HUB_V5 InterfaceHub;
 +            PUSB_BUS_INTERFACE_USBDI_V2 InterfaceDI;
 +            PPDO_DEVICE_EXTENSION PdoDeviceExtension;
 +            PFDO_DEVICE_EXTENSION FdoDeviceExtension;
 +
 +            DPRINT("Ehci: PDO Query Interface\n");
 +
 +            PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
 +            FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)PdoDeviceExtension->ControllerFdo->DeviceExtension;
 +
 +            Status = RtlStringFromGUID(Stack->Parameters.QueryInterface.InterfaceType, &GuidString);
 +            if (!NT_SUCCESS(Status))
 +            {
 +                DPRINT1("Failed to create string from GUID!\n");
 +            }
 +
 +            /* Assume success */
 +            Status = STATUS_SUCCESS;
 +            Information = 0;
 +
 +            if (IsEqualGUIDAligned(Stack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_HUB_GUID))
 +            {
 +                InterfaceHub = (PUSB_BUS_INTERFACE_HUB_V5)Stack->Parameters.QueryInterface.Interface;
 +                InterfaceHub->Version = Stack->Parameters.QueryInterface.Version;
 +                if (Stack->Parameters.QueryInterface.Version >= 0)
 +                {
 +                    InterfaceHub->Size = Stack->Parameters.QueryInterface.Size;
 +                    InterfaceHub->BusContext = PdoDeviceExtension->DeviceObject;
 +                    InterfaceHub->InterfaceReference = (PINTERFACE_REFERENCE)InterfaceReference;
 +                    InterfaceHub->InterfaceDereference = (PINTERFACE_DEREFERENCE)InterfaceDereference;
 +                }
 +                if (Stack->Parameters.QueryInterface.Version >= 1)
 +                {
 +                    InterfaceHub->CreateUsbDevice = CreateUsbDevice;
 +                    InterfaceHub->InitializeUsbDevice = InitializeUsbDevice;
 +                    InterfaceHub->GetUsbDescriptors = GetUsbDescriptors;
 +                    InterfaceHub->RemoveUsbDevice = RemoveUsbDevice;
 +                    InterfaceHub->RestoreUsbDevice = RestoreUsbDevice;
 +                    InterfaceHub->GetPortHackFlags = GetPortHackFlags;
 +                    InterfaceHub->QueryDeviceInformation = QueryDeviceInformation;
 +                }
 +                if (Stack->Parameters.QueryInterface.Version >= 2)
 +                {
 +                    InterfaceHub->GetControllerInformation = GetControllerInformation;
 +                    InterfaceHub->ControllerSelectiveSuspend = ControllerSelectiveSuspend;
 +                    InterfaceHub->GetExtendedHubInformation = GetExtendedHubInformation;
 +                    InterfaceHub->GetRootHubSymbolicName = GetRootHubSymbolicName;
 +                    InterfaceHub->GetDeviceBusContext = GetDeviceBusContext;
 +                    InterfaceHub->Initialize20Hub = Initialize20Hub;
 +
 +                }
 +                if (Stack->Parameters.QueryInterface.Version >= 3)
 +                {
 +                    InterfaceHub->RootHubInitNotification = RootHubInitNotification;
 +                }
 +                if (Stack->Parameters.QueryInterface.Version >= 4)
 +                {
 +                    InterfaceHub->FlushTransfers = FlushTransfers;
 +                }
 +                if (Stack->Parameters.QueryInterface.Version >= 5)
 +                {
 +                    InterfaceHub->SetDeviceHandleData = SetDeviceHandleData;
 +                }
 +                if (Stack->Parameters.QueryInterface.Version >= 6)
 +                {
 +                    DPRINT1("USB_BUS_INTERFACE_HUB_GUID version not supported!\n");
 +                }
 +                break;
 +            }
 +
 +            if (IsEqualGUIDAligned(Stack->Parameters.QueryInterface.InterfaceType, &USB_BUS_INTERFACE_USBDI_GUID))
 +            {
 +                InterfaceDI = (PUSB_BUS_INTERFACE_USBDI_V2) Stack->Parameters.QueryInterface.Interface;
 +                InterfaceDI->Version = Stack->Parameters.QueryInterface.Version;
 +                if (Stack->Parameters.QueryInterface.Version >= 0)
 +                {
 +                    //InterfaceDI->Size = sizeof(USB_BUS_INTERFACE_USBDI_V2);
 +                    InterfaceDI->Size = Stack->Parameters.QueryInterface.Size;
 +                    InterfaceDI->BusContext = PdoDeviceExtension->DeviceObject;
 +                    InterfaceDI->InterfaceReference = (PINTERFACE_REFERENCE)InterfaceReference;
 +                    InterfaceDI->InterfaceDereference = (PINTERFACE_DEREFERENCE)InterfaceDereference;
 +                    InterfaceDI->GetUSBDIVersion = GetUSBDIVersion;
 +                    InterfaceDI->QueryBusTime = QueryBusTime;
 +                    InterfaceDI->SubmitIsoOutUrb = SubmitIsoOutUrb;
 +                    InterfaceDI->QueryBusInformation = QueryBusInformation;
 +                }
 +                if (Stack->Parameters.QueryInterface.Version >= 1)
 +                {
 +                    InterfaceDI->IsDeviceHighSpeed = IsDeviceHighSpeed;
 +                }
 +                if (Stack->Parameters.QueryInterface.Version >= 2)
 +                {
 +                    InterfaceDI->EnumLogEntry = EnumLogEntry;
 +                }
 +
 +                if (Stack->Parameters.QueryInterface.Version >= 3)
 +                {
 +                    DPRINT1("SB_BUS_INTERFACE_USBDI_GUID version not supported!\n");
 +                }
 +                break;
 +            }
 +
 +            DPRINT1("GUID Not Supported\n");
 +            Status = Irp->IoStatus.Status;
 +            Information = Irp->IoStatus.Information;
 +
 +            break;
 +        }
 +        case IRP_MN_QUERY_BUS_INFORMATION:
 +        {
 +            PPNP_BUS_INFORMATION BusInfo;
 +
 +            BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
 +            if (!BusInfo)
 +                Status = STATUS_INSUFFICIENT_RESOURCES;
 +            else
 +            {
 +                /* FIXME */
 +                /*RtlCopyMemory(
 +                    &BusInfo->BusTypeGuid,
 +                    &GUID_DEVINTERFACE_XXX,
 +                    sizeof(GUID));*/
 +
 +                BusInfo->LegacyBusType = PNPBus;
 +                BusInfo->BusNumber = 0;
 +                Information = (ULONG_PTR)BusInfo;
 +                Status = STATUS_SUCCESS;
 +            }
 +            break;
 +        }
 +        default:
 +        {
 +            /* We are the PDO. So ignore */
 +            DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", MinorFunction);
 +            break;
 +        }
 +    }
 +
 +    Irp->IoStatus.Information = Information;
 +    Irp->IoStatus.Status = Status;
 +    IoCompleteRequest(Irp, IO_NO_INCREMENT);
 +    return Status;
 +}
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 7b808b2,0000000..903a01f
mode 100644,000000..100644
--- /dev/null
@@@ -1,255 -1,0 +1,238 @@@
- typedef struct _EHCIPORTS
- {
-     ULONG PortNumber;
-     ULONG PortType;
-     USHORT PortStatus;
-     USHORT PortChange;
- } EHCIPORTS, *PEHCIPORTS;
 +#pragma once
 +
 +#include "hardware.h"
 +#include <ntifs.h>
 +#include <ntddk.h>
 +#include <stdio.h>
 +#define NDEBUG
 +#include <debug.h>
 +#include <hubbusif.h>
 +#include <usbioctl.h>
 +#include <usb.h>
 +
 +#define USB_POOL_TAG (ULONG)'ebsu'
 +
 +#define DEVICEINTIALIZED        0x01
 +#define DEVICESTARTED           0x02
 +#define DEVICEBUSY              0x04
 +#define DEVICESTOPPED           0x08
 +#define DEVICESTALLED           0x10
 +#define DEVICEREMOVED           0x20
 +
 +
 +#define       MAX_USB_DEVICES         127
 +#define       EHCI_MAX_SIZE_TRANSFER  0x100000
 +
 +#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
 +
 +typedef struct _USB_ENDPOINT
 +{
 +    ULONG Flags;
 +    LIST_ENTRY  UrbList;
 +    struct _USB_INTERFACE *Interface;
 +    USB_ENDPOINT_DESCRIPTOR EndPointDescriptor;
 +} USB_ENDPOINT, *PUSB_ENDPOINT;
 +
 +typedef struct _USB_INTERFACE
 +{
 +    struct _USB_CONFIGURATION *Config;
 +    USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
 +    USB_ENDPOINT *EndPoints[];
 +} USB_INTERFACE, *PUSB_INTERFACE;
 +
 +typedef struct _USB_CONFIGURATION
 +{
 +    struct _USB_DEVICE *Device;
 +    USB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor;
 +    USB_INTERFACE *Interfaces[];
 +} USB_CONFIGURATION, *PUSB_CONFIGURATION;
 +
 +typedef struct _USB_DEVICE
 +{
 +    UCHAR Address;
 +    ULONG Port;
 +    PVOID ParentDevice;
 +    BOOLEAN IsHub;
 +    USB_DEVICE_SPEED DeviceSpeed;
 +    USB_DEVICE_TYPE DeviceType;
 +    ULONG DeviceState;
 +    PDEVICE_OBJECT UsbDevicePdo;
 +    USB_DEVICE_DESCRIPTOR DeviceDescriptor;
 +    UNICODE_STRING LanguageIDs;
 +    UNICODE_STRING iManufacturer;
 +    UNICODE_STRING iProduct;
 +    UNICODE_STRING iSerialNumber;
 +    USB_CONFIGURATION *ActiveConfig;
 +    USB_INTERFACE *ActiveInterface;
 +    USB_CONFIGURATION **Configs;
 +} USB_DEVICE, *PUSB_DEVICE;
 +
 +
 +
 +typedef struct _COMMON_DEVICE_EXTENSION
 +{
 +    BOOLEAN IsFdo;
 +    PDRIVER_OBJECT DriverObject;
 +    PDEVICE_OBJECT DeviceObject;
 +} COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
 +
 +typedef struct _FDO_DEVICE_EXTENSION
 +{
 +    COMMON_DEVICE_EXTENSION Common;
 +
 +    PDEVICE_OBJECT LowerDevice;
 +    PDEVICE_OBJECT Pdo;
 +    ULONG DeviceState;
-     PDMA_ADAPTER pDmaAdapter;
 +    PVOID RootHubDeviceHandle;
-     ULONG MapRegisters;
 +    ULONG Vector;
 +    KIRQL Irql;
 +
 +    KTIMER UpdateTimer;
 +    KINTERRUPT_MODE Mode;
 +    BOOLEAN IrqShared;
 +    PKINTERRUPT EhciInterrupt;
 +    KDPC DpcObject;
 +    KDPC TimerDpcObject;
 +
 +    KAFFINITY Affinity;
 +
-     //PULONG ResourceBase;
-     //ULONG Size;
 +    ULONG BusNumber;
 +    ULONG BusAddress;
 +    ULONG PCIAddress;
 +    USHORT VendorId;
 +    USHORT DeviceId;
 +
 +    BUS_INTERFACE_STANDARD BusInterface;
 +
 +    union
 +    {
 +        ULONG ResourcePort;
 +        ULONG ResourceMemory;
 +    };
 +
 +    EHCI_HOST_CONTROLLER hcd;
 +    PERIODICFRAMELIST PeriodicFrameList;
 +    
 +    FAST_MUTEX FrameListMutex;
 +
 +    BOOLEAN AsyncComplete;
 +
-     ULONG NumberOfPorts;
-     EHCIPORTS Ports[32];
 +} FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
 +
 +typedef struct _PDO_DEVICE_EXTENSION
 +{
 +    COMMON_DEVICE_EXTENSION Common;
 +    PDEVICE_OBJECT DeviceObject;
 +    PDEVICE_OBJECT ControllerFdo;
 +    PUSB_DEVICE UsbDevices[127];
 +    LIST_ENTRY IrpQueue;
 +    KSPIN_LOCK IrpQueueLock;
 +    PIRP CurrentIrp;
 +    HANDLE ThreadHandle;
 +    ULONG ChildDeviceCount;
 +    BOOLEAN HaltQueue;
 +    PVOID CallbackContext;
 +    RH_INIT_CALLBACK *CallbackRoutine;
 +    USB_IDLE_CALLBACK IdleCallback;
 +    PVOID IdleContext;
 +    KTIMER Timer;
 +    KEVENT QueueDrainedEvent;
 +    FAST_MUTEX ListLock;
 +} PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
 +
 +typedef struct _WORKITEMDATA
 +{
 +    WORK_QUEUE_ITEM WorkItem;
 +    PVOID Context;
 +} WORKITEMDATA, *PWORKITEMDATA;
 +
 +VOID NTAPI
 +UrbWorkerThread(PVOID Context);
 +
 +NTSTATUS NTAPI
 +GetBusInterface(PDEVICE_OBJECT pcifido, PBUS_INTERFACE_STANDARD busInterface);
 +
 +NTSTATUS NTAPI
 +ForwardAndWaitCompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp, PKEVENT Event);
 +
 +NTSTATUS NTAPI
 +ForwardAndWait(PDEVICE_OBJECT DeviceObject, PIRP Irp);
 +
 +NTSTATUS NTAPI
 +ForwardIrpAndForget(PDEVICE_OBJECT DeviceObject,PIRP Irp);
 +
 +NTSTATUS NTAPI
 +FdoDispatchPnp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
 +
 +NTSTATUS NTAPI
 +PdoDispatchPnp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
 +
 +NTSTATUS NTAPI
 +AddDevice(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT Pdo);
 +
 +NTSTATUS
 +DuplicateUnicodeString(ULONG Flags, PCUNICODE_STRING SourceString, PUNICODE_STRING DestinationString);
 +
 +PWSTR
 +GetSymbolicName(PDEVICE_OBJECT DeviceObject);
 +
 +PWSTR
 +GetPhysicalDeviceObjectName(PDEVICE_OBJECT DeviceObject);
 +
 +NTSTATUS NTAPI
 +PdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
 +
 +NTSTATUS NTAPI
 +FdoDispatchInternalDeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp);
 +
 +USBD_STATUS
 +ExecuteControlRequest(PFDO_DEVICE_EXTENSION DeviceExtension, PUSB_DEFAULT_PIPE_SETUP_PACKET SetupPacket, UCHAR Address, ULONG Port, PVOID Buffer, ULONG BufferLength);
 +
 +VOID
 +RequestURBCancel (PPDO_DEVICE_EXTENSION DeviceExtension, PIRP Irp);
 +
 +VOID
 +RemoveUrbRequest(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PIRP Irp);
 +
 +VOID
 +QueueURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension, PIRP Irp);
 +
 +VOID
 +CompletePendingURBRequest(PPDO_DEVICE_EXTENSION DeviceExtension);
 +
 +NTSTATUS
 +HandleUrbRequest(PPDO_DEVICE_EXTENSION DeviceExtension, PIRP Irp);
 +
 +PUSB_DEVICE
 +DeviceHandleToUsbDevice(PPDO_DEVICE_EXTENSION PdoDeviceExtension, PUSB_DEVICE_HANDLE DeviceHandle);
 +
 +VOID
 +DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor);
 +
 +VOID
 +DumpFullConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor);
 +
 +
 +VOID
 +DumpTransferDescriptor(PQUEUE_TRANSFER_DESCRIPTOR TransferDescriptor);
 +
 +VOID
 +DumpQueueHead(PQUEUE_HEAD QueueHead);
 +
Simple merge
diff --cc gcc.cmake
index 95bfaa9,0000000..9142772
mode 100644,000000..100644
--- /dev/null
+++ b/gcc.cmake
@@@ -1,323 -1,0 +1,327 @@@
 +
 +# Linking
 +if(ARCH MATCHES i386)
 +link_directories("${REACTOS_SOURCE_DIR}/importlibs")
 +endif()
 +link_directories(${REACTOS_BINARY_DIR}/lib/3rdparty/mingw)
 +set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
 +set(CMAKE_CXX_LINK_EXECUTABLE "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
 +set(CMAKE_EXE_LINKER_FLAGS "-nodefaultlibs -nostdlib -Wl,--enable-auto-image-base -Wl,--disable-auto-import")
 +# -Wl,-T,${REACTOS_SOURCE_DIR}/global.lds
 +set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS_INIT} -Wl,--disable-stdcall-fixup")
 +
 +set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> -i <SOURCE> <CMAKE_C_LINK_FLAGS> <DEFINES> -I${REACTOS_SOURCE_DIR}/include/psdk -I${REACTOS_BINARY_DIR}/include/psdk -I${REACTOS_SOURCE_DIR}/include/ -I${REACTOS_SOURCE_DIR}/include/reactos -I${REACTOS_BINARY_DIR}/include/reactos -I${REACTOS_SOURCE_DIR}/include/reactos/wine -I${REACTOS_SOURCE_DIR}/include/crt -I${REACTOS_SOURCE_DIR}/include/crt/mingw32 -O coff -o <OBJECT>")
 +
++if(NOT CMAKE_HOST_SYSTEM_NAME MATCHES Windows)
++      set(CMAKE_C_CREATE_STATIC_LIBRARY "<CMAKE_AR> crs <TARGET> <LINK_FLAGS> <OBJECTS>")
++endif()
++
 +# Compiler Core
 +add_definitions(-pipe -fms-extensions)
 +
 +set(CMAKE_C_CREATE_SHARED_LIBRARY "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_C_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
 +set(CMAKE_CXX_CREATE_SHARED_LIBRARY "<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
 +set(CMAKE_RC_CREATE_SHARED_LIBRARY "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_C_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
 +
 +# Debugging (Note: DWARF-4 on 4.5.1 when we ship)
 +add_definitions(-gdwarf-2 -g2 -femit-struct-debug-detailed=none -feliminate-unused-debug-types)
 +
 +# Tuning
 +if(ARCH MATCHES i386)
 +    add_definitions(-march=${OARCH} -mtune=${TUNE})
 +else()
 +    add_definitions(-march=${OARCH})
 +endif()
 +
 +# Warnings
 +
 +add_definitions(-Wall -Wno-char-subscripts -Wpointer-arith -Wno-multichar -Wno-error=uninitialized -Wno-unused-value -Winvalid-pch)
 +
 +if(ARCH MATCHES amd64)
 +    add_definitions(-Wno-format)
 +elseif(ARCH MATCHES arm)
 +    add_definitions(-Wno-attributes)
 +endif()
 +
 +# Optimizations
 +
 +if(OPTIMIZE STREQUAL "1")
 +    add_definitions(-Os)
 +elseif(OPTIMIZE STREQUAL "2")
 +    add_definitions(-Os)
 +elseif(OPTIMIZE STREQUAL "3")
 +    add_definitions(-O1)
 +elseif(OPTIMIZE STREQUAL "4")
 +    add_definitions(-O2)
 +elseif(OPTIMIZE STREQUAL "5")
 +    add_definitions(-O3)
 +endif()
 +
 +add_definitions(-fno-strict-aliasing)
 +
 +if(ARCH MATCHES i386)
 +    add_definitions(-mpreferred-stack-boundary=2 -fno-set-stack-executable -fno-optimize-sibling-calls)
 +    if(OPTIMIZE STREQUAL "1")
 +        add_definitions(-ftracer -momit-leaf-frame-pointer)
 +    endif()
 +elseif(ARCH MATCHES amd64)
 +    add_definitions(-mpreferred-stack-boundary=4)
 +    if(OPTIMIZE STREQUAL "1")
 +        add_definitions(-ftracer -momit-leaf-frame-pointer)
 +    endif()
 +elseif(ARCH MATCHES arm)
 +    if(OPTIMIZE STREQUAL "1")
 +        add_definitions(-ftracer)
 +    endif()
 +endif()
 +
 +# Other
 +if(ARCH MATCHES amd64)
 +    add_definitions(-U_X86_ -UWIN32)
 +elseif(ARCH MATCHES arm)
 +    add_definitions(-U_UNICODE -UUNICODE)
 +    add_definitions(-D__MSVCRT__) # DUBIOUS
 +endif()
 +
 +# alternative arch name
 +if(ARCH MATCHES amd64)
 +    set(ARCH2 x86_64)
 +else()
 +    set(ARCH2 ${ARCH})
 +endif()
 +
 +# Macros
 +macro(_PCH_GET_COMPILE_FLAGS _target_name _out_compile_flags _header_filename)
 +    # Add the precompiled header to the build
 +    get_filename_component(FILE ${_header_filename} NAME)
 +    set(_gch_filename "${_target_name}_${FILE}.gch")
 +    list(APPEND ${_out_compile_flags} -c ${_header_filename} -o ${_gch_filename})
 +
 +    # This gets us our includes
 +    get_directory_property(DIRINC INCLUDE_DIRECTORIES)
 +    foreach(item ${DIRINC})
 +        list(APPEND ${_out_compile_flags} -I${item})
 +    endforeach()
 +
 +    # This is a particular bit of undocumented/hacky magic I'm quite proud of
 +    get_directory_property(_compiler_flags DEFINITIONS)
 +    string(REPLACE "\ " "\t" _compiler_flags ${_compiler_flags})
 +    list(APPEND ${_out_compile_flags} ${_compiler_flags})
 +
 +    # This gets any specific definitions that were added with set-target-property
 +    get_target_property(_target_defs ${_target_name} COMPILE_DEFINITIONS)
 +    if (_target_defs)
 +        foreach(item ${_target_defs})
 +            list(APPEND ${_out_compile_flags} -D${item})
 +        endforeach()
 +    endif()
 +endmacro()
 +
 +macro(add_pch _target_name _header_filename _src_list)
 +    get_filename_component(FILE ${_header_filename} NAME)
 +    set(_gch_filename "${_target_name}_${FILE}.gch")
 +    list(APPEND ${_src_list} ${_gch_filename})
 +    _PCH_GET_COMPILE_FLAGS(${_target_name} _args ${_header_filename})
 +    file(REMOVE ${_gch_filename})
 +    add_custom_command(
 +        OUTPUT ${_gch_filename}
 +        COMMAND ${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1} ${_args}
 +        DEPENDS ${_header_filename})
 +endmacro()
 +
 +macro(add_linkerflag MODULE _flag)
 +    set(NEW_LINKER_FLAGS ${_flag})
 +    get_target_property(LINKER_FLAGS ${MODULE} LINK_FLAGS)
 +    if(LINKER_FLAGS)
 +        set(NEW_LINKER_FLAGS "${LINKER_FLAGS} ${NEW_LINKER_FLAGS}")
 +    endif()
 +    set_target_properties(${MODULE} PROPERTIES LINK_FLAGS ${NEW_LINKER_FLAGS})
 +endmacro()
 +
 +# Optional 3rd parameter: stdcall stack bytes
 +macro(set_entrypoint MODULE ENTRYPOINT)
 +    if(${ENTRYPOINT} STREQUAL "0")
 +        add_linkerflag(${MODULE} "-Wl,-entry,0")
 +    elseif(ARCH MATCHES i386)
 +        set(_entrysymbol _${ENTRYPOINT})
 +        if (${ARGC} GREATER 2)
 +            set(_entrysymbol ${_entrysymbol}@${ARGV2})
 +        endif()
 +        add_linkerflag(${MODULE} "-Wl,-entry,${_entrysymbol}")
 +    else()
 +        add_linkerflag(${MODULE} "-Wl,-entry,${ENTRYPOINT}")
 +    endif()
 +endmacro()
 +
 +macro(set_subsystem MODULE SUBSYSTEM)
 +    add_linkerflag(${MODULE} "-Wl,--subsystem,${SUBSYSTEM}")
 +endmacro()
 +
 +macro(set_image_base MODULE IMAGE_BASE)
 +    add_linkerflag(${MODULE} "-Wl,--image-base,${IMAGE_BASE}")
 +endmacro()
 +
 +macro(set_module_type MODULE TYPE)
 +
 +    add_dependencies(${MODULE} psdk buildno_header)
 +    if(${IS_CPP})
 +        target_link_libraries(${MODULE} stlport -lsupc++ -lgcc)
 +    endif()
 +
 +    if(${TYPE} MATCHES nativecui)
 +        set_subsystem(${MODULE} native)
 +        set_entrypoint(${MODULE} NtProcessStartup 4)
 +    elseif(${TYPE} MATCHES win32gui)
 +        set_subsystem(${MODULE} windows)
 +        set_entrypoint(${MODULE} WinMainCRTStartup)
 +        if(NOT IS_UNICODE)
 +            target_link_libraries(${MODULE} mingw_main)
 +        else()
 +            target_link_libraries(${MODULE} mingw_wmain)
 +        endif(NOT IS_UNICODE)
 +        target_link_libraries(${MODULE} mingw_common)
 +    elseif(${TYPE} MATCHES win32cui)
 +        set_subsystem(${MODULE} console)
 +        set_entrypoint(${MODULE} mainCRTStartup)
 +        if(NOT IS_UNICODE)
 +            target_link_libraries(${MODULE} mingw_main)
 +        else()
 +            target_link_libraries(${MODULE} mingw_wmain)
 +        endif(NOT IS_UNICODE)
 +        target_link_libraries(${MODULE} mingw_common)
 +    elseif(${TYPE} MATCHES win32dll)
 +        set_entrypoint(${MODULE} DllMain 12)
 +        target_link_libraries(${MODULE} mingw_dllmain mingw_common)
 +        if(DEFINED baseaddress_${MODULE})
 +            set_image_base(${MODULE} ${baseaddress_${MODULE}})
 +        else()
 +            message(STATUS "${MODULE} has no base address")
 +        endif()
 +    elseif(${TYPE} MATCHES win32ocx)
 +        set_entrypoint(${MODULE} DllMain 12)
 +        target_link_libraries(${MODULE} mingw_dllmain mingw_common)
 +        set_target_properties(${MODULE} PROPERTIES SUFFIX ".ocx")
 +    elseif(${TYPE} MATCHES cpl)
 +        set_entrypoint(${MODULE} DllMain 12)
 +        target_link_libraries(${MODULE} mingw_dllmain mingw_common)
 +        set_target_properties(${MODULE} PROPERTIES SUFFIX ".cpl")
 +    elseif(${TYPE} MATCHES kernelmodedriver)
 +        set_target_properties(${MODULE} PROPERTIES LINK_FLAGS "-Wl,--exclude-all-symbols -Wl,-file-alignment=0x1000 -Wl,-section-alignment=0x1000" SUFFIX ".sys")
 +        set_entrypoint(${MODULE} DriverEntry 8)
 +        set_subsystem(${MODULE} native)
 +        set_image_base(${MODULE} 0x00010000)
 +        add_dependencies(${MODULE} bugcodes)
 +    elseif(${TYPE} MATCHES nativedll)
 +        set_subsystem(${MODULE} native)
 +    else()
 +        message(FATAL_ERROR "Unknown module type : ${TYPE}")
 +    endif()
 +endmacro()
 +
 +macro(set_unicode)
 +   add_definitions(-DUNICODE -D_UNICODE)
 +   set(IS_UNICODE 1)
 +endmacro()
 +
 +# Workaround lack of mingw RC support in cmake
 +macro(set_rc_compiler)
 +    get_directory_property(defines COMPILE_DEFINITIONS)
 +    get_directory_property(includes INCLUDE_DIRECTORIES)
 +
 +    foreach(arg ${defines})
 +        set(rc_result_defs "${rc_result_defs} -D${arg}")
 +    endforeach()
 +
 +    foreach(arg ${includes})
 +        set(rc_result_incs "-I${arg} ${rc_result_incs}")
 +    endforeach()
 +
 +    set(CMAKE_RC_COMPILE_OBJECT "<CMAKE_RC_COMPILER> ${rc_result_defs} ${rc_result_incs} -i <SOURCE> -O coff -o <OBJECT>")
 +endmacro()
 +
 +#idl files support
 +set(IDL_COMPILER native-widl)
 +
 +if(ARCH MATCHES i386)
 +    set(IDL_FLAGS -m32 --win32)
 +elseif(ARCH MATCHES amd64)
 +    set(IDL_FLAGS -m64 --win64)
 +endif()
 +
 +set(IDL_HEADER_ARG -h -o) #.h
 +set(IDL_TYPELIB_ARG -t -o) #.tlb
 +set(IDL_SERVER_ARG -s -S) #.c for server library
 +set(IDL_CLIENT_ARG -c -C) #.c for stub client library
 +set(IDL_PROXY_ARG -p -P)
 +set(IDL_INTERFACE_ARG -u -o)
 +set(IDL_DLLDATA_ARG --dlldata-only -o)
 +
 +
 +macro(add_importlibs MODULE)
 +    add_dependency_node(${MODULE})
 +    foreach(LIB ${ARGN})
 +        target_link_libraries(${MODULE} ${CMAKE_BINARY_DIR}/importlibs/lib${LIB}.a)
 +        add_dependencies(${MODULE} lib${LIB})
 +        add_dependency_edge(${MODULE} ${LIB})
 +    endforeach()
 +endmacro()
 +
 +if(NOT ARCH MATCHES i386)
 +    set(DECO_OPTION "-@")
 +endif()
 +
 +macro(add_importlib_target _exports_file)
 +
 +    get_filename_component(_name ${_exports_file} NAME_WE)
 +    get_filename_component(_extension ${_exports_file} EXT)
 +    get_target_property(_suffix ${_name} SUFFIX)
 +    if(${_suffix} STREQUAL "_suffix-NOTFOUND")
 +        get_target_property(_type ${_name} TYPE)
 +        if(${_type} MATCHES EXECUTABLE)
 +            set(_suffix ".exe")
 +        else()
 +            set(_suffix ".dll")
 +        endif()
 +    endif()
 +
 +    if (${_extension} STREQUAL ".spec")
 +
 +        add_custom_command(
 +            OUTPUT ${CMAKE_BINARY_DIR}/importlibs/lib${_name}.a
 +            COMMAND native-spec2def -n=${_name}${_suffix} -a=${ARCH2} -d=${CMAKE_CURRENT_BINARY_DIR}/${_name}_implib.def ${CMAKE_CURRENT_SOURCE_DIR}/${_exports_file}
 +            COMMAND ${MINGW_PREFIX}dlltool --def ${CMAKE_CURRENT_BINARY_DIR}/${_name}_implib.def --kill-at --output-lib=${CMAKE_BINARY_DIR}/importlibs/lib${_name}.a
 +            DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${_exports_file})
 +
 +    elseif(${_extension} STREQUAL ".def")
 +        message("Use of def files for import libs is deprecated: ${_exports_file}")
 +        add_custom_command(
 +            OUTPUT ${CMAKE_BINARY_DIR}/importlibs/lib${_name}.a
 +            COMMAND ${MINGW_PREFIX}dlltool --def ${CMAKE_CURRENT_SOURCE_DIR}/${_exports_file} --kill-at --output-lib=${CMAKE_BINARY_DIR}/importlibs/lib${_name}.a
 +            DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${_exports_file})
 +    else()
 +        message(FATAL_ERROR "Unsupported exports file extension: ${_extension}")
 +    endif()
 +
 +    add_custom_target(
 +        lib${_name}
 +        DEPENDS ${CMAKE_BINARY_DIR}/importlibs/lib${_name}.a)
 +
 +endmacro()
 +
 +macro(spec2def _dllname _spec_file)
 +    get_filename_component(_file ${_spec_file} NAME_WE)
 +    add_custom_command(
 +        OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_file}.def ${CMAKE_CURRENT_BINARY_DIR}/${_file}_stubs.c
 +        COMMAND native-spec2def -n=${_dllname} --kill-at -a=${ARCH2} -d=${CMAKE_CURRENT_BINARY_DIR}/${_file}.def -s=${CMAKE_CURRENT_BINARY_DIR}/${_file}_stubs.c ${CMAKE_CURRENT_SOURCE_DIR}/${_spec_file}
 +        DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${_spec_file})
 +    set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${_file}.def
 +        PROPERTIES GENERATED TRUE EXTERNAL_OBJECT TRUE)
 +    set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/${_file}_stubs.c PROPERTIES GENERATED TRUE)
 +endmacro()
 +
 +macro(macro_mc FILE)
 +    set(COMMAND_MC ${MINGW_PREFIX}windmc -A -b ${CMAKE_CURRENT_SOURCE_DIR}/${FILE}.mc -r ${REACTOS_BINARY_DIR}/include/reactos -h ${REACTOS_BINARY_DIR}/include/reactos)
 +endmacro()
 +
 +#pseh lib, needed with mingw
 +set(PSEH_LIB "pseh")
index 1a6dc56,0000000..2abea6e
mode 100644,000000..100644
--- /dev/null
@@@ -1,2818 -1,0 +1,2840 @@@
- RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
-                                        UNICODE_STRING *section_name, PVOID ptr )
 +/*
 + * COPYRIGHT:       See COPYING in the top level directory
 + * PROJECT:         ReactOS Runtime Library
 + * PURPOSE:         Activation Context Support
 + * FILE:            lib/rtl/actctx.c
 + * PROGRAMERS:      
 + *                  Jon Griffiths
 + *                  Eric Pouech
 + *                  Jacek Caban for CodeWeavers
 + *                  Alexandre Julliard
 + *                  Stefan Ginsberg (stefan__100__@hotmail.com)
 + *                  Samuel SerapiĆ³n
 + */
 +
 +/* Based on Wine 1.1.26 */
 +
 +/* INCLUDES *****************************************************************/
 +#include <rtl.h>
 +
 +#define NDEBUG
 +#include <debug.h>
 +
 +#include <wine/unicode.h>
 +
 +BOOLEAN RtlpNotAllowingMultipleActivation;
 +
 +#define QUERY_ACTCTX_FLAG_ACTIVE (0x00000001)
 +
 +#define ACTCTX_FLAGS_ALL (\
 +    ACTCTX_FLAG_PROCESSOR_ARCHITECTURE_VALID |\
 +    ACTCTX_FLAG_LANGID_VALID |\
 +    ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID |\
 +    ACTCTX_FLAG_RESOURCE_NAME_VALID |\
 +    ACTCTX_FLAG_SET_PROCESS_DEFAULT |\
 +    ACTCTX_FLAG_APPLICATION_NAME_VALID |\
 +    ACTCTX_FLAG_SOURCE_IS_ASSEMBLYREF |\
 +    ACTCTX_FLAG_HMODULE_VALID )
 +
 +#define ACTCTX_MAGIC       0xC07E3E11
 +
 +#define ACTCTX_FAKE_HANDLE ((HANDLE) 0xf00baa)
 +#define ACTCTX_FAKE_COOKIE ((ULONG_PTR) 0xf00bad)
 +
 +
 +
 +typedef struct
 +{
 +    const WCHAR        *ptr;
 +    unsigned int        len;
 +} xmlstr_t;
 +
 +typedef struct
 +{
 +    const WCHAR        *ptr;
 +    const WCHAR        *end;
 +} xmlbuf_t;
 +
 +struct file_info
 +{
 +    ULONG               type;
 +    WCHAR              *info;
 +};
 +
 +struct assembly_version
 +{
 +    USHORT              major;
 +    USHORT              minor;
 +    USHORT              build;
 +    USHORT              revision;
 +};
 +
 +struct assembly_identity
 +{
 +    WCHAR                *name;
 +    WCHAR                *arch;
 +    WCHAR                *public_key;
 +    WCHAR                *language;
 +    WCHAR                *type;
 +    struct assembly_version version;
 +    BOOL                  optional;
 +};
 +
 +struct entity
 +{
 +    DWORD kind;
 +    union
 +    {
 +        struct
 +        {
 +            WCHAR *tlbid;
 +            WCHAR *version;
 +            WCHAR *helpdir;
 +        } typelib;
 +        struct
 +        {
 +            WCHAR *clsid;
 +        } comclass;
 +        struct {
 +            WCHAR *iid;
 +            WCHAR *name;
 +        } proxy;
 +        struct
 +        {
 +            WCHAR *name;
 +        } class;
 +        struct
 +        {
 +            WCHAR *name;
 +            WCHAR *clsid;
 +        } clrclass;
 +        struct
 +        {
 +            WCHAR *name;
 +            WCHAR *clsid;
 +        } clrsurrogate;
 +    } u;
 +};
 +
 +struct entity_array
 +{
 +    struct entity        *base;
 +    unsigned int          num;
 +    unsigned int          allocated;
 +};
 +
 +struct dll_redirect
 +{
 +    WCHAR                *name;
 +    WCHAR                *hash;
 +    struct entity_array   entities;
 +};
 +
 +enum assembly_type
 +{
 +    APPLICATION_MANIFEST,
 +    ASSEMBLY_MANIFEST,
 +    ASSEMBLY_SHARED_MANIFEST,
 +};
 +
 +struct assembly
 +{
 +    enum assembly_type       type;
 +    struct assembly_identity id;
 +    struct file_info         manifest;
 +    WCHAR                   *directory;
 +    BOOL                     no_inherit;
 +    struct dll_redirect     *dlls;
 +    unsigned int             num_dlls;
 +    unsigned int             allocated_dlls;
 +    struct entity_array      entities;
 +};
 +
 +typedef struct _ACTIVATION_CONTEXT
 +{
 +    ULONG               magic;
 +    long                 ref_count;
 +    struct file_info    config;
 +    struct file_info    appdir;
 +    struct assembly    *assemblies;
 +    unsigned int        num_assemblies;
 +    unsigned int        allocated_assemblies;
 +} ACTIVATION_CONTEXT;
 +
 +struct actctx_loader
 +{
 +    ACTIVATION_CONTEXT       *actctx;
 +    struct assembly_identity *dependencies;
 +    unsigned int              num_dependencies;
 +    unsigned int              allocated_dependencies;
 +};
 +
 +static const WCHAR assemblyW[] = {'a','s','s','e','m','b','l','y',0};
 +static const WCHAR assemblyIdentityW[] = {'a','s','s','e','m','b','l','y','I','d','e','n','t','i','t','y',0};
 +static const WCHAR bindingRedirectW[] = {'b','i','n','d','i','n','g','R','e','d','i','r','e','c','t',0};
 +static const WCHAR clrClassW[] = {'c','l','r','C','l','a','s','s',0};
 +static const WCHAR clrSurrogateW[] = {'c','l','r','S','u','r','r','o','g','a','t','e',0};
 +static const WCHAR comClassW[] = {'c','o','m','C','l','a','s','s',0};
 +static const WCHAR comInterfaceExternalProxyStubW[] = {'c','o','m','I','n','t','e','r','f','a','c','e','E','x','t','e','r','n','a','l','P','r','o','x','y','S','t','u','b',0};
 +static const WCHAR comInterfaceProxyStubW[] = {'c','o','m','I','n','t','e','r','f','a','c','e','P','r','o','x','y','S','t','u','b',0};
 +static const WCHAR dependencyW[] = {'d','e','p','e','n','d','e','n','c','y',0};
 +static const WCHAR dependentAssemblyW[] = {'d','e','p','e','n','d','e','n','t','A','s','s','e','m','b','l','y',0};
 +static const WCHAR descriptionW[] = {'d','e','s','c','r','i','p','t','i','o','n',0};
 +static const WCHAR fileW[] = {'f','i','l','e',0};
 +static const WCHAR asmv2hashW[] = {'a','s','m','v','2',':','h','a','s','h',0};
 +static const WCHAR noInheritW[] = {'n','o','I','n','h','e','r','i','t',0};
 +static const WCHAR noInheritableW[] = {'n','o','I','n','h','e','r','i','t','a','b','l','e',0};
 +static const WCHAR typelibW[] = {'t','y','p','e','l','i','b',0};
 +static const WCHAR windowClassW[] = {'w','i','n','d','o','w','C','l','a','s','s',0};
 +
 +static const WCHAR clsidW[] = {'c','l','s','i','d',0};
 +static const WCHAR hashW[] = {'h','a','s','h',0};
 +static const WCHAR hashalgW[] = {'h','a','s','h','a','l','g',0};
 +static const WCHAR helpdirW[] = {'h','e','l','p','d','i','r',0};
 +static const WCHAR iidW[] = {'i','i','d',0};
 +static const WCHAR languageW[] = {'l','a','n','g','u','a','g','e',0};
 +static const WCHAR manifestVersionW[] = {'m','a','n','i','f','e','s','t','V','e','r','s','i','o','n',0};
 +static const WCHAR nameW[] = {'n','a','m','e',0};
 +static const WCHAR newVersionW[] = {'n','e','w','V','e','r','s','i','o','n',0};
 +static const WCHAR oldVersionW[] = {'o','l','d','V','e','r','s','i','o','n',0};
 +static const WCHAR optionalW[] = {'o','p','t','i','o','n','a','l',0};
 +static const WCHAR processorArchitectureW[] = {'p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e',0};
 +static const WCHAR publicKeyTokenW[] = {'p','u','b','l','i','c','K','e','y','T','o','k','e','n',0};
 +static const WCHAR tlbidW[] = {'t','l','b','i','d',0};
 +static const WCHAR typeW[] = {'t','y','p','e',0};
 +static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
 +static const WCHAR xmlnsW[] = {'x','m','l','n','s',0};
 +
 +static const WCHAR xmlW[] = {'?','x','m','l',0};
 +static const WCHAR manifestv1W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','1',0};
 +static const WCHAR manifestv3W[] = {'u','r','n',':','s','c','h','e','m','a','s','-','m','i','c','r','o','s','o','f','t','-','c','o','m',':','a','s','m','.','v','3',0};
 +
 +static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
 +static const WCHAR version_formatW[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
 +
 +static ACTIVATION_CONTEXT system_actctx = { ACTCTX_MAGIC, 1 };
 +static ACTIVATION_CONTEXT *process_actctx = &system_actctx;
 +
 +static WCHAR *strdupW(const WCHAR* str)
 +{
 +    WCHAR*      ptr;
 +
 +    if (!(ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR))))
 +        return NULL;
 +    return strcpyW(ptr, str);
 +}
 +
 +static WCHAR *xmlstrdupW(const xmlstr_t* str)
 +{
 +    WCHAR *strW;
 +
 +    if ((strW = RtlAllocateHeap(RtlGetProcessHeap(), 0, (str->len + 1) * sizeof(WCHAR))))
 +    {
 +        memcpy( strW, str->ptr, str->len * sizeof(WCHAR) );
 +        strW[str->len] = 0;
 +    }
 +    return strW;
 +}
 +
 +static UNICODE_STRING xmlstr2unicode(const xmlstr_t *xmlstr)
 +{
 +    UNICODE_STRING res;
 +
 +    res.Buffer = (PWSTR)xmlstr->ptr;
 +    res.Length = res.MaximumLength = xmlstr->len * sizeof(WCHAR);
 +
 +    return res;
 +}
 +
 +static inline BOOL xmlstr_cmp(const xmlstr_t* xmlstr, const WCHAR *str)
 +{
 +    return !strncmpW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
 +}
 +
 +static inline BOOL xmlstr_cmpi(const xmlstr_t* xmlstr, const WCHAR *str)
 +{
 +    return !strncmpiW(xmlstr->ptr, str, xmlstr->len) && !str[xmlstr->len];
 +}
 +
 +static inline BOOL xmlstr_cmp_end(const xmlstr_t* xmlstr, const WCHAR *str)
 +{
 +    return (xmlstr->len && xmlstr->ptr[0] == '/' &&
 +            !strncmpW(xmlstr->ptr + 1, str, xmlstr->len - 1) && !str[xmlstr->len - 1]);
 +}
 +
 +static inline BOOL isxmlspace( WCHAR ch )
 +{
 +    return (ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t');
 +}
 +
 +static struct assembly *add_assembly(ACTIVATION_CONTEXT *actctx, enum assembly_type at)
 +{
 +    struct assembly *assembly;
 +
 +    if (actctx->num_assemblies == actctx->allocated_assemblies)
 +    {
 +        void *ptr;
 +        unsigned int new_count;
 +        if (actctx->assemblies)
 +        {
 +            new_count = actctx->allocated_assemblies * 2;
 +            ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
 +                                     actctx->assemblies, new_count * sizeof(*assembly) );
 +        }
 +        else
 +        {
 +            new_count = 4;
 +            ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly) );
 +        }
 +        if (!ptr) return NULL;
 +        actctx->assemblies = ptr;
 +        actctx->allocated_assemblies = new_count;
 +    }
 +
 +    assembly = &actctx->assemblies[actctx->num_assemblies++];
 +    assembly->type = at;
 +    return assembly;
 +}
 +
 +static struct dll_redirect* add_dll_redirect(struct assembly* assembly)
 +{
 +    if (assembly->num_dlls == assembly->allocated_dlls)
 +    {
 +        void *ptr;
 +        unsigned int new_count;
 +        if (assembly->dlls)
 +        {
 +            new_count = assembly->allocated_dlls * 2;
 +            ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
 +                                     assembly->dlls, new_count * sizeof(*assembly->dlls) );
 +        }
 +        else
 +        {
 +            new_count = 4;
 +            ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*assembly->dlls) );
 +        }
 +        if (!ptr) return NULL;
 +        assembly->dlls = ptr;
 +        assembly->allocated_dlls = new_count;
 +    }
 +    return &assembly->dlls[assembly->num_dlls++];
 +}
 +
 +static void free_assembly_identity(struct assembly_identity *ai)
 +{
 +    RtlFreeHeap( RtlGetProcessHeap(), 0, ai->name );
 +    RtlFreeHeap( RtlGetProcessHeap(), 0, ai->arch );
 +    RtlFreeHeap( RtlGetProcessHeap(), 0, ai->public_key );
 +    RtlFreeHeap( RtlGetProcessHeap(), 0, ai->language );
 +    RtlFreeHeap( RtlGetProcessHeap(), 0, ai->type );
 +}
 +
 +static struct entity* add_entity(struct entity_array *array, DWORD kind)
 +{
 +    struct entity*      entity;
 +
 +    if (array->num == array->allocated)
 +    {
 +        void *ptr;
 +        unsigned int new_count;
 +        if (array->base)
 +        {
 +            new_count = array->allocated * 2;
 +            ptr = RtlReAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
 +                                     array->base, new_count * sizeof(*array->base) );
 +        }
 +        else
 +        {
 +            new_count = 4;
 +            ptr = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, new_count * sizeof(*array->base) );
 +        }
 +        if (!ptr) return NULL;
 +        array->base = ptr;
 +        array->allocated = new_count;
 +    }
 +    entity = &array->base[array->num++];
 +    entity->kind = kind;
 +    return entity;
 +}
 +
 +static void free_entity_array(struct entity_array *array)
 +{
 +    unsigned int i;
 +    for (i = 0; i < array->num; i++)
 +    {
 +        struct entity *entity = &array->base[i];
 +        switch (entity->kind)
 +        {
 +        case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
 +            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.comclass.clsid);
 +            break;
 +        case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
 +            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.proxy.iid);
 +            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.proxy.name);
 +            break;
 +        case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
 +            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.tlbid);
 +            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.version);
 +            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.typelib.helpdir);
 +            break;
 +        case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
 +            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.class.name);
 +            break;
 +        case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
 +            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrclass.name);
 +            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrclass.clsid);
 +            break;
 +        case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
 +            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.name);
 +            RtlFreeHeap(RtlGetProcessHeap(), 0, entity->u.clrsurrogate.clsid);
 +            break;
 +        default:
 +            DPRINT1("Unknown entity kind %d\n", entity->kind);
 +        }
 +    }
 +    RtlFreeHeap( RtlGetProcessHeap(), 0, array->base );
 +}
 +
 +static BOOL is_matching_string( const WCHAR *str1, const WCHAR *str2 )
 +{
 +    if (!str1) return !str2;
 +    return str2 && !strcmpiW( str1, str2 );
 +}
 +
 +static BOOL is_matching_identity( const struct assembly_identity *id1,
 +                                  const struct assembly_identity *id2 )
 +{
 +    if (!is_matching_string( id1->name, id2->name )) return FALSE;
 +    if (!is_matching_string( id1->arch, id2->arch )) return FALSE;
 +    if (!is_matching_string( id1->public_key, id2->public_key )) return FALSE;
 +
 +    if (id1->language && id2->language && strcmpiW( id1->language, id2->language ))
 +    {
 +        static const WCHAR wildcardW[] = {'*',0};
 +        if (strcmpW( wildcardW, id1->language ) && strcmpW( wildcardW, id2->language ))
 +            return FALSE;
 +    }
 +    if (id1->version.major != id2->version.major) return FALSE;
 +    if (id1->version.minor != id2->version.minor) return FALSE;
 +    if (id1->version.build > id2->version.build) return FALSE;
 +    if (id1->version.build == id2->version.build &&
 +        id1->version.revision > id2->version.revision) return FALSE;
 +    return TRUE;
 +}
 +
 +static BOOL add_dependent_assembly_id(struct actctx_loader* acl,
 +                                      struct assembly_identity* ai)
 +{
 +    unsigned int i;
 +
 +    /* check if we already have that assembly */
 +
 +    for (i = 0; i < acl->actctx->num_assemblies; i++)
 +        if (is_matching_identity( ai, &acl->actctx->assemblies[i].id ))
 +        {
 +            DPRINT( "reusing existing assembly for %S arch %S version %u.%u.%u.%u\n",
 +                   ai->name, ai->arch, ai->version.major, ai->version.minor,
 +                   ai->version.build, ai->version.revision );
 +            return TRUE;
 +        }
 +
 +    for (i = 0; i < acl->num_dependencies; i++)
 +        if (is_matching_identity( ai, &acl->dependencies[i] ))
 +        {
 +            DPRINT( "reusing existing dependency for %S arch %S version %u.%u.%u.%u\n",
 +                   ai->name, ai->arch, ai->version.major, ai->version.minor,
 +                   ai->version.build, ai->version.revision );
 +            return TRUE;
 +        }
 +
 +    if (acl->num_dependencies == acl->allocated_dependencies)
 +    {
 +        void *ptr;
 +        unsigned int new_count;
 +        if (acl->dependencies)
 +        {
 +            new_count = acl->allocated_dependencies * 2;
 +            ptr = RtlReAllocateHeap(RtlGetProcessHeap(), 0, acl->dependencies,
 +                                    new_count * sizeof(acl->dependencies[0]));
 +        }
 +        else
 +        {
 +            new_count = 4;
 +            ptr = RtlAllocateHeap(RtlGetProcessHeap(), 0, new_count * sizeof(acl->dependencies[0]));
 +        }
 +        if (!ptr) return FALSE;
 +        acl->dependencies = ptr;
 +        acl->allocated_dependencies = new_count;
 +    }
 +    acl->dependencies[acl->num_dependencies++] = *ai;
 +
 +    return TRUE;
 +}
 +
 +static void free_depend_manifests(struct actctx_loader* acl)
 +{
 +    unsigned int i;
 +    for (i = 0; i < acl->num_dependencies; i++)
 +        free_assembly_identity(&acl->dependencies[i]);
 +    RtlFreeHeap(RtlGetProcessHeap(), 0, acl->dependencies);
 +}
 +
 +static WCHAR *build_assembly_dir(struct assembly_identity* ai)
 +{
 +    static const WCHAR undW[] = {'_',0};
 +    static const WCHAR noneW[] = {'n','o','n','e',0};
 +    static const WCHAR mskeyW[] = {'d','e','a','d','b','e','e','f',0};
 +
 +    const WCHAR *arch = ai->arch ? ai->arch : noneW;
 +    const WCHAR *key = ai->public_key ? ai->public_key : noneW;
 +    const WCHAR *lang = ai->language ? ai->language : noneW;
 +    const WCHAR *name = ai->name ? ai->name : noneW;
 +    SIZE_T size = (strlenW(arch) + 1 + strlenW(name) + 1 + strlenW(key) + 24 + 1 +
 +                  strlenW(lang) + 1) * sizeof(WCHAR) + sizeof(mskeyW);
 +    WCHAR *ret;
 +
 +    if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) return NULL;
 +
 +    strcpyW( ret, arch );
 +    strcatW( ret, undW );
 +    strcatW( ret, name );
 +    strcatW( ret, undW );
 +    strcatW( ret, key );
 +    strcatW( ret, undW );
 +    sprintfW( ret + strlenW(ret), version_formatW,
 +              ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
 +    strcatW( ret, undW );
 +    strcatW( ret, lang );
 +    strcatW( ret, undW );
 +    strcatW( ret, mskeyW );
 +    return ret;
 +}
 +
 +static inline void append_string( WCHAR *buffer, const WCHAR *prefix, const WCHAR *str )
 +{
 +    WCHAR *p = buffer;
 +
 +    if (!str) return;
 +    strcatW( buffer, prefix );
 +    p += strlenW(p);
 +    *p++ = '"';
 +    strcpyW( p, str );
 +    p += strlenW(p);
 +    *p++ = '"';
 +    *p = 0;
 +}
 +
 +static WCHAR *build_assembly_id( const struct assembly_identity *ai )
 +{
 +    static const WCHAR archW[] =
 +        {',','p','r','o','c','e','s','s','o','r','A','r','c','h','i','t','e','c','t','u','r','e','=',0};
 +    static const WCHAR public_keyW[] =
 +        {',','p','u','b','l','i','c','K','e','y','T','o','k','e','n','=',0};
 +    static const WCHAR typeW[] =
 +        {',','t','y','p','e','=',0};
 +    static const WCHAR versionW[] =
 +        {',','v','e','r','s','i','o','n','=',0};
 +
 +    WCHAR version[64], *ret;
 +    SIZE_T size = 0;
 +
 +    sprintfW( version, version_formatW,
 +              ai->version.major, ai->version.minor, ai->version.build, ai->version.revision );
 +    if (ai->name) size += strlenW(ai->name) * sizeof(WCHAR);
 +    if (ai->arch) size += strlenW(archW) + strlenW(ai->arch) + 2;
 +    if (ai->public_key) size += strlenW(public_keyW) + strlenW(ai->public_key) + 2;
 +    if (ai->type) size += strlenW(typeW) + strlenW(ai->type) + 2;
 +    size += strlenW(versionW) + strlenW(version) + 2;
 +
 +    if (!(ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
 +        return NULL;
 +
 +    if (ai->name) strcpyW( ret, ai->name );
 +    else *ret = 0;
 +    append_string( ret, archW, ai->arch );
 +    append_string( ret, public_keyW, ai->public_key );
 +    append_string( ret, typeW, ai->type );
 +    append_string( ret, versionW, version );
 +    return ret;
 +}
 +
 +static ACTIVATION_CONTEXT *check_actctx( HANDLE h )
 +{
 +    ACTIVATION_CONTEXT *ret = NULL, *actctx = h;
 +
 +    if (!h || h == INVALID_HANDLE_VALUE) return NULL;
 +    _SEH2_TRY
 +    {
 +        if (actctx && actctx->magic == ACTCTX_MAGIC) ret = actctx;
 +    }
 +    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +    {
 +        DPRINT1("Invalid activation context handle!\n");
 +    }
 +    _SEH2_END;
 +    return ret;
 +}
 +
 +static inline void actctx_addref( ACTIVATION_CONTEXT *actctx )
 +{
 +    InterlockedExchangeAdd( &actctx->ref_count, 1 );
 +}
 +
 +static void actctx_release( ACTIVATION_CONTEXT *actctx )
 +{
 +    if (InterlockedExchangeAdd( &actctx->ref_count, -1 ) == 1)
 +    {
 +        unsigned int i, j;
 +
 +        for (i = 0; i < actctx->num_assemblies; i++)
 +        {
 +            struct assembly *assembly = &actctx->assemblies[i];
 +            for (j = 0; j < assembly->num_dlls; j++)
 +            {
 +                struct dll_redirect *dll = &assembly->dlls[j];
 +                free_entity_array( &dll->entities );
 +                RtlFreeHeap( RtlGetProcessHeap(), 0, dll->name );
 +                RtlFreeHeap( RtlGetProcessHeap(), 0, dll->hash );
 +            }
 +            RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->dlls );
 +            RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->manifest.info );
 +            RtlFreeHeap( RtlGetProcessHeap(), 0, assembly->directory );
 +            free_entity_array( &assembly->entities );
 +            free_assembly_identity(&assembly->id);
 +        }
 +        RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->config.info );
 +        RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->appdir.info );
 +        RtlFreeHeap( RtlGetProcessHeap(), 0, actctx->assemblies );
 +        actctx->magic = 0;
 +        RtlFreeHeap( RtlGetProcessHeap(), 0, actctx );
 +    }
 +}
 +
 +static BOOL next_xml_attr(xmlbuf_t* xmlbuf, xmlstr_t* name, xmlstr_t* value,
 +                          BOOL* error, BOOL* end)
 +{
 +    const WCHAR* ptr;
 +
 +    *error = TRUE;
 +
 +    while (xmlbuf->ptr < xmlbuf->end && isxmlspace(*xmlbuf->ptr))
 +        xmlbuf->ptr++;
 +
 +    if (xmlbuf->ptr == xmlbuf->end) return FALSE;
 +
 +    if (*xmlbuf->ptr == '/')
 +    {
 +        xmlbuf->ptr++;
 +        if (xmlbuf->ptr == xmlbuf->end || *xmlbuf->ptr != '>')
 +            return FALSE;
 +
 +        xmlbuf->ptr++;
 +        *end = TRUE;
 +        *error = FALSE;
 +        return FALSE;
 +    }
 +
 +    if (*xmlbuf->ptr == '>')
 +    {
 +        xmlbuf->ptr++;
 +        *error = FALSE;
 +        return FALSE;
 +    }
 +
 +    ptr = xmlbuf->ptr;
 +    while (ptr < xmlbuf->end && *ptr != '=' && *ptr != '>' && !isxmlspace(*ptr)) ptr++;
 +
 +    if (ptr == xmlbuf->end || *ptr != '=') return FALSE;
 +
 +    name->ptr = xmlbuf->ptr;
 +    name->len = ptr-xmlbuf->ptr;
 +    xmlbuf->ptr = ptr;
 +
 +    ptr++;
 +    if (ptr == xmlbuf->end || (*ptr != '"' && *ptr != '\'')) return FALSE;
 +
 +    value->ptr = ++ptr;
 +    if (ptr == xmlbuf->end) return FALSE;
 +
 +    ptr = memchrW(ptr, ptr[-1], xmlbuf->end - ptr);
 +    if (!ptr)
 +    {
 +        xmlbuf->ptr = xmlbuf->end;
 +        return FALSE;
 +    }
 +
 +    value->len = ptr - value->ptr;
 +    xmlbuf->ptr = ptr + 1;
 +
 +    if (xmlbuf->ptr == xmlbuf->end) return FALSE;
 +
 +    *error = FALSE;
 +    return TRUE;
 +}
 +
 +static BOOL next_xml_elem(xmlbuf_t* xmlbuf, xmlstr_t* elem)
 +{
 +    const WCHAR* ptr;
 +
 +    for (;;)
 +    {
 +        ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
 +        if (!ptr)
 +        {
 +            xmlbuf->ptr = xmlbuf->end;
 +            return FALSE;
 +        }
 +        ptr++;
 +        if (ptr + 3 < xmlbuf->end && ptr[0] == '!' && ptr[1] == '-' && ptr[2] == '-') /* skip comment */
 +        {
 +            for (ptr += 3; ptr + 3 <= xmlbuf->end; ptr++)
 +                if (ptr[0] == '-' && ptr[1] == '-' && ptr[2] == '>') break;
 +
 +            if (ptr + 3 > xmlbuf->end)
 +            {
 +                xmlbuf->ptr = xmlbuf->end;
 +                return FALSE;
 +            }
 +            xmlbuf->ptr = ptr + 3;
 +        }
 +        else break;
 +    }
 +
 +    xmlbuf->ptr = ptr;
 +    while (ptr < xmlbuf->end && !isxmlspace(*ptr) && *ptr != '>' && (*ptr != '/' || ptr == xmlbuf->ptr))
 +        ptr++;
 +
 +    elem->ptr = xmlbuf->ptr;
 +    elem->len = ptr - xmlbuf->ptr;
 +    xmlbuf->ptr = ptr;
 +    return xmlbuf->ptr != xmlbuf->end;
 +}
 +
 +static BOOL parse_xml_header(xmlbuf_t* xmlbuf)
 +{
 +    /* FIXME: parse attributes */
 +    const WCHAR *ptr;
 +
 +    for (ptr = xmlbuf->ptr; ptr < xmlbuf->end - 1; ptr++)
 +    {
 +        if (ptr[0] == '?' && ptr[1] == '>')
 +        {
 +            xmlbuf->ptr = ptr + 2;
 +            return TRUE;
 +        }
 +    }
 +    return FALSE;
 +}
 +
 +static BOOL parse_text_content(xmlbuf_t* xmlbuf, xmlstr_t* content)
 +{
 +    const WCHAR *ptr = memchrW(xmlbuf->ptr, '<', xmlbuf->end - xmlbuf->ptr);
 +
 +    if (!ptr) return FALSE;
 +
 +    content->ptr = xmlbuf->ptr;
 +    content->len = ptr - xmlbuf->ptr;
 +    xmlbuf->ptr = ptr;
 +
 +    return TRUE;
 +}
 +
 +static BOOL parse_version(const xmlstr_t *str, struct assembly_version *version)
 +{
 +    unsigned int ver[4];
 +    unsigned int pos;
 +    const WCHAR *curr;
 +    UNICODE_STRING strU;
 +
 +    /* major.minor.build.revision */
 +    ver[0] = ver[1] = ver[2] = ver[3] = pos = 0;
 +    for (curr = str->ptr; curr < str->ptr + str->len; curr++)
 +    {
 +        if (*curr >= '0' && *curr <= '9')
 +        {
 +            ver[pos] = ver[pos] * 10 + *curr - '0';
 +            if (ver[pos] >= 0x10000) goto error;
 +        }
 +        else if (*curr == '.')
 +        {
 +            if (++pos >= 4) goto error;
 +        }
 +        else goto error;
 +    }
 +    version->major = ver[0];
 +    version->minor = ver[1];
 +    version->build = ver[2];
 +    version->revision = ver[3];
 +    return TRUE;
 +
 +error:
 +    strU = xmlstr2unicode(str);
 +    DPRINT1( "Wrong version definition in manifest file (%wZ)\n", &strU );
 +    return FALSE;
 +}
 +
 +static BOOL parse_expect_elem(xmlbuf_t* xmlbuf, const WCHAR* name)
 +{
 +    xmlstr_t    elem;
 +    UNICODE_STRING elemU;
 +    if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
 +    if (xmlstr_cmp(&elem, name)) return TRUE;
 +    elemU = xmlstr2unicode(&elem);
 +    DPRINT1( "unexpected element %wZ\n", &elemU );
 +    return FALSE;
 +}
 +
 +static BOOL parse_expect_no_attr(xmlbuf_t* xmlbuf, BOOL* end)
 +{
 +    xmlstr_t    attr_name, attr_value;
 +    UNICODE_STRING attr_nameU, attr_valueU;
 +    BOOL        error;
 +
 +    while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, end))
 +    {
 +        attr_nameU = xmlstr2unicode(&attr_name);
 +        attr_valueU = xmlstr2unicode(&attr_name);
 +        DPRINT1( "unexpected attr %S=%S\n", &attr_nameU,
 +             &attr_valueU);
 +    }
 +    return !error;
 +}
 +
 +static BOOL parse_end_element(xmlbuf_t *xmlbuf)
 +{
 +    BOOL end = FALSE;
 +    return parse_expect_no_attr(xmlbuf, &end) && !end;
 +}
 +
 +static BOOL parse_expect_end_elem(xmlbuf_t *xmlbuf, const WCHAR *name)
 +{
 +    xmlstr_t    elem;
 +    UNICODE_STRING elemU;
 +    if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
 +    if (!xmlstr_cmp_end(&elem, name))
 +    {
 +        elemU = xmlstr2unicode(&elem);
 +        DPRINT1( "unexpected element %wZ\n", &elemU );
 +        return FALSE;
 +    }
 +    return parse_end_element(xmlbuf);
 +}
 +
 +static BOOL parse_unknown_elem(xmlbuf_t *xmlbuf, const xmlstr_t *unknown_elem)
 +{
 +    xmlstr_t attr_name, attr_value, elem;
 +    BOOL end = FALSE, error, ret = TRUE;
 +
 +    while(next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end));
 +    if(error || end) return end;
 +
 +    while(ret && (ret = next_xml_elem(xmlbuf, &elem)))
 +    {
 +        if(*elem.ptr == '/' && elem.len - 1 == unknown_elem->len &&
 +           !strncmpW(elem.ptr+1, unknown_elem->ptr, unknown_elem->len))
 +            break;
 +        else
 +            ret = parse_unknown_elem(xmlbuf, &elem);
 +    }
 +
 +    return ret && parse_end_element(xmlbuf);
 +}
 +
 +static BOOL parse_assembly_identity_elem(xmlbuf_t* xmlbuf, ACTIVATION_CONTEXT* actctx,
 +                                         struct assembly_identity* ai)
 +{
 +    xmlstr_t    attr_name, attr_value;
 +    BOOL        end = FALSE, error;
 +    UNICODE_STRING  attr_valueU, attr_nameU;
 +
 +    while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
 +    {
 +        if (xmlstr_cmp(&attr_name, nameW))
 +        {
 +            if (!(ai->name = xmlstrdupW(&attr_value))) return FALSE;
 +        }
 +        else if (xmlstr_cmp(&attr_name, typeW))
 +        {
 +            if (!(ai->type = xmlstrdupW(&attr_value))) return FALSE;
 +        }
 +        else if (xmlstr_cmp(&attr_name, versionW))
 +        {
 +            if (!parse_version(&attr_value, &ai->version)) return FALSE;
 +        }
 +        else if (xmlstr_cmp(&attr_name, processorArchitectureW))
 +        {
 +            if (!(ai->arch = xmlstrdupW(&attr_value))) return FALSE;
 +        }
 +        else if (xmlstr_cmp(&attr_name, publicKeyTokenW))
 +        {
 +            if (!(ai->public_key = xmlstrdupW(&attr_value))) return FALSE;
 +        }
 +        else if (xmlstr_cmp(&attr_name, languageW))
 +        {
 +            if (!(ai->language = xmlstrdupW(&attr_value))) return FALSE;
 +            DPRINT1("Unsupported yet language attribute (%S)\n",
 +                 ai->language);
 +        }
 +        else
 +        {
 +            attr_nameU = xmlstr2unicode(&attr_name);
 +            attr_valueU = xmlstr2unicode(&attr_value);
 +            DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
 +        }
 +    }
 +
 +    if (error || end) return end;
 +    return parse_expect_end_elem(xmlbuf, assemblyIdentityW);
 +}
 +
 +static BOOL parse_com_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
 +{
 +    xmlstr_t elem, attr_name, attr_value;
 +    BOOL ret, end = FALSE, error;
 +    struct entity*      entity;
 +    UNICODE_STRING  attr_valueU, attr_nameU;
 +
 +    if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION)))
 +        return FALSE;
 +
 +    while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
 +    {
 +        if (xmlstr_cmp(&attr_name, clsidW))
 +        {
 +            if (!(entity->u.comclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
 +        }
 +        else
 +        {
 +            attr_nameU = xmlstr2unicode(&attr_name);
 +            attr_valueU = xmlstr2unicode(&attr_value);
 +            DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
 +        }
 +    }
 +
 +    if (error || end) return end;
 +
 +    while ((ret = next_xml_elem(xmlbuf, &elem)))
 +    {
 +        if (xmlstr_cmp_end(&elem, comClassW))
 +        {
 +            ret = parse_end_element(xmlbuf);
 +            break;
 +        }
 +        else
 +        {
 +            attr_nameU = xmlstr2unicode(&elem);
 +            DPRINT1("unknown elem %wZ\n", &attr_nameU);
 +            ret = parse_unknown_elem(xmlbuf, &elem);
 +        }
 +    }
 +    return ret;
 +}
 +
 +static BOOL parse_cominterface_proxy_stub_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
 +{
 +    xmlstr_t    attr_name, attr_value;
 +    BOOL        end = FALSE, error;
 +    struct entity*      entity;
 +    UNICODE_STRING  attr_valueU, attr_nameU;
 +
 +    if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION)))
 +        return FALSE;
 +
 +    while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
 +    {
 +        if (xmlstr_cmp(&attr_name, iidW))
 +        {
 +            if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
 +        }
 +        if (xmlstr_cmp(&attr_name, nameW))
 +        {
 +            if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
 +        }
 +        else
 +        {
 +            attr_nameU = xmlstr2unicode(&attr_name);
 +            attr_valueU = xmlstr2unicode(&attr_value);
 +            DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
 +        }
 +    }
 +
 +    if (error || end) return end;
 +    return parse_expect_end_elem(xmlbuf, comInterfaceProxyStubW);
 +}
 +
 +static BOOL parse_typelib_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
 +{
 +    xmlstr_t    attr_name, attr_value;
 +    BOOL        end = FALSE, error;
 +    struct entity*      entity;
 +    UNICODE_STRING  attr_valueU, attr_nameU;
 +
 +    if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION)))
 +        return FALSE;
 +
 +    while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
 +    {
 +        if (xmlstr_cmp(&attr_name, tlbidW))
 +        {
 +            if (!(entity->u.typelib.tlbid = xmlstrdupW(&attr_value))) return FALSE;
 +        }
 +        if (xmlstr_cmp(&attr_name, versionW))
 +        {
 +            if (!(entity->u.typelib.version = xmlstrdupW(&attr_value))) return FALSE;
 +        }
 +        if (xmlstr_cmp(&attr_name, helpdirW))
 +        {
 +            if (!(entity->u.typelib.helpdir = xmlstrdupW(&attr_value))) return FALSE;
 +        }
 +        else
 +        {
 +            attr_nameU = xmlstr2unicode(&attr_name);
 +            attr_valueU = xmlstr2unicode(&attr_value);
 +            DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
 +        }
 +    }
 +
 +    if (error || end) return end;
 +    return parse_expect_end_elem(xmlbuf, typelibW);
 +}
 +
 +static BOOL parse_window_class_elem(xmlbuf_t* xmlbuf, struct dll_redirect* dll)
 +{
 +    xmlstr_t    elem, content;
 +    BOOL        end = FALSE, ret = TRUE;
 +    struct entity*      entity;
 +    UNICODE_STRING elemU;
 +
 +    if (!(entity = add_entity(&dll->entities, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)))
 +        return FALSE;
 +
 +    if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
 +    if (end) return FALSE;
 +
 +    if (!parse_text_content(xmlbuf, &content)) return FALSE;
 +
 +    if (!(entity->u.class.name = xmlstrdupW(&content))) return FALSE;
 +
 +    while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
 +    {
 +        if (xmlstr_cmp_end(&elem, windowClassW))
 +        {
 +            ret = parse_end_element(xmlbuf);
 +            break;
 +        }
 +        else
 +        {
 +            elemU = xmlstr2unicode(&elem);
 +            DPRINT1("unknown elem %wZ\n", &elemU);
 +            ret = parse_unknown_elem(xmlbuf, &elem);
 +        }
 +    }
 +
 +    return ret;
 +}
 +
 +static BOOL parse_binding_redirect_elem(xmlbuf_t* xmlbuf)
 +{
 +    xmlstr_t    attr_name, attr_value;
 +    UNICODE_STRING  attr_valueU, attr_nameU;
 +    BOOL        end = FALSE, error;
 +
 +    while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
 +    {
 +        attr_nameU = xmlstr2unicode(&attr_name);
 +        attr_valueU = xmlstr2unicode(&attr_value);
 +
 +        if (xmlstr_cmp(&attr_name, oldVersionW))
 +        {
 +            DPRINT1("Not stored yet oldVersion=%wZ\n", &attr_valueU);
 +        }
 +        else if (xmlstr_cmp(&attr_name, newVersionW))
 +        {
 +            DPRINT1("Not stored yet newVersion=%wZ\n", &attr_valueU);
 +        }
 +        else
 +        {
 +            DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
 +        }
 +    }
 +
 +    if (error || end) return end;
 +    return parse_expect_end_elem(xmlbuf, bindingRedirectW);
 +}
 +
 +static BOOL parse_description_elem(xmlbuf_t* xmlbuf)
 +{
 +    xmlstr_t    elem, content;
 +    UNICODE_STRING elemU;
 +    BOOL        end = FALSE, ret = TRUE;
 +
 +    if (!parse_expect_no_attr(xmlbuf, &end) || end ||
 +        !parse_text_content(xmlbuf, &content))
 +        return FALSE;
 +
 +    elemU = xmlstr2unicode(&content);
 +    DPRINT("Got description %wZ\n", &elemU);
 +
 +    while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
 +    {
 +        if (xmlstr_cmp_end(&elem, descriptionW))
 +        {
 +            ret = parse_end_element(xmlbuf);
 +            break;
 +        }
 +        else
 +        {
 +            elemU = xmlstr2unicode(&elem);
 +            DPRINT1("unknown elem %wZ\n", &elemU);
 +            ret = parse_unknown_elem(xmlbuf, &elem);
 +        }
 +    }
 +
 +    return ret;
 +}
 +
 +static BOOL parse_com_interface_external_proxy_stub_elem(xmlbuf_t* xmlbuf,
 +                                                         struct assembly* assembly)
 +{
 +    xmlstr_t            attr_name, attr_value;
 +    BOOL                end = FALSE, error;
 +    struct entity*      entity;
 +
 +    entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION);
 +    if (!entity) return FALSE;
 +
 +    while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
 +    {
 +        if (xmlstr_cmp(&attr_name, iidW))
 +        {
 +            if (!(entity->u.proxy.iid = xmlstrdupW(&attr_value))) return FALSE;
 +        }
 +        if (xmlstr_cmp(&attr_name, nameW))
 +        {
 +            if (!(entity->u.proxy.name = xmlstrdupW(&attr_value))) return FALSE;
 +        }
 +        else
 +        {
 +            DPRINT1("unknown attr %S=%S\n", attr_name.ptr, attr_value.ptr);
 +        }
 +    }
 +
 +    if (error || end) return end;
 +    return parse_expect_end_elem(xmlbuf, comInterfaceExternalProxyStubW);
 +}
 +
 +static BOOL parse_clr_class_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
 +{
 +    xmlstr_t    attr_name, attr_value;
 +    UNICODE_STRING attr_nameU, attr_valueU;
 +    BOOL        end = FALSE, error;
 +    struct entity*      entity;
 +
 +    entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION);
 +    if (!entity) return FALSE;
 +
 +    while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
 +    {
 +        if (xmlstr_cmp(&attr_name, nameW))
 +        {
 +            if (!(entity->u.clrclass.name = xmlstrdupW(&attr_value))) return FALSE;
 +        }
 +        else if (xmlstr_cmp(&attr_name, clsidW))
 +        {
 +            if (!(entity->u.clrclass.clsid = xmlstrdupW(&attr_value))) return FALSE;
 +        }
 +        else
 +        {
 +            attr_nameU = xmlstr2unicode(&attr_name);
 +            attr_valueU = xmlstr2unicode(&attr_value);
 +            DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
 +        }
 +    }
 +
 +    if (error || end) return end;
 +    return parse_expect_end_elem(xmlbuf, clrClassW);
 +}
 +
 +static BOOL parse_clr_surrogate_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
 +{
 +    xmlstr_t    attr_name, attr_value;
 +    UNICODE_STRING attr_nameU, attr_valueU;
 +    BOOL        end = FALSE, error;
 +    struct entity*      entity;
 +
 +    entity = add_entity(&assembly->entities, ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES);
 +    if (!entity) return FALSE;
 +
 +    while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
 +    {
 +        if (xmlstr_cmp(&attr_name, nameW))
 +        {
 +            if (!(entity->u.clrsurrogate.name = xmlstrdupW(&attr_value))) return FALSE;
 +        }
 +        else if (xmlstr_cmp(&attr_name, clsidW))
 +        {
 +            if (!(entity->u.clrsurrogate.clsid = xmlstrdupW(&attr_value))) return FALSE;
 +        }
 +        else
 +        {
 +            attr_nameU = xmlstr2unicode(&attr_name);
 +            attr_valueU = xmlstr2unicode(&attr_value);
 +            DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
 +        }
 +    }
 +
 +    if (error || end) return end;
 +    return parse_expect_end_elem(xmlbuf, clrSurrogateW);
 +}
 +
 +static BOOL parse_dependent_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl, BOOL optional)
 +{
 +    struct assembly_identity    ai;
 +    xmlstr_t                    elem;
 +    BOOL                        end = FALSE, ret = TRUE;
 +
 +    if (!parse_expect_no_attr(xmlbuf, &end) || end) return end;
 +
 +    memset(&ai, 0, sizeof(ai));
 +    ai.optional = optional;
 +
 +    if (!parse_expect_elem(xmlbuf, assemblyIdentityW) ||
 +        !parse_assembly_identity_elem(xmlbuf, acl->actctx, &ai))
 +        return FALSE;
 +
 +    /* store the newly found identity for later loading */
 +    if (!add_dependent_assembly_id(acl, &ai)) return FALSE;
 +
 +    while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
 +    {
 +        if (xmlstr_cmp_end(&elem, dependentAssemblyW))
 +        {
 +            ret = parse_end_element(xmlbuf);
 +            break;
 +        }
 +        else if (xmlstr_cmp(&elem, bindingRedirectW))
 +        {
 +            ret = parse_binding_redirect_elem(xmlbuf);
 +        }
 +        else
 +        {
 +            DPRINT1("unknown elem %S\n", elem.ptr);
 +            ret = parse_unknown_elem(xmlbuf, &elem);
 +        }
 +    }
 +
 +    return ret;
 +}
 +
 +static BOOL parse_dependency_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl)
 +{
 +    xmlstr_t attr_name, attr_value, elem;
 +    UNICODE_STRING attr_nameU, attr_valueU;
 +    BOOL end = FALSE, ret = TRUE, error, optional = FALSE;
 +
 +    while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
 +    {
 +        attr_nameU = xmlstr2unicode(&attr_name);
 +        attr_valueU = xmlstr2unicode(&attr_value);
 +
 +        if (xmlstr_cmp(&attr_name, optionalW))
 +        {
 +            static const WCHAR yesW[] = {'y','e','s',0};
 +            optional = xmlstr_cmpi( &attr_value, yesW );
 +            DPRINT1("optional=%wZ\n", &attr_valueU);
 +        }
 +        else
 +        {
 +            DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
 +        }
 +    }
 +
 +    while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
 +    {
 +        if (xmlstr_cmp_end(&elem, dependencyW))
 +        {
 +            ret = parse_end_element(xmlbuf);
 +            break;
 +        }
 +        else if (xmlstr_cmp(&elem, dependentAssemblyW))
 +        {
 +            ret = parse_dependent_assembly_elem(xmlbuf, acl, optional);
 +        }
 +        else
 +        {
 +            attr_nameU = xmlstr2unicode(&elem);
 +            DPRINT1("unknown element %wZ\n", &attr_nameU);
 +            ret = parse_unknown_elem(xmlbuf, &elem);
 +        }
 +    }
 +
 +    return ret;
 +}
 +
 +static BOOL parse_noinherit_elem(xmlbuf_t* xmlbuf)
 +{
 +    BOOL end = FALSE;
 +
 +    if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
 +    return end || parse_expect_end_elem(xmlbuf, noInheritW);
 +}
 +
 +static BOOL parse_noinheritable_elem(xmlbuf_t* xmlbuf)
 +{
 +    BOOL end = FALSE;
 +
 +    if (!parse_expect_no_attr(xmlbuf, &end)) return FALSE;
 +    return end || parse_expect_end_elem(xmlbuf, noInheritableW);
 +}
 +
 +static BOOL parse_file_elem(xmlbuf_t* xmlbuf, struct assembly* assembly)
 +{
 +    xmlstr_t    attr_name, attr_value, elem;
 +    UNICODE_STRING attr_nameU, attr_valueU;
 +    BOOL        end = FALSE, error, ret = TRUE;
 +    struct dll_redirect* dll;
 +
 +    if (!(dll = add_dll_redirect(assembly))) return FALSE;
 +
 +    while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
 +    {
 +        attr_nameU = xmlstr2unicode(&attr_name);
 +        attr_valueU = xmlstr2unicode(&attr_value);
 +
 +        if (xmlstr_cmp(&attr_name, nameW))
 +        {
 +            if (!(dll->name = xmlstrdupW(&attr_value))) return FALSE;
 +            DPRINT("name=%wZ\n", &attr_valueU);
 +        }
 +        else if (xmlstr_cmp(&attr_name, hashW))
 +        {
 +            if (!(dll->hash = xmlstrdupW(&attr_value))) return FALSE;
 +        }
 +        else if (xmlstr_cmp(&attr_name, hashalgW))
 +        {
 +            static const WCHAR sha1W[] = {'S','H','A','1',0};
 +            if (!xmlstr_cmpi(&attr_value, sha1W))
 +                DPRINT1("hashalg should be SHA1, got %wZ\n", &attr_valueU);
 +        }
 +        else
 +        {
 +            DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
 +        }
 +    }
 +
 +    if (error || !dll->name) return FALSE;
 +    if (end) return TRUE;
 +
 +    while (ret && (ret = next_xml_elem(xmlbuf, &elem)))
 +    {
 +        if (xmlstr_cmp_end(&elem, fileW))
 +        {
 +            ret = parse_end_element(xmlbuf);
 +            break;
 +        }
 +        else if (xmlstr_cmp(&elem, comClassW))
 +        {
 +            ret = parse_com_class_elem(xmlbuf, dll);
 +        }
 +        else if (xmlstr_cmp(&elem, comInterfaceProxyStubW))
 +        {
 +            ret = parse_cominterface_proxy_stub_elem(xmlbuf, dll);
 +        }
 +        else if (xmlstr_cmp(&elem, asmv2hashW))
 +        {
 +            DPRINT1("asmv2hash (undocumented) not supported\n");
 +            ret = parse_unknown_elem(xmlbuf, &elem);
 +        }
 +        else if (xmlstr_cmp(&elem, typelibW))
 +        {
 +            ret = parse_typelib_elem(xmlbuf, dll);
 +        }
 +        else if (xmlstr_cmp(&elem, windowClassW))
 +        {
 +            ret = parse_window_class_elem(xmlbuf, dll);
 +        }
 +        else
 +        {
 +            attr_nameU = xmlstr2unicode(&elem);
 +            DPRINT1("unknown elem %wZ\n", &attr_nameU);
 +            ret = parse_unknown_elem( xmlbuf, &elem );
 +        }
 +    }
 +
 +    return ret;
 +}
 +
 +static BOOL parse_assembly_elem(xmlbuf_t* xmlbuf, struct actctx_loader* acl,
 +                                struct assembly* assembly,
 +                                struct assembly_identity* expected_ai)
 +{
 +    xmlstr_t    attr_name, attr_value, elem;
 +    UNICODE_STRING attr_nameU, attr_valueU;
 +    BOOL        end = FALSE, error, version = FALSE, xmlns = FALSE, ret = TRUE;
 +
 +    while (next_xml_attr(xmlbuf, &attr_name, &attr_value, &error, &end))
 +    {
 +        attr_nameU = xmlstr2unicode(&attr_name);
 +        attr_valueU = xmlstr2unicode(&attr_value);
 +
 +        if (xmlstr_cmp(&attr_name, manifestVersionW))
 +        {
 +            static const WCHAR v10W[] = {'1','.','0',0};
 +            if (!xmlstr_cmp(&attr_value, v10W))
 +            {
 +                DPRINT1("wrong version %wZ\n", &attr_valueU);
 +                return FALSE;
 +            }
 +            version = TRUE;
 +        }
 +        else if (xmlstr_cmp(&attr_name, xmlnsW))
 +        {
 +            if (!xmlstr_cmp(&attr_value, manifestv1W) && !xmlstr_cmp(&attr_value, manifestv3W))
 +            {
 +                DPRINT1("wrong namespace %wZ\n", &attr_valueU);
 +                return FALSE;
 +            }
 +            xmlns = TRUE;
 +        }
 +        else
 +        {
 +            DPRINT1("unknown attr %wZ=%wZ\n", &attr_nameU, &attr_valueU);
 +        }
 +    }
 +
 +    if (error || end || !xmlns || !version) return FALSE;
 +    if (!next_xml_elem(xmlbuf, &elem)) return FALSE;
 +
 +    if (assembly->type == APPLICATION_MANIFEST && xmlstr_cmp(&elem, noInheritW))
 +    {
 +        if (!parse_noinherit_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
 +            return FALSE;
 +        assembly->no_inherit = TRUE;
 +    }
 +
 +    if (xmlstr_cmp(&elem, noInheritableW))
 +    {
 +        if (!parse_noinheritable_elem(xmlbuf) || !next_xml_elem(xmlbuf, &elem))
 +            return FALSE;
 +    }
 +    else if ((assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST) &&
 +             assembly->no_inherit)
 +        return FALSE;
 +
 +    while (ret)
 +    {
 +        if (xmlstr_cmp_end(&elem, assemblyW))
 +        {
 +            ret = parse_end_element(xmlbuf);
 +            break;
 +        }
 +        else if (xmlstr_cmp(&elem, descriptionW))
 +        {
 +            ret = parse_description_elem(xmlbuf);
 +        }
 +        else if (xmlstr_cmp(&elem, comInterfaceExternalProxyStubW))
 +        {
 +            ret = parse_com_interface_external_proxy_stub_elem(xmlbuf, assembly);
 +        }
 +        else if (xmlstr_cmp(&elem, dependencyW))
 +        {
 +            ret = parse_dependency_elem(xmlbuf, acl);
 +        }
 +        else if (xmlstr_cmp(&elem, fileW))
 +        {
 +            ret = parse_file_elem(xmlbuf, assembly);
 +        }
 +        else if (xmlstr_cmp(&elem, clrClassW))
 +        {
 +            ret = parse_clr_class_elem(xmlbuf, assembly);
 +        }
 +        else if (xmlstr_cmp(&elem, clrSurrogateW))
 +        {
 +            ret = parse_clr_surrogate_elem(xmlbuf, assembly);
 +        }
 +        else if (xmlstr_cmp(&elem, assemblyIdentityW))
 +        {
 +            if (!parse_assembly_identity_elem(xmlbuf, acl->actctx, &assembly->id)) return FALSE;
 +
 +            if (expected_ai)
 +            {
 +                /* FIXME: more tests */
 +                if (assembly->type == ASSEMBLY_MANIFEST &&
 +                    memcmp(&assembly->id.version, &expected_ai->version, sizeof(assembly->id.version)))
 +                {
 +                    DPRINT1("wrong version for assembly manifest: %u.%u.%u.%u / %u.%u.%u.%u\n",
 +                          expected_ai->version.major, expected_ai->version.minor,
 +                          expected_ai->version.build, expected_ai->version.revision,
 +                          assembly->id.version.major, assembly->id.version.minor,
 +                          assembly->id.version.build, assembly->id.version.revision);
 +                    ret = FALSE;
 +                }
 +                else if (assembly->type == ASSEMBLY_SHARED_MANIFEST &&
 +                         (assembly->id.version.major != expected_ai->version.major ||
 +                          assembly->id.version.minor != expected_ai->version.minor ||
 +                          assembly->id.version.build < expected_ai->version.build ||
 +                          (assembly->id.version.build == expected_ai->version.build &&
 +                           assembly->id.version.revision < expected_ai->version.revision)))
 +                {
 +                    DPRINT1("wrong version for shared assembly manifest\n");
 +                    ret = FALSE;
 +                }
 +            }
 +        }
 +        else
 +        {
 +            attr_nameU = xmlstr2unicode(&elem);
 +            DPRINT1("unknown element %wZ\n", &attr_nameU);
 +            ret = parse_unknown_elem(xmlbuf, &elem);
 +        }
 +        if (ret) ret = next_xml_elem(xmlbuf, &elem);
 +    }
 +
 +    return ret;
 +}
 +
 +static NTSTATUS parse_manifest_buffer( struct actctx_loader* acl, struct assembly *assembly,
 +                                       struct assembly_identity* ai, xmlbuf_t *xmlbuf )
 +{
 +    xmlstr_t elem;
 +    UNICODE_STRING elemU;
 +
 +    if (!next_xml_elem(xmlbuf, &elem)) return STATUS_SXS_CANT_GEN_ACTCTX;
 +
 +    if (xmlstr_cmp(&elem, xmlW) &&
 +        (!parse_xml_header(xmlbuf) || !next_xml_elem(xmlbuf, &elem)))
 +        return STATUS_SXS_CANT_GEN_ACTCTX;
 +
 +    if (!xmlstr_cmp(&elem, assemblyW))
 +    {
 +        elemU = xmlstr2unicode(&elem);
 +        DPRINT1("root element is %wZ, not <assembly>\n", &elemU);
 +        return STATUS_SXS_CANT_GEN_ACTCTX;
 +    }
 +
 +    if (!parse_assembly_elem(xmlbuf, acl, assembly, ai))
 +    {
 +        DPRINT1("failed to parse manifest %S\n", assembly->manifest.info );
 +        return STATUS_SXS_CANT_GEN_ACTCTX;
 +    }
 +
 +    if (next_xml_elem(xmlbuf, &elem))
 +    {
 +        elemU = xmlstr2unicode(&elem);
 +        DPRINT1("unexpected element %wZ\n", &elemU);
 +        return STATUS_SXS_CANT_GEN_ACTCTX;
 +    }
 +
 +    if (xmlbuf->ptr != xmlbuf->end)
 +    {
 +        DPRINT1("parse error\n");
 +        return STATUS_SXS_CANT_GEN_ACTCTX;
 +    }
 +    return STATUS_SUCCESS;
 +}
 +
 +static NTSTATUS parse_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
 +                                LPCWSTR filename, LPCWSTR directory, BOOL shared,
 +                                const void *buffer, SIZE_T size )
 +{
 +    xmlbuf_t xmlbuf;
 +    NTSTATUS status;
 +    struct assembly *assembly;
 +    int unicode_tests;
 +
 +    DPRINT( "parsing manifest loaded from %S base dir %S\n", filename, directory );
 +
 +    if (!(assembly = add_assembly(acl->actctx, shared ? ASSEMBLY_SHARED_MANIFEST : ASSEMBLY_MANIFEST)))
 +        return STATUS_SXS_CANT_GEN_ACTCTX;
 +
 +    if (directory && !(assembly->directory = strdupW(directory)))
 +        return STATUS_NO_MEMORY;
 +
 +    if (filename) assembly->manifest.info = strdupW( filename + 4 /* skip \??\ prefix */ );
 +    assembly->manifest.type = assembly->manifest.info ? ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE
 +                                                      : ACTIVATION_CONTEXT_PATH_TYPE_NONE;
 +
 +    unicode_tests = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
 +    if (RtlIsTextUnicode( (PVOID) buffer, size, &unicode_tests ))
 +    {
 +        xmlbuf.ptr = buffer;
 +        xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
 +        status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
 +    }
 +    else if (unicode_tests & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
 +    {
 +        const WCHAR *buf = buffer;
 +        WCHAR *new_buff;
 +        unsigned int i;
 +
 +        if (!(new_buff = RtlAllocateHeap( RtlGetProcessHeap(), 0, size )))
 +            return STATUS_NO_MEMORY;
 +        for (i = 0; i < size / sizeof(WCHAR); i++)
 +            new_buff[i] = RtlUshortByteSwap( buf[i] );
 +        xmlbuf.ptr = new_buff;
 +        xmlbuf.end = xmlbuf.ptr + size / sizeof(WCHAR);
 +        status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
 +        RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff );
 +    }
 +    else
 +    {
 +        /* let's assume utf-8 for now */
 +        int len;
 +        WCHAR *new_buff;
 +
 +        _SEH2_TRY
 +        {
 +            len = mbstowcs( NULL, buffer, size);
 +        }
 +        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +        {
 +            DPRINT1("Exception accessing buffer\n");
 +            return STATUS_SXS_CANT_GEN_ACTCTX;
 +        }
 +        _SEH2_END;
 +
 +        DPRINT("len = %x\n", len);
 +
 +        if (len == -1)
 +        {
 +            DPRINT1( "utf-8 conversion failed\n" );
 +            return STATUS_SXS_CANT_GEN_ACTCTX;
 +        }
 +        if (!(new_buff = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, len)))
 +            return STATUS_NO_MEMORY;
 +
 +        mbstowcs( new_buff, buffer, size);
 +        xmlbuf.ptr = new_buff;
 +
 +        xmlbuf.end = xmlbuf.ptr + len / sizeof(WCHAR);
 +        status = parse_manifest_buffer( acl, assembly, ai, &xmlbuf );
 +
 +        RtlFreeHeap( RtlGetProcessHeap(), 0, new_buff );
 +    }
 +    return status;
 +}
 +
 +static NTSTATUS open_nt_file( HANDLE *handle, UNICODE_STRING *name )
 +{
 +    OBJECT_ATTRIBUTES attr;
 +    IO_STATUS_BLOCK io;
 +
 +    attr.Length = sizeof(attr);
 +    attr.RootDirectory = 0;
 +    attr.Attributes = OBJ_CASE_INSENSITIVE;
 +    attr.ObjectName = name;
 +    attr.SecurityDescriptor = NULL;
 +    attr.SecurityQualityOfService = NULL;
 +    return NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT );
 +}
 +
 +static NTSTATUS get_module_filename( HMODULE module, UNICODE_STRING *str, unsigned int extra_len )
 +{
 +    NTSTATUS status;
 +    ULONG magic;
 +    LDR_DATA_TABLE_ENTRY *pldr;
 +
 +    LdrLockLoaderLock(0, NULL, &magic);
 +    status = LdrFindEntryForAddress( module, &pldr );
 +    if (status == STATUS_SUCCESS)
 +    {
 +        if ((str->Buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
 +                                            pldr->FullDllName.Length + extra_len + sizeof(WCHAR) )))
 +        {
 +            memcpy( str->Buffer, pldr->FullDllName.Buffer, pldr->FullDllName.Length + sizeof(WCHAR) );
 +            str->Length = pldr->FullDllName.Length;
 +            str->MaximumLength = pldr->FullDllName.Length + extra_len + sizeof(WCHAR);
 +        }
 +        else status = STATUS_NO_MEMORY;
 +    }
 +    LdrUnlockLoaderLock(0, magic);
 +    return status;
 +}
 +
 +static NTSTATUS get_manifest_in_module( struct actctx_loader* acl, struct assembly_identity* ai,
 +                                        LPCWSTR filename, LPCWSTR directory, BOOL shared,
 +                                        HANDLE hModule, LPCWSTR resname, ULONG lang )
 +{
 +    NTSTATUS status;
 +    UNICODE_STRING nameW;
 +    LDR_RESOURCE_INFO info;
 +    IMAGE_RESOURCE_DATA_ENTRY* entry = NULL;
 +    void *ptr;
 +
 +#if 0
 +    if (TRACE_ON(actctx))
 +    {
 +        if (!filename && !get_module_filename( hModule, &nameW, 0 ))
 +        {
 +            DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
 +                   hModule, debugstr_w(nameW.Buffer) );
 +            RtlFreeUnicodeString( &nameW );
 +        }
 +        else DPRINT( "looking for res %s in module %p %s\n", debugstr_w(resname),
 +                    hModule, debugstr_w(filename) );
 +    }
 +#endif
 +
 +    if (!resname) return STATUS_INVALID_PARAMETER;
 +
 +    info.Type = (ULONG_PTR)RT_MANIFEST;
 +    info.Language = lang;
 +    if (!((ULONG_PTR)resname >> 16))
 +    {
 +        info.Name = (ULONG_PTR)resname;
 +        status = LdrFindResource_U(hModule, &info, 3, &entry);
 +    }
 +    else if (resname[0] == '#')
 +    {
 +        ULONG value;
 +        RtlInitUnicodeString(&nameW, resname + 1);
 +        if (RtlUnicodeStringToInteger(&nameW, 10, &value) != STATUS_SUCCESS || HIWORD(value))
 +            return STATUS_INVALID_PARAMETER;
 +        info.Name = value;
 +        status = LdrFindResource_U(hModule, &info, 3, &entry);
 +    }
 +    else
 +    {
 +        RtlCreateUnicodeString(&nameW, resname);
 +        RtlUpcaseUnicodeString(&nameW, &nameW, FALSE);
 +        info.Name = (ULONG_PTR)nameW.Buffer;
 +        status = LdrFindResource_U(hModule, &info, 3, &entry);
 +        RtlFreeUnicodeString(&nameW);
 +    }
 +    if (status == STATUS_SUCCESS) status = LdrAccessResource(hModule, entry, &ptr, NULL);
 +
 +    if (status == STATUS_SUCCESS)
 +        status = parse_manifest(acl, ai, filename, directory, shared, ptr, entry->Size);
 +
 +    return status;
 +}
 +
 +static NTSTATUS get_manifest_in_pe_file( struct actctx_loader* acl, struct assembly_identity* ai,
 +                                         LPCWSTR filename, LPCWSTR directory, BOOL shared,
 +                                         HANDLE file, LPCWSTR resname, ULONG lang )
 +{
 +    HANDLE              mapping;
 +    OBJECT_ATTRIBUTES   attr;
 +    LARGE_INTEGER       size;
 +    LARGE_INTEGER       offset;
 +    NTSTATUS            status;
 +    SIZE_T              count;
 +    void               *base;
 +
 +    DPRINT( "looking for res %S in %S\n", resname, filename );
 +
 +    attr.Length                   = sizeof(attr);
 +    attr.RootDirectory            = 0;
 +    attr.ObjectName               = NULL;
 +    attr.Attributes               = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
 +    attr.SecurityDescriptor       = NULL;
 +    attr.SecurityQualityOfService = NULL;
 +
 +    size.QuadPart = 0;
 +    status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
 +                              &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
 +    if (status != STATUS_SUCCESS) return status;
 +
 +    offset.QuadPart = 0;
 +    count = 0;
 +    base = NULL;
 +    status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset,
 +                                 &count, ViewShare, 0, PAGE_READONLY );
 +    NtClose( mapping );
 +    if (status != STATUS_SUCCESS) return status;
 +
 +    if (RtlImageNtHeader(base)) /* we got a PE file */
 +    {
 +        HANDLE module = (HMODULE)((ULONG_PTR)base | 1);  /* make it a LOAD_LIBRARY_AS_DATAFILE handle */
 +        status = get_manifest_in_module( acl, ai, filename, directory, shared, module, resname, lang );
 +    }
 +    else status = STATUS_INVALID_IMAGE_FORMAT;
 +
 +    NtUnmapViewOfSection( NtCurrentProcess(), base );
 +    return status;
 +}
 +
 +static NTSTATUS get_manifest_in_manifest_file( struct actctx_loader* acl, struct assembly_identity* ai,
 +                                               LPCWSTR filename, LPCWSTR directory, BOOL shared, HANDLE file )
 +{
 +    FILE_STANDARD_INFORMATION info;
 +    IO_STATUS_BLOCK io;
 +    HANDLE              mapping;
 +    OBJECT_ATTRIBUTES   attr;
 +    LARGE_INTEGER       size;
 +    LARGE_INTEGER       offset;
 +    NTSTATUS            status;
 +    SIZE_T              count;
 +    void               *base;
 +
 +    DPRINT( "loading manifest file %S\n", filename );
 +
 +    attr.Length                   = sizeof(attr);
 +    attr.RootDirectory            = 0;
 +    attr.ObjectName               = NULL;
 +    attr.Attributes               = OBJ_CASE_INSENSITIVE | OBJ_OPENIF;
 +    attr.SecurityDescriptor       = NULL;
 +    attr.SecurityQualityOfService = NULL;
 +
 +    size.QuadPart = 0;
 +    status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
 +                              &attr, &size, PAGE_READONLY, SEC_COMMIT, file );
 +
 +    if (status != STATUS_SUCCESS) return status;
 +
 +    offset.QuadPart = 0;
 +    count = 0;
 +    base = NULL;
 +    status = NtMapViewOfSection( mapping, NtCurrentProcess(), &base, 0, 0, &offset,
 +                                 &count, ViewShare, 0, PAGE_READONLY );
 +
 +    if (status != STATUS_SUCCESS) return status;
 +
 +    /* Fixme: WINE uses FileEndOfFileInformation with NtQueryInformationFile. */
 +    status = NtQueryInformationFile( file, &io, &info, sizeof(info), FileStandardInformation);
 +
 +    if (status == STATUS_SUCCESS)
 +        status = parse_manifest(acl, ai, filename, directory, shared, base, info.EndOfFile.QuadPart);
 +
 +    NtUnmapViewOfSection( NtCurrentProcess(), base );
 +    NtClose( mapping );
 +    return status;
 +}
 +
 +/* try to load the .manifest file associated to the file */
 +static NTSTATUS get_manifest_in_associated_manifest( struct actctx_loader* acl, struct assembly_identity* ai,
 +                                                     LPCWSTR filename, LPCWSTR directory, HMODULE module, LPCWSTR resname )
 +{
 +    static const WCHAR fmtW[] = { '.','%','l','u',0 };
 +    WCHAR *buffer;
 +    NTSTATUS status;
 +    UNICODE_STRING nameW;
 +    HANDLE file;
 +    ULONG_PTR resid = (ULONG_PTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
 +
 +    if (!((ULONG_PTR)resname >> 16)) resid = (ULONG_PTR)resname & 0xffff;
 +
 +    DPRINT( "looking for manifest associated with %S id %lu\n", filename, resid );
 +
 +    if (module) /* use the module filename */
 +    {
 +        UNICODE_STRING name;
 +
 +        if (!(status = get_module_filename( module, &name, sizeof(dotManifestW) + 10*sizeof(WCHAR) )))
 +        {
 +            if (resid != 1) sprintfW( name.Buffer + strlenW(name.Buffer), fmtW, resid );
 +            strcatW( name.Buffer, dotManifestW );
 +            if (!RtlDosPathNameToNtPathName_U( name.Buffer, &nameW, NULL, NULL ))
 +                status = STATUS_RESOURCE_DATA_NOT_FOUND;
 +            RtlFreeUnicodeString( &name );
 +        }
 +        if (status) return status;
 +    }
 +    else
 +    {
 +        if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
 +                                        (strlenW(filename) + 10) * sizeof(WCHAR) + sizeof(dotManifestW) )))
 +            return STATUS_NO_MEMORY;
 +        strcpyW( buffer, filename );
 +        if (resid != 1) sprintfW( buffer + strlenW(buffer), fmtW, resid );
 +        strcatW( buffer, dotManifestW );
 +        RtlInitUnicodeString( &nameW, buffer );
 +    }
 +
 +    if (!open_nt_file( &file, &nameW ))
 +    {
 +        status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
 +        NtClose( file );
 +    }
 +    else status = STATUS_RESOURCE_DATA_NOT_FOUND;
 +    RtlFreeUnicodeString( &nameW );
 +    return status;
 +}
 +
 +static WCHAR *lookup_manifest_file( HANDLE dir, struct assembly_identity *ai )
 +{
 +    static const WCHAR lookup_fmtW[] =
 +        {'%','s','_','%','s','_','%','s','_','%','u','.','%','u','.','*','.','*','_',
 +         '*', /* FIXME */
 +         '.','m','a','n','i','f','e','s','t',0};
 +
 +    WCHAR *lookup, *ret = NULL;
 +    UNICODE_STRING lookup_us;
 +    IO_STATUS_BLOCK io;
 +    unsigned int data_pos = 0, data_len;
 +    char buffer[8192];
 +
 +    if (!(lookup = RtlAllocateHeap( RtlGetProcessHeap(), 0,
 +                                    (strlenW(ai->arch) + strlenW(ai->name)
 +                                     + strlenW(ai->public_key) + 20) * sizeof(WCHAR)
 +                                    + sizeof(lookup_fmtW) )))
 +        return NULL;
 +
 +    sprintfW( lookup, lookup_fmtW, ai->arch, ai->name, ai->public_key, ai->version.major, ai->version.minor);
 +    RtlInitUnicodeString( &lookup_us, lookup );
 +
 +    NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
 +                          FileBothDirectoryInformation, FALSE, &lookup_us, TRUE );
 +    if (io.Status == STATUS_SUCCESS)
 +    {
 +        FILE_BOTH_DIR_INFORMATION *dir_info;
 +        WCHAR *tmp;
 +        ULONG build, revision;
 +
 +        data_len = io.Information;
 +
 +        for (;;)
 +        {
 +            if (data_pos >= data_len)
 +            {
 +                NtQueryDirectoryFile( dir, 0, NULL, NULL, &io, buffer, sizeof(buffer),
 +                                      FileBothDirectoryInformation, FALSE, &lookup_us, FALSE );
 +                if (io.Status != STATUS_SUCCESS) break;
 +                data_len = io.Information;
 +                data_pos = 0;
 +            }
 +            dir_info = (FILE_BOTH_DIR_INFORMATION*)(buffer + data_pos);
 +
 +            if (dir_info->NextEntryOffset) data_pos += dir_info->NextEntryOffset;
 +            else data_pos = data_len;
 +
 +            tmp = (WCHAR *)dir_info->FileName + (strchrW(lookup, '*') - lookup);
 +            build = atoiW(tmp);
 +            if (build < ai->version.build) continue;
 +            tmp = strchrW(tmp, '.') + 1;
 +            revision = atoiW(tmp);
 +            if (build == ai->version.build && revision < ai->version.revision)
 +                continue;
 +            ai->version.build = build;
 +            ai->version.revision = revision;
 +
 +            if ((ret = RtlAllocateHeap( RtlGetProcessHeap(), 0, dir_info->FileNameLength * sizeof(WCHAR) )))
 +            {
 +                memcpy( ret, dir_info->FileName, dir_info->FileNameLength );
 +                ret[dir_info->FileNameLength/sizeof(WCHAR)] = 0;
 +            }
 +            break;
 +        }
 +    }
 +    else DPRINT1("no matching file for %S\n", lookup);
 +    RtlFreeHeap( RtlGetProcessHeap(), 0, lookup );
 +    return ret;
 +}
 +
 +static NTSTATUS lookup_winsxs(struct actctx_loader* acl, struct assembly_identity* ai)
 +{
 +    struct assembly_identity    sxs_ai;
 +    UNICODE_STRING              path_us;
 +    OBJECT_ATTRIBUTES           attr;
 +    IO_STATUS_BLOCK             io;
 +    WCHAR *path, *file = NULL;
 +    HANDLE handle;
 +
 +    static const WCHAR manifest_dirW[] =
 +        {'\\','w','i','n','s','x','s','\\','m','a','n','i','f','e','s','t','s',0};
 +
 +    if (!ai->arch || !ai->name || !ai->public_key) return STATUS_NO_SUCH_FILE;
 +
 +    if (!(path = RtlAllocateHeap( RtlGetProcessHeap(), 0, 
 +                                  ((strlenW(SharedUserData->NtSystemRoot) + 1) *sizeof(WCHAR)) + sizeof(manifest_dirW) )))
 +        return STATUS_NO_MEMORY;
 +
 +    memcpy( path, SharedUserData->NtSystemRoot, strlenW(SharedUserData->NtSystemRoot) * sizeof(WCHAR) );
 +    memcpy( path + strlenW(SharedUserData->NtSystemRoot), manifest_dirW, sizeof(manifest_dirW) );
 +
 +    if (!RtlDosPathNameToNtPathName_U( path, &path_us, NULL, NULL ))
 +    {
 +        RtlFreeHeap( RtlGetProcessHeap(), 0, path );
 +        return STATUS_NO_SUCH_FILE;
 +    }
 +    RtlFreeHeap( RtlGetProcessHeap(), 0, path );
 +
 +    attr.Length = sizeof(attr);
 +    attr.RootDirectory = 0;
 +    attr.Attributes = OBJ_CASE_INSENSITIVE;
 +    attr.ObjectName = &path_us;
 +    attr.SecurityDescriptor = NULL;
 +    attr.SecurityQualityOfService = NULL;
 +
 +    if (!NtOpenFile( &handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ | FILE_SHARE_WRITE,
 +                     FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ))
 +    {
 +        sxs_ai = *ai;
 +        file = lookup_manifest_file( handle, &sxs_ai );
 +        NtClose( handle );
 +    }
 +    if (!file)
 +    {
 +        RtlFreeUnicodeString( &path_us );
 +        return STATUS_NO_SUCH_FILE;
 +    }
 +
 +    /* append file name to directory path */
 +    if (!(path = RtlReAllocateHeap( RtlGetProcessHeap(), 0, path_us.Buffer,
 +                                    path_us.Length + (strlenW(file) + 2) * sizeof(WCHAR) )))
 +    {
 +        RtlFreeHeap( RtlGetProcessHeap(), 0, file );
 +        RtlFreeUnicodeString( &path_us );
 +        return STATUS_NO_MEMORY;
 +    }
 +
 +    path[path_us.Length/sizeof(WCHAR)] = '\\';
 +    strcpyW( path + path_us.Length/sizeof(WCHAR) + 1, file );
 +    RtlInitUnicodeString( &path_us, path );
 +    *strrchrW(file, '.') = 0;  /* remove .manifest extension */
 +
 +    if (!open_nt_file( &handle, &path_us ))
 +    {
 +        io.Status = get_manifest_in_manifest_file(acl, &sxs_ai, path_us.Buffer, file, TRUE, handle);
 +        NtClose( handle );
 +    }
 +    else io.Status = STATUS_NO_SUCH_FILE;
 +
 +    RtlFreeHeap( RtlGetProcessHeap(), 0, file );
 +    RtlFreeUnicodeString( &path_us );
 +    return io.Status;
 +}
 +
 +static NTSTATUS lookup_assembly(struct actctx_loader* acl,
 +                                struct assembly_identity* ai)
 +{
 +    static const WCHAR dotDllW[] = {'.','d','l','l',0};
 +    unsigned int i;
 +    WCHAR *buffer, *p, *directory;
 +    NTSTATUS status;
 +    UNICODE_STRING nameW;
 +    HANDLE file;
 +
 +    DPRINT1( "looking for name=%S version=%u.%u.%u.%u arch=%S\n",
 +           ai->name, ai->version.major, ai->version.minor, ai->version.build, ai->version.revision, ai->arch );
 +
 +    if ((status = lookup_winsxs(acl, ai)) != STATUS_NO_SUCH_FILE) return status;
 +
 +    /* FIXME: add support for language specific lookup */
 +
 +    nameW.Buffer = NULL;
 +    if (!(buffer = RtlAllocateHeap( RtlGetProcessHeap(), 0,
 +                                    (strlenW(acl->actctx->appdir.info) + 2 * strlenW(ai->name) + 2) * sizeof(WCHAR) + sizeof(dotManifestW) )))
 +        return STATUS_NO_MEMORY;
 +
 +    if (!(directory = build_assembly_dir( ai )))
 +    {
 +        RtlFreeHeap( RtlGetProcessHeap(), 0, buffer );
 +        return STATUS_NO_MEMORY;
 +    }
 +
 +    /* lookup in appdir\name.dll
 +     *           appdir\name.manifest
 +     *           appdir\name\name.dll
 +     *           appdir\name\name.manifest
 +     */
 +    strcpyW( buffer, acl->actctx->appdir.info );
 +    p = buffer + strlenW(buffer);
 +    for (i = 0; i < 2; i++)
 +    {
 +        *p++ = '\\';
 +        strcpyW( p, ai->name );
 +        p += strlenW(p);
 +
 +        strcpyW( p, dotDllW );
 +        if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
 +        {
 +            status = open_nt_file( &file, &nameW );
 +            if (!status)
 +            {
 +                status = get_manifest_in_pe_file( acl, ai, nameW.Buffer, directory, FALSE, file,
 +                                                  (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID, 0 );
 +                NtClose( file );
 +                break;
 +            }
 +            RtlFreeUnicodeString( &nameW );
 +        }
 +
 +        strcpyW( p, dotManifestW );
 +        if (RtlDosPathNameToNtPathName_U( buffer, &nameW, NULL, NULL ))
 +        {
 +            status = open_nt_file( &file, &nameW );
 +            if (!status)
 +            {
 +                status = get_manifest_in_manifest_file( acl, ai, nameW.Buffer, directory, FALSE, file );
 +                NtClose( file );
 +                break;
 +            }
 +            RtlFreeUnicodeString( &nameW );
 +        }
 +        status = STATUS_SXS_ASSEMBLY_NOT_FOUND;
 +    }
 +    RtlFreeUnicodeString( &nameW );
 +    RtlFreeHeap( RtlGetProcessHeap(), 0, directory );
 +    RtlFreeHeap( RtlGetProcessHeap(), 0, buffer );
 +    return status;
 +}
 +
 +static NTSTATUS parse_depend_manifests(struct actctx_loader* acl)
 +{
 +    NTSTATUS status = STATUS_SUCCESS;
 +    unsigned int i;
 +
 +    for (i = 0; i < acl->num_dependencies; i++)
 +    {
 +        if (lookup_assembly(acl, &acl->dependencies[i]) != STATUS_SUCCESS)
 +        {
 +            if (!acl->dependencies[i].optional)
 +            {
 +                DPRINT1( "Could not find dependent assembly %S\n", acl->dependencies[i].name );
 +                status = STATUS_SXS_CANT_GEN_ACTCTX;
 +                break;
 +            }
 +        }
 +    }
 +    /* FIXME should now iterate through all refs */
 +    return status;
 +}
 +
 +/* find the appropriate activation context for RtlQueryInformationActivationContext */
 +static NTSTATUS find_query_actctx( HANDLE *handle, DWORD flags, ULONG class )
 +{
 +    NTSTATUS status = STATUS_SUCCESS;
 +
 +    if (flags & QUERY_ACTCTX_FLAG_USE_ACTIVE_ACTCTX)
 +    {
 +        if (*handle) return STATUS_INVALID_PARAMETER;
 +
 +        if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
 +            *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext;
 +    }
 +    else if (flags & (QUERY_ACTCTX_FLAG_ACTCTX_IS_ADDRESS|QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE))
 +    {
 +        ULONG magic;
 +        LDR_DATA_TABLE_ENTRY *pldr;
 +
 +        if (!*handle) return STATUS_INVALID_PARAMETER;
 +
 +        LdrLockLoaderLock( 0, NULL, &magic );
 +        if (!LdrFindEntryForAddress( *handle, &pldr ))
 +        {
 +            if ((flags & QUERY_ACTCTX_FLAG_ACTCTX_IS_HMODULE) && *handle != pldr->DllBase)
 +                status = STATUS_DLL_NOT_FOUND;
 +            else
 +                *handle = pldr->EntryPointActivationContext;
 +        }
 +        else status = STATUS_DLL_NOT_FOUND;
 +        LdrUnlockLoaderLock( 0, magic );
 +    }
 +    else if (!*handle && (class != ActivationContextBasicInformation))
 +        *handle = process_actctx;
 +
 +    return status;
 +}
 +
 +static NTSTATUS fill_keyed_data(PACTCTX_SECTION_KEYED_DATA data, PVOID v1, PVOID v2, unsigned int i)
 +{
 +    data->ulDataFormatVersion = 1;
 +    data->lpData = v1;
 +    data->ulLength = 20; /* FIXME */
 +    data->lpSectionGlobalData = NULL; /* FIXME */
 +    data->ulSectionGlobalDataLength = 0; /* FIXME */
 +    data->lpSectionBase = v2;
 +    data->ulSectionTotalLength = 0; /* FIXME */
 +    data->hActCtx = NULL;
 +    if (data->cbSize >= offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) + sizeof(ULONG))
 +        data->ulAssemblyRosterIndex = i + 1;
 +
 +    return STATUS_SUCCESS;
 +}
 +
 +static NTSTATUS find_dll_redirection(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name,
 +                                     PACTCTX_SECTION_KEYED_DATA data)
 +{
 +    unsigned int i, j, snlen = section_name->Length / sizeof(WCHAR);
 +
 +    for (i = 0; i < actctx->num_assemblies; i++)
 +    {
 +        struct assembly *assembly = &actctx->assemblies[i];
 +        for (j = 0; j < assembly->num_dlls; j++)
 +        {
 +            struct dll_redirect *dll = &assembly->dlls[j];
 +            if (!strncmpiW(section_name->Buffer, dll->name, snlen) && !dll->name[snlen])
 +                return fill_keyed_data(data, dll, assembly, i);
 +        }
 +    }
 +    return STATUS_SXS_KEY_NOT_FOUND;
 +}
 +
 +static NTSTATUS find_window_class(ACTIVATION_CONTEXT* actctx, const UNICODE_STRING *section_name,
 +                                  PACTCTX_SECTION_KEYED_DATA data)
 +{
 +    unsigned int i, j, k, snlen = section_name->Length / sizeof(WCHAR);
 +
 +    for (i = 0; i < actctx->num_assemblies; i++)
 +    {
 +        struct assembly *assembly = &actctx->assemblies[i];
 +        for (j = 0; j < assembly->num_dlls; j++)
 +        {
 +            struct dll_redirect *dll = &assembly->dlls[j];
 +            for (k = 0; k < dll->entities.num; k++)
 +            {
 +                struct entity *entity = &dll->entities.base[k];
 +                if (entity->kind == ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION)
 +                {
 +                    if (!strncmpiW(section_name->Buffer, entity->u.class.name, snlen) && !entity->u.class.name[snlen])
 +                        return fill_keyed_data(data, entity, dll, i);
 +                }
 +            }
 +        }
 +    }
 +    return STATUS_SXS_KEY_NOT_FOUND;
 +}
 +
 +static NTSTATUS find_string(ACTIVATION_CONTEXT* actctx, ULONG section_kind,
 +                            const UNICODE_STRING *section_name,
 +                            DWORD flags, PACTCTX_SECTION_KEYED_DATA data)
 +{
 +    NTSTATUS status;
 +
 +    switch (section_kind)
 +    {
 +    case ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION:
 +        status = find_dll_redirection(actctx, section_name, data);
 +        break;
 +    case ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION:
 +        status = find_window_class(actctx, section_name, data);
 +        break;
 +    case ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION:
 +    case ACTIVATION_CONTEXT_SECTION_COM_INTERFACE_REDIRECTION:
 +    case ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION:
 +    case ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION:
 +    case ACTIVATION_CONTEXT_SECTION_GLOBAL_OBJECT_RENAME_TABLE:
 +    case ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES:
 +        DPRINT1("Unsupported yet section_kind %x\n", section_kind);
 +        return STATUS_SXS_SECTION_NOT_FOUND;
 +    default:
 +        DPRINT1("Unknown section_kind %x\n", section_kind);
 +        return STATUS_SXS_SECTION_NOT_FOUND;
 +    }
 +
 +    if (status != STATUS_SUCCESS) return status;
 +
 +    if (flags & FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
 +    {
 +        actctx_addref(actctx);
 +        data->hActCtx = actctx;
 +    }
 +    return STATUS_SUCCESS;
 +}
 +
 +/* initialize the activation context for the current process */
 +void actctx_init(void)
 +{
 +    ACTCTXW ctx;
 +    HANDLE handle;
 +
 +    ctx.cbSize   = sizeof(ctx);
 +    ctx.lpSource = NULL;
 +    ctx.dwFlags  = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
 +    ctx.hModule  = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress;
 +    ctx.lpResourceName = (LPCWSTR)CREATEPROCESS_MANIFEST_RESOURCE_ID;
 +
 +    if (!RtlCreateActivationContext( &handle, &ctx )) process_actctx = check_actctx(handle);
 +}
 +
 +/* FUNCTIONS ***************************************************************/
 +
 +NTSTATUS WINAPI RtlCreateActivationContext( HANDLE *handle,  void *ptr )
 +{
 +    const ACTCTXW *pActCtx = ptr;
 +    const WCHAR *directory = NULL;
 +    ACTIVATION_CONTEXT *actctx;
 +    UNICODE_STRING nameW;
 +    ULONG lang = 0;
 +    NTSTATUS status = STATUS_NO_MEMORY;
 +    HANDLE file = 0;
 +    struct actctx_loader acl;
 +
 +    DPRINT("%p %08x\n", pActCtx, pActCtx ? pActCtx->dwFlags : 0);
 +
 +    if (!pActCtx || pActCtx->cbSize < sizeof(*pActCtx) ||
 +        (pActCtx->dwFlags & ~ACTCTX_FLAGS_ALL))
 +        return STATUS_INVALID_PARAMETER;
 +
 +
 +    if (!(actctx = RtlAllocateHeap( RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*actctx) )))
 +        return STATUS_NO_MEMORY;
 +
 +    actctx->magic = ACTCTX_MAGIC;
 +    actctx->ref_count = 1;
 +    actctx->config.type = ACTIVATION_CONTEXT_PATH_TYPE_NONE;
 +    actctx->config.info = NULL;
 +    actctx->appdir.type = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
 +    if (pActCtx->dwFlags & ACTCTX_FLAG_APPLICATION_NAME_VALID)
 +    {
 +        if (!(actctx->appdir.info = strdupW( pActCtx->lpApplicationName ))) goto error;
 +    }
 +    else
 +    {
 +        UNICODE_STRING dir;
 +        WCHAR *p;
 +        HMODULE module;
 +
 +        if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID) module = pActCtx->hModule;
 +        else module = NtCurrentTeb()->ProcessEnvironmentBlock->ImageBaseAddress;
 +
 +        if ((status = get_module_filename( module, &dir, 0 ))) goto error;
 +        if ((p = strrchrW( dir.Buffer, '\\' ))) p[1] = 0;
 +        actctx->appdir.info = dir.Buffer;
 +    }
 +
 +    nameW.Buffer = NULL;
 +    if (pActCtx->lpSource)
 +    {
 +        if (!RtlDosPathNameToNtPathName_U(pActCtx->lpSource, &nameW, NULL, NULL))
 +        {
 +            status = STATUS_NO_SUCH_FILE;
 +            goto error;
 +        }
 +        status = open_nt_file( &file, &nameW );
 +        if (status)
 +        {
 +            RtlFreeUnicodeString( &nameW );
 +            goto error;
 +        }
 +    }
 +
 +    acl.actctx = actctx;
 +    acl.dependencies = NULL;
 +    acl.num_dependencies = 0;
 +    acl.allocated_dependencies = 0;
 +
 +    if (pActCtx->dwFlags & ACTCTX_FLAG_LANGID_VALID) lang = pActCtx->wLangId;
 +    if (pActCtx->dwFlags & ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID) directory = pActCtx->lpAssemblyDirectory;
 +
 +    if (pActCtx->dwFlags & ACTCTX_FLAG_RESOURCE_NAME_VALID)
 +    {
 +        /* if we have a resource it's a PE file */
 +        if (pActCtx->dwFlags & ACTCTX_FLAG_HMODULE_VALID)
 +        {
 +            status = get_manifest_in_module( &acl, NULL, NULL, directory, FALSE, pActCtx->hModule,
 +                                             pActCtx->lpResourceName, lang );
 +            if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
 +                /* FIXME: what to do if pActCtx->lpSource is set */
 +                status = get_manifest_in_associated_manifest( &acl, NULL, NULL, directory,
 +                                                              pActCtx->hModule, pActCtx->lpResourceName );
 +        }
 +        else if (pActCtx->lpSource)
 +        {
 +            status = get_manifest_in_pe_file( &acl, NULL, nameW.Buffer, directory, FALSE,
 +                                              file, pActCtx->lpResourceName, lang );
 +            if (status && status != STATUS_SXS_CANT_GEN_ACTCTX)
 +                status = get_manifest_in_associated_manifest( &acl, NULL, nameW.Buffer, directory,
 +                                                              NULL, pActCtx->lpResourceName );
 +        }
 +        else status = STATUS_INVALID_PARAMETER;
 +    }
 +    else
 +    {
 +        status = get_manifest_in_manifest_file( &acl, NULL, nameW.Buffer, directory, FALSE, file );
 +    }
 +
 +    if (file) NtClose( file );
 +    RtlFreeUnicodeString( &nameW );
 +
 +    if (status == STATUS_SUCCESS) status = parse_depend_manifests(&acl);
 +    free_depend_manifests( &acl );
 +
 +    if (status == STATUS_SUCCESS) *handle = actctx;
 +    else actctx_release( actctx );
 +    return status;
 +
 +error:
 +    if (file) NtClose( file );
 +    actctx_release( actctx );
 +    return status;
 +}
 +
 +VOID
 +NTAPI
 +RtlAddRefActivationContext(HANDLE handle)
 +{
 +    ACTIVATION_CONTEXT *actctx;
 +
 +    if ((actctx = check_actctx( handle ))) actctx_addref( actctx );
 +}
 +
 +VOID
 +NTAPI
 +RtlReleaseActivationContext( HANDLE handle )
 +{
 +    ACTIVATION_CONTEXT *actctx;
 +
 +    if ((actctx = check_actctx( handle ))) actctx_release( actctx );
 +}
 +
 +NTSTATUS
 +NTAPI RtlActivateActivationContext( ULONG unknown, HANDLE handle, PULONG_PTR cookie )
 +{
 +    RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
 +
 +    if (!(frame = RtlAllocateHeap( RtlGetProcessHeap(), 0, sizeof(*frame) )))
 +        return STATUS_NO_MEMORY;
 +
 +    frame->Previous = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
 +    frame->ActivationContext = handle;
 +    frame->Flags = 0;
 +
 +    NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame;
 +    RtlAddRefActivationContext( handle );
 +
 +    *cookie = (ULONG_PTR)frame;
 +    DPRINT( "%p cookie=%lx\n", handle, *cookie );
 +    return STATUS_SUCCESS;
 +}
 +
 +
 +NTSTATUS
 +NTAPI
 +RtlDeactivateActivationContext( ULONG flags, ULONG_PTR cookie )
 +{
 +    RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
 +
 +    DPRINT( "%x cookie=%lx\n", flags, cookie );
 +
 +    /* find the right frame */
 +    top = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
 +    for (frame = top; frame; frame = frame->Previous)
 +        if ((ULONG_PTR)frame == cookie) break;
 +
 +    if (!frame)
 +        RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
 +
 +    if (frame != top && !(flags & DEACTIVATE_ACTCTX_FLAG_FORCE_EARLY_DEACTIVATION))
 +        RtlRaiseStatus( STATUS_SXS_EARLY_DEACTIVATION );
 +
 +    /* pop everything up to and including frame */
 +    NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous;
 +
 +    while (top != NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
 +    {
 +        frame = top->Previous;
 +        RtlReleaseActivationContext( top->ActivationContext );
 +        RtlFreeHeap( RtlGetProcessHeap(), 0, top );
 +        top = frame;
 +    }
 +
 +    return STATUS_SUCCESS;
 +}
 +
 +VOID
 +NTAPI RtlFreeThreadActivationContextStack(void)
 +{
 +    RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
 +
 +    frame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
 +    while (frame)
 +    {
 +        RTL_ACTIVATION_CONTEXT_STACK_FRAME *prev = frame->Previous;
 +        RtlReleaseActivationContext( frame->ActivationContext );
 +        RtlFreeHeap( RtlGetProcessHeap(), 0, frame );
 +        frame = prev;
 +    }
 +    NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NULL;
 +}
 +
 +
 +NTSTATUS
 +NTAPI RtlGetActiveActivationContext( HANDLE *handle )
 +{
 +    if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
 +    {
 +        *handle = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext;
 +        RtlAddRefActivationContext( *handle );
 +    }
 +    else
 +        *handle = 0;
 +
 +    return STATUS_SUCCESS;
 +}
 +
 +
 +BOOLEAN
 +NTAPI RtlIsActivationContextActive( HANDLE handle )
 +{
 +    RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame;
 +
 +    for (frame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame; frame; frame = frame->Previous)
 +        if (frame->ActivationContext == handle) return TRUE;
 +    return FALSE;
 +}
 +
 +NTSTATUS
 +NTAPI
 +RtlQueryInformationActivationContext( ULONG flags, HANDLE handle, PVOID subinst,
 +                                      ULONG class, PVOID buffer,
 +                                      SIZE_T bufsize, SIZE_T *retlen )
 +{
 +    ACTIVATION_CONTEXT *actctx;
 +    NTSTATUS status;
 +
 +    DPRINT("%08x %p %p %u %p %ld %p\n", flags, handle,
 +          subinst, class, buffer, bufsize, retlen);
 +
 +    if (retlen) *retlen = 0;
 +    if ((status = find_query_actctx( &handle, flags, class ))) return status;
 +
 +    switch (class)
 +    {
 +    case ActivationContextBasicInformation:
 +        {
 +            ACTIVATION_CONTEXT_BASIC_INFORMATION *info = buffer;
 +
 +            if (retlen) *retlen = sizeof(*info);
 +            if (!info || bufsize < sizeof(*info)) return STATUS_BUFFER_TOO_SMALL;
 +
 +            info->hActCtx = handle;
 +            info->dwFlags = 0;  /* FIXME */
 +            if (!(flags & QUERY_ACTCTX_FLAG_NO_ADDREF)) RtlAddRefActivationContext( handle );
 +        }
 +        break;
 +
 +    case ActivationContextDetailedInformation:
 +        {
 +            ACTIVATION_CONTEXT_DETAILED_INFORMATION *acdi = buffer;
 +            struct assembly *assembly = NULL;
 +            SIZE_T len, manifest_len = 0, config_len = 0, appdir_len = 0;
 +            LPWSTR ptr;
 +
 +            if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
 +
 +            if (actctx->num_assemblies) assembly = actctx->assemblies;
 +
 +            if (assembly && assembly->manifest.info)
 +                manifest_len = strlenW(assembly->manifest.info) + 1;
 +            if (actctx->config.info) config_len = strlenW(actctx->config.info) + 1;
 +            if (actctx->appdir.info) appdir_len = strlenW(actctx->appdir.info) + 1;
 +            len = sizeof(*acdi) + (manifest_len + config_len + appdir_len) * sizeof(WCHAR);
 +
 +            if (retlen) *retlen = len;
 +            if (!buffer || bufsize < len) return STATUS_BUFFER_TOO_SMALL;
 +
 +            acdi->dwFlags = 0;
 +            acdi->ulFormatVersion = assembly ? 1 : 0; /* FIXME */
 +            acdi->ulAssemblyCount = actctx->num_assemblies;
 +            acdi->ulRootManifestPathType = assembly ? assembly->manifest.type : 0 /* FIXME */;
 +            acdi->ulRootManifestPathChars = assembly && assembly->manifest.info ? manifest_len - 1 : 0;
 +            acdi->ulRootConfigurationPathType = actctx->config.type;
 +            acdi->ulRootConfigurationPathChars = actctx->config.info ? config_len - 1 : 0;
 +            acdi->ulAppDirPathType = actctx->appdir.type;
 +            acdi->ulAppDirPathChars = actctx->appdir.info ? appdir_len - 1 : 0;
 +            ptr = (LPWSTR)(acdi + 1);
 +            if (manifest_len)
 +            {
 +                acdi->lpRootManifestPath = ptr;
 +                memcpy(ptr, assembly->manifest.info, manifest_len * sizeof(WCHAR));
 +                ptr += manifest_len;
 +            }
 +            else acdi->lpRootManifestPath = NULL;
 +            if (config_len)
 +            {
 +                acdi->lpRootConfigurationPath = ptr;
 +                memcpy(ptr, actctx->config.info, config_len * sizeof(WCHAR));
 +                ptr += config_len;
 +            }
 +            else acdi->lpRootConfigurationPath = NULL;
 +            if (appdir_len)
 +            {
 +                acdi->lpAppDirPath = ptr;
 +                memcpy(ptr, actctx->appdir.info, appdir_len * sizeof(WCHAR));
 +            }
 +            else acdi->lpAppDirPath = NULL;
 +        }
 +        break;
 +
 +    case AssemblyDetailedInformationInActivationContext:
 +        {
 +            ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *afdi = buffer;
 +            struct assembly *assembly;
 +            WCHAR *assembly_id;
 +            DWORD index;
 +            SIZE_T len, id_len = 0, ad_len = 0, path_len = 0;
 +            LPWSTR ptr;
 +
 +            if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
 +            if (!subinst) return STATUS_INVALID_PARAMETER;
 +
 +            index = *(DWORD*)subinst;
 +            if (!index || index > actctx->num_assemblies) return STATUS_INVALID_PARAMETER;
 +
 +            assembly = &actctx->assemblies[index - 1];
 +
 +            if (!(assembly_id = build_assembly_id( &assembly->id ))) return STATUS_NO_MEMORY;
 +            id_len = strlenW(assembly_id) + 1;
 +            if (assembly->directory) ad_len = strlenW(assembly->directory) + 1;
 +
 +            if (assembly->manifest.info &&
 +                (assembly->type == ASSEMBLY_MANIFEST || assembly->type == ASSEMBLY_SHARED_MANIFEST))
 +                path_len  = strlenW(assembly->manifest.info) + 1;
 +
 +            len = sizeof(*afdi) + (id_len + ad_len + path_len) * sizeof(WCHAR);
 +
 +            if (retlen) *retlen = len;
 +            if (!buffer || bufsize < len)
 +            {
 +                RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id );
 +                return STATUS_BUFFER_TOO_SMALL;
 +            }
 +
 +            afdi->ulFlags = 0;  /* FIXME */
 +            afdi->ulEncodedAssemblyIdentityLength = (id_len - 1) * sizeof(WCHAR);
 +            afdi->ulManifestPathType = assembly->manifest.type;
 +            afdi->ulManifestPathLength = assembly->manifest.info ? (path_len - 1) * sizeof(WCHAR) : 0;
 +            /* FIXME afdi->liManifestLastWriteTime = 0; */
 +            afdi->ulPolicyPathType = ACTIVATION_CONTEXT_PATH_TYPE_NONE; /* FIXME */
 +            afdi->ulPolicyPathLength = 0;
 +            /* FIXME afdi->liPolicyLastWriteTime = 0; */
 +            afdi->ulMetadataSatelliteRosterIndex = 0; /* FIXME */
 +            afdi->ulManifestVersionMajor = 1;
 +            afdi->ulManifestVersionMinor = 0;
 +            afdi->ulPolicyVersionMajor = 0; /* FIXME */
 +            afdi->ulPolicyVersionMinor = 0; /* FIXME */
 +            afdi->ulAssemblyDirectoryNameLength = ad_len ? (ad_len - 1) * sizeof(WCHAR) : 0;
 +            ptr = (LPWSTR)(afdi + 1);
 +            afdi->lpAssemblyEncodedAssemblyIdentity = ptr;
 +            memcpy( ptr, assembly_id, id_len * sizeof(WCHAR) );
 +            ptr += id_len;
 +            if (path_len)
 +            {
 +                afdi->lpAssemblyManifestPath = ptr;
 +                memcpy(ptr, assembly->manifest.info, path_len * sizeof(WCHAR));
 +                ptr += path_len;
 +            } else afdi->lpAssemblyManifestPath = NULL;
 +            afdi->lpAssemblyPolicyPath = NULL; /* FIXME */
 +            if (ad_len)
 +            {
 +                afdi->lpAssemblyDirectoryName = ptr;
 +                memcpy(ptr, assembly->directory, ad_len * sizeof(WCHAR));
 +                ptr += ad_len;
 +            }
 +            else afdi->lpAssemblyDirectoryName = NULL;
 +            RtlFreeHeap( RtlGetProcessHeap(), 0, assembly_id );
 +        }
 +        break;
 +
 +    case FileInformationInAssemblyOfAssemblyInActivationContext:
 +        {
 +            const ACTIVATION_CONTEXT_QUERY_INDEX *acqi = subinst;
 +            ASSEMBLY_FILE_DETAILED_INFORMATION *afdi = buffer;
 +            struct assembly *assembly;
 +            struct dll_redirect *dll;
 +            SIZE_T len, dll_len = 0;
 +            LPWSTR ptr;
 +
 +            if (!(actctx = check_actctx(handle))) return STATUS_INVALID_PARAMETER;
 +            if (!acqi) return STATUS_INVALID_PARAMETER;
 +
 +            if (acqi->ulAssemblyIndex >= actctx->num_assemblies)
 +                return STATUS_INVALID_PARAMETER;
 +            assembly = &actctx->assemblies[acqi->ulAssemblyIndex];
 +
 +            if (acqi->ulFileIndexInAssembly >= assembly->num_dlls)
 +                return STATUS_INVALID_PARAMETER;
 +            dll = &assembly->dlls[acqi->ulFileIndexInAssembly];
 +
 +            if (dll->name) dll_len = strlenW(dll->name) + 1;
 +            len = sizeof(*afdi) + dll_len * sizeof(WCHAR);
 +
 +            if (!buffer || bufsize < len)
 +            {
 +                if (retlen) *retlen = len;
 +                return STATUS_BUFFER_TOO_SMALL;
 +            }
 +            if (retlen) *retlen = 0; /* yes that's what native does !! */
 +            afdi->ulFlags = ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION;
 +            afdi->ulFilenameLength = dll_len ? (dll_len - 1) * sizeof(WCHAR) : 0;
 +            afdi->ulPathLength = 0; /* FIXME */
 +            ptr = (LPWSTR)(afdi + 1);
 +            if (dll_len)
 +            {
 +                afdi->lpFileName = ptr;
 +                memcpy( ptr, dll->name, dll_len * sizeof(WCHAR) );
 +            } else afdi->lpFileName = NULL;
 +            afdi->lpFilePath = NULL; /* FIXME */
 +        }
 +        break;
 +
 +    default:
 +        DPRINT( "class %u not implemented\n", class );
 +        return STATUS_NOT_IMPLEMENTED;
 +    }
 +    return STATUS_SUCCESS;
 +}
 +
++#define FIND_ACTCTX_RETURN_FLAGS 0x00000002
++#define FIND_ACTCTX_RETURN_ASSEMBLY_METADATA 0x00000004
++#define FIND_ACTCTX_VALID_MASK (FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX | FIND_ACTCTX_RETURN_FLAGS | FIND_ACTCTX_RETURN_ASSEMBLY_METADATA)
++
 +NTSTATUS
 +NTAPI
-     PACTCTX_SECTION_KEYED_DATA data = ptr;
-     NTSTATUS status = STATUS_SXS_KEY_NOT_FOUND;
-     if (guid)
++RtlpFindActivationContextSection_CheckParameters( ULONG flags, const GUID *guid, ULONG section_kind,
++                                                  UNICODE_STRING *section_name, PACTCTX_SECTION_KEYED_DATA data )
 +{
-         DPRINT1("expected guid == NULL\n");
++    /* Check general parameter combinations */
++    if (!section_name ||
++        (flags & ~FIND_ACTCTX_VALID_MASK) ||
++        ((flags & FIND_ACTCTX_VALID_MASK) && !data) ||
++        (data && data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex)))
 +    {
-     if (flags & ~FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX)
++        DPRINT1("invalid parameter\n");
 +        return STATUS_INVALID_PARAMETER;
 +    }
-     if (!data || data->cbSize < offsetof(ACTCTX_SECTION_KEYED_DATA, ulAssemblyRosterIndex) ||
-         !section_name || !section_name->Buffer)
-     {
-         DPRINT1("invalid parameter\n");
-         return STATUS_INVALID_PARAMETER;
-     }
++
++    /* TODO */
++    if (flags & FIND_ACTCTX_RETURN_FLAGS ||
++        flags & FIND_ACTCTX_RETURN_ASSEMBLY_METADATA)
 +    {
 +        DPRINT1("unknown flags %08x\n", flags);
 +        return STATUS_INVALID_PARAMETER;
 +    }
++
++    return STATUS_SUCCESS;
++}
++
++NTSTATUS
++NTAPI
++RtlFindActivationContextSectionString( ULONG flags, const GUID *guid, ULONG section_kind,
++                                       UNICODE_STRING *section_name, PVOID ptr )
++{
++    PACTCTX_SECTION_KEYED_DATA data = ptr;
++    NTSTATUS status;
++
++    status = RtlpFindActivationContextSection_CheckParameters(flags, guid, section_kind, section_name, data);
++    if (!NT_SUCCESS(status)) return status;
++
++    status = STATUS_SXS_KEY_NOT_FOUND;
++
++    /* if there is no data, but params are valid,
++       we return that sxs key is not found to be at least somehow compatible */
++    if (!data) return status;
 +
 +    ASSERT(NtCurrentTeb());
 +    ASSERT(NtCurrentTeb()->ActivationContextStackPointer);
 +
 +    if (NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame)
 +    {
 +        ACTIVATION_CONTEXT *actctx = check_actctx(NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame->ActivationContext);
 +        if (actctx) status = find_string( actctx, section_kind, section_name, flags, data );
 +    }
 +
 +    if (status != STATUS_SUCCESS)
 +        status = find_string( process_actctx, section_kind, section_name, flags, data );
 +
 +    return status;
 +}
 +
 +/* Stubs */
 +
 +NTSTATUS
 +NTAPI
 +RtlAllocateActivationContextStack(IN PVOID *Context)
 +{
 +    PACTIVATION_CONTEXT_STACK ContextStack;
 +    ContextStack = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (ACTIVATION_CONTEXT_STACK) );
 +    if (!ContextStack)
 +    {
 +        return STATUS_NO_MEMORY;
 +    }
 +
 +    ContextStack->ActiveFrame = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RTL_ACTIVATION_CONTEXT_STACK_FRAME));
 +    if (!ContextStack->ActiveFrame) return STATUS_NO_MEMORY;
 +
 +    *Context = ContextStack;
 +
 +    /* FIXME: Documentation on MSDN reads that activation contexts are only created
 +              for modules that have a valid manifest file or resource */
 +    actctx_init();
 +
 +    return STATUS_SUCCESS;
 +}
 +
 +PRTL_ACTIVATION_CONTEXT_STACK_FRAME
 +FASTCALL
 +RtlActivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame,
 +                                       IN PVOID Context)
 +{
 +#if NEW_NTDLL_LOADER
 +    RTL_ACTIVATION_CONTEXT_STACK_FRAME *ActiveFrame;
 +
 +    /* Get the curren active frame */
 +    ActiveFrame = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
 +
 +    DPRINT1("ActiveFrame %p, &Frame->Frame %p, Context %p\n", ActiveFrame, &Frame->Frame, Context);
 +
 +    /* Actually activate it */
 +    Frame->Frame.Previous = ActiveFrame;
 +    Frame->Frame.ActivationContext = Context;
 +    Frame->Frame.Flags = 0;
 +
 +    /* Check if we can activate this context */
 +    if ((ActiveFrame && (ActiveFrame->ActivationContext != Context)) ||
 +        Context)
 +    {
 +        /* Set new active frame */
 +        NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = &Frame->Frame;
 +        return &Frame->Frame;
 +    }
 +
 +    /* We can get here only one way: it was already activated */
 +    DPRINT1("Trying to activate improper activation context\n");
 +
 +    /* Activate only if we are allowing multiple activation */
 +    if (!RtlpNotAllowingMultipleActivation)
 +    {
 +        NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = &Frame->Frame;
 +    }
 +    else
 +    {
 +        /* Set flag */
 +        Frame->Frame.Flags = 0x30;
 +    }
 +
 +    /* Return pointer to the activation frame */
 +    return &Frame->Frame;
 +#else
 +    return NULL;
 +#endif
 +}
 +
 +PRTL_ACTIVATION_CONTEXT_STACK_FRAME
 +FASTCALL
 +RtlDeactivateActivationContextUnsafeFast(IN PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED Frame)
 +{
 +#if NEW_NTDLL_LOADER
 +    RTL_ACTIVATION_CONTEXT_STACK_FRAME *frame, *top;
 +
 +    /* find the right frame */
 +    top = NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame;
 +    frame = &Frame->Frame;
 +
 +    if (!frame)
 +        RtlRaiseStatus( STATUS_SXS_INVALID_DEACTIVATION );
 +
 +    /* pop everything up to and including frame */
 +    NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = frame->Previous;
 +
 +    return frame;
 +#else
 +    return NULL;
 +#endif
 +}
 +
 +
 +NTSTATUS
 +NTAPI
 +RtlZombifyActivationContext(PVOID Context)
 +{
 +    UNIMPLEMENTED;
 +
 +    if (Context == ACTCTX_FAKE_HANDLE)
 +        return STATUS_SUCCESS;
 +
 +    return STATUS_NOT_IMPLEMENTED;
 +}
 +
index 0cf67a0,0000000..e50a63d
mode 100644,000000..100644
--- /dev/null
@@@ -1,50 -1,0 +1,49 @@@
-         set(CMAKE_C_CREATE_STATIC_LIBRARY "<CMAKE_AR> crs <TARGET> <LINK_FLAGS> <OBJECTS>")
 +
 +if(NOT ARCH)
 +    set(ARCH i386)
 +endif()
 +
 +# Choose the right MinGW prefix
 +if(ARCH MATCHES i386)
 +
 +    if(CMAKE_HOST_SYSTEM_NAME MATCHES Windows)
 +        set(MINGW_PREFIX "" CACHE STRING "MinGW Prefix")
 +    else()
 +        set(MINGW_PREFIX "mingw32-" CACHE STRING "MinGW Prefix")
 +    endif(CMAKE_HOST_SYSTEM_NAME MATCHES Windows)
 +
 +elseif(ARCH MATCHES amd64)
 +    set(MINGW_PREFIX "x86_64-w64-mingw32-" CACHE STRING "MinGW Prefix")
 +elseif(ARCH MATCHES arm)
 +    set(MINGW_PREFIX "arm-mingw32ce-" CACHE STRING "MinGW Prefix")
 +endif()
 +
 +if(ENABLE_CCACHE)
 +    set(CCACHE "ccache" CACHE STRING "ccache")
 +else()
 +    set(CCACHE "" CACHE STRING "ccache")
 +endif()
 +
 +# the name of the target operating system
 +set(CMAKE_SYSTEM_NAME Windows)
 +set(CMAKE_SYSTEM_PROCESSOR i686)
 +
 +# which compilers to use for C and C++
 +set(CMAKE_C_COMPILER ${CCACHE} ${MINGW_PREFIX}gcc)
 +set(CMAKE_CXX_COMPILER ${CCACHE} ${MINGW_PREFIX}g++)
 +set(CMAKE_RC_COMPILER ${MINGW_PREFIX}windres)
 +set(CMAKE_ASM_COMPILER ${MINGW_PREFIX}gcc)
 +set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> -x assembler-with-cpp -o <OBJECT> -I${REACTOS_SOURCE_DIR}/include/asm -I${REACTOS_BINARY_DIR}/include/asm <FLAGS> <DEFINES> -D__ASM__ -c <SOURCE>")
 +
 +# Use stdcall fixups, and don't link with anything by default unless we say so
 +set(CMAKE_C_STANDARD_LIBRARIES "-lgcc" CACHE STRING "Standard C Libraries")
 +
 +#MARK_AS_ADVANCED(CLEAR CMAKE_CXX_STANDARD_LIBRARIES)
 +set(CMAKE_CXX_STANDARD_LIBRARIES "" CACHE STRING "Standard C++ Libraries")
 +
 +if(ARCH MATCHES i386)
 +    set(CMAKE_SHARED_LINKER_FLAGS_INIT "-nodefaultlibs -nostdlib -Wl,--enable-auto-image-base -Wl,--disable-auto-import")
 +#-Wl,-T,${REACTOS_SOURCE_DIR}/global.lds
 +elseif(ARCH MATCHES amd64)
 +    set(CMAKE_SHARED_LINKER_FLAGS_INIT "-nodefaultlibs -nostdlib -Wl,--enable-auto-image-base -Wl,--disable-auto-import")
 +endif()