mirror of
https://github.com/reactos/reactos.git
synced 2024-07-14 16:36:09 +00:00
- 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 svn path=/trunk/; revision=20283
This commit is contained in:
parent
cb0196f66c
commit
62d79cb1cd
|
@ -3174,182 +3174,6 @@ static HKEY CreateClassKey(HINF hInf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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.@)
|
* SetupDiInstallClassExW (SETUPAPI.@)
|
||||||
*/
|
*/
|
||||||
|
@ -3451,7 +3275,7 @@ BOOL WINAPI SetupDiInstallClassExW(
|
||||||
|
|
||||||
/* Install .Services section */
|
/* Install .Services section */
|
||||||
lstrcatW(SectionName, DotServices);
|
lstrcatW(SectionName, DotServices);
|
||||||
ret = InstallServicesSection(hInf, SectionName, NULL, NULL, NULL, NULL);
|
ret = SetupInstallServicesFromInfSectionW(hInf, SectionName, 0);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
@ -5585,8 +5409,6 @@ SetupDiBuildDriverInfoList(
|
||||||
SetLastError(ERROR_INVALID_HANDLE);
|
SetLastError(ERROR_INVALID_HANDLE);
|
||||||
else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
|
else if (DriverType != SPDIT_CLASSDRIVER && DriverType != SPDIT_COMPATDRIVER)
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
else if (DriverType == SPDIT_CLASSDRIVER && DeviceInfoData)
|
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
|
||||||
else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
|
else if (DriverType == SPDIT_COMPATDRIVER && !DeviceInfoData)
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
|
else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
|
||||||
|
@ -7404,7 +7226,6 @@ SetupDiInstallDevice(
|
||||||
BOOL Result = FALSE;
|
BOOL Result = FALSE;
|
||||||
ULONG DoAction;
|
ULONG DoAction;
|
||||||
DWORD RequiredSize;
|
DWORD RequiredSize;
|
||||||
LPCWSTR AssociatedService = NULL;
|
|
||||||
LPWSTR pSectionName = NULL;
|
LPWSTR pSectionName = NULL;
|
||||||
WCHAR ClassName[MAX_CLASS_NAME_LEN];
|
WCHAR ClassName[MAX_CLASS_NAME_LEN];
|
||||||
GUID ClassGuid;
|
GUID ClassGuid;
|
||||||
|
@ -7569,15 +7390,18 @@ SetupDiInstallDevice(
|
||||||
|
|
||||||
/* Install .Services section */
|
/* Install .Services section */
|
||||||
wcscpy(pSectionName, DotServices);
|
wcscpy(pSectionName, DotServices);
|
||||||
Result = InstallServicesSection(
|
Result = SetupInstallServicesFromInfSectionExW(
|
||||||
SelectedDriver->InfFileDetails->hInf,
|
SelectedDriver->InfFileDetails->hInf,
|
||||||
SectionName,
|
SectionName,
|
||||||
|
0,
|
||||||
DeviceInfoSet,
|
DeviceInfoSet,
|
||||||
DeviceInfoData,
|
DeviceInfoData,
|
||||||
&AssociatedService,
|
NULL,
|
||||||
&RebootRequired);
|
NULL);
|
||||||
if (!Result)
|
if (!Result)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED)
|
||||||
|
RebootRequired = TRUE;
|
||||||
|
|
||||||
/* Copy .inf file to Inf\ directory (if needed) */
|
/* Copy .inf file to Inf\ directory (if needed) */
|
||||||
Result = InfIsFromOEMLocation(SelectedDriver->InfFileDetails->FullInfFileName, &NeedtoCopyFile);
|
Result = InfIsFromOEMLocation(SelectedDriver->InfFileDetails->FullInfFileName, &NeedtoCopyFile);
|
||||||
|
@ -7620,7 +7444,6 @@ SetupDiInstallDevice(
|
||||||
TRACE("ClassGUID : '%S'\n", lpFullGuidString);
|
TRACE("ClassGUID : '%S'\n", lpFullGuidString);
|
||||||
TRACE("DeviceDesc : '%S'\n", SelectedDriver->Info.Description);
|
TRACE("DeviceDesc : '%S'\n", SelectedDriver->Info.Description);
|
||||||
TRACE("Mfg : '%S'\n", SelectedDriver->Info.MfgName);
|
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));
|
rc = RegSetValueEx(hKey, REGSTR_VAL_CLASS, 0, REG_SZ, (const BYTE *)ClassName, (wcslen(ClassName) + 1) * sizeof(WCHAR));
|
||||||
if (rc == ERROR_SUCCESS)
|
if (rc == ERROR_SUCCESS)
|
||||||
rc = RegSetValueEx(hKey, REGSTR_VAL_CLASSGUID, 0, REG_SZ, (const BYTE *)lpFullGuidString, (wcslen(lpFullGuidString) + 1) * sizeof(WCHAR));
|
rc = RegSetValueEx(hKey, REGSTR_VAL_CLASSGUID, 0, REG_SZ, (const BYTE *)lpFullGuidString, (wcslen(lpFullGuidString) + 1) * sizeof(WCHAR));
|
||||||
|
@ -7628,8 +7451,6 @@ SetupDiInstallDevice(
|
||||||
rc = RegSetValueEx(hKey, REGSTR_VAL_DEVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (wcslen(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
|
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)
|
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));
|
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)
|
if (rc != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
SetLastError(rc);
|
SetLastError(rc);
|
||||||
|
@ -7650,7 +7471,6 @@ cleanup:
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hKey);
|
||||||
if (lpGuidString)
|
if (lpGuidString)
|
||||||
RpcStringFreeW(&lpGuidString);
|
RpcStringFreeW(&lpGuidString);
|
||||||
HeapFree(GetProcessHeap(), 0, (LPWSTR)AssociatedService);
|
|
||||||
HeapFree(GetProcessHeap(), 0, lpFullGuidString);
|
HeapFree(GetProcessHeap(), 0, lpFullGuidString);
|
||||||
|
|
||||||
TRACE("Returning %d\n", ret);
|
TRACE("Returning %d\n", ret);
|
||||||
|
|
|
@ -47,9 +47,28 @@ struct register_dll_info
|
||||||
BOOL unregister;
|
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 );
|
typedef BOOL (*iterate_fields_func)( HINF hinf, PCWSTR field, void *arg );
|
||||||
|
|
||||||
/* Unicode constants */
|
/* 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 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 DelFiles[] = {'D','e','l','F','i','l','e','s',0};
|
||||||
static const WCHAR RenFiles[] = {'R','e','n','F','i','l','e','s',0};
|
static const WCHAR RenFiles[] = {'R','e','n','F','i','l','e','s',0};
|
||||||
|
@ -783,6 +802,42 @@ BOOL WINAPI SetupInstallFromInfSectionA( HWND owner, HINF hinf, PCSTR section, U
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* include_callback
|
||||||
|
*
|
||||||
|
* Called once for each Include entry in a given section.
|
||||||
|
*/
|
||||||
|
static BOOL include_callback( HINF hinf, PCWSTR field, void *arg )
|
||||||
|
{
|
||||||
|
return SetupOpenAppendInfFileW( field, 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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* SetupInstallFromInfSectionW (SETUPAPI.@)
|
* SetupInstallFromInfSectionW (SETUPAPI.@)
|
||||||
*/
|
*/
|
||||||
|
@ -791,66 +846,21 @@ BOOL WINAPI SetupInstallFromInfSectionW( HWND owner, HINF hinf, PCWSTR section,
|
||||||
PSP_FILE_CALLBACK_W callback, PVOID context,
|
PSP_FILE_CALLBACK_W callback, PVOID context,
|
||||||
HDEVINFO devinfo, PSP_DEVINFO_DATA devinfo_data )
|
HDEVINFO devinfo, PSP_DEVINFO_DATA devinfo_data )
|
||||||
{
|
{
|
||||||
INFCONTEXT include_context;
|
struct needs_callback_info needs_info;
|
||||||
|
|
||||||
/* Parse 'Include' line */
|
/* Parse 'Include' and 'Needs' directives */
|
||||||
if (SetupFindFirstLineW( hinf, section, Include, &include_context ))
|
iterate_section_fields( hinf, section, Include, include_callback, NULL);
|
||||||
{
|
needs_info.type = 0;
|
||||||
DWORD index = 1;
|
needs_info.owner = owner;
|
||||||
while (TRUE)
|
needs_info.flags = flags;
|
||||||
{
|
needs_info.key_root = key_root;
|
||||||
static WCHAR szBuffer[MAX_PATH];
|
needs_info.src_root = src_root;
|
||||||
PWSTR pBuffer = NULL;
|
needs_info.copy_flags = copy_flags;
|
||||||
DWORD required;
|
needs_info.callback = callback;
|
||||||
BOOL ok;
|
needs_info.context = context;
|
||||||
|
needs_info.devinfo = devinfo;
|
||||||
ok = SetupGetStringFieldW( &include_context, index, szBuffer, MAX_PATH, &required );
|
needs_info.devinfo_data = devinfo_data;
|
||||||
if (!ok && GetLastError() == ERROR_INVALID_PARAMETER)
|
iterate_section_fields( hinf, section, Needs, needs_callback, &needs_info);
|
||||||
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 );
|
|
||||||
|
|
||||||
MyFree(pBuffer);
|
|
||||||
if (!ok) return FALSE;
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
MyFree(pBuffer);
|
|
||||||
if (!ok) return FALSE;
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & SPINST_FILES)
|
if (flags & SPINST_FILES)
|
||||||
{
|
{
|
||||||
|
@ -1099,39 +1109,55 @@ static BOOL GetIntField( HINF hinf, PCWSTR section_name, PCWSTR key_name, INT *v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************
|
static BOOL GetStringField( PINFCONTEXT context, DWORD index, PWSTR *value)
|
||||||
* SetupInstallServicesFromInfSectionExW (SETUPAPI.@)
|
{
|
||||||
*/
|
DWORD RequiredSize;
|
||||||
BOOL WINAPI SetupInstallServicesFromInfSectionExW( HINF hinf, PCWSTR sectionname, DWORD flags, HDEVINFO DeviceInfoSet, PSP_DEVINFO_DATA DeviceInfoData, PVOID reserved1, PVOID reserved2 )
|
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 hSCManager = NULL;
|
||||||
SC_HANDLE hService = NULL;
|
SC_HANDLE hService = NULL;
|
||||||
LPDWORD GroupOrder = NULL;
|
LPDWORD GroupOrder = NULL;
|
||||||
LPQUERY_SERVICE_CONFIG ServiceConfig = NULL;
|
LPQUERY_SERVICE_CONFIG ServiceConfig = NULL;
|
||||||
struct DeviceInfoSet *list;
|
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
|
|
||||||
TRACE("%p, %s, 0x%lx, %p, %p, %p, %p\n", hinf, debugstr_w(sectionname),
|
|
||||||
flags, DeviceInfoSet, DeviceInfoData, reserved1, reserved2);
|
|
||||||
|
|
||||||
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 */
|
|
||||||
/* Maybe find it in DeviceInfoSet/DeviceInfoData? */
|
|
||||||
FIXME("Service name not specified!\n");
|
|
||||||
SetLastError(ERROR_GEN_FAILURE);
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HKEY hGroupOrderListKey = INVALID_HANDLE_VALUE;
|
HKEY hGroupOrderListKey = INVALID_HANDLE_VALUE;
|
||||||
LPWSTR ServiceBinary = NULL;
|
LPWSTR ServiceBinary = NULL;
|
||||||
LPWSTR LoadOrderGroup = NULL;
|
LPWSTR LoadOrderGroup = NULL;
|
||||||
|
@ -1143,11 +1169,11 @@ BOOL WINAPI SetupInstallServicesFromInfSectionExW( HINF hinf, PCWSTR sectionname
|
||||||
DWORD tagId = (DWORD)-1;
|
DWORD tagId = (DWORD)-1;
|
||||||
BOOL useTag;
|
BOOL useTag;
|
||||||
|
|
||||||
if (!GetIntField(hinf, sectionname, L"ServiceType", &ServiceType))
|
if (!GetIntField(hInf, ServiceSection, L"ServiceType", &ServiceType))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
if (!GetIntField(hinf, sectionname, L"StartType", &StartType))
|
if (!GetIntField(hInf, ServiceSection, L"StartType", &StartType))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
if (!GetIntField(hinf, sectionname, L"ErrorControl", &ErrorControl))
|
if (!GetIntField(hInf, ServiceSection, L"ErrorControl", &ErrorControl))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
useTag = (ServiceType == SERVICE_BOOT_START || ServiceType == SERVICE_SYSTEM_START);
|
useTag = (ServiceType == SERVICE_BOOT_START || ServiceType == SERVICE_SYSTEM_START);
|
||||||
|
|
||||||
|
@ -1155,57 +1181,36 @@ BOOL WINAPI SetupInstallServicesFromInfSectionExW( HINF hinf, PCWSTR sectionname
|
||||||
if (hSCManager == NULL)
|
if (hSCManager == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (!GetLineText(hinf, sectionname, L"ServiceBinary", &ServiceBinary))
|
if (!GetLineText(hInf, ServiceSection, L"ServiceBinary", &ServiceBinary))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
/* Don't check return value, as these fields are optional and
|
/* Don't check return value, as these fields are optional and
|
||||||
* GetLineText initialize output parameter even on failure */
|
* GetLineText initialize output parameter even on failure */
|
||||||
GetLineText(hinf, sectionname, L"LoadOrderGroup", &LoadOrderGroup);
|
GetLineText(hInf, ServiceSection, L"LoadOrderGroup", &LoadOrderGroup);
|
||||||
GetLineText(hinf, sectionname, L"DisplayName", &DisplayName);
|
GetLineText(hInf, ServiceSection, L"DisplayName", &DisplayName);
|
||||||
GetLineText(hinf, sectionname, L"Description", &Description);
|
GetLineText(hInf, ServiceSection, L"Description", &Description);
|
||||||
GetLineText(hinf, sectionname, L"Dependencies", &Dependencies);
|
GetLineText(hInf, ServiceSection, L"Dependencies", &Dependencies);
|
||||||
|
|
||||||
hService = OpenServiceW(
|
hService = OpenServiceW(
|
||||||
hSCManager,
|
hSCManager,
|
||||||
reserved1,
|
ServiceName,
|
||||||
GENERIC_READ | GENERIC_WRITE);
|
GENERIC_READ | GENERIC_WRITE);
|
||||||
if (hService == NULL && GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST)
|
if (hService == NULL && GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (flags & (SPSVCINST_STOPSERVICE | SPSVCINST_DELETEEVENTLOGENTRY))
|
if (hService && (ServiceFlags & 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);
|
ret = DeleteService(hService);
|
||||||
if (!ret)
|
if (!ret && GetLastError() != ERROR_SERVICE_MARKED_FOR_DELETE)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
ret = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hService == NULL)
|
if (hService == NULL)
|
||||||
{
|
{
|
||||||
/* Create new service */
|
/* Create new service */
|
||||||
hService = CreateServiceW(
|
hService = CreateServiceW(
|
||||||
hSCManager,
|
hSCManager,
|
||||||
reserved1,
|
ServiceName,
|
||||||
DisplayName,
|
DisplayName,
|
||||||
0,
|
0,
|
||||||
ServiceType,
|
ServiceType,
|
||||||
|
@ -1227,7 +1232,7 @@ BOOL WINAPI SetupInstallServicesFromInfSectionExW( HINF hinf, PCWSTR sectionname
|
||||||
{
|
{
|
||||||
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
ServiceConfig = HeapAlloc(GetProcessHeap(), 0, bufferSize);
|
ServiceConfig = MyMalloc(bufferSize);
|
||||||
if (!ServiceConfig)
|
if (!ServiceConfig)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
@ -1242,14 +1247,14 @@ BOOL WINAPI SetupInstallServicesFromInfSectionExW( HINF hinf, PCWSTR sectionname
|
||||||
ret = ChangeServiceConfigW(
|
ret = ChangeServiceConfigW(
|
||||||
hService,
|
hService,
|
||||||
ServiceType,
|
ServiceType,
|
||||||
(flags & SPSVCINST_NOCLOBBER_STARTTYPE) ? SERVICE_NO_CHANGE : StartType,
|
(ServiceFlags & SPSVCINST_NOCLOBBER_STARTTYPE) ? SERVICE_NO_CHANGE : StartType,
|
||||||
(flags & SPSVCINST_NOCLOBBER_ERRORCONTROL) ? SERVICE_NO_CHANGE : ErrorControl,
|
(ServiceFlags & SPSVCINST_NOCLOBBER_ERRORCONTROL) ? SERVICE_NO_CHANGE : ErrorControl,
|
||||||
ServiceBinary,
|
ServiceBinary,
|
||||||
(flags & SPSVCINST_NOCLOBBER_LOADORDERGROUP && ServiceConfig->lpLoadOrderGroup) ? NULL : LoadOrderGroup,
|
(ServiceFlags & SPSVCINST_NOCLOBBER_LOADORDERGROUP && ServiceConfig->lpLoadOrderGroup) ? NULL : LoadOrderGroup,
|
||||||
useTag ? &tagId : NULL,
|
useTag ? &tagId : NULL,
|
||||||
(flags & SPSVCINST_NOCLOBBER_DEPENDENCIES && ServiceConfig->lpDependencies) ? NULL : Dependencies,
|
(ServiceFlags & SPSVCINST_NOCLOBBER_DEPENDENCIES && ServiceConfig->lpDependencies) ? NULL : Dependencies,
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
(flags & SPSVCINST_NOCLOBBER_DISPLAYNAME && ServiceConfig->lpDisplayName) ? NULL : DisplayName);
|
(ServiceFlags & SPSVCINST_NOCLOBBER_DISPLAYNAME && ServiceConfig->lpDisplayName) ? NULL : DisplayName);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
@ -1264,10 +1269,13 @@ BOOL WINAPI SetupInstallServicesFromInfSectionExW( HINF hinf, PCWSTR sectionname
|
||||||
DWORD bufferSize;
|
DWORD bufferSize;
|
||||||
|
|
||||||
lpLoadOrderGroup = LoadOrderGroup;
|
lpLoadOrderGroup = LoadOrderGroup;
|
||||||
if ((flags & SPSVCINST_NOCLOBBER_LOADORDERGROUP) && ServiceConfig && ServiceConfig->lpLoadOrderGroup)
|
if ((ServiceFlags & SPSVCINST_NOCLOBBER_LOADORDERGROUP) && ServiceConfig && ServiceConfig->lpLoadOrderGroup)
|
||||||
lpLoadOrderGroup = ServiceConfig->lpLoadOrderGroup;
|
lpLoadOrderGroup = ServiceConfig->lpLoadOrderGroup;
|
||||||
|
|
||||||
rc = RegOpenKey(list->HKLM, L"SYSTEM\\CurrentControlSet\\Control\\GroupOrderList", &hGroupOrderListKey);
|
rc = RegOpenKey(
|
||||||
|
list ? list->HKLM : HKEY_LOCAL_MACHINE,
|
||||||
|
L"SYSTEM\\CurrentControlSet\\Control\\GroupOrderList",
|
||||||
|
&hGroupOrderListKey);
|
||||||
if (rc != ERROR_SUCCESS)
|
if (rc != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
SetLastError(rc);
|
SetLastError(rc);
|
||||||
|
@ -1287,7 +1295,7 @@ BOOL WINAPI SetupInstallServicesFromInfSectionExW( HINF hinf, PCWSTR sectionname
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
/* Allocate buffer to store existing data + the new tag */
|
/* Allocate buffer to store existing data + the new tag */
|
||||||
GroupOrder = HeapAlloc(GetProcessHeap(), 0, bufferSize + sizeof(DWORD));
|
GroupOrder = MyMalloc(bufferSize + sizeof(DWORD));
|
||||||
if (!GroupOrder)
|
if (!GroupOrder)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||||||
|
@ -1308,7 +1316,7 @@ BOOL WINAPI SetupInstallServicesFromInfSectionExW( HINF hinf, PCWSTR sectionname
|
||||||
SetLastError(rc);
|
SetLastError(rc);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if (flags & SPSVCINST_TAGTOFRONT)
|
if (ServiceFlags & SPSVCINST_TAGTOFRONT)
|
||||||
memmove(&GroupOrder[2], &GroupOrder[1], bufferSize - sizeof(DWORD));
|
memmove(&GroupOrder[2], &GroupOrder[1], bufferSize - sizeof(DWORD));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1316,7 +1324,7 @@ BOOL WINAPI SetupInstallServicesFromInfSectionExW( HINF hinf, PCWSTR sectionname
|
||||||
GroupOrder[0] = 0;
|
GroupOrder[0] = 0;
|
||||||
}
|
}
|
||||||
GroupOrder[0]++;
|
GroupOrder[0]++;
|
||||||
if (flags & SPSVCINST_TAGTOFRONT)
|
if (ServiceFlags & SPSVCINST_TAGTOFRONT)
|
||||||
GroupOrder[1] = tagId;
|
GroupOrder[1] = tagId;
|
||||||
else
|
else
|
||||||
GroupOrder[bufferSize / sizeof(DWORD)] = tagId;
|
GroupOrder[bufferSize / sizeof(DWORD)] = tagId;
|
||||||
|
@ -1344,13 +1352,125 @@ cleanup:
|
||||||
CloseServiceHandle(hService);
|
CloseServiceHandle(hService);
|
||||||
if (hGroupOrderListKey != INVALID_HANDLE_VALUE)
|
if (hGroupOrderListKey != INVALID_HANDLE_VALUE)
|
||||||
RegCloseKey(hGroupOrderListKey);
|
RegCloseKey(hGroupOrderListKey);
|
||||||
HeapFree(GetProcessHeap(), 0, ServiceConfig);
|
MyFree(ServiceConfig);
|
||||||
HeapFree(GetProcessHeap(), 0, ServiceBinary);
|
MyFree(ServiceBinary);
|
||||||
HeapFree(GetProcessHeap(), 0, LoadOrderGroup);
|
MyFree(LoadOrderGroup);
|
||||||
HeapFree(GetProcessHeap(), 0, DisplayName);
|
MyFree(DisplayName);
|
||||||
HeapFree(GetProcessHeap(), 0, Description);
|
MyFree(Description);
|
||||||
HeapFree(GetProcessHeap(), 0, Dependencies);
|
MyFree(Dependencies);
|
||||||
HeapFree(GetProcessHeap(), 0, GroupOrder);
|
MyFree(GroupOrder);
|
||||||
|
|
||||||
|
TRACE("Returning %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* 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;
|
||||||
|
if (ServiceStatus.dwCurrentState != SERVICE_STOP_PENDING && ServiceStatus.dwCurrentState != SERVICE_STOPPED)
|
||||||
|
{
|
||||||
|
SetLastError(ERROR_INSTALL_SERVICE_FAILURE);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
/* The field may be empty. Ignore the error */
|
||||||
|
ServiceFlags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
ret = SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet, DeviceInfoData, SPDRP_SERVICE, (LPBYTE)ServiceName, (strlenW(ServiceName) + 1) * sizeof(WCHAR));
|
||||||
|
if (!ret)
|
||||||
|
goto nextservice;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("Returning %d\n", ret);
|
TRACE("Returning %d\n", ret);
|
||||||
|
|
Loading…
Reference in a new issue