win32-service 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/extconf.rb DELETED
@@ -1,18 +0,0 @@
1
- require 'mkmf'
2
- require 'fileutils'
3
-
4
- FileUtils.cp('lib/win32/service.c', '.')
5
- FileUtils.cp('lib/win32/service.h', '.')
6
-
7
- have_func('RegisterServiceCtrlHandlerEx') # For future use
8
-
9
- bool1 = have_func('EnumServicesStatusEx')
10
- bool2 = have_func('QueryServiceStatusEx')
11
-
12
- # This is used by the test suite to help setup a couple tests
13
- File.open('test/tmp.yml', 'a+'){ |f|
14
- f.puts 'HAVE_ENUMSERVICESTATUSEX: #{bool1}'
15
- f.puts 'HAVE_QUERYSERVICESTATUSEX: #{bool2}'
16
- }
17
-
18
- create_makefile('win32/service')
@@ -1,2131 +0,0 @@
1
- #include "ruby.h"
2
- #include <windows.h>
3
- #include <string.h>
4
- #include <stdlib.h>
5
- #include <malloc.h>
6
- #include <tchar.h>
7
- #include "service.h"
8
-
9
- #ifndef UNICODE
10
- #define UNICODE
11
- #endif
12
-
13
- static VALUE cServiceError;
14
- static VALUE cDaemonError;
15
- static VALUE v_service_struct, v_service_status_struct;
16
-
17
- static HANDLE hStartEvent;
18
- static HANDLE hStopEvent;
19
- static HANDLE hStopCompletedEvent;
20
- static SERVICE_STATUS_HANDLE ssh;
21
- static DWORD dwServiceState;
22
- static TCHAR error[1024];
23
-
24
- static VALUE EventHookHash;
25
- static VALUE thread_group;
26
- static int cAdd;
27
- static int cList;
28
- static int cSize;
29
-
30
- CRITICAL_SECTION csControlCode;
31
- // I happen to know from looking in the header file
32
- // that 0 is not a valid service control code
33
- // so we will use it, the value does not matter
34
- // as long as it will never show up in ServiceCtrl
35
- // - Patrick Hurley
36
- #define IDLE_CONTROL_CODE 0
37
- static int waiting_control_code = IDLE_CONTROL_CODE;
38
-
39
- static VALUE service_close(VALUE);
40
- void WINAPI Service_Main(DWORD dwArgc, LPTSTR *lpszArgv);
41
- void WINAPI Service_Ctrl(DWORD dwCtrlCode);
42
- void ErrorStopService();
43
- void SetTheServiceStatus(DWORD dwCurrentState,DWORD dwWin32ExitCode,
44
- DWORD dwCheckPoint, DWORD dwWaitHint);
45
-
46
- // Called by the service control manager after the call to
47
- // StartServiceCtrlDispatcher.
48
- void WINAPI Service_Main(DWORD dwArgc, LPTSTR *lpszArgv)
49
- {
50
- int i;
51
-
52
- // Obtain the name of the service.
53
- LPTSTR lpszServiceName = lpszArgv[0];
54
-
55
- // Register the service ctrl handler.
56
- ssh = RegisterServiceCtrlHandler(lpszServiceName,
57
- (LPHANDLER_FUNCTION)Service_Ctrl);
58
-
59
- if(ssh == (SERVICE_STATUS_HANDLE)0){
60
- ErrorStopService();
61
- rb_raise(cDaemonError,"RegisterServiceCtrlHandler failed");
62
- }
63
-
64
- // wait for sevice initialization
65
- for(i=1;TRUE;i++)
66
- {
67
- if(WaitForSingleObject(hStartEvent, 1000) == WAIT_OBJECT_0)
68
- break;
69
-
70
- SetTheServiceStatus(SERVICE_START_PENDING, 0, i, 1000);
71
- }
72
-
73
- // The service has started.
74
- SetTheServiceStatus(SERVICE_RUNNING, NO_ERROR, 0, 0);
75
-
76
- // Main loop for the service.
77
- while(WaitForSingleObject(hStopEvent, 1000) != WAIT_OBJECT_0)
78
- {
79
- }
80
-
81
- // Stop the service.
82
- SetTheServiceStatus(SERVICE_STOPPED, NO_ERROR, 0, 0);
83
- }
84
-
85
- VALUE Service_Event_Dispatch(VALUE val)
86
- {
87
- VALUE func,self;
88
- VALUE result = Qnil;
89
-
90
- if(val!=Qnil) {
91
- self = RARRAY(val)->ptr[0];
92
- func = NUM2INT(RARRAY(val)->ptr[1]);
93
-
94
- result = rb_funcall(self,func,0);
95
- }
96
-
97
- return result;
98
- }
99
-
100
- VALUE Ruby_Service_Ctrl()
101
- {
102
- while (WaitForSingleObject(hStopEvent,0) == WAIT_TIMEOUT)
103
- {
104
- __try
105
- {
106
- EnterCriticalSection(&csControlCode);
107
-
108
- // Check to see if anything interesting has been signaled
109
- if (waiting_control_code != IDLE_CONTROL_CODE)
110
- {
111
- // if there is a code, create a ruby thread to deal with it
112
- // this might be over engineering the solution, but I don't
113
- // want to block Service_Ctrl longer than necessary and the
114
- // critical section will block it.
115
- VALUE val = rb_hash_aref(EventHookHash, INT2NUM(waiting_control_code));
116
- if(val!=Qnil) {
117
- VALUE thread = rb_thread_create(Service_Event_Dispatch, (void*) val);
118
- rb_funcall(thread_group, cAdd, 1, thread);
119
- }
120
-
121
- // some seriously ugly flow control going on in here
122
- if (waiting_control_code == SERVICE_CONTROL_STOP)
123
- break;
124
-
125
- waiting_control_code = IDLE_CONTROL_CODE;
126
- }
127
- }
128
- __finally
129
- {
130
- LeaveCriticalSection(&csControlCode);
131
- }
132
-
133
- // This is an ugly polling loop, be as polite as possible
134
- rb_thread_polling();
135
- }
136
-
137
- for (;;)
138
- {
139
- VALUE list = rb_funcall(thread_group, cList, 0);
140
- VALUE size = rb_funcall(list, cSize, 0);
141
- if (NUM2INT(size) == 0)
142
- break;
143
-
144
- // This is another ugly polling loop, be as polite as possible
145
- rb_thread_polling();
146
- }
147
- SetEvent(hStopCompletedEvent);
148
-
149
- return Qnil;
150
- }
151
-
152
- // Handles control signals from the service control manager.
153
- void WINAPI Service_Ctrl(DWORD dwCtrlCode)
154
- {
155
- DWORD dwState = SERVICE_RUNNING;
156
-
157
- // hard to image this code ever failing, so we probably
158
- // don't need the __try/__finally wrapper
159
- __try
160
- {
161
- EnterCriticalSection(&csControlCode);
162
- waiting_control_code = dwCtrlCode;
163
- }
164
- __finally
165
- {
166
- LeaveCriticalSection(&csControlCode);
167
- }
168
-
169
- switch(dwCtrlCode)
170
- {
171
- case SERVICE_CONTROL_STOP:
172
- dwState = SERVICE_STOP_PENDING;
173
- break;
174
-
175
- case SERVICE_CONTROL_SHUTDOWN:
176
- dwState = SERVICE_STOP_PENDING;
177
- break;
178
-
179
- case SERVICE_CONTROL_PAUSE:
180
- dwState = SERVICE_PAUSED;
181
- break;
182
-
183
- case SERVICE_CONTROL_CONTINUE:
184
- dwState = SERVICE_RUNNING;
185
- break;
186
-
187
- case SERVICE_CONTROL_INTERROGATE:
188
- break;
189
-
190
- default:
191
- break;
192
- }
193
-
194
- // Set the status of the service.
195
- SetTheServiceStatus(dwState, NO_ERROR, 0, 0);
196
-
197
- // Tell service_main thread to stop.
198
- if ((dwCtrlCode == SERVICE_CONTROL_STOP) ||
199
- (dwCtrlCode == SERVICE_CONTROL_SHUTDOWN))
200
- {
201
- // how long should we give ruby to clean up?
202
- // right now we give it forever :-)
203
- while (WaitForSingleObject(hStopCompletedEvent, 500) == WAIT_TIMEOUT)
204
- {
205
- SetTheServiceStatus(dwState, NO_ERROR, 0, 0);
206
- }
207
-
208
- if (!SetEvent(hStopEvent))
209
- ErrorStopService();
210
- // Raise an error here?
211
- }
212
- }
213
-
214
- // Wraps SetServiceStatus.
215
- void SetTheServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode,
216
- DWORD dwCheckPoint, DWORD dwWaitHint)
217
- {
218
- SERVICE_STATUS ss; // Current status of the service.
219
-
220
- // Disable control requests until the service is started.
221
- if (dwCurrentState == SERVICE_START_PENDING){
222
- ss.dwControlsAccepted = 0;
223
- }
224
- else{
225
- ss.dwControlsAccepted =
226
- SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN|
227
- SERVICE_ACCEPT_PAUSE_CONTINUE|SERVICE_ACCEPT_SHUTDOWN;
228
- }
229
-
230
- // Initialize ss structure.
231
- ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
232
- ss.dwServiceSpecificExitCode = 0;
233
- ss.dwCurrentState = dwCurrentState;
234
- ss.dwWin32ExitCode = dwWin32ExitCode;
235
- ss.dwCheckPoint = dwCheckPoint;
236
- ss.dwWaitHint = dwWaitHint;
237
-
238
- dwServiceState = dwCurrentState;
239
-
240
- // Send status of the service to the Service Controller.
241
- if(!SetServiceStatus(ssh, &ss)){
242
- ErrorStopService();
243
- }
244
- }
245
-
246
- // Handle API errors or other problems by ending the service
247
- void ErrorStopService(){
248
-
249
- // If you have threads running, tell them to stop. Something went
250
- // wrong, and you need to stop them so you can inform the SCM.
251
- SetEvent(hStopEvent);
252
-
253
- // Stop the service.
254
- SetTheServiceStatus(SERVICE_STOPPED, GetLastError(), 0, 0);
255
- }
256
-
257
- DWORD WINAPI ThreadProc(LPVOID lpParameter){
258
- SERVICE_TABLE_ENTRY ste[] =
259
- {{TEXT(""),(LPSERVICE_MAIN_FUNCTION)Service_Main}, {NULL, NULL}};
260
-
261
- if (!StartServiceCtrlDispatcher(ste)){
262
- ErrorStopService();
263
- strcpy(error,ErrorDescription(GetLastError()));
264
- // Very questionable here, we should generate an event
265
- // and be polling in a green thread for the event, but
266
- // this really should not happen so here we go
267
- rb_raise(cDaemonError,error);
268
- }
269
-
270
- return 0;
271
- }
272
-
273
- static VALUE daemon_allocate(VALUE klass){
274
- EventHookHash = rb_hash_new();
275
-
276
- thread_group = rb_class_new_instance(0, 0,
277
- rb_const_get(rb_cObject, rb_intern("ThreadGroup")));
278
-
279
- return Data_Wrap_Struct(klass, 0, 0, 0);
280
- }
281
-
282
- /*
283
- * This is the method that actually puts your code into a loop and allows it
284
- * to run as a service. The code that is actually run while in the mainloop
285
- * is what you defined in your own Daemon#service_main method.
286
- */
287
- static VALUE
288
- daemon_mainloop(VALUE self)
289
- {
290
- DWORD ThreadId;
291
- HANDLE hThread;
292
-
293
- dwServiceState = 0;
294
-
295
- // Save a couple symbols
296
- cAdd = rb_intern("add");
297
- cList = rb_intern("list");
298
- cSize = rb_intern("size");
299
-
300
- // Event hooks
301
- if(rb_respond_to(self,rb_intern("service_stop"))){
302
- rb_hash_aset(EventHookHash,INT2NUM(SERVICE_CONTROL_STOP),
303
- rb_ary_new3(2,self,INT2NUM(rb_intern("service_stop"))));
304
- }
305
-
306
- if(rb_respond_to(self,rb_intern("service_pause"))){
307
- rb_hash_aset(EventHookHash,INT2NUM(SERVICE_CONTROL_PAUSE),
308
- rb_ary_new3(2,self,INT2NUM(rb_intern("service_pause"))));
309
- }
310
-
311
- if(rb_respond_to(self,rb_intern("service_resume"))){
312
- rb_hash_aset(EventHookHash,INT2NUM(SERVICE_CONTROL_CONTINUE),
313
- rb_ary_new3(2,self,INT2NUM(rb_intern("service_resume"))));
314
- }
315
-
316
- if(rb_respond_to(self,rb_intern("service_interrogate"))){
317
- rb_hash_aset(EventHookHash,INT2NUM(SERVICE_CONTROL_INTERROGATE),
318
- rb_ary_new3(2,self,INT2NUM(rb_intern("service_interrogate"))));
319
- }
320
-
321
- if(rb_respond_to(self,rb_intern("service_shutdown"))){
322
- rb_hash_aset(EventHookHash,INT2NUM(SERVICE_CONTROL_SHUTDOWN),
323
- rb_ary_new3(2,self,INT2NUM(rb_intern("service_shutdown"))));
324
- }
325
-
326
- #ifdef SERVICE_CONTROL_PARAMCHANGE
327
- if(rb_respond_to(self,rb_intern("service_paramchange"))){
328
- rb_hash_aset(EventHookHash,INT2NUM(SERVICE_CONTROL_PARAMCHANGE),
329
- rb_ary_new3(2,self,INT2NUM(rb_intern("service_paramchange"))));
330
- }
331
- #endif
332
-
333
- #ifdef SERVICE_CONTROL_NETBINDADD
334
- if(rb_respond_to(self,rb_intern("service_netbindadd"))){
335
- rb_hash_aset(EventHookHash,INT2NUM(SERVICE_CONTROL_NETBINDADD),
336
- rb_ary_new3(2,self,INT2NUM(rb_intern("service_netbindadd"))));
337
- }
338
- #endif
339
-
340
- #ifdef SERVICE_CONTROL_NETBINDREMOVE
341
- if(rb_respond_to(self,rb_intern("service_netbindremove"))){
342
- rb_hash_aset(EventHookHash,INT2NUM(SERVICE_CONTROL_NETBINDREMOVE),
343
- rb_ary_new3(2,self,INT2NUM(rb_intern("service_netbindremove"))));
344
- }
345
- #endif
346
-
347
- #ifdef SERVICE_CONTROL_NETBINDENABLE
348
- if(rb_respond_to(self,rb_intern("service_netbindenable"))){
349
- rb_hash_aset(EventHookHash,INT2NUM(SERVICE_CONTROL_NETBINDENABLE),
350
- rb_ary_new3(2,self,INT2NUM(rb_intern("service_netbindenable"))));
351
- }
352
- #endif
353
-
354
- #ifdef SERVICE_CONTROL_NETBINDDISABLE
355
- if(rb_respond_to(self,rb_intern("service_netbinddisable"))){
356
- rb_hash_aset(EventHookHash,INT2NUM(SERVICE_CONTROL_NETBINDDISABLE),
357
- rb_ary_new3(2,self,INT2NUM(rb_intern("service_netbinddisable"))));
358
- }
359
- #endif
360
-
361
- // Create the event to signal the service to start.
362
- hStartEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
363
- if(hStartEvent == NULL){
364
- strcpy(error,ErrorDescription(GetLastError()));
365
- ErrorStopService();
366
- rb_raise(cDaemonError,error);
367
- }
368
-
369
- // Create the event to signal the service to stop.
370
- hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
371
- if(hStopEvent == NULL){
372
- strcpy(error,ErrorDescription(GetLastError()));
373
- ErrorStopService();
374
- rb_raise(cDaemonError,error);
375
- }
376
-
377
- // Create the event to signal the service that stop has completed
378
- hStopCompletedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
379
- if(hStopCompletedEvent == NULL){
380
- strcpy(error,ErrorDescription(GetLastError()));
381
- ErrorStopService();
382
- rb_raise(cDaemonError,error);
383
- }
384
-
385
- // Create the green thread to poll for Service_Ctrl events
386
- rb_thread_create(Ruby_Service_Ctrl, 0);
387
-
388
- // Create Thread for service main
389
- hThread = CreateThread(NULL,0,ThreadProc,0,0,&ThreadId);
390
- if(hThread == INVALID_HANDLE_VALUE){
391
- strcpy(error,ErrorDescription(GetLastError()));
392
- ErrorStopService();
393
- rb_raise(cDaemonError,error);
394
- }
395
-
396
- if(rb_respond_to(self,rb_intern("service_init"))){
397
- rb_funcall(self,rb_intern("service_init"),0);
398
- }
399
-
400
- SetEvent(hStartEvent);
401
-
402
- // Call service_main method
403
- if(rb_respond_to(self,rb_intern("service_main"))){
404
- rb_funcall(self,rb_intern("service_main"),0);
405
- }
406
-
407
- while(WaitForSingleObject(hStopEvent, 1000) != WAIT_OBJECT_0)
408
- {
409
- }
410
-
411
- // Close the event handle and the thread handle.
412
- if(!CloseHandle(hStopEvent)){
413
- strcpy(error,ErrorDescription(GetLastError()));
414
- ErrorStopService();
415
- rb_raise(cDaemonError,error);
416
- }
417
-
418
- // Wait for Thread service main
419
- WaitForSingleObject(hThread, INFINITE);
420
-
421
- return self;
422
- }
423
-
424
- /*
425
- * Returns the state of the service (as an constant integer) which can be any
426
- * of the service status constants, e.g. RUNNING, PAUSED, etc.
427
- *
428
- * This method is typically used within your service_main method to setup the
429
- * loop. For example:
430
- *
431
- * class MyDaemon < Daemon
432
- * def service_main
433
- * while state == RUNNING || state == PAUSED || state == IDLE
434
- * # Your main loop here
435
- * end
436
- * end
437
- * end
438
- *
439
- * See the Daemon#running? method for an abstraction of the above code.
440
- */
441
- static VALUE daemon_state(VALUE self){
442
- return UINT2NUM(dwServiceState);
443
- }
444
-
445
- /*
446
- * Returns whether or not the service is in a running state, i.e. the service
447
- * status is either RUNNING, PAUSED or IDLE.
448
- *
449
- * This is typically used within your service_main method to setup the main
450
- * loop. For example:
451
- *
452
- * class MyDaemon < Daemon
453
- * def service_main
454
- * while running?
455
- * # Your main loop here
456
- * end
457
- * end
458
- * end
459
- */
460
- static VALUE daemon_is_running(VALUE self){
461
- VALUE v_bool = Qfalse;
462
- if(
463
- (dwServiceState == SERVICE_RUNNING) ||
464
- (dwServiceState == SERVICE_PAUSED) ||
465
- (dwServiceState == 0)
466
- ){
467
- v_bool = Qtrue;
468
- }
469
-
470
- return v_bool;
471
- }
472
-
473
- static VALUE service_allocate(VALUE klass){
474
- SvcStruct* ptr = malloc(sizeof(SvcStruct));
475
- return Data_Wrap_Struct(klass,0,service_free,ptr);
476
- }
477
-
478
- /* call-seq:
479
- * Service.new(host=nil, desired_access=nil)
480
- * Service.new(host=nil, desired_access=nil){ |svc| ... }
481
- *
482
- * Creates and returns a new Win32::Service handle on +host+ with the
483
- * +desired_access+. If no host is specified, your local machine is
484
- * used. If no desired access is specified, then
485
- * Service::MANAGER_CREATE_SERVICE is used.
486
- *
487
- * If a block is provided then the object is yielded back to the block and
488
- * automatically closed at the end of the block.
489
- */
490
- static VALUE service_init(int argc, VALUE *argv, VALUE self){
491
- VALUE v_machine_name, v_desired_access;
492
- TCHAR* lpMachineName;
493
- DWORD dwDesiredAccess;
494
- SvcStruct* ptr;
495
-
496
- Data_Get_Struct(self, SvcStruct, ptr);
497
-
498
- rb_scan_args(argc, argv, "02", &v_machine_name, &v_desired_access);
499
-
500
- if(NIL_P(v_machine_name)){
501
- lpMachineName = NULL;
502
- }
503
- else{
504
- SafeStringValue(v_machine_name);
505
- lpMachineName = TEXT(StringValuePtr(v_machine_name));
506
- }
507
-
508
- if(NIL_P(v_desired_access))
509
- dwDesiredAccess = SC_MANAGER_CREATE_SERVICE;
510
- else
511
- dwDesiredAccess = NUM2INT(v_desired_access);
512
-
513
- ptr->hSCManager = OpenSCManager(
514
- lpMachineName,
515
- NULL,
516
- dwDesiredAccess
517
- );
518
-
519
- if(!ptr->hSCManager)
520
- rb_raise(cServiceError,ErrorDescription(GetLastError()));
521
-
522
- rb_iv_set(self, "@machine_name", v_machine_name);
523
- rb_iv_set(self, "@desired_access", v_desired_access);
524
- rb_iv_set(self, "@service_type",
525
- INT2FIX(SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS));
526
-
527
- rb_iv_set(self, "@start_type", INT2FIX(SERVICE_DEMAND_START));
528
- rb_iv_set(self, "@error_control", INT2FIX(SERVICE_ERROR_NORMAL));
529
-
530
- if(rb_block_given_p())
531
- rb_ensure(rb_yield, self, service_close, self);
532
-
533
- return self;
534
- }
535
-
536
- /*
537
- * call-seq:
538
- * Service#close
539
- *
540
- * Closes the service handle. This is the polite way to do things, although
541
- * the service handle should automatically be closed when it goes out of
542
- * scope.
543
- */
544
- static VALUE service_close(VALUE self){
545
- SvcStruct* ptr;
546
- int rv;
547
-
548
- Data_Get_Struct(self, SvcStruct, ptr);
549
-
550
- rv = CloseServiceHandle(ptr->hSCManager);
551
-
552
- if(ptr->hSCManager){
553
- if(0 == rv){
554
- rb_raise(cServiceError, ErrorDescription(GetLastError()));
555
- }
556
- }
557
-
558
- return self;
559
- }
560
-
561
- /*
562
- * call-seq:
563
- * Service#configure_service{ |service| ... }
564
- *
565
- * Configures the service object. Valid methods for the service object are
566
- * as follows:
567
- *
568
- * * desired_access=
569
- * * service_name=
570
- * * display_name=
571
- * * service_type=
572
- * * start_type=
573
- * * error_control=
574
- * * tag_id=
575
- * * binary_path_name=
576
- * * load_order_group=
577
- * * start_name=
578
- * * password=
579
- * * dependencies=
580
- * * service_description=
581
- *
582
- * See the docs for individual instance methods for more details.
583
- */
584
- static VALUE service_configure(VALUE self){
585
- SvcStruct* ptr;
586
- SC_HANDLE hSCService;
587
- DWORD dwServiceType, dwStartType, dwErrorControl;
588
- TCHAR* lpServiceName;
589
- TCHAR* lpDisplayName;
590
- TCHAR* lpBinaryPathName;
591
- TCHAR* lpLoadOrderGroup;
592
- TCHAR* lpServiceStartName;
593
- TCHAR* lpPassword;
594
- TCHAR* lpDependencies;
595
- int rv;
596
-
597
- Data_Get_Struct(self,SvcStruct,ptr);
598
-
599
- rb_yield(self); /* block is mandatory */
600
-
601
- if(NIL_P(rb_iv_get(self, "@service_name"))){
602
- rb_raise(cServiceError, "No service name specified");
603
- }
604
- else{
605
- VALUE v_tmp = rb_iv_get(self, "@service_name");
606
- lpServiceName = TEXT(StringValuePtr(v_tmp));
607
- }
608
-
609
- hSCService = OpenService(
610
- ptr->hSCManager,
611
- lpServiceName,
612
- SERVICE_CHANGE_CONFIG
613
- );
614
-
615
- if(!hSCService)
616
- rb_raise(cServiceError, ErrorDescription(GetLastError()));
617
-
618
- if(NIL_P(rb_iv_get(self, "@service_type")))
619
- dwServiceType = SERVICE_NO_CHANGE;
620
- else
621
- dwServiceType = NUM2INT(rb_iv_get(self, "@service_type"));
622
-
623
- if(NIL_P(rb_iv_get(self, "@start_type")))
624
- dwStartType = SERVICE_NO_CHANGE;
625
- else
626
- dwStartType = NUM2INT(rb_iv_get(self, "@start_type"));
627
-
628
- if(NIL_P(rb_iv_get(self, "@error_control")))
629
- dwErrorControl = SERVICE_NO_CHANGE;
630
- else
631
- dwErrorControl = NUM2INT(rb_iv_get(self, "@error_control"));
632
-
633
- if(NIL_P(rb_iv_get(self, "@binary_path_name"))){
634
- lpBinaryPathName = NULL;
635
- }
636
- else{
637
- VALUE v_tmp = rb_iv_get(self, "@binary_path_name");
638
- lpBinaryPathName = TEXT(StringValuePtr(v_tmp));
639
- }
640
-
641
- if(NIL_P(rb_iv_get(self, "@load_order_group"))){
642
- lpLoadOrderGroup = NULL;
643
- }
644
- else{
645
- VALUE v_tmp = rb_iv_get(self, "@load_order_group");
646
- lpLoadOrderGroup = TEXT(StringValuePtr(v_tmp));
647
- }
648
-
649
- /* There are 3 possibilities for dependencies - Some, none, or unchanged:
650
- *
651
- * null => don't change
652
- * empty array => no dependencies (deletes any existing dependencies)
653
- * array => sets dependencies (deletes any existing dependencies)
654
- */
655
- if(NIL_P(rb_iv_get(self, "@dependencies"))){
656
- lpDependencies = NULL;
657
- }
658
- else{
659
- int i,size=1;
660
- TCHAR* ptr;
661
- VALUE rbDepArray = rb_iv_get(self, "@dependencies");
662
-
663
- if(0 == RARRAY(rbDepArray)->len){
664
- lpDependencies = TEXT("");
665
- }
666
- else{
667
- for(i = 0; i< RARRAY(rbDepArray)->len; i++)
668
- {
669
- size += strlen(StringValueCStr(RARRAY(rbDepArray)->ptr[i]))+1;
670
- }
671
- lpDependencies = malloc(size);
672
- memset(lpDependencies, 0x00, size);
673
- ptr = lpDependencies;
674
- for(i = 0; i < RARRAY(rbDepArray)->len; i++){
675
- VALUE v_tmp = rb_ary_entry(rbDepArray,i);
676
- TCHAR* string = TEXT(StringValuePtr(v_tmp));
677
- memcpy(ptr,string,strlen(string));
678
- ptr+=strlen(string)+1;
679
- }
680
- }
681
- }
682
-
683
- if(NIL_P(rb_iv_get(self, "@start_name"))){
684
- lpServiceStartName = NULL;
685
- }
686
- else{
687
- VALUE v_tmp = rb_iv_get(self, "@start_name");
688
- lpServiceStartName = TEXT(StringValuePtr(v_tmp));
689
- }
690
-
691
- if(NIL_P(rb_iv_get(self, "@password"))){
692
- lpPassword = NULL;
693
- }
694
- else{
695
- VALUE v_tmp = rb_iv_get(self, "@password");
696
- lpPassword = TEXT(StringValuePtr(v_tmp));
697
- }
698
-
699
- if(NIL_P(rb_iv_get(self, "@display_name"))){
700
- lpDisplayName = NULL;
701
- }
702
- else{
703
- VALUE v_tmp = rb_iv_get(self, "@display_name");
704
- lpDisplayName = TEXT(StringValuePtr(v_tmp));
705
- }
706
-
707
- rv = ChangeServiceConfig(
708
- hSCService,
709
- dwServiceType,
710
- dwStartType,
711
- dwErrorControl,
712
- lpBinaryPathName,
713
- lpLoadOrderGroup,
714
- NULL, // TagID
715
- lpDependencies,
716
- lpServiceStartName,
717
- lpPassword,
718
- lpDisplayName
719
- );
720
-
721
- if(lpDependencies)
722
- free(lpDependencies);
723
-
724
- if(0 == rv){
725
- strcpy(error,ErrorDescription(GetLastError()));
726
- CloseServiceHandle(hSCService);
727
- rb_raise(cServiceError,error);
728
- }
729
-
730
- if(!NIL_P(rb_iv_get(self, "@service_description"))){
731
- SERVICE_DESCRIPTION servDesc;
732
- VALUE v_desc = rb_iv_get(self, "@service_description");
733
-
734
- servDesc.lpDescription = TEXT(StringValuePtr(v_desc));
735
-
736
- if(!ChangeServiceConfig2(
737
- hSCService,
738
- SERVICE_CONFIG_DESCRIPTION,
739
- &servDesc
740
- )){
741
- rb_raise(cServiceError,ErrorDescription(GetLastError()));
742
- }
743
- }
744
-
745
- CloseServiceHandle(hSCService);
746
-
747
- return self;
748
- }
749
-
750
- /*
751
- * call-seq:
752
- * Service#create_service{ |service| ... }
753
- *
754
- * Creates the specified service. In order for this to work, the
755
- * 'service_name' and 'binary_path_name' attributes must be defined
756
- * or ServiceError will be raised.
757
-
758
- * See the Service#configure_service method for a list of valid methods to
759
- * pass to the service object. See the individual methods for more
760
- * information, including default values.
761
- */
762
- static VALUE service_create(VALUE self){
763
- VALUE v_tmp;
764
- SvcStruct* ptr;
765
- SC_HANDLE hSCService;
766
- DWORD dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl;
767
- TCHAR* lpMachineName;
768
- TCHAR* lpServiceName;
769
- TCHAR* lpDisplayName;
770
- TCHAR* lpBinaryPathName;
771
- TCHAR* lpLoadOrderGroup;
772
- TCHAR* lpServiceStartName;
773
- TCHAR* lpPassword;
774
- TCHAR* lpDependencies;
775
-
776
- if(rb_block_given_p())
777
- rb_yield(self);
778
-
779
- Data_Get_Struct(self, SvcStruct, ptr);
780
-
781
- // The service name and exe name must be set to create a service
782
- if(NIL_P(rb_iv_get(self, "@service_name")))
783
- rb_raise(cServiceError, "Service Name must be defined");
784
-
785
- if(NIL_P(rb_iv_get(self, "@binary_path_name")))
786
- rb_raise(cServiceError, "Executable Name must be defined");
787
-
788
- // If the display name is not set, set it to the same as the service name
789
- if(NIL_P(rb_iv_get(self, "@display_name")))
790
- rb_iv_set(self,"@display_name", rb_iv_get(self,"@service_name"));
791
-
792
- v_tmp = rb_iv_get(self, "@service_name");
793
- lpServiceName = TEXT(StringValuePtr(v_tmp));
794
-
795
- v_tmp = rb_iv_get(self, "@display_name");
796
- lpDisplayName = TEXT(StringValuePtr(v_tmp));
797
-
798
- v_tmp = rb_iv_get(self, "@binary_path_name");
799
- lpBinaryPathName = TEXT(StringValuePtr(v_tmp));
800
-
801
- if(NIL_P(rb_iv_get(self, "@machine_name"))){
802
- lpMachineName = NULL;
803
- }
804
- else{
805
- v_tmp = rb_iv_get(self, "@machine_name");
806
- lpMachineName = TEXT(StringValuePtr(v_tmp));
807
- }
808
-
809
- if(NIL_P(rb_iv_get(self, "@load_order_group"))){
810
- lpLoadOrderGroup = NULL;
811
- }
812
- else{
813
- v_tmp = rb_iv_get(self, "@load_order_group");
814
- lpLoadOrderGroup = TEXT(StringValuePtr(v_tmp));
815
- }
816
-
817
- if(NIL_P(rb_iv_get(self, "@start_name"))){
818
- lpServiceStartName = NULL;
819
- }
820
- else{
821
- v_tmp = rb_iv_get(self,"@start_name");
822
- lpServiceStartName =
823
- TEXT(StringValuePtr(v_tmp));
824
- }
825
-
826
- if(NIL_P(rb_iv_get(self, "@password"))){
827
- lpPassword = NULL;
828
- }
829
- else{
830
- v_tmp = rb_iv_get(self,"@password");
831
- lpPassword = TEXT(StringValuePtr(v_tmp));
832
- }
833
-
834
- // There are 3 possibilities for dependencies - Some, none, or unchanged
835
- // null = don't change
836
- // empty array = no dependencies (deletes any existing dependencies)
837
- // array = sets dependencies (deletes any existing dependencies)
838
- if(NIL_P(rb_iv_get(self, "@dependencies"))){
839
- lpDependencies = NULL;
840
- }
841
- else{
842
- int i,size=1;
843
- TCHAR* ptr;
844
- VALUE rbDepArray = rb_iv_get(self, "@dependencies");
845
-
846
- if(0 == RARRAY(rbDepArray)->len){
847
- lpDependencies = TEXT("");
848
- }
849
- else{
850
- for(i = 0; i< RARRAY(rbDepArray)->len; i++)
851
- {
852
- size += strlen(StringValueCStr(RARRAY(rbDepArray)->ptr[i]))+1;
853
- }
854
- lpDependencies = malloc(size);
855
- memset(lpDependencies,0x00,size);
856
- ptr = lpDependencies;
857
- for(i = 0; i < RARRAY(rbDepArray)->len; i++){
858
- VALUE v_tmp = rb_ary_entry(rbDepArray,i);
859
- TCHAR* string = TEXT(StringValuePtr(v_tmp));
860
- memcpy(ptr,string,strlen(string));
861
- ptr+=strlen(string)+1;
862
- }
863
- }
864
- }
865
-
866
- if(NIL_P(rb_iv_get(self, "@desired_access"))){
867
- dwDesiredAccess = SERVICE_ALL_ACCESS;
868
- }
869
- else{
870
- dwDesiredAccess = NUM2INT(rb_iv_get(self, "@desired_access"));
871
- }
872
-
873
- if(NIL_P(rb_iv_get(self,"@service_type"))){
874
- dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;
875
- }
876
- else{
877
- dwServiceType = NUM2INT(rb_iv_get(self, "@service_type"));
878
- }
879
-
880
- if(NIL_P(rb_iv_get(self,"@start_type"))){
881
- dwStartType = SERVICE_DEMAND_START;
882
- }
883
- else{
884
- dwStartType = NUM2INT(rb_iv_get(self, "@start_type"));
885
- }
886
-
887
- if(NIL_P(rb_iv_get(self, "@error_control"))){
888
- dwErrorControl = SERVICE_ERROR_NORMAL;
889
- }
890
- else{
891
- dwErrorControl = NUM2INT(rb_iv_get(self, "@error_control"));
892
- }
893
-
894
- // Add support for tag id and dependencies
895
- hSCService = CreateService(
896
- ptr->hSCManager,
897
- lpServiceName,
898
- lpDisplayName,
899
- dwDesiredAccess,
900
- dwServiceType,
901
- dwStartType,
902
- dwErrorControl,
903
- lpBinaryPathName,
904
- lpLoadOrderGroup,
905
- NULL, // Tag ID
906
- lpDependencies,
907
- lpServiceStartName,
908
- lpPassword
909
- );
910
-
911
- if(lpDependencies)
912
- free(lpDependencies);
913
-
914
- if(!hSCService)
915
- rb_raise(cServiceError, ErrorDescription(GetLastError()));
916
-
917
- // Set the description after the fact if specified, since we can't set it
918
- // in CreateService().
919
- if(!NIL_P(rb_iv_get(self, "@service_description"))){
920
- SERVICE_DESCRIPTION servDesc;
921
- VALUE v_desc = rb_iv_get(self, "@service_description");
922
-
923
- servDesc.lpDescription = TEXT(StringValuePtr(v_desc));
924
-
925
- if(!ChangeServiceConfig2(
926
- hSCService,
927
- SERVICE_CONFIG_DESCRIPTION,
928
- &servDesc
929
- )){
930
- rb_raise(cServiceError,ErrorDescription(GetLastError()));
931
- }
932
- }
933
-
934
- CloseServiceHandle(hSCService);
935
- return self;
936
- }
937
-
938
- // CLASS METHODS
939
-
940
- /*
941
- * call-seq:
942
- * Service.delete(name, host=localhost)
943
- *
944
- * Deletes the service +name+ from +host+, or the localhost if none is
945
- * provided.
946
- */
947
- static VALUE service_delete(int argc, VALUE *argv, VALUE klass)
948
- {
949
- SC_HANDLE hSCManager, hSCService;
950
- TCHAR* lpMachineName;
951
- TCHAR* lpServiceName;
952
- VALUE v_service_name, v_machine_name;
953
-
954
- rb_scan_args(argc, argv, "11", &v_service_name, &v_machine_name);
955
-
956
- SafeStringValue(v_service_name);
957
- lpServiceName = TEXT(StringValuePtr(v_service_name));
958
-
959
- if(NIL_P(v_machine_name)){
960
- lpMachineName = NULL;
961
- }
962
- else{
963
- SafeStringValue(v_machine_name);
964
- lpMachineName = TEXT(StringValuePtr(v_machine_name));
965
- }
966
-
967
- hSCManager = OpenSCManager(
968
- lpMachineName,
969
- NULL,
970
- SC_MANAGER_CREATE_SERVICE
971
- );
972
-
973
- if(!hSCManager)
974
- rb_raise(cServiceError,ErrorDescription(GetLastError()));
975
-
976
- hSCService = OpenService(
977
- hSCManager,
978
- lpServiceName,
979
- DELETE
980
- );
981
-
982
- if(!hSCService){
983
- strcpy(error,ErrorDescription(GetLastError()));
984
- CloseServiceHandle(hSCManager);
985
- rb_raise(cServiceError,error);
986
- }
987
-
988
- if(!DeleteService(hSCService)){
989
- strcpy(error,ErrorDescription(GetLastError()));
990
- CloseServiceHandle(hSCService);
991
- CloseServiceHandle(hSCManager);
992
- rb_raise(cServiceError,error);
993
- }
994
-
995
- CloseServiceHandle(hSCService);
996
- CloseServiceHandle(hSCManager);
997
-
998
- return klass;
999
- }
1000
-
1001
- /*
1002
- * call-seq:
1003
- * Service.services(host=nil, group=nil){ |struct| ... }
1004
- *
1005
- * Enumerates over a list of service types on host, or the local
1006
- * machine if no host is specified, yielding a Win32Service struct for each
1007
- * service.
1008
- *
1009
- * If a 'group' is specified, then only those services that belong to
1010
- * that group are enumerated. If an empty string is provided, then only
1011
- * services that do not belong to any group are enumerated. If this parameter
1012
- * is nil, group membership is ignored and all services are enumerated.
1013
- *
1014
- * The 'group' option is only available on Windows 2000 or later, and only
1015
- * if compiled with VC++ 7.0 or later, or the .NET SDK.
1016
- *
1017
- * The Win32 service struct contains the following members.
1018
- *
1019
- * * service_name
1020
- * * display_name
1021
- * * service_type
1022
- * * current_state
1023
- * * controls_accepted
1024
- * * win32_exit_code
1025
- * * service_specific_exit_code
1026
- * * check_point
1027
- * * wait_hint
1028
- * * binary_path_name
1029
- * * start_type
1030
- * * error_control
1031
- * * load_order_group
1032
- * * tag_id
1033
- * * start_name
1034
- * * dependencies
1035
- * * description
1036
- * * interactive
1037
- * * pid (Win2k or later)
1038
- * * service_flags (Win2k or later)
1039
- */
1040
- static VALUE service_services(int argc, VALUE *argv, VALUE klass)
1041
- {
1042
- SC_HANDLE hSCManager = NULL;
1043
- SC_HANDLE hSCService = NULL;
1044
- DWORD dwBytesNeeded = 0;
1045
- DWORD dwServicesReturned = 0;
1046
- DWORD dwResumeHandle = 0;
1047
- LPQUERY_SERVICE_CONFIG lpqscConf;
1048
- LPSERVICE_DESCRIPTION lpqscDesc;
1049
- TCHAR* lpMachineName;
1050
- VALUE v_machine_name = Qnil;
1051
- VALUE v_dependencies = Qnil;
1052
- VALUE v_struct;
1053
- VALUE v_array = Qnil;
1054
- int rv = 0;
1055
-
1056
- #ifdef HAVE_ENUMSERVICESSTATUSEX
1057
- TCHAR* pszGroupName;
1058
- VALUE v_group = Qnil;
1059
- ENUM_SERVICE_STATUS_PROCESS svcArray[MAX_SERVICES];
1060
- rb_scan_args(argc, argv, "02", &v_machine_name, &v_group);
1061
- #else
1062
- ENUM_SERVICE_STATUS svcArray[MAX_SERVICES];
1063
- rb_scan_args(argc, argv, "01", &v_machine_name);
1064
- #endif
1065
-
1066
- // If no block is provided, return an array of struct's.
1067
- if(!rb_block_given_p())
1068
- v_array = rb_ary_new();
1069
-
1070
- if(NIL_P(v_machine_name)){
1071
- lpMachineName = NULL;
1072
- }
1073
- else{
1074
- SafeStringValue(v_machine_name);
1075
- lpMachineName = TEXT(StringValuePtr(v_machine_name));
1076
- }
1077
-
1078
- #ifdef HAVE_ENUMSERVICESSTATUSEX
1079
- if(NIL_P(v_group)){
1080
- pszGroupName = NULL;
1081
- }
1082
- else{
1083
- SafeStringValue(v_group);
1084
- pszGroupName = TEXT(StringValuePtr(v_group));
1085
- }
1086
- #endif
1087
-
1088
- hSCManager = OpenSCManager(
1089
- lpMachineName,
1090
- NULL,
1091
- SC_MANAGER_ENUMERATE_SERVICE
1092
- );
1093
-
1094
- if(NULL == hSCManager){
1095
- sprintf(error, "OpenSCManager() call failed: %s",
1096
- ErrorDescription(GetLastError()));
1097
- rb_raise(cServiceError,error);
1098
- }
1099
-
1100
- lpqscConf = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LPTR, MAX_BUF_SIZE);
1101
- lpqscDesc = (LPSERVICE_DESCRIPTION) LocalAlloc(LPTR, MAX_BUF_SIZE);
1102
-
1103
- #ifdef HAVE_ENUMSERVICESSTATUSEX
1104
- rv = EnumServicesStatusEx(
1105
- hSCManager, // SC Manager
1106
- SC_ENUM_PROCESS_INFO, // Info level (only possible value)
1107
- SERVICE_WIN32 | SERVICE_DRIVER, // Service type
1108
- SERVICE_STATE_ALL, // Service state
1109
- (LPBYTE)svcArray, // Array of structs
1110
- sizeof(svcArray),
1111
- &dwBytesNeeded,
1112
- &dwServicesReturned,
1113
- &dwResumeHandle,
1114
- pszGroupName
1115
- );
1116
- #else
1117
- rv = EnumServicesStatus(
1118
- hSCManager, // SC Manager
1119
- SERVICE_WIN32 | SERVICE_DRIVER, // Service type
1120
- SERVICE_STATE_ALL, // Service state
1121
- svcArray, // Array of structs
1122
- sizeof(svcArray),
1123
- &dwBytesNeeded,
1124
- &dwServicesReturned,
1125
- &dwResumeHandle
1126
- );
1127
- #endif
1128
-
1129
- if(rv != 0)
1130
- {
1131
- unsigned i;
1132
- int rv;
1133
- VALUE v_service_type, v_current_state, v_controls_accepted;
1134
- VALUE v_binary_path_name, v_error_control, v_load_order_group;
1135
- VALUE v_start_type, v_service_start_name, v_description, v_interactive;
1136
-
1137
- for(i = 0; i < dwServicesReturned; i++){
1138
- DWORD dwBytesNeeded;
1139
- v_controls_accepted = rb_ary_new();
1140
- v_interactive = Qfalse;
1141
-
1142
- hSCService = OpenService(
1143
- hSCManager,
1144
- svcArray[i].lpServiceName,
1145
- SERVICE_QUERY_CONFIG
1146
- );
1147
-
1148
- if(!hSCService){
1149
- sprintf(error, "OpenService() call failed: %s",
1150
- ErrorDescription(GetLastError()));
1151
- CloseServiceHandle(hSCManager);
1152
- rb_raise(cServiceError, error);
1153
- }
1154
-
1155
- // Retrieve a QUERY_SERVICE_CONFIG structure for the Service, from
1156
- // which we can gather the service type, start type, etc.
1157
- rv = QueryServiceConfig(
1158
- hSCService,
1159
- lpqscConf,
1160
- MAX_BUF_SIZE,
1161
- &dwBytesNeeded
1162
- );
1163
-
1164
- if(0 == rv){
1165
- sprintf(error, "QueryServiceConfig() call failed: %s",
1166
- ErrorDescription(GetLastError()));
1167
- CloseServiceHandle(hSCManager);
1168
- rb_raise(cServiceError, error);
1169
- }
1170
-
1171
- // Get the description for the Service
1172
- rv = QueryServiceConfig2(
1173
- hSCService,
1174
- SERVICE_CONFIG_DESCRIPTION,
1175
- (LPBYTE)lpqscDesc,
1176
- MAX_BUF_SIZE,
1177
- &dwBytesNeeded
1178
- );
1179
-
1180
- if(0 == rv){
1181
- sprintf(error,"QueryServiceConfig2() call failed: %s",
1182
- ErrorDescription(GetLastError()));
1183
- CloseServiceHandle(hSCManager);
1184
- rb_raise(cServiceError, error);
1185
- }
1186
-
1187
- #ifdef HAVE_ENUMSERVICESSTATUSEX
1188
- if(svcArray[i].ServiceStatusProcess.dwServiceType
1189
- & SERVICE_INTERACTIVE_PROCESS){
1190
- v_interactive = Qtrue;
1191
- }
1192
- #else
1193
- if(svcArray[i].ServiceStatus.dwServiceType
1194
- & SERVICE_INTERACTIVE_PROCESS){
1195
- v_interactive = Qtrue;
1196
- }
1197
- #endif
1198
-
1199
- #ifdef HAVE_ENUMSERVICESSTATUSEX
1200
- v_service_type =
1201
- rb_get_service_type(svcArray[i].ServiceStatusProcess.dwServiceType);
1202
-
1203
- v_current_state =
1204
- rb_get_current_state(
1205
- svcArray[i].ServiceStatusProcess.dwCurrentState);
1206
-
1207
- v_controls_accepted =
1208
- rb_get_controls_accepted(
1209
- svcArray[i].ServiceStatusProcess.dwControlsAccepted);
1210
- #else
1211
- v_service_type =
1212
- rb_get_service_type(svcArray[i].ServiceStatus.dwServiceType);
1213
-
1214
- v_current_state =
1215
- rb_get_current_state(svcArray[i].ServiceStatus.dwCurrentState);
1216
-
1217
- v_controls_accepted =
1218
- rb_get_controls_accepted(
1219
- svcArray[i].ServiceStatus.dwControlsAccepted);
1220
- #endif
1221
-
1222
- if(_tcslen(lpqscConf->lpBinaryPathName) > 0)
1223
- v_binary_path_name = rb_str_new2(lpqscConf->lpBinaryPathName);
1224
- else
1225
- v_binary_path_name = Qnil;
1226
-
1227
- if(_tcslen(lpqscConf->lpLoadOrderGroup) > 0)
1228
- v_load_order_group = rb_str_new2(lpqscConf->lpLoadOrderGroup);
1229
- else
1230
- v_load_order_group = Qnil;
1231
-
1232
- if(_tcslen(lpqscConf->lpServiceStartName) > 0)
1233
- v_service_start_name = rb_str_new2(lpqscConf->lpServiceStartName);
1234
- else
1235
- v_service_start_name = Qnil;
1236
-
1237
- if(lpqscDesc->lpDescription != NULL)
1238
- v_description = rb_str_new2(lpqscDesc->lpDescription);
1239
- else
1240
- v_description = Qnil;
1241
-
1242
- v_start_type = rb_get_start_type(lpqscConf->dwStartType);
1243
- v_error_control = rb_get_error_control(lpqscConf->dwErrorControl);
1244
- v_dependencies = rb_get_dependencies(lpqscConf->lpDependencies);
1245
-
1246
- CloseServiceHandle(hSCService);
1247
-
1248
- #ifdef HAVE_ENUMSERVICESSTATUSEX
1249
- v_struct = rb_struct_new(v_service_struct,
1250
- rb_str_new2(svcArray[i].lpServiceName),
1251
- rb_str_new2(svcArray[i].lpDisplayName),
1252
- v_service_type,
1253
- v_current_state,
1254
- v_controls_accepted,
1255
- INT2FIX(svcArray[i].ServiceStatusProcess.dwWin32ExitCode),
1256
- INT2FIX(svcArray[i].ServiceStatusProcess.dwServiceSpecificExitCode),
1257
- INT2FIX(svcArray[i].ServiceStatusProcess.dwCheckPoint),
1258
- INT2FIX(svcArray[i].ServiceStatusProcess.dwWaitHint),
1259
- v_binary_path_name,
1260
- v_start_type,
1261
- v_error_control,
1262
- v_load_order_group,
1263
- INT2FIX(lpqscConf->dwTagId),
1264
- v_service_start_name,
1265
- v_dependencies,
1266
- v_description,
1267
- v_interactive,
1268
- INT2FIX(svcArray[i].ServiceStatusProcess.dwProcessId),
1269
- INT2FIX(svcArray[i].ServiceStatusProcess.dwServiceFlags)
1270
- );
1271
- #else
1272
- v_struct = rb_struct_new(v_service_struct,
1273
- rb_str_new2(svcArray[i].lpServiceName),
1274
- rb_str_new2(svcArray[i].lpDisplayName),
1275
- v_service_type,
1276
- v_current_state,
1277
- v_controls_accepted,
1278
- INT2FIX(svcArray[i].ServiceStatus.dwWin32ExitCode),
1279
- INT2FIX(svcArray[i].ServiceStatus.dwServiceSpecificExitCode),
1280
- INT2FIX(svcArray[i].ServiceStatus.dwCheckPoint),
1281
- INT2FIX(svcArray[i].ServiceStatus.dwWaitHint),
1282
- v_binary_path_name,
1283
- v_start_type,
1284
- v_error_control,
1285
- v_load_order_group,
1286
- INT2FIX(lpqscConf->dwTagId),
1287
- v_service_start_name,
1288
- v_dependencies,
1289
- v_description,
1290
- v_interactive
1291
- );
1292
- #endif
1293
- if(rb_block_given_p()){
1294
- rb_yield(v_struct);
1295
- }
1296
- else{
1297
- rb_ary_push(v_array, v_struct);
1298
- }
1299
- }
1300
- }
1301
- else{
1302
- sprintf(error,"EnumServiceStatus() call failed: %s",
1303
- ErrorDescription(GetLastError()));
1304
- LocalFree(lpqscConf);
1305
- LocalFree(lpqscDesc);
1306
- CloseServiceHandle(hSCManager);
1307
- rb_raise(cServiceError,error);
1308
- }
1309
-
1310
- LocalFree(lpqscConf);
1311
- LocalFree(lpqscDesc);
1312
- CloseServiceHandle(hSCManager);
1313
- return v_array; // Nil if a block was given
1314
- }
1315
-
1316
- /*
1317
- * call-seq:
1318
- * Service.stop(name, host=localhost)
1319
- *
1320
- * Stop a service. Attempting to stop an already stopped service raises
1321
- * a ServiceError.
1322
- */
1323
- static VALUE service_stop(int argc, VALUE *argv, VALUE klass)
1324
- {
1325
- SC_HANDLE hSCManager, hSCService;
1326
- TCHAR* lpMachineName;
1327
- TCHAR* lpServiceName;
1328
- SERVICE_STATUS serviceStatus;
1329
- VALUE v_service_name, v_machine_name;
1330
- int rv;
1331
-
1332
- rb_scan_args(argc, argv, "11", &v_service_name, &v_machine_name);
1333
-
1334
- SafeStringValue(v_service_name);
1335
- lpServiceName = TEXT(StringValuePtr(v_service_name));
1336
-
1337
- if(NIL_P(v_machine_name)){
1338
- lpMachineName = NULL;
1339
- }
1340
- else{
1341
- SafeStringValue(v_machine_name);
1342
- lpMachineName = TEXT(StringValuePtr(v_machine_name));
1343
- }
1344
-
1345
- hSCManager = OpenSCManager(
1346
- lpMachineName,
1347
- NULL,
1348
- SC_MANAGER_CONNECT
1349
- );
1350
-
1351
- if(!hSCManager)
1352
- rb_raise(cServiceError,ErrorDescription(GetLastError()));
1353
-
1354
- hSCService = OpenService(
1355
- hSCManager,
1356
- lpServiceName,
1357
- SERVICE_STOP
1358
- );
1359
-
1360
- if(!hSCService){
1361
- strcpy(error,ErrorDescription(GetLastError()));
1362
- CloseServiceHandle(hSCManager);
1363
- rb_raise(cServiceError,error);
1364
- }
1365
-
1366
- rv = ControlService(
1367
- hSCService,
1368
- SERVICE_CONTROL_STOP,
1369
- &serviceStatus
1370
- );
1371
-
1372
- if(0 == rv){
1373
- strcpy(error,ErrorDescription(GetLastError()));
1374
- CloseServiceHandle(hSCService);
1375
- CloseServiceHandle(hSCManager);
1376
- rb_raise(cServiceError,error);
1377
- }
1378
-
1379
- CloseServiceHandle(hSCService);
1380
- CloseServiceHandle(hSCManager);
1381
-
1382
- return klass;
1383
- }
1384
-
1385
- /*
1386
- * call-seq:
1387
- * Service.pause(name, host=localhost)
1388
- *
1389
- * Pause a service. Attempting to pause an already paused service will raise
1390
- * a ServiceError.
1391
- *
1392
- * Note that not all services are configured to accept a pause (or resume)
1393
- * command.
1394
- */
1395
- static VALUE service_pause(int argc, VALUE *argv, VALUE klass)
1396
- {
1397
- SC_HANDLE hSCManager, hSCService;
1398
- TCHAR* lpMachineName;
1399
- TCHAR* lpServiceName;
1400
- SERVICE_STATUS serviceStatus;
1401
- VALUE v_service_name, v_machine_name;
1402
- int rv;
1403
-
1404
- rb_scan_args(argc, argv, "11", &v_service_name, &v_machine_name);
1405
-
1406
- SafeStringValue(v_service_name);
1407
- lpServiceName = TEXT(StringValuePtr(v_service_name));
1408
-
1409
- if(NIL_P(v_machine_name)){
1410
- lpMachineName = NULL;
1411
- }
1412
- else{
1413
- SafeStringValue(v_machine_name);
1414
- lpMachineName = TEXT(StringValuePtr(v_machine_name));
1415
- }
1416
-
1417
- hSCManager = OpenSCManager(
1418
- lpMachineName,
1419
- NULL,
1420
- SC_MANAGER_CONNECT
1421
- );
1422
-
1423
- if(!hSCManager)
1424
- rb_raise(cServiceError,ErrorDescription(GetLastError()));
1425
-
1426
- hSCService = OpenService(
1427
- hSCManager,
1428
- lpServiceName,
1429
- SERVICE_PAUSE_CONTINUE
1430
- );
1431
-
1432
- if(!hSCService){
1433
- strcpy(error,ErrorDescription(GetLastError()));
1434
- CloseServiceHandle(hSCManager);
1435
- rb_raise(cServiceError,error);
1436
- }
1437
-
1438
- rv = ControlService(
1439
- hSCService,
1440
- SERVICE_CONTROL_PAUSE,
1441
- &serviceStatus
1442
- );
1443
-
1444
- if(0 == rv){
1445
- strcpy(error,ErrorDescription(GetLastError()));
1446
- CloseServiceHandle(hSCService);
1447
- CloseServiceHandle(hSCManager);
1448
- rb_raise(cServiceError,error);
1449
- }
1450
-
1451
- CloseServiceHandle(hSCService);
1452
- CloseServiceHandle(hSCManager);
1453
-
1454
- return klass;
1455
- }
1456
-
1457
- /*
1458
- * call-seq:
1459
- * Service.resume(name, host=localhost)
1460
- *
1461
- * Resume a service. Attempting to resume a service that isn't paused will
1462
- * raise a ServiceError.
1463
- *
1464
- * Note that not all services are configured to accept a resume (or pause)
1465
- * command. In that case, a ServiceError will be raised.
1466
- */
1467
- static VALUE service_resume(int argc, VALUE *argv, VALUE klass)
1468
- {
1469
- SC_HANDLE hSCManager, hSCService;
1470
- TCHAR* lpMachineName;
1471
- TCHAR* lpServiceName;
1472
- SERVICE_STATUS serviceStatus;
1473
- VALUE v_service_name, v_machine_name;
1474
- int rv;
1475
-
1476
- rb_scan_args(argc, argv, "11", &v_service_name, &v_machine_name);
1477
-
1478
- SafeStringValue(v_service_name);
1479
- lpServiceName = TEXT(StringValuePtr(v_service_name));
1480
-
1481
- if(NIL_P(v_machine_name)){
1482
- lpMachineName = NULL;
1483
- }
1484
- else{
1485
- SafeStringValue(v_machine_name);
1486
- lpMachineName = TEXT(StringValuePtr(v_machine_name));
1487
- }
1488
-
1489
- hSCManager = OpenSCManager(
1490
- lpMachineName,
1491
- NULL,
1492
- SC_MANAGER_CONNECT
1493
- );
1494
-
1495
- if(!hSCManager){
1496
- rb_raise(cServiceError,ErrorDescription(GetLastError()));
1497
- }
1498
-
1499
- hSCService = OpenService(
1500
- hSCManager,
1501
- lpServiceName,
1502
- SERVICE_PAUSE_CONTINUE
1503
- );
1504
-
1505
- if(!hSCService){
1506
- strcpy(error,ErrorDescription(GetLastError()));
1507
- CloseServiceHandle(hSCManager);
1508
- rb_raise(cServiceError,error);
1509
- }
1510
-
1511
- rv = ControlService(
1512
- hSCService,
1513
- SERVICE_CONTROL_CONTINUE,
1514
- &serviceStatus
1515
- );
1516
-
1517
- if(0 == rv){
1518
- strcpy(error,ErrorDescription(GetLastError()));
1519
- CloseServiceHandle(hSCService);
1520
- CloseServiceHandle(hSCManager);
1521
- rb_raise(cServiceError,error);
1522
- }
1523
-
1524
- CloseServiceHandle(hSCService);
1525
- CloseServiceHandle(hSCManager);
1526
-
1527
- return klass;
1528
- }
1529
-
1530
- /*
1531
- * call-seq:
1532
- * Service.start(name, host=localhost, args=nil)
1533
- *
1534
- * Attempts to start service +name+ on +host+, or the local machine if no
1535
- * host is provided. If +args+ are provided, they are passed to the service's
1536
- * Service_Main() function.
1537
- *
1538
- *-- Note that the WMI interface does not allow you to pass arguments to the
1539
- *-- Service_Main function.
1540
- */
1541
- static VALUE service_start(int argc, VALUE *argv, VALUE klass){
1542
- SC_HANDLE hSCManager, hSCService;
1543
- TCHAR* lpMachineName;
1544
- TCHAR* lpServiceName;
1545
- TCHAR** lpServiceArgVectors;
1546
- VALUE v_service_name, v_machine_name, rbArgs;
1547
- int rv;
1548
-
1549
- rb_scan_args(argc, argv, "11*", &v_service_name, &v_machine_name, &rbArgs);
1550
-
1551
- SafeStringValue(v_service_name);
1552
- lpServiceName = TEXT(StringValuePtr(v_service_name));
1553
-
1554
- if(NIL_P(v_machine_name)){
1555
- lpMachineName = NULL;
1556
- }
1557
- else{
1558
- SafeStringValue(v_machine_name);
1559
- lpMachineName = TEXT(StringValuePtr(v_machine_name));
1560
- }
1561
-
1562
- if( (NIL_P(rbArgs)) || (RARRAY(rbArgs)->len == 0) ){
1563
- lpServiceArgVectors = NULL;
1564
- }
1565
- else{
1566
- int i;
1567
- lpServiceArgVectors =
1568
- malloc(RARRAY(rbArgs)->len * sizeof(*lpServiceArgVectors));
1569
-
1570
- for(i = 0; i < RARRAY(rbArgs)->len; i++){
1571
- VALUE v_tmp = rb_ary_entry(rbArgs, i);
1572
- TCHAR* string = TEXT(StringValuePtr(v_tmp));
1573
- lpServiceArgVectors[i] = malloc(*string);
1574
- lpServiceArgVectors[i] = string;
1575
- }
1576
- }
1577
-
1578
- hSCManager = OpenSCManager(
1579
- lpMachineName,
1580
- NULL,
1581
- SC_MANAGER_CONNECT
1582
- );
1583
-
1584
- if(!hSCManager)
1585
- rb_raise(cServiceError,ErrorDescription(GetLastError()));
1586
-
1587
- hSCService = OpenService(
1588
- hSCManager,
1589
- lpServiceName,
1590
- SERVICE_START
1591
- );
1592
-
1593
- if(!hSCService){
1594
- strcpy(error,ErrorDescription(GetLastError()));
1595
- CloseServiceHandle(hSCManager);
1596
- rb_raise(cServiceError,error);
1597
- }
1598
-
1599
- rv = StartService(
1600
- hSCService,
1601
- 0,
1602
- lpServiceArgVectors
1603
- );
1604
-
1605
- if(0 == rv){
1606
- strcpy(error,ErrorDescription(GetLastError()));
1607
- CloseServiceHandle(hSCManager);
1608
- CloseServiceHandle(hSCService);
1609
- if(lpServiceArgVectors){
1610
- free(lpServiceArgVectors);
1611
- }
1612
- rb_raise(cServiceError,error);
1613
- }
1614
-
1615
- CloseServiceHandle(hSCManager);
1616
- CloseServiceHandle(hSCService);
1617
-
1618
- if(lpServiceArgVectors)
1619
- free(lpServiceArgVectors);
1620
-
1621
- return klass;
1622
- }
1623
-
1624
- /*
1625
- * call-seq:
1626
- * Service.getservicename(display_name, host=localhost)
1627
- *
1628
- * Returns the service name for the corresponding +display_name+ on +host+, or
1629
- * the local machine if no host is specified.
1630
- */
1631
- static VALUE service_get_service_name(int argc, VALUE *argv, VALUE klass)
1632
- {
1633
- SC_HANDLE hSCManager;
1634
- TCHAR* lpMachineName;
1635
- TCHAR* lpDisplayName;
1636
- TCHAR szRegKey[MAX_PATH];
1637
- DWORD dwKeySize = sizeof(szRegKey);
1638
- VALUE v_machine_name, rbDisplayName;
1639
- int rv;
1640
-
1641
- rb_scan_args(argc, argv, "11", &rbDisplayName, &v_machine_name);
1642
-
1643
- SafeStringValue(rbDisplayName);
1644
- lpDisplayName = TEXT(StringValuePtr(rbDisplayName));
1645
-
1646
- if(NIL_P(v_machine_name)){
1647
- lpMachineName = NULL;
1648
- }
1649
- else{
1650
- SafeStringValue(v_machine_name);
1651
- lpMachineName = TEXT(StringValuePtr(v_machine_name));
1652
- }
1653
-
1654
- hSCManager = OpenSCManager(
1655
- lpMachineName,
1656
- NULL,
1657
- SC_MANAGER_CONNECT
1658
- );
1659
-
1660
- if(!hSCManager)
1661
- rb_raise(rb_eArgError,ErrorDescription(GetLastError()));
1662
-
1663
- rv = GetServiceKeyName(
1664
- hSCManager,
1665
- lpDisplayName,
1666
- szRegKey,
1667
- &dwKeySize
1668
- );
1669
-
1670
- if(0 == rv){
1671
- strcpy(error,ErrorDescription(GetLastError()));
1672
- CloseServiceHandle(hSCManager);
1673
- rb_raise(rb_eArgError,error);
1674
- }
1675
-
1676
- CloseServiceHandle(hSCManager);
1677
-
1678
- return rb_str_new2(szRegKey);
1679
- }
1680
-
1681
- /*
1682
- * call-seq:
1683
- * Service.getdisplayname(service_name, host=localhost)
1684
- *
1685
- * Returns the display name for the service +service_name+ on +host+, or the
1686
- * localhost if no host is specified.
1687
- */
1688
- static VALUE service_get_display_name(int argc, VALUE *argv, VALUE klass)
1689
- {
1690
- SC_HANDLE hSCManager;
1691
- TCHAR* lpMachineName;
1692
- TCHAR* lpServiceName;
1693
- TCHAR szRegKey[MAX_PATH];
1694
- DWORD dwKeySize = sizeof(szRegKey);
1695
- VALUE v_machine_name, v_service_name;
1696
- int rv;
1697
-
1698
- rb_scan_args(argc, argv, "11", &v_service_name, &v_machine_name);
1699
-
1700
- SafeStringValue(v_service_name);
1701
- lpServiceName = TEXT(StringValuePtr(v_service_name));
1702
-
1703
- if(NIL_P(v_machine_name)){
1704
- lpMachineName = NULL;
1705
- }
1706
- else{
1707
- SafeStringValue(v_machine_name);
1708
- lpMachineName = TEXT(StringValuePtr(v_machine_name));
1709
- }
1710
-
1711
- hSCManager = OpenSCManager(
1712
- lpMachineName,
1713
- NULL,
1714
- SC_MANAGER_CONNECT
1715
- );
1716
-
1717
- if(!hSCManager)
1718
- rb_raise(rb_eArgError,ErrorDescription(GetLastError()));
1719
-
1720
- rv = GetServiceDisplayName(
1721
- hSCManager,
1722
- lpServiceName,
1723
- szRegKey,
1724
- &dwKeySize
1725
- );
1726
-
1727
- if(0 == rv){
1728
- strcpy(error,ErrorDescription(GetLastError()));
1729
- CloseServiceHandle(hSCManager);
1730
- rb_raise(rb_eArgError,error);
1731
- }
1732
-
1733
- CloseServiceHandle(hSCManager);
1734
-
1735
- return rb_str_new2(szRegKey);
1736
- }
1737
-
1738
- /*
1739
- * Sets the dependencies for the given service. Use this when you call
1740
- * Service.create_service, if desired.
1741
- */
1742
- static VALUE service_set_dependencies(VALUE self, VALUE array)
1743
- {
1744
- Check_Type(array, T_ARRAY);
1745
- rb_iv_set(self, "@dependencies", array);
1746
- return self;
1747
- }
1748
-
1749
- /*
1750
- * Returns an array of dependencies for the given service, or nil if there
1751
- * aren't any dependencies.
1752
- */
1753
- static VALUE service_get_dependencies(VALUE self){
1754
- return rb_iv_get(self, "@dependencies");
1755
- }
1756
-
1757
- /*
1758
- * call-seq:
1759
- * Service.status(name, host=localhost)
1760
- *
1761
- * Returns a ServiceStatus struct indicating the status of service +name+ on
1762
- * +host+, or the localhost if none is provided.
1763
- *
1764
- * The ServiceStatus struct contains the following members:
1765
- *
1766
- * * service_type
1767
- * * current_state
1768
- * * controls_accepted
1769
- * * win32_exit_code
1770
- * * service_specific_exit_code
1771
- * * check_point
1772
- * * wait_hint
1773
- * * pid (Win2k or later)
1774
- * * service_flags (Win2k or later)
1775
- */
1776
- static VALUE service_status(int argc, VALUE *argv, VALUE klass){
1777
- SC_HANDLE hSCManager, hSCService;
1778
- VALUE v_service_name, v_machine_name;
1779
- VALUE v_service_type, v_current_state, v_controls_accepted;
1780
- VALUE v_interactive = Qfalse;
1781
- TCHAR* lpMachineName;
1782
- TCHAR* lpServiceName;
1783
- DWORD dwBytesNeeded;
1784
- int rv;
1785
-
1786
- #ifdef HAVE_QUERYSERVICESTATUSEX
1787
- SERVICE_STATUS_PROCESS ssProcess;
1788
- #else
1789
- SERVICE_STATUS ssProcess;
1790
- #endif
1791
-
1792
- rb_scan_args(argc, argv, "11", &v_service_name, &v_machine_name);
1793
-
1794
- SafeStringValue(v_service_name);
1795
- lpServiceName = TEXT(StringValuePtr(v_service_name));
1796
-
1797
- if(NIL_P(v_machine_name)){
1798
- lpMachineName = NULL;
1799
- }
1800
- else{
1801
- SafeStringValue(v_machine_name);
1802
- lpMachineName = TEXT(StringValuePtr(v_machine_name));
1803
- }
1804
-
1805
- hSCManager = OpenSCManager(
1806
- lpMachineName,
1807
- NULL,
1808
- SC_MANAGER_ENUMERATE_SERVICE
1809
- );
1810
-
1811
- if(!hSCManager)
1812
- rb_raise(cServiceError,ErrorDescription(GetLastError()));
1813
-
1814
- hSCService = OpenService(
1815
- hSCManager,
1816
- lpServiceName,
1817
- SERVICE_QUERY_STATUS
1818
- );
1819
-
1820
- if(!hSCService){
1821
- strcpy(error,ErrorDescription(GetLastError()));
1822
- CloseServiceHandle(hSCManager);
1823
- rb_raise(cServiceError,error);
1824
- }
1825
-
1826
- #ifdef HAVE_QUERYSERVICESTATUSEX
1827
- rv = QueryServiceStatusEx(
1828
- hSCService,
1829
- SC_STATUS_PROCESS_INFO,
1830
- (LPBYTE)&ssProcess,
1831
- sizeof(SERVICE_STATUS_PROCESS),
1832
- &dwBytesNeeded
1833
- );
1834
- #else
1835
- rv = QueryServiceStatus(
1836
- hSCService,
1837
- &ssProcess
1838
- );
1839
- #endif
1840
-
1841
- v_service_type = rb_get_service_type(ssProcess.dwServiceType);
1842
- v_current_state = rb_get_current_state(ssProcess.dwCurrentState);
1843
- v_controls_accepted = rb_get_controls_accepted(ssProcess.dwControlsAccepted);
1844
-
1845
- if(ssProcess.dwServiceType & SERVICE_INTERACTIVE_PROCESS){
1846
- v_interactive = Qtrue;
1847
- }
1848
-
1849
- CloseServiceHandle(hSCService);
1850
- CloseServiceHandle(hSCManager);
1851
-
1852
- return rb_struct_new(v_service_status_struct,
1853
- v_service_type,
1854
- v_current_state,
1855
- v_controls_accepted,
1856
- INT2FIX(ssProcess.dwWin32ExitCode),
1857
- INT2FIX(ssProcess.dwServiceSpecificExitCode),
1858
- INT2FIX(ssProcess.dwCheckPoint),
1859
- INT2FIX(ssProcess.dwWaitHint),
1860
- v_interactive
1861
- #ifdef HAVE_QUERYSERVICESTATUSEX
1862
- ,INT2FIX(ssProcess.dwProcessId)
1863
- ,INT2FIX(ssProcess.dwServiceFlags)
1864
- #endif
1865
- );
1866
- }
1867
-
1868
- /* call-seq:
1869
- * Service.exists?(name, host=localhost)
1870
- *
1871
- * Returns whether or not the service +name+ exists on +host+, or the localhost
1872
- * if none is provided.
1873
- */
1874
- static VALUE service_exists(int argc, VALUE *argv, VALUE klass){
1875
- SC_HANDLE hSCManager, hSCService;
1876
- TCHAR* lpMachineName;
1877
- TCHAR* lpServiceName;
1878
- VALUE v_service_name, v_machine_name;
1879
- VALUE rbExists = Qtrue;
1880
-
1881
- rb_scan_args(argc, argv, "11", &v_service_name, &v_machine_name);
1882
-
1883
- SafeStringValue(v_service_name);
1884
- lpServiceName = TEXT(StringValuePtr(v_service_name));
1885
-
1886
- if(NIL_P(v_machine_name)){
1887
- lpMachineName = NULL;
1888
- }
1889
- else{
1890
- SafeStringValue(v_machine_name);
1891
- lpMachineName = TEXT(StringValuePtr(v_machine_name));
1892
- }
1893
-
1894
- hSCManager = OpenSCManager(
1895
- lpMachineName,
1896
- NULL,
1897
- SC_MANAGER_ENUMERATE_SERVICE
1898
- );
1899
-
1900
- if(!hSCManager)
1901
- rb_raise(cServiceError,ErrorDescription(GetLastError()));
1902
-
1903
- hSCService = OpenService(
1904
- hSCManager,
1905
- lpServiceName,
1906
- SERVICE_QUERY_STATUS
1907
- );
1908
-
1909
- if(!hSCService)
1910
- rbExists = Qfalse;
1911
-
1912
- CloseServiceHandle(hSCService);
1913
- CloseServiceHandle(hSCManager);
1914
-
1915
- return rbExists;
1916
- }
1917
-
1918
- /*
1919
- * call-seq:
1920
- * Service.open(service_name, host=nil, desired_access=nil)
1921
- * Service.open(service_name, host=nil, desired_access=nil){ |svc| ... }
1922
- *
1923
- * Opens and returns a new Service object based on +service_name+ from +host+
1924
- * or the local machine if no host is specified. If a block is provided, the
1925
- * object is automatically closed at the end of the block.
1926
- *
1927
- * Note that the default desired access for the returned object is
1928
- * Service::SERVICE_QUERY_CONFIG. You will probably need to change that in
1929
- * order to configure or delete an existing service using the returned object.
1930
- */
1931
- static VALUE service_open(int argc, VALUE* argv, VALUE klass){
1932
- VALUE self, v_service_name, v_host, v_desired_access;
1933
- SvcStruct* ptr;
1934
- SC_HANDLE hSCService;
1935
- TCHAR* lpMachineName;
1936
- LPQUERY_SERVICE_CONFIG lpConf;
1937
- LPSERVICE_DESCRIPTION lpDesc;
1938
- DWORD dwDesiredAccess = SERVICE_QUERY_CONFIG;
1939
- DWORD dwBytesNeeded, rv;
1940
-
1941
- rb_scan_args(argc, argv, "12", &v_service_name, &v_host, &v_desired_access);
1942
-
1943
- self = Data_Make_Struct(klass, SvcStruct, 0, service_free, ptr);
1944
-
1945
- /* Set the host name, or use the localhost if no host is specified */
1946
- if(NIL_P(v_host)){
1947
- TCHAR name[MAX_PATH];
1948
- lpMachineName = NULL;
1949
-
1950
- if(gethostname(name, MAX_PATH))
1951
- rb_raise(cServiceError, "gethostname() failed");
1952
-
1953
- v_host = rb_str_new2(name);
1954
- }
1955
- else{
1956
- lpMachineName = TEXT(StringValuePtr(v_host));
1957
- }
1958
-
1959
- /* Set the desired access level. Default to SERVICE_QUERY_CONFIG */
1960
- if(NIL_P(v_desired_access))
1961
- v_desired_access = INT2FIX(SERVICE_QUERY_CONFIG);
1962
- else
1963
- dwDesiredAccess = NUM2INT(v_desired_access);
1964
-
1965
- ptr->hSCManager = OpenSCManager(
1966
- lpMachineName,
1967
- NULL,
1968
- dwDesiredAccess
1969
- );
1970
-
1971
- if(!ptr->hSCManager)
1972
- rb_raise(cServiceError, ErrorDescription(GetLastError()));
1973
-
1974
- lpConf = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LPTR, MAX_BUF_SIZE);
1975
- lpDesc = (LPSERVICE_DESCRIPTION) LocalAlloc(LPTR, MAX_BUF_SIZE);
1976
-
1977
- hSCService = OpenService(
1978
- ptr->hSCManager,
1979
- TEXT(StringValuePtr(v_service_name)),
1980
- SERVICE_QUERY_CONFIG
1981
- );
1982
-
1983
- if(!hSCService)
1984
- rb_raise(cServiceError, ErrorDescription(GetLastError()));
1985
-
1986
- rv = QueryServiceConfig(
1987
- hSCService,
1988
- lpConf,
1989
- MAX_BUF_SIZE,
1990
- &dwBytesNeeded
1991
- );
1992
-
1993
- if(0 == rv){
1994
- sprintf(error, "QueryServiceConfig() call failed: %s",
1995
- ErrorDescription(GetLastError()));
1996
- CloseServiceHandle(ptr->hSCManager);
1997
- rb_raise(cServiceError, error);
1998
- }
1999
-
2000
- rv = QueryServiceConfig2(
2001
- hSCService,
2002
- SERVICE_CONFIG_DESCRIPTION,
2003
- (LPBYTE)lpDesc,
2004
- MAX_BUF_SIZE,
2005
- &dwBytesNeeded
2006
- );
2007
-
2008
- if(0 == rv){
2009
- sprintf(error, "QueryServiceConfig2() call failed: %s",
2010
- ErrorDescription(GetLastError()));
2011
- CloseServiceHandle(ptr->hSCManager);
2012
- rb_raise(cServiceError,error);
2013
- }
2014
-
2015
- CloseServiceHandle(hSCService);
2016
-
2017
- /* Designer's note: the original plan to convert integer constants was
2018
- * abandoned because methods like Service#configure expect a number.
2019
- */
2020
- rb_iv_set(self, "@machine_name", v_host);
2021
- rb_iv_set(self, "@desired_access", v_desired_access);
2022
- rb_iv_set(self, "@service_name", v_service_name);
2023
- rb_iv_set(self, "@display_name", rb_str_new2(lpConf->lpDisplayName));
2024
- rb_iv_set(self, "@service_type", INT2FIX(lpConf->dwServiceType));
2025
- rb_iv_set(self, "@start_type", INT2FIX(lpConf->dwStartType));
2026
- rb_iv_set(self, "@binary_path_name", rb_str_new2(lpConf->lpBinaryPathName));
2027
- rb_iv_set(self, "@tag_id", INT2FIX(lpConf->dwTagId));
2028
- rb_iv_set(self, "@start_name", rb_str_new2(lpConf->lpServiceStartName));
2029
- rb_iv_set(self, "@service_description", rb_str_new2(lpDesc->lpDescription));
2030
- rb_iv_set(self, "@error_control", INT2FIX(lpConf->dwErrorControl));
2031
-
2032
- if(lpConf->lpLoadOrderGroup){
2033
- rb_iv_set(self, "@load_order_group",
2034
- rb_str_new2(lpConf->lpLoadOrderGroup));
2035
- }
2036
-
2037
- rb_iv_set(self, "@dependencies",
2038
- rb_get_dependencies(lpConf->lpDependencies));
2039
-
2040
- if(rb_block_given_p()){
2041
- rb_ensure(rb_yield, self, service_close, self);
2042
- return Qnil;
2043
- }
2044
- else{
2045
- return self;
2046
- }
2047
- }
2048
-
2049
- void Init_service()
2050
- {
2051
- VALUE mWin32, cService, cDaemon;
2052
- int i = 0;
2053
-
2054
- // Modules and classes
2055
- mWin32 = rb_define_module("Win32");
2056
- cService = rb_define_class_under(mWin32, "Service", rb_cObject);
2057
- cDaemon = rb_define_class_under(mWin32, "Daemon", rb_cObject);
2058
- cServiceError = rb_define_class_under(
2059
- mWin32, "ServiceError", rb_eStandardError);
2060
- cDaemonError = rb_define_class_under(
2061
- mWin32, "DaemonError", rb_eStandardError);
2062
-
2063
- // Service class and instance methods
2064
- rb_define_alloc_func(cService,service_allocate);
2065
- rb_define_method(cService, "initialize", service_init, -1);
2066
- rb_define_method(cService, "close", service_close, 0);
2067
- rb_define_method(cService, "create_service", service_create, 0);
2068
- rb_define_method(cService, "configure_service", service_configure, 0);
2069
-
2070
- // We do type checking for these two methods, so they're defined
2071
- // indepedently.
2072
- rb_define_method(cService, "dependencies=", service_set_dependencies, 1);
2073
- rb_define_method(cService, "dependencies", service_get_dependencies, 0);
2074
-
2075
- rb_define_singleton_method(cService, "open", service_open, -1);
2076
- rb_define_singleton_method(cService, "delete", service_delete, -1);
2077
- rb_define_singleton_method(cService, "start", service_start, -1);
2078
- rb_define_singleton_method(cService, "stop", service_stop, -1);
2079
- rb_define_singleton_method(cService, "pause", service_pause, -1);
2080
- rb_define_singleton_method(cService, "resume", service_resume, -1);
2081
- rb_define_singleton_method(cService, "services", service_services, -1);
2082
- rb_define_singleton_method(cService, "status", service_status, -1);
2083
- rb_define_singleton_method(cService, "exists?", service_exists, -1);
2084
-
2085
- rb_define_singleton_method(cService, "getdisplayname",
2086
- service_get_display_name, -1);
2087
-
2088
- rb_define_singleton_method(cService, "getservicename",
2089
- service_get_service_name, -1);
2090
-
2091
- // Daemon class and instance methods
2092
- rb_define_alloc_func(cDaemon, daemon_allocate);
2093
- rb_define_method(cDaemon, "mainloop", daemon_mainloop, 0);
2094
- rb_define_method(cDaemon, "state", daemon_state, 0);
2095
- rb_define_method(cDaemon, "running?", daemon_is_running, 0);
2096
-
2097
- // Intialize critical section used by green polling thread
2098
- InitializeCriticalSection(&csControlCode);
2099
-
2100
- // Constants
2101
- rb_define_const(cService, "VERSION", rb_str_new2(WIN32_SERVICE_VERSION));
2102
- rb_define_const(cDaemon, "VERSION", rb_str_new2(WIN32_SERVICE_VERSION));
2103
- set_service_constants(cService);
2104
- set_daemon_constants(cDaemon);
2105
-
2106
- // Structs
2107
- v_service_status_struct = rb_struct_define("Win32ServiceStatus",
2108
- "service_type", "current_state", "controls_accepted", "win32_exit_code",
2109
- "service_specific_exit_code", "check_point", "wait_hint",
2110
- "interactive"
2111
- #ifdef HAVE_QUERYSERVICESTATUSEX
2112
- ,"pid", "service_flags"
2113
- #endif
2114
- ,0);
2115
-
2116
- v_service_struct = rb_struct_define("Win32Service", "service_name",
2117
- "display_name", "service_type", "current_state", "controls_accepted",
2118
- "win32_exit_code", "service_specific_exit_code", "check_point",
2119
- "wait_hint", "binary_path_name", "start_type", "error_control",
2120
- "load_order_group", "tag_id", "start_name", "dependencies",
2121
- "description", "interactive"
2122
- #ifdef HAVE_ENUMSERVICESSTATUSEX
2123
- ,"pid", "service_flags"
2124
- #endif
2125
- ,0);
2126
-
2127
- // Create an attr_accessor for each valid instance method
2128
- for(i = 0; i < sizeof(keys)/sizeof(char*); i++){
2129
- rb_define_attr(cService,keys[i],1,1);
2130
- }
2131
- }