Exemplo n.º 1
0
/******************************************************************
 CaSchedSecureObjects - entry point for CaReadSecureObjects Custom Action

 called as Type 1 CustomAction (binary DLL) from Windows Installer
 in InstallExecuteSequence before CaSecureObjects
******************************************************************/
extern "C" UINT __stdcall SchedSecureObjects(
	__in MSIHANDLE hInstall
	)
{
//	AssertSz(FALSE, "debug SchedSecureObjects");
	HRESULT hr = S_OK;
	UINT er = ERROR_SUCCESS;

	LPWSTR pwzData = NULL;
	LPWSTR pwzTable = NULL;
	LPWSTR pwzTargetPath = NULL;
	LPWSTR pwzFormattedString = NULL;

	int iRoot = 0;
	int iAllUsers = 0;
	LPWSTR pwzKey = NULL;

	PMSIHANDLE hView = NULL;
	PMSIHANDLE hRec = NULL;

	MSIHANDLE hViewObject = NULL; // Don't free this since it's always a copy of either hViewService or hViewCreateFolder
	PMSIHANDLE hViewService = NULL;
	PMSIHANDLE hViewCreateFolder = NULL;
	PMSIHANDLE hViewFile = NULL;
	PMSIHANDLE hViewRegistry = NULL;
	PMSIHANDLE hRecObject = NULL;

	INSTALLSTATE isInstalled;
	INSTALLSTATE isAction;

	LPWSTR pwzCustomActionData = NULL;
	DWORD cchCustomActionData = 0;

	DWORD cObjects = 0;
	eOBJECTTYPE eType = OT_UNKNOWN;

	//
	// initialize
	//
	hr = WcaInitialize(hInstall, "SchedSecureObjects");
	ExitOnFailure(hr, "failed to initialize");

	//
	// loop through all the objects to be secured
	//
	hr = WcaOpenExecuteView(wzQUERY_SECUREOBJECTS, &hView);
	ExitOnFailure(hr, "failed to open view on SecureObjects table");
	while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
	{
		hViewObject = NULL;
		eType = OT_UNKNOWN;

		hr = WcaGetRecordString(hRec, QSO_TABLE, &pwzTable);
		ExitOnFailure(hr, "failed to get object table");

		// ensure we're looking at a known table
		if (0 == lstrcmpW(L"ServiceInstall", pwzTable))
		{
			eType = OT_SERVICE;
		}
		else if (0 == lstrcmpW(L"CreateFolder", pwzTable))
		{
			eType = OT_FOLDER;
		}
		else if (0 == lstrcmpW(L"File", pwzTable))
		{
			eType = OT_FILE;
		}
		else if (0 == lstrcmpW(L"Registry", pwzTable))
		{
			eType = OT_REGISTRY;
		}
		else
		{
			ExitOnFailure1(hr = E_INVALIDARG, "unknown SecureObject.Table: %S", pwzTable);
		}

		// if we haven't opened a view on the ServiceInstall/CreateFolder table, do that now
		if (OT_SERVICE == eType)
		{
			if (!hViewService)
			{
				hr = WcaTableExists(pwzTable);
				if (S_FALSE == hr)
					hr = E_UNEXPECTED;
				ExitOnFailure1(hr, "failed to open %s table to secure object", pwzTable);

				hr = WcaOpenView(wzQUERY_SERVICECOMPONENT, &hViewService);
				ExitOnFailure(hr, "failed to open view on ServiceInstall table");
			}

			hViewObject = hViewService;
		}
		else if (OT_FOLDER == eType)
		{
			if (!hViewCreateFolder)
			{
				hr = WcaTableExists(pwzTable);
				if (S_FALSE == hr)
					hr = E_UNEXPECTED;
				ExitOnFailure1(hr, "failed to open %s table to secure object", pwzTable);

				hr = WcaOpenView(wzQUERY_CREATEFOLDERCOMPONENT, &hViewCreateFolder);
				ExitOnFailure(hr, "failed to open view on CreateFolder table");
			}

			hViewObject = hViewCreateFolder;
		}
		else if (OT_FILE== eType)
		{
			if (!hViewFile)
			{
				hr = WcaTableExists(pwzTable);
				if (S_FALSE == hr)
					hr = E_UNEXPECTED;
				ExitOnFailure1(hr, "failed to open %s table to secure object", pwzTable);

				hr = WcaOpenView(wzQUERY_FILECOMPONENT, &hViewFile);
				ExitOnFailure(hr, "failed to open view on CreateFolder table");
			}

			hViewObject = hViewFile;
		}
		else if (OT_REGISTRY== eType)
		{
			if (!hViewRegistry)
			{
				hr = WcaTableExists(pwzTable);
				if (S_FALSE == hr)
					hr = E_UNEXPECTED;
				ExitOnFailure1(hr, "failed to open %s table to secure object", pwzTable);

				hr = WcaOpenView(wzQUERY_REGISTRYCOMPONENT, &hViewRegistry);
				ExitOnFailure(hr, "failed to open view on CreateFolder table");
			}

			hViewObject = hViewRegistry;
		}

		Assert(hViewObject);

		// execute a view looking for the object's Component_
		hr = WcaExecuteView(hViewObject, hRec);
		ExitOnFailure1(hr, "failed to execute view on %S table", pwzData);
		hr = WcaFetchSingleRecord(hViewObject, &hRecObject);
		ExitOnFailure(hr, "failed to fetch Component for secure object");

		hr = WcaGetRecordString(hRecObject, QSOC_COMPONENT, &pwzData);
		ExitOnFailure(hr, "failed to get Component name for secure object");

		//
		// if we are installing this Component
		//
		er = ::MsiGetComponentStateW(hInstall, pwzData, &isInstalled, &isAction);
		ExitOnFailure1(hr = HRESULT_FROM_WIN32(er), "failed to get install state for Component: %S", pwzData);

		if (WcaIsInstalling(isInstalled, isAction))
		{
			// add the data to the CustomActionData
			hr = WcaGetRecordString(hRecObject, QSOC_OBJECTNAME, &pwzData);
			ExitOnFailure(hr, "failed to get name of object");

			if (OT_SERVICE == eType)
			{
				hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
				ExitOnFailure(hr, "failed to add data to CustomActionData");
			}
			else if (OT_FOLDER == eType)
			{
				hr = WcaGetTargetPath(pwzData, &pwzTargetPath);
				ExitOnFailure1(hr, "failed to get target path for directory id: %S", pwzData);
				hr = WcaWriteStringToCaData(pwzTargetPath, &pwzCustomActionData);
				ExitOnFailure(hr, "failed to add data to CustomActionData");
			}
			else if (OT_FILE == eType)
			{
				hr = StrAllocFormatted(&pwzFormattedString, L"[#%s]", pwzData);
				ExitOnFailure1(hr, "failed to create formatted string for securing file object: %S", pwzData);

				hr = WcaGetFormattedString(pwzFormattedString, &pwzTargetPath);
				ExitOnFailure2(hr, "failed to get file path from formatted string: %S for secure object: %S", pwzFormattedString, pwzData);

				hr = WcaWriteStringToCaData(pwzTargetPath, &pwzCustomActionData);
				ExitOnFailure(hr, "failed to add data to CustomActionData");
			}
			else if (OT_REGISTRY == eType)
			{
				hr = WcaGetRecordInteger(hRecObject, QSOC_REGROOT, &iRoot);
				ExitOnFailure1(hr, "Failed to get reg key root for secure object: %S", pwzData);

				hr = WcaGetRecordFormattedString(hRecObject, QSOC_REGKEY, &pwzKey);
				ExitOnFailure1(hr, "Failed to get reg key for secure object: %S", pwzData);

				// Decode the root value
				if (-1 == iRoot)
				{
					// They didn't specify a root so that means it's either HKCU or HKLM depending on ALLUSERS property
					hr = WcaGetIntProperty(L"ALLUSERS", &iAllUsers);
					ExitOnFailure(hr, "failed to get value of ALLUSERS property");

					if (1 == iAllUsers)
					{
						hr = StrAllocString(&pwzTargetPath, L"MACHINE\\", 0);
						ExitOnFailure(hr, "failed to allocate target registry string with HKLM root");
					}
					else
					{
						hr = StrAllocString(&pwzTargetPath, L"CURRENT_USER\\", 0);
						ExitOnFailure(hr, "failed to allocate target registry string with HKCU root");
					}
				}
				else if (/*msidbRegistryRootClassesRoot*/ 0 == iRoot)
				{
					hr = StrAllocString(&pwzTargetPath, L"CLASSES_ROOT\\", 0);
					ExitOnFailure(hr, "failed to allocate target registry string with HKCR root");
				}
				else if (/*msidbRegistryRootCurrentUser*/ 1 == iRoot)
				{
					hr = StrAllocString(&pwzTargetPath, L"CURRENT_USER\\", 0);
					ExitOnFailure(hr, "failed to allocate target registry string with HKCU root");
				}
				else if (/*msidbRegistryRootLocalMachine*/ 2 == iRoot)
				{
					hr = StrAllocString(&pwzTargetPath, L"MACHINE\\", 0);
					ExitOnFailure(hr, "failed to allocate target registry string with HKLM root");
				}
				else if (/*msidbRegistryRootUsers*/ 3 == iRoot)
				{
					hr = StrAllocString(&pwzTargetPath, L"USERS\\", 0);
					ExitOnFailure(hr, "failed to allocate target registry string with HKU root");
				}
				else
				{
					ExitOnFailure2(hr = E_UNEXPECTED, "Unknown registry key root specified for secure object: '%S' root: %d", pwzData, iRoot);
				}

				hr = StrAllocConcat(&pwzTargetPath, pwzKey, 0);
				ExitOnFailure2(hr, "Failed to concat key: %S for secure object: %S", pwzKey, pwzData);

				hr = WcaWriteStringToCaData(pwzTargetPath, &pwzCustomActionData);
				ExitOnFailure(hr, "failed to add data to CustomActionData");
			}
			else
			{
				AssertSz(FALSE, "How did you get here?");
			}

			hr = WcaWriteStringToCaData(pwzTable, &pwzCustomActionData);
			ExitOnFailure(hr, "failed to add data to CustomActionData");

			hr = WcaGetRecordFormattedString(hRec, QSO_DOMAIN, &pwzData);
			ExitOnFailure(hr, "failed to get domain for user to configure object");
			hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
			ExitOnFailure(hr, "failed to add data to CustomActionData");

			hr = WcaGetRecordFormattedString(hRec, QSO_USER, &pwzData);
			ExitOnFailure(hr, "failed to get user to configure object");
			hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
			ExitOnFailure(hr, "failed to add data to CustomActionData");

			hr = WcaGetRecordString(hRec, QSO_PERMISSION, &pwzData);
			ExitOnFailure(hr, "failed to get domain for user to configure object");
			hr = WcaWriteStringToCaData(pwzData, &pwzCustomActionData);
			ExitOnFailure(hr, "failed to add data to CustomActionData");

			cObjects++;
		}
	}

	// if we looped through all records all is well
	if (E_NOMOREITEMS == hr)
		hr = S_OK;
	ExitOnFailure(hr, "failed while looping through all objects to secure");

	//
	// schedule the custom action and add to progress bar
	//
	if (pwzCustomActionData && *pwzCustomActionData)
	{
		Assert(0 < cObjects);

		hr = WcaDoDeferredAction(L"ExecSecureObjects", pwzCustomActionData, cObjects * COST_SECUREOBJECT);
		ExitOnFailure(hr, "failed to schedule ExecSecureObjects action");
	}

LExit:
	ReleaseStr(pwzCustomActionData);
	ReleaseStr(pwzData);
	ReleaseStr(pwzTable);
	ReleaseStr(pwzTargetPath);
	ReleaseStr(pwzFormattedString);
	ReleaseStr(pwzKey);

	if (FAILED(hr))
		er = ERROR_INSTALL_FAILURE;
	return WcaFinalize(er);
}
Exemplo n.º 2
0
/******************************************************************
 WixSchedInternetShortcuts - entry point

********************************************************************/
extern "C" UINT __stdcall WixSchedInternetShortcuts(
    __in MSIHANDLE hInstall
)
{
    HRESULT hr = S_OK;
    UINT er = ERROR_SUCCESS;

    UINT uiCost = 0;

    PMSIHANDLE hView = NULL;
    PMSIHANDLE hRec = NULL;

    MSIHANDLE hCreateFolderTable = NULL;
    MSIHANDLE hCreateFolderColumns = NULL;

    LPWSTR pwzCustomActionData = NULL;
    LPWSTR pwzComponent = NULL;
    LPWSTR pwzDirectory = NULL;
    LPWSTR pwzFilename = NULL;
    LPWSTR pwzTarget = NULL;
    LPWSTR pwzShortcutPath = NULL;
    int iAttr = 0;
    LPWSTR pwzIconFile = NULL;
    int iIconIndex = 0;
    IUniformResourceLocatorW* piURL = NULL;
    IShellLinkW* piShellLink = NULL;
    BOOL fInitializedCom = FALSE;

    hr = WcaInitialize(hInstall, "WixSchedInternetShortcuts");
    ExitOnFailure(hr, "failed to initialize WixSchedInternetShortcuts.");

    // anything to do?
    if (S_OK != WcaTableExists(L"WixInternetShortcut"))
    {
        WcaLog(LOGMSG_STANDARD, "WixInternetShortcut table doesn't exist, so there are no Internet shortcuts to process");
        goto LExit;
    }

    // check to see if we can create a shortcut - Server Core and others may not have a shell registered.  
    hr = ::CoInitialize(NULL);
    ExitOnFailure(hr, "failed to initialize COM");
    fInitializedCom = TRUE;

    hr = ::CoCreateInstance(CLSID_InternetShortcut, NULL, CLSCTX_ALL, IID_IUniformResourceLocatorW, (void**)&piURL);
    if (S_OK != hr)
    {
        WcaLog(LOGMSG_STANDARD, "failed to create an instance of IUniformResourceLocatorW, skipping shortcut creation");
        ExitFunction1(hr = S_OK);
    }

    hr = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_ALL, IID_IShellLinkW, (void**)&piShellLink);
    if (S_OK != hr)
    {
        WcaLog(LOGMSG_STANDARD, "failed to create an instance of IShellLinkW, skipping shortcut creation");
        ExitFunction1(hr = S_OK);
    }

    // query and loop through all the shortcuts
    hr = WcaOpenExecuteView(vcsShortcutsQuery, &hView);
    ExitOnFailure(hr, "failed to open view on WixInternetShortcut table");

    while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
    {
        // read column values
        hr = WcaGetRecordString(hRec, esqComponent, &pwzComponent);
        ExitOnFailure(hr, "failed to get shortcut component");
        hr = WcaGetRecordString(hRec, esqDirectory, &pwzDirectory);
        ExitOnFailure(hr, "failed to get shortcut directory");
        hr = WcaGetRecordString(hRec, esqFilename, &pwzFilename);
        ExitOnFailure(hr, "failed to get shortcut filename");
        hr = WcaGetRecordFormattedString(hRec, esqTarget, &pwzTarget);
        ExitOnFailure(hr, "failed to get shortcut target");
        hr = WcaGetRecordInteger(hRec, esqAttributes, &iAttr);
        ExitOnFailure(hr, "failed to get shortcut attributes");
        hr = WcaGetRecordFormattedString(hRec, esqIconFile, &pwzIconFile);
        ExitOnFailure(hr, "failed to get shortcut icon file");
        hr = WcaGetRecordInteger(hRec, esqIconIndex, &iIconIndex);
        ExitOnFailure(hr, "failed to get shortcut icon index");

        // skip processing this WixInternetShortcut row if the component isn't being configured
        WCA_TODO todo = WcaGetComponentToDo(pwzComponent);
        if (WCA_TODO_UNKNOWN == todo)
        {
            WcaLog(LOGMSG_VERBOSE, "Skipping shortcut for null-action component '%ls'", pwzComponent);
            continue;
        }

        // we need to create the directory where the shortcut is supposed to live; rather
        // than doing so in our deferred custom action, use the CreateFolder table to have MSI 
        // make (and remove) them on our behalf (including the correct cleanup of parent directories).
        MSIDBERROR dbError = MSIDBERROR_NOERROR;
        WcaLog(LOGMSG_STANDARD, "Adding folder '%ls', component '%ls' to the CreateFolder table", pwzDirectory, pwzComponent);
        hr = WcaAddTempRecord(&hCreateFolderTable, &hCreateFolderColumns, L"CreateFolder", &dbError, 0, 2, pwzDirectory, pwzComponent);
        if (MSIDBERROR_DUPLICATEKEY == dbError)
        {
            WcaLog(LOGMSG_STANDARD, "Folder '%ls' already exists in the CreateFolder table; the above error is harmless", pwzDirectory);
            hr = S_OK;
        }
        ExitOnFailure(hr, "Couldn't add temporary CreateFolder row");

        // only if we're installing/reinstalling do we need to schedule the deferred CA
        // (uninstallation is handled via permanent RemoveFile rows and temporary CreateFolder rows)
        if (WCA_TODO_INSTALL == todo || WCA_TODO_REINSTALL == todo)
        {
            // turn the Directory_ id into a path
            hr = WcaGetTargetPath(pwzDirectory, &pwzShortcutPath);
            ExitOnFailure(hr, "failed to allocate string for shortcut directory");

            // append the shortcut filename
            hr = StrAllocConcat(&pwzShortcutPath, pwzFilename, 0);
            ExitOnFailure(hr, "failed to allocate string for shortcut filename");

            // write the shortcut path and target to custom action data for deferred CAs
            hr = WcaWriteStringToCaData(pwzShortcutPath, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to write shortcut path to custom action data");
            hr = WcaWriteStringToCaData(pwzTarget, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to write shortcut target to custom action data");
            hr = WcaWriteIntegerToCaData(iAttr, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to write shortcut attributes to custom action data");
            hr = WcaWriteStringToCaData(pwzIconFile, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to write icon file to custom action data");
            hr = WcaWriteIntegerToCaData(iIconIndex, &pwzCustomActionData);
            ExitOnFailure(hr, "failed to write icon index to custom action data");

            uiCost += COST_INTERNETSHORTCUT;
        }
    }

    if (E_NOMOREITEMS == hr)
    {
        hr = S_OK;
    }
    ExitOnFailure(hr, "Failure occured while processing WixInternetShortcut table");

    // if we have any shortcuts to install
    if (pwzCustomActionData && *pwzCustomActionData)
    {
        // add cost to progress bar
        hr = WcaProgressMessage(uiCost, TRUE);
        ExitOnFailure(hr, "failed to extend progress bar for InternetShortcuts");

        // provide custom action data to deferred and rollback CAs
        hr = WcaSetProperty(PLATFORM_DECORATION(L"WixRollbackInternetShortcuts"), pwzCustomActionData);
        ExitOnFailure(hr, "failed to set WixRollbackInternetShortcuts rollback custom action data");
        hr = WcaSetProperty(PLATFORM_DECORATION(L"WixCreateInternetShortcuts"), pwzCustomActionData);
        ExitOnFailure(hr, "failed to set WixCreateInternetShortcuts custom action data");
    }

LExit:
    if (hCreateFolderTable)
    {
        ::MsiCloseHandle(hCreateFolderTable);
    }

    if (hCreateFolderColumns)
    {
        ::MsiCloseHandle(hCreateFolderColumns);
    }

    ReleaseStr(pwzCustomActionData);
    ReleaseStr(pwzComponent);
    ReleaseStr(pwzDirectory);
    ReleaseStr(pwzFilename);
    ReleaseStr(pwzTarget);
    ReleaseStr(pwzShortcutPath);
    ReleaseObject(piShellLink);
    ReleaseObject(piURL);

    if (fInitializedCom)
    {
        ::CoUninitialize();
    }

    er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
    return WcaFinalize(er);
}
Exemplo n.º 3
0
static HRESULT GetTargetPath(
    __in eOBJECTTYPE eType,
    __in LPCWSTR pwzSecureObject,
    __out LPWSTR* ppwzTargetPath
    )
{
    HRESULT hr = S_OK;

    PMSIHANDLE hView = NULL;
    PMSIHANDLE hRecObject = NULL;
    PMSIHANDLE hRec = NULL;

    int iRoot = 0;
    int iAllUsers = 0;
    LPWSTR pwzKey = NULL;
    LPWSTR pwzFormattedString = NULL;

    if (OT_SERVICE == eType)
    {
        hr = WcaTableExists(L"ServiceInstall");
        if (S_FALSE == hr)
        {
            hr = E_UNEXPECTED;
        }
        ExitOnFailure(hr, "failed to open ServiceInstall table to secure object");

        hr = WcaOpenView(wzQUERY_SERVICEINSTALL, &hView);
        ExitOnFailure(hr, "failed to open view on ServiceInstall table");

        // create a record that stores the object to secure
        hRec = MsiCreateRecord(1);
        MsiRecordSetStringW(hRec, 1, pwzSecureObject);

        // execute a view looking for the object's ServiceInstall.ServiceInstall row.
        hr = WcaExecuteView(hView, hRec);
        ExitOnFailure(hr, "failed to execute view on ServiceInstall table");
        hr = WcaFetchSingleRecord(hView, &hRecObject);
        ExitOnFailure(hr, "failed to fetch ServiceInstall row for secure object");

        hr = WcaGetRecordFormattedString(hRecObject, QSSI_NAME, ppwzTargetPath);
        ExitOnFailure1(hr, "failed to get service name for secure object: %ls", pwzSecureObject);
    }
    else if (OT_FOLDER == eType)
    {
        hr = WcaGetTargetPath(pwzSecureObject, ppwzTargetPath);
        ExitOnFailure1(hr, "failed to get target path for directory id: %ls", pwzSecureObject);
    }
    else if (OT_FILE == eType)
    {
        hr = StrAllocFormatted(&pwzFormattedString, L"[#%s]", pwzSecureObject);
        ExitOnFailure1(hr, "failed to create formatted string for securing file object: %ls", pwzSecureObject);

        hr = WcaGetFormattedString(pwzFormattedString, ppwzTargetPath);
        ExitOnFailure2(hr, "failed to get file path from formatted string: %ls for secure object: %ls", pwzFormattedString, pwzSecureObject);
    }
    else if (OT_REGISTRY == eType)
    {
        hr = WcaTableExists(L"Registry");
        if (S_FALSE == hr)
        {
            hr = E_UNEXPECTED;
        }
        ExitOnFailure(hr, "failed to open Registry table to secure object");

        hr = WcaOpenView(wzQUERY_REGISTRY, &hView);
        ExitOnFailure(hr, "failed to open view on Registry table");

        // create a record that stores the object to secure
        hRec = MsiCreateRecord(1);
        MsiRecordSetStringW(hRec, 1, pwzSecureObject);

        // execute a view looking for the object's Registry row
        hr = WcaExecuteView(hView, hRec);
        ExitOnFailure(hr, "failed to execute view on Registry table");
        hr = WcaFetchSingleRecord(hView, &hRecObject);
        ExitOnFailure(hr, "failed to fetch Registry row for secure object");

        hr = WcaGetRecordInteger(hRecObject, QSOC_REGROOT, &iRoot);
        ExitOnFailure1(hr, "Failed to get reg key root for secure object: %ls", pwzSecureObject);

        hr = WcaGetRecordFormattedString(hRecObject, QSOC_REGKEY, &pwzKey);
        ExitOnFailure1(hr, "Failed to get reg key for secure object: %ls", pwzSecureObject);

        // Decode the root value
        if (-1 == iRoot)
        {
            // They didn't specify a root so that means it's either HKCU or HKLM depending on ALLUSERS property
            hr = WcaGetIntProperty(L"ALLUSERS", &iAllUsers);
            ExitOnFailure(hr, "failed to get value of ALLUSERS property");

            if (1 == iAllUsers)
            {
                hr = StrAllocString(ppwzTargetPath, L"MACHINE\\", 0);
                ExitOnFailure(hr, "failed to allocate target registry string with HKLM root");
            }
            else
            {
                hr = StrAllocString(ppwzTargetPath, L"CURRENT_USER\\", 0);
                ExitOnFailure(hr, "failed to allocate target registry string with HKCU root");
            }
        }
        else if (msidbRegistryRootClassesRoot == iRoot)
        {
            hr = StrAllocString(ppwzTargetPath, L"CLASSES_ROOT\\", 0);
            ExitOnFailure(hr, "failed to allocate target registry string with HKCR root");
        }
        else if (msidbRegistryRootCurrentUser == iRoot)
        {
            hr = StrAllocString(ppwzTargetPath, L"CURRENT_USER\\", 0);
            ExitOnFailure(hr, "failed to allocate target registry string with HKCU root");
        }
        else if (msidbRegistryRootLocalMachine == iRoot)
        {
            hr = StrAllocString(ppwzTargetPath, L"MACHINE\\", 0);
            ExitOnFailure(hr, "failed to allocate target registry string with HKLM root");
        }
        else if (msidbRegistryRootUsers == iRoot)
        {
            hr = StrAllocString(ppwzTargetPath, L"USERS\\", 0);
            ExitOnFailure(hr, "failed to allocate target registry string with HKU root");
        }
        else
        {
            ExitOnFailure2(hr = E_UNEXPECTED, "Unknown registry key root specified for secure object: '%ls' root: %d", pwzSecureObject, iRoot);
        }
        
        hr = StrAllocConcat(ppwzTargetPath, pwzKey, 0);
        ExitOnFailure2(hr, "Failed to concat key: %ls for secure object: %ls", pwzKey, pwzSecureObject);
    }
    else
    {
        AssertSz(FALSE, "How did you get here?");
        ExitOnFailure1(hr = E_UNEXPECTED, "Unknown secure object type: %d", eType);
    }

LExit:
    ReleaseStr(pwzFormattedString);
    ReleaseStr(pwzKey);

    return hr;
}