Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensvchost.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
1.7.6.1
|