https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3ad5c7fd84bdcce26db5f46a2afd4c7a972c7700
commit 3ad5c7fd84bdcce26db5f46a2afd4c7a972c7700 Author: Eric Kohl <eric.k...@reactos.org> AuthorDate: Sun Nov 12 23:27:09 2017 +0100 [SETUPAPI] Improve the range list implementation. - SEH-protect the range list validation and move it into a separate function. - Use a mutex to synchronize access to the range list. - Implement CM_First_Range and parts of CM_Add_Range. --- dll/win32/setupapi/cfgmgr.c | 162 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 150 insertions(+), 12 deletions(-) diff --git a/dll/win32/setupapi/cfgmgr.c b/dll/win32/setupapi/cfgmgr.c index 898b755ec3..14f05963e2 100644 --- a/dll/win32/setupapi/cfgmgr.c +++ b/dll/win32/setupapi/cfgmgr.c @@ -69,17 +69,18 @@ typedef struct _NOTIFY_DATA #define NOTIFY_MAGIC 0x44556677 -typedef struct _INTERNAL_RANGE_ELEMENT +typedef struct _INTERNAL_RANGE { - struct _INTERNAL_RANGE_ELEMENT *Next; - ULONG ulDummy; -} INTERNAL_RANGE_ELEMENT, *PINTERNAL_RANGE_ELEMENT; + LIST_ENTRY ListEntry; + DWORDLONG ullStart; + DWORDLONG ullEnd; +} INTERNAL_RANGE, *PINTERNAL_RANGE; typedef struct _INTERNAL_RANGE_LIST { ULONG ulMagic; - PINTERNAL_RANGE_ELEMENT Current; - PINTERNAL_RANGE_ELEMENT First; + HANDLE hMutex; + LIST_ENTRY ListHead; } INTERNAL_RANGE_LIST, *PINTERNAL_RANGE_LIST; #define RANGE_LIST_MAGIC 0x33445566 @@ -338,6 +339,30 @@ done: } +BOOL +IsValidRangeList( + _In_ PINTERNAL_RANGE_LIST pRangeList) +{ + BOOL bValid = TRUE; + + if (pRangeList == NULL) + return FALSE; + + _SEH2_TRY + { + if (pRangeList->ulMagic != RANGE_LIST_MAGIC) + bValid = FALSE; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + bValid = FALSE; + } + _SEH2_END; + + return bValid; +} + + /*********************************************************************** * CMP_GetBlockedDriverInfo [SETUPAPI.@] */ @@ -950,9 +975,53 @@ CM_Add_Range( _In_ RANGE_LIST rlh, _In_ ULONG ulFlags) { + PINTERNAL_RANGE_LIST pRangeList; + PINTERNAL_RANGE pRange; + CONFIGRET ret = CR_SUCCESS; + FIXME("CM_Add_Range(%I64u %I64u %p %lx)\n", ullStartValue, ullEndValue, rlh, ulFlags); - return CR_CALL_NOT_IMPLEMENTED; + + pRangeList = (PINTERNAL_RANGE_LIST)rlh; + + if (!IsValidRangeList(pRangeList)) + return CR_INVALID_RANGE_LIST; + + if (ulFlags & ~CM_ADD_RANGE_BITS) + return CR_INVALID_FLAG; + + if (ullEndValue < ullStartValue) + return CR_INVALID_RANGE; + + /* Lock the range list */ + WaitForSingleObject(pRangeList->hMutex, INFINITE); + + /* Allocate the new range */ + pRange = HeapAlloc(GetProcessHeap(), 0, sizeof(INTERNAL_RANGE)); + if (pRange == NULL) + { + ret = CR_OUT_OF_MEMORY; + goto done; + } + + pRange->ullStart = ullStartValue; + pRange->ullEnd = ullEndValue; + + /* Insert the range */ + if (IsListEmpty(&pRangeList->ListHead)) + { + InsertTailList(&pRangeList->ListHead, &pRange->ListEntry); + } + else + { + + } + +done: + /* Unlock the range list */ + ReleaseMutex(pRangeList->hMutex); + + return ret; } @@ -1266,13 +1335,23 @@ CM_Create_Range_List( if (prlh == NULL) return CR_INVALID_POINTER; + /* Allocate the range list */ pRangeList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(INTERNAL_RANGE_LIST)); if (pRangeList == NULL) return CR_OUT_OF_MEMORY; + /* Set the magic value */ pRangeList->ulMagic = RANGE_LIST_MAGIC; - // TODO: More initialization + /* Initialize the mutex for synchonized access */ + pRangeList->hMutex = CreateMutex(NULL, FALSE, NULL); + if (pRangeList->hMutex == NULL) + { + HeapFree(GetProcessHeap(), 0, pRangeList); + return CR_FAILURE; + } + + InitializeListHead(&pRangeList->ListHead); *prlh = (RANGE_LIST)pRangeList; @@ -1814,9 +1893,49 @@ CM_First_Range( _Out_ PRANGE_ELEMENT preElement, _In_ ULONG ulFlags) { + PINTERNAL_RANGE_LIST pRangeList; + PINTERNAL_RANGE pRange; + PLIST_ENTRY ListEntry; + CONFIGRET ret = CR_SUCCESS; + FIXME("CM_First_Range(%p %p %p %p %lx)\n", rlh, pullStart, pullEnd, preElement, ulFlags); - return CR_CALL_NOT_IMPLEMENTED; + + pRangeList = (PINTERNAL_RANGE_LIST)rlh; + + if (!IsValidRangeList(pRangeList)) + return CR_INVALID_RANGE_LIST; + + if (pullStart == NULL || pullEnd == NULL || preElement == NULL) + return CR_INVALID_POINTER; + + if (ulFlags != 0) + return CR_INVALID_FLAG; + + /* Lock the range list */ + WaitForSingleObject(pRangeList->hMutex, INFINITE); + + /* Fail, if the list is empty */ + if (IsListEmpty(&pRangeList->ListHead)) + { + ret = CR_FAILURE; + goto done; + } + + /* Get the first range */ + ListEntry = pRangeList->ListHead.Flink; + pRange = CONTAINING_RECORD(ListEntry, INTERNAL_RANGE, ListEntry); + + /* Return the range data */ + *pullStart = pRange->ullStart; + *pullEnd = pRange->ullEnd; + *preElement = (RANGE_ELEMENT)pRange; + +done: + /* Unlock the range list */ + ReleaseMutex(pRangeList->hMutex); + + return ret; } @@ -1920,19 +2039,38 @@ CM_Free_Range_List( _In_ ULONG ulFlags) { PINTERNAL_RANGE_LIST pRangeList; + PINTERNAL_RANGE pRange; + PLIST_ENTRY ListEntry; - FIXME("CM_Free_Range_List(%p %lx)\n", RangeList, ulFlags); + FIXME("CM_Free_Range_List(%p %lx)\n", + RangeList, ulFlags); pRangeList = (PINTERNAL_RANGE_LIST)RangeList; - if (pRangeList == NULL || pRangeList->ulMagic != RANGE_LIST_MAGIC) + if (!IsValidRangeList(pRangeList)) return CR_INVALID_RANGE_LIST; if (ulFlags != 0) return CR_INVALID_FLAG; - // TODO: Free the list of ranges + /* Lock the range list */ + WaitForSingleObject(pRangeList->hMutex, INFINITE); + + /* Free the list of ranges */ + while (!IsListEmpty(&pRangeList->ListHead)) + { + ListEntry = RemoveHeadList(&pRangeList->ListHead); + pRange = CONTAINING_RECORD(ListEntry, INTERNAL_RANGE, ListEntry); + HeapFree(GetProcessHeap(), 0, pRange); + } + + /* Unlock the range list */ + ReleaseMutex(pRangeList->hMutex); + + /* Close the mutex */ + CloseHandle(pRangeList->hMutex); + /* Free the range list */ HeapFree(GetProcessHeap(), 0, pRangeList); return CR_SUCCESS;