Don't leak memory when destroying device info set and driver lists
Try to keep .inf files handles instead of opening/parsing them at each
device installation step
Modified: trunk/reactos/lib/setupapi/devinst.c
_____
Modified: trunk/reactos/lib/setupapi/devinst.c
--- trunk/reactos/lib/setupapi/devinst.c 2005-10-24 05:05:07 UTC
(rev 18730)
+++ trunk/reactos/lib/setupapi/devinst.c 2005-10-24 09:16:34 UTC
(rev 18731)
@@ -116,6 +116,14 @@
WCHAR SymbolicLink[0]; /* \\?\ACPI#PNP0501#4&2658d0a0&0#{GUID} */
};
+/* We don't want to open the .inf file to read only one information in
it, so keep a handle to it once it
+ * has been already loaded once. Keep also a reference counter */
+struct InfFileDetails
+{
+ HINF hInf;
+ ULONG References;
+};
+
struct DriverInfoElement /* Element of DeviceInfoSet.DriverListHead and
DeviceInfoElement.DriverListHead */
{
LIST_ENTRY ListEntry;
@@ -125,6 +133,7 @@
SP_DRVINFO_DETAIL_DATA_W Details;
GUID ClassGuid;
LPWSTR MatchingId;
+ struct InfFileDetails *InfFileDetails;
};
struct DeviceInfoElement /* Element of DeviceInfoSet.ListHead */
@@ -1934,6 +1943,57 @@
return ret;
}
+static BOOL DestroyDriverInfoElement(struct DriverInfoElement*
driverInfo)
+{
+ if (InterlockedDecrement(&driverInfo->InfFileDetails->References)
== 0)
+ {
+ SetupCloseInfFile(driverInfo->InfFileDetails->hInf);
+ HeapFree(GetProcessHeap(), 0, driverInfo->InfFileDetails);
+ }
+ HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
+ HeapFree(GetProcessHeap(), 0, driverInfo);
+ return TRUE;
+}
+
+static BOOL DestroyDeviceInfoElement(struct DeviceInfoElement*
deviceInfo)
+{
+ PLIST_ENTRY ListEntry;
+ struct DriverInfoElement *driverInfo;
+
+ while (!IsListEmpty(&deviceInfo->DriverListHead))
+ {
+ ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
+ driverInfo = (struct DriverInfoElement *)ListEntry;
+ if (!DestroyDriverInfoElement(driverInfo))
+ return FALSE;
+ }
+ while (!IsListEmpty(&deviceInfo->InterfaceListHead))
+ {
+ ListEntry = RemoveHeadList(&deviceInfo->InterfaceListHead);
+ HeapFree(GetProcessHeap(), 0, ListEntry);
+ }
+ HeapFree(GetProcessHeap(), 0, deviceInfo);
+ return TRUE;
+}
+
+static BOOL DestroyDeviceInfoSet(struct DeviceInfoSet* list)
+{
+ PLIST_ENTRY ListEntry;
+ struct DeviceInfoElement *deviceInfo;
+
+ while (!IsListEmpty(&list->ListHead))
+ {
+ ListEntry = RemoveHeadList(&list->ListHead);
+ deviceInfo = (struct DeviceInfoElement *)ListEntry;
+ if (!DestroyDeviceInfoElement(deviceInfo))
+ return FALSE;
+ }
+ if (list->HKLM != HKEY_LOCAL_MACHINE)
+ RegCloseKey(list->HKLM);
+ HeapFree(GetProcessHeap(), 0, list);
+ return TRUE;
+}
+
/***********************************************************************
* SetupDiDestroyDeviceInfoList (SETUPAPI.@)
*/
@@ -1947,25 +2007,7 @@
struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
if (list->magic == SETUP_DEV_INFO_SET_MAGIC)
- {
- PLIST_ENTRY ListEntry, InterfaceEntry;
- struct DeviceInfoElement *deviceInfo;
- while (!IsListEmpty(&list->ListHead))
- {
- ListEntry = RemoveHeadList(&list->ListHead);
- deviceInfo = (struct DeviceInfoElement *)ListEntry;
- while (!IsListEmpty(&deviceInfo->InterfaceListHead))
- {
- InterfaceEntry =
RemoveHeadList(&deviceInfo->InterfaceListHead);
- HeapFree(GetProcessHeap(), 0, InterfaceEntry);
- }
- HeapFree(GetProcessHeap(), 0, ListEntry);
- }
- if (list->HKLM != HKEY_LOCAL_MACHINE)
- RegCloseKey(list->HKLM);
- HeapFree(GetProcessHeap(), 0, list);
- ret = TRUE;
- }
+ ret = DestroyDeviceInfoSet(list);
else
SetLastError(ERROR_INVALID_HANDLE);
}
@@ -3824,6 +3866,7 @@
IN DWORD DriverType, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
IN LPGUID ClassGuid,
IN INFCONTEXT ContextDevice,
+ IN struct InfFileDetails *InfFileDetails,
IN LPCWSTR InfFile,
IN LPCWSTR ProviderName,
IN LPCWSTR ManufacturerName,
@@ -3929,6 +3972,8 @@
driverInfo->Info.ProviderName[0] = '\0';
driverInfo->Info.DriverDate = DriverDate;
driverInfo->Info.DriverVersion = DriverVersion;
+ InterlockedIncrement(&InfFileDetails->References);
+ driverInfo->InfFileDetails = InfFileDetails;
/* Insert current driver in driver list, according to its rank */
PreviousEntry = DriverListHead->Flink;
@@ -4094,7 +4139,7 @@
struct DeviceInfoSet *list;
SP_DEVINSTALL_PARAMS_W InstallParams;
PVOID Buffer = NULL;
- HINF hInf = INVALID_HANDLE_VALUE;
+ struct InfFileDetails *currentInfFileDetails = NULL;
LPWSTR ProviderName = NULL;
LPWSTR ManufacturerName = NULL;
WCHAR ManufacturerSection[LINE_LEN + 1];
@@ -4220,19 +4265,29 @@
GUID ClassGuid;
TRACE("Opening file %S\n", filename);
- hInf = SetupOpenInfFileW(filename, NULL,
INF_STYLE_WIN4, NULL);
- if (hInf == INVALID_HANDLE_VALUE)
+ currentInfFileDetails = HeapAlloc(GetProcessHeap(), 0,
sizeof(struct InfFileDetails));
+ if (!currentInfFileDetails)
continue;
+ memset(currentInfFileDetails, 0, sizeof(struct
InfFileDetails));
+ currentInfFileDetails->hInf =
SetupOpenInfFileW(filename, NULL, INF_STYLE_WIN4, NULL);
+ if (currentInfFileDetails->hInf ==
INVALID_HANDLE_VALUE)
+ {
+ HeapFree(GetProcessHeap(), 0,
currentInfFileDetails);
+ currentInfFileDetails = NULL;
+ continue;
+ }
+
if (!GetVersionInformationFromInfFile(
- hInf,
+ currentInfFileDetails->hInf,
&ClassGuid,
&ProviderName,
&DriverDate,
&DriverVersion))
{
- SetupCloseInfFile(hInf);
- hInf = INVALID_HANDLE_VALUE;
+ SetupCloseInfFile(currentInfFileDetails->hInf);
+ HeapFree(GetProcessHeap(), 0,
currentInfFileDetails->hInf);
+ currentInfFileDetails = NULL;
continue;
}
@@ -4246,7 +4301,7 @@
}
/* Get the manufacturers list */
- Result = SetupFindFirstLineW(hInf, L"Manufacturer",
NULL, &ContextManufacturer);
+ Result =
SetupFindFirstLineW(currentInfFileDetails->hInf, L"Manufacturer", NULL,
&ContextManufacturer);
while (Result)
{
Result = SetupGetStringFieldW(
@@ -4280,11 +4335,11 @@
ManufacturerSection[RequiredSize] = 0; /* Final
NULL char */
/* Add (possible) extension to manufacturer
section name */
Result = SetupDiGetActualSectionToInstallW(
- hInf, ManufacturerSection,
ManufacturerSection, LINE_LEN, NULL, NULL);
+ currentInfFileDetails->hInf,
ManufacturerSection, ManufacturerSection, LINE_LEN, NULL, NULL);
if (Result)
{
TRACE("Enumerating devices in manufacturer
%S\n", ManufacturerSection);
- Result = SetupFindFirstLineW(hInf,
ManufacturerSection, NULL, &ContextDevice);
+ Result =
SetupFindFirstLineW(currentInfFileDetails->hInf, ManufacturerSection,
NULL, &ContextDevice);
}
}
while (Result)
@@ -4297,6 +4352,7 @@
DriverType,
&ClassGuid,
ContextDevice,
+ currentInfFileDetails,
filename,
ProviderName,
ManufacturerName,
@@ -4352,6 +4408,7 @@
DriverType,
&ClassGuid,
ContextDevice,
+ currentInfFileDetails,
filename,
ProviderName,
ManufacturerName,
@@ -4372,6 +4429,7 @@
DriverType,
&ClassGuid,
ContextDevice,
+ currentInfFileDetails,
filename,
ProviderName,
ManufacturerName,
@@ -4398,8 +4456,12 @@
HeapFree(GetProcessHeap(), 0, ProviderName);
ProviderName = NULL;
- SetupCloseInfFile(hInf);
- hInf = INVALID_HANDLE_VALUE;
+ if (currentInfFileDetails->References == 0)
+ {
+ SetupCloseInfFile(currentInfFileDetails->hInf);
+ HeapFree(GetProcessHeap(), 0,
currentInfFileDetails);
+ currentInfFileDetails = NULL;
+ }
}
ret = TRUE;
}
@@ -4425,8 +4487,11 @@
HeapFree(GetProcessHeap(), 0, ManufacturerName);
HeapFree(GetProcessHeap(), 0, HardwareIDs);
HeapFree(GetProcessHeap(), 0, CompatibleIDs);
- if (hInf != INVALID_HANDLE_VALUE)
- SetupCloseInfFile(hInf);
+ if (currentInfFileDetails && currentInfFileDetails->References ==
0)
+ {
+ SetupCloseInfFile(currentInfFileDetails->hInf);
+ HeapFree(GetProcessHeap(), 0, currentInfFileDetails);
+ }
HeapFree(GetProcessHeap(), 0, Buffer);
TRACE("Returning %d\n", ret);
@@ -4505,8 +4570,7 @@
{
ListEntry = RemoveHeadList(&list->DriverListHead);
driverInfo = (struct DriverInfoElement *)ListEntry;
- HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
- HeapFree(GetProcessHeap(), 0, driverInfo);
+ DestroyDriverInfoElement(driverInfo);
}
InstallParams.Reserved = 0;
InstallParams.Flags &= ~(DI_DIDCLASS | DI_MULTMFGS);
@@ -4531,8 +4595,7 @@
InstallParamsSet.Reserved = 0;
SetupDiSetDeviceInstallParamsW(DeviceInfoSet,
NULL, &InstallParamsSet);
}
- HeapFree(GetProcessHeap(), 0, driverInfo->MatchingId);
- HeapFree(GetProcessHeap(), 0, driverInfo);
+ DestroyDriverInfoElement(driverInfo);
}
InstallParams.Reserved = 0;
InstallParams.Flags &= ~DI_DIDCOMPAT;
@@ -5263,7 +5326,6 @@
else
{
SP_DEVINSTALL_PARAMS_W InstallParams;
- HINF hInf = INVALID_HANDLE_VALUE;
struct DriverInfoElement *SelectedDriver;
WCHAR SectionName[MAX_PATH];
DWORD SectionNameLength = 0;
@@ -5280,18 +5342,17 @@
goto cleanup;
}
- hInf = SetupOpenInfFileW(SelectedDriver->Details.InfFileName,
NULL, INF_STYLE_WIN4, NULL);
- if (hInf == INVALID_HANDLE_VALUE)
- goto cleanup;
-
- ret = SetupDiGetActualSectionToInstallW(hInf,
SelectedDriver->Details.SectionName,
+ ret = SetupDiGetActualSectionToInstallW(
+ SelectedDriver->InfFileDetails->hInf,
+ SelectedDriver->Details.SectionName,
SectionName, MAX_PATH, &SectionNameLength, NULL);
if (!ret)
goto cleanup;
if (InstallParams.InstallMsgHandler)
{
- ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
hInf, SectionName,
+ ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
+ SelectedDriver->InfFileDetails->hInf, SectionName,
SPINST_FILES, NULL, NULL, SP_COPY_NEWER,
InstallParams.InstallMsgHandler,
InstallParams.InstallMsgHandlerContext,
DeviceInfoSet, DeviceInfoData);
@@ -5299,15 +5360,14 @@
else
{
PVOID callback_context =
SetupInitDefaultQueueCallback(InstallParams.hwndParent);
- ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
hInf, SectionName,
+ ret = SetupInstallFromInfSectionW(InstallParams.hwndParent,
+ SelectedDriver->InfFileDetails->hInf, SectionName,
SPINST_FILES, NULL, NULL, SP_COPY_NEWER,
SetupDefaultQueueCallbackW, callback_context,
DeviceInfoSet, DeviceInfoData);
SetupTermDefaultQueueCallback(callback_context);
}
cleanup:
- if (hInf != INVALID_HANDLE_VALUE)
- SetupCloseInfFile(hInf);
if (ret)
{
InstallParams.Flags |= DI_NOFILECOPY;
@@ -5371,10 +5431,9 @@
INT Flags;
ULONG DoAction;
DWORD RequiredSize;
- HINF hInf = INVALID_HANDLE_VALUE;
LPCWSTR AssociatedService = NULL;
LPWSTR pSectionName = NULL;
- LPWSTR ClassName = NULL;
+ WCHAR ClassName[MAX_CLASS_NAME_LEN];
GUID ClassGuid;
LPWSTR lpGuidString = NULL, lpFullGuidString = NULL;
BOOL RebootRequired = FALSE;
@@ -5422,32 +5481,17 @@
FileTimeToSystemTime(&SelectedDriver->Info.DriverDate,
&DriverDate);
- hInf = SetupOpenInfFileW(SelectedDriver->Details.InfFileName, NULL,
INF_STYLE_WIN4, NULL);
- if (hInf == INVALID_HANDLE_VALUE)
- goto cleanup;
-
- Result = SetupDiGetActualSectionToInstallW(hInf,
SelectedDriver->Details.SectionName,
+ Result = SetupDiGetActualSectionToInstallW(
+ SelectedDriver->InfFileDetails->hInf,
+ SelectedDriver->Details.SectionName,
SectionName, MAX_PATH, &SectionNameLength, NULL);
if (!Result || SectionNameLength > MAX_PATH - 9)
goto cleanup;
pSectionName = &SectionName[wcslen(SectionName)];
/* Get information from [Version] section */
- ClassName = NULL;
- RequiredSize = 0;
- if (!SetupDiGetINFClassW(SelectedDriver->Details.InfFileName,
&ClassGuid, ClassName, RequiredSize, &RequiredSize))
- {
- if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
- goto cleanup;
- ClassName = HeapAlloc(GetProcessHeap(), 0, RequiredSize *
sizeof(WCHAR));
- if (!ClassName)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto cleanup;
- }
- if (!SetupDiGetINFClassW(SelectedDriver->Details.InfFileName,
&ClassGuid, ClassName, RequiredSize, &RequiredSize))
- goto cleanup;
- }
+ if (!SetupDiGetINFClassW(SelectedDriver->Details.InfFileName,
&ClassGuid, ClassName, MAX_CLASS_NAME_LEN, &RequiredSize))
+ goto cleanup;
/* Format ClassGuid to a string */
if (UuidToStringW((UUID*)&ClassGuid, &lpGuidString) != RPC_S_OK)
goto cleanup;
@@ -5481,7 +5525,8 @@
/* Files have already been copied in SetupDiInstallDriverFiles.
* Process only registry entries. */
*pSectionName = '\0';
- Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
hInf, SectionName,
+ Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
+ SelectedDriver->InfFileDetails->hInf, SectionName,
DoAction, hKey, NULL, SP_COPY_NEWER,
InstallParams.InstallMsgHandler,
InstallParams.InstallMsgHandlerContext,
DeviceInfoSet, DeviceInfoData);
@@ -5541,7 +5586,7 @@
/* Install .Services section */
wcscpy(pSectionName, L".Services");
- Result = SetupFindFirstLineW(hInf, SectionName, NULL,
&ContextService);
+ Result = SetupFindFirstLineW(SelectedDriver->InfFileDetails->hInf,
SectionName, NULL, &ContextService);
while (Result)
{
LPWSTR ServiceName = NULL;
@@ -5600,12 +5645,14 @@
&ContextService,
3, /* Field index */
ServiceSection, RequiredSize,
- &RequiredSize);
+ &RequiredSize);
if (!Result)
- goto nextfile;
+ goto nextfile;
}
SetLastError(ERROR_SUCCESS);
- Result = SetupInstallServicesFromInfSectionExW(hInf,
ServiceSection, Flags, DeviceInfoSet, DeviceInfoData, ServiceName,
NULL);
+ Result = SetupInstallServicesFromInfSectionExW(
+ SelectedDriver->InfFileDetails->hInf,
+ ServiceSection, Flags, DeviceInfoSet, DeviceInfoData,
ServiceName, NULL);
if (Result && (Flags & SPSVCINST_ASSOCSERVICE))
{
AssociatedService = ServiceName;
@@ -5631,7 +5678,8 @@
/* Install .HW section */
wcscpy(pSectionName, L".HW");
- Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
hInf, SectionName,
+ Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
+ SelectedDriver->InfFileDetails->hInf, SectionName,
SPINST_REGISTRY, hKey, NULL, 0,
InstallParams.InstallMsgHandler,
InstallParams.InstallMsgHandlerContext,
DeviceInfoSet, DeviceInfoData);
@@ -5681,10 +5729,7 @@
if (lpGuidString)
RpcStringFreeW(&lpGuidString);
HeapFree(GetProcessHeap(), 0, (LPWSTR)AssociatedService);
- HeapFree(GetProcessHeap(), 0, ClassName);
HeapFree(GetProcessHeap(), 0, lpFullGuidString);
- if (hInf != INVALID_HANDLE_VALUE)
- SetupCloseInfFile(hInf);
TRACE("Returning %d\n", ret);
return ret;