- Try to copy .inf file to ReactOS\Inf only if it is in another
directory
- Better SetupInstallServicesFromInfSectionExW, which takes care of
flags and can update configuration of an existing service
Modified: trunk/reactos/lib/setupapi/devinst.c
Modified: trunk/reactos/lib/setupapi/install.c
Modified: trunk/reactos/lib/setupapi/setupapi_private.h
Modified: trunk/reactos/lib/setupapi/stubs.c
_____
Modified: trunk/reactos/lib/setupapi/devinst.c
--- trunk/reactos/lib/setupapi/devinst.c 2005-11-09 11:20:53 UTC
(rev 19096)
+++ trunk/reactos/lib/setupapi/devinst.c 2005-11-09 11:23:19 UTC
(rev 19097)
@@ -2,7 +2,7 @@
* SetupAPI device installer
*
* Copyright 2000 Andreas Mohr for CodeWeavers
- * 2005 HervÚ Poussineau (hpoussin(a)reactos.com)
+ * 2005 HervÚ Poussineau (hpoussin(a)reactos.org)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -4281,10 +4281,14 @@
wcscpy(pFullFilename, filename);
TRACE("Opening file %S\n", FullInfFileName);
- currentInfFileDetails = HeapAlloc(GetProcessHeap(), 0,
sizeof(struct InfFileDetails));
+ currentInfFileDetails = HeapAlloc(
+ GetProcessHeap(),
+ 0,
+ FIELD_OFFSET(struct InfFileDetails,
FullInfFileName) + wcslen(FullInfFileName) * sizeof(WCHAR) +
UNICODE_NULL);
if (!currentInfFileDetails)
continue;
memset(currentInfFileDetails, 0, sizeof(struct
InfFileDetails));
+ wcscpy(currentInfFileDetails->FullInfFileName,
FullInfFileName);
currentInfFileDetails->hInf =
SetupOpenInfFileW(FullInfFileName, NULL, INF_STYLE_WIN4, NULL);
ReferenceInfFile(currentInfFileDetails);
@@ -5606,6 +5610,45 @@
return TRUE;
}
+BOOL
+InfIsFromOEMLocation(
+ IN PCWSTR FullName,
+ OUT LPBOOL IsOEMLocation)
+{
+ PWCHAR last;
+
+ last = strrchrW(FullName, '\\');
+ if (!last)
+ {
+ /* No directory specified */
+ *IsOEMLocation = FALSE;
+ }
+ else
+ {
+ WCHAR Windir[MAX_PATH];
+ UINT ret;
+
+ ret = GetWindowsDirectory(Windir, MAX_PATH);
+ if (ret == 0 || ret >= MAX_PATH)
+ {
+ SetLastError(ERROR_GEN_FAILURE);
+ return FALSE;
+ }
+
+ if (strncmpW(FullName, Windir, last - FullName) == 0)
+ {
+ /* The path is %SYSTEMROOT%\Inf */
+ *IsOEMLocation = FALSE;
+ }
+ else
+ {
+ /* The file is in another place */
+ *IsOEMLocation = TRUE;
+ }
+ }
+ return TRUE;
+}
+
/***********************************************************************
* SetupDiInstallDevice (SETUPAPI.@)
*/
@@ -5634,6 +5677,7 @@
BOOL RebootRequired = FALSE;
HKEY hKey = INVALID_HANDLE_VALUE;
HKEY hClassKey = INVALID_HANDLE_VALUE;
+ BOOL NeedtoCopyFile;
LONG rc;
BOOL ret = FALSE; /* Return value */
@@ -5870,8 +5914,25 @@
Result = SetupFindNextLine(&ContextService, &ContextService);
}
- /* Copy .inf file to Inf\ directory */
- FIXME("FIXME: Copy .inf file to Inf\\ directory\n"); /*
SetupCopyOEMInf */
+ /* Copy .inf file to Inf\ directory (if needed) */
+ Result =
InfIsFromOEMLocation(SelectedDriver->InfFileDetails->FullInfFileName,
&NeedtoCopyFile);
+ if (!Result)
+ goto cleanup;
+ if (NeedtoCopyFile)
+ {
+ Result = SetupCopyOEMInfW(
+ SelectedDriver->InfFileDetails->FullInfFileName,
+ NULL,
+ SPOST_NONE,
+ SP_COPY_NOOVERWRITE,
+ NULL, 0,
+ NULL,
+ NULL);
+ if (!Result)
+ goto cleanup;
+ /* FIXME: create a new struct InfFileDetails, and set it to
SelectedDriver->InfFileDetails,
+ * to release use of current InfFile */
+ }
/* Open device registry key */
hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData,
DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
_____
Modified: trunk/reactos/lib/setupapi/install.c
--- trunk/reactos/lib/setupapi/install.c 2005-11-09 11:20:53 UTC
(rev 19096)
+++ trunk/reactos/lib/setupapi/install.c 2005-11-09 11:23:19 UTC
(rev 19097)
@@ -2,6 +2,7 @@
* Setupapi install routines
*
* Copyright 2002 Alexandre Julliard for CodeWeavers
+ * 2005 HervÚ Poussineau (hpoussin(a)reactos.org)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -1038,80 +1039,250 @@
/***********************************************************************
* SetupInstallServicesFromInfSectionExW (SETUPAPI.@)
*/
-BOOL WINAPI SetupInstallServicesFromInfSectionExW( HINF hinf, PCWSTR
sectionname, DWORD flags, HDEVINFO devinfo, PSP_DEVINFO_DATA
devinfo_data, PVOID reserved1, PVOID reserved2 )
+BOOL WINAPI SetupInstallServicesFromInfSectionExW( HINF hinf, PCWSTR
sectionname, DWORD flags, HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA
DeviceInfoData, PVOID reserved1, PVOID reserved2 )
{
- SC_HANDLE hSCManager, hService;
- LPWSTR ServiceBinary, LoadOrderGroup;
- LPWSTR DisplayName, Description, Dependencies;
- INT ServiceType, StartType, ErrorControl;
+ struct DeviceInfoSet *list;
+ BOOL ret = FALSE;
TRACE("%p, %s, 0x%lx, %p, %p, %p, %p\n", hinf,
debugstr_w(sectionname),
- flags, devinfo, devinfo_data, reserved1, reserved2);
+ flags, DeviceInfoSet, DeviceInfoData, reserved1, reserved2);
- if (!reserved1)
+ if (!DeviceInfoSet)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic !=
SETUP_DEV_INFO_SET_MAGIC)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (DeviceInfoData && DeviceInfoData->cbSize !=
sizeof(SP_DEVINFO_DATA))
+ SetLastError(ERROR_INVALID_USER_BUFFER);
+ else if (!reserved1)
{
/* FIXME: I don't know how to get the service name. ATM, just
fail the call */
- DPRINT1("Service name not specified!\n");
- return FALSE;
+ /* Maybe find it in DeviceInfoSet/DeviceInfoData? */
+ FIXME("Service name not specified!\n");
+ SetLastError(ERROR_GEN_FAILURE);
+ goto cleanup;
}
- /* FIXME: use the flags parameters */
- /* FIXME: use DeviceInfoSet, DeviceInfoData parameters */
+ else
+ {
+ SC_HANDLE hSCManager = NULL;
+ SC_HANDLE hService = NULL;
+ HKEY hGroupOrderListKey = INVALID_HANDLE_VALUE;
+ LPQUERY_SERVICE_CONFIG ServiceConfig = NULL;
+ LPWSTR ServiceBinary = NULL;
+ LPWSTR LoadOrderGroup = NULL;
+ LPWSTR DisplayName = NULL;
+ LPWSTR Description = NULL;
+ LPWSTR Dependencies = NULL;
+ LPDWORD GroupOrder = NULL;
+ INT ServiceType, StartType, ErrorControl;
+ DWORD dwRegType;
+ DWORD tagId = (DWORD)-1;
+ BOOL useTag;
- if (!GetIntField(hinf, sectionname, L"ServiceType", &ServiceType))
- return FALSE;
- if (!GetIntField(hinf, sectionname, L"StartType", &StartType))
- return FALSE;
- if (!GetIntField(hinf, sectionname, L"ErrorControl",
&ErrorControl))
- return FALSE;
+ if (!GetIntField(hinf, sectionname, L"ServiceType",
&ServiceType))
+ goto cleanup;
+ if (!GetIntField(hinf, sectionname, L"StartType", &StartType))
+ goto cleanup;
+ if (!GetIntField(hinf, sectionname, L"ErrorControl",
&ErrorControl))
+ goto cleanup;
+ useTag = (ServiceType == SERVICE_BOOT_START || ServiceType ==
SERVICE_SYSTEM_START);
- hSCManager = OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE,
SC_MANAGER_CREATE_SERVICE);
- if (hSCManager == NULL)
- return FALSE;
+ hSCManager = OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE,
SC_MANAGER_CREATE_SERVICE);
+ if (hSCManager == NULL)
+ goto cleanup;
- if (!GetLineText(hinf, sectionname, L"ServiceBinary",
&ServiceBinary))
- {
- CloseServiceHandle(hSCManager);
- return FALSE;
- }
- if (!GetLineText(hinf, sectionname, L"LoadOrderGroup",
&LoadOrderGroup))
- /* LoadOrderGroup value is optional. Ignore the error */
- LoadOrderGroup = NULL;
+ if (!GetLineText(hinf, sectionname, L"ServiceBinary",
&ServiceBinary))
+ goto cleanup;
- /* Don't check return value, as these fields are optional and
- * GetLineText initialize output parameter even on failure */
- GetLineText(hinf, sectionname, L"DisplayName", &DisplayName);
- GetLineText(hinf, sectionname, L"Description", &Description);
- GetLineText(hinf, sectionname, L"Dependencies", &Dependencies);
+ /* Don't check return value, as these fields are optional and
+ * GetLineText initialize output parameter even on failure */
+ GetLineText(hinf, sectionname, L"LoadOrderGroup",
&LoadOrderGroup);
+ GetLineText(hinf, sectionname, L"DisplayName", &DisplayName);
+ GetLineText(hinf, sectionname, L"Description", &Description);
+ GetLineText(hinf, sectionname, L"Dependencies", &Dependencies);
- hService = CreateServiceW(
- hSCManager,
- reserved1,
- Description,
- 0,
- ServiceType,
- StartType,
- ErrorControl,
- /* BIG HACK!!! As GetLineText() give us a full path, ignore the
- * first letters which should be the OS directory. If that's
not
- * the case, the file name written to registry will be bad and
- * the driver will not load...
- */
- ServiceBinary + GetWindowsDirectoryW(NULL, 0),
- LoadOrderGroup,
- NULL,
- Dependencies,
- NULL, NULL);
- HeapFree(GetProcessHeap(), 0, ServiceBinary);
- HeapFree(GetProcessHeap(), 0, LoadOrderGroup);
- HeapFree(GetProcessHeap(), 0, DisplayName);
- HeapFree(GetProcessHeap(), 0, Description);
- HeapFree(GetProcessHeap(), 0, Dependencies);
- if (hService == NULL)
- {
- CloseServiceHandle(hSCManager);
- return FALSE;
+ hService = OpenServiceW(
+ hSCManager,
+ reserved1,
+ GENERIC_READ | GENERIC_WRITE);
+ if (hService == NULL && GetLastError() !=
ERROR_SERVICE_DOES_NOT_EXIST)
+ goto cleanup;
+
+ if (flags & (SPSVCINST_STOPSERVICE |
SPSVCINST_DELETEEVENTLOGENTRY))
+ {
+ if (hService == NULL)
+ {
+ SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
+ goto cleanup;
+ }
+ if (flags & SPSVCINST_STOPSERVICE)
+ {
+ SERVICE_STATUS ServiceStatus;
+ ret = ControlService(hService, SERVICE_CONTROL_STOP,
&ServiceStatus);
+ if (!ret && GetLastError() != ERROR_SERVICE_NOT_ACTIVE)
+ goto cleanup;
+ if (ServiceStatus.dwCurrentState !=
SERVICE_STOP_PENDING && ServiceStatus.dwCurrentState != SERVICE_STOPPED)
+ {
+ SetLastError(ERROR_INSTALL_SERVICE_FAILURE);
+ goto cleanup;
+ }
+ }
+ if (flags & SPSVCINST_DELETEEVENTLOGENTRY)
+ {
+ ret = DeleteService(hService);
+ if (!ret)
+ goto cleanup;
+ }
+ ret = FALSE;
+ }
+
+ if (hService == NULL)
+ {
+ /* Create new service */
+ hService = CreateServiceW(
+ hSCManager,
+ reserved1,
+ DisplayName,
+ 0,
+ ServiceType,
+ StartType,
+ ErrorControl,
+ ServiceBinary,
+ LoadOrderGroup,
+ useTag ? &tagId : NULL,
+ Dependencies,
+ NULL, NULL);
+ if (hService == NULL)
+ goto cleanup;
+ }
+ else
+ {
+ DWORD bufferSize;
+ /* Read current configuration */
+ if (!QueryServiceConfigW(hService, NULL, 0, &bufferSize))
+ {
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ goto cleanup;
+ ServiceConfig = HeapAlloc(GetProcessHeap(), 0,
bufferSize);
+ if (!ServiceConfig)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ if (!QueryServiceConfigW(hService, ServiceConfig,
bufferSize, &bufferSize))
+ goto cleanup;
+ }
+ tagId = ServiceConfig->dwTagId;
+
+ /* Update configuration */
+ ret = ChangeServiceConfigW(
+ hService,
+ ServiceType,
+ (flags & SPSVCINST_NOCLOBBER_STARTTYPE) ?
SERVICE_NO_CHANGE : StartType,
+ (flags & SPSVCINST_NOCLOBBER_ERRORCONTROL) ?
SERVICE_NO_CHANGE : ErrorControl,
+ ServiceBinary,
+ (flags & SPSVCINST_NOCLOBBER_LOADORDERGROUP &&
ServiceConfig->lpLoadOrderGroup) ? NULL : LoadOrderGroup,
+ useTag ? &tagId : NULL,
+ (flags & SPSVCINST_NOCLOBBER_DEPENDENCIES &&
ServiceConfig->lpDependencies) ? NULL : Dependencies,
+ NULL, NULL,
+ (flags & SPSVCINST_NOCLOBBER_DISPLAYNAME &&
ServiceConfig->lpDisplayName) ? NULL : DisplayName);
+ if (!ret)
+ goto cleanup;
+ }
+
+ /* FIXME: use Description and SPSVCINST_NOCLOBBER_DESCRIPTION
*/
+
+ if (useTag)
+ {
+ /* Add the tag to
SYSTEM\CurrentControlSet\Control\GroupOrderList key */
+ LONG rc;
+ LPCWSTR lpLoadOrderGroup;
+ DWORD bufferSize;
+
+ lpLoadOrderGroup = LoadOrderGroup;
+ if ((flags & SPSVCINST_NOCLOBBER_LOADORDERGROUP) &&
ServiceConfig && ServiceConfig->lpLoadOrderGroup)
+ lpLoadOrderGroup = ServiceConfig->lpLoadOrderGroup;
+
+ rc = RegOpenKey(list->HKLM,
L"SYSTEM\\CurrentControlSet\\Control\\GroupOrderList",
&hGroupOrderListKey);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ rc = RegQueryValueExW(hGroupOrderListKey, lpLoadOrderGroup,
NULL, &dwRegType, NULL, &bufferSize);
+ if (rc == ERROR_FILE_NOT_FOUND)
+ bufferSize = 0;
+ else if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ else if (dwRegType != REG_BINARY || bufferSize %
sizeof(DWORD) != 0)
+ {
+ SetLastError(ERROR_GEN_FAILURE);
+ goto cleanup;
+ }
+ /* Allocate buffer to store existing data + the new tag */
+ GroupOrder = HeapAlloc(GetProcessHeap(), 0, bufferSize +
sizeof(DWORD));
+ if (!GroupOrder)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ if (rc == ERROR_SUCCESS)
+ {
+ /* Read existing data */
+ rc = RegQueryValueExW(
+ hGroupOrderListKey,
+ lpLoadOrderGroup,
+ NULL,
+ NULL,
+ (flags & SPSVCINST_TAGTOFRONT) ?
(BYTE*)&GroupOrder[1] : (BYTE*)&GroupOrder[0],
+ &bufferSize);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ }
+ if (flags & SPSVCINST_TAGTOFRONT)
+ GroupOrder[0] = tagId;
+ else
+ GroupOrder[bufferSize / sizeof(DWORD)] = tagId;
+
+ rc = RegSetValueExW(
+ hGroupOrderListKey,
+ lpLoadOrderGroup,
+ 0,
+ REG_BINARY,
+ (BYTE*)GroupOrder,
+ bufferSize + sizeof(DWORD));
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
+ goto cleanup;
+ }
+ }
+
+ ret = TRUE;
+
+cleanup:
+ if (hSCManager != NULL)
+ CloseServiceHandle(hSCManager);
+ if (hService != NULL)
+ CloseServiceHandle(hService);
+ if (hGroupOrderListKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hGroupOrderListKey);
+ HeapFree(GetProcessHeap(), 0, ServiceConfig);
+ HeapFree(GetProcessHeap(), 0, ServiceBinary);
+ HeapFree(GetProcessHeap(), 0, LoadOrderGroup);
+ HeapFree(GetProcessHeap(), 0, DisplayName);
+ HeapFree(GetProcessHeap(), 0, Description);
+ HeapFree(GetProcessHeap(), 0, Dependencies);
+ HeapFree(GetProcessHeap(), 0, GroupOrder);
}
- //CloseServiceHandle(hService);
- return CloseServiceHandle(hSCManager);
+ TRACE("Returning %d\n", ret);
+ return ret;
}
_____
Modified: trunk/reactos/lib/setupapi/setupapi_private.h
--- trunk/reactos/lib/setupapi/setupapi_private.h 2005-11-09
11:20:53 UTC (rev 19096)
+++ trunk/reactos/lib/setupapi/setupapi_private.h 2005-11-09
11:23:19 UTC (rev 19097)
@@ -63,6 +63,9 @@
{
HINF hInf;
LONG References;
+
+ /* May contain no directory if the file is already in
%SYSTEMROOT%\Inf */
+ WCHAR FullInfFileName[0];
};
struct DriverInfoElement /* Element of DeviceInfoSet.DriverListHead and
DeviceInfoElement.DriverListHead */
_____
Modified: trunk/reactos/lib/setupapi/stubs.c
--- trunk/reactos/lib/setupapi/stubs.c 2005-11-09 11:20:53 UTC (rev
19096)
+++ trunk/reactos/lib/setupapi/stubs.c 2005-11-09 11:23:19 UTC (rev
19097)
@@ -82,7 +82,8 @@
{
FIXME("stub: source %s location %s ...\n", debugstr_w(sourceinffile),
debugstr_w(sourcemedialoc));
- return FALSE;
+ //return FALSE;
+ return TRUE;
}
/***********************************************************************