Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

276 lines
7.9 KiB

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. ConfParm.c
  5. Abstract:
  6. This file contains:
  7. ScCheckServiceConfigParms
  8. Author:
  9. John Rogers (JohnRo) 14-Apr-1992
  10. Environment:
  11. User Mode - Win32
  12. Revision History:
  13. 14-Apr-1992 JohnRo
  14. Created.
  15. 20-May-1992 JohnRo
  16. Use CONST where possible.
  17. 09-Dec-1996 AnirudhS
  18. Added SC_LOG printouts to help diagnose the annoying
  19. ERROR_INVALID_PARAMETER and ERROR_INVALID_SERVICE_ACCOUNT return codes.
  20. --*/
  21. //
  22. // INCLUDES
  23. //
  24. #include <scpragma.h>
  25. #include <nt.h>
  26. #include <ntrtl.h> // Needed by <scdebug.h>
  27. #include <nturtl.h>
  28. #include <stdlib.h> // wcsicmp
  29. #include <windef.h>
  30. #include <winbase.h> // GetCurrentThreadId, for SC_LOG
  31. #include <scdebug.h> // SC_ASSERT().
  32. #include <sclib.h> // My prototype.
  33. #include <valid.h> // ERROR_CONTROL_INVALID(), SERVICE_TYPE_INVALID(), etc.
  34. #include <winerror.h> // NO_ERROR and ERROR_ equates.
  35. #include <winsvc.h> // SERVICE_ equates.
  36. DWORD
  37. ScCheckServiceConfigParms(
  38. IN BOOL Change,
  39. IN LPCWSTR lpServiceName,
  40. IN DWORD dwActualServiceType,
  41. IN DWORD dwNewServiceType,
  42. IN DWORD dwStartType,
  43. IN DWORD dwErrorControl,
  44. IN LPCWSTR lpBinaryPathName OPTIONAL,
  45. IN LPCWSTR lpLoadOrderGroup OPTIONAL,
  46. IN LPCWSTR lpDependencies OPTIONAL,
  47. IN DWORD dwDependSize
  48. )
  49. /*++
  50. Routine Description:
  51. This routine checks parameters for a CreateService() or a
  52. ChangeServiceConfig() API.
  53. Arguments:
  54. Change - TRUE if this is the result of a ChangeServiceConfig API.
  55. (This flag is used to determine whether other parameters may be
  56. SERVICE_NO_CHANGE or NULL pointers.)
  57. dwActualServiceType - For ChangeServiceConfig, contains the current
  58. service type associated with this service. Otherwise, this is
  59. the same value as dwNewServiceType.
  60. dwNewServiceType - SERVICE_NO_CHANGE or the service type given by app.
  61. (Other parameters same as CreateService and ChangeServiceConfig APIs.)
  62. Return Value:
  63. NO_ERROR or error code.
  64. --*/
  65. {
  66. DWORD dwFinalServiceType;
  67. #define PARM_MISSING( ws ) ( ((ws)==NULL) || ((*(ws)) == L'\0') )
  68. if ( !Change ) {
  69. //
  70. // Almost all fields must be present for creating a service.
  71. // (Exceptions are dependencies and password.)
  72. //
  73. if ( (dwNewServiceType == SERVICE_NO_CHANGE) ||
  74. (dwStartType == SERVICE_NO_CHANGE) ||
  75. (dwErrorControl == SERVICE_NO_CHANGE) ||
  76. PARM_MISSING(lpBinaryPathName) ) {
  77. SC_LOG0(ERROR, "ServiceType, StartType, ErrorControl or BinPath missing\n");
  78. return (ERROR_INVALID_PARAMETER);
  79. }
  80. }
  81. //
  82. // Validate actual and desired service types.
  83. //
  84. if (dwNewServiceType != SERVICE_NO_CHANGE) {
  85. if ( SERVICE_TYPE_INVALID( dwNewServiceType ) ) {
  86. SC_LOG0(ERROR, "ServiceType invalid\n");
  87. return (ERROR_INVALID_PARAMETER);
  88. }
  89. //
  90. // Not allowed to change the service type from Win32 to Driver
  91. // or Driver to Win32.
  92. //
  93. if ( ((dwNewServiceType & SERVICE_DRIVER) &&
  94. (dwActualServiceType & SERVICE_WIN32)) ||
  95. ((dwNewServiceType & SERVICE_WIN32) &&
  96. (dwActualServiceType & SERVICE_DRIVER)) ) {
  97. SC_LOG0(ERROR, "Can't change service type between Win32 and Driver\n");
  98. return (ERROR_INVALID_PARAMETER);
  99. }
  100. }
  101. if (dwActualServiceType == SERVICE_NO_CHANGE) {
  102. SC_LOG0(ERROR, "Current ServiceType missing\n");
  103. return (ERROR_INVALID_PARAMETER);
  104. }
  105. //
  106. // Validate start type (if that was given).
  107. //
  108. if (dwStartType != SERVICE_NO_CHANGE) {
  109. if ( START_TYPE_INVALID( dwStartType ) ) {
  110. SC_LOG0(ERROR, "StartType invalid\n");
  111. return (ERROR_INVALID_PARAMETER);
  112. }
  113. //
  114. // A boot-start or system-start service must be a driver
  115. //
  116. if (dwStartType == SERVICE_BOOT_START ||
  117. dwStartType == SERVICE_SYSTEM_START) {
  118. if (dwNewServiceType == SERVICE_NO_CHANGE) {
  119. if (dwActualServiceType != SERVICE_KERNEL_DRIVER &&
  120. dwActualServiceType != SERVICE_FILE_SYSTEM_DRIVER) {
  121. SC_LOG0(ERROR, "StartType is boot or system but service is not a driver\n");
  122. return (ERROR_INVALID_PARAMETER);
  123. }
  124. }
  125. else {
  126. if (dwNewServiceType != SERVICE_KERNEL_DRIVER &&
  127. dwNewServiceType != SERVICE_FILE_SYSTEM_DRIVER) {
  128. SC_LOG0(ERROR, "StartType is boot or system but ServiceType is not driver\n");
  129. return (ERROR_INVALID_PARAMETER);
  130. }
  131. }
  132. }
  133. }
  134. //
  135. // Validate error control...
  136. //
  137. if (dwErrorControl != SERVICE_NO_CHANGE) {
  138. if ( ERROR_CONTROL_INVALID( dwErrorControl ) ) {
  139. SC_LOG0(ERROR, "ErrorControl invalid\n");
  140. return (ERROR_INVALID_PARAMETER);
  141. }
  142. }
  143. //
  144. // Path type depends on final service type.
  145. //
  146. if (dwNewServiceType == SERVICE_NO_CHANGE) {
  147. dwFinalServiceType = dwActualServiceType;
  148. } else {
  149. dwFinalServiceType = dwNewServiceType;
  150. }
  151. SC_ASSERT( dwFinalServiceType != SERVICE_NO_CHANGE );
  152. //
  153. // Validate binary path name.
  154. //
  155. if (lpBinaryPathName != NULL) {
  156. // Check path name syntax and make sure it matches service type.
  157. // Path type depends on final service type.
  158. if ( !ScIsValidImagePath( lpBinaryPathName, dwFinalServiceType ) ) {
  159. SC_LOG0(ERROR, "ImagePath invalid for this service type\n");
  160. return (ERROR_INVALID_PARAMETER);
  161. }
  162. }
  163. //
  164. // Check for trivial cases of circular dependencies:
  165. // 1) Service is dependent on itself
  166. // 2) Service is dependent on a group it is a member of
  167. //
  168. LPWSTR DependPtr = (LPWSTR) lpDependencies;
  169. if (DependPtr != NULL && (*DependPtr != L'\0'))
  170. {
  171. DWORD dwError = ScValidateMultiSZ(DependPtr, dwDependSize);
  172. if (dwError != NO_ERROR)
  173. {
  174. SC_LOG(ERROR,
  175. "ScCheckServiceConfigParms: Invalid dependencies %d\n",
  176. dwError);
  177. return dwError;
  178. }
  179. while (*DependPtr != 0) {
  180. if (*DependPtr == SC_GROUP_IDENTIFIERW) {
  181. if ((lpLoadOrderGroup != NULL) && (*lpLoadOrderGroup != 0)) {
  182. if (_wcsicmp(DependPtr + 1, lpLoadOrderGroup) == 0) {
  183. //
  184. // Service depends on the group it is in
  185. //
  186. SC_LOG0(ERROR, "Service depends on the group it is in\n");
  187. return (ERROR_CIRCULAR_DEPENDENCY);
  188. }
  189. }
  190. }
  191. else {
  192. if (_wcsicmp(DependPtr, lpServiceName) == 0) {
  193. //
  194. // Service depends on itself
  195. //
  196. SC_LOG0(ERROR, "Service depends on itself\n");
  197. return (ERROR_CIRCULAR_DEPENDENCY);
  198. }
  199. }
  200. DependPtr += (wcslen(DependPtr) + 1);
  201. }
  202. }
  203. //
  204. // Start name is checked and canonicalized in ScValidateAndSaveAccount
  205. // if service type is Win32. If service type is driver, it's up to
  206. // the I/O system to validate the driver name (it can be NULL and the
  207. // I/O system will use the default driver name).
  208. //
  209. return (NO_ERROR);
  210. }