summaryrefslogblamecommitdiffstats
path: root/private/net/examples/netsvc.c
blob: 3322b0852f6f3993f12963896b8fabfa957687d7 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424







































































































































































































































































































































































































































                                                                                
/*
   NETSVC.C -- a sample program demonstrating NetService API functions.

   This program requires that you have admin privilege on the specified
   server.

   usage:  netsvc [-s \\server] [-v servicename] [-l level]

   where:  \\server    = Name of the server. A servername must be preceded
                         by two backslashes (\\).
           servicename = Name of the service.
           level       = Level of detail requested.

   API                   Used to...
   =================     ================================================
   NetServiceInstall     Install the specified service
   NetServiceControl     Check progress of installation and uninstall the
                         specified service
   NetServiceEnum        List services and their status
   NetServiceGetInfo     Show one service and its status

   This code sample is provided for demonstration purposes only.
   Microsoft makes no warranty, either express or implied,
   as to its usability in any given situation.
*/

#define NOSERVICE          // Avoid <winsvc.h> vs. <lmsvc.h> conflicts.

#ifndef UNICODE
#define UNICODE            // Net APIs all require this.
#endif

#include    <windows.h>    // MS Windows base header files, Sleep(), etc.
#include    <lmcons.h>     // LanMan constants, etc.

#include    <lmapibuf.h>   // NetApiBufferFree().
#include    <lmerr.h>      // NERR_, ERROR_, and NO_ERROR equates.
#include    <lmsvc.h>

#include    <samples.h>    // SafeMalloc routines.
#include    <stdio.h>      // C run-time header files
#include    <stdlib.h>     // EXIT_FAILURE, EXIT_SUCCESS, _CRTAPI1.

#define A_SERVICE          SERVICE_TIMESOURCE  // Default servicename
#define DEFAULT_WAITTIME   150          // 0.1 seconds; 150 = 1.5 sec
#define MAX_POLLS          5            // Max. checks (5*1.5 sec = 20 sec)
#define WAIT_MULT          10

void InstallService (LPTSTR pszServer, LPTSTR pszService);
void ShowServices (DWORD dwLevel, LPVOID lpArrayStart, DWORD dwCount);
void UninstallService (LPTSTR pszServer, LPTSTR pszService);
void Usage(char * pszString);

int _CRTAPI1
main(
    int argc,
    char *argv[]
    )
{
   LPTSTR                 pszServer = TEXT("");  // Default to local machine
   LPTSTR                 pszService = A_SERVICE; // Servicename
   LPBYTE                 pbBuffer;        // Buffer for return data
   DWORD                  cEntriesRead;    // Count of entries in buffer
   DWORD                  cTotalEntries;   // Count available
   int                    iCount;          // Arg index and loop counter
   DWORD                  dwLevel = 0;     // Level of detail
   NET_API_STATUS         apiRet;          // API function return code
   LPSERVICE_INFO_0       pSvc0;           // Service info; level 0
   LPSERVICE_INFO_1       pSvc1;           // Service info; level 1
   LPSERVICE_INFO_2       pSvc2;           // Service info; level 2

   for (iCount = 1; iCount < argc; iCount++)
   {
      if ((*argv[iCount] == '-') || (*argv[iCount] == '/'))
      {
         switch (tolower(*(argv[iCount]+1))) // Process switches
         {
            case 's':                        // -s servername
               pszServer = SafeMallocWStrFromStr(argv[++iCount]);
               break;
            case 'v':                        // -v servicename
               pszService = SafeMallocWStrFromStr(argv[++iCount]);
               break;
            case 'l':                        // -l level
               dwLevel = (DWORD)(atoi(argv[++iCount]));
               break;
            default:
               Usage(argv[0]);
         }
      }
      else
         Usage(argv[0]);
   } // End for loop 

//======================================================================
//  NetServiceInstall and NetServiceControl
//
//  This API installs a service. Reassure the user that installation is
//  proceeding by using NetServiceControl.
//======================================================================

   InstallService(pszServer, pszService);

//====================================================================
//  NetServiceGetInfo
//
//  This API gets the status for one service.
//====================================================================

   apiRet = NetServiceGetInfo(pszServer, // Server name
                        pszService,      // Service name
                        dwLevel,         // Info level
                        & pbBuffer );    // Alloc buffer and set ptr
   printf("NetServiceGetInfo returned %lu\n", apiRet);
   if (apiRet == NERR_Success)
   {
      ShowServices( dwLevel, pbBuffer, 1 );
      NetApiBufferFree(pbBuffer);
   } // End if successful return

//====================================================================
//  NetServiceEnum
//
//  This API displays a list of installed services.
//====================================================================

   apiRet = NetServiceEnum(pszServer,    // Servername
                        dwLevel,         // Info level
                        & pbBuffer,      // Alloc buffer and set ptr
                        100,             // Prefered max size (arbitrary)
                        &cEntriesRead,   // Count of entries read
                        &cTotalEntries,  // Count of entries available
                        NULL);           // No resume handle

   pSvc0 = (LPSERVICE_INFO_0) pbBuffer;     // If dwLevel == 0
   pSvc1 = (LPSERVICE_INFO_1) pbBuffer;     // If dwLevel == 1
   pSvc2 = (LPSERVICE_INFO_2) pbBuffer;     // If dwLevel == 2

   printf("NetServiceEnum returned %lu\n", apiRet);
   if (apiRet == NERR_Success)
   {

      printf("Services installed");
      if ((pszServer == NULL) || (*pszServer == '\0'))
          printf(" on local server:\n");
      else
          printf(" on server %ws:\n", pszServer);

      ShowServices( dwLevel, pbBuffer, cEntriesRead );

      NetApiBufferFree(pbBuffer);
   } // End if successful return

//====================================================================
//  NetServiceControl
//
//  This API uninstalls the service.
//====================================================================

   UninstallService(pszServer, pszService);
   return (EXIT_SUCCESS);
}

//====================================================================
//  NetServiceInstall
//
//  This API installs the service. Reassure the user that installation
//  is proceeding by using NetServiceControl.
//====================================================================

void InstallService (LPTSTR pszServer, LPTSTR pszService)
{
   DWORD                 dwTimeElapsed = 0;
   DWORD                 dwOldCheck = 0;
   DWORD                 dwNewCheck = 0;
   DWORD                 dwWaitTime;
   NET_API_STATUS        apiRet;
   LPSERVICE_INFO_2      lpStatBuf;

   apiRet = NetServiceInstall(pszServer, // Servername
                  pszService,            // Servicename 
                  (DWORD) 0,             // Zero command-line args
                  NULL,                  // No ptr to command-line args
                  (LPBYTE *) (LPVOID) &lpStatBuf);  // Level 2 ret buff (alloc)
   printf("NetServiceInstall %ws returned %lu\n", pszService, apiRet);
   switch (apiRet)
   {
      case NERR_Success:
         (void) NetApiBufferFree( lpStatBuf );
         break;
      /*
       * NERR_BadServiceName and ERROR_FILE_NOT_FOUND can be caused
       * by the absence of the service entry in the LANMAN.INI file
       * or when the entry points to a directory that does not contain
       * the executable service program.
       */
      case NERR_BadServiceName:
      case ERROR_FILE_NOT_FOUND:
         printf("\n%ws could not be installed\n", pszService);
         return;

      default:
         return;
   }

   do  // Poll every few seconds.
   {
      apiRet = NetServiceControl(pszServer,      // Servername
                pszService,                      // Servicename
                SERVICE_CTRL_INTERROGATE,        // Opcode
                0,                               // Service-specific args
                (LPBYTE *) (LPVOID) &lpStatBuf); // Alloc return buffer

      switch (lpStatBuf->svci2_status & SERVICE_INSTALL_STATE)
      {
         case SERVICE_INSTALLED:
            printf ("\n%ws successfully installed\n", pszService);
            ShowServices (2, lpStatBuf, 1);
            (void) NetApiBufferFree( lpStatBuf );
            return;

         case SERVICE_INSTALL_PENDING:
            printf(".");
            break;

         default:
            printf ("\nService %ws failed to install\n", pszService);
            printf ("NetServiceControl returned status %ld\n",
               (DWORD) (lpStatBuf->svci2_status & SERVICE_INSTALL_STATE));
            ShowServices (2, lpStatBuf, 1);
            break;
      }

      /*
       * Check the service timing hints. As long as the hints are being
       * changed, assume that the service is still alive.
       */
      if (lpStatBuf->svci2_code & SERVICE_CCP_QUERY_HINT)
      {
         dwNewCheck = (lpStatBuf->svci2_code & SERVICE_CCP_CHKPT_NUM);
         if (dwNewCheck != dwOldCheck)   // Hints are being changed
         {
            dwTimeElapsed = 0;
            dwOldCheck = dwNewCheck;
         }
      }

      // Get wait time from data structure.

      dwWaitTime = WAIT_MULT * ( ( lpStatBuf->svci2_code
                          &  SERVICE_IP_WAIT_TIME )
                          >> SERVICE_IP_WAITTIME_SHIFT);

      // Provide a default wait time if the service doesn't give one.

      if (dwWaitTime == 0)
         dwWaitTime = DEFAULT_WAITTIME;

      // If we've gone maximum amount of time without an update, fail.

      if (dwTimeElapsed >= (DWORD) (MAX_POLLS * dwWaitTime))
      {
         printf("\n%ws failed to install. ", pszService);
         printf("The service did not report an error.\n");
         break;
      }
      /*
       * Sleep() waits for the given number of milliseconds.
       * It's well-behaved (allows other things to run).
       */
      Sleep(dwWaitTime);
      dwTimeElapsed++;

   } while ((lpStatBuf->svci2_status & SERVICE_INSTALL_STATE)
              == SERVICE_INSTALL_PENDING );

   // Successful installation returns true from the switch statement.
   (void) NetApiBufferFree( lpStatBuf );
   return;
}

//====================================================================
//  ShowServices
//
//  This routine displays one or more service structures.
//====================================================================

void ShowServices (DWORD dwLevel, LPVOID lpArrayStart, DWORD dwCount)
{
   DWORD dwEntryNum;
   LPSERVICE_INFO_0       pSvc0;           // Service info; level 0
   LPSERVICE_INFO_1       pSvc1;           // Service info; level 1
   LPSERVICE_INFO_2       pSvc2;           // Service info; level 2

   pSvc0 = (LPSERVICE_INFO_0) lpArrayStart;     // If dwLevel == 0
   pSvc1 = (LPSERVICE_INFO_1) lpArrayStart;     // If dwLevel == 1
   pSvc2 = (LPSERVICE_INFO_2) lpArrayStart;     // If dwLevel == 2

   for (dwEntryNum = 0; dwEntryNum < dwCount; dwEntryNum++)
   {
      switch (dwLevel)
      {
         case 0:
            printf("   %ws\n", pSvc0->svci0_name);
            pSvc0++;
            break;
         case 1:
            printf("Service:  %ws\n", pSvc1->svci1_name);
            printf("   Status :  0x%lX\n", pSvc1->svci1_status);
            printf("   Code   :  0x%lX\n", pSvc1->svci1_code);
            pSvc1++;
            break;
         case 2:
            printf("Service:  %ws\n", pSvc2->svci2_name);
            printf("   Status :  0x%lX\n", pSvc2->svci2_status);
            printf("   Code   :  0x%lX\n", pSvc2->svci2_code);
            printf("   Text   :  %ws\n", pSvc2->svci2_text);
            printf("   SpecErr:  0x%lX\n", pSvc2->svci2_specific_error);
            printf("   DispNam:  %ws\n", pSvc2->svci2_display_name);
            pSvc2++;
            break;
         default:
            break;
      } // End switch
   } // End for loop

}

//====================================================================
//  NetServiceControl
//
//  This API uninstalls the service.
//====================================================================

void UninstallService (LPTSTR pszServer, LPTSTR pszService)
{
   DWORD                 dwElapsedTime = 0;
   NET_API_STATUS        apiRet;
   DWORD                 dwWaitTime;
   LPSERVICE_INFO_2      lpStatBuf;

   apiRet = NetServiceControl (pszServer,         // Servername
                  pszService,                     // Servicename
                  SERVICE_CTRL_UNINSTALL,         // Opcode
                  0,                              // Service-specific args
                  (LPBYTE *) (LPVOID) &lpStatBuf);  // Alloc return buffer
   printf("NetServiceControl(stop) %ws returned %lu\n", pszService, apiRet);
   if (apiRet == NERR_Success) {
      ShowServices (2, lpStatBuf, 1);
      NetApiBufferFree(lpStatBuf);
   }

   do     // Poll every few seconds.
   {
      apiRet = NetServiceControl(pszServer,
                pszService,
                SERVICE_CTRL_INTERROGATE,
                0,
                (LPVOID) (LPBYTE) &lpStatBuf);
      if (apiRet != NERR_Success) {
         printf("NetServiceControl(query) %ws returned %lu\n",
                pszService, apiRet);
         return;
      }

      switch (lpStatBuf->svci2_status & SERVICE_INSTALL_STATE)
      {
         case SERVICE_UNINSTALLED:
            printf ("\nService %ws successfully stopped\n", pszService);
            ShowServices (2, lpStatBuf, 1);
            return;
         case SERVICE_UNINSTALL_PENDING:  // Keep waiting
            break;
         default:
            printf ("\nService %ws failed to stop\n", pszService);
            printf ("NetServiceControl returned status %ld\n",
                 (DWORD) (lpStatBuf->svci2_status & SERVICE_INSTALL_STATE));
            break;
      }

      // Get wait time from data structure.

      dwWaitTime = WAIT_MULT * ( ( lpStatBuf->svci2_code
                             &  SERVICE_IP_WAIT_TIME )
                             >> SERVICE_IP_WAITTIME_SHIFT);

      NetApiBufferFree(lpStatBuf);

      // Provide a default wait time if the service doesn't give one.

      if (dwWaitTime == 0)
         dwWaitTime = DEFAULT_WAITTIME;

      // If service is not stopped in after 20 polls, fail.
      if (dwElapsedTime >= (DWORD) (MAX_POLLS * dwWaitTime))
      {
         printf( "\n%ws failed to stop: ", pszService);
         printf(" The service did not report an error.\n");
         break;
      }

      printf (".");     // Display to let user know program is active.
      Sleep( dwWaitTime );
      dwElapsedTime++;

   } while ((lpStatBuf->svci2_status & SERVICE_INSTALL_STATE)
          == SERVICE_UNINSTALL_PENDING);

   // Successful installation returns from the switch statement.
   return;
}
//=================================================================
//  Usage
//
//  Display possible command-line switches for this example.
//=================================================================

void Usage(char * pszString)
{
   fprintf(stderr, "NetService API sample program: 32-bit, Unicode version.\n");
   fprintf(stderr, "Usage: %s [-s \\\\server] [-v servicename]", pszString);
   fprintf(stderr, " [-l level]\n");
   exit( EXIT_FAILURE );
}