Source code of Windows XP (NT5)
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.

612 lines
15 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. setupsrv.cpp
  5. Abstract:
  6. Routines for secedit integration with system setup and component setup
  7. Author:
  8. Jin Huang (jinhuang) 15-Aug-1997
  9. Revision History:
  10. jinhuang 26-Jan-1998 splitted to client-server
  11. --*/
  12. #include "headers.h"
  13. #include "serverp.h"
  14. #include "srvrpcp.h"
  15. #include "pfp.h"
  16. #include <io.h>
  17. SCESTATUS
  18. ScepUpdateObjectInSection(
  19. IN PSCECONTEXT hProfile,
  20. IN SCETYPE ProfileType,
  21. IN PWSTR ObjectName,
  22. IN SE_OBJECT_TYPE ObjectType,
  23. IN UINT nFlag,
  24. IN PWSTR SDText,
  25. OUT UINT *pStatus
  26. );
  27. //
  28. // implementations
  29. //
  30. DWORD
  31. ScepSetupUpdateObject(
  32. IN PSCECONTEXT Context,
  33. IN PWSTR ObjectFullName,
  34. IN SE_OBJECT_TYPE ObjectType,
  35. IN UINT nFlag,
  36. IN PWSTR SDText
  37. )
  38. /*
  39. Routine Description:
  40. This routine is the private API called from the RPC interface to
  41. update object information in the database.
  42. Arguments:
  43. Context - the database context handle
  44. ObjectFullName - the object's name
  45. Objecttype - the object type
  46. nFlag - the flag on how to update this object
  47. SDText - the security descriptor in SDDL text
  48. Return Value:
  49. */
  50. {
  51. if ( !ObjectFullName || NULL == SDText ) {
  52. return ERROR_INVALID_PARAMETER;
  53. }
  54. switch ( ObjectType ) {
  55. case SE_SERVICE:
  56. case SE_REGISTRY_KEY:
  57. case SE_FILE_OBJECT:
  58. break;
  59. default:
  60. return ERROR_INVALID_PARAMETER;
  61. }
  62. SCESTATUS rc;
  63. DWORD dwInSetup=0;
  64. ScepRegQueryIntValue(HKEY_LOCAL_MACHINE,
  65. TEXT("System\\Setup"),
  66. TEXT("SystemSetupInProgress"),
  67. &dwInSetup
  68. );
  69. //
  70. // convert SDText to security descriptor
  71. //
  72. PSECURITY_DESCRIPTOR pSD=NULL;
  73. DWORD SDSize;
  74. SECURITY_INFORMATION SeInfo=0;
  75. HANDLE Token=NULL;
  76. DWORD Win32rc=ERROR_SUCCESS;
  77. if ( !(nFlag & SCESETUP_UPDATE_DB_ONLY) ) {
  78. //
  79. // security will be set, so compute the security descriptor
  80. //
  81. Win32rc = ConvertTextSecurityDescriptor (
  82. SDText,
  83. &pSD,
  84. &SDSize,
  85. &SeInfo
  86. );
  87. if ( NO_ERROR == Win32rc ) {
  88. ScepChangeAclRevision(pSD, ACL_REVISION);
  89. //
  90. // get current thread/process's token
  91. //
  92. if (!OpenThreadToken( GetCurrentThread(),
  93. TOKEN_QUERY,
  94. FALSE,
  95. &Token)) {
  96. if (!OpenProcessToken( GetCurrentProcess(),
  97. TOKEN_QUERY,
  98. &Token)) {
  99. Win32rc = GetLastError();
  100. }
  101. }
  102. if ( Token && (SeInfo & SACL_SECURITY_INFORMATION) ) {
  103. SceAdjustPrivilege( SE_SECURITY_PRIVILEGE, TRUE, Token );
  104. }
  105. }
  106. }
  107. if ( NO_ERROR == Win32rc ) {
  108. //
  109. // only update DB if it's in setup
  110. //
  111. //
  112. // on 64-bit platform, only update database if setup does not indicate SCE_SETUP_32KEY flag
  113. //
  114. #ifdef _WIN64
  115. if ( dwInSetup && !(nFlag & SCE_SETUP_32KEY) ) {
  116. #else
  117. if ( dwInSetup ) {
  118. #endif
  119. // save this into SCP and SMP, do not overwrite the status/container flag
  120. // if there is one exist, else use SCE_STATUS_CHECK and check for container
  121. //
  122. //
  123. // start a transaction since there are multiple operations
  124. //
  125. rc = SceJetStartTransaction( Context );
  126. if ( rc == SCESTATUS_SUCCESS ) {
  127. UINT Status=SCE_STATUS_CHECK;
  128. rc = ScepUpdateObjectInSection(
  129. Context,
  130. SCE_ENGINE_SMP,
  131. ObjectFullName,
  132. ObjectType,
  133. nFlag,
  134. SDText,
  135. &Status
  136. );
  137. if ( rc == SCESTATUS_SUCCESS &&
  138. (Context->JetSapID != JET_tableidNil) ) {
  139. //
  140. // the SAP table ID points to the tattoo table
  141. // should update the tattoo table too if it exist
  142. //
  143. rc = ScepUpdateObjectInSection(
  144. Context,
  145. SCE_ENGINE_SAP,
  146. ObjectFullName,
  147. ObjectType,
  148. nFlag,
  149. SDText,
  150. NULL
  151. );
  152. }
  153. }
  154. } else {
  155. rc = SCESTATUS_SUCCESS;
  156. }
  157. if ( rc == SCESTATUS_SUCCESS &&
  158. !(nFlag & SCESETUP_UPDATE_DB_ONLY) ) {
  159. //
  160. // set security to the object
  161. //
  162. //
  163. // if 64-bit platform, no synchronization is done and setup will have
  164. // to call the exported API with SCE_SETUP_32KEY if 32-bit hive is desired
  165. //
  166. #ifdef _WIN64
  167. if ( ObjectType == SE_REGISTRY_KEY && (nFlag & SCE_SETUP_32KEY) ){
  168. ObjectType = SE_REGISTRY_WOW64_32KEY;
  169. }
  170. #endif
  171. Win32rc = ScepSetSecurityWin32(
  172. ObjectFullName,
  173. SeInfo,
  174. pSD,
  175. ObjectType
  176. );
  177. } else
  178. Win32rc = ScepSceStatusToDosError(rc);
  179. if ( Win32rc == ERROR_SUCCESS ||
  180. Win32rc == ERROR_FILE_NOT_FOUND ||
  181. Win32rc == ERROR_PATH_NOT_FOUND ||
  182. Win32rc == ERROR_INVALID_OWNER ||
  183. Win32rc == ERROR_INVALID_PRIMARY_GROUP ||
  184. Win32rc == ERROR_INVALID_HANDLE ) {
  185. if ( Win32rc )
  186. gWarningCode = Win32rc;
  187. if ( dwInSetup ) { // in setup, update DB
  188. Win32rc = ScepSceStatusToDosError(
  189. SceJetCommitTransaction( Context, 0));
  190. } else {
  191. Win32rc = ERROR_SUCCESS;
  192. }
  193. } else if ( dwInSetup ) { // in setup
  194. SceJetRollback( Context, 0 );
  195. }
  196. if ( Token && (SeInfo & SACL_SECURITY_INFORMATION) )
  197. SceAdjustPrivilege( SE_SECURITY_PRIVILEGE, FALSE, Token );
  198. }
  199. CloseHandle(Token);
  200. if ( pSD ) {
  201. LocalFree(pSD);
  202. pSD = NULL;
  203. }
  204. return(Win32rc);
  205. }
  206. SCESTATUS
  207. ScepUpdateObjectInSection(
  208. IN PSCECONTEXT Context,
  209. IN SCETYPE ProfileType,
  210. IN PWSTR ObjectName,
  211. IN SE_OBJECT_TYPE ObjectType,
  212. IN UINT nFlag,
  213. IN PWSTR SDText,
  214. OUT UINT *pStatus
  215. )
  216. /*
  217. Routine Description:
  218. Update SCP and SMP. if the table does not exist at all, ignore the update.
  219. Delete SAP entry for the object. If table or record not found, ignore the error.
  220. Arguments:
  221. Return Value:
  222. */
  223. {
  224. if ( Context == NULL || ObjectName == NULL ) {
  225. return(SCESTATUS_INVALID_PARAMETER);
  226. }
  227. SCESTATUS rc;
  228. PSCESECTION hSection=NULL;
  229. PCWSTR SectionName;
  230. switch ( ObjectType ) {
  231. case SE_FILE_OBJECT:
  232. SectionName = szFileSecurity;
  233. break;
  234. case SE_REGISTRY_KEY:
  235. SectionName = szRegistryKeys;
  236. break;
  237. case SE_SERVICE:
  238. SectionName = szServiceGeneral;
  239. break;
  240. default:
  241. return(SCESTATUS_INVALID_PARAMETER);
  242. }
  243. rc = ScepOpenSectionForName(
  244. Context,
  245. ProfileType,
  246. SectionName,
  247. &hSection
  248. );
  249. if ( rc == SCESTATUS_BAD_FORMAT ||
  250. rc == SCESTATUS_RECORD_NOT_FOUND ) {
  251. return(SCESTATUS_SUCCESS);
  252. }
  253. if ( rc == SCESTATUS_SUCCESS ) {
  254. WCHAR StatusFlag=L'\0';
  255. DWORD ValueLen;
  256. BYTE Status=SCE_STATUS_CHECK;
  257. BOOL IsContainer=TRUE;
  258. BYTE StartType;
  259. rc = SceJetGetValue(
  260. hSection,
  261. SCEJET_EXACT_MATCH_NO_CASE,
  262. ObjectName,
  263. NULL,
  264. 0,
  265. NULL,
  266. (PWSTR)&StatusFlag,
  267. 2,
  268. &ValueLen
  269. );
  270. if ( rc == SCESTATUS_SUCCESS ||
  271. rc == SCESTATUS_BUFFER_TOO_SMALL ) {
  272. rc = SCESTATUS_SUCCESS;
  273. Status = *((BYTE *)&StatusFlag);
  274. if ( pStatus ) {
  275. *pStatus = Status;
  276. }
  277. if ( ObjectType == SE_SERVICE ) {
  278. StartType = *((BYTE *)&StatusFlag+1);
  279. } else {
  280. IsContainer = *((CHAR *)&StatusFlag+1) != '0' ? TRUE : FALSE;
  281. }
  282. }
  283. if ( ObjectType == SE_SERVICE ) {
  284. DWORD SDLen, Len;
  285. PWSTR ValueToSet;
  286. StartType = (BYTE)nFlag;
  287. if ( SDText != NULL ) {
  288. SDLen = wcslen(SDText);
  289. Len = ( SDLen+1)*sizeof(WCHAR);
  290. } else
  291. Len = sizeof(WCHAR);
  292. ValueToSet = (PWSTR)ScepAlloc( (UINT)0, Len+sizeof(WCHAR) );
  293. if ( ValueToSet != NULL ) {
  294. //
  295. // The first byte is the flag, the second byte is IsContainer (1,0)
  296. //
  297. *((BYTE *)ValueToSet) = Status;
  298. *((BYTE *)ValueToSet+1) = StartType;
  299. if ( SDText != NULL ) {
  300. swprintf(ValueToSet+1, L"%s", SDText );
  301. ValueToSet[SDLen+1] = L'\0'; //terminate this string
  302. } else {
  303. ValueToSet[1] = L'\0';
  304. }
  305. if ( SCESTATUS_SUCCESS == rc || ProfileType != SCE_ENGINE_SAP ) {
  306. //
  307. // only update tattoo table (pointed by SAP handle) if it finds a record there
  308. // for other table (SMP), ignore the error code, just set
  309. //
  310. rc = SceJetSetLine( hSection,
  311. ObjectName,
  312. FALSE,
  313. ValueToSet,
  314. Len,
  315. 0);
  316. }
  317. ScepFree( ValueToSet );
  318. } else {
  319. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  320. }
  321. } else if ( SCESTATUS_SUCCESS == rc || ProfileType != SCE_ENGINE_SAP ) {
  322. //
  323. // only update tattoo table (pointed by SAP handle) if it finds a record there
  324. // for other table (SMP), ignore the error code, just set
  325. //
  326. rc = ScepSaveObjectString(
  327. hSection,
  328. ObjectName,
  329. IsContainer,
  330. Status,
  331. SDText,
  332. (SDText == NULL ) ? 0 : wcslen(SDText)
  333. );
  334. }
  335. if ( rc == SCESTATUS_RECORD_NOT_FOUND )
  336. rc = SCESTATUS_SUCCESS;
  337. SceJetCloseSection(&hSection, TRUE);
  338. }
  339. return(rc);
  340. }
  341. DWORD
  342. ScepSetupMoveFile(
  343. IN PSCECONTEXT Context,
  344. PWSTR OldName,
  345. PWSTR NewName OPTIONAL,
  346. PWSTR SDText OPTIONAL
  347. )
  348. /*
  349. Routine Description:
  350. Set security to OldName but save with NewName in SCE database if SDText
  351. is not NULL. If NewName is NULL, delete OldName from SCE database.
  352. Arguments:
  353. Context - the databaes context handle
  354. SectionName - the section name
  355. OldName - the object's old name
  356. NewName - the new name to rename to, if NULL, delete the old object
  357. SDText - security string
  358. Return Value:
  359. Win32 error code
  360. */
  361. {
  362. if ( !Context || !OldName ) {
  363. return ERROR_INVALID_PARAMETER;
  364. }
  365. DWORD rc32=ERROR_SUCCESS;
  366. if ( NewName && SDText ) {
  367. //
  368. // set security on OldName with SDText
  369. //
  370. rc32 = ScepSetupUpdateObject(
  371. Context,
  372. OldName,
  373. SE_FILE_OBJECT,
  374. 0,
  375. SDText
  376. );
  377. }
  378. if ( rc32 == ERROR_SUCCESS ) {
  379. //
  380. // save this into SCP and SMP, do not overwrite the status/container flag
  381. // if there is one exist, else use SCE_STATUS_CHECK and check for container
  382. //
  383. SCESTATUS rc = SceJetStartTransaction( Context );
  384. if ( rc == SCESTATUS_SUCCESS ) {
  385. PSCESECTION hSection=NULL;
  386. //
  387. // process SMP section first
  388. //
  389. rc = ScepOpenSectionForName(
  390. Context,
  391. SCE_ENGINE_SMP,
  392. szFileSecurity,
  393. &hSection
  394. );
  395. if ( rc == SCESTATUS_SUCCESS ) {
  396. if ( NewName ) {
  397. //
  398. // rename this line
  399. //
  400. rc = SceJetRenameLine(
  401. hSection,
  402. OldName,
  403. NewName,
  404. FALSE);
  405. } else {
  406. //
  407. // delete this line first
  408. //
  409. rc = SceJetDelete(
  410. hSection,
  411. OldName,
  412. FALSE,
  413. SCEJET_DELETE_LINE_NO_CASE
  414. );
  415. }
  416. SceJetCloseSection( &hSection, TRUE);
  417. }
  418. if ( (SCESTATUS_SUCCESS == rc ||
  419. SCESTATUS_RECORD_NOT_FOUND == rc ||
  420. SCESTATUS_BAD_FORMAT == rc) &&
  421. (Context->JetSapID != JET_tableidNil) ) {
  422. //
  423. // process tattoo table
  424. //
  425. rc = ScepOpenSectionForName(
  426. Context,
  427. SCE_ENGINE_SAP,
  428. szFileSecurity,
  429. &hSection
  430. );
  431. if ( rc == SCESTATUS_SUCCESS ) {
  432. if ( NewName ) {
  433. //
  434. // rename this line
  435. //
  436. rc = SceJetRenameLine(
  437. hSection,
  438. OldName,
  439. NewName,
  440. FALSE);
  441. } else {
  442. //
  443. // delete this line first
  444. //
  445. rc = SceJetDelete(
  446. hSection,
  447. OldName,
  448. FALSE,
  449. SCEJET_DELETE_LINE_NO_CASE
  450. );
  451. }
  452. SceJetCloseSection( &hSection, TRUE);
  453. }
  454. }
  455. if ( SCESTATUS_RECORD_NOT_FOUND == rc ||
  456. SCESTATUS_BAD_FORMAT == rc ) {
  457. rc = SCESTATUS_SUCCESS;
  458. }
  459. if ( SCESTATUS_SUCCESS == rc ) {
  460. //
  461. // commit the transaction
  462. //
  463. rc = SceJetCommitTransaction( Context, 0 );
  464. } else {
  465. //
  466. // rollback the transaction
  467. //
  468. SceJetRollback( Context, 0 );
  469. }
  470. }
  471. rc32 = ScepSceStatusToDosError(rc);
  472. }
  473. return(rc32);
  474. }