home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sysmgmt / sms / smsapi / mgrp / mgrp.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-15  |  19.9 KB  |  651 lines

  1. // ====================================================================
  2. //
  3. //  File: mgrp.cpp
  4. //
  5. //  Copyright (C) 1996 by Microsoft Corporation.
  6. //
  7. //  Author:
  8. //      Jonathan Shuval     Microsoft Corp.
  9. //
  10. //
  11. //  This sample shows how to create a machine group and insert machines
  12. //  into it.
  13. //
  14. // ====================================================================
  15.  
  16.  
  17.  
  18. // ====================================================================
  19. //  Includes.
  20. // ====================================================================
  21. #include <afx.h>
  22. #include <smsapi.h>             // Header for the APIs.
  23. #include <time.h>               // For converting time scalars into string.
  24.  
  25. // Include the GetStatusName function.
  26. // -------------------------------------
  27. #include "..\common\status.inc"
  28.  
  29.  
  30.  
  31. // ====================================================================
  32. //  Defines.
  33. // ====================================================================
  34. #define CCH_MAXINPUT 256
  35.  
  36.  
  37.  
  38. // ====================================================================
  39. //  Local prototypes.
  40. // ====================================================================
  41.  
  42. // Does the real work.
  43. // -------------------------------------------------------------
  44. void doTheWork( HANDLE hConnect );
  45.  
  46.  
  47. // Set filters according to what container we're looking at.
  48. // -------------------------------------------------------------
  49. BOOL setMachFilters( HANDLE hConnect, HANDLE hContainer );
  50.  
  51.  
  52. // Functions to display folders, scalars, and expressions.
  53. // -------------------------------------------------------------
  54. void DisplayFolder( HANDLE hFolder );
  55. void DisplayScalars( HANDLE hFolder );
  56.  
  57.  
  58. // Prompt the user for input and return the reply.
  59. // -------------------------------------------------------------
  60. void InputString(const char* pszMessage, char* pszResult);
  61.  
  62.  
  63. // Connect to the SMS datasource.
  64. // -------------------------------------------------------------
  65. HANDLE ConnectToDatasource();
  66.  
  67.  
  68. // Display an error message with its SMS status value.
  69. // -------------------------------------------------------------
  70. void DisplaySmsError(const char* pszMessage, SMS_STATUS stat);
  71.  
  72.  
  73. // Get the string equivallent for an SMS status code.
  74. // -------------------------------------------------------------
  75. const char *GetStatusName(SMS_STATUS stat);
  76.  
  77. // Set a string scalar.
  78. // -------------------------------------------------------------
  79. SMS_STATUS SetScalarString( HANDLE hFolder, char *pszName, char *pszValue);
  80.  
  81.  
  82. // ====================================================================
  83. //
  84. //  Macros for checking status
  85. //
  86. // ====================================================================
  87.         // Void return
  88. #define CHKSTAT(str) if (stat != SMS_OK) { \
  89.         DisplaySmsError(str, stat);         \
  90.         return; }
  91.  
  92.         // Bool return
  93. #define CHKSTAT_RTN(str) if (stat != SMS_OK) { \
  94.         DisplaySmsError(str, stat);             \
  95.         return(FALSE); }
  96.  
  97.  
  98.  
  99. // ====================================================================
  100. //
  101. //  The work starts here.
  102. //
  103. // ====================================================================
  104. void main()
  105. {
  106.  
  107.     HANDLE hConnect;
  108.  
  109.     // Get and display API version.
  110.     // ----------------------------
  111.     char *pszVersion;
  112.     SmsAPIVer( &pszVersion );
  113.     printf("%s\n", pszVersion );
  114.  
  115.  
  116.  
  117.     //===========================================
  118.     // Connect to the SMS datasource.
  119.     //===========================================
  120.     hConnect = ConnectToDatasource();
  121.     if (hConnect == NULL) {
  122.         return;
  123.     }
  124.  
  125.  
  126.     // This loop allows us to do the real work multiple times.
  127.     // =======================================================
  128.     BOOL bDone = FALSE;
  129.     char reply[10];
  130.  
  131.     while (!bDone) {
  132.  
  133.         doTheWork( hConnect );
  134.  
  135.         printf("Restart [y/n]? "); gets(reply);
  136.         bDone = (reply[0] != 'y' && reply[0] != 'Y');
  137.     }
  138.  
  139.  
  140.     // Disconnect from the datasource.
  141.     // ===============================
  142.     SmsDataSourceDisconnect( hConnect );
  143.  
  144.  
  145. }  /* main */
  146.  
  147.  
  148.  
  149. // ====================================================================
  150. //
  151. //  This function does whatever work is required.
  152. //  In this case, it will:
  153. //      - open a machine group container
  154. //      - create a machine group folder
  155. //      - open a machine container
  156. //      - select machine folders from mach container that I want
  157. //          to copy to the mgrp folder
  158. //      - loop copying these machine folders to the mgrp folder
  159. //      - link and commit the mgrp folder
  160. //      - close everything
  161.  
  162. //
  163. // ====================================================================
  164. void doTheWork( HANDLE hConnect )
  165. {
  166.     HANDLE hMGrpContainer;
  167.     HANDLE hMachContainer;
  168.     SMS_STATUS stat;
  169.  
  170.     // Open the containers
  171.     // ===================
  172.     stat = SmsOpenContainer( C_MACHINEGROUP, hConnect, &hMGrpContainer );
  173.     if (stat != SMS_OK) {
  174.         DisplaySmsError("SmsOpenContainer (mach grp) failed", stat);
  175.         return;
  176.     }
  177.  
  178.     stat = SmsOpenContainer( C_MACHINE, hConnect, &hMachContainer );
  179.     if (stat != SMS_OK) {
  180.         DisplaySmsError("SmsOpenContainer (mach) failed", stat);
  181.         SmsCloseContainer( hMGrpContainer );
  182.         return;
  183.     }
  184.  
  185.  
  186.     // Create machine group folder
  187.     // ===========================
  188.     HANDLE hMGrpFolder;
  189.     stat = SmsCreateFolder( hMGrpContainer, F_MACHINEGROUP, "", &hMGrpFolder );
  190.     if (stat != SMS_OK) {
  191.         char szError[256];
  192.         sprintf(szError, "SmsCreateFolder failed to create MachineGroup folder");
  193.         DisplaySmsError(szError, stat);
  194.         SmsCloseContainer( hMGrpContainer );
  195.         SmsCloseContainer( hMachContainer );
  196.         return;
  197.     }
  198.  
  199.  
  200.  
  201.  
  202.     // Select machine folders that we want tp put in to the mgrp folder.
  203.     // Just get all the PC machines from the mach container for now.
  204.     // Set filter for arch PC only machines.
  205.     // =================================================================
  206.     setMachFilters( hConnect, hMachContainer );
  207.  
  208.     stat = SmsPopulate( hMachContainer, POP_SYNC, NULL );
  209.     if (stat != SMS_OK) {
  210.         DisplaySmsError("Bad return from SmsPopulate", stat);
  211.         // Close everything and return.
  212.         SmsCloseContainer( hMGrpContainer );
  213.         SmsCloseContainer( hMachContainer );
  214.         SmsCloseFolder( hMGrpFolder );
  215.         return;
  216.     }
  217.  
  218.  
  219.  
  220.     // Loop getting a handle to each machine folder and
  221.     // inserting it into the new mgroup folder.
  222.     // ================================================
  223.     DWORD ctFolders;
  224.     SmsGetFolderCount( hMachContainer, F_ANY, &ctFolders );
  225.     printf("\n======== Mach Container has %d folders\n", ctFolders);
  226.  
  227.     HANDLE hFolder;
  228.     char szFolderID[100];               // This folder's ID.
  229.     BOOL bValid = TRUE;
  230.  
  231.     for (DWORD dwLoop = 0; dwLoop < ctFolders; dwLoop++) {
  232.  
  233.         SmsGetNextFolder( hMachContainer, F_ANY, &hFolder );
  234.  
  235.         // Display message saying what we've got
  236.         // -------------------------------------
  237.         stat = SmsGetFolderID( hFolder, szFolderID );
  238.         printf("[%d] Got folder: %s, about to insert in new folder\n",
  239.                 dwLoop+1, szFolderID);
  240.  
  241.  
  242.         // Insert the machine folder into the machine group folder.
  243.         // This can't do a straight swap of parents since we want to keep
  244.         // the machine folder's relationship to his current parent.
  245.         // What this API does therefore is to make a *copy* of the folder
  246.         // and link this copy into the mach group folder (ie the mach group
  247.         // folder becomes the new folder's parent).
  248.         // This means that this API returns a handle to the newly-created
  249.         // folder.
  250.         // ================================================================
  251.         HANDLE hNewFolder;
  252.         stat = SmsDupFolder( hMGrpFolder, hFolder, &hNewFolder );
  253.         if (stat != SMS_OK) {
  254.             printf("Failure duplicating folder %s: %d\n", szFolderID, stat);
  255.             bValid = FALSE;
  256.             break;
  257.         }
  258.  
  259.         // Now we need to link and commit the new machine folder to
  260.         // the machine group folder.
  261.         // ========================================================
  262.         stat = SmsLinkFolder( hNewFolder );
  263.         if (stat != SMS_OK) {
  264.             printf("Failure linking folder %s: %d\n", szFolderID, stat);
  265.             goto CLOSE;
  266.         }
  267.  
  268.         stat = SmsCommitFolder( hNewFolder );
  269.         if (stat != SMS_OK && stat != SMS_PARENT_NEEDS_COMMIT) {
  270.             printf("Failure comitting folder %s: %d\n", szFolderID, stat);
  271.             goto CLOSE;
  272.         }
  273.  
  274.  
  275.  
  276.         SmsCloseFolder( hFolder );
  277.         SmsCloseFolder( hNewFolder );
  278.     }
  279.  
  280.  
  281.     // Set scalars for the mach group folder.
  282.     // ======================================
  283.     char szBuff[99];
  284.     InputString("Give me a unique name for the mach gp", szBuff);
  285.     SetScalarString( hMGrpFolder, "Name", szBuff );
  286.     SetScalarString( hMGrpFolder, "Comment", "some comment" );
  287.  
  288.     // Link mach grp folder into parent and commit it.
  289.     // ===============================================
  290.     stat = SmsLinkFolder( hMGrpFolder );
  291.     if (stat != SMS_OK) {
  292.         DisplaySmsError("SmsLinkFolder failed on the mach Group folder", stat);
  293.         goto CLOSE;
  294.     }
  295.  
  296.     // Write it back to data source.
  297.     // =============================
  298.     stat = SmsCommitFolder( hMGrpFolder );
  299.     if (stat != SMS_OK) {
  300.         DisplaySmsError("SmsCommitFolder failed on the mach Group folder", stat);
  301.         goto CLOSE;
  302.     }
  303.  
  304.  
  305.  
  306.     // If we got here then all seems to be ok.
  307.     // Display the mach group folder
  308.     // =======================================
  309.     DisplayFolder( hMGrpFolder );
  310.  
  311.     // Close everything - we're done.
  312.     // ==============================
  313. CLOSE:
  314.     SmsCloseContainer( hMGrpContainer );
  315.     SmsCloseContainer( hMachContainer );
  316.     SmsCloseFolder( hMGrpFolder );
  317.  
  318.  
  319.     printf("\n********* All done ***************\n");
  320.  
  321. }
  322.  
  323.  
  324.  
  325.  
  326. // ====================================================================
  327. //  We are passed in a handle to a folder. We retrieve the folder's
  328. //  information, displaying scalars if any.
  329. //  We then recursively examine sub-folders (after closing the
  330. //  current folder).
  331. // ====================================================================
  332. void DisplayFolder( HANDLE hFolder )
  333. {
  334.  
  335.     SMS_STATUS stat;
  336.     HANDLE hSubFolder;
  337.     DWORD fType;                   // type of folder we're dealing with.
  338.     char szfType[30];                   // type as a string.
  339.     DWORD totFolders;                   // Total number of sub-folders of
  340.                                         // all types.
  341.     char szFolderID[100];               // This folder's ID.
  342.     DWORD ctScalars;                    // How many scalars in this folder.
  343.  
  344.     printf("\n============================================================\n");
  345.  
  346.     // Get folder type and id.
  347.     // -----------------------
  348.     stat = SmsGetFolderID( hFolder, szFolderID );
  349.     if (stat != SMS_OK) {
  350.         if (stat == SMS_NEW_FOLDER) {
  351.             strcpy(szFolderID, "**New folder**");
  352.         } else {
  353.             CHKSTAT("SmsGetFolderID");
  354.         }
  355.     }
  356.  
  357.     stat = SmsGetFolderType( hFolder, &fType, szfType );
  358.     CHKSTAT("SmsGetFolderType");
  359.     printf("Folder ID \"%s\" is a %s\n\n", szFolderID, szfType);
  360.  
  361.     // How many scalars in this folder.
  362.     // --------------------------------------------------------
  363.     stat = SmsGetScalarCount( hFolder, &ctScalars );
  364.     CHKSTAT("SmsGetScalarCount");
  365.     printf("Contains %d scalars\n\n", ctScalars);
  366.     DisplayScalars( hFolder );
  367.  
  368.  
  369.     // Get count of all sub-folders (ie of all types).
  370.     // and allocate space for their handles.
  371.     // -----------------------------------------------
  372.     stat = SmsGetFolderCount( hFolder, F_ANY, &totFolders );
  373.     printf("Contains %d folders\n\n", totFolders);
  374.  
  375.     char szSubFolderID[100];
  376.     DWORD ctFolders;
  377.     HANDLE *phFolders;
  378.     phFolders = (HANDLE *)malloc(totFolders * sizeof(HANDLE));
  379.  
  380.  
  381.     // This loop gets the sub-folder IDs and displays them.
  382.     // ====================================================
  383.  
  384.     for (ctFolders = 0; ctFolders < totFolders; ctFolders++) {
  385.  
  386.         // Get a handle to a sub-folder.
  387.         // -----------------------------
  388.         stat = SmsGetNextFolder( hFolder, F_ANY, &hSubFolder );
  389.         CHKSTAT("SmsGetNextFolder");
  390.         phFolders[ctFolders] = hSubFolder;
  391.  
  392.         // Get and display the sub-folder's ID.
  393.         // ------------------------------------
  394.         stat = SmsGetFolderID( hSubFolder, szSubFolderID );
  395.         CHKSTAT("SmsGetFolderID");
  396.         printf("\tSub-folder: \"%s\"\n", szSubFolderID);
  397.     }
  398.  
  399.  
  400.     // =======================================================
  401.     // We can now release the handle that was passed in to us.
  402.     // If we wait until the function returns then, because we
  403.     // recurse, we don't release it till the very end.
  404.     // =======================================================
  405.     SmsCloseFolder( hFolder );
  406.  
  407.     // This loop gets the sub-folders and displays them.
  408.     // =================================================
  409.     for (ctFolders = 0; ctFolders < totFolders; ctFolders++) {
  410.         DisplayFolder( phFolders[ctFolders] );
  411.     }
  412.  
  413.     // Free the folder handle array.
  414.     // -----------------------------
  415.     free( phFolders );
  416.  
  417. }  /* DisplayFolder */
  418.  
  419.  
  420.  
  421. // ====================================================================
  422. //
  423. //  Display all the scalars for the folder.
  424. //
  425. // Note: the buffer for string scalars has been deliberately set to a
  426. // value lower than the maximum. If we encounter a string scalar whose
  427. // value exceeds this amount then we will print the 'data truncated'
  428. // message.
  429. //
  430. // ====================================================================
  431. void DisplayScalars( HANDLE hFolder )
  432. {
  433.     SMS_STATUS stat = SMS_OK;
  434.     SCALAR scalar;
  435.     char szName[50];                        // Buffer for name.
  436.     char szValue[SMS_DATA_BUFF_SIZE+1];     // Buffer for string value.
  437.     BYTE byValue[SMS_DATA_BUFF_SIZE+1];     // Buffer for binary scalars.
  438.     scalar.pszName  = szName;
  439.     scalar.pszValue = szValue;
  440.     scalar.pValue   = byValue;
  441.  
  442.     char *pszTime;          // For time scalars.
  443.  
  444.  
  445.     while (1) {
  446.  
  447.         scalar.dwLen = sizeof(szValue)-1;       // must tell him the size
  448.  
  449.         stat = SmsGetNextScalar( hFolder, &scalar);
  450.         if (stat != SMS_OK && stat != SMS_MORE_DATA) {
  451.             break;
  452.         }
  453.  
  454.         if (stat == SMS_MORE_DATA) {
  455.             printf("Receive buffer too small, should be %d. Data truncated\n",
  456.                             scalar.dwLen);
  457.         }
  458.         // Check scalar type, display accordingly.
  459.         // ---------------------------------------
  460.         switch (scalar.scType) {
  461.         case SCALAR_STRING:
  462.             printf("\t%30s: %s\n", scalar.pszName, scalar.pszValue);
  463.             break;
  464.  
  465.         case SCALAR_INT:
  466.             printf("\t%30s: %ld\n", scalar.pszName, scalar.dwValue);
  467.             break;
  468.  
  469.         case SCALAR_TIME:
  470.             // If there is a string equivalence use it.
  471.             if (scalar.bStringEquivalence) {
  472.                 printf("\t%30s: %s\n", scalar.pszName, scalar.pszValue);
  473.             } else {
  474.                 pszTime = ctime( &scalar.tValue );
  475.                 printf("\t%30s: %s", scalar.pszName, pszTime);
  476.             }
  477.             break;
  478.  
  479.         case SCALAR_BINARY:
  480.             // Got binary data.
  481.             // Just tell the user how much data there is.
  482.             printf("\t%30s: Binary data - %d bytes of data\n",
  483.                         scalar.pszName, scalar.dwLen);
  484.             break;
  485.         }
  486.     }
  487.  
  488.     // Why did we exit (other than no more scalars)?
  489.     // ---------------------------------------------
  490.     if (stat != SMS_NO_MORE_DATA) {
  491.         DisplaySmsError("Bad return from Scalar access", stat);
  492.     }
  493.  
  494.     // Terminate with newline.
  495.     // -----------------------
  496.     printf("\n");
  497.  
  498. }
  499.  
  500.  
  501.  
  502.  
  503. // ********************************************************************
  504. //      Helper functions.
  505. // ********************************************************************
  506.  
  507.  
  508.  
  509.  
  510. // ====================================================================
  511. // This function sets the filters when we are looking at a Machine
  512. // container.
  513. //
  514. // Want only PC archs, so we set an architecture filter.
  515. //
  516. // ====================================================================
  517. BOOL setMachFilters( HANDLE hConnect, HANDLE hContainer )
  518. {
  519.     HANDLE hFilter;
  520.  
  521.  
  522.     // =========================================================
  523.     // Architecture filter.
  524.     // Architecture = Personal Computer.
  525.     // =========================================================
  526.     SmsCreateFilter( ARCHITECTURE_FILTER, hConnect, &hFilter );
  527.  
  528.     TOKEN ArchToken;
  529.     memset( &ArchToken, 0, sizeof(TOKEN) );
  530.  
  531.     strcpy( ArchToken.szName, "Architecture" );
  532.     strcpy( ArchToken.szValue, "Personal Computer" );
  533.     ArchToken.dwOp = QOP_STR_EQ;
  534.  
  535.     SmsAddToken( hFilter, OP_OR, &ArchToken, 0 );
  536.  
  537.     SmsSetFilter( hContainer, hFilter );
  538.     SmsCloseFilter( hFilter );
  539.  
  540.     SmsCloseFilter( hFilter );
  541.  
  542.     return(TRUE);
  543.  
  544. }  /* setMachFilters */
  545.  
  546.  
  547.  
  548.  
  549.  
  550. // ====================================================================
  551. // InputString
  552. //
  553. // Prompt the user to input a string and return the string in the
  554. // specified buffer.
  555. //
  556. // Parameters:
  557. //      const char* pszMessage
  558. //          The user prompt to display.
  559. //
  560. //      char* pszResult
  561. //          Pointer to the buffer where the user's input will be returned.
  562. //
  563. // Returns;
  564. //      The user's input is returned via the given buffer.
  565. //
  566. // ====================================================================
  567. void InputString(const char* pszMessage, char* pszResult)
  568. {
  569.     printf("%s: ", pszMessage);
  570.     gets(pszResult);
  571. }
  572.  
  573.  
  574.  
  575.  
  576. // ====================================================================
  577. // ConnectToDatasource
  578. //
  579. // Get the datasource connection information from the user and use it
  580. // to connect to the datasource.
  581. //
  582. // Parameters:  None.
  583. //
  584. // Returns:
  585. //      The connection handle or NULL if the connection failed.
  586. //
  587. // ====================================================================
  588. HANDLE ConnectToDatasource()
  589. {
  590.     // Get the information we need to connect to the
  591.     // data source from the user.
  592.     //==============================================
  593.     char szServer[CCH_MAXINPUT];
  594.     char szUser[CCH_MAXINPUT];
  595.     char szPasswd[CCH_MAXINPUT];
  596.     char szDatabase[CCH_MAXINPUT];
  597.  
  598.     printf("\n");
  599.     printf("**************************\n");
  600.     printf("* Connect to data source *\n");
  601.     printf("**************************\n");
  602.     InputString("SQL server name", szServer);
  603.     InputString("SQL database name", szDatabase);
  604.     InputString("User name for SQL server", szUser);
  605.     InputString("Password for SQL server", szPasswd);
  606.     printf("\n");
  607.  
  608.  
  609.     // Connect to a data source. SQL in this case.
  610.     // ===========================================
  611.     DATASOURCE dsParams;
  612.  
  613.     dsParams.sqlParams.ds          = DB_SQL;
  614.     dsParams.sqlParams.pszServer   = szServer;
  615.     dsParams.sqlParams.pszUserName = szUser;
  616.     dsParams.sqlParams.pszPasswd   = szPasswd;
  617.     dsParams.sqlParams.pszDbName   = szDatabase;
  618.     dsParams.sqlParams.pFunc       = NULL;         // No encryption.
  619.     dsParams.sqlParams.pszKey      = "";
  620.  
  621.     HANDLE hConnect;
  622.     SMS_STATUS stat;
  623.     stat = SmsDataSourceConnect( &dsParams, &hConnect);
  624.  
  625.     if (stat != SMS_OK) {
  626.         hConnect = NULL;
  627.         DisplaySmsError("Connect to data source failed", stat);
  628.     }
  629.  
  630.     return( hConnect );
  631. }
  632.  
  633.  
  634.  
  635. SMS_STATUS SetScalarString(HANDLE hFolder, char* pszName, char* pszValue)
  636. {
  637.     SCALAR sc;
  638.     sc.pszName = pszName;
  639.     sc.scType = SCALAR_STRING;
  640.     sc.pszValue = pszValue;
  641.  
  642.     SMS_STATUS stat;
  643.     stat = SmsSetScalar(hFolder, &sc);
  644.     return( stat );
  645. }
  646.  
  647.  
  648.  
  649. /* EOF: mgrp.cpp */
  650.  
  651.