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 / newpkg / newpkg.cpp < prev    next >
C/C++ Source or Header  |  1996-10-15  |  42KB  |  1,353 lines

  1. //**************************************************************************
  2. // Copyright (C) 1995 by Microsoft Corporation.
  3. //
  4. //  File: newpkg.cpp
  5. //
  6. //  DESCRIPTION:
  7. //
  8. //  This program illustrates how to use the SMS SDK to view, create, and
  9. //  delete packages.  It can be used to create sharing and workstation
  10. //  packages but not inventory packages.  Also the packages created with
  11. //  only a single sub-folder.  Thus the packages it creates can not be for
  12. //  both sharing and workstations.
  13. //
  14. //
  15. //  PROGRAM FLOW:
  16. //
  17. //  After logging on to a datasource, a package container is created and
  18. //  populated. The program then enters a loop asking whether the user
  19. //  wants to view the next package folder, delete the currently viewed
  20. //  folder, or create a new folder.
  21. //
  22. //  Author: Larry A. French
  23. //
  24. //==========================================================================
  25. //  The following API calls are used in this program.
  26. //
  27. //      SmsDataSourceConnect
  28. //      SmsDataSourceDisconnect
  29. //      SmsOpenContainer
  30. //      SmsCloseContainer
  31. //      SmsCreateFolder
  32. //      SmsPopulate
  33. //      SmsGetNextFolder
  34. //      SmsDescribeFolder
  35. //      SmsGetFolderID
  36. //      SmsGetFolderType
  37. //      SmsGetFolderCount
  38. //      SmsLinkFolder
  39. //      SmsUnlinkFolder
  40. //      SmsCommitFolder
  41. //      SmsRewind
  42. //      SmsCloseFolder
  43. //      SmsGetScalarCount
  44. //      SmsSetScalar
  45. //      SmsGetNextScalar
  46. //
  47. //**************************************************************************
  48.  
  49.  
  50. // ====================================================================
  51. //  Includes.
  52. // ====================================================================
  53. #include <afx.h>
  54. #include <stdlib.h>                 // for itoa
  55. #include <smsapi.h>                 // Header for the APIs.
  56. #include <time.h>                   // for time functions.
  57.  
  58. // Include the GetStatusName function.
  59. // -------------------------------------
  60. #include "..\common\status.inc"
  61.  
  62.  
  63. // ====================================================================
  64. //
  65. //      Defines.
  66. //
  67. // ====================================================================
  68.  
  69. #define CCH_MAXSTRING   256
  70. #define MAX_CREATE      100
  71.  
  72. #define PACKAGE_PERMISSIONS (PACKAGE_USER_READ | PACKAGE_USER_WRITE | PACKAGE_GUEST_READ)
  73.  
  74.  
  75.  
  76. // ====================================================================
  77. //
  78. //      Prototypes.
  79. //
  80. // ====================================================================
  81.  
  82. void DisplayScalars( HANDLE hFolder );
  83. void ViewFolder( HANDLE hFolder );
  84. HANDLE CreatePackageFolder( HANDLE hFolderParent );
  85. time_t ReadTime();
  86. BOOL DidRequestHelp(int argc, char** argv);
  87. void DisplayHelp();
  88. void DisplayGreeting();
  89. BOOL UserSaysYes(const char* pszPrompt);
  90. HANDLE ConnectToDatasource();
  91. void DisplaySmsError(const char* pszMessage, SMS_STATUS stat);
  92. const char* GetStatusName(SMS_STATUS stat);
  93. void InputString(const char* pszMessage, char* pszResult);
  94.  
  95.  
  96.  
  97.  
  98. // ====================================================================
  99. //
  100. //  The work starts here.
  101. //
  102. // ====================================================================
  103. void main(int argc, char** argv)
  104. {
  105.     // Check to see if this is a request to display the help
  106.     // screen.  If so, display it. Otherwise, display a greeting
  107.     // banner.
  108.     //=========================================================
  109.     if (DidRequestHelp(argc, argv)) {
  110.         DisplayHelp();
  111.         return;
  112.     }
  113.     else {
  114.         DisplayGreeting();
  115.     }
  116.  
  117.  
  118.     SMS_STATUS stat;
  119.     HANDLE hConnect;
  120.     HANDLE hContainerPkg;
  121.     DWORD numFolders;
  122.     DWORD numFoldersMax;
  123.     DWORD dwFolder;
  124.     DWORD dwIndex;
  125.  
  126.  
  127.     // Connect to the data source.  If the connect fails, give up.
  128.     // Note that a status message will be displayed by ConnectToDatasource.
  129.     //=====================================================================
  130.     hConnect = ConnectToDatasource();
  131.     if (hConnect == NULL) {
  132.         return;
  133.     }
  134.  
  135.     // Open package container.
  136.     // ==============================================================
  137.     stat = SmsOpenContainer( C_PACKAGE, hConnect, &hContainerPkg );
  138.     if (stat != SMS_OK) {
  139.         printf("SmsOpenContainer failed: %d\n", stat);
  140.         SmsDataSourceDisconnect( hConnect );
  141.         return;
  142.     }
  143.  
  144.     // Any filters would be set here.
  145.  
  146.  
  147.     // Select all folders matching our filters.
  148.     // ========================================
  149.     stat = SmsPopulate( hContainerPkg, POP_SYNC, NULL);
  150.     if (!(stat == SMS_OK || stat==SMS_EMPTY)) {
  151.         printf("Bad return from SmsPopulate: %d\n", stat);
  152.         SmsCloseContainer( hContainerPkg );
  153.         SmsDataSourceDisconnect( hConnect );
  154.         return;
  155.     }
  156.  
  157.  
  158.     stat = SmsGetFolderCount( hContainerPkg, F_ANY, &numFolders);
  159.     if (stat != SMS_OK) {
  160.         DisplaySmsError("SmsGetFolderCount failed on package container", stat);
  161.         return;
  162.     }
  163.  
  164.     printf("==========  Container has %d folders  =========\n\n", numFolders );
  165.  
  166.  
  167.     // Allocate enough space to hold handles for all of the folders currently
  168.     // in the container, plus more than enough space to hold all of the folders
  169.     // that we will create.
  170.     //=========================================================================
  171.     numFoldersMax = numFolders + MAX_CREATE;
  172.  
  173.     HANDLE *phFolders = (HANDLE *)malloc(numFoldersMax * sizeof(HANDLE));
  174.     HANDLE hFolder;
  175.  
  176.     // Open all top-level folders.
  177.     // ---------------------------
  178.     for (dwFolder = 0; dwFolder < numFolders; dwFolder++) {
  179.         stat = SmsGetNextFolder( hContainerPkg, F_ANY, &hFolder );
  180.         if (stat != SMS_OK) {
  181.             printf("Error in retrieving a folder: %d\n", stat);
  182.             break;
  183.         }
  184.  
  185.         phFolders[dwFolder] = hFolder;
  186.     }
  187.  
  188.  
  189.     // Now we enter a loop asking the user whether they want to
  190.     // view the next folder, Delete the folder just displayed,
  191.     // or create a new folder.
  192.     // =========================================================
  193.     BOOL bDoQuit = FALSE;
  194.     char szReply[CCH_MAXSTRING];
  195.     dwFolder = 0;
  196.  
  197.     while (!bDoQuit) {
  198.  
  199.         printf("\n\n");
  200.         printf("*******************************************\n");
  201.         printf("* Enter a command:                        *\n");
  202.         printf("*    N      View next folder.             *\n");
  203.         printf("*    P      View previous folder.         *\n");
  204.         printf("*    V      View current folder.          *\n");
  205.         printf("*    D      Delete current folder.        *\n");
  206.         printf("*    C      Create new folder.            *\n");
  207.         printf("*    X      Exit.                         *\n");
  208.         printf("*******************************************\n");
  209.         printf("\n");
  210.  
  211.         InputString("[NPVDCX]", szReply);
  212.  
  213.         switch (szReply[0]) {
  214.         case 0:
  215.         case 'N': case 'n':
  216.  
  217.             // Fall through to the "View" command
  218.             // =========== View next folder ====================
  219.             if ((dwFolder + 1) < numFolders) {
  220.                 dwFolder++;
  221.                 ViewFolder( phFolders[dwFolder] );
  222.             } else
  223.                 printf("At end of folder list\n");
  224.            break;
  225.  
  226.         case 'P': case 'p':
  227.             if (dwFolder > 0) {
  228.                 --dwFolder;
  229.                 ViewFolder(phFolders[dwFolder]);
  230.             } else {
  231.                 printf("At first folder\n");
  232.             }
  233.             break;
  234.  
  235.         case 'V': case 'v':
  236.             if (dwFolder >= 0 && dwFolder < numFolders) {
  237.                 ViewFolder( phFolders[dwFolder]);
  238.             } else {
  239.                 printf("View: No such folder: %d\n", dwFolder);
  240.             }
  241.             break;
  242.  
  243.         case 'D': case 'd':
  244.             // =========== Delete current folder ===============
  245.  
  246.             // Check we have a folder to delete.
  247.             if (dwFolder >= numFolders || dwFolder < 0) {
  248.                 printf("Delete: No such folder: %d\n", dwFolder);
  249.                 break;
  250.             }
  251.  
  252.             hFolder = phFolders[dwFolder];
  253.  
  254.             if (!UserSaysYes("Are you sure you want to delete this folder")) {
  255.                 printf("Delete cancelled\n");
  256.                 break;
  257.             }
  258.  
  259.             stat = SmsUnlinkFolder( hFolder );
  260.             if (stat != SMS_OK) {
  261.                 DisplaySmsError("Delete: UnlinkFolder failed", stat);
  262.                 break;
  263.             }
  264.             stat = SmsCommitFolder( hFolder );
  265.             if (stat != SMS_OK) {
  266.                 DisplaySmsError("Delete: commit folder failed", stat);
  267.                 break;
  268.             }
  269.  
  270.             // Close the folder so that its memory will be deallocated
  271.             // when all other references to it go away.  Note that the
  272.             // container retains a reference to its folder, so the memory
  273.             // will not actually be deallocated until the container is
  274.             // also closed.
  275.             //==========================================================
  276.             stat = SmsCloseFolder(hFolder);
  277.             if (stat != SMS_OK) {
  278.                 DisplaySmsError("Delete: close folder failed", stat);
  279.                 break;
  280.             }
  281.  
  282.             // Remove the folder's handle from the handle table.
  283.             //==================================================
  284.             for(dwIndex = dwFolder; dwIndex < (numFolders - 1); ++dwIndex) {
  285.                 phFolders[dwIndex] = phFolders[dwIndex+1];
  286.             }
  287.  
  288.             // Adjust the folder index and folder count.
  289.             // since there is now one less folder in the table.
  290.             //=================================================
  291.             --numFolders;
  292.             if ((dwFolder > 0) && (dwFolder >= numFolders)) {
  293.                 --dwFolder;
  294.             }
  295.             printf("Folder deleted\n");
  296.             break;
  297.  
  298.         case 'C': case 'c':
  299.             // =========== Create new folder ===================
  300.  
  301.             // Check to see if the folder handle array is already
  302.             // full.  If so, then display an error message and
  303.             // begin a new command.
  304.             //===================================================
  305.             if (numFolders >= numFoldersMax) {
  306.                 printf("Can't create a new folder because the folder\n");
  307.                 printf("handle array is full.\n");
  308.                 printf("\n");
  309.                 break;
  310.             }
  311.  
  312.             HANDLE hFolderPkg;
  313.             hFolderPkg = CreatePackageFolder(hContainerPkg);
  314.             if (hFolderPkg != NULL) {
  315.                 dwFolder = numFolders;
  316.                 phFolders[numFolders++] = hFolderPkg;
  317.             }
  318.             break;
  319.  
  320.         case 'X': case 'x':
  321.             // Terminate.
  322.             bDoQuit = TRUE;
  323.             break;
  324.  
  325.         default:
  326.             // print the message again.
  327.             printf("Actions are: N(ext folder), D(elete folder), C(reate folder)\n");
  328.             printf("Type x to exit\n");
  329.             break;
  330.         }
  331.     }
  332.  
  333.     // Close all of the package folders so that their memory will
  334.     // be deallocated (when the container is closed).
  335.     //===========================================================
  336.     for (dwFolder=0; dwFolder < numFolders; ++dwFolder) {
  337.         stat = SmsCloseFolder(phFolders[dwFolder]);
  338.         if (stat != SMS_OK) {
  339.             DisplaySmsError("Failed to close a package folder", stat);
  340.         }
  341.     }
  342.  
  343.  
  344.     // Close the container.
  345.     //=====================
  346.     stat = SmsCloseContainer( hContainerPkg );
  347.     if (stat != SMS_OK) {
  348.         DisplaySmsError("Failed to close the package container", stat);
  349.     }
  350.  
  351.     // Disconnect from the datasource.
  352.     //================================
  353.     stat = SmsDataSourceDisconnect( hConnect );
  354.     if (stat != SMS_OK) {
  355.         DisplaySmsError("Failed to disconnecct from the datasource", stat);
  356.     }
  357.  
  358.     // Deallocate memory used for folder handles.
  359.     //===========================================
  360.     free( phFolders );
  361.  
  362. }  /* main */
  363.  
  364.  
  365.  
  366.  
  367.  
  368.  
  369. //***************************************************************************
  370. // ReadTime
  371. //
  372. // Ask the user to enter a time string and convert it to a time_t value.
  373. //
  374. // Input: None.
  375. //
  376. // Returns:
  377. //      time_t     The time value the user entered.
  378. //
  379. //
  380. //***************************************************************************
  381. time_t ReadTime()
  382. {
  383.     char szTime[CCH_MAXSTRING];
  384.     InputString("Enter time in the form mm/dd/yy hh:mm ", szTime);
  385.  
  386.  
  387.     int mon, day, year, hour, min;
  388.     time_t today;
  389.     time( &today );
  390.  
  391.     // Get the month (1..12)
  392.     mon = (szTime[0] - '0') * 10 + (szTime[1]) - '0';
  393.     mon--;
  394.     if (mon < 0 || mon > 11) {
  395.         printf("Month wrong (valid 01-12)\n");
  396.         return(today);
  397.     }
  398.  
  399.     // Day (1..31)
  400.     day = (szTime[3] - '0') * 10 + (szTime[4] - '0');
  401.     if (day < 1 || day > 31) {
  402.         printf("Day wrong (Valid 01-07)\n");
  403.         return(today);
  404.     }
  405.  
  406.     // Year
  407.     year = (szTime[6] - '0') * 10 + (szTime[7] - '0');
  408.     if (year < 90 || year > 99) {
  409.         printf("Year wrong (Valid 90-99)\n");
  410.         return(today);
  411.     }
  412.  
  413.     // Hour (0..23)
  414.     hour = (szTime[9] - '0') * 10 + (szTime[10] - '0');
  415.     if (hour < 0 || hour > 23) {
  416.         printf("Hour wrong (Valid 00-23)\n");
  417.         return(today);
  418.     }
  419.  
  420.     // Minute (0..59)
  421.     min = (szTime[12] - '0') * 10 + (szTime[13] - '0');
  422.     if (min < 0 || min > 59) {
  423.         printf("Minute wrong (Valid 00-59)\n");
  424.         return(today);
  425.     }
  426.  
  427.     // Format the time, we want a time_t.
  428.     struct tm theTime;
  429.     theTime.tm_mon   = mon;
  430.     theTime.tm_mday  = day;
  431.     theTime.tm_year  = year;
  432.     theTime.tm_hour  = hour;
  433.     theTime.tm_min   = min;
  434.     theTime.tm_sec   = 0;
  435.     theTime.tm_isdst = -1;
  436.  
  437.     time_t time = mktime( &theTime );
  438.     return(time);
  439. }
  440.  
  441.  
  442.  
  443.  
  444. //**************************************************************************
  445. // SetScalarString
  446. //
  447. // This function sets the value specified scalar to the given string
  448. // value.
  449. //
  450. // Parameters:
  451. //      HANDLE hFolder
  452. //          The handle of the folder containing the scalar to modify.
  453. //      char* pszName
  454. //          The name of the scalar.
  455. //      char* pszValue
  456. //          The string that will be assigned to the scalar's value.
  457. //
  458. // Returns:
  459. //      SMS_STATUS
  460. //          The SMS status code.
  461. //
  462. // Note that the scalar specified must be of type SCALAR_STRING.
  463. //***************************************************************************
  464. SMS_STATUS SetScalarString(HANDLE hFolder, char* pszName, char* pszValue)
  465. {
  466.     SCALAR sc;
  467.     sc.pszName = pszName;
  468.     sc.scType = SCALAR_STRING;
  469.     sc.pszValue = pszValue;
  470.  
  471.     SMS_STATUS stat;
  472.     stat = SmsSetScalar(hFolder, &sc);
  473.     return( stat );
  474. }
  475.  
  476.  
  477.  
  478.  
  479. //**************************************************************************
  480. // SetScalarDword
  481. //
  482. // This function sets the value of the specified scalar to
  483. // the given DWORD value.
  484. //
  485. // Parameters:
  486. //      HANDLE hFolder
  487. //          The handle of the folder containing the scalar to modify.
  488. //      char* pszName
  489. //          The name of the scalar.
  490. //      DWORD dwValue
  491. //          The DWORD value to set the scalar to.
  492. //
  493. // Returns:
  494. //      SMS_STATUS
  495. //          The SMS status code.
  496. //
  497. // Note that the scalar specified must be of type SCALAR_INT.
  498. //***************************************************************************
  499. SMS_STATUS SetScalarDword(HANDLE hFolder, char* pszName, DWORD dwValue)
  500. {
  501.     SCALAR sc;
  502.     sc.pszName = pszName;
  503.     sc.scType = SCALAR_INT;
  504.     sc.dwValue = dwValue;
  505.  
  506.  
  507.     SMS_STATUS stat;
  508.     stat = SmsSetScalar(hFolder, &sc);
  509.     return( stat );
  510. }
  511.  
  512.  
  513.  
  514.  
  515. //**************************************************************************
  516. // GetPlatformSelection
  517. //
  518. // Prompt the user to select a one or more platforms.  The platforms are
  519. // selected by entering a comma separated list of platform indexes.  These
  520. // platform indexes are converted to the platforms flags value for the SDK.
  521. //
  522. // Parameters:  None.
  523. //
  524. // Returns:
  525. //      The SMS SDK platform flags value.
  526. //***************************************************************************
  527. DWORD GetPlatformSelection()
  528. {
  529.     printf("\n\n");
  530.     printf("**********************************************\n");
  531.     printf("* Select a platform from the following list. *\n");
  532.     printf("**********************************************\n");
  533.     printf("   1) MS-DOS \n");
  534.     printf("   2) Windows 3.1\n");
  535.     printf("   3) Windows 95\n");
  536.     printf("   4) Windows NT (X86)\n");
  537.     printf("   5) Windows NT (Mips)\n");
  538.     printf("   6) Windows NT (Alpha)\n");
  539.     printf("   7) Macintosh\n");
  540.     printf("\n");
  541.  
  542.     DWORD dwPlatforms = 0;
  543.     char szReply[CCH_MAXSTRING];
  544.     InputString("Enter a comma separated list of platform number(s)", szReply);
  545.     printf("\n");
  546.  
  547.     // Scan through the reply string and set the bits
  548.     // dwPlatforms to correspond to the platform(s) specified
  549.     // by the user.  Note that the list is a string of comma
  550.     // separated digits.
  551.     //======================================================
  552.     const char* pszReply = szReply;
  553.     while (*pszReply) {
  554.         if (*pszReply < '1' || *pszReply > '7') {
  555.             // An invalid character is present in the
  556.             // reply.  Flag this error by returning zero.
  557.             //==========================================
  558.             dwPlatforms = 0;
  559.             break;
  560.         }
  561.  
  562.         // Interpret the platform selector character.
  563.         //===========================================
  564.         switch(*pszReply++) {
  565.         case '1':
  566.             dwPlatforms |= PLTFRM_MSDOS;
  567.             break;
  568.         case '2':
  569.             dwPlatforms |= PLTFRM_WIN16;
  570.             break;
  571.         case '3':
  572.             dwPlatforms |= PLTFRM_WIN95;
  573.             break;
  574.         case '4':
  575.             dwPlatforms |= PLTFRM_WIN32_X86;
  576.             break;
  577.         case '5':
  578.             dwPlatforms |= PLTFRM_WIN32_MIPS;
  579.             break;
  580.         case '6':
  581.             dwPlatforms |= PLTFRM_WIN32_ALPHA;
  582.             break;
  583.         case '7':
  584.             dwPlatforms |= PLTFRM_MACINTOSH;
  585.             break;
  586.         }
  587.  
  588.         // Skip any trailing whitespace after the digit.
  589.         //==============================================
  590.         while (*pszReply == ' ' || *pszReply=='\t') {
  591.             ++pszReply;
  592.         }
  593.  
  594.         // Skip the comma.
  595.         //================
  596.         if (*pszReply == ',') {
  597.             ++pszReply;
  598.         }
  599.  
  600.         // Skip white space preceding the next digit.
  601.         //=========================
  602.         while (*pszReply == ' ' || *pszReply=='\t') {
  603.             ++pszReply;
  604.         }
  605.  
  606.     }
  607.  
  608.     return( dwPlatforms );
  609. }
  610.  
  611.  
  612.  
  613.  
  614.  
  615.  
  616. //**************************************************************************
  617. // ConnectToDatasource
  618. //
  619. // Get the datasource connection information from the user and use it
  620. // to connect to the datasource.
  621. //
  622. // Parameters:  None.
  623. //
  624. // Returns:
  625. //      The connection handle or NULL if the connection failed.
  626. //***************************************************************************
  627. HANDLE ConnectToDatasource()
  628. {
  629.     // Get the information we need to connect to the
  630.     // data source from the user.
  631.     //==============================================
  632.     char szServer[CCH_MAXSTRING];
  633.     char szUser[CCH_MAXSTRING];
  634.     char szPasswd[CCH_MAXSTRING];
  635.     char szDatabase[CCH_MAXSTRING];
  636.  
  637.     printf("\n");
  638.     printf("**************************\n");
  639.     printf("* Connect to data source *\n");
  640.     printf("**************************\n");
  641.     InputString("SQL server name", szServer);
  642.     InputString("SQL database name", szDatabase);
  643.     InputString("User name for SQL server", szUser);
  644.     InputString("Password for SQL server", szPasswd);
  645.     printf("\n");
  646.  
  647.  
  648.     // Connect to a data source. SQL in this case.
  649.     // ===========================================
  650.     DATASOURCE dsParams;
  651.  
  652.     dsParams.sqlParams.ds          = DB_SQL;
  653.     dsParams.sqlParams.pszServer   = szServer;
  654.     dsParams.sqlParams.pszUserName = szUser;
  655.     dsParams.sqlParams.pszPasswd   = szPasswd;
  656.     dsParams.sqlParams.pszDbName   = szDatabase;
  657.     dsParams.sqlParams.pFunc       = NULL;         // No encryption.
  658.     dsParams.sqlParams.pszKey      = "";
  659.  
  660.     HANDLE hConnect;
  661.     SMS_STATUS stat;
  662.     stat = SmsDataSourceConnect( &dsParams, &hConnect);
  663.  
  664.     if (stat != SMS_OK) {
  665.         hConnect = NULL;
  666.         DisplaySmsError("Connect to data source failed", stat);
  667.     }
  668.  
  669.     return( hConnect );
  670. }
  671.  
  672.  
  673.  
  674.  
  675.  
  676.  
  677.  
  678. //**************************************************************************
  679. // ViewFolder
  680. //
  681. //  Display the folder contents.  This version only displays the folder name
  682. //  and type, number of scalars, and the scalars. Other information not
  683. //  relevant.
  684. //
  685. //  NOTE: no error checking.
  686. //
  687. // Parameters:
  688. //      HANDLE hFolder
  689. //          The handle of the folder to view.
  690. //
  691. // Returns: Nothing.
  692. //
  693. //**************************************************************************
  694. void ViewFolder( HANDLE hFolder )
  695. {
  696.     char szFolderID[SMS_DATA_BUFF_SIZE + 1];        // This folder's ID.
  697.     char szfType[SMS_DATA_BUFF_SIZE + 1];           // Folder's tag.
  698.     DWORD fType;                        // Folder's type.
  699.     DWORD ctScalars;                    // How many scalars in this folder.
  700.     SMS_STATUS stat;
  701.  
  702.  
  703.     // Get folder ID and type.
  704.     // -----------------------
  705.     stat = SmsGetFolderID( hFolder, szFolderID );
  706.     if (stat == SMS_NEW_FOLDER) {
  707.         strcpy( szFolderID, "New folder without an ID yet" );
  708.  
  709.     }
  710.     else if (stat != SMS_OK) {
  711.         DisplaySmsError("ViewFolder: can't get folder ID", stat);
  712.         strcpy( szFolderID, "Couldn't get the folder ID" );
  713.     }
  714.  
  715.     printf("============== %s ===========\n", szFolderID);
  716.  
  717.     stat = SmsGetFolderType( hFolder, &fType, szfType );
  718.     if (stat != SMS_OK) {
  719.         DisplaySmsError("ViewFolder: can't get folder type", stat);
  720.     }
  721.  
  722.     printf("SCALARS FOR FOLDER %s\n", szFolderID);
  723.  
  724.     // Get count of scalars.
  725.     // ---------------------
  726.     stat = SmsGetScalarCount( hFolder, &ctScalars );
  727.     if (stat != SMS_OK) {
  728.         DisplaySmsError("ViewFolder: can't get scalar count", stat);
  729.     }
  730.     printf("%s (%s) contains %d scalars\n", szFolderID, szfType, ctScalars);
  731.  
  732.  
  733.     // Display the scalars.
  734.     // --------------------
  735.     DisplayScalars( hFolder );
  736.  
  737.  
  738.     // Get the folder count
  739.     DWORD ctFolders;
  740.     stat = SmsGetFolderCount(hFolder, F_ANY, &ctFolders);
  741.     printf("%s (%s) contains %d sub-folders\n", szFolderID, szfType, ctFolders);
  742.     for (DWORD dwFolder = 0; dwFolder < ctFolders; ++dwFolder) {
  743.         printf("Getting subfolder\n");
  744.         HANDLE hSubFolder;
  745.         stat = SmsGetNextFolder(hFolder, F_ANY, &hSubFolder);
  746.         if (stat != SMS_OK) {
  747.             DisplaySmsError("SmsGetNextFolder failed", stat);
  748.             break;
  749.         }
  750.  
  751.         ViewFolder(hSubFolder);
  752.  
  753.         // Close the sub-folder to avoid a memory leak.
  754.         //============================================
  755.         stat = SmsCloseFolder(hSubFolder);
  756.         if (stat != SMS_OK) {
  757.             DisplaySmsError("Failed to close an open folder", stat);
  758.             break;
  759.         }
  760.     }
  761.  
  762.  
  763.     SmsRewind(hFolder, RW_FOLDER | RW_SCALAR);
  764.  
  765. }  /* ViewFolder */
  766.  
  767.  
  768.  
  769.  
  770.  
  771. //*************************************************************************
  772. // CreateWcl
  773. //
  774. // This method is called to create a WCL subfolder in
  775. // a package folder.
  776. //
  777. // Parameters:
  778. //      HANDLE hFolderPkg
  779. //          This is the handle of the parent folder that the newly
  780. //          created subfolder will be inserted into.  For WCL and
  781. //          program item folders, the parent folder is a package
  782. //          folder.
  783. //
  784. // Returns:
  785. //      HANDLE
  786. //          This is the handle of the newly created subfolder.
  787. //
  788. //*************************************************************************
  789. HANDLE CreateWcl(HANDLE hFolderPkg)
  790. {
  791.     printf("\n\n");
  792.     printf("*****************************************************\n");
  793.     printf("* Creating the workstation command line sub-folder. *\n");
  794.     printf("*****************************************************\n");
  795.     printf("\n");
  796.  
  797.  
  798.     HANDLE hFolderNew;
  799.     SMS_STATUS stat;
  800.     char szError[CCH_MAXSTRING];
  801.     char szReply[CCH_MAXSTRING];
  802.     DWORD dwPlatforms;
  803.  
  804.     // Create the WCL folder
  805.     //======================
  806.     stat = SmsCreateFolder( hFolderPkg, F_WCL, "", &hFolderNew );
  807.     if (stat != SMS_OK) {
  808.         sprintf(szError, "SmsCreateFolder failed to create the WCL folder");
  809.         DisplaySmsError(szError, stat);
  810.         return( NULL );
  811.     }
  812.  
  813.  
  814.     dwPlatforms = GetPlatformSelection();
  815.  
  816.  
  817.     printf("\n\n");
  818.     printf("*********************************************\n");
  819.     printf("* Enter values for the WCL folder scalars.  *\n");
  820.     printf("*********************************************\n");
  821.     printf("\n");
  822.  
  823.     InputString("Name", szReply);
  824.     SetScalarString(hFolderNew, "Name", szReply);
  825.  
  826.     InputString("Command", szReply);
  827.     SetScalarString(hFolderNew, "Command", szReply);
  828.  
  829.     SetScalarDword(hFolderNew, "Flags", 0);
  830.     SetScalarDword(hFolderNew, "Platforms", dwPlatforms);
  831.  
  832.  
  833.  
  834.     // Link the new WCL folder into the folder hierarchy.  Note that
  835.     // this does not insert the folder into the datasource.  Only
  836.     // SmsCommitFolder modifies the datasource.
  837.     //==============================================================
  838.     stat = SmsLinkFolder(hFolderNew);
  839.     if ((stat != SMS_OK) && (stat != SMS_PARENT_NEEDS_COMMIT)) {
  840.         sprintf(szError, "SmsLinkFolder failed to link the WCL folder");
  841.         DisplaySmsError(szError, stat);
  842.         return( NULL );
  843.     }
  844.  
  845.     return( hFolderNew ) ;
  846. }
  847.  
  848.  
  849.  
  850. //*************************************************************************
  851. // CreateProgItem
  852. //
  853. // This method is called to create a program item subfolder in
  854. // a package folder.
  855. //
  856. // Parameters:
  857. //      HANDLE hFolderPkg
  858. //          This is the handle of the parent folder that the newly
  859. //          created subfolder will be inserted into.  For WCL and
  860. //          program item folders, the parent folder is a package
  861. //          folder.
  862. //
  863. // Returns:
  864. //      HANDLE
  865. //          This is the handle of the newly created subfolder.
  866. //
  867. //*************************************************************************
  868. HANDLE CreateProgItem(HANDLE hFolderPkg)
  869. {
  870.     printf("\n\n");
  871.     printf("*****************************************\n");
  872.     printf("* Creating the program item sub-folder. *\n");
  873.     printf("*****************************************\n");
  874.     printf("\n");
  875.  
  876.     HANDLE hFolderNew;
  877.     SMS_STATUS stat;
  878.     char szReply[CCH_MAXSTRING];
  879.     char szError[CCH_MAXSTRING];
  880.     DWORD dwPlatforms;
  881.  
  882.     // Create the programe item folder
  883.     //================================
  884.     stat = SmsCreateFolder( hFolderPkg, F_PROGITEM, "", &hFolderNew );
  885.     if (stat != SMS_OK) {
  886.         sprintf(szError, "SmsCreateFolder failed to create the program item folder");
  887.         DisplaySmsError(szError, stat);
  888.         return( NULL );
  889.     }
  890.  
  891.  
  892.  
  893.     // Set the value of the scalars for the program item.
  894.     //===================================================
  895.     dwPlatforms = GetPlatformSelection();
  896.  
  897.  
  898.  
  899.     printf("\n\n");
  900.     printf("******************************************************\n");
  901.     printf("* Enter values for the program item folder scalars.  *\n");
  902.     printf("******************************************************\n");
  903.     printf("\n");
  904.  
  905.     InputString("Description", szReply);
  906.     SetScalarString(hFolderNew, "Description", szReply);
  907.  
  908.     InputString("Command line", szReply);
  909.     SetScalarString(hFolderNew, "Command line", szReply);
  910.  
  911.     SetScalarDword(hFolderNew,  "Run minimized", FALSE);
  912.     SetScalarDword(hFolderNew,  "Platforms", dwPlatforms);
  913.     SetScalarString(hFolderNew, "Configure script file", "");
  914.     SetScalarDword(hFolderNew,  "Search local flag", 1);
  915.     SetScalarDword(hFolderNew,  "Drive mode", 1);
  916.  
  917.     InputString("Registry name", szReply);
  918.     SetScalarString(hFolderNew, "Registry name", szReply);
  919.     SetScalarDword(hFolderNew,  "Executable flag", TRUE);
  920.  
  921.  
  922.  
  923.     // Link the new WCL folder into the folder hierarchy.  Note that
  924.     // this does not insert the folder into the datasource.  Only
  925.     // SmsCommitFolder modifies the datasource.
  926.     //==============================================================
  927.     stat = SmsLinkFolder(hFolderNew);
  928.     if ((stat != SMS_OK) && (stat != SMS_PARENT_NEEDS_COMMIT)) {
  929.         sprintf(szError, "SmsLinkFolder failed to link the programe item folder");
  930.         DisplaySmsError(szError, stat);
  931.         return( NULL );
  932.     }
  933.  
  934.     return( hFolderNew ) ;
  935. }
  936.  
  937.  
  938.  
  939.  
  940.  
  941. //*************************************************************************
  942. // CreatePackageFolder
  943. //
  944. // Create a new package folder
  945. //
  946. // Parameters:
  947. //      HANDLE hPackageContainer
  948. //          This is the handle to the package folder's parent, which
  949. //          is a package container.
  950. //
  951. // Returns:
  952. //      The package folder's handle.
  953. //
  954. // ====================================================================
  955. HANDLE CreatePackageFolder(HANDLE hPackageContainer)
  956. {
  957.     SMS_STATUS stat;
  958.     char szReply[CCH_MAXSTRING];
  959.     HANDLE hFolderPkg = NULL;
  960.     HANDLE hFolderWCL = NULL;
  961.     HANDLE hFolderProgItem = NULL;
  962.  
  963.  
  964.  
  965.     stat = SmsCreateFolder( hPackageContainer, F_PACKAGE, "", &hFolderPkg );
  966.     if (stat != SMS_OK) {
  967.         DisplaySmsError("SmsCreateFolder failed to create the package folder.", stat);
  968.         return( NULL );
  969.     }
  970.  
  971.  
  972.     printf("\n\n");
  973.     printf("***************************************************\n");
  974.     printf("* Creating package folder.  Select a package      *\n");
  975.     printf("* type.                                           *\n");
  976.     printf("*                                                 *\n");
  977.     printf("*    S         Sharing.                           *\n");
  978.     printf("*    W         Workstation.                       *\n");
  979.     printf("***************************************************\n");
  980.     printf("\n");
  981.  
  982.     InputString("SW: ", szReply);
  983.     switch(szReply[0]) {
  984.     case 'S': case 's':
  985.         hFolderProgItem = CreateProgItem(hFolderPkg);
  986.         break;
  987.     case 'W': case 'w':
  988.         hFolderWCL = CreateWcl(hFolderPkg);
  989.         break;
  990.     }
  991.  
  992.  
  993.  
  994.  
  995.     printf("\n\n");
  996.     printf("*************************************\n");
  997.     printf("* Enter the package folder scalars. *\n");
  998.     printf("*************************************\n");
  999.     printf("\n");
  1000.  
  1001.  
  1002.     InputString("Package name", szReply);
  1003.     SetScalarString(hFolderPkg, "Name", szReply);
  1004.  
  1005.     InputString("Package comment", szReply);
  1006.     SetScalarString(hFolderPkg, "Comment", szReply);
  1007.  
  1008.     // If this package contains a workstation command line, then set the
  1009.     // scalars that are relevant to workstation command lines.
  1010.     //==================================================================
  1011.     if (hFolderWCL) {
  1012.         SetScalarDword(hFolderPkg, "Share permissions", (DWORD) PACKAGE_PERMISSIONS);
  1013.  
  1014.         InputString("Workstation root", szReply);
  1015.         SetScalarString(hFolderPkg, "Workstation root", szReply);
  1016.  
  1017.     }
  1018.  
  1019.     // If this package contains a program item, then set the scalars
  1020.     // that are relevant to program items.
  1021.     //==============================================================
  1022.     if (hFolderProgItem) {
  1023.         SetScalarDword(hFolderPkg, "Share permissions", (DWORD) PACKAGE_PERMISSIONS);
  1024.  
  1025.         InputString("Server root", szReply);
  1026.         SetScalarString(hFolderPkg, "Server root", szReply);
  1027.  
  1028.         InputString("Share name", szReply);
  1029.         SetScalarString(hFolderPkg, "Share name", szReply);
  1030.     }
  1031.  
  1032.  
  1033.  
  1034.  
  1035.  
  1036.     // Display the folder and ask the user if he or she really wants to
  1037.     // write the folder to the datasource.  If the user says yes, then
  1038.     // commit the subfolder's first and then the package folder.  Note that
  1039.     // it does not make any sense to commit the package folder before its
  1040.     // subfolders because, once a folder is committed, modification is not
  1041.     // allowed and it would not be possible to commit the subfolders.
  1042.     //===================================================================
  1043.  
  1044.     ViewFolder(hFolderPkg);
  1045.  
  1046.     if (UserSaysYes("OK to write the folder to the datasource")) {
  1047.  
  1048.         if (hFolderWCL) {
  1049.             stat = SmsCommitFolder(hFolderWCL);
  1050.             if (stat != SMS_OK && stat!=SMS_PARENT_NEEDS_COMMIT) {
  1051.                 DisplaySmsError("Failed to commit the WCL folder", stat);
  1052.                 goto CLOSE_FOLDERS_AND_EXIT;
  1053.             }
  1054.         }
  1055.  
  1056.         if (hFolderProgItem) {
  1057.             stat = SmsCommitFolder(hFolderProgItem);
  1058.             if (stat != SMS_OK && stat!=SMS_PARENT_NEEDS_COMMIT) {
  1059.                 DisplaySmsError("Failed to commit the program item folder", stat);
  1060.                 goto CLOSE_FOLDERS_AND_EXIT;
  1061.             }
  1062.         }
  1063.  
  1064.  
  1065.  
  1066.         // Place the package folder in the in-memory hierarchy.
  1067.         stat = SmsLinkFolder(hFolderPkg);
  1068.         if (stat != SMS_OK) {
  1069.             DisplaySmsError("SmsLinkFolder failed on the package folder", stat);
  1070.             goto CLOSE_FOLDERS_AND_EXIT;
  1071.         }
  1072.  
  1073.  
  1074.         // write it back to data source.
  1075.         stat = SmsCommitFolder( hFolderPkg );
  1076.         if (stat != SMS_OK) {
  1077.             DisplaySmsError("Failed to commit the package folder", stat);
  1078.         }
  1079.     }
  1080.  
  1081.     // Fall through to close the folders.
  1082.  
  1083. CLOSE_FOLDERS_AND_EXIT:
  1084.  
  1085.     // Close the folder's so that memory will be freed when there are no
  1086.     // references to them.  A folder's memory is freed when its reference
  1087.     // count goes to zero.  A folder has one reference for each handle to it
  1088.     // that is returned plus an additional refernce from its parent folder or
  1089.     // container.  Thus we close the folder handles here so that the memory
  1090.     // allocated to the folders will be freed, but the memory won't actually
  1091.     // be freed until the package container is closed.  If you fail to close
  1092.     // any handle returned to you by the SMS API, the memory for that folder
  1093.     // will never be deallocated (even when the folder's container is closed).
  1094.     //========================================================================
  1095.  
  1096.  
  1097.     if (hFolderWCL != NULL) {
  1098.         stat = SmsCloseFolder(hFolderWCL);
  1099.         if (stat != SMS_OK) {
  1100.             DisplaySmsError("Failed to close the WCL folder", stat);
  1101.         }
  1102.     }
  1103.  
  1104.     if (hFolderProgItem != NULL) {
  1105.         stat = SmsCloseFolder(hFolderProgItem);
  1106.         if (stat != SMS_OK) {
  1107.             DisplaySmsError("Failed to close the program item folder", stat);
  1108.         }
  1109.     }
  1110.  
  1111.  
  1112.     return( hFolderPkg );
  1113. }
  1114.  
  1115.  
  1116. //*************************************************************************
  1117. // DisplayScalars
  1118. //
  1119. // Display a folder's scalars.
  1120. //
  1121. // Parameters:
  1122. //      HANDLE hfolder
  1123. //          This is the folder handle.
  1124. //
  1125. // Returns: Nothing.
  1126. //
  1127. // ====================================================================
  1128. void DisplayScalars( HANDLE hFolder )
  1129. {
  1130.     SMS_STATUS stat = SMS_OK;
  1131.     SCALAR scalar;
  1132.     char *pszTime;          // For conversion of time scalars.
  1133.  
  1134.     // The scalars do not have their own string value buffer, so
  1135.     // we allocate the buffers here and set pointers to them in the
  1136.     // scalar structure.
  1137.     //=============================================================
  1138.     char szName[SMS_DATA_BUFF_SIZE+1];
  1139.     char szValue[SMS_DATA_BUFF_SIZE+1];
  1140.     scalar.pszName  = szName;
  1141.     scalar.pszValue = szValue;
  1142.     scalar.pValue = NULL;
  1143.  
  1144.  
  1145.     while (1) {
  1146.  
  1147.         scalar.dwLen = sizeof(szValue)-1;       // must tell him the size
  1148.  
  1149.         stat = SmsGetNextScalar( hFolder, &scalar);
  1150.         if (stat == SMS_NO_MORE_DATA) {
  1151.             break;
  1152.         }
  1153.  
  1154.         if (stat != SMS_OK && stat != SMS_MORE_DATA) {
  1155.             DisplaySmsError("SmsGetNextScalar failed in method DisplayScalars", stat);
  1156.             break;
  1157.         }
  1158.  
  1159.         if (stat == SMS_MORE_DATA) {
  1160.  
  1161.             printf("Receive buffer too small, should be %d. Data truncated\n",
  1162.                             scalar.dwLen);
  1163.         }
  1164.  
  1165.         // Check scalar type, display accordingly.
  1166.         // ---------------------------------------
  1167.         switch (scalar.scType) {
  1168.         case SCALAR_STRING:
  1169.             printf("\t%25s: %s\n", scalar.pszName, scalar.pszValue);
  1170.             break;
  1171.  
  1172.         case SCALAR_INT:
  1173.             printf("\t%25s: %ld\n", scalar.pszName, scalar.dwValue);
  1174.             break;
  1175.  
  1176.         case SCALAR_TIME:
  1177.             // Check if we have a string equivalence. If so use it.
  1178.             if (scalar.bStringEquivalence) {
  1179.                 printf("\t%25s: %s\n", scalar.pszName, scalar.pszValue);
  1180.  
  1181.             } else {
  1182.                 pszTime = ctime( &scalar.tValue );
  1183.                 printf("\t%25s: %s", scalar.pszName, pszTime);
  1184.             }
  1185.             break;
  1186.  
  1187.         case SCALAR_BINARY:
  1188.             // In this sample we won't display the binary data.
  1189.             // Just tell the user its size.
  1190.             printf("\t%25s (Binary - this is its size): %ld\n", scalar.pszName, scalar.dwLen);
  1191.             break;
  1192.         }
  1193.     }
  1194.  
  1195.     // Why did we exit (other than no more scalars)?
  1196.     //==============================================
  1197.     if (stat != SMS_NO_MORE_DATA) {
  1198.         printf("Bad return from Scalar access: %d\n", stat);
  1199.     }
  1200.  
  1201.     printf("\n");
  1202. }
  1203.  
  1204.  
  1205.  
  1206.  
  1207.  
  1208.  
  1209.  
  1210.  
  1211.  
  1212.  
  1213. // ********************************************************************
  1214. //      Helper functions.
  1215. // ********************************************************************
  1216.  
  1217. //**********************************************************
  1218. // DidRequestHelp
  1219. //
  1220. // Check the program's arguments to see if the user asked for
  1221. // the help screen to be displayed.
  1222. //
  1223. // Parameters:
  1224. //      int argc
  1225. //          The argc value from main(argc, argv)
  1226. //
  1227. //      char** argv
  1228. //          The argv value from main(argc, argv)
  1229. //
  1230. // Returns:
  1231. //      TRUE if command line parameters included a request
  1232. //      for help to be displayed.
  1233. //
  1234. //***********************************************************
  1235. BOOL DidRequestHelp(int argc, char** argv)
  1236. {
  1237.     const char* pszCommand = argv[1];
  1238.     if (argc==2  && (strcmp((const char*) argv[1], "-help")==0)) {
  1239.         return(TRUE);
  1240.     }
  1241.     else {
  1242.         return(FALSE);
  1243.     }
  1244. }
  1245.  
  1246.  
  1247. //**********************************************************************
  1248. // DisplayHelp
  1249. //
  1250. // This function displays the samples help screen.
  1251. //
  1252. // Parameters:
  1253. //      None
  1254. //
  1255. // Returns:
  1256. //      Nothing.
  1257. //
  1258. //*********************************************************************
  1259. void DisplayHelp()
  1260. {
  1261.     printf("\n\n");
  1262.     printf("********************************************************\n");
  1263.     printf("* newpkg.exe:                                          *\n");
  1264.     printf("*                                                      *\n");
  1265.     printf("* This is a sample program for the SMS SDK. It can be  *\n");
  1266.     printf("* used to view, create, or delete packages in the SMS  *\n");
  1267.     printf("* database.                                            *\n");
  1268.     printf("*                                                      *\n");
  1269.     printf("* Syntax:                                              *\n");
  1270.     printf("*     newpkg.exe [-help]                               *\n");
  1271.     printf("*                                                      *\n");
  1272.     printf("* Switches:                                            *\n");
  1273.     printf("*     -help       Display this help screen.            *\n");
  1274.     printf("*                                                      *\n");
  1275.     printf("********************************************************\n");
  1276.     printf("\n");
  1277. }
  1278.  
  1279.  
  1280.  
  1281. //*******************************************************************
  1282. // DisplayGreeting
  1283. //
  1284. // Display the initial greeting banner.
  1285. //
  1286. // Parameters:
  1287. //     None.
  1288. //
  1289. // Returns:
  1290. //     Nothing.
  1291. //******************************************************************
  1292. void DisplayGreeting()
  1293. {
  1294.     // For this sample, the greeting is identical to the help screen.
  1295.     //===============================================================
  1296.     DisplayHelp();
  1297. }
  1298.  
  1299.  
  1300.  
  1301.  
  1302. //**************************************************************************
  1303. // InputString
  1304. //
  1305. // Prompt the user to input a string and return the string in the
  1306. // specified buffer.
  1307. //
  1308. // Parameters:
  1309. //      const char* pszMessage
  1310. //          The user prompt to display.
  1311. //
  1312. //      char* pszResult
  1313. //          Pointer to the buffer where the user's input will be returned.
  1314. //
  1315. // Returns;
  1316. //      The user's input is returned via the given buffer.
  1317. //***************************************************************************
  1318. void InputString(const char* pszMessage, char* pszResult)
  1319. {
  1320.     printf("%s: ", pszMessage);
  1321.     gets(pszResult);
  1322. }
  1323.  
  1324.  
  1325. //**************************************************************************
  1326. // UserSaysYes
  1327. //
  1328. // Prompt the user to reply yes or no.  If the user enters "Y" then
  1329. // return TRUE, otherwise FALSE.
  1330. //
  1331. // Parameters:
  1332. //      const char* pszPrompt
  1333. //          The string used to prompt the user
  1334. //
  1335. // Returns:
  1336. //      TRUE = User replied "Y" or "y"
  1337. //      FALSE = User gave any other reply.
  1338. //**************************************************************************
  1339. BOOL UserSaysYes(const char* pszPrompt)
  1340. {
  1341.     printf("%s? [y/n]", pszPrompt);
  1342.     char szReply[CCH_MAXSTRING];
  1343.     gets(szReply);
  1344.  
  1345.     return(szReply[0] == 'y' || szReply[0] == 'Y');
  1346.  
  1347. }
  1348.  
  1349.  
  1350.  
  1351. /* EOF: newjob.cpp */
  1352.  
  1353.