UINT __stdcall FillListbox(MSIHANDLE hInstall) { HRESULT hr = S_OK; UINT er = ERROR_SUCCESS; hr = WcaInitialize(hInstall, "FillListbox"); ExitOnFailure(hr, "Failed to initialize"); WcaLog(LOGMSG_STANDARD, "Initialized."); // TODO: Add your custom action code here. MSIHANDLE hTable = NULL; MSIHANDLE hColumns = NULL; MSIDBERROR dbErr = MSIDBERROR_NOERROR; WcaLog(LOGMSG_STANDARD, "AddingTempRecord %d hTable = %x hColumns = %x dbErr = %d.", 0, hTable, hColumns, dbErr); hr = WcaAddTempRecord (&hTable, &hColumns, L"ListBox", &dbErr, 0, 3, L"LISTBOXVALUES", 1, L"Item 1"); WcaLog(LOGMSG_STANDARD, "AddingTempRecord %d hTable = %x hColumns = %x dbErr = %d.", 1, hTable, hColumns, dbErr); hr = WcaAddTempRecord (&hTable, &hColumns, L"ListBox", &dbErr, 0, 3, L"LISTBOXVALUES", 2, L"Item 2"); WcaLog(LOGMSG_STANDARD, "AddingTempRecord %d hTable = %x hColumns = %x dbErr = %d.", 2, hTable, hColumns, dbErr); hr = WcaAddTempRecord (&hTable, &hColumns, L"ListBox", &dbErr, 0, 3, L"LISTBOXVALUES", 3, L"Item 3"); WcaLog(LOGMSG_STANDARD, "AddingTempRecord %d hTable = %x hColumns = %x dbErr = %d.", 3, hTable, hColumns, dbErr); if (hTable) MsiCloseHandle (hTable); if (hColumns) MsiCloseHandle (hColumns); LExit: er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; return WcaFinalize(er); }
extern "C" UINT __stdcall FillListbox(MSIHANDLE hInstall) { HRESULT hResult = WcaInitialize(hInstall, "FillListbox"); if (FAILED(hResult)) return ERROR_INSTALL_FAILURE; MSIHANDLE hTable = NULL; MSIHANDLE hColumns = NULL; hResult = WcaAddTempRecord(&hTable, &hColumns, L"ListBox", NULL, 0, 3, L"LISTBOXVALUES", 1, L"Item 1"); hResult = WcaAddTempRecord(&hTable, &hColumns, L"ListBox", NULL, 0, 3, L"LISTBOXVALUES", 2, L"Item 2"); hResult = WcaAddTempRecord(&hTable, &hColumns, L"ListBox", NULL, 0, 3, L"LISTBOXVALUES", 3, L"Item 3"); if (hTable) MsiCloseHandle(hTable); if (hColumns) MsiCloseHandle(hColumns); return WcaFinalize(hResult); }
/****************************************************************** 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); }
static HRESULT RecursePath( __in_z LPCWSTR wzPath, __in_z LPCWSTR wzId, __in_z LPCWSTR wzComponent, __in_z LPCWSTR wzProperty, __in int iMode, __inout DWORD* pdwCounter, __inout MSIHANDLE* phTable, __inout MSIHANDLE* phColumns ) { HRESULT hr = S_OK; DWORD er; LPWSTR sczSearch = NULL; LPWSTR sczProperty = NULL; HANDLE hFind = INVALID_HANDLE_VALUE; WIN32_FIND_DATAW wfd; LPWSTR sczNext = NULL; // First recurse down to all the child directories. hr = StrAllocFormatted(&sczSearch, L"%s*", wzPath); ExitOnFailure1(hr, "Failed to allocate file search string in path: %S", wzPath); hFind = ::FindFirstFileW(sczSearch, &wfd); if (INVALID_HANDLE_VALUE == hFind) { er = ::GetLastError(); if (ERROR_PATH_NOT_FOUND == er) { ExitFunction1(hr = S_FALSE); } else { hr = HRESULT_FROM_WIN32(er); } ExitOnFailure1(hr, "Failed to find all files in path: %S", wzPath); } do { // Skip files and the dot directories. if (FILE_ATTRIBUTE_DIRECTORY != (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || L'.' == wfd.cFileName[0] && (L'\0' == wfd.cFileName[1] || (L'.' == wfd.cFileName[1] && L'\0' == wfd.cFileName[2]))) { continue; } hr = StrAllocFormatted(&sczNext, L"%s%s\\", wzPath, wfd.cFileName); ExitOnFailure2(hr, "Failed to concat filename '%S' to string: %S", wfd.cFileName, wzPath); hr = RecursePath(sczNext, wzId, wzComponent, wzProperty, iMode, pdwCounter, phTable, phColumns); ExitOnFailure1(hr, "Failed to recurse path: %S", sczNext); } while (::FindNextFileW(hFind, &wfd)); er = ::GetLastError(); if (ERROR_NO_MORE_FILES == er) { hr = S_OK; } else { hr = HRESULT_FROM_WIN32(er); ExitOnFailure1(hr, "Failed while looping through files in directory: %S", wzPath); } // Finally, set a property that points at our path. hr = StrAllocFormatted(&sczProperty, L"_%s_%u", wzProperty, *pdwCounter); ExitOnFailure1(hr, "Failed to allocate Property for RemoveFile table with property: %S.", wzProperty); ++(*pdwCounter); hr = WcaSetProperty(sczProperty, wzPath); ExitOnFailure2(hr, "Failed to set Property: %S with path: %S", sczProperty, wzPath); // Add the row to remove any files and another row to remove the folder. hr = WcaAddTempRecord(phTable, phColumns, L"RemoveFile", NULL, 1, 5, L"RfxFiles", wzComponent, L"*.*", sczProperty, iMode); ExitOnFailure2(hr, "Failed to add row to remove all files for WixRemoveFolderEx row: %S under path:", wzId, wzPath); hr = WcaAddTempRecord(phTable, phColumns, L"RemoveFile", NULL, 1, 5, L"RfxFolder", wzComponent, NULL, sczProperty, iMode); ExitOnFailure2(hr, "Failed to add row to remove folder for WixRemoveFolderEx row: %S under path: %S", wzId, wzPath); LExit: if (INVALID_HANDLE_VALUE != hFind) { ::FindClose(hFind); } ReleaseStr(sczNext); ReleaseStr(sczProperty); ReleaseStr(sczSearch); return hr; }