home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 June / Chip_2001-06_cd1.bin / zkuste / vbasic / Data / Utility / MSISDK15.msi / Process.cpp < prev    next >
C/C++ Source or Header  |  2000-10-05  |  9KB  |  249 lines

  1. #if 0  // makefile definitions
  2. DESCRIPTION = Process UserAccounts Database Table
  3. MODULENAME = process
  4. FILEVERSION = Msi
  5. ENTRY = ProcessUserAccounts,UninstallUserAccounts
  6. LINKLIBS = netapi32.lib
  7. UNICODE=1
  8. !include "..\TOOLS\MsiTool.mak"
  9. !if 0  #nmake skips the rest of this file
  10. #endif // end of makefile definitions
  11.  
  12. // Required headers
  13. #define WINDOWS_LEAN_AND_MEAN  // faster compile
  14. #include <windows.h>
  15. #ifndef RC_INVOKED    // start of source code
  16.  
  17. #include "msiquery.h"
  18. #include <windows.h>
  19. #include <basetsd.h>
  20. #include <lm.h>
  21.  
  22. #define UNICODE 1
  23.  
  24. //+-------------------------------------------------------------------------
  25. //
  26. //  Microsoft Windows
  27. //
  28. //  Copyright (C) Microsoft Corporation, 2000
  29. //
  30. //  File:       process.cpp
  31. //
  32. //  Notes: DLL custom actions, must be used in conjunction with the DLL
  33. //         custom actions included in create.cpp and remove.cpp
  34. //--------------------------------------------------------------------------
  35.  
  36. //-----------------------------------------------------------------------------------------
  37. //
  38. // BUILD Instructions
  39. //
  40. // notes:
  41. //    - SDK represents the full path to the install location of the
  42. //     Windows Installer SDK
  43. //
  44. // Using NMake:
  45. //        %vcbin%\nmake -f process.cpp include="%include;SDK\Include" lib="%lib%;SDK\Lib"
  46. //
  47. // Using MsDev:
  48. //        1. Create a new Win32 DLL project
  49. //      2. Add process.cpp to the project
  50. //      3. Add SDK\Include and SDK\Lib directories on the Tools\Options Directories tab
  51. //      4. Add msi.libto the library list in the Project Settings dialog
  52. //          (in addition to the standard libs included by MsDev)
  53. //      5. Add /DUNICODE to the project options in the Project Settings dialog
  54. //
  55. //------------------------------------------------------------------------------------------
  56.  
  57. //////////////////////////////////////////////////////////////////////////
  58. // ProcessUserAccounts (resides in process.dll)
  59. //
  60. //     Process the UserAccounts custom table generating deferred actions
  61. //       to handle account creation (requires elevated priviledges) and
  62. //       rollback
  63. //
  64. UINT __stdcall ProcessUserAccounts(MSIHANDLE hInstall)
  65. {
  66.     PMSIHANDLE hDatabase = ::MsiGetActiveDatabase(hInstall);
  67.     PMSIHANDLE hView = 0;
  68.     
  69.     //
  70.     // constants -- custom action names, SQL query, separator
  71.     //
  72.     // wszCreateCA = name of deferred CA to create account
  73.     // wszRollbackCA = name of rollback CA to rollback account creation
  74.     //
  75.     const WCHAR wszCreateCA[] = L"CreateAccount";
  76.     const WCHAR wszRollbackCA[] = L"RollbackAccount";
  77.     const WCHAR wszSQL[] = L"SELECT `UserName`, `TempPassWord`, `Attributes` FROM `CustomUserAccounts`";
  78.     const WCHAR wchSep = '\001';
  79.  
  80.     UINT uiStat;
  81.     if (ERROR_SUCCESS != (uiStat = ::MsiDatabaseOpenViewW(hDatabase, wszSQL, &hView)))
  82.     {
  83.         if (ERROR_BAD_QUERY_SYNTAX == uiStat)
  84.             return ERROR_SUCCESS; // table not present
  85.         else
  86.             return ERROR_INSTALL_FAILURE; // error -- should never happen
  87.     }
  88.     if (ERROR_SUCCESS != (uiStat = ::MsiViewExecute(hView, 0)))
  89.         return ERROR_INSTALL_FAILURE; // error -- should never happen
  90.  
  91.     // Fetch all entries from the CustomUserAccounts table
  92.     PMSIHANDLE hRecFetch = 0;
  93.     while (ERROR_SUCCESS == (uiStat = ::MsiViewFetch(hView, &hRecFetch)))
  94.     {
  95.         // Obtain user name
  96.         WCHAR* wszUser = 0;
  97.         DWORD dwUser = 0;
  98.         ::MsiRecordGetStringW(hRecFetch, 1, L"", &dwUser);
  99.         wszUser = new WCHAR[++dwUser];
  100.         if (ERROR_SUCCESS != ::MsiRecordGetStringW(hRecFetch, 1, wszUser, &dwUser))
  101.         {
  102.             if (wszUser)
  103.                 delete [] wszUser;
  104.             return ERROR_INSTALL_FAILURE; // error -- should never happen
  105.         }
  106.         
  107.         // Obtain temporary password
  108.         WCHAR* wszPassWd = 0;
  109.         DWORD dwPassWd = 0;
  110.         ::MsiRecordGetStringW(hRecFetch, 2, L"", &dwPassWd);
  111.         wszPassWd = new WCHAR[++dwPassWd];
  112.         if (ERROR_SUCCESS != ::MsiRecordGetStringW(hRecFetch, 2, wszPassWd, &dwPassWd))
  113.         {
  114.             if (wszUser)
  115.                 delete [] wszUser;
  116.             if (wszPassWd)
  117.                 delete [] wszPassWd;
  118.             return ERROR_INSTALL_FAILURE; // error -- should never happen
  119.         }
  120.         
  121.         // Obtain attributes of user account
  122.         WCHAR* wszAttrib  = 0;
  123.         DWORD dwAttrib = 0;
  124.         ::MsiRecordGetStringW(hRecFetch, 3, L"", &dwAttrib);
  125.         wszAttrib = new WCHAR[++dwAttrib];
  126.         if (ERROR_SUCCESS != ::MsiRecordGetStringW(hRecFetch, 3, wszAttrib, &dwAttrib))
  127.         {
  128.             if (wszUser)
  129.                 delete [] wszUser;
  130.             if (wszPassWd)
  131.                 delete [] wszPassWd;
  132.             if (wszAttrib)
  133.                 delete [] wszAttrib;
  134.             return ERROR_INSTALL_FAILURE; // error -- should never happen
  135.         }
  136.  
  137.         // Generate the customized property that the deferred action will read
  138.         WCHAR* wszBuf = new WCHAR[dwUser + dwPassWd + dwAttrib + 4];
  139.         wsprintf(wszBuf, L"%s%c%s%c%s", wszUser, wchSep, wszPassWd, wchSep, wszAttrib);
  140.  
  141.         // Add action data (template is in ActionText table), but do not display temp passwd
  142.         PMSIHANDLE hRecInfo = ::MsiCreateRecord(2);
  143.         ::MsiRecordSetStringW(hRecInfo, 1, wszUser);
  144.         ::MsiRecordSetStringW(hRecInfo, 2, wszAttrib);
  145.         ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ACTIONDATA, hRecInfo);
  146.  
  147.         // Rollback custom action goes first
  148.         // Create a rollback custom action (in case install is stopped and rolls back)
  149.         // Rollback custom action can't read tables, so we have to set a property
  150.         ::MsiSetPropertyW(hInstall, wszRollbackCA, wszUser);
  151.         ::MsiDoActionW(hInstall, wszRollbackCA);
  152.  
  153.         // Create a deferred custom action (gives us the right priviledges to create the user account)
  154.         // Deferred custom actions can't read tables, so we have to set a property
  155.         ::MsiSetPropertyW(hInstall, wszCreateCA, wszBuf);
  156.         ::MsiDoActionW(hInstall, wszCreateCA);
  157.  
  158.  
  159.         if (wszBuf)
  160.             delete [] wszBuf;
  161.         if (wszUser)
  162.             delete [] wszUser;
  163.         if (wszPassWd)
  164.             delete [] wszPassWd;
  165.         if (wszAttrib)
  166.             delete [] wszAttrib;
  167.     }
  168.     return (ERROR_NO_MORE_ITEMS != uiStat) ? ERROR_INSTALL_FAILURE : ERROR_SUCCESS;
  169. }
  170.  
  171. //////////////////////////////////////////////////////////////////////////
  172. // UninstallUserAccounts (resides in process.dll)
  173. //
  174. //     Process the UserAccounts custom table generating deferred actions
  175. //       to handle removal of user accounts
  176. //
  177. UINT __stdcall UninstallUserAccounts(MSIHANDLE hInstall)
  178. {
  179.     //
  180.     // constants -- custom action name SQL query
  181.     //
  182.     // wszRemoveCA = name of deferred CA to remove user account
  183.     //
  184.     const WCHAR wszRemoveCA[] = L"RemoveAccount";
  185.     const WCHAR wszSQL[] = L"SELECT `UserName` FROM `CustomUserAccounts`";
  186.  
  187.     PMSIHANDLE hDatabase = ::MsiGetActiveDatabase(hInstall);
  188.     PMSIHANDLE hView = 0;
  189.  
  190.     UINT uiStat;
  191.     if (ERROR_SUCCESS != (uiStat = ::MsiDatabaseOpenViewW(hDatabase, wszSQL, &hView)))
  192.     {
  193.         if (ERROR_BAD_QUERY_SYNTAX == uiStat)
  194.             return ERROR_SUCCESS; // table not present
  195.         else
  196.             return ERROR_INSTALL_FAILURE; // error -- should never happen
  197.     }
  198.  
  199.     if (ERROR_SUCCESS != (uiStat = ::MsiViewExecute(hView, 0)))
  200.         return ERROR_INSTALL_FAILURE; // error -- should never happen
  201.  
  202.     // Fetch all entries from the UserAccounts custom table
  203.     PMSIHANDLE hRecFetch = 0;
  204.     while (ERROR_SUCCESS == (uiStat = ::MsiViewFetch(hView, &hRecFetch)))
  205.     {
  206.         // Obtain user name
  207.         WCHAR* wszUser = 0;
  208.         DWORD dwUser = 0;
  209.         ::MsiRecordGetStringW(hRecFetch, 1, L"", &dwUser);
  210.         wszUser = new WCHAR[++dwUser];
  211.         if (ERROR_SUCCESS != ::MsiRecordGetStringW(hRecFetch, 1, wszUser, &dwUser))
  212.         {
  213.             if (wszUser)
  214.                 delete [] wszUser;
  215.             return ERROR_INSTALL_FAILURE; // error -- should never happen
  216.         }
  217.         
  218.         // Send ActionData message (template is in ActionText table)
  219.         PMSIHANDLE hRecInfo = ::MsiCreateRecord(1);
  220.         ::MsiRecordSetStringW(hRecInfo, 1, wszUser);
  221.         ::MsiProcessMessage(hInstall, INSTALLMESSAGE_ACTIONDATA, hRecInfo);
  222.  
  223.         // We can't do a rollback custom action here (well, we could, but it wouldn't be correct)
  224.         // After a user account has been deleted, it cannot be recreated exactly as it was before
  225.         // because it will have been assigned a new SID.  In the case of uninstall, we won't
  226.         // rollback the deletion.
  227.  
  228.         // Create a deferred custom action (gives us the right priviledges to create the user account)
  229.         // Deferred custom actions can't read tables, so we have to set a property
  230.         ::MsiSetPropertyW(hInstall, wszRemoveCA, wszUser);
  231.         ::MsiDoActionW(hInstall, wszRemoveCA);
  232.  
  233.         if (wszUser)
  234.             delete [] wszUser;
  235.     }
  236.     if (ERROR_NO_MORE_ITEMS != uiStat)
  237.         return ERROR_INSTALL_FAILURE; // error -- should never happen
  238.  
  239.     return ERROR_SUCCESS;
  240. }
  241.  
  242. #else // RC_INVOKED, end of source code, start of resources
  243. // resource definition go here
  244.  
  245. #endif // RC_INVOKED
  246. #if 0 
  247. !endif // makefile terminator
  248. #endif
  249.