win32-service 0.5.2-mswin32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,416 @@
1
+ #define WIN32_SERVICE_VERSION "0.5.2"
2
+
3
+ #define MAX_KEY_SIZE 24
4
+ #define MAX_SERVICES 1000
5
+ #define MAX_BUF_SIZE 4096
6
+
7
+ struct servicestruct{
8
+ SC_HANDLE hSCManager;
9
+ };
10
+
11
+ typedef struct servicestruct SvcStruct;
12
+
13
+ static void service_free(SvcStruct *p){
14
+ CloseServiceHandle(p->hSCManager);
15
+ p->hSCManager = NULL;
16
+ free(p);
17
+ }
18
+
19
+ // A list of valid keys (attributes) for the Service class. Note that the
20
+ // 'dependencies' attribute is defined manually for type checking purposes
21
+ // so it is not included in this array.
22
+ char *keys[] = {
23
+ "machine_name",
24
+ "desired_access",
25
+ "service_name",
26
+ "display_name",
27
+ "service_type",
28
+ "start_type",
29
+ "error_control",
30
+ "tag_id",
31
+ "binary_path_name",
32
+ "load_order_group",
33
+ "start_name",
34
+ "password",
35
+ "service_description"
36
+ };
37
+
38
+ // Return an error code as a string
39
+ LPTSTR ErrorDescription(DWORD p_dwError)
40
+ {
41
+ HLOCAL hLocal = NULL;
42
+ static TCHAR ErrStr[1024];
43
+ int len;
44
+
45
+ if (!(len=FormatMessage(
46
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
47
+ FORMAT_MESSAGE_FROM_SYSTEM |
48
+ FORMAT_MESSAGE_IGNORE_INSERTS,
49
+ NULL,
50
+ p_dwError,
51
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
52
+ (LPTSTR)&hLocal,
53
+ 0,
54
+ NULL)))
55
+ {
56
+ rb_raise(rb_eStandardError, "unable to format error message");
57
+ }
58
+ memset(ErrStr, 0, sizeof(ErrStr));
59
+ strncpy(ErrStr, (LPTSTR)hLocal, len-2); // remove \r\n
60
+ LocalFree(hLocal);
61
+ return ErrStr;
62
+ }
63
+
64
+ static VALUE rb_get_dependencies(LPTSTR lpDependencies){
65
+ VALUE v_dependencies = rb_ary_new();
66
+
67
+ if(lpDependencies){
68
+ TCHAR* pszDepend = 0;
69
+ int i = 0;
70
+
71
+ pszDepend = &lpDependencies[i];
72
+
73
+ while(*pszDepend != 0){
74
+ rb_ary_push(v_dependencies, rb_str_new2(pszDepend));
75
+ i += _tcslen(lpDependencies) + 1;
76
+ pszDepend = &lpDependencies[i];
77
+ }
78
+ }
79
+
80
+ if(RARRAY(v_dependencies)->len == 0)
81
+ v_dependencies = Qnil;
82
+
83
+ return v_dependencies;
84
+ }
85
+
86
+ static VALUE rb_get_error_control(DWORD dwErrorControl){
87
+ VALUE v_error_control;
88
+ switch(dwErrorControl){
89
+ case SERVICE_ERROR_CRITICAL:
90
+ v_error_control = rb_str_new2("critical");
91
+ break;
92
+ case SERVICE_ERROR_IGNORE:
93
+ v_error_control = rb_str_new2("ignore");
94
+ break;
95
+ case SERVICE_ERROR_NORMAL:
96
+ v_error_control = rb_str_new2("normal");
97
+ break;
98
+ case SERVICE_ERROR_SEVERE:
99
+ v_error_control = rb_str_new2("severe");
100
+ break;
101
+ default:
102
+ v_error_control = Qnil;
103
+
104
+ }
105
+
106
+ return v_error_control;
107
+ }
108
+
109
+ static VALUE rb_get_start_type(DWORD dwStartType){
110
+ VALUE v_start_type;
111
+ switch(dwStartType){
112
+ case SERVICE_AUTO_START:
113
+ v_start_type = rb_str_new2("auto start");
114
+ break;
115
+ case SERVICE_BOOT_START:
116
+ v_start_type = rb_str_new2("boot start");
117
+ break;
118
+ case SERVICE_DEMAND_START:
119
+ v_start_type = rb_str_new2("demand start");
120
+ break;
121
+ case SERVICE_DISABLED:
122
+ v_start_type = rb_str_new2("disabled");
123
+ break;
124
+ case SERVICE_SYSTEM_START:
125
+ v_start_type = rb_str_new2("system start");
126
+ break;
127
+ default:
128
+ v_start_type = Qnil;
129
+ }
130
+
131
+ return v_start_type;
132
+ }
133
+
134
+ /* Helper function to retrieve the service type. Note that some of these
135
+ * values were not documented from the MSDN web site, but are listed in the
136
+ * winnt.h header file.
137
+ */
138
+ static VALUE rb_get_service_type(DWORD dwServiceType){
139
+ VALUE rbServiceType;
140
+ switch(dwServiceType){
141
+ case SERVICE_FILE_SYSTEM_DRIVER:
142
+ rbServiceType = rb_str_new2("filesystem driver");
143
+ break;
144
+ case SERVICE_KERNEL_DRIVER:
145
+ rbServiceType = rb_str_new2("kernel driver");
146
+ break;
147
+ case SERVICE_WIN32_OWN_PROCESS:
148
+ rbServiceType = rb_str_new2("own process");
149
+ break;
150
+ case SERVICE_WIN32_SHARE_PROCESS:
151
+ rbServiceType = rb_str_new2("share process");
152
+ break;
153
+ /* There is some debate whether this is supposed to be 'RECOGNIZED' */
154
+ case SERVICE_RECOGNIZER_DRIVER:
155
+ rbServiceType = rb_str_new2("recognizer driver");
156
+ break;
157
+ case SERVICE_DRIVER:
158
+ rbServiceType = rb_str_new2("driver");
159
+ break;
160
+ case SERVICE_WIN32:
161
+ rbServiceType = rb_str_new2("win32");
162
+ break;
163
+ case SERVICE_TYPE_ALL:
164
+ rbServiceType = rb_str_new2("all");
165
+ break;
166
+ case (SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS):
167
+ rbServiceType = rb_str_new2("own process, interactive");
168
+ break;
169
+ case (SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_SHARE_PROCESS):
170
+ rbServiceType = rb_str_new2("share process, interactive");
171
+ break;
172
+ default:
173
+ rbServiceType = Qnil;
174
+ }
175
+
176
+ return rbServiceType;
177
+ }
178
+
179
+ static VALUE rb_get_current_state(DWORD dwCurrentState){
180
+ VALUE rbCurrentState;
181
+ switch(dwCurrentState){
182
+ case SERVICE_CONTINUE_PENDING:
183
+ rbCurrentState = rb_str_new2("continue pending");
184
+ break;
185
+ case SERVICE_PAUSE_PENDING:
186
+ rbCurrentState = rb_str_new2("pause pending");
187
+ break;
188
+ case SERVICE_PAUSED:
189
+ rbCurrentState = rb_str_new2("paused");
190
+ break;
191
+ case SERVICE_RUNNING:
192
+ rbCurrentState = rb_str_new2("running");
193
+ break;
194
+ case SERVICE_START_PENDING:
195
+ rbCurrentState = rb_str_new2("start pending");
196
+ break;
197
+ case SERVICE_STOP_PENDING:
198
+ rbCurrentState = rb_str_new2("stop pending");
199
+ break;
200
+ case SERVICE_STOPPED:
201
+ rbCurrentState = rb_str_new2("stopped");
202
+ break;
203
+ default:
204
+ rbCurrentState = Qnil;
205
+ }
206
+
207
+ return rbCurrentState;
208
+ }
209
+
210
+ static VALUE rb_get_controls_accepted(DWORD dwControlsAccepted){
211
+ VALUE rbControlsAccepted = rb_ary_new();
212
+ if(dwControlsAccepted & SERVICE_ACCEPT_NETBINDCHANGE){
213
+ rb_ary_push(rbControlsAccepted,rb_str_new2("netbind change"));
214
+ }
215
+
216
+ if(dwControlsAccepted & SERVICE_ACCEPT_PARAMCHANGE){
217
+ rb_ary_push(rbControlsAccepted,rb_str_new2("param change"));
218
+ }
219
+
220
+ if(dwControlsAccepted & SERVICE_PAUSE_CONTINUE){
221
+ rb_ary_push(rbControlsAccepted,rb_str_new2("pause continue"));
222
+ }
223
+
224
+ if(dwControlsAccepted & SERVICE_ACCEPT_SHUTDOWN){
225
+ rb_ary_push(rbControlsAccepted,rb_str_new2("shutdown"));
226
+ }
227
+
228
+ if(dwControlsAccepted & SERVICE_ACCEPT_STOP){
229
+ rb_ary_push(rbControlsAccepted,rb_str_new2("stop"));
230
+ }
231
+
232
+ if(RARRAY(rbControlsAccepted)->len == 0){
233
+ rbControlsAccepted = Qnil;
234
+ }
235
+
236
+ return rbControlsAccepted;
237
+ }
238
+
239
+ static void set_service_constants(VALUE klass)
240
+ {
241
+ // Desired Access Flags
242
+ rb_define_const(klass, "MANAGER_ALL_ACCESS",
243
+ INT2NUM(SC_MANAGER_ALL_ACCESS));
244
+
245
+ rb_define_const(klass, "MANAGER_CREATE_SERVICE",
246
+ INT2NUM(SC_MANAGER_CREATE_SERVICE));
247
+
248
+ rb_define_const(klass, "MANAGER_CONNECT",
249
+ INT2NUM(SC_MANAGER_CONNECT));
250
+
251
+ rb_define_const(klass, "MANAGER_ENUMERATE_SERVICE",
252
+ INT2NUM(SC_MANAGER_ENUMERATE_SERVICE));
253
+
254
+ rb_define_const(klass, "MANAGER_LOCK",
255
+ INT2NUM(SC_MANAGER_LOCK));
256
+
257
+ #ifdef SC_MANAGER_BOOT_CONFIG
258
+ rb_define_const(klass, "MANAGER_BOOT_CONFIG",
259
+ INT2NUM(SC_MANAGER_BOOT_CONFIG));
260
+ #endif
261
+
262
+ rb_define_const(klass, "MANAGER_QUERY_LOCK_STATUS",
263
+ INT2NUM(SC_MANAGER_QUERY_LOCK_STATUS));
264
+
265
+ /* Service specific access flags */
266
+ rb_define_const(klass, "ALL_ACCESS", INT2NUM(SERVICE_ALL_ACCESS));
267
+ rb_define_const(klass, "CHANGE_CONFIG", INT2NUM(SERVICE_CHANGE_CONFIG));
268
+
269
+ rb_define_const(klass, "ENUMERATE_DEPENDENTS",
270
+ INT2NUM(SERVICE_ENUMERATE_DEPENDENTS));
271
+
272
+ rb_define_const(klass, "INTERROGATE", INT2NUM(SERVICE_INTERROGATE));
273
+ rb_define_const(klass, "PAUSE_CONTINUE", INT2NUM(SERVICE_PAUSE_CONTINUE));
274
+ rb_define_const(klass, "QUERY_CONFIG", INT2NUM(SERVICE_QUERY_CONFIG));
275
+ rb_define_const(klass, "QUERY_STATUS", INT2NUM(SERVICE_QUERY_STATUS));
276
+ rb_define_const(klass, "STOP", INT2NUM(SERVICE_STOP));
277
+ rb_define_const(klass, "START", INT2NUM(SERVICE_START));
278
+
279
+ rb_define_const(klass, "USER_DEFINED_CONTROL",
280
+ INT2NUM(SERVICE_USER_DEFINED_CONTROL));
281
+
282
+ // Service Type
283
+ rb_define_const(klass, "FILE_SYSTEM_DRIVER",
284
+ INT2NUM(SERVICE_FILE_SYSTEM_DRIVER));
285
+
286
+ rb_define_const(klass, "KERNEL_DRIVER",
287
+ INT2NUM(SERVICE_KERNEL_DRIVER));
288
+
289
+ rb_define_const(klass, "WIN32_OWN_PROCESS",
290
+ INT2NUM(SERVICE_WIN32_OWN_PROCESS));
291
+
292
+ rb_define_const(klass, "WIN32_SHARE_PROCESS",
293
+ INT2NUM(SERVICE_WIN32_SHARE_PROCESS));
294
+
295
+ rb_define_const(klass, "INTERACTIVE_PROCESS",
296
+ INT2NUM(SERVICE_INTERACTIVE_PROCESS));
297
+
298
+ // Start Type
299
+ rb_define_const(klass, "AUTO_START",
300
+ INT2NUM(SERVICE_AUTO_START));
301
+
302
+ rb_define_const(klass, "BOOT_START",
303
+ INT2NUM(SERVICE_BOOT_START));
304
+
305
+ rb_define_const(klass, "DEMAND_START",
306
+ INT2NUM(SERVICE_DEMAND_START));
307
+
308
+ rb_define_const(klass, "DISABLED",
309
+ INT2NUM(SERVICE_DISABLED));
310
+
311
+ rb_define_const(klass, "SYSTEM_START",
312
+ INT2NUM(SERVICE_SYSTEM_START));
313
+
314
+ // Error Control
315
+ rb_define_const(klass, "ERROR_IGNORE",
316
+ INT2NUM(SERVICE_ERROR_IGNORE));
317
+
318
+ rb_define_const(klass, "ERROR_NORMAL",
319
+ INT2NUM(SERVICE_ERROR_NORMAL));
320
+
321
+ rb_define_const(klass, "ERROR_SEVERE",
322
+ INT2NUM(SERVICE_ERROR_SEVERE));
323
+
324
+ rb_define_const(klass, "ERROR_CRITICAL",
325
+ INT2NUM(SERVICE_ERROR_CRITICAL));
326
+
327
+ // Service Status
328
+ rb_define_const(klass, "CONTINUE_PENDING",
329
+ INT2NUM(SERVICE_CONTINUE_PENDING));
330
+
331
+ rb_define_const(klass, "PAUSE_PENDING",
332
+ INT2NUM(SERVICE_PAUSE_PENDING));
333
+
334
+ rb_define_const(klass, "PAUSED",
335
+ INT2NUM(SERVICE_PAUSED));
336
+
337
+ rb_define_const(klass, "RUNNING",
338
+ INT2NUM(SERVICE_RUNNING));
339
+
340
+ rb_define_const(klass, "START_PENDING",
341
+ INT2NUM(SERVICE_START_PENDING));
342
+
343
+ rb_define_const(klass, "STOP_PENDING",
344
+ INT2NUM(SERVICE_STOP_PENDING));
345
+
346
+ rb_define_const(klass, "STOPPED",
347
+ INT2NUM(SERVICE_STOPPED));
348
+
349
+ // Service Control Signals
350
+ rb_define_const(klass, "CONTROL_STOP",
351
+ INT2NUM(SERVICE_CONTROL_STOP));
352
+
353
+ rb_define_const(klass, "CONTROL_PAUSE",
354
+ INT2NUM(SERVICE_CONTROL_PAUSE));
355
+
356
+ rb_define_const(klass, "CONTROL_CONTINUE",
357
+ INT2NUM(SERVICE_CONTROL_CONTINUE));
358
+
359
+ rb_define_const(klass, "CONTROL_INTERROGATE",
360
+ INT2NUM(SERVICE_CONTROL_INTERROGATE));
361
+
362
+ rb_define_const(klass, "CONTROL_SHUTDOWN",
363
+ INT2NUM(SERVICE_CONTROL_SHUTDOWN));
364
+
365
+ #ifdef SERVICE_CONTROL_PARAMCHANGE
366
+ rb_define_const(klass, "CONTROL_PARAMCHANGE",
367
+ INT2NUM(SERVICE_CONTROL_PARAMCHANGE));
368
+ #endif
369
+
370
+ #ifdef SERVICE_CONTROL_NETBINDADD
371
+ rb_define_const(klass, "CONTROL_NETBINDADD",
372
+ INT2NUM(SERVICE_CONTROL_NETBINDADD));
373
+ #endif
374
+
375
+ #ifdef SERVICE_CONTROL_NETBINDREMOVE
376
+ rb_define_const(klass, "CONTROL_NETBINDREMOVE",
377
+ INT2NUM(SERVICE_CONTROL_NETBINDREMOVE));
378
+ #endif
379
+
380
+ #ifdef SERVICE_CONTROL_NETBINDENABLE
381
+ rb_define_const(klass, "CONTROL_NETBINDENABLE",
382
+ INT2NUM(SERVICE_CONTROL_NETBINDENABLE));
383
+ #endif
384
+
385
+ #ifdef SERVICE_CONTROL_NETBINDDISABLE
386
+ rb_define_const(klass, "CONTROL_NETBINDDISABLE",
387
+ INT2NUM(SERVICE_CONTROL_NETBINDDISABLE));
388
+ #endif
389
+ }
390
+
391
+ // The Daemon class only needs a subset of the Service constants
392
+ void set_daemon_constants(VALUE klass){
393
+ rb_define_const(klass, "CONTINUE_PENDING",
394
+ INT2NUM(SERVICE_CONTINUE_PENDING));
395
+
396
+ rb_define_const(klass, "PAUSE_PENDING",
397
+ INT2NUM(SERVICE_PAUSE_PENDING));
398
+
399
+ rb_define_const(klass, "PAUSED",
400
+ INT2NUM(SERVICE_PAUSED));
401
+
402
+ rb_define_const(klass, "RUNNING",
403
+ INT2NUM(SERVICE_RUNNING));
404
+
405
+ rb_define_const(klass, "START_PENDING",
406
+ INT2NUM(SERVICE_START_PENDING));
407
+
408
+ rb_define_const(klass, "STOP_PENDING",
409
+ INT2NUM(SERVICE_STOP_PENDING));
410
+
411
+ rb_define_const(klass, "STOPPED",
412
+ INT2NUM(SERVICE_STOPPED));
413
+
414
+ rb_define_const(klass, "IDLE", INT2NUM(0));
415
+ }
416
+
Binary file
@@ -0,0 +1,59 @@
1
+ #########################################################################
2
+ # tc_daemon.rb
3
+ #
4
+ # Test suite for the Daemon class
5
+ #########################################################################
6
+ if File.basename(Dir.pwd) == "test"
7
+ require "ftools"
8
+ Dir.chdir ".."
9
+ Dir.mkdir("win32") unless File.exists?("win32")
10
+ File.copy("service.so","win32")
11
+ $LOAD_PATH.unshift Dir.pwd
12
+ end
13
+
14
+ require "win32/service"
15
+ require "test/unit"
16
+ include Win32
17
+
18
+ class TC_Daemon < Test::Unit::TestCase
19
+ def setup
20
+ @d = Daemon.new
21
+ end
22
+
23
+ def test_version
24
+ assert_equal("0.5.2", Daemon::VERSION)
25
+ end
26
+
27
+ def test_constructor
28
+ assert_respond_to(Daemon, :new)
29
+ assert_nothing_raised{ Daemon.new }
30
+ assert_raises(ArgumentError){ Daemon.new(1) } # No arguments by default
31
+ end
32
+
33
+ def test_mainloop
34
+ assert_respond_to(@d, :mainloop)
35
+ end
36
+
37
+ def test_state
38
+ assert_respond_to(@d, :state)
39
+ end
40
+
41
+ def test_running
42
+ assert_respond_to(@d, :running?)
43
+ end
44
+
45
+ def test_constants
46
+ assert_not_nil(Daemon::CONTINUE_PENDING)
47
+ assert_not_nil(Daemon::PAUSE_PENDING)
48
+ assert_not_nil(Daemon::PAUSED)
49
+ assert_not_nil(Daemon::RUNNING)
50
+ assert_not_nil(Daemon::START_PENDING)
51
+ assert_not_nil(Daemon::STOP_PENDING)
52
+ assert_not_nil(Daemon::STOPPED)
53
+ assert_not_nil(Daemon::IDLE)
54
+ end
55
+
56
+ def teardown
57
+ @d = nil
58
+ end
59
+ end