prevent buffer overflow, LoadString accepts the size of the buffer in TCHARs, not...
[reactos.git] / reactos / subsys / system / services / rpcserver.c
1 /*
2
3 */
4
5 /* INCLUDES ****************************************************************/
6
7 #define NTOS_MODE_USER
8 #include <ntos.h>
9 #include <stdio.h>
10 #include <windows.h>
11
12 #include "services.h"
13 #include "svcctl_s.h"
14
15 #define NDEBUG
16 #include <debug.h>
17
18
19 /* GLOBALS *****************************************************************/
20
21 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */
22 #define SERVICE_TAG 0x63765368 /* 'hSvc' */
23
24 typedef struct _SCMGR_HANDLE
25 {
26 DWORD Tag;
27 DWORD RefCount;
28 DWORD DesiredAccess;
29 } SCMGR_HANDLE;
30
31
32 typedef struct _MANAGER_HANDLE
33 {
34 SCMGR_HANDLE Handle;
35
36 /* FIXME: Insert more data here */
37
38 WCHAR DatabaseName[1];
39 } MANAGER_HANDLE, *PMANAGER_HANDLE;
40
41
42 typedef struct _SERVICE_HANDLE
43 {
44 SCMGR_HANDLE Handle;
45
46 DWORD DesiredAccess;
47 PSERVICE ServiceEntry;
48
49 /* FIXME: Insert more data here */
50
51 } SERVICE_HANDLE, *PSERVICE_HANDLE;
52
53
54 #define SC_MANAGER_READ \
55 (STANDARD_RIGHTS_READ | \
56 SC_MANAGER_QUERY_LOCK_STATUS | \
57 SC_MANAGER_ENUMERATE_SERVICE)
58
59 #define SC_MANAGER_WRITE \
60 (STANDARD_RIGHTS_WRITE | \
61 SC_MANAGER_MODIFY_BOOT_CONFIG | \
62 SC_MANAGER_CREATE_SERVICE)
63
64 #define SC_MANAGER_EXECUTE \
65 (STANDARD_RIGHTS_EXECUTE | \
66 SC_MANAGER_LOCK | \
67 SC_MANAGER_ENUMERATE_SERVICE | \
68 SC_MANAGER_CONNECT | \
69 SC_MANAGER_CREATE_SERVICE)
70
71
72 #define SERVICE_READ \
73 (STANDARD_RIGHTS_READ | \
74 SERVICE_INTERROGATE | \
75 SERVICE_ENUMERATE_DEPENDENTS | \
76 SERVICE_QUERY_STATUS | \
77 SERVICE_QUERY_CONFIG)
78
79 #define SERVICE_WRITE \
80 (STANDARD_RIGHTS_WRITE | \
81 SERVICE_CHANGE_CONFIG)
82
83 #define SERVICE_EXECUTE \
84 (STANDARD_RIGHTS_EXECUTE | \
85 SERVICE_USER_DEFINED_CONTROL | \
86 SERVICE_PAUSE_CONTINUE | \
87 SERVICE_STOP | \
88 SERVICE_START)
89
90
91 /* VARIABLES ***************************************************************/
92
93 static GENERIC_MAPPING
94 ScmManagerMapping = {SC_MANAGER_READ,
95 SC_MANAGER_WRITE,
96 SC_MANAGER_EXECUTE,
97 SC_MANAGER_ALL_ACCESS};
98
99 static GENERIC_MAPPING
100 ScmServiceMapping = {SERVICE_READ,
101 SERVICE_WRITE,
102 SERVICE_EXECUTE,
103 SC_MANAGER_ALL_ACCESS};
104
105
106 /* FUNCTIONS ***************************************************************/
107
108 VOID
109 ScmStartRpcServer(VOID)
110 {
111 RPC_STATUS Status;
112
113 DPRINT("ScmStartRpcServer() called");
114
115 Status = RpcServerUseProtseqEp(L"ncacn_np",
116 10,
117 L"\\pipe\\ntsvcs",
118 NULL);
119 if (Status != RPC_S_OK)
120 {
121 DPRINT1("RpcServerUseProtseqEp() failed (Status %lx)\n", Status);
122 return;
123 }
124
125 Status = RpcServerRegisterIf(svcctl_ServerIfHandle,
126 NULL,
127 NULL);
128 if (Status != RPC_S_OK)
129 {
130 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
131 return;
132 }
133
134 Status = RpcServerListen(1, 20, TRUE);
135 if (Status != RPC_S_OK)
136 {
137 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
138 return;
139 }
140
141 DPRINT("ScmStartRpcServer() done");
142 }
143
144
145 static DWORD
146 ScmCreateManagerHandle(LPWSTR lpDatabaseName,
147 SC_HANDLE *Handle)
148 {
149 PMANAGER_HANDLE Ptr;
150
151 Ptr = GlobalAlloc(GPTR,
152 sizeof(MANAGER_HANDLE) + wcslen(lpDatabaseName) * sizeof(WCHAR));
153 if (Ptr == NULL)
154 return ERROR_NOT_ENOUGH_MEMORY;
155
156 Ptr->Handle.Tag = MANAGER_TAG;
157 Ptr->Handle.RefCount = 1;
158
159 /* FIXME: initialize more data here */
160
161 wcscpy(Ptr->DatabaseName, lpDatabaseName);
162
163 *Handle = (SC_HANDLE)Ptr;
164
165 return ERROR_SUCCESS;
166 }
167
168
169 static DWORD
170 ScmCreateServiceHandle(PSERVICE lpServiceEntry,
171 SC_HANDLE *Handle)
172 {
173 PSERVICE_HANDLE Ptr;
174
175 Ptr = GlobalAlloc(GPTR,
176 sizeof(SERVICE_HANDLE));
177 if (Ptr == NULL)
178 return ERROR_NOT_ENOUGH_MEMORY;
179
180 Ptr->Handle.Tag = SERVICE_TAG;
181 Ptr->Handle.RefCount = 1;
182
183 /* FIXME: initialize more data here */
184 Ptr->ServiceEntry = lpServiceEntry;
185
186 *Handle = (SC_HANDLE)Ptr;
187
188 return ERROR_SUCCESS;
189 }
190
191
192 static DWORD
193 ScmCheckAccess(SC_HANDLE Handle,
194 DWORD dwDesiredAccess)
195 {
196 PMANAGER_HANDLE hMgr;
197
198 hMgr = (PMANAGER_HANDLE)Handle;
199 if (hMgr->Handle.Tag == MANAGER_TAG)
200 {
201 RtlMapGenericMask(&dwDesiredAccess,
202 &ScmManagerMapping);
203
204 hMgr->Handle.DesiredAccess = dwDesiredAccess;
205
206 return ERROR_SUCCESS;
207 }
208 else if (hMgr->Handle.Tag == SERVICE_TAG)
209 {
210 RtlMapGenericMask(&dwDesiredAccess,
211 &ScmServiceMapping);
212
213 hMgr->Handle.DesiredAccess = dwDesiredAccess;
214
215 return ERROR_SUCCESS;
216 }
217
218 return ERROR_INVALID_HANDLE;
219 }
220
221
222 /* Function 0 */
223 unsigned long
224 ScmrCloseServiceHandle(handle_t BindingHandle,
225 unsigned int hScObject)
226 {
227 PMANAGER_HANDLE hManager;
228
229 DPRINT("ScmrCloseServiceHandle() called\n");
230
231 DPRINT("hScObject = %X\n", hScObject);
232
233 if (hScObject == 0)
234 return ERROR_INVALID_HANDLE;
235
236 hManager = (PMANAGER_HANDLE)hScObject;
237 if (hManager->Handle.Tag == MANAGER_TAG)
238 {
239 DPRINT("Found manager handle\n");
240
241 hManager->Handle.RefCount--;
242 if (hManager->Handle.RefCount == 0)
243 {
244 /* FIXME: add cleanup code */
245
246 GlobalFree(hManager);
247 }
248
249 DPRINT("ScmrCloseServiceHandle() done\n");
250 return ERROR_SUCCESS;
251 }
252 else if (hManager->Handle.Tag == SERVICE_TAG)
253 {
254 DPRINT("Found service handle\n");
255
256 hManager->Handle.RefCount--;
257 if (hManager->Handle.RefCount == 0)
258 {
259 /* FIXME: add cleanup code */
260
261 GlobalFree(hManager);
262 }
263
264 DPRINT("ScmrCloseServiceHandle() done\n");
265 return ERROR_SUCCESS;
266 }
267
268 DPRINT1("Invalid handle tag (Tag %lx)\n", hManager->Handle.Tag);
269
270 return ERROR_INVALID_HANDLE;
271 }
272
273
274 /* Function 1 */
275 unsigned long
276 ScmrControlService(handle_t BindingHandle,
277 unsigned int hService,
278 unsigned long dwControl,
279 LPSERVICE_STATUS lpServiceStatus)
280 {
281 PSERVICE_HANDLE hSvc;
282 PSERVICE lpService;
283
284 DPRINT1("ScmrControlService() called\n");
285
286 hSvc = (PSERVICE_HANDLE)hService;
287 if (hSvc->Handle.Tag != SERVICE_TAG)
288 {
289 DPRINT1("Invalid handle tag!\n");
290 return ERROR_INVALID_HANDLE;
291 }
292
293
294 /* FIXME: Check access rights */
295
296
297 lpService = hSvc->ServiceEntry;
298 if (lpService == NULL)
299 {
300 DPRINT1("lpService == NULL!\n");
301 return ERROR_INVALID_HANDLE;
302 }
303
304
305 /* FIXME: Send control code to the service */
306
307
308 /* Return service status information */
309 lpServiceStatus->dwServiceType = lpService->Type;
310 lpServiceStatus->dwCurrentState = lpService->CurrentState;
311 lpServiceStatus->dwControlsAccepted = lpService->ControlsAccepted;
312 lpServiceStatus->dwWin32ExitCode = lpService->Win32ExitCode;
313 lpServiceStatus->dwServiceSpecificExitCode = lpService->ServiceSpecificExitCode;
314 lpServiceStatus->dwCheckPoint = lpService->CheckPoint;
315 lpServiceStatus->dwWaitHint = lpService->WaitHint;
316
317 return ERROR_SUCCESS;
318 }
319
320
321 /* Function 2 */
322 unsigned long
323 ScmrDeleteService(handle_t BindingHandle,
324 unsigned int hService)
325 {
326 PSERVICE_HANDLE hSvc;
327 PSERVICE lpService;
328
329 DPRINT1("ScmrDeleteService() called\n");
330
331 hSvc = (PSERVICE_HANDLE)hService;
332 if (hSvc->Handle.Tag != SERVICE_TAG)
333 return ERROR_INVALID_HANDLE;
334
335 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
336 STANDARD_RIGHTS_REQUIRED))
337 return ERROR_ACCESS_DENIED;
338
339 lpService = hSvc->ServiceEntry;
340 if (lpService == NULL)
341 {
342 DPRINT1("lpService == NULL!\n");
343 return ERROR_INVALID_HANDLE;
344 }
345
346 /* FIXME: Mark service for delete */
347
348 return ERROR_SUCCESS;
349 }
350
351
352 /* Function 3 */
353 unsigned long
354 ScmrLockServiceDatabase(handle_t BindingHandle,
355 unsigned int hSCManager,
356 unsigned int *hLock)
357 {
358 PMANAGER_HANDLE hMgr;
359
360 DPRINT("ScmrLockServiceDatabase() called\n");
361
362 *hLock = 0;
363
364 hMgr = (PMANAGER_HANDLE)hSCManager;
365 if (hMgr->Handle.Tag != MANAGER_TAG)
366 return ERROR_INVALID_HANDLE;
367
368 if (!RtlAreAllAccessesGranted(hMgr->Handle.DesiredAccess,
369 SC_MANAGER_LOCK))
370 return ERROR_ACCESS_DENIED;
371
372 /* FIXME: Lock the database */
373 *hLock = 0x12345678; /* Dummy! */
374
375 return ERROR_SUCCESS;
376 }
377
378
379 /* Function 4 */
380 unsigned long
381 ScmrQueryServiceObjectSecurity(handle_t BindingHandle)
382 {
383 DPRINT1("ScmrQueryServiceSecurity() is unimplemented\n");
384 return ERROR_CALL_NOT_IMPLEMENTED;
385 }
386
387
388 /* Function 5 */
389 unsigned long
390 ScmrSetServiceObjectSecurity(handle_t BindingHandle)
391 {
392 DPRINT1("ScmrSetServiceSecurity() is unimplemented\n");
393 return ERROR_CALL_NOT_IMPLEMENTED;
394 }
395
396
397 /* Function 6 */
398 unsigned long
399 ScmrQueryServiceStatus(handle_t BindingHandle,
400 unsigned int hService,
401 LPSERVICE_STATUS lpServiceStatus)
402 {
403 PSERVICE_HANDLE hSvc;
404 PSERVICE lpService;
405
406 DPRINT("ScmrQueryServiceStatus() called\n");
407
408 hSvc = (PSERVICE_HANDLE)hService;
409 if (hSvc->Handle.Tag != SERVICE_TAG)
410 {
411 DPRINT1("Invalid handle tag!\n");
412 return ERROR_INVALID_HANDLE;
413 }
414
415 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
416 SERVICE_QUERY_STATUS))
417 {
418 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
419 return ERROR_ACCESS_DENIED;
420 }
421
422 lpService = hSvc->ServiceEntry;
423 if (lpService == NULL)
424 {
425 DPRINT1("lpService == NULL!\n");
426 return ERROR_INVALID_HANDLE;
427 }
428
429 /* Return service status information */
430 lpServiceStatus->dwServiceType = lpService->Type;
431 lpServiceStatus->dwCurrentState = lpService->CurrentState;
432 lpServiceStatus->dwControlsAccepted = lpService->ControlsAccepted;
433 lpServiceStatus->dwWin32ExitCode = lpService->Win32ExitCode;
434 lpServiceStatus->dwServiceSpecificExitCode = lpService->ServiceSpecificExitCode;
435 lpServiceStatus->dwCheckPoint = lpService->CheckPoint;
436 lpServiceStatus->dwWaitHint = lpService->WaitHint;
437
438 return ERROR_SUCCESS;
439 }
440
441
442 /* Function 7 */
443 unsigned long
444 ScmrSetServiceStatus(handle_t BindingHandle)
445 {
446 DPRINT1("ScmrSetServiceStatus() is unimplemented\n");
447 /* FIXME */
448 return ERROR_CALL_NOT_IMPLEMENTED;
449 }
450
451
452 /* Function 8 */
453 unsigned long
454 ScmrUnlockServiceDatabase(handle_t BindingHandle,
455 unsigned int hLock)
456 {
457 DPRINT1("ScmrUnlockServiceDatabase() called\n");
458 /* FIXME */
459 return ERROR_SUCCESS;
460 }
461
462
463 /* Function 9 */
464 unsigned long
465 ScmrNotifyBootConfigStatus(handle_t BindingHandle,
466 unsigned long BootAcceptable)
467 {
468 DPRINT1("ScmrNotifyBootConfigStatus() called\n");
469 /* FIXME */
470 return ERROR_SUCCESS;
471 }
472
473
474
475 /* Function 12 */
476 #if 0
477 unsigned long
478 ScmrCreateServiceW(handle_t BindingHandle,
479 unsigned int hSCManager,
480 wchar_t *lpServiceName,
481 wchar_t *lpDisplayName,
482 unsigned long dwDesiredAccess,
483 unsigned long dwServiceType,
484 unsigned long dwStartType,
485 unsigned long dwErrorControl,
486 wchar_t *lpBinaryPathName,
487 wchar_t *lpLoadOrderGroup,
488 unsigned long *lpdwTagId,
489 wchar_t *lpDependencies,
490 wchar_t *lpServiceStartName,
491 wchar_t *lpPassword)
492 {
493 DPRINT1("ScmrCreateServiceW() called\n");
494 if (lpdwTagId != NULL)
495 *lpdwTagId = 0;
496 return ERROR_SUCCESS;
497 }
498 #endif
499
500
501 /* Function 15 */
502 unsigned long
503 ScmrOpenSCManagerW(handle_t BindingHandle,
504 wchar_t *lpMachineName,
505 wchar_t *lpDatabaseName,
506 unsigned long dwDesiredAccess,
507 unsigned int *hScm)
508 {
509 DWORD dwError;
510 SC_HANDLE hHandle;
511
512 DPRINT("ScmrOpenSCManagerW() called\n");
513 DPRINT("lpMachineName = %p\n", lpMachineName);
514 DPRINT("lpMachineName: %S\n", lpMachineName);
515 DPRINT("lpDataBaseName = %p\n", lpDatabaseName);
516 DPRINT("lpDataBaseName: %S\n", lpDatabaseName);
517 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
518
519 dwError = ScmCreateManagerHandle(lpDatabaseName,
520 &hHandle);
521 if (dwError != ERROR_SUCCESS)
522 {
523 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError);
524 return dwError;
525 }
526
527 /* Check the desired access */
528 dwError = ScmCheckAccess(hHandle,
529 dwDesiredAccess | SC_MANAGER_CONNECT);
530 if (dwError != ERROR_SUCCESS)
531 {
532 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError);
533 GlobalFree(hHandle);
534 return dwError;
535 }
536
537 *hScm = (unsigned int)hHandle;
538 DPRINT("*hScm = %x\n", *hScm);
539
540 DPRINT("ScmrOpenSCManagerW() done\n");
541
542 return ERROR_SUCCESS;
543 }
544
545
546 /* Function 16 */
547 unsigned int
548 ScmrOpenServiceW(handle_t BindingHandle,
549 unsigned int hSCManager,
550 wchar_t *lpServiceName,
551 unsigned long dwDesiredAccess,
552 unsigned int *hService)
553 {
554 UNICODE_STRING ServiceName;
555 PSERVICE lpService;
556 PMANAGER_HANDLE hManager;
557 SC_HANDLE hHandle;
558 DWORD dwError;
559
560 DPRINT("ScmrOpenServiceW() called\n");
561 DPRINT("hSCManager = %x\n", hSCManager);
562 DPRINT("lpServiceName = %p\n", lpServiceName);
563 DPRINT("lpServiceName: %S\n", lpServiceName);
564 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
565
566 hManager = (PMANAGER_HANDLE)hSCManager;
567 if (hManager->Handle.Tag != MANAGER_TAG)
568 {
569 DPRINT1("Invalid manager handle!\n");
570 return ERROR_INVALID_HANDLE;
571 }
572
573 /* FIXME: Lock the service list */
574
575 /* Get service database entry */
576 RtlInitUnicodeString(&ServiceName,
577 lpServiceName);
578
579 lpService = ScmGetServiceEntryByName(&ServiceName);
580 if (lpService == NULL)
581 {
582 DPRINT1("Could not find a service!\n");
583 return ERROR_SERVICE_DOES_NOT_EXIST;
584 }
585
586 /* Create a service handle */
587 dwError = ScmCreateServiceHandle(lpService,
588 &hHandle);
589 if (dwError != ERROR_SUCCESS)
590 {
591 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError);
592 return dwError;
593 }
594
595 /* Check the desired access */
596 dwError = ScmCheckAccess(hHandle,
597 dwDesiredAccess);
598 if (dwError != ERROR_SUCCESS)
599 {
600 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError);
601 GlobalFree(hHandle);
602 return dwError;
603 }
604
605 *hService = (unsigned int)hHandle;
606 DPRINT("*hService = %x\n", *hService);
607
608 DPRINT("ScmrOpenServiceW() done\n");
609
610 return ERROR_SUCCESS;
611 }
612
613
614
615 /* Function 27 */
616 unsigned long
617 ScmrOpenSCManagerA(handle_t BindingHandle,
618 char *lpMachineName,
619 char *lpDatabaseName,
620 unsigned long dwDesiredAccess,
621 unsigned int *hScm)
622 {
623 UNICODE_STRING MachineName;
624 UNICODE_STRING DatabaseName;
625 DWORD dwError;
626
627 DPRINT("ScmrOpenSCManagerA() called\n");
628
629 if (lpMachineName)
630 RtlCreateUnicodeStringFromAsciiz(&MachineName,
631 lpMachineName);
632
633 if (lpDatabaseName)
634 RtlCreateUnicodeStringFromAsciiz(&DatabaseName,
635 lpDatabaseName);
636
637 dwError = ScmrOpenSCManagerW(BindingHandle,
638 lpMachineName ? MachineName.Buffer : NULL,
639 lpDatabaseName ? DatabaseName.Buffer : NULL,
640 dwDesiredAccess,
641 hScm);
642
643 if (lpMachineName)
644 RtlFreeUnicodeString(&MachineName);
645
646 if (lpDatabaseName)
647 RtlFreeUnicodeString(&DatabaseName);
648
649 return dwError;
650 }
651
652
653 /* Function 28 */
654 unsigned int
655 ScmrOpenServiceA(handle_t BindingHandle,
656 unsigned int hSCManager,
657 char *lpServiceName,
658 unsigned long dwDesiredAccess,
659 unsigned int *hService)
660 {
661 UNICODE_STRING ServiceName;
662 DWORD dwError;
663
664 DPRINT("ScmrOpenServiceA() called\n");
665
666 RtlCreateUnicodeStringFromAsciiz(&ServiceName,
667 lpServiceName);
668
669 dwError = ScmrOpenServiceW(BindingHandle,
670 hSCManager,
671 ServiceName.Buffer,
672 dwDesiredAccess,
673 hService);
674
675 RtlFreeUnicodeString(&ServiceName);
676
677 return dwError;
678 }
679
680
681
682 void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
683 {
684 return GlobalAlloc(GPTR, len);
685 }
686
687
688 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
689 {
690 GlobalFree(ptr);
691 }
692
693 /* EOF */