ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

sctrl.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:     ReactOS advapi32
00003  * LICENSE:     GPL - See COPYING in the top level directory
00004  * FILE:        dll/win32/advapi32/service/sctrl.c
00005  * PURPOSE:     Service control manager functions
00006  * COPYRIGHT:   Copyright 1999 Emanuele Aliberti
00007  *              Copyright 2007 Ged Murphy <gedmurphy@reactos.org>
00008  *                             Gregor Brunmar <gregor.brunmar@home.se>
00009  *
00010  */
00011 
00012 
00013 /* INCLUDES ******************************************************************/
00014 
00015 #include <advapi32.h>
00016 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
00017 
00018 
00019 /* TYPES *********************************************************************/
00020 
00021 typedef struct _SERVICE_THREAD_PARAMSA
00022 {
00023     LPSERVICE_MAIN_FUNCTIONA lpServiceMain;
00024     DWORD dwArgCount;
00025     LPSTR *lpArgVector;
00026 } SERVICE_THREAD_PARAMSA, *PSERVICE_THREAD_PARAMSA;
00027 
00028 
00029 typedef struct _SERVICE_THREAD_PARAMSW
00030 {
00031     LPSERVICE_MAIN_FUNCTIONW lpServiceMain;
00032     DWORD dwArgCount;
00033     LPWSTR *lpArgVector;
00034 } SERVICE_THREAD_PARAMSW, *PSERVICE_THREAD_PARAMSW;
00035 
00036 
00037 typedef struct _ACTIVE_SERVICE
00038 {
00039     SERVICE_STATUS_HANDLE hServiceStatus;
00040     UNICODE_STRING ServiceName;
00041     union
00042     {
00043         SERVICE_THREAD_PARAMSA A;
00044         SERVICE_THREAD_PARAMSW W;
00045     } ThreadParams;
00046     LPHANDLER_FUNCTION HandlerFunction;
00047     LPHANDLER_FUNCTION_EX HandlerFunctionEx;
00048     LPVOID HandlerContext;
00049     BOOL bUnicode;
00050 } ACTIVE_SERVICE, *PACTIVE_SERVICE;
00051 
00052 
00053 /* GLOBALS *******************************************************************/
00054 
00055 static DWORD dwActiveServiceCount = 0;
00056 static PACTIVE_SERVICE lpActiveServices = NULL;
00057 static handle_t hStatusBinding = NULL;
00058 
00059 
00060 /* FUNCTIONS *****************************************************************/
00061 
00062 handle_t __RPC_USER
00063 RPC_SERVICE_STATUS_HANDLE_bind(RPC_SERVICE_STATUS_HANDLE hServiceStatus)
00064 {
00065     return hStatusBinding;
00066 }
00067 
00068 
00069 void __RPC_USER
00070 RPC_SERVICE_STATUS_HANDLE_unbind(RPC_SERVICE_STATUS_HANDLE hServiceStatus,
00071                                  handle_t hBinding)
00072 {
00073 }
00074 
00075 
00076 static RPC_STATUS
00077 ScCreateStatusBinding(VOID)
00078 {
00079     LPWSTR pszStringBinding;
00080     RPC_STATUS status;
00081 
00082     TRACE("ScCreateStatusBinding() called\n");
00083 
00084     status = RpcStringBindingComposeW(NULL,
00085                                       L"ncacn_np",
00086                                       NULL,
00087                                       L"\\pipe\\ntsvcs",
00088                                       NULL,
00089                                       &pszStringBinding);
00090     if (status != RPC_S_OK)
00091     {
00092         ERR("RpcStringBindingCompose returned 0x%x\n", status);
00093         return status;
00094     }
00095 
00096     /* Set the binding handle that will be used to bind to the server. */
00097     status = RpcBindingFromStringBindingW(pszStringBinding,
00098                                           &hStatusBinding);
00099     if (status != RPC_S_OK)
00100     {
00101         ERR("RpcBindingFromStringBinding returned 0x%x\n", status);
00102     }
00103 
00104     status = RpcStringFreeW(&pszStringBinding);
00105     if (status != RPC_S_OK)
00106     {
00107         ERR("RpcStringFree returned 0x%x\n", status);
00108     }
00109 
00110     return status;
00111 }
00112 
00113 
00114 static RPC_STATUS
00115 ScDestroyStatusBinding(VOID)
00116 {
00117     RPC_STATUS status;
00118 
00119     TRACE("ScDestroyStatusBinding() called\n");
00120 
00121     if (hStatusBinding == NULL)
00122         return RPC_S_OK;
00123 
00124     status = RpcBindingFree(&hStatusBinding);
00125     if (status != RPC_S_OK)
00126     {
00127         ERR("RpcBindingFree returned 0x%x\n", status);
00128     }
00129     else
00130     {
00131         hStatusBinding = NULL;
00132     }
00133 
00134     return status;
00135 }
00136 
00137 
00138 static PACTIVE_SERVICE
00139 ScLookupServiceByServiceName(LPCWSTR lpServiceName)
00140 {
00141     DWORD i;
00142 
00143     TRACE("ScLookupServiceByServiceName(%S) called\n", lpServiceName);
00144 
00145     for (i = 0; i < dwActiveServiceCount; i++)
00146     {
00147         TRACE("Checking %S\n", lpActiveServices[i].ServiceName.Buffer);
00148         if (_wcsicmp(lpActiveServices[i].ServiceName.Buffer, lpServiceName) == 0)
00149         {
00150             TRACE("Found!\n");
00151             return &lpActiveServices[i];
00152         }
00153     }
00154 
00155     TRACE("No service found!\n");
00156 
00157     SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
00158 
00159     return NULL;
00160 }
00161 
00162 
00163 static DWORD WINAPI
00164 ScServiceMainStub(LPVOID Context)
00165 {
00166     PACTIVE_SERVICE lpService = (PACTIVE_SERVICE)Context;
00167 
00168     TRACE("ScServiceMainStub() called\n");
00169 
00170     /* Call the main service routine and free the arguments vector */
00171     if (lpService->bUnicode)
00172     {
00173         (lpService->ThreadParams.W.lpServiceMain)(lpService->ThreadParams.W.dwArgCount,
00174                                                   lpService->ThreadParams.W.lpArgVector);
00175 
00176         if (lpService->ThreadParams.A.lpArgVector != NULL)
00177         {
00178             HeapFree(GetProcessHeap(),
00179                      0,
00180                      lpService->ThreadParams.W.lpArgVector);
00181 
00182             lpService->ThreadParams.W.lpArgVector = NULL;
00183             lpService->ThreadParams.W.dwArgCount = 0;
00184         }
00185     }
00186     else
00187     {
00188         (lpService->ThreadParams.A.lpServiceMain)(lpService->ThreadParams.A.dwArgCount,
00189                                                   lpService->ThreadParams.A.lpArgVector);
00190 
00191         if (lpService->ThreadParams.A.lpArgVector != NULL)
00192         {
00193             HeapFree(GetProcessHeap(),
00194                      0,
00195                      lpService->ThreadParams.A.lpArgVector);
00196 
00197             lpService->ThreadParams.A.lpArgVector = NULL;
00198             lpService->ThreadParams.A.dwArgCount = 0;
00199         }
00200     }
00201 
00202     return ERROR_SUCCESS;
00203 }
00204 
00205 
00206 static DWORD
00207 ScConnectControlPipe(HANDLE *hPipe)
00208 {
00209     DWORD dwBytesWritten;
00210     DWORD dwState;
00211     DWORD dwServiceCurrent = 0;
00212     NTSTATUS Status;
00213     WCHAR NtControlPipeName[MAX_PATH + 1];
00214     RTL_QUERY_REGISTRY_TABLE QueryTable[2];
00215     DWORD dwProcessId;
00216 
00217     /* Get the service number and create the named pipe */
00218     RtlZeroMemory(&QueryTable,
00219                   sizeof(QueryTable));
00220 
00221     QueryTable[0].Name = L"";
00222     QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
00223     QueryTable[0].EntryContext = &dwServiceCurrent;
00224 
00225     Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
00226                                     L"ServiceCurrent",
00227                                     QueryTable,
00228                                     NULL,
00229                                     NULL);
00230 
00231     if (!NT_SUCCESS(Status))
00232     {
00233         ERR("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
00234         return RtlNtStatusToDosError(Status);
00235     }
00236 
00237     swprintf(NtControlPipeName, L"\\\\.\\pipe\\net\\NtControlPipe%u", dwServiceCurrent);
00238 
00239     if (!WaitNamedPipeW(NtControlPipeName, 15000))
00240     {
00241         ERR("WaitNamedPipe(%S) failed (Error %lu)\n", NtControlPipeName, GetLastError());
00242         return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
00243     }
00244 
00245     *hPipe = CreateFileW(NtControlPipeName,
00246                          GENERIC_READ | GENERIC_WRITE,
00247                          0,
00248                          NULL,
00249                          OPEN_EXISTING,
00250                          FILE_ATTRIBUTE_NORMAL,
00251                          NULL);
00252     if (*hPipe == INVALID_HANDLE_VALUE)
00253     {
00254         ERR("CreateFileW() failed for pipe %S (Error %lu)\n", NtControlPipeName, GetLastError());
00255         return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
00256     }
00257 
00258     dwState = PIPE_READMODE_MESSAGE;
00259     if (!SetNamedPipeHandleState(*hPipe, &dwState, NULL, NULL))
00260     {
00261         CloseHandle(*hPipe);
00262         *hPipe = INVALID_HANDLE_VALUE;
00263         return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
00264     }
00265 
00266     /* Pass the ProcessId to the SCM */
00267     dwProcessId = GetCurrentProcessId();
00268     WriteFile(*hPipe,
00269               &dwProcessId,
00270               sizeof(DWORD),
00271               &dwBytesWritten,
00272               NULL);
00273 
00274     TRACE("Sent Process ID %lu\n", dwProcessId);
00275 
00276     return ERROR_SUCCESS;
00277 }
00278 
00279 
00280 static DWORD
00281 ScBuildUnicodeArgsVector(PSCM_CONTROL_PACKET ControlPacket,
00282                          LPDWORD lpArgCount,
00283                          LPWSTR **lpArgVector)
00284 {
00285     LPWSTR *lpVector;
00286     LPWSTR *lpArg;
00287     DWORD i;
00288 
00289     *lpArgCount = 0;
00290     *lpArgVector = NULL;
00291 
00292     if (ControlPacket->dwArgumentsCount > 0)
00293     {
00294         lpVector = HeapAlloc(GetProcessHeap(),
00295                              HEAP_ZERO_MEMORY,
00296                              ControlPacket->dwSize - ControlPacket->dwArgumentsOffset);
00297         if (lpVector == NULL)
00298             return ERROR_OUTOFMEMORY;
00299 
00300         memcpy(lpVector,
00301                ((PBYTE)ControlPacket + ControlPacket->dwArgumentsOffset),
00302                ControlPacket->dwSize - ControlPacket->dwArgumentsOffset);
00303 
00304         lpArg = lpVector;
00305         for (i = 0; i < ControlPacket->dwArgumentsCount; i++)
00306         {
00307             *lpArg = (LPWSTR)((ULONG_PTR)lpArg + (ULONG_PTR)*lpArg);
00308             lpArg++;
00309         }
00310 
00311         *lpArgCount = ControlPacket->dwArgumentsCount;
00312         *lpArgVector = lpVector;
00313     }
00314 
00315     return ERROR_SUCCESS;
00316 }
00317 
00318 
00319 static DWORD
00320 ScBuildAnsiArgsVector(PSCM_CONTROL_PACKET ControlPacket,
00321                       LPDWORD lpArgCount,
00322                       LPSTR **lpArgVector)
00323 {
00324     LPSTR *lpVector;
00325     LPSTR *lpPtr;
00326     LPWSTR lpUnicodeString;
00327     LPSTR lpAnsiString;
00328     DWORD dwVectorSize;
00329     DWORD dwUnicodeSize;
00330     DWORD dwAnsiSize;
00331     DWORD i;
00332 
00333     *lpArgCount = 0;
00334     *lpArgVector = NULL;
00335 
00336     if (ControlPacket->dwArgumentsCount > 0)
00337     {
00338         dwVectorSize = ControlPacket->dwArgumentsCount * sizeof(LPWSTR);
00339 
00340         lpUnicodeString = (LPWSTR)((PBYTE)ControlPacket +
00341                                    ControlPacket->dwArgumentsOffset +
00342                                    dwVectorSize);
00343         dwUnicodeSize = (ControlPacket->dwSize -
00344                          ControlPacket->dwArgumentsOffset -
00345                          dwVectorSize) / sizeof(WCHAR);
00346 
00347         dwAnsiSize = WideCharToMultiByte(CP_ACP,
00348                                          0,
00349                                          lpUnicodeString,
00350                                          dwUnicodeSize,
00351                                          NULL,
00352                                          0,
00353                                          NULL,
00354                                          NULL);
00355 
00356         lpVector = HeapAlloc(GetProcessHeap(),
00357                              HEAP_ZERO_MEMORY,
00358                              dwVectorSize + dwAnsiSize);
00359         if (lpVector == NULL)
00360             return ERROR_OUTOFMEMORY;
00361 
00362         lpPtr = (LPSTR*)lpVector;
00363         lpAnsiString = (LPSTR)((ULONG_PTR)lpVector + dwVectorSize);
00364 
00365         WideCharToMultiByte(CP_ACP,
00366                             0,
00367                             lpUnicodeString,
00368                             dwUnicodeSize,
00369                             lpAnsiString,
00370                             dwAnsiSize,
00371                             NULL,
00372                             NULL);
00373 
00374         for (i = 0; i < ControlPacket->dwArgumentsCount; i++)
00375         {
00376             *lpPtr = lpAnsiString;
00377 
00378             lpPtr++;
00379             lpAnsiString += (strlen(lpAnsiString) + 1);
00380         }
00381 
00382         *lpArgCount = ControlPacket->dwArgumentsCount;
00383         *lpArgVector = lpVector;
00384     }
00385 
00386     return ERROR_SUCCESS;
00387 }
00388 
00389 
00390 static DWORD
00391 ScStartService(PACTIVE_SERVICE lpService,
00392                PSCM_CONTROL_PACKET ControlPacket)
00393 {
00394     HANDLE ThreadHandle;
00395     DWORD ThreadId;
00396     DWORD dwError;
00397 
00398     TRACE("ScStartService() called\n");
00399     TRACE("Size: %lu\n", ControlPacket->dwSize);
00400     TRACE("Service: %S\n", (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset));
00401 
00402     /* Set the service status handle */
00403     lpService->hServiceStatus = ControlPacket->hServiceStatus;
00404 
00405     /* Build the arguments vector */
00406     if (lpService->bUnicode == TRUE)
00407     {
00408         dwError = ScBuildUnicodeArgsVector(ControlPacket,
00409                                            &lpService->ThreadParams.W.dwArgCount,
00410                                            &lpService->ThreadParams.W.lpArgVector);
00411     }
00412     else
00413     {
00414         dwError = ScBuildAnsiArgsVector(ControlPacket,
00415                                         &lpService->ThreadParams.A.dwArgCount,
00416                                         &lpService->ThreadParams.A.lpArgVector);
00417     }
00418 
00419     if (dwError != ERROR_SUCCESS)
00420         return dwError;
00421 
00422     /* Invoke the services entry point and implement the command loop */
00423     ThreadHandle = CreateThread(NULL,
00424                                 0,
00425                                 ScServiceMainStub,
00426                                 lpService,
00427                                 CREATE_SUSPENDED,
00428                                 &ThreadId);
00429     if (ThreadHandle == NULL)
00430     {
00431         /* Free the arguments vector */
00432         if (lpService->bUnicode)
00433         {
00434             if (lpService->ThreadParams.W.lpArgVector != NULL)
00435             {
00436                 HeapFree(GetProcessHeap(),
00437                          0,
00438                          lpService->ThreadParams.W.lpArgVector);
00439                 lpService->ThreadParams.W.lpArgVector = NULL;
00440                 lpService->ThreadParams.W.dwArgCount = 0;
00441             }
00442         }
00443         else
00444         {
00445             if (lpService->ThreadParams.A.lpArgVector != NULL)
00446             {
00447                 HeapFree(GetProcessHeap(),
00448                          0,
00449                          lpService->ThreadParams.A.lpArgVector);
00450                 lpService->ThreadParams.A.lpArgVector = NULL;
00451                 lpService->ThreadParams.A.dwArgCount = 0;
00452             }
00453         }
00454 
00455         return ERROR_SERVICE_NO_THREAD;
00456     }
00457 
00458     ResumeThread(ThreadHandle);
00459     CloseHandle(ThreadHandle);
00460 
00461     return ERROR_SUCCESS;
00462 }
00463 
00464 
00465 static DWORD
00466 ScControlService(PACTIVE_SERVICE lpService,
00467                  PSCM_CONTROL_PACKET ControlPacket)
00468 {
00469     TRACE("ScControlService() called\n");
00470     TRACE("Size: %lu\n", ControlPacket->dwSize);
00471     TRACE("Service: %S\n", (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset));
00472 
00473     if (lpService->HandlerFunction)
00474     {
00475         (lpService->HandlerFunction)(ControlPacket->dwControl);
00476     }
00477     else if (lpService->HandlerFunctionEx)
00478     {
00479         /* FIXME: send correct params */
00480         (lpService->HandlerFunctionEx)(ControlPacket->dwControl, 0, NULL, NULL);
00481     }
00482 
00483     TRACE("ScControlService() done\n");
00484 
00485     return ERROR_SUCCESS;
00486 }
00487 
00488 
00489 static BOOL
00490 ScServiceDispatcher(HANDLE hPipe,
00491                     PUCHAR lpBuffer,
00492                     DWORD dwBufferSize)
00493 {
00494     PSCM_CONTROL_PACKET ControlPacket;
00495     DWORD Count;
00496     BOOL bResult;
00497     DWORD dwRunningServices = 0;
00498     LPWSTR lpServiceName;
00499     PACTIVE_SERVICE lpService;
00500     SCM_REPLY_PACKET ReplyPacket;
00501     DWORD dwError;
00502 
00503     TRACE("ScDispatcherLoop() called\n");
00504 
00505     ControlPacket = HeapAlloc(GetProcessHeap(),
00506                               HEAP_ZERO_MEMORY,
00507                               1024);
00508     if (ControlPacket == NULL)
00509         return FALSE;
00510 
00511     while (TRUE)
00512     {
00513         /* Read command from the control pipe */
00514         bResult = ReadFile(hPipe,
00515                            ControlPacket,
00516                            1024,
00517                            &Count,
00518                            NULL);
00519         if (bResult == FALSE)
00520         {
00521             ERR("Pipe read failed (Error: %lu)\n", GetLastError());
00522             return FALSE;
00523         }
00524 
00525         lpServiceName = (LPWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
00526         TRACE("Service: %S\n", lpServiceName);
00527 
00528         lpService = ScLookupServiceByServiceName(lpServiceName);
00529         if (lpService != NULL)
00530         {
00531             /* Execute command */
00532             switch (ControlPacket->dwControl)
00533             {
00534                 case SERVICE_CONTROL_START:
00535                     TRACE("Start command - recieved SERVICE_CONTROL_START\n");
00536                     dwError = ScStartService(lpService, ControlPacket);
00537                     if (dwError == ERROR_SUCCESS)
00538                         dwRunningServices++;
00539                     break;
00540 
00541                 case SERVICE_CONTROL_STOP:
00542                     TRACE("Stop command - recieved SERVICE_CONTROL_STOP\n");
00543                     dwError = ScControlService(lpService, ControlPacket);
00544                     if (dwError == ERROR_SUCCESS)
00545                         dwRunningServices--;
00546                     break;
00547 
00548                 default:
00549                     TRACE("Command %lu received", ControlPacket->dwControl);
00550                     dwError = ScControlService(lpService, ControlPacket);
00551                     break;
00552             }
00553         }
00554         else
00555         {
00556             dwError = ERROR_SERVICE_DOES_NOT_EXIST;
00557         }
00558 
00559         ReplyPacket.dwError = dwError;
00560 
00561         /* Send the reply packet */
00562         bResult = WriteFile(hPipe,
00563                             &ReplyPacket,
00564                             sizeof(ReplyPacket),
00565                             &Count,
00566                             NULL);
00567         if (bResult == FALSE)
00568         {
00569             ERR("Pipe write failed (Error: %lu)\n", GetLastError());
00570             return FALSE;
00571         }
00572 
00573         if (dwRunningServices == 0)
00574             break;
00575     }
00576 
00577     HeapFree(GetProcessHeap(),
00578              0,
00579              ControlPacket);
00580 
00581     return TRUE;
00582 }
00583 
00584 
00585 /**********************************************************************
00586  *  RegisterServiceCtrlHandlerA
00587  *
00588  * @implemented
00589  */
00590 SERVICE_STATUS_HANDLE WINAPI
00591 RegisterServiceCtrlHandlerA(LPCSTR lpServiceName,
00592                             LPHANDLER_FUNCTION lpHandlerProc)
00593 {
00594     ANSI_STRING ServiceNameA;
00595     UNICODE_STRING ServiceNameU;
00596     SERVICE_STATUS_HANDLE SHandle;
00597 
00598     RtlInitAnsiString(&ServiceNameA, (LPSTR)lpServiceName);
00599     if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE)))
00600     {
00601         SetLastError(ERROR_OUTOFMEMORY);
00602         return (SERVICE_STATUS_HANDLE)0;
00603     }
00604 
00605     SHandle = RegisterServiceCtrlHandlerW(ServiceNameU.Buffer,
00606                                           lpHandlerProc);
00607 
00608     RtlFreeUnicodeString(&ServiceNameU);
00609 
00610     return SHandle;
00611 }
00612 
00613 
00614 /**********************************************************************
00615  *  RegisterServiceCtrlHandlerW
00616  *
00617  * @implemented
00618  */
00619 SERVICE_STATUS_HANDLE WINAPI
00620 RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName,
00621                             LPHANDLER_FUNCTION lpHandlerProc)
00622 {
00623     PACTIVE_SERVICE Service;
00624 
00625     Service = ScLookupServiceByServiceName((LPWSTR)lpServiceName);
00626     if (Service == NULL)
00627     {
00628         return (SERVICE_STATUS_HANDLE)NULL;
00629     }
00630 
00631     Service->HandlerFunction = lpHandlerProc;
00632     Service->HandlerFunctionEx = NULL;
00633 
00634     TRACE("RegisterServiceCtrlHandler returning %lu\n", Service->hServiceStatus);
00635 
00636     return Service->hServiceStatus;
00637 }
00638 
00639 
00640 /**********************************************************************
00641  *  RegisterServiceCtrlHandlerExA
00642  *
00643  * @implemented
00644  */
00645 SERVICE_STATUS_HANDLE WINAPI
00646 RegisterServiceCtrlHandlerExA(LPCSTR lpServiceName,
00647                               LPHANDLER_FUNCTION_EX lpHandlerProc,
00648                               LPVOID lpContext)
00649 {
00650     ANSI_STRING ServiceNameA;
00651     UNICODE_STRING ServiceNameU;
00652     SERVICE_STATUS_HANDLE SHandle;
00653 
00654     RtlInitAnsiString(&ServiceNameA, (LPSTR)lpServiceName);
00655     if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE)))
00656     {
00657         SetLastError(ERROR_OUTOFMEMORY);
00658         return (SERVICE_STATUS_HANDLE)0;
00659     }
00660 
00661     SHandle = RegisterServiceCtrlHandlerExW(ServiceNameU.Buffer,
00662                                             lpHandlerProc,
00663                                             lpContext);
00664 
00665     RtlFreeUnicodeString(&ServiceNameU);
00666 
00667     return SHandle;
00668 }
00669 
00670 
00671 /**********************************************************************
00672  *  RegisterServiceCtrlHandlerExW
00673  *
00674  * @implemented
00675  */
00676 SERVICE_STATUS_HANDLE WINAPI
00677 RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName,
00678                               LPHANDLER_FUNCTION_EX lpHandlerProc,
00679                               LPVOID lpContext)
00680 {
00681     PACTIVE_SERVICE Service;
00682 
00683     Service = ScLookupServiceByServiceName(lpServiceName);
00684     if (Service == NULL)
00685     {
00686         return (SERVICE_STATUS_HANDLE)NULL;
00687     }
00688 
00689     Service->HandlerFunction = NULL;
00690     Service->HandlerFunctionEx = lpHandlerProc;
00691     Service->HandlerContext = lpContext;
00692 
00693     TRACE("RegisterServiceCtrlHandlerEx returning %lu\n", Service->hServiceStatus);
00694 
00695     return Service->hServiceStatus;
00696 }
00697 
00698 
00699 /**********************************************************************
00700  *  I_ScSetServiceBitsA
00701  *
00702  * Undocumented
00703  *
00704  * @implemented
00705  */
00706 BOOL WINAPI
00707 I_ScSetServiceBitsA(SERVICE_STATUS_HANDLE hServiceStatus,
00708                     DWORD dwServiceBits,
00709                     BOOL bSetBitsOn,
00710                     BOOL bUpdateImmediately,
00711                     LPSTR lpString)
00712 {
00713     BOOL bResult;
00714 
00715     RpcTryExcept
00716     {
00717         /* Call to services.exe using RPC */
00718         bResult = RI_ScSetServiceBitsA((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
00719                                        dwServiceBits,
00720                                        bSetBitsOn,
00721                                        bUpdateImmediately,
00722                                        lpString);
00723     }
00724     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
00725     {
00726         SetLastError(ScmRpcStatusToWinError(RpcExceptionCode()));
00727         bResult = FALSE;
00728     }
00729     RpcEndExcept;
00730 
00731     return bResult;
00732 }
00733 
00734 
00735 /**********************************************************************
00736  *  I_ScSetServiceBitsW
00737  *
00738  * Undocumented
00739  *
00740  * @implemented
00741  */
00742 BOOL WINAPI
00743 I_ScSetServiceBitsW(SERVICE_STATUS_HANDLE hServiceStatus,
00744                     DWORD dwServiceBits,
00745                     BOOL bSetBitsOn,
00746                     BOOL bUpdateImmediately,
00747                     LPWSTR lpString)
00748 {
00749     BOOL bResult;
00750 
00751     RpcTryExcept
00752     {
00753         /* Call to services.exe using RPC */
00754         bResult = RI_ScSetServiceBitsW((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
00755                                        dwServiceBits,
00756                                        bSetBitsOn,
00757                                        bUpdateImmediately,
00758                                        lpString);
00759     }
00760     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
00761     {
00762         SetLastError(ScmRpcStatusToWinError(RpcExceptionCode()));
00763         bResult = FALSE;
00764     }
00765     RpcEndExcept;
00766 
00767     return bResult;
00768 }
00769 
00770 
00771 /**********************************************************************
00772  *  SetServiceBits
00773  *
00774  * @implemented
00775  */
00776 BOOL WINAPI
00777 SetServiceBits(SERVICE_STATUS_HANDLE hServiceStatus,
00778                DWORD dwServiceBits,
00779                BOOL bSetBitsOn,
00780                BOOL bUpdateImmediately)
00781 {
00782     return I_ScSetServiceBitsW(hServiceStatus,
00783                                dwServiceBits,
00784                                bSetBitsOn,
00785                                bUpdateImmediately,
00786                                NULL);
00787 }
00788 
00789 
00790 /**********************************************************************
00791  *  SetServiceStatus
00792  *
00793  * @implemented
00794  */
00795 BOOL WINAPI
00796 SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus,
00797                  LPSERVICE_STATUS lpServiceStatus)
00798 {
00799     DWORD dwError;
00800 
00801     TRACE("SetServiceStatus() called\n");
00802     TRACE("hServiceStatus %lu\n", hServiceStatus);
00803 
00804     RpcTryExcept
00805     {
00806         /* Call to services.exe using RPC */
00807         dwError = RSetServiceStatus((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
00808                                     lpServiceStatus);
00809     }
00810     RpcExcept(EXCEPTION_EXECUTE_HANDLER)
00811     {
00812         dwError = ScmRpcStatusToWinError(RpcExceptionCode());
00813     }
00814     RpcEndExcept;
00815 
00816     if (dwError != ERROR_SUCCESS)
00817     {
00818         ERR("ScmrSetServiceStatus() failed (Error %lu)\n", dwError);
00819         SetLastError(dwError);
00820         return FALSE;
00821     }
00822 
00823     TRACE("SetServiceStatus() done (ret %lu)\n", dwError);
00824 
00825     return TRUE;
00826 }
00827 
00828 
00829 /**********************************************************************
00830  *  StartServiceCtrlDispatcherA
00831  *
00832  * @implemented
00833  */
00834 BOOL WINAPI
00835 StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA * lpServiceStartTable)
00836 {
00837     ULONG i;
00838     HANDLE hPipe;
00839     DWORD dwError;
00840     PUCHAR lpMessageBuffer;
00841 
00842     TRACE("StartServiceCtrlDispatcherA() called\n");
00843 
00844     i = 0;
00845     while (lpServiceStartTable[i].lpServiceProc != NULL)
00846     {
00847         i++;
00848     }
00849 
00850     dwActiveServiceCount = i;
00851     lpActiveServices = RtlAllocateHeap(RtlGetProcessHeap(),
00852                                        HEAP_ZERO_MEMORY,
00853                                        dwActiveServiceCount * sizeof(ACTIVE_SERVICE));
00854     if (lpActiveServices == NULL)
00855     {
00856         return FALSE;
00857     }
00858 
00859     /* Copy service names and start procedure */
00860     for (i = 0; i < dwActiveServiceCount; i++)
00861     {
00862         RtlCreateUnicodeStringFromAsciiz(&lpActiveServices[i].ServiceName,
00863                                          lpServiceStartTable[i].lpServiceName);
00864         lpActiveServices[i].ThreadParams.A.lpServiceMain = lpServiceStartTable[i].lpServiceProc;
00865         lpActiveServices[i].hServiceStatus = 0;
00866         lpActiveServices[i].bUnicode = FALSE;
00867     }
00868 
00869     dwError = ScConnectControlPipe(&hPipe);
00870     if (dwError != ERROR_SUCCESS)
00871     {
00872         /* Free the service table */
00873         for (i = 0; i < dwActiveServiceCount; i++)
00874         {
00875             RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
00876         }
00877         RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
00878         lpActiveServices = NULL;
00879         dwActiveServiceCount = 0;
00880         return FALSE;
00881     }
00882 
00883     lpMessageBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
00884                                       HEAP_ZERO_MEMORY,
00885                                       256);
00886     if (lpMessageBuffer == NULL)
00887     {
00888         /* Free the service table */
00889         for (i = 0; i < dwActiveServiceCount; i++)
00890         {
00891             RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
00892         }
00893         RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
00894         lpActiveServices = NULL;
00895         dwActiveServiceCount = 0;
00896         CloseHandle(hPipe);
00897         return FALSE;
00898     }
00899 
00900     ScCreateStatusBinding();
00901 
00902     ScServiceDispatcher(hPipe, lpMessageBuffer, 256);
00903 
00904     ScDestroyStatusBinding();
00905 
00906     CloseHandle(hPipe);
00907 
00908     /* Free the message buffer */
00909     RtlFreeHeap(RtlGetProcessHeap(), 0, lpMessageBuffer);
00910 
00911     /* Free the service table */
00912     for (i = 0; i < dwActiveServiceCount; i++)
00913     {
00914         RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
00915     }
00916     RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
00917     lpActiveServices = NULL;
00918     dwActiveServiceCount = 0;
00919 
00920     return TRUE;
00921 }
00922 
00923 
00924 /**********************************************************************
00925  *  StartServiceCtrlDispatcherW
00926  *
00927  * @implemented
00928  */
00929 BOOL WINAPI
00930 StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW * lpServiceStartTable)
00931 {
00932     ULONG i;
00933     HANDLE hPipe;
00934     DWORD dwError;
00935     PUCHAR lpMessageBuffer;
00936 
00937     TRACE("StartServiceCtrlDispatcherW() called\n");
00938 
00939     i = 0;
00940     while (lpServiceStartTable[i].lpServiceProc != NULL)
00941     {
00942         i++;
00943     }
00944 
00945     dwActiveServiceCount = i;
00946     lpActiveServices = RtlAllocateHeap(RtlGetProcessHeap(),
00947                                        HEAP_ZERO_MEMORY,
00948                                        dwActiveServiceCount * sizeof(ACTIVE_SERVICE));
00949     if (lpActiveServices == NULL)
00950     {
00951         return FALSE;
00952     }
00953 
00954     /* Copy service names and start procedure */
00955     for (i = 0; i < dwActiveServiceCount; i++)
00956     {
00957         RtlCreateUnicodeString(&lpActiveServices[i].ServiceName,
00958                                lpServiceStartTable[i].lpServiceName);
00959         lpActiveServices[i].ThreadParams.W.lpServiceMain = lpServiceStartTable[i].lpServiceProc;
00960         lpActiveServices[i].hServiceStatus = 0;
00961         lpActiveServices[i].bUnicode = TRUE;
00962     }
00963 
00964     dwError = ScConnectControlPipe(&hPipe);
00965     if (dwError != ERROR_SUCCESS)
00966     {
00967         /* Free the service table */
00968         for (i = 0; i < dwActiveServiceCount; i++)
00969         {
00970             RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
00971         }
00972         RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
00973         lpActiveServices = NULL;
00974         dwActiveServiceCount = 0;
00975         return FALSE;
00976     }
00977 
00978     lpMessageBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
00979                                       HEAP_ZERO_MEMORY,
00980                                       256);
00981     if (lpMessageBuffer == NULL)
00982     {
00983         /* Free the service table */
00984         for (i = 0; i < dwActiveServiceCount; i++)
00985         {
00986             RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
00987         }
00988         RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
00989         lpActiveServices = NULL;
00990         dwActiveServiceCount = 0;
00991         CloseHandle(hPipe);
00992         return FALSE;
00993     }
00994 
00995     ScCreateStatusBinding();
00996 
00997     ScServiceDispatcher(hPipe, lpMessageBuffer, 256);
00998 
00999     ScDestroyStatusBinding();
01000 
01001     CloseHandle(hPipe);
01002 
01003     /* Free the message buffer */
01004     RtlFreeHeap(RtlGetProcessHeap(), 0, lpMessageBuffer);
01005 
01006     /* Free the service table */
01007     for (i = 0; i < dwActiveServiceCount; i++)
01008     {
01009         RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
01010     }
01011     RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
01012     lpActiveServices = NULL;
01013     dwActiveServiceCount = 0;
01014 
01015     return TRUE;
01016 }
01017 
01018 /* EOF */

Generated on Sun May 27 2012 04:22:45 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.