win32-service 0.5.2-mswin32

Sign up to get free protection for your applications and to get access to all the features.
@@ -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