- Fix horribly broken implementation of
SetupInstallServicesFromInfSectionExW, which should install a whole
Services section and not a particular service.
- Simplify handling of Include and Needs directives
Modified: trunk/reactos/lib/setupapi/devinst.c
Modified: trunk/reactos/lib/setupapi/install.c
_____
Modified: trunk/reactos/lib/setupapi/devinst.c
--- trunk/reactos/lib/setupapi/devinst.c 2005-12-20 23:54:21 UTC
(rev 20282)
+++ trunk/reactos/lib/setupapi/devinst.c 2005-12-21 12:28:55 UTC
(rev 20283)
@@ -3174,182 +3174,6 @@
}
-static BOOL
-InstallServicesSection(
- IN HINF hInf,
- IN PCWSTR SectionName,
- IN HDEVINFO DeviceInfoSet OPTIONAL,
- IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
- OUT PCWSTR* pAssociatedService OPTIONAL,
- OUT PBOOL pRebootRequired OPTIONAL)
-{
- INFCONTEXT ContextService;
- INFCONTEXT ContextInclude;
- DWORD RequiredSize;
- INT Flags;
- BOOL ret = FALSE;
-
- /* Parse 'Include' line */
- if (SetupFindFirstLineW(hInf, SectionName, L"Include",
&ContextInclude))
- {
- DWORD Index = 1;
- while (TRUE)
- {
- static WCHAR szBuffer[MAX_PATH];
- PWSTR pBuffer = NULL;
- DWORD required;
-
- ret = SetupGetStringFieldW(&ContextInclude, Index,
szBuffer, MAX_PATH, &required);
- if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
- break;
- else if (!ret && GetLastError() ==
ERROR_INSUFFICIENT_BUFFER)
- {
- pBuffer = MyMalloc(required);
- ret = SetupGetStringFieldW(&ContextInclude, Index,
pBuffer, required, &required);
- }
- if (ret)
- ret = SetupOpenAppendInfFileW(pBuffer ? pBuffer :
szBuffer, hInf, NULL);
-
- MyFree(pBuffer);
- if (!ret)
- goto done;
- Index++;
- }
- }
-
- /* Parse 'Needs' line */
- if (SetupFindFirstLineW(hInf, SectionName, L"Needs",
&ContextInclude))
- {
- DWORD Index = 1;
- while (TRUE)
- {
- static WCHAR szBuffer[MAX_PATH];
- PWSTR pBuffer = NULL;
- DWORD required;
-
- ret = SetupGetStringFieldW(&ContextInclude, Index,
szBuffer, MAX_PATH, &required);
- if (!ret && GetLastError() == ERROR_INVALID_PARAMETER)
- break;
- else if (!ret && GetLastError() ==
ERROR_INSUFFICIENT_BUFFER)
- {
- pBuffer = MyMalloc(required);
- ret = SetupGetStringFieldW(&ContextInclude, Index,
pBuffer, required, &required);
- }
- if (ret)
- {
- ret = InstallServicesSection(hInf, pBuffer ? pBuffer :
szBuffer,
- DeviceInfoSet, DeviceInfoData, pAssociatedService,
pRebootRequired);
- }
-
- MyFree(pBuffer);
- if (!ret)
- goto done;
- Index++;
- }
- }
-
- ret = SetupFindFirstLineW(hInf, SectionName, NULL,
&ContextService);
- while (ret)
- {
- LPWSTR ServiceName = NULL;
- LPWSTR ServiceSection = NULL;
-
- ret = SetupGetStringFieldW(
- &ContextService,
- 1, /* Field index */
- NULL, 0,
- &RequiredSize);
- if (!ret)
- goto nextservice;
- if (RequiredSize > 0)
- {
- /* We got the needed size for the buffer */
- ServiceName = HeapAlloc(GetProcessHeap(), 0, RequiredSize *
sizeof(WCHAR));
- if (!ServiceName)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto nextservice;
- }
- ret = SetupGetStringFieldW(
- &ContextService,
- 1, /* Field index */
- ServiceName, RequiredSize,
- &RequiredSize);
- if (!ret)
- goto nextservice;
- }
- ret = SetupGetIntField(
- &ContextService,
- 2, /* Field index */
- &Flags);
- if (!ret)
- {
- /* The field may be empty. Ignore the error */
- Flags = 0;
- }
- ret = SetupGetStringFieldW(
- &ContextService,
- 3, /* Field index */
- NULL, 0,
- &RequiredSize);
- if (!ret)
- {
- if (GetLastError() == ERROR_INVALID_PARAMETER)
- {
- /* This first is probably missing. It is not
- * required, so ignore the error */
- RequiredSize = 0;
- ret = TRUE;
- }
- else
- goto nextservice;
- }
- if (RequiredSize > 0)
- {
- /* We got the needed size for the buffer */
- ServiceSection = HeapAlloc(GetProcessHeap(), 0,
RequiredSize * sizeof(WCHAR));
- if (!ServiceSection)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto nextservice;
- }
- ret = SetupGetStringFieldW(
- &ContextService,
- 3, /* Field index */
- ServiceSection, RequiredSize,
- &RequiredSize);
- if (!ret)
- goto nextservice;
-
- SetLastError(ERROR_SUCCESS);
- ret = SetupInstallServicesFromInfSectionExW(
- hInf,
- ServiceSection, Flags, DeviceInfoSet, DeviceInfoData,
ServiceName, NULL);
- }
- if (ret && (Flags & SPSVCINST_ASSOCSERVICE))
- {
- if (pAssociatedService)
- {
- *pAssociatedService = ServiceName;
- ServiceName = NULL;
- }
- if (pRebootRequired && GetLastError() ==
ERROR_SUCCESS_REBOOT_REQUIRED)
- *pRebootRequired = TRUE;
- }
-nextservice:
- HeapFree(GetProcessHeap(), 0, ServiceName);
- HeapFree(GetProcessHeap(), 0, ServiceSection);
- if (!ret)
- goto done;
- ret = SetupFindNextLine(&ContextService, &ContextService);
- }
-
- ret = TRUE;
-
-done:
- return ret;
-}
-
/***********************************************************************
* SetupDiInstallClassExW (SETUPAPI.@)
*/
@@ -3451,7 +3275,7 @@
/* Install .Services section */
lstrcatW(SectionName, DotServices);
- ret = InstallServicesSection(hInf, SectionName, NULL, NULL,
NULL, NULL);
+ ret = SetupInstallServicesFromInfSectionW(hInf,
SectionName, 0);
if (!ret)
goto cleanup;
@@ -5585,8 +5409,6 @@
SetLastError(ERROR_INVALID_HANDLE);
else if (DriverType != SPDIT_CLASSDRIVER && DriverType !=
SPDIT_COMPATDRIVER)
SetLastError(ERROR_INVALID_PARAMETER);
- else if (DriverType == SPDIT_CLASSDRIVER && DeviceInfoData)
- SetLastError(ERROR_INVALID_PARAMETER);
else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
SetLastError(ERROR_INVALID_PARAMETER);
else if (DeviceInfoData && DeviceInfoData->cbSize !=
sizeof(SP_DEVINFO_DATA))
@@ -7404,7 +7226,6 @@
BOOL Result = FALSE;
ULONG DoAction;
DWORD RequiredSize;
- LPCWSTR AssociatedService = NULL;
LPWSTR pSectionName = NULL;
WCHAR ClassName[MAX_CLASS_NAME_LEN];
GUID ClassGuid;
@@ -7569,15 +7390,18 @@
/* Install .Services section */
wcscpy(pSectionName, DotServices);
- Result = InstallServicesSection(
+ Result = SetupInstallServicesFromInfSectionExW(
SelectedDriver->InfFileDetails->hInf,
SectionName,
+ 0,
DeviceInfoSet,
DeviceInfoData,
- &AssociatedService,
- &RebootRequired);
+ NULL,
+ NULL);
if (!Result)
goto cleanup;
+ if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED)
+ RebootRequired = TRUE;
/* Copy .inf file to Inf\ directory (if needed) */
Result =
InfIsFromOEMLocation(SelectedDriver->InfFileDetails->FullInfFileName,
&NeedtoCopyFile);
@@ -7620,7 +7444,6 @@
TRACE("ClassGUID : '%S'\n", lpFullGuidString);
TRACE("DeviceDesc : '%S'\n",
SelectedDriver->Info.Description);
TRACE("Mfg : '%S'\n",
SelectedDriver->Info.MfgName);
- TRACE("Service : '%S'\n", AssociatedService);
rc = RegSetValueEx(hKey, REGSTR_VAL_CLASS, 0, REG_SZ, (const BYTE
*)ClassName, (wcslen(ClassName) + 1) * sizeof(WCHAR));
if (rc == ERROR_SUCCESS)
rc = RegSetValueEx(hKey, REGSTR_VAL_CLASSGUID, 0, REG_SZ,
(const BYTE *)lpFullGuidString, (wcslen(lpFullGuidString) + 1) *
sizeof(WCHAR));
@@ -7628,8 +7451,6 @@
rc = RegSetValueEx(hKey, REGSTR_VAL_DEVDESC, 0, REG_SZ, (const
BYTE *)SelectedDriver->Info.Description,
(wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
if (rc == ERROR_SUCCESS)
rc = RegSetValueEx(hKey, REGSTR_VAL_MFG, 0, REG_SZ, (const BYTE
*)SelectedDriver->Info.MfgName, (wcslen(SelectedDriver->Info.MfgName) +
1) * sizeof(WCHAR));
- if (rc == ERROR_SUCCESS && AssociatedService && *AssociatedService)
- rc = RegSetValueEx(hKey, REGSTR_VAL_SERVICE, 0, REG_SZ, (const
BYTE *)AssociatedService, (wcslen(AssociatedService) + 1) *
sizeof(WCHAR));
if (rc != ERROR_SUCCESS)
{
SetLastError(rc);
@@ -7650,7 +7471,6 @@
RegCloseKey(hKey);
if (lpGuidString)
RpcStringFreeW(&lpGuidString);
- HeapFree(GetProcessHeap(), 0, (LPWSTR)AssociatedService);
HeapFree(GetProcessHeap(), 0, lpFullGuidString);
TRACE("Returning %d\n", ret);
_____
Modified: trunk/reactos/lib/setupapi/install.c
--- trunk/reactos/lib/setupapi/install.c 2005-12-20 23:54:21 UTC
(rev 20282)
+++ trunk/reactos/lib/setupapi/install.c 2005-12-21 12:28:55 UTC
(rev 20283)
@@ -47,9 +47,28 @@
BOOL unregister;
};
+/* info passed to callback functions dealing with Needs directives */
+struct needs_callback_info
+{
+ UINT type;
+
+ HWND owner;
+ UINT flags;
+ HKEY key_root;
+ LPCWSTR src_root;
+ UINT copy_flags;
+ PVOID callback;
+ PVOID context;
+ HDEVINFO devinfo;
+ PSP_DEVINFO_DATA devinfo_data;
+ PVOID reserved1;
+ PVOID reserved2;
+};
+
typedef BOOL (*iterate_fields_func)( HINF hinf, PCWSTR field, void *arg
);
/* Unicode constants */
+static const WCHAR AddService[] =
{'A','d','d','S','e','r','v','i','c','e',0};
static const WCHAR CopyFiles[] =
{'C','o','p','y','F','i','l','e','s',0};
static const WCHAR DelFiles[] =
{'D','e','l','F','i','l','e','s',0};
static const WCHAR RenFiles[] =
{'R','e','n','F','i','l','e','s',0};
@@ -784,73 +803,64 @@
/***********************************************************************
- * SetupInstallFromInfSectionW (SETUPAPI.@)
+ * include_callback
+ *
+ * Called once for each Include entry in a given section.
*/
-BOOL WINAPI SetupInstallFromInfSectionW( HWND owner, HINF hinf, PCWSTR
section, UINT flags,
- HKEY key_root, PCWSTR
src_root, UINT copy_flags,
- PSP_FILE_CALLBACK_W callback,
PVOID context,
- HDEVINFO devinfo,
PSP_DEVINFO_DATA devinfo_data )
+static BOOL include_callback( HINF hinf, PCWSTR field, void *arg )
{
- INFCONTEXT include_context;
+ return SetupOpenAppendInfFileW( field, hinf, NULL );
+}
- /* Parse 'Include' line */
- if (SetupFindFirstLineW( hinf, section, Include, &include_context
))
- {
- DWORD index = 1;
- while (TRUE)
- {
- static WCHAR szBuffer[MAX_PATH];
- PWSTR pBuffer = NULL;
- DWORD required;
- BOOL ok;
- ok = SetupGetStringFieldW( &include_context, index,
szBuffer, MAX_PATH, &required );
- if (!ok && GetLastError() == ERROR_INVALID_PARAMETER)
- break;
- else if (!ok && GetLastError() ==
ERROR_INSUFFICIENT_BUFFER)
- {
- pBuffer = MyMalloc(required);
- ok = SetupGetStringFieldW( &include_context, index,
pBuffer, required, &required );
- }
- if (ok)
- ok = SetupOpenAppendInfFileW( pBuffer ? pBuffer :
szBuffer, hinf, NULL );
+/**********************************************************************
*
+ * needs_callback
+ *
+ * Called once for each Needs entry in a given section.
+ */
+static BOOL needs_callback( HINF hinf, PCWSTR field, void *arg )
+{
+ struct needs_callback_info *info = arg;
- MyFree(pBuffer);
- if (!ok) return FALSE;
- index++;
- }
+ switch (info->type)
+ {
+ case 0:
+ return SetupInstallFromInfSectionW(info->owner, hinf,
field, info->flags,
+ info->key_root, info->src_root, info->copy_flags,
info->callback,
+ info->context, info->devinfo, info->devinfo_data);
+ case 1:
+ return SetupInstallServicesFromInfSectionExW(hinf, field,
info->flags,
+ info->devinfo, info->devinfo_data, info->reserved1,
info->reserved2);
+ default:
+ ERR("Unknown info type %ld\n", info->type);
+ return FALSE;
}
+}
- /* Parse 'Needs' line */
- if (SetupFindFirstLineW( hinf, section, Needs, &include_context ))
- {
- DWORD index = 1;
- while (TRUE)
- {
- static WCHAR szBuffer[MAX_PATH];
- PWSTR pBuffer = NULL;
- DWORD required;
- BOOL ok;
- ok = SetupGetStringFieldW( &include_context, index,
szBuffer, MAX_PATH, &required );
- if (!ok && GetLastError() == ERROR_INVALID_PARAMETER)
- break;
- else if (!ok && GetLastError() ==
ERROR_INSUFFICIENT_BUFFER)
- {
- pBuffer = MyMalloc(required);
- ok = SetupGetStringFieldW( &include_context, index,
pBuffer, required, &required );
- }
- if (ok)
- {
- ok = SetupInstallFromInfSectionW( owner, hinf, pBuffer
? pBuffer : szBuffer,
- flags, key_root, src_root, copy_flags, callback,
context, devinfo, devinfo_data );
- }
+/**********************************************************************
*
+ * SetupInstallFromInfSectionW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupInstallFromInfSectionW( HWND owner, HINF hinf, PCWSTR
section, UINT flags,
+ HKEY key_root, PCWSTR
src_root, UINT copy_flags,
+ PSP_FILE_CALLBACK_W callback,
PVOID context,
+ HDEVINFO devinfo,
PSP_DEVINFO_DATA devinfo_data )
+{
+ struct needs_callback_info needs_info;
- MyFree(pBuffer);
- if (!ok) return FALSE;
- index++;
- }
- }
+ /* Parse 'Include' and 'Needs' directives */
+ iterate_section_fields( hinf, section, Include, include_callback,
NULL);
+ needs_info.type = 0;
+ needs_info.owner = owner;
+ needs_info.flags = flags;
+ needs_info.key_root = key_root;
+ needs_info.src_root = src_root;
+ needs_info.copy_flags = copy_flags;
+ needs_info.callback = callback;
+ needs_info.context = context;
+ needs_info.devinfo = devinfo;
+ needs_info.devinfo_data = devinfo_data;
+ iterate_section_fields( hinf, section, Needs, needs_callback,
&needs_info);
if (flags & SPINST_FILES)
{
@@ -1099,258 +1109,368 @@
}
-/**********************************************************************
*
- * SetupInstallServicesFromInfSectionExW (SETUPAPI.@)
- */
-BOOL WINAPI SetupInstallServicesFromInfSectionExW( HINF hinf, PCWSTR
sectionname, DWORD flags, HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA
DeviceInfoData, PVOID reserved1, PVOID reserved2 )
+static BOOL GetStringField( PINFCONTEXT context, DWORD index, PWSTR
*value)
{
+ DWORD RequiredSize;
+ BOOL ret;
+
+ ret = SetupGetStringFieldW(
+ context,
+ index,
+ NULL, 0,
+ &RequiredSize);
+ if (!ret)
+ return FALSE;
+ else if (RequiredSize == 0)
+ {
+ *value = NULL;
+ return TRUE;
+ }
+
+ /* We got the needed size for the buffer */
+ *value = MyMalloc(RequiredSize * sizeof(WCHAR));
+ if (!*value)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return FALSE;
+ }
+ ret = SetupGetStringFieldW(
+ context,
+ index,
+ *value, RequiredSize, NULL);
+ if (!ret)
+ MyFree(*value);
+
+ return ret;
+}
+
+
+static BOOL InstallOneService(
+ struct DeviceInfoSet *list,
+ IN HINF hInf,
+ IN LPCWSTR ServiceSection,
+ IN LPCWSTR ServiceName,
+ IN UINT ServiceFlags)
+{
SC_HANDLE hSCManager = NULL;
SC_HANDLE hService = NULL;
LPDWORD GroupOrder = NULL;
LPQUERY_SERVICE_CONFIG ServiceConfig = NULL;
- struct DeviceInfoSet *list;
BOOL ret = FALSE;
- TRACE("%p, %s, 0x%lx, %p, %p, %p, %p\n", hinf,
debugstr_w(sectionname),
- flags, DeviceInfoSet, DeviceInfoData, reserved1, reserved2);
+ HKEY hGroupOrderListKey = INVALID_HANDLE_VALUE;
+ LPWSTR ServiceBinary = NULL;
+ LPWSTR LoadOrderGroup = NULL;
+ LPWSTR DisplayName = NULL;
+ LPWSTR Description = NULL;
+ LPWSTR Dependencies = NULL;
+ INT ServiceType, StartType, ErrorControl;
+ DWORD dwRegType;
+ DWORD tagId = (DWORD)-1;
+ BOOL useTag;
- 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)
+ if (!GetIntField(hInf, ServiceSection, L"ServiceType",
&ServiceType))
+ goto cleanup;
+ if (!GetIntField(hInf, ServiceSection, L"StartType", &StartType))
+ goto cleanup;
+ if (!GetIntField(hInf, ServiceSection, 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)
+ goto cleanup;
+
+ if (!GetLineText(hInf, ServiceSection, 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, ServiceSection, L"LoadOrderGroup",
&LoadOrderGroup);
+ GetLineText(hInf, ServiceSection, L"DisplayName", &DisplayName);
+ GetLineText(hInf, ServiceSection, L"Description", &Description);
+ GetLineText(hInf, ServiceSection, L"Dependencies", &Dependencies);
+
+ hService = OpenServiceW(
+ hSCManager,
+ ServiceName,
+ GENERIC_READ | GENERIC_WRITE);
+ if (hService == NULL && GetLastError() !=
ERROR_SERVICE_DOES_NOT_EXIST)
+ goto cleanup;
+
+ if (hService && (ServiceFlags & SPSVCINST_DELETEEVENTLOGENTRY))
{
- /* FIXME: I don't know how to get the service name. ATM, just
fail the call */
- /* Maybe find it in DeviceInfoSet/DeviceInfoData? */
- FIXME("Service name not specified!\n");
- SetLastError(ERROR_GEN_FAILURE);
- goto cleanup;
+ ret = DeleteService(hService);
+ if (!ret && GetLastError() != ERROR_SERVICE_MARKED_FOR_DELETE)
+ goto cleanup;
}
+
+ if (hService == NULL)
+ {
+ /* Create new service */
+ hService = CreateServiceW(
+ hSCManager,
+ ServiceName,
+ DisplayName,
+ 0,
+ ServiceType,
+ StartType,
+ ErrorControl,
+ ServiceBinary,
+ LoadOrderGroup,
+ useTag ? &tagId : NULL,
+ Dependencies,
+ NULL, NULL);
+ if (hService == NULL)
+ goto cleanup;
+ }
else
{
- HKEY hGroupOrderListKey = INVALID_HANDLE_VALUE;
- LPWSTR ServiceBinary = NULL;
- LPWSTR LoadOrderGroup = NULL;
- LPWSTR DisplayName = NULL;
- LPWSTR Description = NULL;
- LPWSTR Dependencies = NULL;
- INT ServiceType, StartType, ErrorControl;
- DWORD dwRegType;
- DWORD tagId = (DWORD)-1;
- BOOL useTag;
+ DWORD bufferSize;
+ /* Read current configuration */
+ if (!QueryServiceConfigW(hService, NULL, 0, &bufferSize))
+ {
+ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+ goto cleanup;
+ ServiceConfig = MyMalloc(bufferSize);
+ if (!ServiceConfig)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ goto cleanup;
+ }
+ if (!QueryServiceConfigW(hService, ServiceConfig,
bufferSize, &bufferSize))
+ goto cleanup;
+ }
+ tagId = ServiceConfig->dwTagId;
- if (!GetIntField(hinf, sectionname, L"ServiceType",
&ServiceType))
+ /* Update configuration */
+ ret = ChangeServiceConfigW(
+ hService,
+ ServiceType,
+ (ServiceFlags & SPSVCINST_NOCLOBBER_STARTTYPE) ?
SERVICE_NO_CHANGE : StartType,
+ (ServiceFlags & SPSVCINST_NOCLOBBER_ERRORCONTROL) ?
SERVICE_NO_CHANGE : ErrorControl,
+ ServiceBinary,
+ (ServiceFlags & SPSVCINST_NOCLOBBER_LOADORDERGROUP &&
ServiceConfig->lpLoadOrderGroup) ? NULL : LoadOrderGroup,
+ useTag ? &tagId : NULL,
+ (ServiceFlags & SPSVCINST_NOCLOBBER_DEPENDENCIES &&
ServiceConfig->lpDependencies) ? NULL : Dependencies,
+ NULL, NULL,
+ (ServiceFlags & SPSVCINST_NOCLOBBER_DISPLAYNAME &&
ServiceConfig->lpDisplayName) ? NULL : DisplayName);
+ if (!ret)
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)
- goto cleanup;
+ /* FIXME: use Description and SPSVCINST_NOCLOBBER_DESCRIPTION */
- if (!GetLineText(hinf, sectionname, L"ServiceBinary",
&ServiceBinary))
- goto cleanup;
+ if (useTag)
+ {
+ /* Add the tag to
SYSTEM\CurrentControlSet\Control\GroupOrderList key */
+ LONG rc;
+ LPCWSTR lpLoadOrderGroup;
+ DWORD bufferSize;
- /* 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);
+ lpLoadOrderGroup = LoadOrderGroup;
+ if ((ServiceFlags & SPSVCINST_NOCLOBBER_LOADORDERGROUP) &&
ServiceConfig && ServiceConfig->lpLoadOrderGroup)
+ lpLoadOrderGroup = ServiceConfig->lpLoadOrderGroup;
- hService = OpenServiceW(
- hSCManager,
- reserved1,
- GENERIC_READ | GENERIC_WRITE);
- if (hService == NULL && GetLastError() !=
ERROR_SERVICE_DOES_NOT_EXIST)
+ rc = RegOpenKey(
+ list ? list->HKLM : HKEY_LOCAL_MACHINE,
+ L"SYSTEM\\CurrentControlSet\\Control\\GroupOrderList",
+ &hGroupOrderListKey);
+ if (rc != ERROR_SUCCESS)
+ {
+ SetLastError(rc);
goto cleanup;
-
- if (flags & (SPSVCINST_STOPSERVICE |
SPSVCINST_DELETEEVENTLOGENTRY))
+ }
+ rc = RegQueryValueExW(hGroupOrderListKey, lpLoadOrderGroup,
NULL, &dwRegType, NULL, &bufferSize);
+ if (rc == ERROR_FILE_NOT_FOUND)
+ bufferSize = sizeof(DWORD);
+ else if (rc != ERROR_SUCCESS)
{
- if (hService == NULL)
+ SetLastError(rc);
+ goto cleanup;
+ }
+ else if (dwRegType != REG_BINARY || bufferSize == 0 ||
bufferSize % sizeof(DWORD) != 0)
+ {
+ SetLastError(ERROR_GEN_FAILURE);
+ goto cleanup;
+ }
+ /* Allocate buffer to store existing data + the new tag */
+ GroupOrder = MyMalloc(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,
+ (BYTE*)GroupOrder,
+ &bufferSize);
+ if (rc != ERROR_SUCCESS)
{
- SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
+ SetLastError(rc);
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 (ServiceFlags & SPSVCINST_TAGTOFRONT)
+ memmove(&GroupOrder[2], &GroupOrder[1], bufferSize -
sizeof(DWORD));
}
-
- if (hService == NULL)
+ else
{
- /* 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;
+ GroupOrder[0] = 0;
}
+ GroupOrder[0]++;
+ if (ServiceFlags & SPSVCINST_TAGTOFRONT)
+ GroupOrder[1] = tagId;
else
+ GroupOrder[bufferSize / sizeof(DWORD)] = tagId;
+
+ rc = RegSetValueExW(
+ hGroupOrderListKey,
+ lpLoadOrderGroup,
+ 0,
+ REG_BINARY,
+ (BYTE*)GroupOrder,
+ bufferSize + sizeof(DWORD));
+ if (rc != ERROR_SUCCESS)
{
- 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;
+ SetLastError(rc);
+ goto cleanup;
}
+ }
- /* FIXME: use Description and SPSVCINST_NOCLOBBER_DESCRIPTION
*/
+ ret = TRUE;
- if (useTag)
- {
- /* Add the tag to
SYSTEM\CurrentControlSet\Control\GroupOrderList key */
- LONG rc;
- LPCWSTR lpLoadOrderGroup;
- DWORD bufferSize;
+cleanup:
+ if (hSCManager != NULL)
+ CloseServiceHandle(hSCManager);
+ if (hService != NULL)
+ CloseServiceHandle(hService);
+ if (hGroupOrderListKey != INVALID_HANDLE_VALUE)
+ RegCloseKey(hGroupOrderListKey);
+ MyFree(ServiceConfig);
+ MyFree(ServiceBinary);
+ MyFree(LoadOrderGroup);
+ MyFree(DisplayName);
+ MyFree(Description);
+ MyFree(Dependencies);
+ MyFree(GroupOrder);
- lpLoadOrderGroup = LoadOrderGroup;
- if ((flags & SPSVCINST_NOCLOBBER_LOADORDERGROUP) &&
ServiceConfig && ServiceConfig->lpLoadOrderGroup)
- lpLoadOrderGroup = ServiceConfig->lpLoadOrderGroup;
+ TRACE("Returning %d\n", ret);
+ return ret;
+}
- rc = RegOpenKey(list->HKLM,
L"SYSTEM\\CurrentControlSet\\Control\\GroupOrderList",
&hGroupOrderListKey);
- if (rc != ERROR_SUCCESS)
- {
- SetLastError(rc);
+
+/**********************************************************************
*
+ * SetupInstallServicesFromInfSectionExW (SETUPAPI.@)
+ */
+BOOL WINAPI SetupInstallServicesFromInfSectionExW( HINF hinf, PCWSTR
sectionname, DWORD flags, HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA
DeviceInfoData, PVOID reserved1, PVOID reserved2 )
+{
+ struct DeviceInfoSet *list = NULL;
+ BOOL ret = FALSE;
+
+ TRACE("%p, %s, 0x%lx, %p, %p, %p, %p\n", hinf,
debugstr_w(sectionname),
+ flags, DeviceInfoSet, DeviceInfoData, reserved1, reserved2);
+
+ if (!sectionname)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else if (flags & ~(SPSVCINST_TAGTOFRONT |
SPSVCINST_DELETEEVENTLOGENTRY | SPSVCINST_NOCLOBBER_DISPLAYNAME |
SPSVCINST_NOCLOBBER_STARTTYPE | SPSVCINST_NOCLOBBER_ERRORCONTROL |
SPSVCINST_NOCLOBBER_LOADORDERGROUP | SPSVCINST_NOCLOBBER_DEPENDENCIES |
SPSVCINST_STOPSERVICE))
+ {
+ TRACE("Unknown flags: 0x%08lx\n", flags &
~(SPSVCINST_TAGTOFRONT | SPSVCINST_DELETEEVENTLOGENTRY |
SPSVCINST_NOCLOBBER_DISPLAYNAME | SPSVCINST_NOCLOBBER_STARTTYPE |
SPSVCINST_NOCLOBBER_ERRORCONTROL | SPSVCINST_NOCLOBBER_LOADORDERGROUP |
SPSVCINST_NOCLOBBER_DEPENDENCIES | SPSVCINST_STOPSERVICE));
+ SetLastError(ERROR_INVALID_FLAGS);
+ }
+ else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
+ SetLastError(ERROR_INVALID_HANDLE);
+ else if (DeviceInfoSet && (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 != NULL || reserved2 != NULL)
+ SetLastError(ERROR_INVALID_PARAMETER);
+ else
+ {
+ struct needs_callback_info needs_info;
+ LPWSTR ServiceName = NULL;
+ LPWSTR ServiceSection = NULL;
+ UINT ServiceFlags;
+ INFCONTEXT ContextService;
+ BOOL bNeedReboot = FALSE;
+
+ /* Parse 'Include' and 'Needs' directives */
+ iterate_section_fields( hinf, sectionname, Include,
include_callback, NULL);
+ needs_info.type = 1;
+ needs_info.flags = flags;
+ needs_info.devinfo = DeviceInfoSet;
+ needs_info.devinfo_data = DeviceInfoData;
+ needs_info.reserved1 = reserved1;
+ needs_info.reserved2 = reserved2;
+ iterate_section_fields( hinf, sectionname, Needs,
needs_callback, &needs_info);
+
+ if (flags & SPSVCINST_STOPSERVICE)
+ {
+ FIXME("Stopping the device not implemented\n");
+ /* This may lead to require a reboot */
+ /* bNeedReboot = TRUE; */
+#if 0
+ SERVICE_STATUS ServiceStatus;
+ ret = ControlService(hService, SERVICE_CONTROL_STOP,
&ServiceStatus);
+ if (!ret && GetLastError() != ERROR_SERVICE_NOT_ACTIVE)
goto cleanup;
- }
- rc = RegQueryValueExW(hGroupOrderListKey, lpLoadOrderGroup,
NULL, &dwRegType, NULL, &bufferSize);
- if (rc == ERROR_FILE_NOT_FOUND)
- bufferSize = sizeof(DWORD);
- else if (rc != ERROR_SUCCESS)
+ if (ServiceStatus.dwCurrentState != SERVICE_STOP_PENDING &&
ServiceStatus.dwCurrentState != SERVICE_STOPPED)
{
- SetLastError(rc);
+ SetLastError(ERROR_INSTALL_SERVICE_FAILURE);
goto cleanup;
}
- else if (dwRegType != REG_BINARY || bufferSize == 0 ||
bufferSize % sizeof(DWORD) != 0)
+#endif
+ flags &= ~SPSVCINST_STOPSERVICE;
+ }
+
+ ret = SetupFindFirstLineW(hinf, sectionname, AddService,
&ContextService);
+ while (ret)
+ {
+ if (!GetStringField(&ContextService, 1, &ServiceName))
+ goto nextservice;
+
+ ret = SetupGetIntField(
+ &ContextService,
+ 2, /* Field index */
+ &ServiceFlags);
+ if (!ret)
{
- SetLastError(ERROR_GEN_FAILURE);
- goto cleanup;
+ /* The field may be empty. Ignore the error */
+ ServiceFlags = 0;
}
- /* Allocate buffer to store existing data + the new tag */
- GroupOrder = HeapAlloc(GetProcessHeap(), 0, bufferSize +
sizeof(DWORD));
- if (!GroupOrder)
+
+ if (!GetStringField(&ContextService, 3, &ServiceSection))
+ goto nextservice;
+
+ ret = InstallOneService(list, hinf, ServiceSection,
ServiceName, (ServiceFlags & ~SPSVCINST_ASSOCSERVICE) | flags);
+ if (!ret)
+ goto nextservice;
+
+ if (ServiceFlags & SPSVCINST_ASSOCSERVICE)
{
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- goto cleanup;
+ ret = SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet,
DeviceInfoData, SPDRP_SERVICE, (LPBYTE)ServiceName,
(strlenW(ServiceName) + 1) * sizeof(WCHAR));
+ if (!ret)
+ goto nextservice;
}
- if (rc == ERROR_SUCCESS)
- {
- /* Read existing data */
- rc = RegQueryValueExW(
- hGroupOrderListKey,
- lpLoadOrderGroup,
- NULL,
- NULL,
- (BYTE*)GroupOrder,
- &bufferSize);
- if (rc != ERROR_SUCCESS)
- {
- SetLastError(rc);
- goto cleanup;
- }
- if (flags & SPSVCINST_TAGTOFRONT)
- memmove(&GroupOrder[2], &GroupOrder[1], bufferSize
- sizeof(DWORD));
- }
- else
- {
- GroupOrder[0] = 0;
- }
- GroupOrder[0]++;
- if (flags & SPSVCINST_TAGTOFRONT)
- GroupOrder[1] = 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;
- }
+nextservice:
+ HeapFree(GetProcessHeap(), 0, ServiceName);
+ HeapFree(GetProcessHeap(), 0, ServiceSection);
+ ServiceName = ServiceSection = NULL;
+ ret = SetupFindNextMatchLineW(&ContextService, AddService,
&ContextService);
}
+ if (bNeedReboot)
+ SetLastError(ERROR_SUCCESS_REBOOT_REQUIRED);
+ else
+ SetLastError(ERROR_SUCCESS);
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);
}
TRACE("Returning %d\n", ret);