home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / dbmsg / sql / ods / procsrv / service.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-03  |  12.7 KB  |  481 lines

  1. //
  2. // This program installs the PROCSRV.exe into the Service Control Manager.  It also
  3. // adds a service entry to the SQL Service Manager.
  4. // The service name "ProcSrv" will be added to the registry under the tree
  5. // "\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SQLServer\"
  6. //
  7. // Copyright 1994, Microsoft.
  8. //
  9.  
  10. #include <windows.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14.  
  15. #define PROCSRV             "ProcSrv"
  16. #define PROCSRV_KEY_PATH    "SOFTWARE\\Microsoft\\MSSQLServer\\ProcSrv\\"
  17. #define SQL_SM_KEY          "SOFTWARE\\Microsoft\\MSSQLServer\\SQL Service Manager\\"
  18.  
  19. #define NAMED_PIPE_DLL      "SSNMPN60"
  20. #define NAMED_PIPE_ADDRESS  "\\\\.\\pipe\\sql\\query"
  21. #define TCP_IP_DLL          "SSMSSO60"
  22. #define TCP_ADDRESS         "1433"
  23.  
  24. void AddToRegistry();
  25. void RemoveFromRegistry();
  26. BOOL DuplicateEntry();
  27. void RefreshStoplight();
  28.  
  29. void main( int argc, char ** argv )
  30. {
  31.     if( argc != 2 )
  32.         goto Usage;
  33.  
  34.     if( !stricmp("add", argv[1]) )
  35.                 AddToRegistry();
  36.         else if( !stricmp("remove", argv[1]) )
  37.                 RemoveFromRegistry();
  38.     else
  39.         goto Usage;
  40.  
  41.     RefreshStoplight();
  42.     return;
  43.  
  44. Usage:
  45.         printf( "Usage: service {add|remove}\n"
  46.                     "  where \"add\" adds ProcSrv and \"remove\" removes it\n" );
  47. }
  48.  
  49.  
  50. // **************************************************************************
  51. //
  52. //  FUNCTION: AddToRegistry()
  53. //
  54. //  PURPOSE:  Add ProcSrv to Registry and Service Control Manager
  55. //
  56. // **************************************************************************
  57.  
  58. void AddToRegistry()
  59. {
  60.     int    i;
  61.     HKEY   hKey;
  62.     HKEY   hKeySM;
  63.     DWORD  dwDisposition;
  64.     DWORD  dwSize = 0;
  65.     DWORD  dwSizeSM;
  66.     DWORD  dwType;
  67.     DWORD  dwPathLength;
  68.     char   szPath[1024];
  69.     char   szSMvalues[1024];
  70.     char   szSaveListenOn[1024];
  71.     char * szSaveListenOnPos = szSaveListenOn;
  72.  
  73.     SC_HANDLE hSCM;     // Handle to opened Service Control Manager
  74.     SC_LOCK   LockSCM;  // Lock of Service Control Manager
  75.     SC_HANDLE hSrvc;    // Handle to service
  76.  
  77.     // Check for existance of "ProcSrv" in registry
  78.     //
  79.     if( DuplicateEntry() )
  80.     {
  81.         printf( "Duplicate entry 'ProcSrv' found in Registry, remove 'ProcSrv' from Registry\n" );
  82.         return;
  83.     }
  84.  
  85.     // ======== Update SQL Service Manager info ===========
  86.     //
  87.     if( RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  88.                        SQL_SM_KEY,
  89.                        0,
  90.                        NULL,
  91.                        REG_OPTION_NON_VOLATILE,
  92.                        KEY_ALL_ACCESS,
  93.                        NULL,
  94.                        &hKeySM,
  95.                        &dwDisposition)
  96.     != ERROR_SUCCESS )
  97.         goto AddExit2;
  98.  
  99.     dwSizeSM = sizeof( szSMvalues );
  100.  
  101.     // Get list of SQL Service Manager entries
  102.     //
  103.     if( RegQueryValueEx(hKeySM,
  104.                         "Services",
  105.                         NULL,
  106.                         &dwType,
  107.                         szSMvalues,
  108.                         &dwSizeSM)
  109.     != ERROR_SUCCESS )
  110.     {
  111.         dwSizeSM = 1;
  112.         szSMvalues[0] = '\0';
  113.     }
  114.  
  115.     if( (dwSizeSM+strlen(PROCSRV)+1) < sizeof(szSMvalues) )
  116.     {
  117.         // Append new value to list of SQL Service Manager entries.
  118.         //
  119.         memcpy( (szSMvalues+dwSizeSM-1),
  120.                 PROCSRV,
  121.                 (strlen(PROCSRV)+1) );
  122.         dwSizeSM += strlen(PROCSRV);
  123.         szSMvalues[dwSizeSM] = '\0';
  124.         dwSizeSM++;
  125.     }
  126.  
  127.     // Note that we delay write of new values to Stoplight Registry entry.
  128.     // First well will try to update the Service Control Manager.
  129.  
  130.     // ==== Write entry to Service Control Manager ====
  131.     //
  132.     hSCM = OpenSCManager( NULL,
  133.                           "ServicesActive",
  134.                           SC_MANAGER_ALL_ACCESS );
  135.     if( hSCM == NULL )
  136.         goto AddExit4;
  137.  
  138.     i = 0;
  139.     while( TRUE )
  140.     {
  141.         LockSCM = LockServiceDatabase( hSCM );
  142.  
  143.         if( LockSCM != NULL )
  144.             break;
  145.  
  146.         if( i++ >= 5 )
  147.             goto AddExit3;  // Can't lock database
  148.  
  149.         Sleep( 1000 );  // sleep for a second
  150.     }
  151.  
  152.     // Get the path of this process.  We'll use it to constuct the path of the
  153.     // ProcSrv.exe
  154.     //
  155.     szPath[0] = '\0';
  156.     dwPathLength = GetModuleFileName( GetModuleHandle(NULL), szPath, sizeof(szPath) );
  157.  
  158.     // Stip off process name (i.e. "service.exe")
  159.     //
  160.     while( dwPathLength > 1 )
  161.     {
  162.         --dwPathLength;
  163.         if( szPath[dwPathLength] == '\\' || szPath[dwPathLength] == ':' )
  164.         {
  165.                 dwPathLength++;
  166.                 szPath[dwPathLength] = '\0';    // Null terminate after the back slash
  167.                 break;
  168.         }
  169.     }
  170.  
  171.     // Append "procsrv.exe" to path
  172.     //
  173.     strcat( szPath, PROCSRV );
  174.     strcat( szPath, ".exe" );
  175.  
  176.     // Let's create the service entry
  177.     //
  178.     hSrvc = CreateService( hSCM,
  179.                            PROCSRV,  // Service name to start
  180.                            PROCSRV,  // Display name
  181.                            SERVICE_ALL_ACCESS,
  182.                            SERVICE_WIN32_OWN_PROCESS,
  183.                            SERVICE_DEMAND_START,
  184.                            SERVICE_ERROR_NORMAL,
  185.                            szPath,
  186.                            NULL,
  187.                            NULL,
  188.                            NULL,
  189.                            NULL,
  190.                            NULL );
  191.     if( hSrvc == NULL )
  192.         goto AddExit3;
  193.  
  194.     CloseServiceHandle( hSrvc );
  195.     UnlockServiceDatabase( LockSCM );
  196.     CloseServiceHandle( hSCM );
  197.  
  198.     // Now we'll update Registry with new ProcSrv entry
  199.     //
  200.     if( RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  201.                        PROCSRV_KEY_PATH,
  202.                        0,
  203.                        NULL,
  204.                        REG_OPTION_NON_VOLATILE,
  205.                        KEY_ALL_ACCESS,
  206.                        NULL,
  207.                        &hKey,
  208.                        &dwDisposition)
  209.     != ERROR_SUCCESS )
  210.         goto AddExit2;
  211.  
  212.     // ==== Update ListenOn ====
  213.     //
  214.     strcpy( szSaveListenOnPos, NAMED_PIPE_DLL );
  215.     strcat( szSaveListenOnPos, "," );
  216.     strcat( szSaveListenOnPos, NAMED_PIPE_ADDRESS );
  217.  
  218.     dwSize += (strlen(szSaveListenOnPos) + 1);
  219.     szSaveListenOnPos = szSaveListenOn + dwSize;
  220.  
  221.     strcpy( szSaveListenOnPos, TCP_IP_DLL );
  222.     strcat( szSaveListenOnPos, "," );
  223.     strcat( szSaveListenOnPos, TCP_ADDRESS );
  224.  
  225.  
  226.     dwSize += (strlen(szSaveListenOnPos) + 1);
  227.     szSaveListenOnPos = szSaveListenOn + dwSize;
  228.  
  229.     szSaveListenOn[dwSize] = '\0';
  230.     dwSize++;
  231.  
  232.     if( RegSetValueEx(hKey,
  233.                       "ListenOn",
  234.                       0,
  235.                       REG_MULTI_SZ,
  236.                       szSaveListenOn,
  237.                       dwSize)
  238.     != ERROR_SUCCESS )
  239.         goto AddExit1;
  240.  
  241.     // ==== Complete the update of the SQL Service Manager info ============
  242.     // We do it here to avoid a duplicate entry if other registry updates
  243.     // fail.
  244.     //
  245.     if( RegSetValueEx(hKeySM,
  246.                       "Services",
  247.                       0,
  248.                       REG_MULTI_SZ,
  249.                       szSMvalues,
  250.                       dwSizeSM)
  251.     != ERROR_SUCCESS )
  252.     {
  253.         RegCloseKey( hKeySM );
  254.         goto AddExit1;
  255.     }
  256.  
  257.     RegFlushKey( hKeySM );
  258.     RegCloseKey( hKeySM );
  259.  
  260.     return;
  261.  
  262. AddExit1:
  263.     RegCloseKey( hKey );
  264.  
  265. AddExit2:
  266.     printf( "Unable to Update Registry\n" );
  267.     return;
  268.  
  269. AddExit3:
  270.     UnlockServiceDatabase( LockSCM );
  271.     CloseServiceHandle( hSCM );
  272.  
  273. AddExit4:
  274.     printf( "Unable to Update Service Control Manager\n" );
  275.     return;
  276. }
  277.  
  278.  
  279. // **************************************************************************
  280. //
  281. //  FUNCTION: RemoveFromRegistry()
  282. //
  283. //  PURPOSE:  Remove ProcSrv From Registry and Service Control Manager
  284. //
  285. // **************************************************************************
  286.  
  287. void RemoveFromRegistry()
  288. {
  289.     int    i;
  290.     HKEY   hKey;
  291.     DWORD  dwSizeSM;
  292.     DWORD  dwType;
  293.     char   szSMvalues[1024];
  294.     char * szSMvaluesPos;
  295.  
  296.     SC_HANDLE hSCM;     // Handle to opened Service Control Manager
  297.     SC_LOCK   LockSCM;  // Lock of Service Control Manager
  298.     SC_HANDLE hSrvc;    // Handle to service
  299.  
  300.     // Check for non-existance of "ProcSrv" in registry
  301.     //
  302.     if( !DuplicateEntry() )
  303.     {
  304.         printf( "'ProcSrv' not found in Registry\n" );
  305.         return;
  306.     }
  307.  
  308.     // =============== Remove 'ProcSrv' key from Registry =============
  309.     //
  310.     RegDeleteKey( HKEY_LOCAL_MACHINE, PROCSRV_KEY_PATH );
  311.  
  312.     // =============== Update SQL Service Manager info ================
  313.     //
  314.     if( RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  315.                      SQL_SM_KEY,
  316.                      0,
  317.                      KEY_ALL_ACCESS,
  318.                      &hKey)
  319.     != ERROR_SUCCESS )
  320.         goto RemoveExit2;
  321.  
  322.     dwSizeSM = sizeof( szSMvalues );
  323.  
  324.     // Get SQL Service Manager entries
  325.     //
  326.     if( RegQueryValueEx(hKey,
  327.                         "Services",
  328.                         NULL,
  329.                         &dwType,
  330.                         szSMvalues,
  331.                         &dwSizeSM)
  332.     != ERROR_SUCCESS )
  333.         goto RemoveExit1;       // No SQL Service Manager entries.
  334.  
  335.     szSMvaluesPos = szSMvalues;
  336.  
  337.     while( szSMvaluesPos < (szSMvalues + dwSizeSM) )
  338.     {
  339.         if( !stricmp(szSMvaluesPos, PROCSRV) )
  340.         {
  341.                 // Remove 'ProcSrv' from SQL Service Manager entries.
  342.                 //
  343.                 memcpy( szSMvaluesPos,
  344.                         szSMvaluesPos + sizeof(PROCSRV),
  345.                         ((szSMvalues + dwSizeSM) - (szSMvaluesPos + sizeof(PROCSRV))) );
  346.  
  347.             dwSizeSM -= sizeof( PROCSRV );
  348.                 break;
  349.         }
  350.  
  351.         // 'ProcSrv' entry not found, position to next entry.
  352.         //
  353.         szSMvaluesPos += (strlen( szSMvaluesPos ) + 1);
  354.     }
  355.  
  356.     // Write back out new list of SQL Service Manager entries.
  357.     //
  358.     if( RegSetValueEx(hKey,
  359.                       "Services",
  360.                       0,
  361.                       REG_MULTI_SZ,
  362.                       szSMvalues,
  363.                       dwSizeSM)
  364.     != ERROR_SUCCESS )
  365.     {
  366.         RegCloseKey( hKey );
  367.         goto RemoveExit1;
  368.     }
  369.  
  370.     RegFlushKey( hKey );
  371.     RegCloseKey( hKey );
  372.  
  373.     // ==== Remove entry from Service Control Manager ====
  374.     //
  375.     hSCM = OpenSCManager( NULL,
  376.                           "ServicesActive",
  377.                           SC_MANAGER_ALL_ACCESS );
  378.     if( hSCM == NULL )
  379.         goto RemoveExit4;
  380.  
  381.     i = 0;
  382.     while( TRUE )
  383.     {
  384.         LockSCM = LockServiceDatabase( hSCM );
  385.  
  386.         if( LockSCM != NULL )
  387.             break;
  388.  
  389.         if( i++ >= 5 )
  390.             goto RemoveExit3;   // Can't lock database
  391.  
  392.         Sleep( 1000 );  // sleep for a second
  393.     }
  394.  
  395.     // Let's remove the service entry
  396.     //
  397.     hSrvc = OpenService( hSCM,
  398.                          PROCSRV,       // Service name
  399.                          SERVICE_ALL_ACCESS );
  400.     if( hSrvc == NULL )
  401.         goto RemoveExit3;
  402.  
  403.     DeleteService( hSrvc );
  404.  
  405.     CloseServiceHandle( hSrvc );
  406.     UnlockServiceDatabase( LockSCM );
  407.     CloseServiceHandle( hSCM );
  408.  
  409.     return;
  410.  
  411. RemoveExit1:
  412.     RegCloseKey( hKey );
  413.  
  414. RemoveExit2:
  415.     printf( "Unable to Update Registry\n" );
  416.     return;
  417.  
  418. RemoveExit3:
  419.     UnlockServiceDatabase( LockSCM );
  420.     CloseServiceHandle( hSCM );
  421.  
  422. RemoveExit4:
  423.     printf( "Unable to Update Service Control Manager\n" );
  424.     return;
  425. }
  426.  
  427.  
  428. // **************************************************************************
  429. //
  430. //  FUNCTION: DuplicateEntry
  431. //
  432. //  PURPOSE:  Determines if a duplicate "ProcSrv" exist in
  433. //            the registry.
  434. //
  435. //  RETURNS:
  436. //          TRUE if name exist, else
  437. //          FALSE if name not found.
  438. //
  439. //
  440. // **************************************************************************
  441.  
  442. BOOL DuplicateEntry()
  443. {
  444.     HKEY     hKey;
  445.  
  446.     if( RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  447.                      PROCSRV_KEY_PATH,
  448.                      0,
  449.                      KEY_ENUMERATE_SUB_KEYS,
  450.                      &hKey)
  451.     != ERROR_SUCCESS )
  452.         return FALSE;
  453.  
  454.     RegCloseKey( hKey );
  455.     return TRUE;
  456. }
  457.  
  458.  
  459. // **************************************************************************
  460. //
  461. //  FUNCTION: RefreshStoplight()
  462. //
  463. //  PURPOSE:  This routine causes the SQL Service Manager to refresh its
  464. //            list.
  465. //
  466. // **************************************************************************
  467.  
  468. void RefreshStoplight()
  469. {
  470.     HANDLE hEvent;
  471.  
  472.     hEvent = OpenEvent( EVENT_MODIFY_STATE,
  473.                         TRUE,
  474.                         "MICROSOFTSQLServiceControlManagerRefresh" );
  475.     if( hEvent )
  476.     {
  477.         SetEvent( hEvent );
  478.         CloseHandle( hEvent );
  479.     }
  480. }
  481.