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

svchost.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS SvcHost
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            /base/services/svchost/svchost.c
00005  * PURPOSE:         Provide dll service loader
00006  * PROGRAMMERS:     Gregor Brunmar (gregor.brunmar@home.se)
00007  */
00008 
00009 /* INCLUDES ******************************************************************/
00010 
00011 #include "svchost.h"
00012 
00013 #define NDEBUG
00014 #include <debug.h>
00015 
00016 #ifdef _MSC_VER
00017 #undef DPRINT1
00018 #define DPRINT1
00019 #endif
00020 
00021 /* DEFINES *******************************************************************/
00022 
00023 static LPCTSTR SVCHOST_REG_KEY  = _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\SvcHost");
00024 static LPCTSTR SERVICE_KEY      = _T("SYSTEM\\CurrentControlSet\\Services\\");
00025 static LPCTSTR PARAMETERS_KEY   = _T("\\Parameters");
00026 
00027 #define SERVICE_KEY_LENGTH  _tcslen(SERVICE_KEY);
00028 #define REG_MAX_DATA_SIZE   2048
00029 
00030 static PSERVICE FirstService = NULL;
00031 
00032 /* FUNCTIONS *****************************************************************/
00033 
00034 BOOL PrepareService(LPCTSTR ServiceName)
00035 {
00036     HKEY hServiceKey;
00037     TCHAR ServiceKeyBuffer[MAX_PATH + 1];
00038     DWORD LeftOfBuffer = sizeof(ServiceKeyBuffer) / sizeof(ServiceKeyBuffer[0]);
00039     DWORD KeyType;
00040     PTSTR Buffer = NULL;
00041     DWORD BufferSize = MAX_PATH + 1;
00042     LONG RetVal;
00043     HINSTANCE hServiceDll;
00044     TCHAR DllPath[MAX_PATH + 2]; /* See MSDN on ExpandEnvironmentStrings() for ANSI strings for more details on + 2 */
00045     LPSERVICE_MAIN_FUNCTION ServiceMainFunc;
00046     PSERVICE Service;
00047 
00048     /* Compose the registry path to the service's "Parameter" key */
00049     _tcsncpy(ServiceKeyBuffer, SERVICE_KEY, LeftOfBuffer);
00050     LeftOfBuffer -= _tcslen(SERVICE_KEY);
00051     _tcsncat(ServiceKeyBuffer, ServiceName, LeftOfBuffer);
00052     LeftOfBuffer -= _tcslen(ServiceName);
00053     _tcsncat(ServiceKeyBuffer, PARAMETERS_KEY, LeftOfBuffer);
00054     LeftOfBuffer -= _tcslen(PARAMETERS_KEY);
00055 
00056     if (LeftOfBuffer < 0)
00057     {
00058         DPRINT1("Buffer overflow for service name: '%s'\n", ServiceName);
00059         return FALSE;
00060     }
00061 
00062     /* Open the service registry key to find the dll name */
00063     if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, ServiceKeyBuffer, 0, KEY_READ, &hServiceKey))
00064     {
00065         DPRINT1("Could not open service key (%s)\n", ServiceKeyBuffer);
00066         return FALSE;
00067     }
00068 
00069     do
00070     {
00071         if (Buffer)
00072             HeapFree(GetProcessHeap(), 0, Buffer);
00073 
00074         Buffer = HeapAlloc(GetProcessHeap(), 0, BufferSize);
00075         if (NULL == Buffer)
00076         {
00077             DPRINT1("Not enough memory for service: %s\n", ServiceName);
00078             return FALSE;
00079         }
00080 
00081         RetVal = RegQueryValueEx(hServiceKey, _T("ServiceDll"), NULL, &KeyType, (LPBYTE)Buffer, &BufferSize);
00082 
00083     } while (ERROR_MORE_DATA == RetVal);
00084 
00085 
00086     RegCloseKey(hServiceKey);
00087 
00088     if (ERROR_SUCCESS != RetVal || 0 == BufferSize)
00089     {
00090         DPRINT1("Could not read 'ServiceDll' value from service: %s, ErrorCode: 0x%x\n", ServiceName, RetVal);
00091         HeapFree(GetProcessHeap(), 0, Buffer);
00092         return FALSE;
00093     }
00094 
00095     /* Convert possible %SystemRoot% to a real path */
00096     BufferSize = ExpandEnvironmentStrings(Buffer, DllPath, _countof(DllPath));
00097     if (0 == BufferSize)
00098     {
00099         DPRINT1("Invalid ServiceDll path: %s\n", Buffer);
00100         HeapFree(GetProcessHeap(), 0, Buffer);
00101         return FALSE;
00102     }
00103 
00104     HeapFree(GetProcessHeap(), 0, Buffer);
00105 
00106     /* Load the service dll */
00107     DPRINT("Trying to load dll\n");
00108     hServiceDll = LoadLibrary(DllPath);
00109 
00110     if (NULL == hServiceDll)
00111     {
00112         DPRINT1("Unable to load ServiceDll: %s, ErrorCode: %u\n", DllPath, GetLastError());
00113         return FALSE;
00114     }
00115 
00116     ServiceMainFunc = (LPSERVICE_MAIN_FUNCTION)GetProcAddress(hServiceDll, "ServiceMain");
00117 
00118     /* Allocate a service node in the linked list */
00119     Service = HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE));
00120     if (NULL == Service)
00121     {
00122         DPRINT1("Not enough memory for service: %s\n", ServiceName);
00123         return FALSE;
00124     }
00125 
00126     memset(Service, 0, sizeof(SERVICE));
00127     Service->Name = HeapAlloc(GetProcessHeap(), 0, (_tcslen(ServiceName)+1) * sizeof(TCHAR));
00128     if (NULL == Service->Name)
00129     {
00130         DPRINT1("Not enough memory for service: %s\n", ServiceName);
00131         HeapFree(GetProcessHeap(), 0, Service);
00132         return FALSE;
00133     }
00134     _tcscpy(Service->Name, ServiceName);
00135 
00136     Service->hServiceDll = hServiceDll;
00137     Service->ServiceMainFunc = ServiceMainFunc;
00138 
00139     Service->Next = FirstService;
00140     FirstService = Service;
00141 
00142     return TRUE;
00143 }
00144 
00145 VOID FreeServices(VOID)
00146 {
00147     while (FirstService)
00148     {
00149         PSERVICE Service = FirstService;
00150         FirstService = Service->Next;
00151 
00152         FreeLibrary(Service->hServiceDll);
00153 
00154         HeapFree(GetProcessHeap(), 0, Service->Name);
00155         HeapFree(GetProcessHeap(), 0, Service);
00156     }
00157 }
00158 
00159 /*
00160  * Returns the number of services successfully loaded from the category
00161  */
00162 DWORD LoadServiceCategory(LPCTSTR ServiceCategory)
00163 {
00164     HKEY hServicesKey;
00165     DWORD KeyType;
00166     DWORD BufferSize = REG_MAX_DATA_SIZE;
00167     TCHAR Buffer[REG_MAX_DATA_SIZE];
00168     LPCTSTR ServiceName;
00169     DWORD BufferIndex = 0;
00170     DWORD NrOfServices = 0;
00171 
00172     /* Get all the services in this category */
00173     if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, SVCHOST_REG_KEY, 0, KEY_READ, &hServicesKey))
00174     {
00175         DPRINT1("Could not open service category: %s\n", ServiceCategory);
00176         return 0;
00177     }
00178 
00179     if (ERROR_SUCCESS != RegQueryValueEx(hServicesKey, ServiceCategory, NULL, &KeyType, (LPBYTE)Buffer, &BufferSize))
00180     {
00181         DPRINT1("Could not open service category (2): %s\n", ServiceCategory);
00182         RegCloseKey(hServicesKey);
00183         return 0;
00184     }
00185 
00186     /* Clean up */
00187     RegCloseKey(hServicesKey);
00188 
00189     /* Load services in the category */
00190     ServiceName = Buffer;
00191     while (_T('\0') != ServiceName[0])
00192     {
00193         size_t Length;
00194         
00195         Length = _tcslen(ServiceName);
00196         if (0 == Length)
00197             break;
00198 
00199         if (TRUE == PrepareService(ServiceName))
00200             ++NrOfServices;
00201 
00202         BufferIndex += Length + 1;
00203 
00204         ServiceName = &Buffer[BufferIndex];
00205     }
00206 
00207     return NrOfServices;
00208 }
00209 
00210 int _tmain (int argc, LPTSTR argv [])
00211 {
00212     DWORD NrOfServices;
00213     LPSERVICE_TABLE_ENTRY ServiceTable;
00214 
00215     if (argc < 3)
00216     {
00217         /* MS svchost.exe doesn't seem to print help, should we? */
00218         return 0;
00219     }
00220 
00221     if (_tcscmp(argv[1], _T("-k")) != 0)
00222     {
00223         /* For now, we only handle "-k" */
00224         return 0;
00225     }
00226 
00227     NrOfServices = LoadServiceCategory(argv[2]);
00228 
00229     DPRINT("NrOfServices: %lu\n", NrOfServices);
00230     if (0 == NrOfServices)
00231         return 0;
00232 
00233     ServiceTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SERVICE_TABLE_ENTRY) * (NrOfServices + 1));
00234 
00235     if (NULL != ServiceTable)
00236     {
00237         DWORD i;
00238         PSERVICE Service = FirstService;
00239 
00240         /* Fill the service table */
00241         for (i = 0; i < NrOfServices; i++)
00242         {
00243             DPRINT("Loading service: %s\n", Service->Name);
00244             ServiceTable[i].lpServiceName = Service->Name;
00245             ServiceTable[i].lpServiceProc = Service->ServiceMainFunc;
00246             Service = Service->Next;
00247         }
00248 
00249         /* Set a NULL entry to end the service table */
00250         ServiceTable[i].lpServiceName = NULL;
00251         ServiceTable[i].lpServiceProc = NULL;
00252 
00253         if (FALSE == StartServiceCtrlDispatcher(ServiceTable))
00254             DPRINT1("Failed to start service control dispatcher, ErrorCode: %lu\n", GetLastError());
00255 
00256         HeapFree(GetProcessHeap(), 0, ServiceTable);
00257     }
00258     else
00259     {
00260         DPRINT1("Not enough memory for the service table, trying to allocate %u bytes\n", sizeof(SERVICE_TABLE_ENTRY) * (NrOfServices + 1));
00261     }
00262 
00263     DPRINT("Freeing services...\n");
00264     FreeServices();
00265 
00266     return 0;
00267 }
00268 
00269 /* EOF */

Generated on Sat May 26 2012 04:16:38 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.