Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

703 lines
17 KiB

/*****************************************************************************
* resource.cpp - resource list object implementation
*****************************************************************************
* Copyright (c) 1997-2000 Microsoft Corporation. All rights reserved.
*/
#include "private.h"
/*****************************************************************************
* Factory.
*/
#pragma code_seg("PAGE")
/*****************************************************************************
* CreateResourceList()
*****************************************************************************
* Creates a resource list object.
*/
NTSTATUS
CreateResourceList
(
OUT PUNKNOWN * Unknown,
IN REFCLSID,
IN PUNKNOWN UnknownOuter OPTIONAL,
IN POOL_TYPE PoolType
)
{
PAGED_CODE();
ASSERT(Unknown);
_DbgPrintF(DEBUGLVL_LIFETIME,("Creating RESOURCELIST"));
STD_CREATE_BODY
(
CResourceList,
Unknown,
UnknownOuter,
PoolType
);
}
/*****************************************************************************
* PcNewResourceList()
*****************************************************************************
* Creates and initializes a resource list.
* Creates an empty resource list if both of the PCM_RESOURCE_LIST parameters
* are NULL.
*/
PORTCLASSAPI
NTSTATUS
NTAPI
PcNewResourceList
(
OUT PRESOURCELIST * OutResourceList,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN POOL_TYPE PoolType,
IN PCM_RESOURCE_LIST TranslatedResources,
IN PCM_RESOURCE_LIST UntranslatedResources
)
{
PAGED_CODE();
ASSERT(OutResourceList);
//
// Validate Parameters.
//
if (NULL == OutResourceList)
{
_DbgPrintF(DEBUGLVL_TERSE, ("PcNewResourceList : Invalid Parameter"));
return STATUS_INVALID_PARAMETER;
}
PUNKNOWN unknown;
NTSTATUS ntStatus =
CreateResourceList
(
&unknown,
GUID_NULL,
OuterUnknown,
PoolType
);
if (NT_SUCCESS(ntStatus))
{
PRESOURCELISTINIT resourceList;
ntStatus =
unknown->QueryInterface
(
IID_IResourceList,
(PVOID *) &resourceList
);
if (NT_SUCCESS(ntStatus))
{
ntStatus =
resourceList->Init
(
TranslatedResources,
UntranslatedResources,
PoolType
);
if (NT_SUCCESS(ntStatus))
{
*OutResourceList = resourceList;
}
else
{
resourceList->Release();
}
}
unknown->Release();
}
return ntStatus;
}
/*****************************************************************************
* PcNewResourceSublist()
*****************************************************************************
* Creates and initializes an empty resource list derived from another
* resource list.
*/
PORTCLASSAPI
NTSTATUS
NTAPI
PcNewResourceSublist
(
OUT PRESOURCELIST * OutResourceList,
IN PUNKNOWN OuterUnknown OPTIONAL,
IN POOL_TYPE PoolType,
IN PRESOURCELIST ParentList,
IN ULONG MaximumEntries
)
{
PAGED_CODE();
ASSERT(OutResourceList);
ASSERT(ParentList);
ASSERT(MaximumEntries);
//
// Validate Parameters.
//
if (NULL == OutResourceList ||
NULL == ParentList ||
0 == MaximumEntries)
{
_DbgPrintF(DEBUGLVL_TERSE, ("PcNewResourceSubList : Invalid Parameter"));
return STATUS_INVALID_PARAMETER;
}
PUNKNOWN unknown;
NTSTATUS ntStatus =
CreateResourceList
(
&unknown,
GUID_NULL,
OuterUnknown,
PoolType
);
if (NT_SUCCESS(ntStatus))
{
PRESOURCELISTINIT resourceList;
ntStatus =
unknown->QueryInterface
(
IID_IResourceList,
(PVOID *) &resourceList
);
if (NT_SUCCESS(ntStatus))
{
ntStatus =
resourceList->InitFromParent
(
ParentList,
MaximumEntries,
PoolType
);
if (NT_SUCCESS(ntStatus))
{
*OutResourceList = resourceList;
}
else
{
resourceList->Release();
}
}
unknown->Release();
}
return ntStatus;
}
/*****************************************************************************
* Member functions.
*/
/*****************************************************************************
* CResourceList::~CResourceList()
*****************************************************************************
* Destructor.
*/
CResourceList::
~CResourceList
( void
)
{
PAGED_CODE();
_DbgPrintF(DEBUGLVL_LIFETIME,("Destroying RESOURCELIST (0x%08x)",this));
if (Translated)
{
ExFreePool(Translated);
}
if (Untranslated)
{
ExFreePool(Untranslated);
}
}
/*****************************************************************************
* CResourceList::NonDelegatingQueryInterface()
*****************************************************************************
* Obtains an interface.
*/
STDMETHODIMP_(NTSTATUS)
CResourceList::
NonDelegatingQueryInterface
(
REFIID Interface,
PVOID * Object
)
{
PAGED_CODE();
ASSERT(Object);
if (IsEqualGUIDAligned(Interface,IID_IUnknown))
{
*Object = PVOID(PUNKNOWN(this));
}
else
if (IsEqualGUIDAligned(Interface,IID_IResourceList))
{
*Object = PVOID(PRESOURCELISTINIT(this));
}
else
{
*Object = NULL;
}
if (*Object)
{
PUNKNOWN(*Object)->AddRef();
return STATUS_SUCCESS;
}
return STATUS_INVALID_PARAMETER;
}
/*****************************************************************************
* CResourceList::Init()
*****************************************************************************
* Initializes the object.
*/
STDMETHODIMP_(NTSTATUS)
CResourceList::
Init
(
IN PCM_RESOURCE_LIST TranslatedResources,
IN PCM_RESOURCE_LIST UntranslatedResources,
IN POOL_TYPE PoolType
)
{
PAGED_CODE();
_DbgPrintF(DEBUGLVL_LIFETIME,("Initializing RESOURCELIST (0x%08x)",this));
// check NULL resource lists.
if (!TranslatedResources && !UntranslatedResources)
{
EntriesAllocated = EntriesInUse = 0;
Translated = Untranslated = NULL;
return STATUS_SUCCESS;
}
// this check fails if _one_ of the resource lists is NULL, which should
// never happen.
ASSERT (TranslatedResources);
ASSERT (UntranslatedResources);
if (!TranslatedResources || !UntranslatedResources)
{
return STATUS_INVALID_PARAMETER;
}
EntriesAllocated =
EntriesInUse =
UntranslatedResources->List[0].PartialResourceList.Count;
ULONG listSize =
( sizeof(CM_RESOURCE_LIST)
+ ( (EntriesInUse - 1)
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
)
);
NTSTATUS ntStatus = STATUS_SUCCESS;
Translated = PCM_RESOURCE_LIST(ExAllocatePoolWithTag(PoolType,listSize,'lRcP'));
if (Translated)
{
Untranslated =
PCM_RESOURCE_LIST(ExAllocatePoolWithTag(PoolType,listSize,'lRcP'));
if (Untranslated)
{
RtlCopyMemory(Untranslated,UntranslatedResources,listSize);
RtlCopyMemory(Translated,TranslatedResources,listSize);
}
else
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
ExFreePool(Translated);
Translated = NULL;
}
}
else
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
return ntStatus;
}
/*****************************************************************************
* CResourceList::InitFromParent()
*****************************************************************************
* Initializes the object from a parent object.
*/
STDMETHODIMP_(NTSTATUS)
CResourceList::
InitFromParent
(
IN PRESOURCELIST ParentList,
IN ULONG MaximumEntries,
IN POOL_TYPE PoolType
)
{
PAGED_CODE();
ASSERT(ParentList);
ASSERT(MaximumEntries);
ULONG listSize =
( sizeof(CM_RESOURCE_LIST)
+ ( ( MaximumEntries
- 1
)
* sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
)
);
NTSTATUS ntStatus = STATUS_SUCCESS;
Translated = PCM_RESOURCE_LIST(ExAllocatePoolWithTag(PoolType,listSize,'lRcP'));
if (Translated)
{
Untranslated = PCM_RESOURCE_LIST(ExAllocatePoolWithTag(PoolType,listSize,'lRcP'));
if (Untranslated)
{
RtlZeroMemory(Translated,listSize);
RtlZeroMemory(Untranslated,listSize);
// Copy headers from the parent.
RtlCopyMemory
(
Translated,
ParentList->TranslatedList(),
( sizeof(CM_RESOURCE_LIST)
- sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
)
);
RtlCopyMemory
(
Untranslated,
ParentList->UntranslatedList(),
( sizeof(CM_RESOURCE_LIST)
- sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
)
);
EntriesAllocated = MaximumEntries;
EntriesInUse = 0;
Translated->List[0].PartialResourceList.Count = EntriesInUse;
Untranslated->List[0].PartialResourceList.Count = EntriesInUse;
}
else
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
ExFreePool(Translated);
Translated = NULL;
}
}
else
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
return ntStatus;
}
/*****************************************************************************
* CResourceList::NumberOfEntries()
*****************************************************************************
* Determine the number of entries in the list.
*/
STDMETHODIMP_(ULONG)
CResourceList::
NumberOfEntries
( void
)
{
PAGED_CODE();
return EntriesInUse;
}
/*****************************************************************************
* CResourceList::NumberOfEntriesOfType()
*****************************************************************************
* Determines the number of entries of a given type in the list.
*/
STDMETHODIMP_(ULONG)
CResourceList::
NumberOfEntriesOfType
(
IN CM_RESOURCE_TYPE Type
)
{
PAGED_CODE();
if (!Untranslated) {
return 0;
}
PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor =
Untranslated->List[0].PartialResourceList.PartialDescriptors;
ULONG entriesOfType = 0;
for
( ULONG count = EntriesInUse;
count--;
descriptor++
)
{
if (descriptor->Type == Type)
{
entriesOfType++;
}
}
return entriesOfType;
}
/*****************************************************************************
* CResourceList::FindTranslatedEntry()
*****************************************************************************
* Finds a translated entry.
*/
STDMETHODIMP_(PCM_PARTIAL_RESOURCE_DESCRIPTOR)
CResourceList::
FindTranslatedEntry
(
IN CM_RESOURCE_TYPE Type,
IN ULONG Index
)
{
PAGED_CODE();
if (!Translated) {
return 0;
}
PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor =
Translated->List[0].PartialResourceList.PartialDescriptors;
ULONG count = EntriesInUse;
if (count)
{
while (descriptor)
{
if (count-- == 0)
{
descriptor = NULL;
}
else
{
if (descriptor->Type == Type)
{
if (Index-- == 0)
{
break;
}
}
descriptor++;
}
}
}
return descriptor;
}
/*****************************************************************************
* CResourceList::FindUntranslatedEntry()
*****************************************************************************
* Finds an untranslated entry.
*/
STDMETHODIMP_(PCM_PARTIAL_RESOURCE_DESCRIPTOR)
CResourceList::
FindUntranslatedEntry
(
IN CM_RESOURCE_TYPE Type,
IN ULONG Index
)
{
PAGED_CODE();
if (!Untranslated) {
return 0;
}
PCM_PARTIAL_RESOURCE_DESCRIPTOR descriptor =
Untranslated->List[0].PartialResourceList.PartialDescriptors;
ULONG count = EntriesInUse;
if (count)
{
while (descriptor)
{
if (count-- == 0)
{
descriptor = NULL;
}
else
{
if (descriptor->Type == Type)
{
if (Index-- == 0)
{
break;
}
}
descriptor++;
}
}
}
return descriptor;
}
/*****************************************************************************
* CResourceList::AddEntry()
*****************************************************************************
* Adds an entry.
*/
STDMETHODIMP_(NTSTATUS)
CResourceList::
AddEntry
(
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedDescr,
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR UntranslatedDescr
)
{
PAGED_CODE();
ASSERT(TranslatedDescr);
ASSERT(UntranslatedDescr);
NTSTATUS ntStatus = STATUS_SUCCESS;
// when there is no resource list stored in this object, both EntriesInUse
// and EntriesAllocated are 0.
if (EntriesInUse < EntriesAllocated)
{
Translated->
List[0].PartialResourceList.PartialDescriptors[EntriesInUse] =
*TranslatedDescr;
Untranslated->
List[0].PartialResourceList.PartialDescriptors[EntriesInUse] =
*UntranslatedDescr;
EntriesInUse++;
// update counts
Translated->
List[0].PartialResourceList.Count = EntriesInUse;
Untranslated->
List[0].PartialResourceList.Count = EntriesInUse;
}
else
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
return ntStatus;
}
/*****************************************************************************
* CResourceList::AddEntryFromParent()
*****************************************************************************
* Adds an entry from a parent.
*/
STDMETHODIMP_(NTSTATUS)
CResourceList::
AddEntryFromParent
(
IN PRESOURCELIST Parent,
IN CM_RESOURCE_TYPE Type,
IN ULONG Index
)
{
PAGED_CODE();
ASSERT(Parent);
PCM_PARTIAL_RESOURCE_DESCRIPTOR translated =
Parent->FindTranslatedEntry(Type,Index);
PCM_PARTIAL_RESOURCE_DESCRIPTOR untranslated =
Parent->FindUntranslatedEntry(Type,Index);
NTSTATUS ntStatus;
if (translated && untranslated)
{
ntStatus = AddEntry(translated,untranslated);
}
else
{
ntStatus = STATUS_INVALID_PARAMETER;
}
return ntStatus;
}
/*****************************************************************************
* CResourceList::TranslatedList()
*****************************************************************************
* Gets the list of translated resources.
*/
STDMETHODIMP_(PCM_RESOURCE_LIST)
CResourceList::
TranslatedList
( void
)
{
PAGED_CODE();
return Translated; // Attention: This could be NULL.
}
/*****************************************************************************
* CResourceList::UntranslatedList()
*****************************************************************************
* Gets the list of untranslated resources.
*/
STDMETHODIMP_(PCM_RESOURCE_LIST)
CResourceList::
UntranslatedList
( void
)
{
PAGED_CODE();
return Untranslated; // Attention: This could be NULL.
}
#pragma code_seg()