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 / srvinst / srvinst.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-15  |  59.2 KB  |  1,951 lines

  1. //**************************************************************************
  2. // Copyright (C) 1995 by Microsoft Corporation.
  3. //
  4. // This is a sample program for the SMS SDK.  It illustrates how to create
  5. // a server install job and monitor its status until the job completes.
  6. //
  7. // This sample program also illustrates how to create a run command on
  8. // workstation job.
  9. //
  10. // The program will request the following input:
  11. //
  12. // Share package on workstation job:
  13. //    Package name    = User defined name of the package
  14. //    Package comment = User defined text
  15. //    Package location (UNC path) = The pathname to the directory where the
  16. //                                  package files are located.
  17. //    Package share name = The name that the package will be shared as on the
  18. //                         server.
  19. //    Program item description = User defined text
  20. //    Program item command line = The command to execute on the server.
  21. //    Program item registry name = User defined registry key for the package
  22. //
  23. // Run command on workstation job.
  24. //    Package name = User defined name of the package
  25. //    Package comment = User defined text
  26. //    Package location (share name) = The pathname to the directory where the
  27. //                                    client package is located.
  28. //    WCL Name = User defined name for the workstation command line
  29. //    WCL Command = The command line to execute.
  30. //
  31. // NOTE: If you choose to create a share package on server job, then you must
  32. //       first share the package directory.  If you choose to create a run
  33. //       command on workstation job, then you must first share the directory
  34. //       where the package files are located.
  35. //
  36. //*****************************************************************************
  37.  
  38.  
  39. #include <afx.h>
  40. #include <smsapi.h>
  41. #include <smsinfo.h>
  42.  
  43. // Include the GetStatusName function.
  44. // -------------------------------------
  45. #include "..\common\status.inc"
  46.  
  47.  
  48. // ====================================================================
  49. //      Defines.
  50. // ====================================================================
  51.  
  52. #define CCH_MAXSTRING   256
  53. #define CCH_MAXINPUT    256
  54. #define C_MAXSITES      256
  55.  
  56. #define SHARE_PERMISSIONS (PACKAGE_USER_READ | PACKAGE_USER_WRITE | PACKAGE_GUEST_READ)
  57.  
  58.  
  59. extern const char *GetStatusName( SMS_STATUS stat );
  60.  
  61. enum {CMD_RUN_COMMAND, CMD_SHARE_PACKAGE, CMD_QUIT};
  62.  
  63.  
  64.  
  65.  
  66. // ====================================================================
  67. // TClientParams
  68. //
  69. // This typedef defines the parameters for the client setup
  70. // job that are collected from the user.
  71. // ====================================================================
  72. typedef struct
  73. {
  74.     char szPackageName[CCH_MAXSTRING];
  75.     char szPackageComment[CCH_MAXSTRING];
  76.     char szPackagePath[CCH_MAXSTRING];
  77.     char szWclName[CCH_MAXSTRING];
  78.     char szWclCommand[CCH_MAXSTRING];
  79.     char szSiteName[CCH_MAXSTRING];
  80.     DWORD dwPlatforms;
  81. } TClientParams;
  82.  
  83.  
  84. // ====================================================================
  85. // TServerParams
  86. //
  87. // This typedef defines the parameters for the share package on
  88. // workstation job that are collected from the user.
  89. // ====================================================================
  90. typedef struct
  91. {
  92.     char szPackageName[CCH_MAXSTRING];
  93.     char szPackageComment[CCH_MAXSTRING];
  94.     char szPackagePath[CCH_MAXSTRING];
  95.     char szShareName[CCH_MAXSTRING];
  96.     char szDescription[CCH_MAXSTRING];
  97.     char szCmdLine[CCH_MAXSTRING];
  98.     char szRegistryName[CCH_MAXSTRING];
  99.     char szSiteName[CCH_MAXSTRING];
  100.     DWORD dwPlatforms;
  101.  
  102. } TServerParams;
  103.  
  104.  
  105.  
  106. // ====================================================================
  107. //
  108. //  Local prototypes.
  109. //
  110. // ====================================================================
  111.  
  112. void DisplayHelp();
  113.  
  114. void DisplayGreeting();
  115.  
  116. BOOL DidRequestHelp( int argc, char** argv );
  117.  
  118. void DisplaySmsError( const char *pszMessage, SMS_STATUS stat );
  119.  
  120. const char *GetStatusName( SMS_STATUS stat );
  121.  
  122. BOOL DidRequestHelp( int argc, char** argv );
  123.  
  124. HANDLE ConnectToDatasource();
  125.  
  126. void InputString( const char *pszMessage, char *pszResult );
  127.  
  128. void GetSiteName( HANDLE hConnect, char *pszSiteName );
  129.  
  130. void ClientDoRunCommand( HANDLE hConnect, TClientParams *pcp );
  131.  
  132. DWORD GetPlatformSelection();
  133.  
  134. void ServerDoShare( HANDLE hConnect, TServerParams *psp );
  135.  
  136. int GetJobType();
  137.  
  138.  
  139. SMS_STATUS ClientJobCreate( HANDLE hConnect,
  140.                             TClientParams *pcp,
  141.                             char *pszPackageID,
  142.                             char *pszWCLID );
  143.  
  144.  
  145. // ====================================================================
  146. //
  147. //  The work starts here.
  148. //
  149. // ====================================================================
  150. void main( int argc, char **argv )
  151. {
  152.  
  153.     // Check to see if this is a request to display the help
  154.     // screen.  If so, display it. Otherwise, display a greeting
  155.     // banner.
  156.     //=========================================================
  157.     if (DidRequestHelp(argc, argv)) {
  158.         DisplayHelp();
  159.         return;
  160.     }
  161.     else {
  162.         DisplayGreeting();
  163.     }
  164.  
  165.     HANDLE hConnect = ConnectToDatasource();
  166.     if (hConnect == NULL) {
  167.         return;
  168.     }
  169.  
  170.  
  171.     char szSiteName[CCH_MAXSTRING];
  172.     GetSiteName(hConnect, szSiteName);
  173.  
  174.     DWORD dwPlatforms = 0;
  175.     while (dwPlatforms == 0) {
  176.         dwPlatforms = GetPlatformSelection();
  177.         if (dwPlatforms == 0) {
  178.             printf("Error: Invalid platform selection\n");
  179.         }
  180.     }
  181.  
  182.  
  183.  
  184.  
  185.     switch(GetJobType()) {
  186.     case CMD_SHARE_PACKAGE:
  187.  
  188.         printf("***************************************\n");
  189.         printf("* Share package on server job.        *\n");
  190.         printf("***************************************\n");
  191.         TServerParams sp;
  192.         strcpy(sp.szSiteName, szSiteName);
  193.         sp.dwPlatforms = dwPlatforms;
  194.         InputString("Package name", sp.szPackageName);
  195.         InputString("Package comment", sp.szPackageComment);
  196.         InputString("Package directory location (UNC path)", sp.szPackagePath);
  197.         InputString("Package share name", sp.szShareName);
  198.         InputString("Program item description", sp.szDescription);
  199.         InputString("Program item command line", sp.szCmdLine);
  200.         InputString("Program item registry name", sp.szRegistryName);
  201.         printf("\n");
  202.  
  203.         // First share the package on the server
  204.         //=======================================
  205.         ServerDoShare(hConnect, &sp);
  206.  
  207.         printf("**************************************************\n");
  208.         printf("* The server install job has completed.  To      *\n");
  209.         printf("* use the shared package please create a program *\n");
  210.         printf("* group in the SMS administration program and add*\n");
  211.         printf("* the package that was just shared to the group. *\n");
  212.         printf("*                                                *\n");
  213.         printf("* For more information, please refer to chapter  *\n");
  214.         printf("* nine of the SMS Administrator's guide.         *\n");
  215.         printf("**************************************************\n");
  216.         printf("\n");
  217.         break;
  218.  
  219.     case CMD_RUN_COMMAND:
  220.  
  221.         printf("************************************************\n");
  222.         printf("* Run command on workstation job.              *\n");
  223.         printf("************************************************\n");
  224.         TClientParams cp;
  225.         strcpy(cp.szSiteName, szSiteName);
  226.         cp.dwPlatforms = dwPlatforms;
  227.         InputString("Package name", cp.szPackageName);
  228.         InputString("Package directory location (UNC path)", cp.szPackagePath);
  229.         InputString("Package comment", cp.szPackageComment);
  230.         InputString("WCL Name", cp.szWclName);
  231.         InputString("WCL Command", cp.szWclCommand);
  232.         printf("\n");
  233.  
  234.  
  235.         // Now that we've shared the package on the server,
  236.         // submit a job to setup the client program.
  237.         //=================================================
  238.         ClientDoRunCommand(hConnect, &cp);
  239.         break;
  240.     default:
  241.         printf("Invalid job type. No job submitted.\n");
  242.         break;
  243.     }
  244.  
  245.     if (hConnect != NULL) {
  246.         SmsDataSourceDisconnect( hConnect );
  247.     }
  248. }
  249.  
  250.  
  251.  
  252.  
  253.  
  254.  
  255. // ====================================================================
  256. //
  257. // SetScalarString
  258. //
  259. // This function sets the value specified scalar to the given string
  260. // value.
  261. //
  262. // Parameters:
  263. //      HANDLE hFolder
  264. //          The handle of the folder containing the scalar to modify.
  265. //      char *pszName
  266. //          The name of the scalar.
  267. //      char *pszValue
  268. //          The string that will be assigned to the scalar's value.
  269. //
  270. // Returns:
  271. //      SMS_STATUS
  272. //          The SMS status code.
  273. //
  274. // Note that the scalar specified must be of type SCALAR_STRING.
  275. //
  276. // ====================================================================
  277. SMS_STATUS SetScalarString( HANDLE hFolder, char *pszName, char *pszValue )
  278. {
  279.     SCALAR sc;
  280.     sc.pszName = pszName;
  281.     sc.scType = SCALAR_STRING;
  282.     sc.pszValue = pszValue;
  283.  
  284.     SMS_STATUS stat;
  285.     stat = SmsSetScalar(hFolder, &sc);
  286.     return stat;
  287. }
  288.  
  289.  
  290. // ====================================================================
  291. //
  292. // SetScalarBool
  293. //
  294. // This function sets the value specified scalar to the given boolean value
  295. //
  296. // Parameters:
  297. //      HANDLE hFolder
  298. //          The handle of the folder containing the scalar to modify.
  299. //      char *pszName
  300. //          The name of the scalar.
  301. //      BOOL bIsTrue
  302. //          The boolean value to set the scalar to.
  303. //
  304. // Returns:
  305. //      SMS_STATUS
  306. //          The SMS status code.
  307. //
  308. // Note that the scalar specified must be of type SCALAR_INT.
  309. //
  310. // ====================================================================
  311. SMS_STATUS SetScalarBool( HANDLE hFolder, char *pszName, BOOL bIsTrue )
  312. {
  313.     SCALAR sc;
  314.     sc.pszName = pszName;
  315.     sc.scType = SCALAR_INT;
  316.     sc.dwValue = bIsTrue ? 1 : 0;
  317.  
  318.  
  319.     SMS_STATUS stat;
  320.     stat = SmsSetScalar(hFolder, &sc);
  321.     return stat;
  322. }
  323.  
  324.  
  325. // ====================================================================
  326. //
  327. // SetScalarDword
  328. //
  329. // This function sets the value specified scalar to the given DWORD value.
  330. //
  331. // Parameters:
  332. //      HANDLE hFolder
  333. //          The handle of the folder containing the scalar to modify.
  334. //      char *pszName
  335. //          The name of the scalar.
  336. //      DWORD dwValue
  337. //          The DWORD value to set the scalar to.
  338. //
  339. // Returns:
  340. //      SMS_STATUS
  341. //          The SMS status code.
  342. //
  343. // Note that the scalar specified must be of type SCALAR_INT.
  344. //
  345. // ====================================================================
  346. SMS_STATUS SetScalarDword( HANDLE hFolder, char *pszName, DWORD dwValue )
  347. {
  348.     SCALAR sc;
  349.     sc.pszName = pszName;
  350.     sc.scType = SCALAR_INT;
  351.     sc.dwValue = dwValue;
  352.  
  353.  
  354.     SMS_STATUS stat;
  355.     stat = SmsSetScalar(hFolder, &sc);
  356.     return stat;
  357. }
  358.  
  359.  
  360. // ====================================================================
  361. //
  362. // SetScalarTime
  363. //
  364. // This function sets the value specified scalar to the given time
  365. // value.
  366. //
  367. // Parameters:
  368. //      HANDLE hFolder
  369. //          The handle of the folder containing the scalar to modify.
  370. //      char *pszName
  371. //          The name of the scalar.
  372. //      time_t tValue
  373. //          The time value to assign to the scalar.
  374. //
  375. // Returns:
  376. //      SMS_STATUS
  377. //          The SMS status code.
  378. //
  379. // Note that the scalar specified must be of type SCALAR_TIME.
  380. //
  381. // ====================================================================
  382. SMS_STATUS SetScalarTime( HANDLE hFolder, char *pszName, time_t tValue )
  383. {
  384.     SCALAR sc;
  385.     sc.pszName = pszName;
  386.     sc.scType = SCALAR_TIME;
  387.     sc.tValue = tValue;
  388.  
  389.     SMS_STATUS stat;
  390.     stat = SmsSetScalar(hFolder, &sc);
  391.     return stat;
  392. }
  393.  
  394.  
  395. // ====================================================================
  396. //
  397. // GetScalarString
  398. //
  399. // This function gets the string value of the specified scalar.
  400. //
  401. // Parameters:
  402. //      HANDLE hFolder
  403. //          The handle of the folder containing the scalar to modify.
  404. //      char *pszName
  405. //          The name of the scalar.
  406. //      char *pchBuffer
  407. //          Pointer to the buffer to store the scalar's string value.
  408. //      DWORD cchBuffer
  409. //          The size of the buffer.
  410. //
  411. // Returns:
  412. //      SMS_STATUS
  413. //          The SMS status code.
  414. //
  415. // Note that the scalar specified must be of type SCALAR_STRING.
  416. //
  417. // ====================================================================
  418. SMS_STATUS GetScalarString( HANDLE hFolder,
  419.                             char *pszName,
  420.                             char *pchBuffer,
  421.                             DWORD cchBuffer )
  422. {
  423.     SCALAR sc;
  424.  
  425.     SMS_STATUS stat;
  426.     *pchBuffer = '\0';
  427.  
  428.     char szNameBuffer[CCH_MAXSTRING];
  429.     sc.pszName = szNameBuffer;
  430.     sc.pszValue = pchBuffer;
  431.     sc.dwLen = cchBuffer;
  432.     stat = SmsGetScalarByName(hFolder, pszName, &sc);
  433.  
  434.     if (stat == SMS_OK) {
  435.         if (sc.scType == SCALAR_STRING) {
  436.             strcpy(pchBuffer, sc.pszValue);
  437.         }
  438.         else {
  439.             DisplaySmsError("GetScalarString: scalar is not SCALAR_STRING", SMS_OK);
  440.             stat = SMS_ERROR;
  441.         }
  442.     }
  443.     else {
  444.         DisplaySmsError("GetScalarString: SmsGetScalarByName failed", stat);
  445.     }
  446.     return(stat);
  447. }
  448.  
  449.  
  450. // ====================================================================
  451. //
  452. // GetScalarDword
  453. //
  454. // This function gets the DWORD value of the specified scalar.
  455. //
  456. // Parameters:
  457. //      HANDLE hFolder
  458. //          The handle of the folder containing the scalar to modify.
  459. //
  460. //      char *pszName
  461. //          The name of the scalar.
  462. //
  463. //      DWORD *pdwValue
  464. //          Pointer to the place to store the scalar's DWORD value.
  465. //
  466. // Returns:
  467. //      SMS_STATUS
  468. //          The SMS status code.
  469. //
  470. // Note that the scalar specified must be of type SCALAR_INT.
  471. //
  472. // ====================================================================
  473. SMS_STATUS GetScalarDword( HANDLE hFolder, char *pszName, DWORD *pdwValue )
  474. {
  475.     SCALAR sc;
  476.  
  477.     SMS_STATUS stat;
  478.     char szNameBuffer[CCH_MAXSTRING];
  479.     sc.pszName = szNameBuffer;
  480.     stat = SmsGetScalarByName(hFolder, pszName, &sc);
  481.  
  482.     if (stat == SMS_OK) {
  483.         if (sc.scType == SCALAR_INT) {
  484.             *pdwValue = sc.dwValue;
  485.         }
  486.         else {
  487.             DisplaySmsError("GetScalarDword: Scalar is not SCALAR_INT", SMS_OK);
  488.             stat = SMS_ERROR;
  489.         }
  490.     }
  491.     else {
  492.         DisplaySmsError("GetScalarDword: SmsGetScalarByName failed", stat);
  493.     }
  494.     return(stat);
  495. }
  496.  
  497.  
  498. // ====================================================================
  499. //
  500. // FindFolder
  501. //
  502. // This function searches a container for a folder with a scalar that
  503. // matches the given scalar name and string scalar value.
  504. //
  505. // Parameters:
  506. //      HANDLE hContainer
  507. //          The handle of the containter to search.
  508. //
  509. //      char *pszName
  510. //          The name of the scalar.
  511. //
  512. //      char *pszScalarValue
  513. //          The "match" value to test for.
  514. //
  515. //      HFOLDER* phFolder
  516. //          Pointer to the place to store the folder handle if a folder
  517. //          containing the specified scalar value is found.
  518. //
  519. //
  520. // Returns;
  521. //      SMS_OK if the folder is found, SMS_NOT_FOUND otherwise.
  522. //      The folder handle is returned via a pointer.
  523. //
  524. // ====================================================================
  525. SMS_STATUS FindFolder( HANDLE hContainer,
  526.                        DWORD fType,
  527.                        char *pszScalarName,
  528.                        char *pszScalarValue,
  529.                        HANDLE *phFolder )
  530. {
  531.     *phFolder = NULL;
  532.  
  533.     while(TRUE) {
  534.         SMS_STATUS stat;
  535.         HANDLE hFolder;
  536.         char szValue[CCH_MAXSTRING];
  537.  
  538.         stat = SmsGetNextFolder(hContainer, fType, &hFolder);
  539.         if (stat == SMS_NO_MORE_DATA) {
  540.             return(SMS_NOT_FOUND);
  541.         }
  542.  
  543.         if (stat != SMS_OK) {
  544.             DisplaySmsError("SmsGetNextFolder error", stat);
  545.             return(SMS_NOT_FOUND);
  546.         }
  547.  
  548.         GetScalarString(hFolder, pszScalarName, szValue, sizeof(szValue));
  549.         if (!strcmp(szValue, pszScalarValue)) {
  550.             *phFolder = hFolder;
  551.             return(SMS_OK);
  552.         }
  553.  
  554.         SmsCloseFolder(hFolder);
  555.     }
  556. }
  557.  
  558.  
  559. // ====================================================================
  560. //
  561. // InputString
  562. //
  563. // Prompt the user to input a string and return the string in the
  564. // specified buffer.
  565. //
  566. // Parameters:
  567. //      const char *pszMessage
  568. //          The user prompt to display.
  569. //
  570. //      char *pszResult
  571. //          Pointer to the buffer where the user's input will be returned.
  572. //
  573. // Returns;
  574. //      The user's input is returned via the given buffer.
  575. //
  576. // ====================================================================
  577. void InputString( const char *pszMessage, char *pszResult )
  578. {
  579.     printf("%s: ", pszMessage);
  580.     gets(pszResult);
  581. }
  582.  
  583.  
  584.  
  585.  
  586. // ====================================================================
  587. //
  588. // ConnectToDatasource
  589. //
  590. // Get the datasource connection information from the user and use it
  591. // to connect to the datasource.
  592. //
  593. // Parameters:  None.
  594. //
  595. // Returns:
  596. //      The connection handle or NULL if the connection failed.
  597. //
  598. // ====================================================================
  599. HANDLE ConnectToDatasource()
  600. {
  601.     // Get the information we need to connect to the
  602.     // data source from the user.
  603.     //==============================================
  604.     char szServer[CCH_MAXINPUT];
  605.     char szUser[CCH_MAXINPUT];
  606.     char szPasswd[CCH_MAXINPUT];
  607.     char szDatabase[CCH_MAXINPUT];
  608.  
  609.     printf("\n");
  610.     printf("**************************\n");
  611.     printf("* Connect to data source *\n");
  612.     printf("**************************\n");
  613.     InputString("SQL server name", szServer);
  614.     InputString("SQL database name", szDatabase);
  615.     InputString("User name for SQL server", szUser);
  616.     InputString("Password for SQL server", szPasswd);
  617.     printf("\n");
  618.  
  619.  
  620.     // Connect to a data source. SQL in this case.
  621.     // ===========================================
  622.     DATASOURCE dsParams;
  623.  
  624.     dsParams.sqlParams.ds          = DB_SQL;
  625.     dsParams.sqlParams.pszServer   = szServer;
  626.     dsParams.sqlParams.pszUserName = szUser;
  627.     dsParams.sqlParams.pszPasswd   = szPasswd;
  628.     dsParams.sqlParams.pszDbName   = szDatabase;
  629.     dsParams.sqlParams.pFunc       = NULL;         // No encryption.
  630.     dsParams.sqlParams.pszKey      = "";
  631.  
  632.     HANDLE hConnect;
  633.     SMS_STATUS stat;
  634.     stat = SmsDataSourceConnect( &dsParams, &hConnect);
  635.  
  636.     if (stat != SMS_OK) {
  637.         hConnect = NULL;
  638.         DisplaySmsError("Connect to data source failed", stat);
  639.     }
  640.  
  641.     return( hConnect );
  642. }
  643.  
  644.  
  645.  
  646. // ====================================================================
  647. //
  648. // GetPlatformSelection
  649. //
  650. // Prompt the user to select a one or more platforms.  The platforms
  651. // are selected by entering a comma separated list of platform indexes.
  652. // These platform indexes are converted to the platforms flags value
  653. // for the SDK.
  654. //
  655. // Parameters:  None.
  656. //
  657. // Returns:
  658. //      The SMS SDK platform flags value.
  659. //
  660. // ====================================================================
  661. DWORD GetPlatformSelection()
  662. {
  663.     printf("**********************************************\n");
  664.     printf("* Select a platform from the following list. *\n");
  665.     printf("**********************************************\n");
  666.     printf("   1) MS-DOS \n");
  667.     printf("   2) Windows 3.1\n");
  668.     printf("   3) Windows95\n");
  669.     printf("   4) Windows NT (X86)\n");
  670.     printf("   5) Windows NT (Mips)\n");
  671.     printf("   6) Windows NT (Alpha)\n");
  672.     printf("   7) Macintosh\n");
  673.     printf("\n");
  674.  
  675.     DWORD dwPlatforms = 0;
  676.     char szReply[CCH_MAXINPUT];
  677.     InputString("Enter a comma separated list of platform number(s)", szReply);
  678.     printf("\n");
  679.  
  680.     const char *pszReply = szReply;
  681.     while (*pszReply) {
  682.  
  683.  
  684.         if (*pszReply < '1' || *pszReply > '6') {
  685.             // An invalid character is present in the
  686.             // reply.  Flag this error by returning zero.
  687.             //==========================================
  688.             dwPlatforms = 0;
  689.             break;
  690.         }
  691.  
  692.         // Interpret the platform selector character.
  693.         //===========================================
  694.         switch(*pszReply++) {
  695.         case '1':
  696.             dwPlatforms |= PLTFRM_MSDOS;
  697.             break;
  698.  
  699.         case '2':
  700.             dwPlatforms |= PLTFRM_WIN16;
  701.             break;
  702.  
  703.         case '3':
  704.             dwPlatforms |= PLTFRM_WIN95;
  705.             break;
  706.  
  707.         case '4':
  708.             dwPlatforms |= PLTFRM_WIN32_X86;
  709.             break;
  710.  
  711.         case '5':
  712.             dwPlatforms |= PLTFRM_WIN32_MIPS;
  713.             break;
  714.  
  715.         case '6':
  716.             dwPlatforms |= PLTFRM_WIN32_ALPHA;
  717.             break;
  718.  
  719.         case '7':
  720.             dwPlatforms |= PLTFRM_MACINTOSH;
  721.             break;
  722.         }
  723.  
  724.         // Skip any trailing whitespace after the digit.
  725.         //==============================================
  726.         while(*pszReply == ' ' || *pszReply=='\t') {
  727.             ++pszReply;
  728.         }
  729.  
  730.         // Skip the comma.
  731.         //================
  732.         if (*pszReply == ',') {
  733.             ++pszReply;
  734.         }
  735.  
  736.         // Skip white space preceding the next digit.
  737.         //=========================
  738.         while (*pszReply == ' ' || *pszReply=='\t') {
  739.             ++pszReply;
  740.         }
  741.  
  742.     }
  743.  
  744.     return( dwPlatforms );
  745. }
  746.  
  747.  
  748.  
  749.  
  750. // ====================================================================
  751. //
  752. // ServerWriteProgItem
  753. //
  754. // Set the value of the program item folder's scalars, link it into the
  755. // folder hierarchy and finally insert it into the data source.
  756. //
  757. // Parameters:
  758. //      HANDLE hFolderProgItem
  759. //          The program item folder's handle.
  760. //
  761. //      TServerParams *psp
  762. //          Pointer to the "share package on server" parameters
  763. //          that the user was asked to input at the beginning of the
  764. //          program.
  765. //
  766. // Returns:
  767. //      SMS_OK if no error occurred, otherwise the SDK status code.
  768. //
  769. // ====================================================================
  770. SMS_STATUS ServerWriteProgItem( HANDLE hFolderProgItem, TServerParams *psp )
  771. {
  772.  
  773.     SetScalarString(hFolderProgItem, "Description", psp->szDescription);
  774.     SetScalarString(hFolderProgItem, "Command line", psp->szCmdLine);
  775.     SetScalarDword(hFolderProgItem,  "Run minimized", 0);
  776.     SetScalarDword(hFolderProgItem,  "Platforms", psp->dwPlatforms);
  777.     SetScalarString(hFolderProgItem, "Configure script file", "");
  778.     SetScalarDword(hFolderProgItem,  "Search local flag", 1);
  779.     SetScalarDword(hFolderProgItem,  "Drive mode", 1);
  780.     SetScalarString(hFolderProgItem, "Registry name", psp->szRegistryName);
  781.     SetScalarDword(hFolderProgItem,  "Executable flag", 1);
  782.  
  783.  
  784.  
  785.     SMS_STATUS stat;
  786.     stat = SmsLinkFolder(hFolderProgItem);
  787.     if (stat != SMS_OK) {
  788.         DisplaySmsError("Failed to link the server share program item folder into the hierarchy", stat);
  789.         return( stat );
  790.     }
  791.  
  792.     stat = SmsCommitFolder(hFolderProgItem);
  793.     if ((stat != SMS_OK) && (stat != SMS_PARENT_NEEDS_COMMIT)) {
  794.         DisplaySmsError("Failed to insert the server share program item folder into the package", stat);
  795.     }
  796.     else {
  797.         // If the status code was SMS_PARENT_NEEDS_COMMIT, we convert the status to
  798.         // SMS_OK, since the commit was successful.
  799.         //=========================================================================
  800.         stat = SMS_OK;
  801.     }
  802.  
  803.  
  804.     // Note program item folders are not actually inserted into the
  805.     // datasource until a commit is also done on the parent
  806.     // package folder.
  807.     //=====================================================
  808.     return( stat );
  809. }
  810.  
  811.  
  812. // ====================================================================
  813. //
  814. // ServerWritePkg
  815. //
  816. // Set the value of the package folder's scalars, link it into the
  817. // folder hierarchy and finally insert it into the data source.
  818. //
  819. // Parameters:
  820. //      HANDLE hFolderPkg
  821. //          The package folder's handle.
  822. //
  823. //      TServerParams *psp
  824. //          Pointer to the "share package on server" parameters
  825. //          that the user was asked to input at the beginning of the
  826. //          program.
  827. //
  828. // Returns:
  829. //      SMS_OK if no error occurred, otherwise the SDK status code.
  830. //
  831. // ====================================================================
  832. SMS_STATUS ServerWritePkg( HANDLE hFolderPkg, TServerParams *psp )
  833. {
  834.     SetScalarString(hFolderPkg, "Name", psp->szPackageName);
  835.     SetScalarString(hFolderPkg, "Comment", psp->szPackageComment);
  836.     SetScalarString(hFolderPkg, "Server root", psp->szPackagePath);
  837.     SetScalarString(hFolderPkg, "Share name", psp->szShareName);
  838.     SetScalarDword(hFolderPkg,  "Share permissions", (DWORD)SHARE_PERMISSIONS);
  839.  
  840.  
  841.     SMS_STATUS stat;
  842.     stat = SmsLinkFolder(hFolderPkg);
  843.     if (stat != SMS_OK) {
  844.         DisplaySmsError("Failed to link the server share package folder into the hierarchy", stat);
  845.         return( stat );
  846.     }
  847.  
  848.  
  849.     stat = SmsCommitFolder(hFolderPkg);
  850.     if ((stat != SMS_OK) && (stat != SMS_PARENT_NEEDS_COMMIT)) {
  851.         DisplaySmsError("Failed to insert the server share package folder into the datasource", stat);
  852.     }
  853.  
  854.     return( stat );
  855. }
  856.  
  857.  
  858. // ====================================================================
  859. //
  860. // ServerCreatePkg
  861. //
  862. // This function create the server install job package.
  863. //
  864. // Parameters:
  865. //      HANDLE hConnect
  866. //          The datasource connection handle.
  867. //
  868. //      TServerParams *psp
  869. //          Pointer to the "share package on server" parameters
  870. //          that the user was asked to input at the beginning of the
  871. //          program.
  872. //
  873. //      char *pszPackageID
  874. //          Pointer to the buffer where the package ID will be
  875. //          returned.
  876. //
  877. //      DWORD cchPackageID
  878. //          Size of the package ID buffer.
  879. //
  880. //      char *pszProgItemID
  881. //          Pointer to the buffer where the program item ID will be
  882. //          returned.
  883. //
  884. //      DWORD cchProgItemID
  885. //          Size of the program item ID buffer.
  886. //
  887. // Returns:
  888. //      SMS_OK if no error occurred, otherwise the SDK status code.
  889. //
  890. // ====================================================================
  891. SMS_STATUS ServerCreatePkg( HANDLE hConnect,
  892.                             TServerParams *psp,
  893.                             char *pszPackageID,
  894.                             DWORD cchPackageID,
  895.                             char *pszProgItemID,
  896.                             DWORD cchProgItemID)
  897. {
  898.     SMS_STATUS stat;
  899.     HANDLE hContainer;
  900.     HANDLE hFolderPkg = NULL;
  901.     HANDLE hFolderProgItem = NULL;
  902.  
  903.     // First open the package container.  If we fail to open it,
  904.     // display an error message and give up.
  905.     //=========================================================
  906.     stat = SmsOpenContainer( C_PACKAGE, hConnect, &hContainer );
  907.     if (stat != SMS_OK) {
  908.         DisplaySmsError("Failed to open the package container", stat);
  909.         return( stat );
  910.     }
  911.  
  912.     // Now create a new package folder.
  913.     //=================================
  914.     stat = SmsCreateFolder( hContainer, F_PACKAGE, "Dummy", &hFolderPkg );
  915.     if (stat != SMS_OK) {
  916.         DisplaySmsError("Failed to create server share package", stat);
  917.         goto CLEANUP_AND_EXIT;
  918.     }
  919.  
  920.  
  921.     stat = SmsCreateFolder(hFolderPkg, F_PROGITEM, "Dummy", &hFolderProgItem);
  922.     if (stat != SMS_OK) {
  923.         DisplaySmsError("Failed to create server share program item", stat);
  924.         goto CLEANUP_AND_EXIT;
  925.     }
  926.  
  927.  
  928.     stat = ServerWriteProgItem(hFolderProgItem, psp);
  929.     if (stat != SMS_OK) {
  930.         goto CLEANUP_AND_EXIT;
  931.     }
  932.  
  933.     stat = ServerWritePkg(hFolderPkg, psp);
  934.     if (stat != SMS_OK) {
  935.         goto CLEANUP_AND_EXIT;
  936.     }
  937.  
  938.  
  939.     GetScalarString(hFolderPkg, "Key", pszPackageID, cchPackageID);
  940.     GetScalarString(hFolderProgItem, "ItemKey", pszProgItemID, cchProgItemID);
  941.     stat = SMS_OK;
  942.  
  943.  
  944. CLEANUP_AND_EXIT:
  945.  
  946.     if (hFolderProgItem) {
  947.         SmsCloseFolder(hFolderProgItem);
  948.     }
  949.  
  950.     if (hFolderPkg) {
  951.         SmsCloseFolder(hFolderPkg);
  952.     }
  953.  
  954.     SmsCloseContainer(hContainer);
  955.     return( stat );
  956. }
  957.  
  958.  
  959.  
  960. // ====================================================================
  961. //
  962. // ServerWriteJob
  963. //
  964. // This function sets the values of the job folder's scalars, links the
  965. // job folder into the folder hierachy, and then inserts the folder
  966. // into the data source.
  967. //
  968. // Parameters:
  969. //      HANDLE hFolderJob
  970. //          The handle to the server install job folder.
  971. //
  972. //      TServerParams *psp
  973. //          Pointer to the "share package on server" parameters
  974. //          that the user was asked to input at the beginning of the
  975. //          program.
  976. //
  977. //      char *pszPackageID
  978. //          Pointer to the server install package ID.
  979. //
  980. // Returns:
  981. //      SMS_OK if no error occurred, otherwise the SDK status code.
  982. //
  983. // ====================================================================
  984. BOOL ServerWriteJob( HANDLE hFolderJob,
  985.                      TServerParams *psp,
  986.                      char *pszPackageID )
  987. {
  988.     // Submit the job immediately, so set the job submission time
  989.     // to the current time.
  990.     //===========================================================
  991.     time_t timeJob;
  992.     time( &timeJob );
  993.  
  994.  
  995.     SetScalarString(hFolderJob, "Job comment",      "This is an SDK sample job");
  996.     SetScalarTime(  hFolderJob, "Activate time",    timeJob);
  997.     SetScalarDword( hFolderJob, "Priority",         3);
  998.     SetScalarDword( hFolderJob, "Repeat mode",      1);
  999.     SetScalarDword( hFolderJob, "Cancel mode",      0);
  1000.     SetScalarString(hFolderJob, "Package ID",       pszPackageID);
  1001.     SetScalarDword( hFolderJob, "PackageOverwriteFlag", 0);
  1002.     SetScalarDword( hFolderJob, "Job target",       WKSTAJOB_TGT_MACHPATH);
  1003.     SetScalarDword( hFolderJob, "Limit to sites",   JOBTGT_SITE);
  1004.     SetScalarDword( hFolderJob, "Include subsites", JOBTGT_INCLUDESUBSITES);
  1005.     SetScalarString(hFolderJob, "Site limit name",  psp->szSiteName);
  1006.  
  1007.     // At this point we have a folder in memory, but it has not
  1008.     // been linked into the folder hierarchy yet.  We do so by
  1009.     // calling SmsLinkFolder.
  1010.     //=========================================================
  1011.     SMS_STATUS stat;
  1012.     stat = SmsLinkFolder(hFolderJob);
  1013.     if (stat != SMS_OK) {
  1014.         DisplaySmsError("SmsLinkFolder(hFolderJob) failed", stat);
  1015.         return(stat);
  1016.     }
  1017.  
  1018.     // The folder is now linked into the folder hierachy, but it
  1019.     // has not yet been inserted into the data source.  We do so
  1020.     // now by calling SmsCommitFolder.
  1021.     //==========================================================
  1022.     stat = SmsCommitFolder(hFolderJob);
  1023.     if (stat != SMS_OK) {
  1024.         DisplaySmsError("Failed to insert the job into the datasource", stat);
  1025.         return(stat);
  1026.     }
  1027.  
  1028.     return( SMS_OK );
  1029. }
  1030.  
  1031.  
  1032.  
  1033.  
  1034. // ====================================================================
  1035. //
  1036. // ServerSubmitShareJob
  1037. //
  1038. // This function creates a share package on server job.
  1039. //
  1040. // Parameters:
  1041. //      HANDLE hConnect
  1042. //          The datasource connection handle.
  1043. //
  1044. //      TServerParams *psp
  1045. //          Pointer to the "share package on server" parameters
  1046. //          that the user was asked to input at the beginning of the
  1047. //          program.
  1048. //
  1049. //      char *pszPackageID
  1050. //          Pointer to the server install package ID.
  1051. //
  1052. //      char *pszJobID
  1053. //          Pointer to the buffer where the server install job ID will
  1054. //          be returned.
  1055. //
  1056. //      DWORD cchJobID
  1057. //          The size of the job ID buffer.
  1058. //
  1059. // Returns;
  1060. //      SMS_OK if everything was successful, otherwise the SMS SDK
  1061. //      status code.
  1062. //      The job ID is in the job name buffer.
  1063. //
  1064. // ====================================================================
  1065. SMS_STATUS ServerSubmitShareJob(HANDLE hConnect,
  1066.                                 TServerParams *psp,
  1067.                                 char *pszPackageID,
  1068.                                 char *pszJobID,
  1069.                                 DWORD cchJobID)
  1070. {
  1071.     *pszJobID = 0;
  1072.  
  1073.     SMS_STATUS stat;
  1074.     HANDLE hContainerJob;
  1075.     stat = SmsOpenContainer( C_JOB, hConnect, &hContainerJob );
  1076.     if (stat != SMS_OK) {
  1077.         DisplaySmsError("Failed to open job container", stat);
  1078.         return( stat );
  1079.     }
  1080.  
  1081.     HANDLE hFolderJob;
  1082.     stat = SmsCreateFolder( hContainerJob, F_SRVINSTALLJOB, "Dummy", &hFolderJob );
  1083.     if (stat == SMS_OK) {
  1084.         if (ServerWriteJob(hFolderJob, psp, pszPackageID) == SMS_OK) {
  1085.  
  1086.             // We will need the Job ID later so that we can wait for
  1087.             // the job to complete before submitting the client setup
  1088.             // package.  We get the Job ID below.
  1089.             //==================================================
  1090.             GetScalarString(hFolderJob, "Job ID", pszJobID, cchJobID);
  1091.         }
  1092.  
  1093.  
  1094.         // We close the folder to avoid a memory leak.
  1095.         //============================================
  1096.         stat = SmsCloseFolder(hFolderJob);
  1097.         if (stat != SMS_OK) {
  1098.             DisplaySmsError("Failed to close job folder", stat);
  1099.         }
  1100.  
  1101.     }
  1102.     else {
  1103.         DisplaySmsError("Failed to create the job folder", stat);
  1104.     }
  1105.  
  1106.  
  1107.  
  1108.     stat = SmsCloseContainer(hContainerJob);
  1109.     if (stat != SMS_OK) {
  1110.         DisplaySmsError("Failed to close the job container", stat);
  1111.     }
  1112.     return stat;
  1113. }
  1114.  
  1115.  
  1116. // ====================================================================
  1117. //
  1118. // JobStatusToString
  1119. //
  1120. // Convert the job status value to a human readable string.
  1121. //
  1122. // Parameters:
  1123. //      DWORD dwJobStatus
  1124. //          The status value from the job's "Job status" scalar.
  1125. //
  1126. //      char *pszJobStatus
  1127. //          Pointer to a buffer to recieve the human readable version
  1128. //          of the job status.
  1129. //          The size of the job ID buffer.
  1130. //
  1131. // Returns;
  1132. //      SMS_OK if everything was successful, otherwise the SMS SDK
  1133. //      status code.
  1134. //
  1135. // ====================================================================
  1136. void JobStatusToString( DWORD dwJobStatus, char *pszJobStatus )
  1137. {
  1138.     char *psz;
  1139.     switch(dwJobStatus) {
  1140.     case JOBSTAT_PENDING:
  1141.         psz = "pending";
  1142.         break;
  1143.     case JOBSTAT_ACTIVE:
  1144.         psz = "active";
  1145.         break;
  1146.     case JOBSTAT_CANCELLED:
  1147.         psz = "cancelled";
  1148.         break;
  1149.     case JOBSTAT_COMPLETE:
  1150.         psz = "complete";
  1151.         break;
  1152.     case JOBSTAT_FAILED:
  1153.         psz = "failed";
  1154.         break;
  1155.     case JOBSTAT_RETRYING:
  1156.         psz = "retrying";
  1157.         break;
  1158.     default:
  1159.         sprintf(pszJobStatus, "unkown status %ld", dwJobStatus);
  1160.         return;
  1161.         break;
  1162.     }
  1163.     strcpy(pszJobStatus, psz);
  1164. }
  1165.  
  1166.  
  1167.  
  1168. // ====================================================================
  1169. //
  1170. // ServerWaitJobComplete
  1171. //
  1172. // This function polls the status of the server install job and
  1173. // continues doing so until the job is complete.  As this is done,
  1174. // status given to the user as to the progress of the job.
  1175. //
  1176. // Parameters:
  1177. //      HANDLE hConnect
  1178. //          The datasource connection handle.
  1179. //
  1180. //      char *pszJobID
  1181. //          Pointer to the ID string for the job to wait on.
  1182. //
  1183. // Returns:
  1184. //      SMS_OK if everything went ok and the job has completed,
  1185. //      otherwise the SDK status code.
  1186. //
  1187. // ====================================================================
  1188. SMS_STATUS ServerWaitJobComplete( HANDLE hConnect, char *pszJobID )
  1189. {
  1190.     printf("***************************************\n");
  1191.     printf("* Share package on server job.        *\n");
  1192.     printf("* Waiting for job to complete.        *\n");
  1193.     printf("***************************************\n");
  1194.  
  1195.     while(TRUE) {
  1196.         SMS_STATUS stat;
  1197.         HANDLE hContainerJob;
  1198.         stat = SmsOpenContainer( C_JOB, hConnect, &hContainerJob );
  1199.         if (stat != SMS_OK) {
  1200.             DisplaySmsError("Failed to open job container while waiting for server share job", stat);
  1201.             return( stat );
  1202.         }
  1203.  
  1204.         stat = SmsPopulate(hContainerJob, POP_SYNC, NULL);
  1205.         if (stat != SMS_OK) {
  1206.             DisplaySmsError("Failed to populate job container while waiting for server share job", stat);
  1207.             SmsCloseContainer(hContainerJob);
  1208.             return(stat);
  1209.         }
  1210.  
  1211.         HANDLE hFolderJob;
  1212.         stat = FindFolder(hContainerJob,  F_SRVINSTALLJOB, "Job ID", pszJobID, &hFolderJob);
  1213.         if (stat != SMS_OK) {
  1214.             DisplaySmsError("Server share job not found while waiting", stat);
  1215.             SmsCloseContainer(hContainerJob);
  1216.             return(stat);
  1217.         }
  1218.  
  1219.         DWORD dwScalarValue;
  1220.         GetScalarDword(hFolderJob, "Job status", &dwScalarValue);
  1221.  
  1222.         SmsCloseFolder(hFolderJob);
  1223.         SmsCloseContainer(hContainerJob);
  1224.  
  1225.  
  1226.         char szJobStatus[CCH_MAXSTRING];
  1227.         JobStatusToString(dwScalarValue, szJobStatus);
  1228.  
  1229.         printf("Share package on server job, status = %s\n", szJobStatus);
  1230.  
  1231.         if (dwScalarValue == 4) {
  1232.              return(SMS_OK);
  1233.         }
  1234.  
  1235.  
  1236.  
  1237.         // Sleep for 10 seconds before checking the status of the server
  1238.         // share job again.
  1239.         //=============================================================
  1240.         Sleep(10000);
  1241.     }
  1242.  
  1243.     // Control should never come here. So no return value is
  1244.     // necessary.
  1245.     //======================================================
  1246.  
  1247. }
  1248.  
  1249.  
  1250.  
  1251.  
  1252.  
  1253.  
  1254. // ====================================================================
  1255. //
  1256. // ServerDoShare
  1257. //
  1258. // This function creates a server install package and then submits
  1259. // a share package on server job.
  1260. //
  1261. // Parameters:
  1262. //      HANDLE hConnect
  1263. //          The datasource connection handle.
  1264. //
  1265. //      TServerParams *psp
  1266. //          Pointer to the "share package on server" parameters
  1267. //          that the user was asked to input at the beginning of the
  1268. //          program.
  1269. //
  1270. // Returns:
  1271. //      SMS_OK if everything went ok, otherwise the SDK status code.
  1272. //
  1273. // ====================================================================
  1274. void ServerDoShare( HANDLE hConnect, TServerParams *psp )
  1275. {
  1276.     char szPackageID[CCH_MAXSTRING];
  1277.     char szProgItemID[CCH_MAXSTRING];
  1278.     char szJobID[CCH_MAXSTRING];
  1279.     SMS_STATUS stat;
  1280.  
  1281.     stat = ServerCreatePkg(hConnect,
  1282.                            psp,
  1283.                            szPackageID, sizeof(szPackageID),
  1284.                            szProgItemID, sizeof(szProgItemID));
  1285.     if (stat != SMS_OK) {
  1286.         DisplaySmsError("Failed to create server share package", stat);
  1287.         return;
  1288.     }
  1289.  
  1290.  
  1291.     // Submit the share package on server job and get the
  1292.     // job ID.
  1293.     //====================================================
  1294.     stat = ServerSubmitShareJob(hConnect,
  1295.                     psp,
  1296.                     szPackageID,
  1297.                     szJobID,
  1298.                     sizeof(szJobID));
  1299.     if (stat != SMS_OK) {
  1300.         DisplaySmsError("Failed to submit server share package", stat);
  1301.         return;
  1302.     }
  1303.  
  1304.  
  1305.     ServerWaitJobComplete(hConnect, szJobID);
  1306. }
  1307.  
  1308.  
  1309.  
  1310.  
  1311.  
  1312. // ====================================================================
  1313. //
  1314. // ClientWritePkg
  1315. //
  1316. // This function defines the attributes (scalar values) for the client
  1317. // setup package.
  1318. //
  1319. // Parameters:
  1320. //      HANDLE hFolderPkg
  1321. //          The handle to the package folder for the client setup job.
  1322. //
  1323. //      TClientParams *pcp
  1324. //          Pointer to the "run setup command on client" parameters
  1325. //          that the user was asked to input at the beginning of the
  1326. //          program.
  1327. //
  1328. // Returns:
  1329. //      SMS_OK if everything went ok, otherwise the SDK status code.
  1330. //
  1331. // ====================================================================
  1332. BOOL ClientWritePkg( HANDLE hFolderPkg, TClientParams *pcp )
  1333. {
  1334.     SetScalarString(hFolderPkg, "Name", pcp->szPackageName);
  1335.     SetScalarString(hFolderPkg, "Comment", pcp->szPackageComment);
  1336.     SetScalarString(hFolderPkg, "Workstation root", pcp->szPackagePath);
  1337.     SetScalarDword(hFolderPkg,  "Share permissions", (DWORD) SHARE_PERMISSIONS);
  1338.  
  1339.     SMS_STATUS stat;
  1340.     stat = SmsCommitFolder(hFolderPkg);
  1341.     if (stat != SMS_OK) {
  1342.         DisplaySmsError("Failed to insert the package into the datasource", stat);
  1343.         return(FALSE);
  1344.     }
  1345.  
  1346.     return(TRUE);
  1347. }
  1348.  
  1349.  
  1350. // ====================================================================
  1351. //
  1352. // ClientWriteWcl
  1353. //
  1354. // This function defines the attributes (scalar values) for the
  1355. // workstation command line folder that is part of the client setup
  1356. // package.
  1357. //
  1358. // Parameters:
  1359. //      HANDLE hFolderWcl
  1360. //          The handle to the workstation command line folder for the
  1361. //          client setup job.
  1362. //
  1363. //      TClientParams *pcp
  1364. //          Pointer to the "run setup command on client" parameters
  1365. //          that the user was asked to input at the beginning of the
  1366. //          program.
  1367. //
  1368. // Returns:
  1369. //      SMS_OK if everything went ok, otherwise the SDK status code.
  1370. //
  1371. // ====================================================================
  1372. BOOL ClientWriteWcl( HANDLE hFolderWCL, TClientParams *pcp )
  1373. {
  1374.  
  1375.     SetScalarString(hFolderWCL, "Name",      pcp->szWclName);
  1376.     SetScalarString(hFolderWCL, "Command",   pcp->szWclCommand);
  1377.     SetScalarDword( hFolderWCL, "Flags",     0);
  1378.     SetScalarDword( hFolderWCL, "Platforms", pcp->dwPlatforms);
  1379.  
  1380.  
  1381.     SMS_STATUS stat;
  1382.     stat = SmsLinkFolder(hFolderWCL);
  1383.     if (stat != SMS_OK) {
  1384.         DisplaySmsError("Failed to link the WCL folder into the hierarchy", stat);
  1385.         return( FALSE );
  1386.     }
  1387.  
  1388.     stat = SmsCommitFolder(hFolderWCL);
  1389.     if ((stat != SMS_OK) && (stat != SMS_PARENT_NEEDS_COMMIT)) {
  1390.         DisplaySmsError("Failed to insert the WCL folder into the package", stat);
  1391.         return( FALSE );
  1392.     }
  1393.  
  1394.  
  1395.  
  1396.     // Note WCL folders are not actually inserted into the
  1397.     // datasource until a commit is also done on the parent
  1398.     // package folder.
  1399.     //=====================================================
  1400.  
  1401.     return( TRUE );
  1402. }
  1403.  
  1404.  
  1405.  
  1406.  
  1407.  
  1408.  
  1409. // ====================================================================
  1410. //
  1411. // ClientPkgCreate
  1412. //
  1413. // This function defines creates an SMS package for the client setup
  1414. // program.
  1415. //
  1416. // Parameters:
  1417. //      HANDLE hConnect
  1418. //          The datasource connection handle.
  1419. //
  1420. //      TClientParams *pcp
  1421. //          Pointer to the "run setup command on client" parameters
  1422. //          that the user was asked to input at the beginning of the
  1423. //          program.
  1424. //
  1425. //      char *pszPackageID
  1426. //          Pointer to the buffer where the package folder ID string
  1427. //          will be returned.
  1428. //
  1429. //      DWORD cchPackageID
  1430. //          The size of the package ID buffer.
  1431. //
  1432. //      char *pszWclID
  1433. //          Pointer to the buffer where the workstation command line
  1434. //          folder ID will be returned.
  1435. //
  1436. //      DWORD cchWclID
  1437. //          The size of the workstation command line ID buffer.
  1438. //
  1439. // Returns:
  1440. //      SMS_OK if everything went ok, otherwise the SMS SDK status
  1441. //      code.
  1442. //      The package ID and the WCL IDs are returned in their respective
  1443. //      buffers.
  1444. //
  1445. // ====================================================================
  1446. SMS_STATUS ClientPkgCreate( HANDLE hConnect,
  1447.                             TClientParams *pcp,
  1448.                             char *pszPackageID,
  1449.                             DWORD cchPackageID,
  1450.                             char *pszWclID,
  1451.                             DWORD cchWclID )
  1452. {
  1453.     SMS_STATUS stat;
  1454.     HANDLE hContainer;
  1455.  
  1456.     // First open the package container.  If we fail to open it,
  1457.     // display an error message and give up.
  1458.     //=========================================================
  1459.     stat = SmsOpenContainer( C_PACKAGE, hConnect, &hContainer );
  1460.     if (stat != SMS_OK) {
  1461.         DisplaySmsError("Failed to open the package container", stat);
  1462.         return( stat );
  1463.     }
  1464.  
  1465.     // Now create a new package folder.
  1466.     //=================================
  1467.     HANDLE hFolderPkg;
  1468.     stat = SmsCreateFolder( hContainer, F_PACKAGE, "Dummy", &hFolderPkg );
  1469.     if (stat != SMS_OK) {
  1470.         DisplaySmsError("Failed to create package folder for setup command", stat);
  1471.         SmsCloseContainer(hContainer);
  1472.         return(stat);
  1473.     }
  1474.  
  1475.  
  1476.     HANDLE hFolderWCL;
  1477.     stat = SmsCreateFolder(hFolderPkg, F_WCL, "Dummy", &hFolderWCL);
  1478.     if (stat != SMS_OK) {
  1479.         DisplaySmsError("Failed to create WCL folder for setup command", stat);
  1480.         SmsCloseContainer(hContainer);
  1481.         return(stat);
  1482.     }
  1483.  
  1484.  
  1485.     // At this point we have created both the WCL and the package folder
  1486.     // and now we define their attributes.  Note that the WCL attributes
  1487.     // are defined first because the call to SmsCommitFolder for the WCL
  1488.     // must precede the call to SmsCommitFolder for the package.  This is
  1489.     // because the WCL is part of the package and the package can't be
  1490.     // modified after a commit is done on it.
  1491.     //==================================================================
  1492.     ClientWriteWcl(hFolderWCL, pcp);
  1493.     ClientWritePkg(hFolderPkg, pcp);
  1494.  
  1495.  
  1496.  
  1497.     // We now get the identification strings for the package and the WCL.
  1498.     // This is done here because the WCL key is not defined until the
  1499.     // package it is contained in has been committed.
  1500.     //==================================================================
  1501.     GetScalarString(hFolderPkg, "Key", pszPackageID, cchPackageID);
  1502.     GetScalarString(hFolderWCL, "Name", pszWclID, cchWclID);
  1503.  
  1504.     stat = SmsCloseFolder(hFolderWCL);
  1505.     if (stat != SMS_OK) {
  1506.         DisplaySmsError("Failed to close the WCL folder", stat);
  1507.     }
  1508.  
  1509.  
  1510.     stat = SmsCloseFolder(hFolderPkg);
  1511.     if (stat != SMS_OK) {
  1512.         DisplaySmsError("Failed to close the package folder", stat);
  1513.     }
  1514.  
  1515.     stat = SmsCloseContainer(hContainer);
  1516.     if (stat != SMS_OK) {
  1517.         DisplaySmsError("Failed to close the package container", stat);
  1518.     }
  1519.  
  1520.     return( stat );
  1521. }
  1522.  
  1523.  
  1524. // ====================================================================
  1525. //
  1526. // ClientWriteJob
  1527. //
  1528. // This function defines the values of the job folder, links the folder
  1529. // into the folder hierarchy, and finally inserts the folder into the
  1530. // datasource.
  1531. //
  1532. // Parameters:
  1533. //      HANDLE hFolderJob
  1534. //          The job folder's handle.
  1535. //
  1536. //      TClientParams *pcp
  1537. //          Pointer to the "run command on client" parameters
  1538. //          that the user was asked to input at the beginning of the
  1539. //          program.
  1540. //
  1541. //      char *pszPackageID
  1542. //          Pointer to the package folder ID string.
  1543. //
  1544. //      char *pszWclID
  1545. //          Pointer to the workstation command line folder ID.
  1546. //
  1547. // Returns:
  1548. //   SMS_OK if everything went OK, otherwise the SMS SDK status code.
  1549. //
  1550. // ====================================================================
  1551. SMS_STATUS ClientWriteJob(  HANDLE hFolderJob,
  1552.                             TClientParams *pcp,
  1553.                             char *pszPackageID,
  1554.                             char *pszWCLID)
  1555. {
  1556.     // Submit the job immediately. To do this we set the job
  1557.     // submission time to the current time.
  1558.     //======================================================
  1559.     time_t timeJob;
  1560.     time( &timeJob );
  1561.  
  1562.     SetScalarString(hFolderJob, "Job comment",          "This is an SDK sample job");
  1563.     SetScalarTime(  hFolderJob, "Activate time",        timeJob);
  1564.     SetScalarDword( hFolderJob, "Priority",             JOBPRI_LOW);
  1565.     SetScalarDword( hFolderJob, "Repeat mode",          JOBRPT_NEVER);
  1566.     SetScalarDword( hFolderJob, "Cancel mode",          JOBCANCEL_DONT_CANCEL);
  1567.     SetScalarString(hFolderJob, "Package ID",           pszPackageID);
  1568.     SetScalarString(hFolderJob, "WCL name",             pcp->szWclName);
  1569.     SetScalarString(hFolderJob, "Machine path",         "*|*|*");
  1570.     SetScalarTime(  hFolderJob, "Offer time",           timeJob);
  1571.     SetScalarTime(  hFolderJob, "Mandatory time",       timeJob);
  1572.     SetScalarDword( hFolderJob, "Use mandatory time",   0);
  1573.     SetScalarDword( hFolderJob, "Force over slow link", 0);
  1574.     SetScalarDword( hFolderJob, "Use expire time",      0);
  1575.     SetScalarDword( hFolderJob, "Job target",           WKSTAJOB_TGT_MACHPATH);
  1576.     SetScalarDword( hFolderJob, "Limit to sites",       JOBTGT_SITE);
  1577.     SetScalarDword( hFolderJob, "Include subsites",     JOBTGT_INCLUDESUBSITES);
  1578.     SetScalarString(hFolderJob, "Site limit name",      pcp->szSiteName);
  1579.     SetScalarDword( hFolderJob, "Run workstation command",  TRUE);
  1580.  
  1581.  
  1582.     // At this point, the job folder exists in memory.  Now
  1583.     // we must insert the folder into the data source.  We do
  1584.     // this by calling SmsCommitFolder.
  1585.     //=========================================================
  1586.     SMS_STATUS stat;
  1587.     stat = SmsLinkFolder(hFolderJob);
  1588.     if (stat != SMS_OK) {
  1589.         DisplaySmsError("SmsLinkFolder(hFolderJob) failed", stat);
  1590.         return(stat);
  1591.     }
  1592.  
  1593.     stat = SmsCommitFolder(hFolderJob);
  1594.     if (stat != SMS_OK) {
  1595.         DisplaySmsError("Failed to insert the job into the datasource", stat);
  1596.         return(stat);
  1597.     }
  1598.  
  1599.     return( SMS_OK );
  1600. }
  1601.  
  1602.  
  1603.  
  1604.  
  1605. // ====================================================================
  1606. //
  1607. // ClientJobCreate
  1608. //
  1609. // This function creates an SMS job to run a command on the client
  1610. // workstation.   The name of the network share path is passed
  1611. // as a parameter to the client setup program.
  1612. //
  1613. // Parameters:
  1614. //      HANDLE hConnect
  1615. //          The datasource connection handle.
  1616. //
  1617. //      TClientParams *pcp
  1618. //          Pointer to the "run command on client" parameters
  1619. //          that the user was asked to input at the beginning of the
  1620. //          program.
  1621. //
  1622. //      char *pszPackageID
  1623. //          Pointer to the package folder ID string.
  1624. //
  1625. //      char *pszWclID
  1626. //          Pointer to the workstation command line folder ID.
  1627. //
  1628. // Returns:
  1629. //      SMS_OK if everything went OK, otherwise the SMS SDK status
  1630. //      code.
  1631. //
  1632. // ====================================================================
  1633. SMS_STATUS ClientJobCreate( HANDLE hConnect,
  1634.                             TClientParams *pcp,
  1635.                             char *pszPackageID,
  1636.                             char *pszWCLID)
  1637. {
  1638.  
  1639.     SMS_STATUS stat;
  1640.  
  1641.     HANDLE hContainerJob;
  1642.     stat = SmsOpenContainer( C_JOB, hConnect, &hContainerJob );
  1643.     if (stat != SMS_OK) {
  1644.         DisplaySmsError("Failed to open job container", stat);
  1645.         return( stat );
  1646.     }
  1647.  
  1648.     HANDLE hFolderJob;
  1649.     stat = SmsCreateFolder( hContainerJob, F_INSTALLJOB, "Dummy", &hFolderJob );
  1650.     if (stat == SMS_OK) {
  1651.         ClientWriteJob(hFolderJob, pcp, pszPackageID, pszWCLID);
  1652.  
  1653.         stat = SmsCloseFolder(hFolderJob);
  1654.         if (stat != SMS_OK) {
  1655.             DisplaySmsError("Failed to close job folder", stat);
  1656.         }
  1657.  
  1658.     }
  1659.     else {
  1660.         DisplaySmsError("Failed to create the job folder", stat);
  1661.     }
  1662.  
  1663.     stat = SmsCloseContainer(hContainerJob);
  1664.     if (stat != SMS_OK) {
  1665.         DisplaySmsError("Failed to close the job container", stat);
  1666.     }
  1667.     return stat;
  1668. }
  1669.  
  1670.  
  1671. // ====================================================================
  1672. //
  1673. // ClientDoRunCommand
  1674. //
  1675. // This function submits a run command on workstation job.
  1676. //
  1677. //
  1678. // Parameters:
  1679. //      HANDLE hConnect
  1680. //          The datasource connection handle.
  1681. //
  1682. //      TClientParams *pcp
  1683. //          Pointer to the "client" parameters that the user was asked to
  1684. //          input at the beginning of the program.
  1685. //
  1686. // Returns:  Nothing.
  1687. //
  1688. // ====================================================================
  1689. void ClientDoRunCommand( HANDLE hConnect, TClientParams *pcp )
  1690. {
  1691.     char szPackageID[CCH_MAXSTRING];
  1692.     char szWclID[CCH_MAXSTRING];
  1693.  
  1694.     SMS_STATUS stat;
  1695.     stat = ClientPkgCreate(hConnect,
  1696.                            pcp,
  1697.                            szPackageID, sizeof(szPackageID),
  1698.                            szWclID, sizeof(szWclID));
  1699.     if (stat != SMS_OK) {
  1700.         DisplaySmsError("Could not create client package", stat);
  1701.         return;
  1702.     }
  1703.  
  1704.     stat =  ClientJobCreate(hConnect, pcp, szPackageID, szWclID);
  1705.     if (stat != SMS_OK) {
  1706.         DisplaySmsError("Could not create client job", stat);
  1707.     }
  1708. }
  1709.  
  1710.  
  1711.  
  1712. // ====================================================================
  1713. //
  1714. // GetSiteName
  1715. //
  1716. // This function query's the user to select the SMS site that will be
  1717. // used in this sample
  1718. //
  1719. // Parameters:
  1720. //      HANDLE hConnect
  1721. //          The datasource connection handle.
  1722. //
  1723. //      char *pszSiteName
  1724. //          Pointer to the buffer where the site name will be returned.
  1725. //
  1726. // Returns:  Nothing.
  1727. //
  1728. // ====================================================================
  1729. void GetSiteName( HANDLE hConnect, char *pszSiteName )
  1730. {
  1731.     *pszSiteName = '\0';
  1732.  
  1733.  
  1734.     HANDLE hContainerSite;
  1735.     SMS_STATUS stat;
  1736.  
  1737.     stat = SmsOpenContainer( C_SITE, hConnect, &hContainerSite );
  1738.     if (stat != SMS_OK) {
  1739.         DisplaySmsError("Failed to open site container", stat);
  1740.         return;
  1741.     }
  1742.  
  1743.  
  1744.     stat = SmsPopulate(hContainerSite, POP_SYNC, NULL);
  1745.     if (stat != SMS_OK) {
  1746.         DisplaySmsError("Failed to populate site container", stat);
  1747.         return;
  1748.     }
  1749.  
  1750.  
  1751.     HANDLE ahFolderSite[C_MAXSITES];
  1752.     HANDLE hFolderSite;
  1753.     int ctFolders = 0;
  1754.     int iFolder;
  1755.  
  1756.  
  1757.     // Get the folder handle for each folder in the site container.  Also
  1758.     // count the folders so that we know how many we have.
  1759.     //===================================================================
  1760.     while(SmsGetNextFolder(hContainerSite, F_SITE, &hFolderSite) == SMS_OK) {
  1761.         ahFolderSite[ctFolders] = hFolderSite;
  1762.         ++ctFolders;
  1763.     }
  1764.  
  1765.  
  1766.  
  1767.     // Ask the user to select one of the sites.  After the user
  1768.     // select's a site, copy its name to pszSiteName.
  1769.     //=========================================================
  1770.     char szValue[CCH_MAXSTRING];
  1771.     if (ctFolders > 0) {
  1772.         printf("******************************************\n");
  1773.         printf("* Select a site from the following list. *\n");
  1774.         printf("******************************************\n");
  1775.         printf("\n");
  1776.  
  1777.  
  1778.         for(iFolder=0; iFolder < ctFolders; ++iFolder) {
  1779.             GetScalarString(ahFolderSite[iFolder], "Site name", szValue, sizeof(szValue));
  1780.             printf("[%d]. %s\n", iFolder + 1, szValue);
  1781.         }
  1782.         printf("\n");
  1783.  
  1784.  
  1785.         InputString("Enter site number", szValue);
  1786.         printf("\n");
  1787.         sscanf(szValue, "%d", &iFolder);
  1788.  
  1789.         if (iFolder > 0 && iFolder <= ctFolders) {
  1790.             GetScalarString(ahFolderSite[iFolder-1], "Site name", szValue, sizeof(szValue));
  1791.             strcpy(pszSiteName, szValue);
  1792.         }
  1793.     }
  1794.  
  1795.     // Close all of the site folders that we opened via SmsGetNextFolder.
  1796.     //===================================================================
  1797.     for (iFolder = 0; iFolder < ctFolders; ++iFolder) {
  1798.         SmsCloseFolder(ahFolderSite[iFolder]);
  1799.     }
  1800.  
  1801. }
  1802.  
  1803.  
  1804. // ====================================================================
  1805. //
  1806. // GetJobType
  1807. //
  1808. // This function query's the user to select the type of SMS job he or
  1809. // she would like to create.
  1810. //
  1811. // Parameters: None.
  1812. //
  1813. // Returns.  A status code indicating the job type.
  1814. //      CMD_RUN_COMMAND = Run command on workstation job.
  1815. //      CMD_SHARE_PACKAGE = Share package on server job.
  1816. //      CMD_QUIT = Exit without creating a job.
  1817. //
  1818. // ====================================================================
  1819. int GetJobType()
  1820. {
  1821.     printf("***************************************\n");
  1822.     printf("* Select the job type to create.      *\n");
  1823.     printf("***************************************\n");
  1824.     printf("1. Run command on workstation.\n");
  1825.     printf("2. Share package on server.\n");
  1826.     printf("3. Quit.\n");
  1827.     printf("\n");
  1828.  
  1829.     char szReply[CCH_MAXSTRING];
  1830.     InputString("Enter the job type", szReply);
  1831.     printf("\n");
  1832.  
  1833.     int iType = 0;
  1834.     sscanf(szReply, "%d", &iType);
  1835.     switch(iType) {
  1836.     case 1:
  1837.         return(CMD_RUN_COMMAND);
  1838.     case 2:
  1839.         return(CMD_SHARE_PACKAGE);
  1840.     default:
  1841.         return(CMD_QUIT);
  1842.     }
  1843. }
  1844.  
  1845.  
  1846.  
  1847.  
  1848. // ********************************************************************
  1849. //      Helper functions.
  1850. // ********************************************************************
  1851.  
  1852.  
  1853.  
  1854.  
  1855. // ====================================================================
  1856. //
  1857. // DidRequestHelp
  1858. //
  1859. // Check the program's arguments to see if the user asked for
  1860. // the help screen to be displayed.
  1861. //
  1862. // Parameters:
  1863. //      int argc
  1864. //          The argc value from main(argc, argv)
  1865. //
  1866. //      char** argv
  1867. //          The argv value from main(argc, argv)
  1868. //
  1869. // Returns:
  1870. //      TRUE if command line parameters included a request
  1871. //      for help to be displayed.
  1872. //
  1873. // ====================================================================
  1874. BOOL DidRequestHelp(int argc, char** argv)
  1875. {
  1876.     if (argc == 2  && (strcmp(argv[1], "-help") == 0)) {
  1877.         return(TRUE);
  1878.     }
  1879.     else {
  1880.         return(FALSE);
  1881.     }
  1882. }
  1883.  
  1884.  
  1885.  
  1886.  
  1887. // ====================================================================
  1888. //
  1889. // DisplayHelp
  1890. //
  1891. // This function displays the samples help screen.
  1892. //
  1893. // Parameters:
  1894. //      None
  1895. //
  1896. // Returns:
  1897. //      Nothing.
  1898. //
  1899. // ====================================================================
  1900. void DisplayHelp()
  1901. {
  1902.     printf("\n\n");
  1903.     printf("***********************************************************\n");
  1904.     printf("* srvinst.exe:                                            *\n");
  1905.     printf("*                                                         *\n");
  1906.     printf("* SMS API Example: Creation of jobs.                      *\n");
  1907.     printf("*                                                         *\n");
  1908.     printf("* This sample program demonstrates how the SMS SDK can    *\n");
  1909.     printf("* be used to create a \"share package on server\" job or a  *\n");
  1910.     printf("* \"run command on workstation\" job.                       *\n");
  1911.     printf("*                                                         *\n");
  1912.     printf("* Prior to running this program, you must first share the *\n");
  1913.     printf("* directory where the source files are for the package.   *\n");
  1914.     printf("*                                                         *\n");
  1915.     printf("* Syntax:                                                 *\n");
  1916.     printf("*     srvinst.exe [-help]                                 *\n");
  1917.     printf("*                                                         *\n");
  1918.     printf("* Switches:                                               *\n");
  1919.     printf("*     -help       Display this help message.              *\n");
  1920.     printf("*                                                         *\n");
  1921.     printf("***********************************************************\n");
  1922.     printf("\n");
  1923. }
  1924.  
  1925.  
  1926.  
  1927. // ====================================================================
  1928. //
  1929. // DisplayGreeting
  1930. //
  1931. // Display the initial greeting banner.
  1932. //
  1933. // Parameters:
  1934. //     None.
  1935. //
  1936. // Returns:
  1937. //     Nothing.
  1938. //
  1939. // ====================================================================
  1940. void DisplayGreeting()
  1941. {
  1942.     // For this sample, the greeting is identical to the help screen.
  1943.     //===============================================================
  1944.     DisplayHelp();
  1945. }
  1946.  
  1947.  
  1948.  
  1949. /* EOF: srvinst.cpp */
  1950.  
  1951.