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.

5528 lines
145 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. infwrite.c
  5. Abstract:
  6. Routines to set information into security profiles (INF layout).
  7. Author:
  8. Jin Huang (jinhuang) 07-Dec-1996
  9. Revision History:
  10. --*/
  11. #include "headers.h"
  12. #include "scedllrc.h"
  13. #include "infp.h"
  14. #include "sceutil.h"
  15. #include "splay.h"
  16. #include <io.h>
  17. #include <sddl.h>
  18. #pragma hdrstop
  19. const TCHAR c_szCRLF[] = TEXT("\r\n");
  20. //
  21. // Forward references
  22. //
  23. SCESTATUS
  24. SceInfpWriteSystemAccess(
  25. IN PCWSTR ProfileName,
  26. IN PSCE_PROFILE_INFO pSCEinfo,
  27. IN BOOL bOverwrite,
  28. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  29. );
  30. SCESTATUS
  31. SceInfpWritePrivileges(
  32. IN PCWSTR ProfileName,
  33. IN PSCE_PRIVILEGE_ASSIGNMENT pPrivileges,
  34. IN BOOL bOverwrite,
  35. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  36. );
  37. SCESTATUS
  38. SceInfpWriteUserSettings(
  39. IN PCWSTR ProfileName,
  40. IN PSCE_NAME_LIST pProfiles,
  41. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  42. );
  43. SCESTATUS
  44. SceInfpWriteGroupMembership(
  45. IN PCWSTR ProfileName,
  46. IN PSCE_GROUP_MEMBERSHIP pGroupMembership,
  47. IN BOOL bOverwrite,
  48. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  49. );
  50. SCESTATUS
  51. SceInfpWriteServices(
  52. IN PCWSTR ProfileName,
  53. IN PCWSTR SectionName,
  54. IN PSCE_SERVICES pServices,
  55. IN BOOL bOverwrite,
  56. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  57. );
  58. DWORD
  59. SceInfpWriteOneService(
  60. IN PSCE_SERVICES pService,
  61. OUT PSCE_NAME_LIST *pNameList,
  62. OUT PDWORD ObjectSize,
  63. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  64. );
  65. SCESTATUS
  66. SceInfpWriteObjects(
  67. IN PCWSTR ProfileName,
  68. IN PCWSTR SectionName,
  69. IN PSCE_OBJECT_ARRAY pObjects,
  70. IN BOOL bOverwrite,
  71. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  72. );
  73. DWORD
  74. SceInfpWriteOneObject(
  75. IN PSCE_OBJECT_SECURITY pObject,
  76. OUT PSCE_NAME_LIST *pNameList,
  77. OUT PDWORD ObjectSize,
  78. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  79. );
  80. SCESTATUS
  81. SceInfpWriteAuditing(
  82. IN PCWSTR ProfileName,
  83. IN PSCE_PROFILE_INFO pSCEinfo,
  84. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  85. );
  86. SCESTATUS
  87. SceInfpAppendAuditing(
  88. IN PCWSTR ProfileName,
  89. IN PSCE_PROFILE_INFO pSCEinfo,
  90. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  91. );
  92. SCESTATUS
  93. ScepWriteOneIntValueToProfile(
  94. IN PCWSTR InfFileName,
  95. IN PCWSTR InfSectionName,
  96. IN PWSTR KeyName,
  97. IN DWORD Value
  98. );
  99. SCESTATUS
  100. SceInfpWriteAuditLogSetting(
  101. IN PCWSTR InfFileName,
  102. IN PCWSTR InfSectionName,
  103. IN DWORD LogSize,
  104. IN DWORD Periods,
  105. IN DWORD RetentionDays,
  106. IN DWORD RestrictGuest,
  107. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  108. );
  109. SCESTATUS
  110. SceInfpWriteInfSection(
  111. IN PCWSTR InfFileName,
  112. IN PCWSTR InfSectionName,
  113. IN DWORD TotalSize,
  114. IN PWSTR *EachLineStr,
  115. IN DWORD *EachLineSize,
  116. IN DWORD StartIndex,
  117. IN DWORD EndIndex,
  118. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  119. );
  120. #define SCEINF_ADD_EQUAL_SIGN 1
  121. #define SCEINF_APPEND_SECTION 2
  122. DWORD
  123. SceInfpWriteListSection(
  124. IN PCWSTR InfFileName,
  125. IN PCWSTR InfSectionName,
  126. IN DWORD TotalSize,
  127. IN PSCE_NAME_LIST ListLines,
  128. IN DWORD Option,
  129. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  130. );
  131. LONG
  132. SceInfpConvertNameListToString(
  133. IN LSA_HANDLE LsaHandle,
  134. IN PCWSTR KeyText,
  135. IN PSCE_NAME_LIST Fields,
  136. IN BOOL bOverwrite,
  137. OUT PWSTR *Strvalue,
  138. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  139. );
  140. LONG
  141. SceInfpConvertMultiSZToString(
  142. IN PCWSTR KeyText,
  143. IN UNICODE_STRING Fields,
  144. OUT PWSTR *Strvalue,
  145. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  146. );
  147. SCESTATUS
  148. ScepAllocateAndCopy(
  149. OUT PWSTR *Buffer,
  150. OUT PDWORD BufSize,
  151. IN DWORD MaxSize,
  152. IN PWSTR SrcBuf
  153. );
  154. SCESTATUS
  155. SceInfpBreakTextIntoMultiFields(
  156. IN PWSTR szText,
  157. IN DWORD dLen,
  158. OUT LPDWORD pnFields,
  159. OUT LPDWORD *arrOffset
  160. );
  161. SCESTATUS
  162. SceInfpWriteKerberosPolicy(
  163. IN PCWSTR ProfileName,
  164. IN PSCE_KERBEROS_TICKET_INFO pKerberosInfo,
  165. IN BOOL bOverwrite,
  166. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  167. );
  168. SCESTATUS
  169. SceInfpWriteRegistryValues(
  170. IN PCWSTR ProfileName,
  171. IN PSCE_REGISTRY_VALUE_INFO pRegValues,
  172. IN DWORD ValueCount,
  173. IN BOOL bOverwrite,
  174. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  175. );
  176. DWORD
  177. SceInfpWriteOneValue(
  178. IN PCWSTR ProfileName,
  179. IN SCE_REGISTRY_VALUE_INFO RegValue,
  180. IN BOOL bOverwrite,
  181. OUT PSCE_NAME_LIST *pNameList,
  182. OUT PDWORD ObjectSize
  183. );
  184. SCESTATUS
  185. ScepWriteSecurityProfile(
  186. IN PCWSTR InfProfileName,
  187. IN AREA_INFORMATION Area,
  188. IN PSCE_PROFILE_INFO InfoBuffer,
  189. IN BOOL bOverwrite,
  190. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  191. );
  192. DWORD
  193. ScepCreateTempFiles(
  194. IN PWSTR InfProfileName,
  195. OUT PWSTR *ppszTempFileName,
  196. OUT PWSTR *ppszTargetTempName
  197. );
  198. DWORD
  199. ScepWritePrivateProfileSection(
  200. IN LPCWSTR SectionName,
  201. IN LPTSTR pData,
  202. IN LPCWSTR FileName,
  203. IN BOOL bOverwrite
  204. );
  205. DWORD
  206. ScepAppendProfileSection(
  207. IN LPCWSTR SectionName,
  208. IN LPCWSTR FileName,
  209. IN LPTSTR pData
  210. );
  211. #define SCEP_PROFILE_WRITE_SECTIONNAME 0x1
  212. #define SCEP_PROFILE_GENERATE_KEYS 0x2
  213. #define SCEP_PROFILE_CHECK_DUP 0x4
  214. DWORD
  215. ScepOverwriteProfileSection(
  216. IN LPCWSTR SectionName,
  217. IN LPCWSTR FileName,
  218. IN LPTSTR pData,
  219. IN DWORD dwFlags,
  220. IN OUT PSCEP_SPLAY_TREE pKeys
  221. );
  222. DWORD
  223. ScepWriteStrings(
  224. IN HANDLE hFile,
  225. IN BOOL bUnicode,
  226. IN PWSTR szPrefix,
  227. IN DWORD dwPrefixLen,
  228. IN PWSTR szString,
  229. IN DWORD dwStrLen,
  230. IN PWSTR szSuffix,
  231. IN DWORD dwSuffixLen,
  232. IN BOOL bCRLF
  233. );
  234. SCESTATUS
  235. WINAPI
  236. SceWriteSecurityProfileInfo(
  237. IN PCWSTR InfProfileName,
  238. IN AREA_INFORMATION Area,
  239. IN PSCE_PROFILE_INFO InfoBuffer,
  240. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  241. )
  242. // see comments in ScepWriteSecurityProfile
  243. {
  244. return( ScepWriteSecurityProfile( InfProfileName,
  245. Area,
  246. InfoBuffer,
  247. TRUE, // overwrite the section(s)
  248. Errlog
  249. ) );
  250. }
  251. SCESTATUS
  252. WINAPI
  253. SceAppendSecurityProfileInfo(
  254. IN PCWSTR InfProfileName,
  255. IN AREA_INFORMATION Area,
  256. IN PSCE_PROFILE_INFO InfoBuffer,
  257. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  258. )
  259. // see comments in ScepWriteSecurityProfile
  260. {
  261. if ( InfoBuffer == NULL ) return SCESTATUS_SUCCESS;
  262. SCESTATUS rc=SCESTATUS_SUCCESS;
  263. /*
  264. AREA_INFORMATION Area2=0;
  265. HINF hInf=NULL;
  266. PSCE_PROFILE_INFO pOldBuffer=NULL;
  267. PSCE_OBJECT_ARRAY pNewKeys=NULL, pNewFiles=NULL;
  268. PSCE_OBJECT_ARRAY pOldKeys=NULL, pOldFiles=NULL;
  269. if ( (Area & AREA_REGISTRY_SECURITY) &&
  270. (InfoBuffer->pRegistryKeys.pAllNodes != NULL) &&
  271. (InfoBuffer->pRegistryKeys.pAllNodes->Count > 0) ) {
  272. Area2 |= AREA_REGISTRY_SECURITY;
  273. }
  274. if ( (Area & AREA_FILE_SECURITY) &&
  275. (InfoBuffer->pFiles.pAllNodes != NULL ) &&
  276. (InfoBuffer->pFiles.pAllNodes->Count > 0 ) ) {
  277. Area2 |= AREA_FILE_SECURITY;
  278. }
  279. if ( Area2 > 0 ) {
  280. //
  281. // query existing info from the template and check for duplicate
  282. // because these two sections do not support INF key name
  283. // any error occured in duplicate checking is ignored
  284. //
  285. rc = SceInfpOpenProfile(
  286. InfProfileName,
  287. &hInf
  288. );
  289. if ( SCESTATUS_SUCCESS == rc ) {
  290. rc = SceInfpGetSecurityProfileInfo(
  291. hInf,
  292. Area2,
  293. &pOldBuffer,
  294. NULL
  295. );
  296. if ( SCESTATUS_SUCCESS == rc ) {
  297. //
  298. // files/keys in the template are queried
  299. // now check if there is any existing files/keys
  300. //
  301. DWORD i,j,idxNew;
  302. if ( (Area2 & AREA_REGISTRY_SECURITY) &&
  303. (pOldBuffer->pRegistryKeys.pAllNodes != NULL) &&
  304. (pOldBuffer->pRegistryKeys.pAllNodes->Count > 0) ) {
  305. //
  306. // there are existing keys
  307. // now create a new buffer
  308. //
  309. pNewKeys = (PSCE_OBJECT_ARRAY)ScepAlloc(0,sizeof(SCE_OBJECT_ARRAY));
  310. if ( pNewKeys ) {
  311. pNewKeys->Count = 0;
  312. pNewKeys->pObjectArray = (PSCE_OBJECT_SECURITY *)ScepAlloc(LPTR, (pOldBuffer->pRegistryKeys.pAllNodes->Count)*sizeof(PSCE_OBJECT_SECURITY));
  313. if ( pNewKeys->pObjectArray ) {
  314. //
  315. // checking duplicate now
  316. //
  317. idxNew=0;
  318. for ( i=0; i<InfoBuffer->pRegistryKeys.pAllNodes->Count; i++) {
  319. if ( InfoBuffer->pRegistryKeys.pAllNodes->pObjectArray[i] == NULL )
  320. continue;
  321. for ( j=0; j<pOldBuffer->pRegistryKeys.pAllNodes->Count; j++) {
  322. if ( pOldBuffer->pRegistryKeys.pAllNodes->pObjectArray[j] == NULL )
  323. continue;
  324. // check if this one has been checked
  325. if ( pOldBuffer->pRegistryKeys.pAllNodes->pObjectArray[j]->Status == 255 )
  326. continue;
  327. if ( _wcsicmp(InfoBuffer->pRegistryKeys.pAllNodes->pObjectArray[i]->Name,
  328. pOldBuffer->pRegistryKeys.pAllNodes->pObjectArray[j]->Name) == 0 ) {
  329. //
  330. // found it
  331. //
  332. pOldBuffer->pRegistryKeys.pAllNodes->pObjectArray[j]->Status = 255;
  333. break;
  334. }
  335. }
  336. if ( j >= pOldBuffer->pRegistryKeys.pAllNodes->Count ) {
  337. //
  338. // did not find it, now link it to the new buffer
  339. //
  340. pNewKeys->pObjectArray[idxNew] = InfoBuffer->pRegistryKeys.pAllNodes->pObjectArray[i];
  341. idxNew++;
  342. }
  343. }
  344. pNewKeys->Count = idxNew;
  345. } else {
  346. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  347. ScepFree(pNewKeys);
  348. pNewKeys = NULL;
  349. }
  350. } else {
  351. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  352. }
  353. }
  354. if ( (Area2 & AREA_FILE_SECURITY) &&
  355. (pOldBuffer->pFiles.pAllNodes != NULL ) &&
  356. (pOldBuffer->pFiles.pAllNodes->Count > 0 ) ) {
  357. //
  358. // there are existing files
  359. // now create a new buffer
  360. //
  361. pNewFiles = (PSCE_OBJECT_ARRAY)ScepAlloc(0,sizeof(SCE_OBJECT_ARRAY));
  362. if ( pNewFiles ) {
  363. pNewFiles->Count = 0;
  364. pNewFiles->pObjectArray = (PSCE_OBJECT_SECURITY *)ScepAlloc(LPTR, (pOldBuffer->pFiles.pAllNodes->Count)*sizeof(PSCE_OBJECT_SECURITY));
  365. if ( pNewFiles->pObjectArray ) {
  366. //
  367. // checking duplicate now
  368. //
  369. idxNew=0;
  370. for ( i=0; i<InfoBuffer->pFiles.pAllNodes->Count; i++) {
  371. if ( InfoBuffer->pFiles.pAllNodes->pObjectArray[i] == NULL )
  372. continue;
  373. for ( j=0; j<pOldBuffer->pFiles.pAllNodes->Count; j++) {
  374. if ( pOldBuffer->pFiles.pAllNodes->pObjectArray[j] == NULL )
  375. continue;
  376. // check if this one has been checked
  377. if ( pOldBuffer->pFiles.pAllNodes->pObjectArray[j]->Status == 255 )
  378. continue;
  379. if ( _wcsicmp(InfoBuffer->pFiles.pAllNodes->pObjectArray[i]->Name,
  380. pOldBuffer->pFiles.pAllNodes->pObjectArray[j]->Name) == 0 ) {
  381. //
  382. // found it
  383. //
  384. pOldBuffer->pFiles.pAllNodes->pObjectArray[j]->Status = 255;
  385. break;
  386. }
  387. }
  388. if ( j >= pOldBuffer->pFiles.pAllNodes->Count ) {
  389. //
  390. // did not find it, now link it to the new buffer
  391. //
  392. pNewFiles->pObjectArray[idxNew] = InfoBuffer->pFiles.pAllNodes->pObjectArray[i];
  393. idxNew++;
  394. }
  395. }
  396. pNewFiles->Count = idxNew;
  397. } else {
  398. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  399. ScepFree(pNewFiles);
  400. pNewFiles = NULL;
  401. }
  402. } else {
  403. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  404. }
  405. }
  406. }
  407. SceInfpCloseProfile(hInf);
  408. SceFreeProfileMemory(pOldBuffer);
  409. }
  410. }
  411. if ( pNewKeys != NULL ) {
  412. //
  413. // use the purged buffer and save the old one
  414. //
  415. pOldKeys = InfoBuffer->pRegistryKeys.pAllNodes;
  416. InfoBuffer->pRegistryKeys.pAllNodes = pNewKeys;
  417. }
  418. if ( pNewFiles != NULL ) {
  419. //
  420. // use the purged buffer and save the old one
  421. //
  422. pOldFiles = InfoBuffer->pFiles.pAllNodes;
  423. InfoBuffer->pFiles.pAllNodes = pNewFiles;
  424. }
  425. */
  426. rc = ScepWriteSecurityProfile( InfProfileName,
  427. Area,
  428. InfoBuffer,
  429. FALSE, // append to the section(s)
  430. Errlog
  431. );
  432. /*
  433. if ( pNewKeys != NULL ) {
  434. //
  435. // reset the old pointer and free the new buffer
  436. //
  437. InfoBuffer->pRegistryKeys.pAllNodes = pOldKeys;
  438. ScepFree(pNewKeys->pObjectArray);
  439. ScepFree(pNewKeys);
  440. }
  441. if ( pNewFiles != NULL ) {
  442. //
  443. // use the purged buffer and save the old one
  444. //
  445. InfoBuffer->pFiles.pAllNodes = pOldFiles;
  446. ScepFree(pNewFiles->pObjectArray);
  447. ScepFree(pNewFiles);
  448. }
  449. */
  450. return rc;
  451. }
  452. DWORD
  453. ScepCreateTempFiles(
  454. IN PWSTR InfProfileName,
  455. OUT PWSTR *ppszTempFileName,
  456. OUT PWSTR *ppszTargetTempName
  457. )
  458. /*
  459. Description:
  460. This function is to get a temporary file name for system context (in system
  461. directory) as well as for normal user context (in user profile), and copy the
  462. input template data to the temporary file.
  463. Arguments:
  464. InfProfileName - the template file to copy from
  465. ppszTempFileName - the name of the temporary file to work on
  466. ppszTargetTempName - the backup copy of the template file in sysvol
  467. */
  468. {
  469. if ( InfProfileName == NULL || ppszTempFileName == NULL ||
  470. ppszTargetTempName == NULL) {
  471. return(SCESTATUS_INVALID_PARAMETER);
  472. }
  473. HANDLE Token=NULL;
  474. BOOL bSystem=FALSE;
  475. LONG Len=0, nSize=0, nRequired=0;
  476. PWSTR pTempName=NULL;
  477. DWORD rc=0;
  478. PWSTR pTemp=NULL;
  479. *ppszTempFileName = NULL;
  480. *ppszTargetTempName = NULL;
  481. //
  482. // check if we should have temp file on the target too.
  483. // only do this if the target file is in sysvol
  484. //
  485. if ((0xFFFFFFFF != GetFileAttributes(InfProfileName)) &&
  486. InfProfileName[0] == L'\\' && InfProfileName[1] == L'\\' &&
  487. (pTemp=wcschr(InfProfileName+2, L'\\')) ) {
  488. if ( _wcsnicmp(pTemp, L"\\sysvol\\", 8) == 0 ) {
  489. //
  490. // this is a file on sysvol
  491. //
  492. Len = wcslen(InfProfileName);
  493. *ppszTargetTempName = (PWSTR)LocalAlloc(LPTR, (Len+1)*sizeof(WCHAR));
  494. if ( *ppszTargetTempName ) {
  495. wcsncpy(*ppszTargetTempName, InfProfileName, Len-4);
  496. wcscat(*ppszTargetTempName, L".tmp");
  497. } else {
  498. rc = ERROR_NOT_ENOUGH_MEMORY;
  499. return rc;
  500. }
  501. }
  502. }
  503. //
  504. // determine if the current thread/process is system context
  505. // if this function fails, it's treated a regular user and the temp
  506. // file will be created in user profile location.
  507. //
  508. if (!OpenThreadToken( GetCurrentThread(),
  509. TOKEN_QUERY,
  510. FALSE,
  511. &Token)) {
  512. if (!OpenProcessToken( GetCurrentProcess(),
  513. TOKEN_QUERY,
  514. &Token))
  515. Token = NULL;
  516. }
  517. if ( Token != NULL ) {
  518. ScepIsSystemContext(Token, &bSystem);
  519. CloseHandle(Token);
  520. }
  521. //
  522. // get a temp file name.
  523. //
  524. if ( bSystem ) {
  525. Len = lstrlen(TEXT("\\security\\sce00000.tmp"));
  526. nRequired = GetSystemWindowsDirectory(NULL, 0);
  527. } else {
  528. //
  529. // get the temp file name from user's temp directory
  530. // the environment variable "TMP" is used here because this write API
  531. // is always called in user's process (except called from system context)
  532. //
  533. Len = lstrlen(TEXT("\\sce00000.tmp"));
  534. nRequired = GetEnvironmentVariable( L"TMP", NULL, 0 );
  535. }
  536. if ( nRequired > 0 ) {
  537. //
  538. // allocate buffer big enough for the temp file name
  539. //
  540. pTempName = (LPTSTR)LocalAlloc(0, (nRequired+2+Len)*sizeof(TCHAR));
  541. if ( pTempName ) {
  542. if ( bSystem ) {
  543. nSize = GetSystemWindowsDirectory(pTempName, nRequired);
  544. } else {
  545. nSize = GetEnvironmentVariable(L"TMP", pTempName, nRequired );
  546. }
  547. if ( nSize > 0 ) {
  548. pTempName[nSize] = L'\0';
  549. } else {
  550. //
  551. // if failed to query the information, should fail
  552. //
  553. rc = GetLastError();
  554. #if DBG == 1
  555. SceDebugPrint(DEB_ERROR, "Error %d to query temporary file path\n", rc);
  556. #endif
  557. LocalFree(pTempName);
  558. pTempName = NULL;
  559. }
  560. } else {
  561. rc = ERROR_NOT_ENOUGH_MEMORY;
  562. }
  563. } else {
  564. rc = GetLastError();
  565. #if DBG == 1
  566. SceDebugPrint(DEB_ERROR, "Error %d to query temporary file path\n", rc);
  567. #endif
  568. }
  569. //
  570. // check if the temp file name is already used.
  571. //
  572. if ( ERROR_SUCCESS == rc && pTempName &&
  573. nSize <= nRequired ) {
  574. ULONG seed=GetTickCount();
  575. ULONG ranNum=0;
  576. ranNum = RtlRandomEx(&seed);
  577. //
  578. // make sure that it's not over 5 digits (99999)
  579. //
  580. if ( ranNum > 99999 )
  581. ranNum = ranNum % 99999;
  582. swprintf(pTempName+nSize,
  583. bSystem ? L"\\security\\sce%05d.tmp\0" : L"\\sce%05d.tmp\0",
  584. ranNum);
  585. DWORD index=0;
  586. while ( 0xFFFFFFFF != GetFileAttributes(pTempName) &&
  587. index <= 99999) {
  588. ranNum = RtlRandomEx(&seed);
  589. //
  590. // make sure that it's not over 5 digits (99999)
  591. //
  592. if ( ranNum > 99999 )
  593. ranNum = ranNum % 99999;
  594. index++;
  595. swprintf(pTempName+nSize,
  596. bSystem ? L"\\security\\sce%05d.tmp\0" : L"\\sce%05d.tmp\0",
  597. ranNum);
  598. }
  599. if ( index >= 100000 ) {
  600. //
  601. // can't get a temp file name
  602. //
  603. rc = ERROR_DUP_NAME;
  604. #if DBG == 1
  605. SceDebugPrint(DEB_ERROR, "Can't get an unique temporary file name\n", rc);
  606. #endif
  607. }
  608. } else if ( ERROR_SUCCESS == rc ) {
  609. rc = ERROR_INSUFFICIENT_BUFFER;
  610. }
  611. //
  612. // make a copy of the temp file
  613. //
  614. if ( ERROR_SUCCESS == rc ) {
  615. //
  616. // detect if the profile exist and if it does, make a local copy
  617. //
  618. DWORD dwAttr = GetFileAttributes(InfProfileName);
  619. if ( 0xFFFFFFFF != dwAttr ) {
  620. if ( FALSE == CopyFile( InfProfileName, pTempName, FALSE ) ) {
  621. rc = GetLastError();
  622. #if DBG == 1
  623. SceDebugPrint(DEB_ERROR, "CopyFile to temp failed with %d\n", rc);
  624. #endif
  625. }
  626. }
  627. }
  628. if ( ERROR_SUCCESS == rc ) {
  629. *ppszTempFileName = pTempName;
  630. } else {
  631. if ( pTempName ) {
  632. //
  633. // make usre the file is not left over
  634. //
  635. DeleteFile(pTempName);
  636. LocalFree(pTempName);
  637. }
  638. if ( *ppszTargetTempName ) {
  639. LocalFree(*ppszTargetTempName);
  640. *ppszTargetTempName = NULL;
  641. }
  642. }
  643. return(rc);
  644. }
  645. //
  646. // function definitions
  647. //
  648. SCESTATUS
  649. ScepWriteSecurityProfile(
  650. IN PCWSTR szInfProfileName,
  651. IN AREA_INFORMATION Area,
  652. IN PSCE_PROFILE_INFO InfoBuffer,
  653. IN BOOL bOverwrite,
  654. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  655. )
  656. /**++
  657. Function Description:
  658. This function writes all or part of information into a SCP profile in
  659. INF format.
  660. Arguments:
  661. ProfileName - The INF file name to write to
  662. Area - area(s) for which to get information from
  663. AREA_SECURITY_POLICY
  664. AREA_PRIVILEGES
  665. AREA_USER_SETTINGS
  666. AREA_GROUP_MEMBERSHIP
  667. AREA_REGISTRY_SECURITY
  668. AREA_SYSTEM_SERVICE
  669. AREA_FILE_SECURITY
  670. InfoBuffer - Information to write. The Header of InfoBuffer contains
  671. SCP/SAP file name or file handle.
  672. bOverwrite - TRUE = overwrite the section(s) with InfoBuffer
  673. FALSE = append InfoBuffer to the section(s)
  674. Errlog - A buffer to hold all error codes/text encountered when
  675. parsing the INF file. If Errlog is NULL, no further error
  676. information is returned except the return DWORD
  677. Return Value:
  678. SCESTATUS_SUCCESS
  679. SCESTATUS_PROFILE_NOT_FOUND
  680. SCESTATUS_NOT_ENOUGH_RESOURCE
  681. SCESTATUS_INVALID_PARAMETER
  682. SCESTATUS_CORRUPT_PROFILE
  683. SCESTATUS_INVALID_DATA
  684. -- **/
  685. {
  686. SCESTATUS rc=SCESTATUS_SUCCESS;
  687. DWORD Win32rc;
  688. DWORD SDsize;
  689. PSCE_PROFILE_INFO pNewBuffer=NULL;
  690. AREA_INFORMATION Area2=0;
  691. PWSTR InfProfileName=NULL;
  692. PWSTR TargetTempName=NULL;
  693. if ( szInfProfileName == NULL || InfoBuffer == NULL ||
  694. Area == 0 ) {
  695. return(SCESTATUS_INVALID_PARAMETER);
  696. }
  697. //
  698. // get a temp file name
  699. // if this is system context, the temp file is under %windir%\security\scexxxxx.tmp
  700. // else the temp file will be in the user profile location.
  701. //
  702. // temp file name must be unique to handle simultaneous changes to different templates (GPOs)
  703. // temp file created under system context will be cleaned up when system booted up.
  704. //
  705. Win32rc = ScepCreateTempFiles((PWSTR)szInfProfileName, &InfProfileName, &TargetTempName);
  706. if ( Win32rc != ERROR_SUCCESS ) {
  707. ScepBuildErrorLogInfo(
  708. Win32rc,
  709. Errlog,
  710. SCEERR_ERROR_CREATE,
  711. TEXT("Temp")
  712. );
  713. return(ScepDosErrorToSceStatus(Win32rc));
  714. }
  715. //
  716. // initialize the error log buffer
  717. //
  718. if ( Errlog ) {
  719. *Errlog = NULL;
  720. }
  721. //
  722. // get Revision of this template
  723. //
  724. INT Revision = GetPrivateProfileInt( L"Version",
  725. L"Revision",
  726. 0,
  727. InfProfileName
  728. );
  729. if ( Revision == 0 ) {
  730. //
  731. // maybe a old version of inf file, or
  732. // it's a brand new file
  733. //
  734. TCHAR szBuf[20];
  735. szBuf[0] = L'\0';
  736. SDsize = GetPrivateProfileString(TEXT("Version"),
  737. TEXT("signature"),
  738. TEXT(""),
  739. szBuf,
  740. 20,
  741. InfProfileName
  742. );
  743. if ( SDsize == 0 ) {
  744. //
  745. // this is a new inf file
  746. //
  747. Revision = SCE_TEMPLATE_MAX_SUPPORTED_VERSION;
  748. //
  749. // make it unicode file, if error continues to use ansi
  750. //
  751. SetupINFAsUCS2(InfProfileName);
  752. }
  753. }
  754. //
  755. // system access
  756. //
  757. if ( Area & AREA_SECURITY_POLICY ) {
  758. rc = SceInfpWriteSystemAccess(
  759. InfProfileName,
  760. InfoBuffer,
  761. bOverwrite,
  762. Errlog
  763. );
  764. if( rc != SCESTATUS_SUCCESS )
  765. goto Done;
  766. //
  767. // system auditing
  768. //
  769. if ( bOverwrite ) {
  770. rc = SceInfpWriteAuditing(
  771. InfProfileName,
  772. InfoBuffer,
  773. Errlog
  774. );
  775. } else {
  776. rc = SceInfpAppendAuditing(
  777. InfProfileName,
  778. InfoBuffer,
  779. Errlog
  780. );
  781. }
  782. if( rc != SCESTATUS_SUCCESS )
  783. goto Done;
  784. //
  785. // kerberos policy
  786. //
  787. rc = SceInfpWriteKerberosPolicy(
  788. InfProfileName,
  789. InfoBuffer->pKerberosInfo,
  790. bOverwrite,
  791. Errlog
  792. );
  793. if( rc != SCESTATUS_SUCCESS )
  794. goto Done;
  795. //
  796. // regsitry values
  797. //
  798. rc = SceInfpWriteRegistryValues(
  799. InfProfileName,
  800. InfoBuffer->aRegValues,
  801. InfoBuffer->RegValueCount,
  802. bOverwrite,
  803. Errlog
  804. );
  805. if( rc != SCESTATUS_SUCCESS )
  806. goto Done;
  807. }
  808. //
  809. // privilege/rights
  810. //
  811. if ( Area & AREA_PRIVILEGES ) {
  812. rc = SceInfpWritePrivileges(
  813. InfProfileName,
  814. InfoBuffer->OtherInfo.scp.u.pInfPrivilegeAssignedTo,
  815. bOverwrite,
  816. Errlog
  817. );
  818. if( rc != SCESTATUS_SUCCESS )
  819. goto Done;
  820. }
  821. //
  822. // privilege/rights and account profiles for each user
  823. //
  824. #if 0
  825. if ( Area & AREA_USER_SETTINGS ) {
  826. rc = SceInfpWriteUserSettings(
  827. InfProfileName,
  828. InfoBuffer->OtherInfo.scp.pAccountProfiles,
  829. Errlog
  830. );
  831. if( rc != SCESTATUS_SUCCESS )
  832. goto Done;
  833. }
  834. #endif
  835. //
  836. // group memberships
  837. //
  838. if ( Area & AREA_GROUP_MEMBERSHIP ) {
  839. rc = SceInfpWriteGroupMembership(
  840. InfProfileName,
  841. InfoBuffer->pGroupMembership,
  842. bOverwrite,
  843. Errlog
  844. );
  845. if( rc != SCESTATUS_SUCCESS )
  846. goto Done;
  847. }
  848. if ( Revision == 0 ) {
  849. //
  850. // old SDDL format, convert it
  851. //
  852. Area2 = ~Area & (AREA_REGISTRY_SECURITY |
  853. AREA_FILE_SECURITY |
  854. AREA_DS_OBJECTS |
  855. AREA_SYSTEM_SERVICE
  856. );
  857. if ( Area2 > 0 ) {
  858. HINF hInf;
  859. rc = SceInfpOpenProfile(
  860. InfProfileName,
  861. &hInf
  862. );
  863. if ( SCESTATUS_SUCCESS == rc ) {
  864. rc = SceInfpGetSecurityProfileInfo(
  865. hInf,
  866. Area2,
  867. &pNewBuffer,
  868. NULL
  869. );
  870. SceInfpCloseProfile(hInf);
  871. if ( SCESTATUS_SUCCESS != rc ) {
  872. goto Done;
  873. }
  874. } else {
  875. //
  876. // the template can't be opened (new profile)
  877. // ignore the error
  878. //
  879. rc = SCESTATUS_SUCCESS;
  880. }
  881. }
  882. }
  883. //
  884. // registry keys security
  885. //
  886. if ( Area & AREA_REGISTRY_SECURITY ) {
  887. if ( !bOverwrite && pNewBuffer ) {
  888. rc = SceInfpWriteObjects(
  889. InfProfileName,
  890. szRegistryKeys,
  891. pNewBuffer->pRegistryKeys.pAllNodes,
  892. TRUE,
  893. Errlog
  894. );
  895. if( rc != SCESTATUS_SUCCESS )
  896. goto Done;
  897. }
  898. rc = SceInfpWriteObjects(
  899. InfProfileName,
  900. szRegistryKeys,
  901. InfoBuffer->pRegistryKeys.pAllNodes,
  902. bOverwrite,
  903. Errlog
  904. );
  905. if( rc != SCESTATUS_SUCCESS )
  906. goto Done;
  907. } else if ( pNewBuffer ) {
  908. //
  909. // should convert this section to new SDDL format
  910. //
  911. rc = SceInfpWriteObjects(
  912. InfProfileName,
  913. szRegistryKeys,
  914. pNewBuffer->pRegistryKeys.pAllNodes,
  915. TRUE,
  916. Errlog
  917. );
  918. if( rc != SCESTATUS_SUCCESS )
  919. goto Done;
  920. }
  921. //
  922. // file security
  923. //
  924. if ( Area & AREA_FILE_SECURITY ) {
  925. if ( !bOverwrite && pNewBuffer ) {
  926. rc = SceInfpWriteObjects(
  927. InfProfileName,
  928. szFileSecurity,
  929. pNewBuffer->pFiles.pAllNodes,
  930. TRUE,
  931. Errlog
  932. );
  933. if( rc != SCESTATUS_SUCCESS )
  934. goto Done;
  935. }
  936. rc = SceInfpWriteObjects(
  937. InfProfileName,
  938. szFileSecurity,
  939. InfoBuffer->pFiles.pAllNodes,
  940. bOverwrite,
  941. Errlog
  942. );
  943. if( rc != SCESTATUS_SUCCESS )
  944. goto Done;
  945. } else if ( pNewBuffer ) {
  946. //
  947. // should convert this section to new SDDL format
  948. //
  949. rc = SceInfpWriteObjects(
  950. InfProfileName,
  951. szFileSecurity,
  952. pNewBuffer->pFiles.pAllNodes,
  953. TRUE,
  954. Errlog
  955. );
  956. if( rc != SCESTATUS_SUCCESS )
  957. goto Done;
  958. }
  959. #if 0
  960. //
  961. // DS security
  962. //
  963. if ( Area & AREA_DS_OBJECTS ) {
  964. if ( !bOverwrite && pNewBuffer ) {
  965. rc = SceInfpWriteObjects(
  966. InfProfileName,
  967. szDSSecurity,
  968. pNewBuffer->pDsObjects.pAllNodes,
  969. TRUE,
  970. Errlog
  971. );
  972. if( rc != SCESTATUS_SUCCESS )
  973. goto Done;
  974. }
  975. rc = SceInfpWriteObjects(
  976. InfProfileName,
  977. szDSSecurity,
  978. InfoBuffer->pDsObjects.pAllNodes,
  979. bOverwrite,
  980. Errlog
  981. );
  982. if( rc != SCESTATUS_SUCCESS )
  983. goto Done;
  984. } else if ( pNewBuffer ) {
  985. //
  986. // should convert this section to new SDDL format
  987. //
  988. rc = SceInfpWriteObjects(
  989. InfProfileName,
  990. szDSSecurity,
  991. pNewBuffer->pDsObjects.pAllNodes,
  992. TRUE,
  993. Errlog
  994. );
  995. if( rc != SCESTATUS_SUCCESS )
  996. goto Done;
  997. }
  998. #endif
  999. if ( Area & AREA_SYSTEM_SERVICE ) {
  1000. if ( !bOverwrite && pNewBuffer ) {
  1001. rc = SceInfpWriteServices(
  1002. InfProfileName,
  1003. szServiceGeneral,
  1004. pNewBuffer->pServices,
  1005. TRUE,
  1006. Errlog
  1007. );
  1008. if( rc != SCESTATUS_SUCCESS )
  1009. goto Done;
  1010. }
  1011. rc = SceInfpWriteServices(
  1012. InfProfileName,
  1013. szServiceGeneral,
  1014. InfoBuffer->pServices,
  1015. bOverwrite,
  1016. Errlog
  1017. );
  1018. if( rc != SCESTATUS_SUCCESS )
  1019. goto Done;
  1020. } else if ( pNewBuffer ) {
  1021. //
  1022. // should convert this section to new SDDL format
  1023. //
  1024. rc = SceInfpWriteServices(
  1025. InfProfileName,
  1026. szServiceGeneral,
  1027. pNewBuffer->pServices,
  1028. TRUE,
  1029. Errlog
  1030. );
  1031. if( rc != SCESTATUS_SUCCESS )
  1032. goto Done;
  1033. }
  1034. Done:
  1035. if ( rc == SCESTATUS_SUCCESS ) {
  1036. //
  1037. // always write [Version] section.
  1038. //
  1039. WCHAR tmp[64];
  1040. memset(tmp, 0, 64*2);
  1041. wcscpy(tmp, L"signature=\"$CHICAGO$\"");
  1042. swprintf(tmp+wcslen(tmp)+1,L"Revision=%d\0\0",
  1043. SCE_TEMPLATE_MAX_SUPPORTED_VERSION);
  1044. WritePrivateProfileSection(
  1045. L"Version",
  1046. tmp,
  1047. InfProfileName);
  1048. //
  1049. // all data are successfully written
  1050. //
  1051. if ( TargetTempName &&
  1052. (0xFFFFFFFF != GetFileAttributes(szInfProfileName)) ) {
  1053. //
  1054. // now make a copy of the sysvol file first on the target directory
  1055. //
  1056. if ( FALSE == CopyFile( szInfProfileName, TargetTempName, FALSE ) ) {
  1057. Win32rc = GetLastError();
  1058. ScepBuildErrorLogInfo(
  1059. Win32rc,
  1060. Errlog,
  1061. IDS_ERROR_COPY_TEMPLATE,
  1062. Win32rc,
  1063. TargetTempName
  1064. );
  1065. rc = ScepDosErrorToSceStatus(Win32rc);
  1066. #if DBG == 1
  1067. SceDebugPrint(DEB_ERROR, "CopyFile to backup fails with %d\n", Win32rc);
  1068. #endif
  1069. }
  1070. }
  1071. if ( SCESTATUS_SUCCESS == rc ) {
  1072. //
  1073. // now copy the temp file to the real sysvol file
  1074. // make several attempts
  1075. //
  1076. int indx=0;
  1077. while (indx < 5 ) {
  1078. indx++;
  1079. Win32rc = ERROR_SUCCESS;
  1080. rc = SCESTATUS_SUCCESS;
  1081. if ( FALSE == CopyFile( InfProfileName,
  1082. szInfProfileName, FALSE ) ) {
  1083. Win32rc = GetLastError();
  1084. ScepBuildErrorLogInfo(
  1085. Win32rc,
  1086. Errlog,
  1087. IDS_ERROR_COPY_TEMPLATE,
  1088. Win32rc,
  1089. szInfProfileName
  1090. );
  1091. rc = ScepDosErrorToSceStatus(Win32rc);
  1092. #if DBG == 1
  1093. SceDebugPrint(DEB_WARN, "%d attempt of CopyFile fails with %d\n", indx, Win32rc);
  1094. #endif
  1095. } else {
  1096. break;
  1097. }
  1098. Sleep(100);
  1099. }
  1100. ASSERT(ERROR_SUCCESS == Win32rc);
  1101. }
  1102. }
  1103. //
  1104. // delete the temp file for both success and failure case
  1105. //
  1106. DeleteFile(InfProfileName);
  1107. LocalFree(InfProfileName);
  1108. if ( TargetTempName ) {
  1109. //
  1110. // leave the file there if copy fails.
  1111. //
  1112. if ( rc == SCESTATUS_SUCCESS )
  1113. DeleteFile(TargetTempName);
  1114. LocalFree(TargetTempName);
  1115. }
  1116. return(rc);
  1117. }
  1118. SCESTATUS
  1119. SceInfpWriteSystemAccess(
  1120. IN PCWSTR ProfileName,
  1121. IN PSCE_PROFILE_INFO pSCEinfo,
  1122. IN BOOL bOverwrite,
  1123. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1124. )
  1125. /*++
  1126. Routine Description:
  1127. This routine writes system access area information to the INF file
  1128. in section [System Access].
  1129. Arguments:
  1130. ProfileName - The profile to write to
  1131. pSCEinfo - the profile info (SCP) to write.
  1132. Errlog - A buffer to hold all error codes/text encountered when
  1133. parsing the INF file. If Errlog is NULL, no further error
  1134. information is returned except the return DWORD
  1135. Return value:
  1136. SCESTATUS - SCESTATUS_SUCCESS
  1137. SCESTATUS_NOT_ENOUGH_RESOURCE
  1138. SCESTATUS_INVALID_PARAMETER
  1139. SCESTATUS_CORRUPT_PROFILE
  1140. SCESTATUS_INVALID_DATA
  1141. --*/
  1142. {
  1143. SCESTATUS rc=SCESTATUS_SUCCESS;
  1144. DWORD Value;
  1145. PWSTR Strvalue=NULL;
  1146. DWORD TotalSize=0;
  1147. SCE_KEY_LOOKUP AccessSCPLookup[] = {
  1148. {(PWSTR)TEXT("MinimumPasswordAge"), offsetof(struct _SCE_PROFILE_INFO, MinimumPasswordAge), 'D'},
  1149. {(PWSTR)TEXT("MaximumPasswordAge"), offsetof(struct _SCE_PROFILE_INFO, MaximumPasswordAge), 'D'},
  1150. {(PWSTR)TEXT("MinimumPasswordLength"), offsetof(struct _SCE_PROFILE_INFO, MinimumPasswordLength), 'D'},
  1151. {(PWSTR)TEXT("PasswordComplexity"), offsetof(struct _SCE_PROFILE_INFO, PasswordComplexity), 'D'},
  1152. {(PWSTR)TEXT("PasswordHistorySize"), offsetof(struct _SCE_PROFILE_INFO, PasswordHistorySize), 'D'},
  1153. {(PWSTR)TEXT("LockoutBadCount"), offsetof(struct _SCE_PROFILE_INFO, LockoutBadCount), 'D'},
  1154. {(PWSTR)TEXT("ResetLockoutCount"), offsetof(struct _SCE_PROFILE_INFO, ResetLockoutCount), 'D'},
  1155. {(PWSTR)TEXT("LockoutDuration"), offsetof(struct _SCE_PROFILE_INFO, LockoutDuration), 'D'},
  1156. {(PWSTR)TEXT("RequireLogonToChangePassword"), offsetof(struct _SCE_PROFILE_INFO, RequireLogonToChangePassword), 'D'},
  1157. {(PWSTR)TEXT("ForceLogoffWhenHourExpire"), offsetof(struct _SCE_PROFILE_INFO, ForceLogoffWhenHourExpire), 'D'},
  1158. {(PWSTR)TEXT("NewAdministratorName"), 0, 'A'},
  1159. {(PWSTR)TEXT("NewGuestName"), 0, 'G'},
  1160. {(PWSTR)TEXT("ClearTextPassword"), offsetof(struct _SCE_PROFILE_INFO, ClearTextPassword), 'D'},
  1161. {(PWSTR)TEXT("LSAAnonymousNameLookup"), offsetof(struct _SCE_PROFILE_INFO, LSAAnonymousNameLookup), 'D'},
  1162. {(PWSTR)TEXT("EnableAdminAccount"), offsetof(struct _SCE_PROFILE_INFO, EnableAdminAccount), 'D'},
  1163. {(PWSTR)TEXT("EnableGuestAccount"), offsetof(struct _SCE_PROFILE_INFO, EnableGuestAccount), 'D'}
  1164. };
  1165. DWORD cAccess = sizeof(AccessSCPLookup) / sizeof(SCE_KEY_LOOKUP);
  1166. DWORD i, j;
  1167. UINT Offset;
  1168. PWSTR EachLine[25];
  1169. DWORD EachSize[25];
  1170. DWORD Len;
  1171. if (ProfileName == NULL || pSCEinfo == NULL )
  1172. return(SCESTATUS_INVALID_PARAMETER);
  1173. for ( i=0, j=0; i<cAccess; i++) {
  1174. EachLine[i] = NULL;
  1175. EachSize[i] = 0;
  1176. //
  1177. // get settings in AccessLookup table
  1178. //
  1179. Offset = AccessSCPLookup[i].Offset;
  1180. Value = 0;
  1181. Strvalue = NULL;
  1182. Len = wcslen(AccessSCPLookup[i].KeyString);
  1183. switch ( AccessSCPLookup[i].BufferType ) {
  1184. case 'B':
  1185. //
  1186. // Int Field
  1187. //
  1188. Value = *((BOOL *)((CHAR *)pSCEinfo+Offset)) ? 1 : 0;
  1189. EachSize[j] = Len+5;
  1190. break;
  1191. case 'D':
  1192. //
  1193. // Int Field
  1194. //
  1195. Value = *((DWORD *)((CHAR *)pSCEinfo+Offset));
  1196. if ( Value != SCE_NO_VALUE )
  1197. EachSize[j] = Len+15;
  1198. break;
  1199. default:
  1200. //
  1201. // String Field
  1202. //
  1203. switch( AccessSCPLookup[i].BufferType ) {
  1204. case 'A':
  1205. Strvalue = pSCEinfo->NewAdministratorName;
  1206. break;
  1207. case 'G':
  1208. Strvalue = pSCEinfo->NewGuestName;
  1209. break;
  1210. default:
  1211. Strvalue = *((PWSTR *)((CHAR *)pSCEinfo+Offset));
  1212. break;
  1213. }
  1214. if ( Strvalue != NULL ) {
  1215. EachSize[j] = Len+5+wcslen(Strvalue);
  1216. }
  1217. break;
  1218. }
  1219. if ( EachSize[j] <= 0 )
  1220. continue;
  1221. if ( bOverwrite ) {
  1222. Len=(EachSize[j]+1)*sizeof(WCHAR);
  1223. EachLine[j] = (PWSTR)ScepAlloc( LMEM_ZEROINIT, Len);
  1224. if ( EachLine[j] == NULL ) {
  1225. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1226. goto Done;
  1227. }
  1228. if (AccessSCPLookup[i].BufferType != 'B' &&
  1229. AccessSCPLookup[i].BufferType != 'D') {
  1230. swprintf(EachLine[j], L"%s = \"%s\"", AccessSCPLookup[i].KeyString, Strvalue);
  1231. } else {
  1232. swprintf(EachLine[j], L"%s = %d", AccessSCPLookup[i].KeyString, Value);
  1233. EachSize[j] = wcslen(EachLine[j]);
  1234. }
  1235. } else {
  1236. //
  1237. // in append mode, we have to write each line separately
  1238. //
  1239. if (AccessSCPLookup[i].BufferType == 'B' ||
  1240. AccessSCPLookup[i].BufferType == 'D') {
  1241. ScepWriteOneIntValueToProfile(
  1242. ProfileName,
  1243. szSystemAccess,
  1244. AccessSCPLookup[i].KeyString,
  1245. Value
  1246. );
  1247. } else if ( Strvalue ) {
  1248. WritePrivateProfileString (szSystemAccess,
  1249. AccessSCPLookup[i].KeyString,
  1250. Strvalue,
  1251. ProfileName);
  1252. }
  1253. }
  1254. TotalSize += EachSize[j]+1;
  1255. j++;
  1256. }
  1257. //
  1258. // writes the profile section
  1259. //
  1260. if ( bOverwrite ) {
  1261. if ( j > 0 ) {
  1262. rc = SceInfpWriteInfSection(
  1263. ProfileName,
  1264. szSystemAccess,
  1265. TotalSize+1,
  1266. EachLine,
  1267. &EachSize[0],
  1268. 0,
  1269. j-1,
  1270. Errlog
  1271. );
  1272. } else {
  1273. WritePrivateProfileSection(
  1274. szSystemAccess,
  1275. NULL,
  1276. ProfileName);
  1277. }
  1278. }
  1279. Done:
  1280. for ( i=0; i<cAccess; i++ ) {
  1281. if ( EachLine[i] != NULL ) {
  1282. ScepFree(EachLine[i]);
  1283. }
  1284. EachLine[i] = NULL;
  1285. EachSize[i] = 0;
  1286. }
  1287. return(rc);
  1288. }
  1289. SCESTATUS
  1290. SceInfpWritePrivileges(
  1291. IN PCWSTR ProfileName,
  1292. IN PSCE_PRIVILEGE_ASSIGNMENT pPrivileges,
  1293. IN BOOL bOverwrite,
  1294. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1295. )
  1296. /* ++
  1297. Routine Description:
  1298. This routine writes privilege assignments info from the SCP buffer
  1299. into the INF file in section [Privilege Rights].
  1300. Arguments:
  1301. ProfileName - the inf profile name
  1302. pPrivileges - the privilege assignment buffer.
  1303. Errlog - The error list encountered inside inf processing.
  1304. Return value:
  1305. SCESTATUS - SCESTATUS_SUCCESS
  1306. SCESTATUS_NOT_ENOUGH_RESOURCE
  1307. SCESTATUS_INVALID_PARAMETER
  1308. SCESTATUS_BAD_FORMAT
  1309. SCESTATUS_INVALID_DATA
  1310. -- */
  1311. {
  1312. SCESTATUS rc;
  1313. PSCE_PRIVILEGE_ASSIGNMENT pCurRight=NULL;
  1314. PSCE_NAME_LIST pNameList=NULL;
  1315. LONG Keysize;
  1316. PWSTR Strvalue=NULL;
  1317. DWORD TotalSize;
  1318. //
  1319. // [Privilege Rights] section
  1320. //
  1321. if (ProfileName == NULL )
  1322. return(SCESTATUS_INVALID_PARAMETER);
  1323. if ( pPrivileges == NULL ) {
  1324. //
  1325. // the buffer doesn't contain any privileges
  1326. // empty the section in the file
  1327. //
  1328. if ( bOverwrite ) {
  1329. WritePrivateProfileString(
  1330. szPrivilegeRights,
  1331. NULL,
  1332. NULL,
  1333. ProfileName
  1334. );
  1335. }
  1336. return(SCESTATUS_SUCCESS);
  1337. }
  1338. //
  1339. // open lsa policy handle for sid/name lookup
  1340. //
  1341. LSA_HANDLE LsaHandle=NULL;
  1342. rc = RtlNtStatusToDosError(
  1343. ScepOpenLsaPolicy(
  1344. POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION,
  1345. &LsaHandle,
  1346. TRUE
  1347. ));
  1348. if ( ERROR_SUCCESS != rc ) {
  1349. ScepBuildErrorLogInfo(
  1350. rc,
  1351. Errlog,
  1352. SCEERR_ADD,
  1353. TEXT("LSA")
  1354. );
  1355. return(ScepDosErrorToSceStatus(rc));
  1356. }
  1357. for (pCurRight=pPrivileges, TotalSize=0;
  1358. pCurRight != NULL;
  1359. pCurRight = pCurRight->Next) {
  1360. //
  1361. // Each privilege assignment contains the privilege's name and a list
  1362. // of user/groups to assign to.
  1363. //
  1364. Keysize = SceInfpConvertNameListToString(
  1365. LsaHandle,
  1366. pCurRight->Name,
  1367. pCurRight->AssignedTo,
  1368. bOverwrite,
  1369. &Strvalue,
  1370. Errlog
  1371. );
  1372. if ( Keysize >= 0 && Strvalue ) {
  1373. if ( bOverwrite ) {
  1374. rc = ScepAddToNameList(&pNameList, Strvalue, Keysize);
  1375. if ( rc != SCESTATUS_SUCCESS ) { //win32 error code
  1376. ScepBuildErrorLogInfo(
  1377. rc,
  1378. Errlog,
  1379. SCEERR_ADD,
  1380. pCurRight->Name
  1381. );
  1382. goto Done;
  1383. }
  1384. TotalSize += Keysize + 1;
  1385. } else {
  1386. //
  1387. // in append mode, write one line at a time
  1388. //
  1389. WritePrivateProfileString( szPrivilegeRights,
  1390. pCurRight->Name,
  1391. Strvalue,
  1392. ProfileName
  1393. );
  1394. }
  1395. } else if ( Keysize == -1 ) {
  1396. rc = ERROR_EXTENDED_ERROR;
  1397. goto Done;
  1398. }
  1399. ScepFree(Strvalue);
  1400. Strvalue = NULL;
  1401. }
  1402. //
  1403. // writes the profile section
  1404. //
  1405. if ( bOverwrite ) {
  1406. rc = SceInfpWriteListSection(
  1407. ProfileName,
  1408. szPrivilegeRights,
  1409. TotalSize+1,
  1410. pNameList,
  1411. 0, // do not overwrite section, do not add equal sign
  1412. Errlog
  1413. );
  1414. }
  1415. Done:
  1416. if ( Strvalue != NULL )
  1417. ScepFree(Strvalue);
  1418. ScepFreeNameList(pNameList);
  1419. if ( LsaHandle ) {
  1420. LsaClose(LsaHandle);
  1421. }
  1422. return( ScepDosErrorToSceStatus(rc) );
  1423. }
  1424. SCESTATUS
  1425. SceInfpWriteUserSettings(
  1426. IN PCWSTR ProfileName,
  1427. IN PSCE_NAME_LIST pProfiles,
  1428. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1429. )
  1430. /* ++
  1431. Routine Description:
  1432. This routine writes user settings information from the SCP buffer
  1433. into the INF file in section [Account Profiles].
  1434. Arguments:
  1435. ProfileName - the inf profile name
  1436. pProfiles - a list of profiles to write to the section.
  1437. Errlog - The error list encountered inside inf processing.
  1438. Return value:
  1439. SCESTATUS - SCESTATUS_SUCCESS
  1440. SCESTATUS_OTHER_ERROR
  1441. -- */
  1442. {
  1443. DWORD rc;
  1444. PSCE_NAME_LIST pCurProfile;
  1445. DWORD TotalSize;
  1446. if (ProfileName == NULL )
  1447. return(SCESTATUS_INVALID_PARAMETER);
  1448. if ( pProfiles == NULL )
  1449. return(SCESTATUS_SUCCESS);
  1450. for (pCurProfile=pProfiles, TotalSize=0;
  1451. pCurProfile != NULL;
  1452. pCurProfile = pCurProfile->Next) {
  1453. TotalSize += wcslen(pCurProfile->Name) + 3; // " ="
  1454. }
  1455. //
  1456. // write the accountProfile section
  1457. //
  1458. rc = SceInfpWriteListSection(
  1459. ProfileName,
  1460. szAccountProfiles,
  1461. TotalSize+1,
  1462. pProfiles,
  1463. SCEINF_ADD_EQUAL_SIGN,
  1464. Errlog
  1465. );
  1466. if ( rc != NO_ERROR ) {
  1467. ScepBuildErrorLogInfo(rc, Errlog,
  1468. SCEERR_WRITE_INFO,
  1469. szAccountProfiles
  1470. );
  1471. return(ScepDosErrorToSceStatus(rc));
  1472. } else
  1473. return(SCESTATUS_SUCCESS);
  1474. }
  1475. SCESTATUS
  1476. SceInfpWriteGroupMembership(
  1477. IN PCWSTR ProfileName,
  1478. IN PSCE_GROUP_MEMBERSHIP pGroupMembership,
  1479. IN BOOL bOverwrite,
  1480. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1481. )
  1482. /* ++
  1483. Routine Description:
  1484. This routine writes group membership information to the SCP INF file in
  1485. [Group Membership] section.
  1486. Arguments:
  1487. ProfileName - the INF profile name
  1488. pGroupMembership - the group membership info
  1489. Errlog - the error list for errors encountered in this routine.
  1490. Return value:
  1491. SCESTATUS - SCESTATUS_SUCCESS
  1492. SCESTATUS_NOT_ENOUGH_RESOURCE
  1493. SCESTATUS_INVALID_PARAMETER
  1494. SCESTATUS_BAD_FORMAT
  1495. SCESTATUS_INVALID_DATA
  1496. -- */
  1497. {
  1498. PSCE_GROUP_MEMBERSHIP pGroupMembers=NULL;
  1499. PWSTR Strvalue=NULL;
  1500. LONG Keysize;
  1501. SCESTATUS rc=SCESTATUS_SUCCESS;
  1502. DWORD TotalSize;
  1503. PSCE_NAME_LIST pNameList=NULL;
  1504. PWSTR Keyname=NULL;
  1505. DWORD Len;
  1506. PWSTR SidString=NULL;
  1507. if (ProfileName == NULL )
  1508. return(SCESTATUS_INVALID_PARAMETER);
  1509. if ( pGroupMembership == NULL ) {
  1510. //
  1511. // the buffer doesn't contain any groups
  1512. // empty the section in the file
  1513. //
  1514. if ( bOverwrite ) {
  1515. WritePrivateProfileString(
  1516. szGroupMembership,
  1517. NULL,
  1518. NULL,
  1519. ProfileName
  1520. );
  1521. }
  1522. return(SCESTATUS_SUCCESS);
  1523. }
  1524. //
  1525. // open lsa policy handle for sid/name lookup
  1526. //
  1527. LSA_HANDLE LsaHandle=NULL;
  1528. rc = RtlNtStatusToDosError(
  1529. ScepOpenLsaPolicy(
  1530. POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION,
  1531. &LsaHandle,
  1532. TRUE
  1533. ));
  1534. if ( ERROR_SUCCESS != rc ) {
  1535. ScepBuildErrorLogInfo(
  1536. rc,
  1537. Errlog,
  1538. SCEERR_ADD,
  1539. TEXT("LSA")
  1540. );
  1541. return(ScepDosErrorToSceStatus(rc));
  1542. }
  1543. //
  1544. // process each group in the list
  1545. //
  1546. for ( pGroupMembers=pGroupMembership, TotalSize=0;
  1547. pGroupMembers != NULL;
  1548. pGroupMembers = pGroupMembers->Next ) {
  1549. if ( (pGroupMembers->Status & SCE_GROUP_STATUS_NC_MEMBERS) &&
  1550. (pGroupMembers->Status & SCE_GROUP_STATUS_NC_MEMBEROF) ) {
  1551. continue;
  1552. }
  1553. if ( SidString ) {
  1554. LocalFree(SidString);
  1555. SidString = NULL;
  1556. }
  1557. Len = 0;
  1558. if ( wcschr(pGroupMembers->GroupName, L'\\') ) {
  1559. //
  1560. // convert group name into *SID format
  1561. //
  1562. ScepConvertNameToSidString(
  1563. LsaHandle,
  1564. pGroupMembers->GroupName,
  1565. FALSE,
  1566. &SidString,
  1567. &Len
  1568. );
  1569. }
  1570. else {
  1571. if ( ScepLookupNameTable(pGroupMembers->GroupName, &SidString) ) {
  1572. Len = wcslen(SidString);
  1573. }
  1574. }
  1575. if ( SidString == NULL ) {
  1576. Len = wcslen(pGroupMembers->GroupName);
  1577. }
  1578. Keyname = (PWSTR)ScepAlloc( 0, (Len+15)*sizeof(WCHAR));
  1579. if ( Keyname == NULL ) {
  1580. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1581. goto Done;
  1582. }
  1583. if ( SidString ) {
  1584. wcsncpy(Keyname, SidString, Len);
  1585. } else {
  1586. wcsncpy(Keyname, pGroupMembers->GroupName, Len);
  1587. }
  1588. if ( !(pGroupMembers->Status & SCE_GROUP_STATUS_NC_MEMBERS) ) {
  1589. wcscpy(Keyname+Len, szMembers);
  1590. Keyname[Len+9] = L'\0';
  1591. //
  1592. // convert the member list into a string
  1593. //
  1594. Keysize = SceInfpConvertNameListToString(
  1595. LsaHandle,
  1596. Keyname,
  1597. pGroupMembers->pMembers,
  1598. bOverwrite,
  1599. &Strvalue,
  1600. Errlog
  1601. );
  1602. if ( Keysize >= 0 && Strvalue ) {
  1603. if ( bOverwrite ) {
  1604. rc = ScepAddToNameList(&pNameList, Strvalue, Keysize);
  1605. if ( rc != SCESTATUS_SUCCESS ) {
  1606. ScepBuildErrorLogInfo(
  1607. rc,
  1608. Errlog,
  1609. SCEERR_ADD_MEMBERS,
  1610. pGroupMembers->GroupName
  1611. );
  1612. rc = ScepDosErrorToSceStatus(rc);
  1613. goto Done;
  1614. }
  1615. } else {
  1616. //
  1617. // append mode, write one line at a time
  1618. //
  1619. WritePrivateProfileString( szGroupMembership,
  1620. Keyname,
  1621. Strvalue,
  1622. ProfileName
  1623. );
  1624. }
  1625. TotalSize += Keysize + 1;
  1626. } else if ( Keysize == -1 ) {
  1627. rc = SCESTATUS_OTHER_ERROR;
  1628. goto Done;
  1629. }
  1630. ScepFree(Strvalue);
  1631. Strvalue = NULL;
  1632. }
  1633. if ( !(pGroupMembers->Status & SCE_GROUP_STATUS_NC_MEMBEROF) ) {
  1634. //
  1635. // convert the memberof list into a string
  1636. //
  1637. swprintf(Keyname+Len, L"%s", szMemberof);
  1638. Keyname[Len+10] = L'\0';
  1639. Keysize = SceInfpConvertNameListToString(
  1640. LsaHandle,
  1641. Keyname,
  1642. pGroupMembers->pMemberOf,
  1643. bOverwrite,
  1644. &Strvalue,
  1645. Errlog
  1646. );
  1647. if ( Keysize >= 0 && Strvalue ) {
  1648. if ( bOverwrite ) {
  1649. rc = ScepAddToNameList(&pNameList, Strvalue, Keysize);
  1650. if ( rc != SCESTATUS_SUCCESS ) {
  1651. ScepBuildErrorLogInfo(
  1652. rc,
  1653. Errlog,
  1654. SCEERR_ADD_MEMBEROF,
  1655. pGroupMembers->GroupName
  1656. );
  1657. rc = ScepDosErrorToSceStatus(rc);
  1658. goto Done;
  1659. }
  1660. } else {
  1661. //
  1662. // in append mode, write one line at a time
  1663. //
  1664. WritePrivateProfileString( szGroupMembership,
  1665. Keyname,
  1666. Strvalue,
  1667. ProfileName
  1668. );
  1669. }
  1670. TotalSize += Keysize + 1;
  1671. } else if ( Keysize == -1 ) {
  1672. rc = SCESTATUS_OTHER_ERROR;
  1673. goto Done;
  1674. }
  1675. ScepFree(Strvalue);
  1676. Strvalue = NULL;
  1677. }
  1678. }
  1679. //
  1680. // write to this profile's section
  1681. //
  1682. if ( bOverwrite ) {
  1683. rc = SceInfpWriteListSection(
  1684. ProfileName,
  1685. szGroupMembership,
  1686. TotalSize+1,
  1687. pNameList,
  1688. 0,
  1689. Errlog
  1690. );
  1691. rc = ScepDosErrorToSceStatus(rc);
  1692. }
  1693. Done:
  1694. if ( Keyname != NULL )
  1695. ScepFree(Keyname);
  1696. if ( Strvalue != NULL )
  1697. ScepFree(Strvalue);
  1698. if ( SidString ) {
  1699. LocalFree(SidString);
  1700. }
  1701. ScepFreeNameList(pNameList);
  1702. if ( LsaHandle ) {
  1703. LsaClose(LsaHandle);
  1704. }
  1705. return(rc);
  1706. }
  1707. SCESTATUS
  1708. SceInfpWriteObjects(
  1709. IN PCWSTR ProfileName,
  1710. IN PCWSTR SectionName,
  1711. IN PSCE_OBJECT_ARRAY pObjects,
  1712. IN BOOL bOverwrite,
  1713. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1714. )
  1715. /* ++
  1716. Routine Description:
  1717. This routine writes registry or files security information (names and
  1718. security descriptors) into the INF SCP file in the section provided.
  1719. Arguments:
  1720. ProfileName - the SCP INF file name
  1721. SectionName - a individual section name to retrieve. NULL = all sections for
  1722. the area.
  1723. pObjects - the buffer of objects to write.
  1724. Errlog - the cummulative error list to hold errors encountered in this routine.
  1725. Return value:
  1726. SCESTATUS - SCESTATUS_SUCCESS
  1727. SCESTATUS_NOT_ENOUGH_RESOURCE
  1728. SCESTATUS_INVALID_PARAMETER
  1729. SCESTATUS_BAD_FORMAT
  1730. SCESTATUS_INVALID_DATA
  1731. -- */
  1732. {
  1733. SCESTATUS rc=SCESTATUS_SUCCESS;
  1734. PSCE_NAME_LIST pNameList=NULL;
  1735. DWORD TotalSize=0;
  1736. DWORD i, ObjectSize;
  1737. if (ProfileName == NULL || SectionName == NULL )
  1738. return(SCESTATUS_INVALID_PARAMETER);
  1739. if ( pObjects == NULL || pObjects->Count == 0 ) {
  1740. //
  1741. // the buffer doesn't contain any objects
  1742. // empty the section in the file
  1743. //
  1744. if ( bOverwrite ) {
  1745. WritePrivateProfileString(
  1746. SectionName,
  1747. NULL,
  1748. NULL,
  1749. ProfileName
  1750. );
  1751. }
  1752. return(SCESTATUS_SUCCESS);
  1753. }
  1754. for ( i=0; i<pObjects->Count; i++) {
  1755. //
  1756. // Get string fields. Don't care the key name or if it exist.
  1757. // Must have 3 fields each line.
  1758. //
  1759. rc = SceInfpWriteOneObject(
  1760. pObjects->pObjectArray[i],
  1761. &pNameList,
  1762. &ObjectSize,
  1763. Errlog
  1764. );
  1765. if ( rc != SCESTATUS_SUCCESS ) {
  1766. ScepBuildErrorLogInfo(
  1767. rc,
  1768. Errlog,
  1769. SCEERR_WRITE_INFO,
  1770. pObjects->pObjectArray[i]->Name
  1771. );
  1772. goto Done;
  1773. }
  1774. TotalSize += ObjectSize + 1;
  1775. }
  1776. //
  1777. // write to this profile's section
  1778. //
  1779. rc = SceInfpWriteListSection(
  1780. ProfileName,
  1781. SectionName,
  1782. TotalSize+1,
  1783. pNameList,
  1784. bOverwrite ? 0 : SCEINF_APPEND_SECTION,
  1785. Errlog
  1786. );
  1787. if ( rc != SCESTATUS_SUCCESS ) {
  1788. ScepBuildErrorLogInfo(
  1789. rc,
  1790. Errlog,
  1791. SCEERR_WRITE_INFO,
  1792. SectionName
  1793. );
  1794. }
  1795. Done:
  1796. ScepFreeNameList(pNameList);
  1797. rc = ScepDosErrorToSceStatus(rc);
  1798. return(rc);
  1799. }
  1800. SCESTATUS
  1801. SceInfpWriteServices(
  1802. IN PCWSTR ProfileName,
  1803. IN PCWSTR SectionName,
  1804. IN PSCE_SERVICES pServices,
  1805. IN BOOL bOverwrite,
  1806. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1807. )
  1808. /* ++
  1809. Routine Description:
  1810. This routine writes system services general settings (startup and
  1811. security descriptors) into the INF SCP file in the section provided.
  1812. Arguments:
  1813. ProfileName - the SCP INF file name
  1814. SectionName - a individual section name to retrieve. NULL = all sections for
  1815. the area.
  1816. pServices - the buffer of services to write.
  1817. Errlog - the cummulative error list to hold errors encountered in this routine.
  1818. Return value:
  1819. SCESTATUS - SCESTATUS_SUCCESS
  1820. SCESTATUS_NOT_ENOUGH_RESOURCE
  1821. SCESTATUS_INVALID_PARAMETER
  1822. SCESTATUS_BAD_FORMAT
  1823. SCESTATUS_INVALID_DATA
  1824. -- */
  1825. {
  1826. SCESTATUS rc=SCESTATUS_SUCCESS;
  1827. PSCE_NAME_LIST pNameList=NULL;
  1828. PSCE_SERVICES pNode;
  1829. DWORD TotalSize=0;
  1830. DWORD ObjectSize;
  1831. if (ProfileName == NULL || SectionName == NULL )
  1832. return(SCESTATUS_INVALID_PARAMETER);
  1833. if ( pServices == NULL ) {
  1834. //
  1835. // the buffer doesn't contain any services
  1836. // empty the section in the file
  1837. //
  1838. if ( bOverwrite ) {
  1839. WritePrivateProfileString(
  1840. SectionName,
  1841. NULL,
  1842. NULL,
  1843. ProfileName
  1844. );
  1845. }
  1846. return(SCESTATUS_SUCCESS);
  1847. }
  1848. for ( pNode=pServices; pNode != NULL; pNode = pNode->Next) {
  1849. //
  1850. // write string fields.
  1851. //
  1852. rc = SceInfpWriteOneService(
  1853. pNode,
  1854. &pNameList,
  1855. &ObjectSize,
  1856. Errlog
  1857. );
  1858. if ( rc != SCESTATUS_SUCCESS ) {
  1859. ScepBuildErrorLogInfo(
  1860. rc,
  1861. Errlog,
  1862. SCEERR_WRITE_INFO,
  1863. pNode->ServiceName
  1864. );
  1865. goto Done;
  1866. }
  1867. TotalSize += ObjectSize + 1;
  1868. }
  1869. //
  1870. // write to this profile's section
  1871. //
  1872. rc = SceInfpWriteListSection(
  1873. ProfileName,
  1874. SectionName,
  1875. TotalSize+1,
  1876. pNameList,
  1877. bOverwrite ? 0 : SCEINF_APPEND_SECTION,
  1878. Errlog
  1879. );
  1880. if ( rc != SCESTATUS_SUCCESS ) {
  1881. ScepBuildErrorLogInfo(
  1882. rc,
  1883. Errlog,
  1884. SCEERR_WRITE_INFO,
  1885. SectionName
  1886. );
  1887. }
  1888. Done:
  1889. ScepFreeNameList(pNameList);
  1890. rc = ScepDosErrorToSceStatus(rc);
  1891. return(rc);
  1892. }
  1893. DWORD
  1894. SceInfpWriteOneObject(
  1895. IN PSCE_OBJECT_SECURITY pObject,
  1896. OUT PSCE_NAME_LIST *pNameList,
  1897. OUT PDWORD ObjectSize,
  1898. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1899. )
  1900. /* ++
  1901. Routine Description:
  1902. This routine builds security descriptor text for one object (a registry key,
  1903. or a file) into the name list. Each object represents one line in the INF file.
  1904. Arguments:
  1905. pObject - The object's security settings
  1906. pNameList - The output string list.
  1907. TotalSize - the total size of the list
  1908. Errlog - The cummulative error list for errors encountered in this routine
  1909. Return value:
  1910. SCESTATUS - SCESTATUS_SUCCESS
  1911. SCESTATUS_NOT_ENOUGH_RESOURCE
  1912. SCESTATUS_INVALID_PARAMETER
  1913. SCESTATUS_BAD_FORMAT
  1914. SCESTATUS_INVALID_DATA
  1915. -- */
  1916. {
  1917. DWORD rc;
  1918. PWSTR Strvalue=NULL;
  1919. PWSTR SDspec=NULL;
  1920. DWORD SDsize=0;
  1921. DWORD nFields;
  1922. DWORD *aFieldOffset=NULL;
  1923. DWORD i;
  1924. *ObjectSize = 0;
  1925. if ( pObject == NULL )
  1926. return(ERROR_SUCCESS);
  1927. if ( pObject->pSecurityDescriptor != NULL ) {
  1928. //
  1929. // convert security to text
  1930. //
  1931. rc = ConvertSecurityDescriptorToText(
  1932. pObject->pSecurityDescriptor,
  1933. pObject->SeInfo,
  1934. &SDspec,
  1935. &SDsize
  1936. );
  1937. if ( rc != NO_ERROR ) {
  1938. ScepBuildErrorLogInfo(
  1939. rc,
  1940. Errlog,
  1941. SCEERR_BUILD_SD,
  1942. pObject->Name
  1943. );
  1944. return(rc);
  1945. }
  1946. }
  1947. //
  1948. // The Registry/File INF layout must have more than 3 fields for each line.
  1949. // The first field is the key/file name, the 2nd field is the status
  1950. // flag, and the 3rd field and after is the security descriptor in text
  1951. //
  1952. //
  1953. // security descriptor in text is broken into multiple fields if the length
  1954. // is greater than MAX_STRING_LENGTH (the limit of setupapi). The break point
  1955. // is at the following characters: ) ( ; " or space
  1956. //
  1957. rc = SceInfpBreakTextIntoMultiFields(SDspec, SDsize, &nFields, &aFieldOffset);
  1958. if ( SCESTATUS_SUCCESS != rc ) {
  1959. rc = ScepSceStatusToDosError(rc);
  1960. goto Done;
  1961. }
  1962. //
  1963. // each extra field will use 3 more chars : ,"<field>"
  1964. //
  1965. *ObjectSize = wcslen(pObject->Name)+5 + SDsize;
  1966. if ( nFields ) {
  1967. *ObjectSize += 3*nFields;
  1968. } else {
  1969. *ObjectSize += 2;
  1970. }
  1971. //
  1972. // allocate the output buffer
  1973. //
  1974. Strvalue = (PWSTR)ScepAlloc(LMEM_ZEROINIT, (*ObjectSize+1) * sizeof(WCHAR) );
  1975. if ( Strvalue == NULL ) {
  1976. rc = ERROR_NOT_ENOUGH_MEMORY;
  1977. goto Done;
  1978. }
  1979. //
  1980. // copy data into the buffer
  1981. //
  1982. if ( SDspec != NULL ) {
  1983. if ( nFields == 0 || !aFieldOffset ) {
  1984. swprintf(Strvalue, L"\"%s\",%1d,\"%s\"", pObject->Name, pObject->Status, SDspec);
  1985. } else {
  1986. //
  1987. // loop through the fields
  1988. //
  1989. swprintf(Strvalue, L"\"%s\",%1d\0", pObject->Name, pObject->Status);
  1990. for ( i=0; i<nFields; i++ ) {
  1991. if ( aFieldOffset[i] < SDsize ) {
  1992. wcscat(Strvalue, L",\"");
  1993. if ( i == nFields-1 ) {
  1994. //
  1995. // the last field
  1996. //
  1997. wcscat(Strvalue, SDspec+aFieldOffset[i]);
  1998. } else {
  1999. wcsncat(Strvalue, SDspec+aFieldOffset[i],
  2000. aFieldOffset[i+1]-aFieldOffset[i]);
  2001. }
  2002. wcscat(Strvalue, L"\"");
  2003. }
  2004. }
  2005. }
  2006. } else
  2007. swprintf(Strvalue, L"\"%s\",%1d,\"\"", pObject->Name, pObject->Status);
  2008. rc = ScepAddToNameList(pNameList, Strvalue, *ObjectSize);
  2009. ScepFree(Strvalue);
  2010. Done:
  2011. if ( aFieldOffset ) {
  2012. ScepFree(aFieldOffset);
  2013. }
  2014. if ( SDspec != NULL )
  2015. ScepFree(SDspec);
  2016. return(rc);
  2017. }
  2018. DWORD
  2019. SceInfpWriteOneService(
  2020. IN PSCE_SERVICES pService,
  2021. OUT PSCE_NAME_LIST *pNameList,
  2022. OUT PDWORD ObjectSize,
  2023. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2024. )
  2025. /* ++
  2026. Routine Description:
  2027. This routine builds security descriptor text for one object (a registry key,
  2028. or a file) into the name list. Each object represents one line in the INF file.
  2029. Arguments:
  2030. pService - The service's general setting
  2031. pNameList - The output string list.
  2032. TotalSize - the total size of the list
  2033. Errlog - The cummulative error list for errors encountered in this routine
  2034. Return value:
  2035. Win32 error
  2036. -- */
  2037. {
  2038. DWORD rc;
  2039. PWSTR Strvalue=NULL;
  2040. PWSTR SDspec=NULL;
  2041. DWORD SDsize=0;
  2042. DWORD nFields;
  2043. DWORD *aFieldOffset=NULL;
  2044. DWORD i;
  2045. *ObjectSize = 0;
  2046. if ( pService == NULL )
  2047. return(ERROR_SUCCESS);
  2048. if ( pService->General.pSecurityDescriptor != NULL ) {
  2049. //
  2050. // convert security to text
  2051. //
  2052. rc = ConvertSecurityDescriptorToText(
  2053. pService->General.pSecurityDescriptor,
  2054. pService->SeInfo,
  2055. &SDspec,
  2056. &SDsize
  2057. );
  2058. if ( rc != NO_ERROR ) {
  2059. ScepBuildErrorLogInfo(
  2060. rc,
  2061. Errlog,
  2062. SCEERR_BUILD_SD,
  2063. pService->ServiceName
  2064. );
  2065. return(rc);
  2066. }
  2067. }
  2068. //
  2069. // The service INF layout must have 3 or more fields for each line.
  2070. // The first field is the service name, the 2nd field is the startup
  2071. // flag, and the 3rd field and after is the security descriptor in text
  2072. //
  2073. //
  2074. // security descriptor in text is broken into multiple fields if the length
  2075. // is greater than MAX_STRING_LENGTH (the limit of setupapi). The break point
  2076. // is at the following characters: ) ( ; " or space
  2077. //
  2078. rc = SceInfpBreakTextIntoMultiFields(SDspec, SDsize, &nFields, &aFieldOffset);
  2079. if ( SCESTATUS_SUCCESS != rc ) {
  2080. rc = ScepSceStatusToDosError(rc);
  2081. goto Done;
  2082. }
  2083. //
  2084. // each extra field will use 3 more chars : ,"<field>"
  2085. //
  2086. *ObjectSize = wcslen(pService->ServiceName)+3 + SDsize;
  2087. if ( nFields ) {
  2088. *ObjectSize += 3*nFields;
  2089. } else {
  2090. *ObjectSize += 2;
  2091. }
  2092. //
  2093. // allocate the output buffer
  2094. //
  2095. Strvalue = (PWSTR)ScepAlloc(LMEM_ZEROINIT, (*ObjectSize+1) * sizeof(WCHAR) );
  2096. if ( Strvalue == NULL ) {
  2097. rc = ERROR_NOT_ENOUGH_MEMORY;
  2098. goto Done;
  2099. }
  2100. //
  2101. // copy data into the buffer
  2102. //
  2103. if ( SDspec != NULL ) {
  2104. if ( nFields == 0 || !aFieldOffset ) {
  2105. swprintf(Strvalue, L"%s,%1d,\"%s\"", pService->ServiceName,
  2106. pService->Startup, SDspec);
  2107. } else {
  2108. //
  2109. // loop through the fields
  2110. //
  2111. swprintf(Strvalue, L"%s,%1d\0", pService->ServiceName, pService->Startup);
  2112. for ( i=0; i<nFields; i++ ) {
  2113. if ( aFieldOffset[i] < SDsize ) {
  2114. wcscat(Strvalue, L",\"");
  2115. if ( i == nFields-1 ) {
  2116. //
  2117. // the last field
  2118. //
  2119. wcscat(Strvalue, SDspec+aFieldOffset[i]);
  2120. } else {
  2121. wcsncat(Strvalue, SDspec+aFieldOffset[i],
  2122. aFieldOffset[i+1]-aFieldOffset[i]);
  2123. }
  2124. wcscat(Strvalue, L"\"");
  2125. }
  2126. }
  2127. }
  2128. } else {
  2129. swprintf(Strvalue, L"%s,%1d,\"\"", pService->ServiceName, pService->Startup);
  2130. }
  2131. rc = ScepAddToNameList(pNameList, Strvalue, *ObjectSize);
  2132. ScepFree(Strvalue);
  2133. Done:
  2134. if ( aFieldOffset ) {
  2135. ScepFree(aFieldOffset);
  2136. }
  2137. if ( SDspec != NULL )
  2138. ScepFree(SDspec);
  2139. return(rc);
  2140. }
  2141. SCESTATUS
  2142. SceInfpWriteAuditing(
  2143. IN PCWSTR ProfileName,
  2144. IN PSCE_PROFILE_INFO pSCEinfo,
  2145. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2146. )
  2147. /* ++
  2148. Routine Description:
  2149. This routine writes system auditing information into the SCP INF file
  2150. in [System Log], [Security Log], [Application Log], [Event Audit],
  2151. [Registry Audit], and [File Audit] sections.
  2152. Arguments:
  2153. ProfileName - The INF profile's name
  2154. pSCEinfo - the info buffer to write.
  2155. Errlog - The cummulative error list to hold errors encountered in this routine.
  2156. Return value:
  2157. SCESTATUS - SCESTATUS_SUCCESS
  2158. SCESTATUS_NOT_ENOUGH_RESOURCE
  2159. SCESTATUS_INVALID_PARAMETER
  2160. SCESTATUS_BAD_FORMAT
  2161. SCESTATUS_INVALID_DATA
  2162. -- */
  2163. {
  2164. SCESTATUS rc;
  2165. DWORD LogSize;
  2166. DWORD Periods;
  2167. DWORD RetentionDays;
  2168. DWORD RestrictGuest;
  2169. PCWSTR szAuditLog;
  2170. DWORD i, j;
  2171. PWSTR EachLine[10];
  2172. DWORD EachSize[10];
  2173. DWORD TotalSize=0;
  2174. if (ProfileName == NULL || pSCEinfo == NULL )
  2175. return(SCESTATUS_INVALID_PARAMETER);
  2176. //
  2177. // Writes Log setting for system log, security log and application log
  2178. //
  2179. for ( i=0; i<3; i++) {
  2180. // get the section name
  2181. switch (i) {
  2182. case 0:
  2183. szAuditLog = szAuditSystemLog;
  2184. break;
  2185. case 1:
  2186. szAuditLog = szAuditSecurityLog;
  2187. break;
  2188. default:
  2189. szAuditLog = szAuditApplicationLog;
  2190. break;
  2191. }
  2192. // set audit log setting
  2193. LogSize = pSCEinfo->MaximumLogSize[i];
  2194. Periods = pSCEinfo->AuditLogRetentionPeriod[i];
  2195. RetentionDays = pSCEinfo->RetentionDays[i];
  2196. RestrictGuest = pSCEinfo->RestrictGuestAccess[i];
  2197. //
  2198. // writes the setting to the section
  2199. //
  2200. rc = SceInfpWriteAuditLogSetting(
  2201. ProfileName,
  2202. szAuditLog,
  2203. LogSize,
  2204. Periods,
  2205. RetentionDays,
  2206. RestrictGuest,
  2207. Errlog
  2208. );
  2209. if ( rc != SCESTATUS_SUCCESS )
  2210. return(rc);
  2211. }
  2212. //
  2213. // fill the array
  2214. //
  2215. for (i=0; i<10; i++) {
  2216. EachLine[i] = NULL;
  2217. EachSize[i] = 25;
  2218. }
  2219. j = 0;
  2220. //
  2221. // process each attribute for event auditing
  2222. //
  2223. // AuditSystemEvents
  2224. //
  2225. if ( pSCEinfo->AuditSystemEvents != SCE_NO_VALUE ) {
  2226. EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
  2227. if ( EachLine[j] != NULL ) {
  2228. swprintf(EachLine[j], L"AuditSystemEvents = %d\0", pSCEinfo->AuditSystemEvents);
  2229. EachSize[j] = wcslen(EachLine[j]);
  2230. TotalSize += EachSize[j] + 1;
  2231. j++;
  2232. } else {
  2233. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2234. goto Done;
  2235. }
  2236. }
  2237. // AuditLogonEvents
  2238. if ( pSCEinfo->AuditLogonEvents != SCE_NO_VALUE ) {
  2239. EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
  2240. if ( EachLine[j] != NULL ) {
  2241. swprintf(EachLine[j], L"AuditLogonEvents = %d\0", pSCEinfo->AuditLogonEvents);
  2242. EachSize[j] = wcslen(EachLine[j]);
  2243. TotalSize += EachSize[j] + 1;
  2244. j++;
  2245. } else {
  2246. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2247. goto Done;
  2248. }
  2249. }
  2250. // AuditObjectAccess
  2251. if ( pSCEinfo->AuditObjectAccess != SCE_NO_VALUE ) {
  2252. EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
  2253. if ( EachLine[j] != NULL ) {
  2254. swprintf(EachLine[j], L"AuditObjectAccess = %d\0", pSCEinfo->AuditObjectAccess);
  2255. EachSize[j] = wcslen(EachLine[j]);
  2256. TotalSize += EachSize[j] + 1;
  2257. j++;
  2258. } else {
  2259. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2260. goto Done;
  2261. }
  2262. }
  2263. // AuditPrivilegeUse
  2264. if ( pSCEinfo->AuditPrivilegeUse != SCE_NO_VALUE ) {
  2265. EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
  2266. if ( EachLine[j] != NULL ) {
  2267. swprintf(EachLine[j], L"AuditPrivilegeUse = %d\0", pSCEinfo->AuditPrivilegeUse);
  2268. EachSize[j] = wcslen(EachLine[j]);
  2269. TotalSize += EachSize[j] + 1;
  2270. j++;
  2271. } else {
  2272. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2273. goto Done;
  2274. }
  2275. }
  2276. // AuditPolicyChange
  2277. if ( pSCEinfo->AuditPolicyChange != SCE_NO_VALUE ) {
  2278. EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
  2279. if ( EachLine[j] != NULL ) {
  2280. swprintf(EachLine[j], L"AuditPolicyChange = %d\0", pSCEinfo->AuditPolicyChange);
  2281. EachSize[j] = wcslen(EachLine[j]);
  2282. TotalSize += EachSize[j] + 1;
  2283. j++;
  2284. } else {
  2285. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2286. goto Done;
  2287. }
  2288. }
  2289. // AuditAccountManage
  2290. if ( pSCEinfo->AuditAccountManage != SCE_NO_VALUE ) {
  2291. EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
  2292. if ( EachLine[j] != NULL ) {
  2293. swprintf(EachLine[j], L"AuditAccountManage = %d\0", pSCEinfo->AuditAccountManage);
  2294. EachSize[j] = wcslen(EachLine[j]);
  2295. TotalSize += EachSize[j] + 1;
  2296. j++;
  2297. } else {
  2298. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2299. goto Done;
  2300. }
  2301. }
  2302. // AuditprocessTracking
  2303. if ( pSCEinfo->AuditProcessTracking != SCE_NO_VALUE ) {
  2304. EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
  2305. if ( EachLine[j] != NULL ) {
  2306. swprintf(EachLine[j], L"AuditProcessTracking = %d\0", pSCEinfo->AuditProcessTracking);
  2307. EachSize[j] = wcslen(EachLine[j]);
  2308. TotalSize += EachSize[j] + 1;
  2309. j++;
  2310. } else {
  2311. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2312. goto Done;
  2313. }
  2314. }
  2315. // AuditDSAccess
  2316. if ( pSCEinfo->AuditDSAccess != SCE_NO_VALUE ) {
  2317. EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
  2318. if ( EachLine[j] != NULL ) {
  2319. swprintf(EachLine[j], L"AuditDSAccess = %d\0", pSCEinfo->AuditDSAccess);
  2320. EachSize[j] = wcslen(EachLine[j]);
  2321. TotalSize += EachSize[j] + 1;
  2322. j++;
  2323. } else {
  2324. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2325. goto Done;
  2326. }
  2327. }
  2328. // AuditAccountLogon
  2329. if ( pSCEinfo->AuditAccountLogon != SCE_NO_VALUE ) {
  2330. EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
  2331. if ( EachLine[j] != NULL ) {
  2332. swprintf(EachLine[j], L"AuditAccountLogon = %d\0", pSCEinfo->AuditAccountLogon);
  2333. EachSize[j] = wcslen(EachLine[j]);
  2334. TotalSize += EachSize[j] + 1;
  2335. j++;
  2336. } else {
  2337. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2338. goto Done;
  2339. }
  2340. }
  2341. //
  2342. // Writes the section
  2343. //
  2344. if ( j > 0 ) {
  2345. rc = SceInfpWriteInfSection(
  2346. ProfileName,
  2347. szAuditEvent,
  2348. TotalSize+1,
  2349. EachLine,
  2350. &EachSize[0],
  2351. 0,
  2352. j-1,
  2353. Errlog
  2354. );
  2355. } else {
  2356. WritePrivateProfileSection(
  2357. szAuditEvent,
  2358. NULL,
  2359. ProfileName);
  2360. }
  2361. Done:
  2362. for ( i=0; i<10; i++ )
  2363. if ( EachLine[i] != NULL ) {
  2364. ScepFree(EachLine[i]);
  2365. }
  2366. return(rc);
  2367. }
  2368. SCESTATUS
  2369. SceInfpAppendAuditing(
  2370. IN PCWSTR ProfileName,
  2371. IN PSCE_PROFILE_INFO pSCEinfo,
  2372. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2373. )
  2374. {
  2375. SCESTATUS rc=SCESTATUS_SUCCESS;
  2376. DWORD Value;
  2377. SCE_KEY_LOOKUP AuditSCPLookup[] = {
  2378. {(PWSTR)TEXT("AuditSystemEvents"), offsetof(struct _SCE_PROFILE_INFO, AuditSystemEvents), 'D'},
  2379. {(PWSTR)TEXT("AuditLogonEvents"), offsetof(struct _SCE_PROFILE_INFO, AuditLogonEvents), 'D'},
  2380. {(PWSTR)TEXT("AuditObjectAccess"), offsetof(struct _SCE_PROFILE_INFO, AuditObjectAccess), 'D'},
  2381. {(PWSTR)TEXT("AuditPrivilegeUse"), offsetof(struct _SCE_PROFILE_INFO, AuditPrivilegeUse), 'D'},
  2382. {(PWSTR)TEXT("AuditPolicyChange"), offsetof(struct _SCE_PROFILE_INFO, AuditPolicyChange), 'D'},
  2383. {(PWSTR)TEXT("AuditAccountManage"), offsetof(struct _SCE_PROFILE_INFO, AuditAccountManage), 'D'},
  2384. {(PWSTR)TEXT("AuditProcessTracking"), offsetof(struct _SCE_PROFILE_INFO, AuditProcessTracking), 'D'},
  2385. {(PWSTR)TEXT("AuditDSAccess"), offsetof(struct _SCE_PROFILE_INFO, AuditDSAccess), 'D'},
  2386. {(PWSTR)TEXT("AuditAccountLogon"), offsetof(struct _SCE_PROFILE_INFO, AuditAccountLogon), 'D'}
  2387. };
  2388. DWORD cAudit = sizeof(AuditSCPLookup) / sizeof(SCE_KEY_LOOKUP);
  2389. PCWSTR szAuditLog;
  2390. DWORD i;
  2391. UINT Offset;
  2392. if (ProfileName == NULL || pSCEinfo == NULL )
  2393. return(SCESTATUS_INVALID_PARAMETER);
  2394. for ( i=0; i<3; i++) {
  2395. // get the section name
  2396. switch (i) {
  2397. case 0:
  2398. szAuditLog = szAuditSystemLog;
  2399. break;
  2400. case 1:
  2401. szAuditLog = szAuditSecurityLog;
  2402. break;
  2403. default:
  2404. szAuditLog = szAuditApplicationLog;
  2405. break;
  2406. }
  2407. ScepWriteOneIntValueToProfile(
  2408. ProfileName,
  2409. szAuditLog,
  2410. L"MaximumLogSize",
  2411. pSCEinfo->MaximumLogSize[i]
  2412. );
  2413. ScepWriteOneIntValueToProfile(
  2414. ProfileName,
  2415. szAuditLog,
  2416. L"AuditLogRetentionPeriod",
  2417. pSCEinfo->AuditLogRetentionPeriod[i]
  2418. );
  2419. ScepWriteOneIntValueToProfile(
  2420. ProfileName,
  2421. szAuditLog,
  2422. L"RetentionDays",
  2423. pSCEinfo->RetentionDays[i]
  2424. );
  2425. ScepWriteOneIntValueToProfile(
  2426. ProfileName,
  2427. szAuditLog,
  2428. L"RestrictGuestAccess",
  2429. pSCEinfo->RestrictGuestAccess[i]
  2430. );
  2431. }
  2432. for ( i=0; i<cAudit; i++) {
  2433. //
  2434. // get settings in AuditLookup table
  2435. //
  2436. Offset = AuditSCPLookup[i].Offset;
  2437. switch ( AuditSCPLookup[i].BufferType ) {
  2438. case 'D':
  2439. //
  2440. // Int Field
  2441. //
  2442. Value = *((DWORD *)((CHAR *)pSCEinfo+Offset));
  2443. ScepWriteOneIntValueToProfile(
  2444. ProfileName,
  2445. szAuditEvent,
  2446. AuditSCPLookup[i].KeyString,
  2447. Value
  2448. );
  2449. break;
  2450. default:
  2451. break;
  2452. }
  2453. }
  2454. return(rc);
  2455. }
  2456. SCESTATUS
  2457. ScepWriteOneIntValueToProfile(
  2458. IN PCWSTR InfFileName,
  2459. IN PCWSTR InfSectionName,
  2460. IN PWSTR KeyName,
  2461. IN DWORD Value
  2462. )
  2463. {
  2464. WCHAR TmpBuf[15];
  2465. if ( Value == SCE_NO_VALUE ) {
  2466. return(SCESTATUS_SUCCESS);
  2467. }
  2468. swprintf(TmpBuf, L"%d\0", Value);
  2469. WritePrivateProfileString( InfSectionName,
  2470. KeyName,
  2471. TmpBuf,
  2472. InfFileName
  2473. );
  2474. return(SCESTATUS_SUCCESS);
  2475. }
  2476. SCESTATUS
  2477. SceInfpWriteAuditLogSetting(
  2478. IN PCWSTR InfFileName,
  2479. IN PCWSTR InfSectionName,
  2480. IN DWORD LogSize,
  2481. IN DWORD Periods,
  2482. IN DWORD RetentionDays,
  2483. IN DWORD RestrictGuest,
  2484. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2485. )
  2486. /* ++
  2487. Routine Description:
  2488. This routine retrieves audit log setting from the INF file (SCP and SAP)
  2489. based on the SectionName passed in. The audit log settings include MaximumSize,
  2490. RetentionPeriod and RetentionDays. There are 3 different logs (system,
  2491. security, and application) which all have the same setting. The information
  2492. returned in in LogSize, Periods, RetentionDays. These 3 output arguments will
  2493. be reset at the begining of the routine. So if error occurs after the reset,
  2494. the original values won't be set back.
  2495. Arguments:
  2496. InfFileName - The INF file name to write to
  2497. InfSectionName - Log section name (SAdtSystemLog, SAdtSecurityLog, SAdtApplicationLog)
  2498. LogSize - The maximum size of the log
  2499. Periods - The retention period of the log
  2500. RetentionDays - The number of days for log retention
  2501. Errlog - The error list
  2502. Return value:
  2503. SCESTATUS - SCESTATUS_SUCCESS
  2504. SCESTATUS_NOT_ENOUGH_RESOURCE
  2505. SCESTATUS_INVALID_PARAMETER
  2506. SCESTATUS_BAD_FORMAT
  2507. SCESTATUS_INVALID_DATA
  2508. -- */
  2509. {
  2510. SCESTATUS rc=SCESTATUS_SUCCESS;
  2511. PWSTR EachLine[4];
  2512. DWORD EachSize[4];
  2513. DWORD TotalSize=0;
  2514. DWORD i;
  2515. if (InfFileName == NULL || InfSectionName == NULL )
  2516. return(SCESTATUS_INVALID_PARAMETER);
  2517. //
  2518. // initialize and fill the array
  2519. //
  2520. for ( i=0; i<4; i++ ) {
  2521. EachLine[i] = NULL;
  2522. EachSize[i] = 37;
  2523. }
  2524. i = 0;
  2525. if ( LogSize != (DWORD)SCE_NO_VALUE ) {
  2526. EachLine[i] = (PWSTR)ScepAlloc((UINT)0, EachSize[i]*sizeof(WCHAR));
  2527. if ( EachLine[i] != NULL ) {
  2528. swprintf(EachLine[i], L"MaximumLogSize = %d", LogSize);
  2529. EachSize[i] = wcslen(EachLine[i]);
  2530. TotalSize += EachSize[i] + 1;
  2531. i++;
  2532. } else {
  2533. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2534. goto Done;
  2535. }
  2536. }
  2537. if ( Periods != (DWORD)SCE_NO_VALUE ) {
  2538. EachLine[i] = (PWSTR)ScepAlloc((UINT)0, EachSize[i]*sizeof(WCHAR));
  2539. if ( EachLine[i] != NULL ) {
  2540. swprintf(EachLine[i], L"AuditLogRetentionPeriod = %d", Periods);
  2541. EachSize[i] = wcslen(EachLine[i]);
  2542. TotalSize += EachSize[i] + 1;
  2543. i++;
  2544. } else {
  2545. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2546. goto Done;
  2547. }
  2548. }
  2549. if ( RetentionDays != (DWORD)SCE_NO_VALUE ) {
  2550. EachLine[i] = (PWSTR)ScepAlloc((UINT)0, EachSize[i]*sizeof(WCHAR));
  2551. if ( EachLine[i] != NULL ) {
  2552. swprintf(EachLine[i], L"RetentionDays = %d", RetentionDays);
  2553. EachSize[i] = wcslen(EachLine[i]);
  2554. TotalSize += EachSize[i] + 1;
  2555. i++;
  2556. } else {
  2557. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2558. goto Done;
  2559. }
  2560. }
  2561. if ( RestrictGuest != (DWORD)SCE_NO_VALUE ) {
  2562. EachLine[i] = (PWSTR)ScepAlloc((UINT)0, EachSize[i]*sizeof(WCHAR));
  2563. if ( EachLine[i] != NULL ) {
  2564. swprintf(EachLine[i], L"RestrictGuestAccess = %d", RestrictGuest);
  2565. EachSize[i] = wcslen(EachLine[i]);
  2566. TotalSize += EachSize[i] + 1;
  2567. i++;
  2568. } else {
  2569. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2570. goto Done;
  2571. }
  2572. }
  2573. //
  2574. // write this section
  2575. //
  2576. if ( i == 0 ) {
  2577. //
  2578. // all settings are not configured
  2579. // delete the section
  2580. //
  2581. WritePrivateProfileString(
  2582. InfSectionName,
  2583. NULL,
  2584. NULL,
  2585. InfFileName
  2586. );
  2587. } else {
  2588. rc = SceInfpWriteInfSection(
  2589. InfFileName,
  2590. InfSectionName,
  2591. TotalSize+1,
  2592. EachLine,
  2593. &EachSize[0],
  2594. 0,
  2595. i-1,
  2596. Errlog
  2597. );
  2598. }
  2599. Done:
  2600. if ( rc != SCESTATUS_SUCCESS ) {
  2601. ScepBuildErrorLogInfo(
  2602. ScepSceStatusToDosError(rc),
  2603. Errlog,
  2604. SCEERR_WRITE_INFO,
  2605. InfSectionName
  2606. );
  2607. }
  2608. //
  2609. // free memory
  2610. //
  2611. for ( i=0; i<4; i++ ) {
  2612. if ( EachLine[i] != NULL )
  2613. ScepFree(EachLine[i]);
  2614. }
  2615. return(rc);
  2616. }
  2617. SCESTATUS
  2618. SceInfpWriteInfSection(
  2619. IN PCWSTR InfFileName,
  2620. IN PCWSTR InfSectionName,
  2621. IN DWORD TotalSize,
  2622. IN PWSTR *EachLineStr,
  2623. IN DWORD *EachLineSize,
  2624. IN DWORD StartIndex,
  2625. IN DWORD EndIndex,
  2626. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2627. )
  2628. /* ++
  2629. Routine Description:
  2630. This routine writes information in a array (each element in the array
  2631. represents a line in the section) to the section specified by
  2632. InfSectionName in the file specified by InfFileName. TotalSize is used
  2633. to allocate a block of memory for writing.
  2634. Arguments:
  2635. InfFileName - the INF file name
  2636. InfSectionName - the section into which to write information
  2637. TotalSize - The size of the buffer required to write
  2638. EachLineStr - a array of strings (each element represents a line )
  2639. EachLineSize - a array of numbers (each number is the size of the corresponding
  2640. element in EachLineStr).
  2641. StartIndex - The first index of the array
  2642. EndIndex - The last index of the array
  2643. Errlog - The list of errors
  2644. Return value:
  2645. Win32 error code
  2646. -- */
  2647. {
  2648. PWSTR SectionString=NULL;
  2649. PWSTR pTemp;
  2650. DWORD i;
  2651. BOOL status;
  2652. DWORD rc = NO_ERROR;
  2653. if (InfFileName == NULL || InfSectionName == NULL ||
  2654. EachLineStr == NULL || EachLineSize == NULL )
  2655. return(SCESTATUS_INVALID_PARAMETER);
  2656. if ( TotalSize > 1 ) {
  2657. SectionString = (PWSTR)ScepAlloc( (UINT)0, (TotalSize+1)*sizeof(WCHAR));
  2658. if ( SectionString == NULL ) {
  2659. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2660. return(rc);
  2661. }
  2662. pTemp = SectionString;
  2663. for ( i=StartIndex; i<=EndIndex; i++) {
  2664. if ( EachLineStr[i] != NULL && EachLineSize[i] > 0 ) {
  2665. wcsncpy(pTemp, EachLineStr[i], EachLineSize[i]);
  2666. pTemp += EachLineSize[i];
  2667. *pTemp = L'\0';
  2668. pTemp++;
  2669. }
  2670. }
  2671. *pTemp = L'\0';
  2672. //
  2673. // writes the profile section, the following call should empty the section then
  2674. // add all keys in SectionString to the section.
  2675. //
  2676. status = WritePrivateProfileSection(
  2677. InfSectionName,
  2678. SectionString,
  2679. InfFileName
  2680. );
  2681. if ( status == FALSE ) {
  2682. rc = GetLastError();
  2683. ScepBuildErrorLogInfo(
  2684. rc,
  2685. Errlog,
  2686. SCEERR_WRITE_INFO,
  2687. InfSectionName
  2688. );
  2689. }
  2690. ScepFree(SectionString);
  2691. SectionString = NULL;
  2692. }
  2693. return(ScepDosErrorToSceStatus(rc));
  2694. }
  2695. DWORD
  2696. SceInfpWriteListSection(
  2697. IN PCWSTR InfFileName,
  2698. IN PCWSTR InfSectionName,
  2699. IN DWORD TotalSize,
  2700. IN PSCE_NAME_LIST ListLines,
  2701. IN DWORD Option,
  2702. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2703. )
  2704. /* ++
  2705. Routine Description:
  2706. This routine writes information in a PSCE_NAME_LIST type list (each node
  2707. in the list represents a line in the section) to the section specified
  2708. by InfSectionName in the file specified by InfFileName. TotalSize is used
  2709. to allocate a block of memory for writing.
  2710. Arguments:
  2711. InfFileName - the INF file name
  2712. InfSectionName - the section into which to write information
  2713. TotalSize - The size of the buffer required to write
  2714. ListLines - The list of each line's text
  2715. Errlog - The list of errors
  2716. Return value:
  2717. Win32 error code
  2718. -- */
  2719. {
  2720. PWSTR SectionString=NULL;
  2721. PWSTR pTemp;
  2722. PSCE_NAME_LIST pName;
  2723. BOOL status;
  2724. DWORD rc=NO_ERROR;
  2725. DWORD Len;
  2726. if ( TotalSize > 1 ) {
  2727. SectionString = (PWSTR)ScepAlloc( (UINT)0, TotalSize*sizeof(WCHAR));
  2728. if ( SectionString == NULL ) {
  2729. rc = ERROR_NOT_ENOUGH_MEMORY;
  2730. return(rc);
  2731. }
  2732. pTemp = SectionString;
  2733. for ( pName=ListLines; pName != NULL; pName = pName->Next ) {
  2734. Len = wcslen(pName->Name);
  2735. wcsncpy(pTemp, pName->Name, Len);
  2736. pTemp += Len;
  2737. if ( Option & SCEINF_ADD_EQUAL_SIGN ) {
  2738. *pTemp++ = L' ';
  2739. *pTemp++ = L'=';
  2740. }
  2741. *pTemp++ = L'\0';
  2742. }
  2743. *pTemp = L'\0';
  2744. /*
  2745. if ( !( Option & SCEINF_APPEND_SECTION ) ) {
  2746. //
  2747. // empty the section first
  2748. //
  2749. WritePrivateProfileString(
  2750. InfSectionName,
  2751. NULL,
  2752. NULL,
  2753. InfFileName
  2754. );
  2755. }
  2756. //
  2757. // write the section
  2758. //
  2759. status = WritePrivateProfileSection(
  2760. InfSectionName,
  2761. SectionString,
  2762. InfFileName
  2763. );
  2764. */
  2765. //
  2766. // write the section
  2767. //
  2768. rc = ScepWritePrivateProfileSection(
  2769. InfSectionName,
  2770. SectionString,
  2771. InfFileName,
  2772. ( Option & SCEINF_APPEND_SECTION ) ? FALSE : TRUE
  2773. );
  2774. ScepFree(SectionString);
  2775. SectionString = NULL;
  2776. // if ( status == FALSE ) {
  2777. // rc = GetLastError();
  2778. if ( ERROR_SUCCESS != rc ) {
  2779. ScepBuildErrorLogInfo(
  2780. rc,
  2781. Errlog,
  2782. SCEERR_WRITE_INFO,
  2783. InfSectionName
  2784. );
  2785. }
  2786. }
  2787. return(rc);
  2788. }
  2789. LONG
  2790. SceInfpConvertNameListToString(
  2791. IN LSA_HANDLE LsaPolicy,
  2792. IN PCWSTR KeyText,
  2793. IN PSCE_NAME_LIST Fields,
  2794. IN BOOL bOverwrite,
  2795. OUT PWSTR *Strvalue,
  2796. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2797. )
  2798. /* ++
  2799. Routine Description:
  2800. This routine converts names in a name list to comma delimited string.
  2801. The format of the returned string is KeyText = f1,f2,f3,f4... where
  2802. f1..fn are names in the name list.
  2803. Arguments:
  2804. KeyText - a string represents the key (left side of the = sign)
  2805. Fields - The name list
  2806. Strvalue - The output string
  2807. Errlog - The error list
  2808. Return value:
  2809. Length of the output string if successful. -1 if error.
  2810. -- */
  2811. {
  2812. DWORD TotalSize;
  2813. DWORD Strsize;
  2814. PWSTR pTemp = NULL;
  2815. PSCE_NAME_LIST pName;
  2816. SCE_TEMP_NODE *tmpArray=NULL, *pa=NULL;
  2817. DWORD i=0,j;
  2818. DWORD cntAllocated=0;
  2819. DWORD rc=ERROR_SUCCESS;
  2820. //
  2821. // count the total size of all fields
  2822. //
  2823. for ( pName=Fields, TotalSize=0; pName != NULL; pName = pName->Next ) {
  2824. if (pName->Name[0] == L'\0') {
  2825. continue;
  2826. }
  2827. if ( i >= cntAllocated ) {
  2828. //
  2829. // array is not enough, reallocate
  2830. //
  2831. tmpArray = (SCE_TEMP_NODE *)ScepAlloc(LPTR, (cntAllocated+16)*sizeof(SCE_TEMP_NODE));
  2832. if ( tmpArray ) {
  2833. //
  2834. // move pointers from the old array to the new array
  2835. //
  2836. if ( pa ) {
  2837. for ( j=0; j<cntAllocated; j++ ) {
  2838. tmpArray[j].Name = pa[j].Name;
  2839. tmpArray[j].Len = pa[j].Len;
  2840. tmpArray[j].bFree = pa[j].bFree;
  2841. }
  2842. ScepFree(pa);
  2843. }
  2844. pa = tmpArray;
  2845. tmpArray = NULL;
  2846. cntAllocated += 16;
  2847. } else {
  2848. rc = ERROR_NOT_ENOUGH_MEMORY;
  2849. break;
  2850. }
  2851. }
  2852. pTemp = NULL;
  2853. if ( wcschr(pName->Name, L'\\') &&
  2854. LsaPolicy ) {
  2855. //
  2856. // check if the name has a '\' in it, it should be translated to
  2857. // *SID
  2858. //
  2859. ScepConvertNameToSidString(LsaPolicy, pName->Name, FALSE, &pTemp, &Strsize);
  2860. if ( pTemp ) {
  2861. pa[i].Name = pTemp;
  2862. pa[i].bFree = TRUE;
  2863. } else {
  2864. pa[i].Name = pName->Name;
  2865. pa[i].bFree = FALSE;
  2866. Strsize = wcslen(pName->Name);
  2867. }
  2868. } else {
  2869. if ( ScepLookupNameTable(pName->Name, &pTemp) ) {
  2870. pa[i].Name = pTemp;
  2871. pa[i].bFree = TRUE;
  2872. Strsize = wcslen(pTemp);
  2873. }
  2874. else {
  2875. pa[i].Name = pName->Name;
  2876. pa[i].bFree = FALSE;
  2877. Strsize = wcslen(pName->Name);
  2878. }
  2879. }
  2880. pa[i].Len = Strsize;
  2881. TotalSize += Strsize + 1;
  2882. i++;
  2883. }
  2884. if ( ERROR_SUCCESS == rc ) {
  2885. //
  2886. // The format of the string is
  2887. // KeyText = f1,f2,f3,....
  2888. //
  2889. if ( bOverwrite ) {
  2890. Strsize = 3 + wcslen(KeyText);
  2891. if ( TotalSize > 0 )
  2892. TotalSize += Strsize;
  2893. else
  2894. TotalSize = Strsize;
  2895. } else {
  2896. Strsize = 0;
  2897. }
  2898. *Strvalue = (PWSTR)ScepAlloc((UINT)0, (TotalSize+1)*sizeof(WCHAR));
  2899. if ( *Strvalue == NULL ) {
  2900. rc = ERROR_NOT_ENOUGH_MEMORY;
  2901. } else {
  2902. if ( bOverwrite ) {
  2903. swprintf(*Strvalue, L"%s = ", KeyText);
  2904. }
  2905. pTemp = *Strvalue + Strsize;
  2906. for (j=0; j<i; j++) {
  2907. if ( pa[j].Name ) {
  2908. wcscpy(pTemp, pa[j].Name);
  2909. pTemp += pa[j].Len;
  2910. *pTemp = L',';
  2911. pTemp++;
  2912. }
  2913. }
  2914. if ( pTemp != (*Strvalue+Strsize) ) {
  2915. *(pTemp-1) = L'\0';
  2916. }
  2917. *pTemp = L'\0';
  2918. }
  2919. }
  2920. if ( pa ) {
  2921. for ( j=0; j<i; j++ ) {
  2922. if ( pa[j].Name && pa[j].bFree ) {
  2923. ScepFree(pa[j].Name);
  2924. }
  2925. }
  2926. ScepFree(pa);
  2927. }
  2928. if ( rc != ERROR_SUCCESS ) {
  2929. return(-1);
  2930. } else if ( TotalSize == 0 ) {
  2931. return(TotalSize);
  2932. } else {
  2933. return(TotalSize-1);
  2934. }
  2935. }
  2936. #if 0
  2937. SCESTATUS
  2938. WINAPI
  2939. SceWriteUserSection(
  2940. IN PCWSTR InfProfileName,
  2941. IN PWSTR Name,
  2942. IN PSCE_USER_PROFILE pProfile,
  2943. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2944. )
  2945. /* ++
  2946. Routine Description:
  2947. Arguments:
  2948. Return Value:
  2949. -- */
  2950. {
  2951. PWSTR InfSectionName=NULL;
  2952. SCESTATUS rc;
  2953. PWSTR EachLine[12];
  2954. DWORD EachSize[12];
  2955. DWORD TotalSize;
  2956. TCHAR Keyname[SCE_KEY_MAX_LENGTH];
  2957. DWORD Value;
  2958. LONG Keysize, i;
  2959. PSCE_LOGON_HOUR pLogonHour=NULL;
  2960. PWSTR Strvalue=NULL;
  2961. if ( InfProfileName == NULL ||
  2962. Name == NULL ||
  2963. pProfile == NULL ) {
  2964. return(SCESTATUS_INVALID_PARAMETER);
  2965. }
  2966. //
  2967. // process each detail profile section
  2968. //
  2969. for ( i=0; i<12; i++ ) {
  2970. EachLine[i] = NULL;
  2971. EachSize[i] = 0;
  2972. }
  2973. TotalSize=0;
  2974. memset(Keyname, '\0', SCE_KEY_MAX_LENGTH*sizeof(WCHAR));
  2975. i = 0;
  2976. InfSectionName = (PWSTR)ScepAlloc(LMEM_ZEROINIT, (wcslen(Name)+12)*sizeof(WCHAR));
  2977. if ( InfSectionName == NULL )
  2978. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  2979. swprintf(InfSectionName, L"UserProfile %s", Name);
  2980. //
  2981. // initialize the error log buffer
  2982. //
  2983. if ( Errlog ) {
  2984. *Errlog = NULL;
  2985. }
  2986. if ( pProfile->DisallowPasswordChange != SCE_NO_VALUE ) {
  2987. // DisallowPasswordChange
  2988. Value = pProfile->DisallowPasswordChange == 0 ? 0 : 1;
  2989. swprintf(Keyname, L"DisallowPasswordChange = %d", Value);
  2990. rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], 30, Keyname );
  2991. if ( rc != SCESTATUS_SUCCESS) {
  2992. ScepBuildErrorLogInfo(
  2993. ScepSceStatusToDosError(rc),
  2994. Errlog,
  2995. SCEERR_ADDTO,
  2996. L"DisallowPasswordChange",
  2997. InfSectionName
  2998. );
  2999. goto Done;
  3000. }
  3001. TotalSize += EachSize[i]+1;
  3002. i++;
  3003. }
  3004. if ( pProfile->NeverExpirePassword != SCE_NO_VALUE ||
  3005. pProfile->ForcePasswordChange != SCE_NO_VALUE ) {
  3006. // PasswordChangeStyle
  3007. if ( pProfile->NeverExpirePassword != SCE_NO_VALUE &&
  3008. pProfile->NeverExpirePassword != 0 )
  3009. Value = 1;
  3010. else {
  3011. if ( pProfile->ForcePasswordChange != SCE_NO_VALUE &&
  3012. pProfile->ForcePasswordChange != 0 )
  3013. Value = 2;
  3014. else
  3015. Value = 0;
  3016. }
  3017. swprintf(Keyname, L"PasswordChangeStyle = %d", Value);
  3018. rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], 30, Keyname );
  3019. if ( rc != SCESTATUS_SUCCESS) {
  3020. ScepBuildErrorLogInfo(
  3021. ScepSceStatusToDosError(rc),
  3022. Errlog,
  3023. SCEERR_ADDTO,
  3024. L"PasswordChangeStyle",
  3025. InfSectionName
  3026. );
  3027. goto Done;
  3028. }
  3029. TotalSize += EachSize[i]+1;
  3030. i++;
  3031. }
  3032. if ( pProfile->AccountDisabled != SCE_NO_VALUE ) {
  3033. // AccountDisabled
  3034. Value = pProfile->AccountDisabled == 0 ? 0 : 1;
  3035. swprintf(Keyname, L"AccountDisabled = %d", Value);
  3036. rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], 30, Keyname );
  3037. if ( rc != SCESTATUS_SUCCESS) {
  3038. ScepBuildErrorLogInfo(
  3039. ScepSceStatusToDosError(rc),
  3040. Errlog,
  3041. SCEERR_ADDTO,
  3042. L"AccountDisabled",
  3043. InfSectionName
  3044. );
  3045. goto Done;
  3046. }
  3047. TotalSize += EachSize[i]+1;
  3048. i++;
  3049. }
  3050. if ( pProfile->UserProfile != NULL ) {
  3051. // UserProfile
  3052. swprintf(Keyname, L"UserProfile = %s", pProfile->UserProfile);
  3053. rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], wcslen(Keyname)+10, Keyname );
  3054. if ( rc != SCESTATUS_SUCCESS) {
  3055. ScepBuildErrorLogInfo(
  3056. ScepSceStatusToDosError(rc),
  3057. Errlog,
  3058. SCEERR_ADDTO,
  3059. L"UserProfile",
  3060. InfSectionName
  3061. );
  3062. goto Done;
  3063. }
  3064. TotalSize += EachSize[i]+1;
  3065. i++;
  3066. }
  3067. if ( pProfile->LogonScript != NULL ) {
  3068. // LogonScript
  3069. swprintf(Keyname, L"LogonScript = %s", pProfile->LogonScript);
  3070. rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], wcslen(Keyname)+10, Keyname );
  3071. if ( rc != SCESTATUS_SUCCESS) {
  3072. ScepBuildErrorLogInfo(
  3073. ScepSceStatusToDosError(rc),
  3074. Errlog,
  3075. SCEERR_ADDTO,
  3076. L"LogonScript",
  3077. InfSectionName
  3078. );
  3079. goto Done;
  3080. }
  3081. TotalSize += EachSize[i]+1;
  3082. i++;
  3083. }
  3084. if ( pProfile->HomeDir != NULL ) {
  3085. // HomeDir
  3086. swprintf(Keyname, L"HomeDir = %s", pProfile->HomeDir);
  3087. rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], wcslen(Keyname)+10, Keyname );
  3088. if ( rc != SCESTATUS_SUCCESS) {
  3089. ScepBuildErrorLogInfo(
  3090. ScepSceStatusToDosError(rc),
  3091. Errlog,
  3092. SCEERR_ADDTO,
  3093. L"HomeDir",
  3094. InfSectionName
  3095. );
  3096. goto Done;
  3097. }
  3098. TotalSize += EachSize[i]+1;
  3099. i++;
  3100. }
  3101. if ( pProfile->pLogonHours != NULL ) {
  3102. // LogonHours
  3103. swprintf(Keyname, L"LogonHours = ");
  3104. Keysize = wcslen(Keyname);
  3105. for ( pLogonHour=pProfile->pLogonHours;
  3106. pLogonHour != NULL;
  3107. pLogonHour = pLogonHour->Next) {
  3108. swprintf(&Keyname[Keysize], L"%d,%d,",pLogonHour->Start,
  3109. pLogonHour->End);
  3110. Keysize += ((pLogonHour->Start < 9) ? 2 : 3) +
  3111. ((pLogonHour->End < 9 ) ? 2 : 3);
  3112. }
  3113. // turn off the last comma
  3114. Keyname[Keysize-1] = L'\0';
  3115. rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], Keysize+5, Keyname );
  3116. if ( rc != SCESTATUS_SUCCESS) {
  3117. ScepBuildErrorLogInfo(
  3118. ScepSceStatusToDosError(rc),
  3119. Errlog,
  3120. SCEERR_ADDTO,
  3121. L"LogonHours",
  3122. InfSectionName
  3123. );
  3124. goto Done;
  3125. }
  3126. TotalSize += EachSize[i]+1;
  3127. i++;
  3128. }
  3129. if ( pProfile->pWorkstations.Buffer != NULL ) {
  3130. // Workstations
  3131. Keysize = SceInfpConvertMultiSZToString(
  3132. L"Workstations",
  3133. pProfile->pWorkstations,
  3134. &Strvalue,
  3135. Errlog
  3136. );
  3137. if ( Keysize > 0 ) {
  3138. EachLine[i] = Strvalue;
  3139. EachSize[i] = Keysize;
  3140. Strvalue = NULL;
  3141. } else {
  3142. rc = SCESTATUS_OTHER_ERROR;
  3143. ScepFree(Strvalue);
  3144. Strvalue = NULL;
  3145. goto Done;
  3146. }
  3147. if ( rc != SCESTATUS_SUCCESS) {
  3148. ScepBuildErrorLogInfo(
  3149. ScepSceStatusToDosError(rc),
  3150. Errlog,
  3151. SCEERR_ADDTO,
  3152. L"WorkstationRestricitons",
  3153. InfSectionName
  3154. );
  3155. goto Done;
  3156. }
  3157. TotalSize += EachSize[i]+1;
  3158. i++;
  3159. }
  3160. if ( pProfile->pGroupsBelongsTo != NULL ) {
  3161. // GroupsBelongsTo
  3162. Keysize = SceInfpConvertNameListToString(
  3163. NULL,
  3164. L"GroupsBelongsTo",
  3165. pProfile->pGroupsBelongsTo,
  3166. TRUE,
  3167. &Strvalue,
  3168. Errlog
  3169. );
  3170. if ( Keysize > 0 ) {
  3171. EachLine[i] = Strvalue;
  3172. EachSize[i] = Keysize;
  3173. Strvalue = NULL;
  3174. } else {
  3175. rc = SCESTATUS_OTHER_ERROR;
  3176. ScepFree(Strvalue);
  3177. Strvalue = NULL;
  3178. goto Done;
  3179. }
  3180. if ( rc != SCESTATUS_SUCCESS) {
  3181. ScepBuildErrorLogInfo(
  3182. ScepSceStatusToDosError(rc),
  3183. Errlog,
  3184. SCEERR_ADDTO,
  3185. L"GroupsBelongsTo",
  3186. InfSectionName
  3187. );
  3188. goto Done;
  3189. }
  3190. TotalSize += EachSize[i]+1;
  3191. i++;
  3192. }
  3193. if ( pProfile->pAssignToUsers != NULL ) {
  3194. // AssignToUsers
  3195. Keysize = SceInfpConvertNameListToString(
  3196. NULL,
  3197. L"AssignToUsers",
  3198. pProfile->pAssignToUsers,
  3199. TRUE,
  3200. &Strvalue,
  3201. Errlog
  3202. );
  3203. if ( Keysize > 0 ) {
  3204. EachLine[i] = Strvalue;
  3205. EachSize[i] = Keysize;
  3206. Strvalue = NULL;
  3207. } else {
  3208. rc = SCESTATUS_OTHER_ERROR;
  3209. ScepFree(Strvalue);
  3210. Strvalue = NULL;
  3211. goto Done;
  3212. }
  3213. } else {
  3214. swprintf(Keyname, L"AssignToUsers = ");
  3215. rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], 30, Keyname );
  3216. }
  3217. if ( rc != SCESTATUS_SUCCESS) {
  3218. ScepBuildErrorLogInfo(
  3219. ScepSceStatusToDosError(rc),
  3220. Errlog,
  3221. SCEERR_ADDTO,
  3222. L"AssignToUsers",
  3223. InfSectionName
  3224. );
  3225. goto Done;
  3226. }
  3227. TotalSize += EachSize[i]+1;
  3228. i++;
  3229. if ( pProfile->pHomeDirSecurity != NULL ) {
  3230. // HomeDirSecurity
  3231. rc = ConvertSecurityDescriptorToText(
  3232. pProfile->pHomeDirSecurity,
  3233. pProfile->HomeSeInfo,
  3234. &Strvalue,
  3235. (PULONG)&Keysize
  3236. );
  3237. if ( rc == NO_ERROR ) {
  3238. EachSize[i] = Keysize + 21;
  3239. EachLine[i] = (PWSTR)ScepAlloc( 0, EachSize[i]*sizeof(WCHAR));
  3240. if ( EachLine[i] != NULL ) {
  3241. swprintf(EachLine[i], L"HomeDirSecurity = \"%s\"", Strvalue);
  3242. EachLine[i][EachSize[i]-1] = L'\0';
  3243. } else
  3244. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3245. ScepFree(Strvalue);
  3246. Strvalue = NULL;
  3247. } else {
  3248. ScepBuildErrorLogInfo(
  3249. rc,
  3250. Errlog,
  3251. SCEERR_ADD,
  3252. L"HomeDirSecurity",
  3253. InfSectionName
  3254. );
  3255. rc = ScepDosErrorToSceStatus(rc);
  3256. }
  3257. if ( rc != SCESTATUS_SUCCESS )
  3258. goto Done;
  3259. TotalSize += EachSize[i]+1;
  3260. i++;
  3261. }
  3262. if ( pProfile->pTempDirSecurity != NULL ) {
  3263. // TempDirSecurity
  3264. rc = ConvertSecurityDescriptorToText(
  3265. pProfile->pTempDirSecurity,
  3266. pProfile->TempSeInfo,
  3267. &Strvalue,
  3268. (PULONG)&Keysize
  3269. );
  3270. if ( rc == NO_ERROR ) {
  3271. EachSize[i] = Keysize + 21;
  3272. EachLine[i] = (PWSTR)ScepAlloc( 0, EachSize[i]*sizeof(WCHAR));
  3273. if ( EachLine[i] != NULL ) {
  3274. swprintf(EachLine[i], L"TempDirSecurity = \"%s\"", Strvalue);
  3275. EachLine[i][EachSize[i]-1] = L'\0';
  3276. } else
  3277. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3278. ScepFree(Strvalue);
  3279. Strvalue = NULL;
  3280. } else {
  3281. ScepBuildErrorLogInfo(
  3282. rc,
  3283. Errlog,
  3284. SCEERR_ADDTO,
  3285. L"TempDirSecurity",
  3286. InfSectionName
  3287. );
  3288. rc = ScepDosErrorToSceStatus(rc);
  3289. }
  3290. if ( rc != SCESTATUS_SUCCESS )
  3291. goto Done;
  3292. TotalSize += EachSize[i]+1;
  3293. i++;
  3294. }
  3295. //
  3296. // write to this profile's section
  3297. //
  3298. rc = SceInfpWriteInfSection(
  3299. InfProfileName,
  3300. InfSectionName,
  3301. TotalSize+1,
  3302. EachLine,
  3303. &EachSize[0],
  3304. 0,
  3305. i-1,
  3306. Errlog
  3307. );
  3308. if ( rc != SCESTATUS_SUCCESS )
  3309. goto Done;
  3310. Done:
  3311. if ( InfSectionName != NULL )
  3312. ScepFree(InfSectionName);
  3313. if ( Strvalue != NULL )
  3314. ScepFree(Strvalue);
  3315. for ( i=0; i<12; i++ )
  3316. if ( EachLine[i] != NULL )
  3317. ScepFree(EachLine[i]);
  3318. return(rc);
  3319. }
  3320. #endif
  3321. LONG
  3322. SceInfpConvertMultiSZToString(
  3323. IN PCWSTR KeyText,
  3324. IN UNICODE_STRING Fields,
  3325. OUT PWSTR *Strvalue,
  3326. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  3327. )
  3328. /* ++
  3329. Routine Description:
  3330. This routine converts names in a unicode string in Multi-SZ format
  3331. (separated by NULLs) to comma delimited string. The format of the
  3332. returned string is KeyText = f1,f2,f3,f4... where f1..fn are names
  3333. in the unicode string.
  3334. Arguments:
  3335. KeyText - a string represents the key (left side of the = sign)
  3336. Fields - The Multi-SZ string
  3337. Strvalue - The output string
  3338. Errlog - The error list
  3339. Return value:
  3340. Length of the output string if successful. -1 if error.
  3341. -- */
  3342. {
  3343. DWORD TotalSize;
  3344. DWORD Strsize;
  3345. PWSTR pTemp = NULL;
  3346. PWSTR pField=NULL;
  3347. //
  3348. // The format of the string is
  3349. // KeyText = f1,f2,f3,....
  3350. //
  3351. Strsize = 3 + wcslen(KeyText);
  3352. TotalSize = Fields.Length/2 + Strsize;
  3353. *Strvalue = (PWSTR)ScepAlloc((UINT)0, (TotalSize+1)*sizeof(WCHAR));
  3354. if ( *Strvalue == NULL ) {
  3355. return(-1);
  3356. }
  3357. swprintf(*Strvalue, L"%s = ", KeyText);
  3358. pTemp = *Strvalue + Strsize;
  3359. pField = Fields.Buffer;
  3360. while ( pField != NULL && pField[0] ) {
  3361. wcscpy(pTemp, pField);
  3362. Strsize = wcslen(pField);
  3363. pField += Strsize+1;
  3364. pTemp += Strsize;
  3365. *pTemp = L',';
  3366. pTemp++;
  3367. }
  3368. *(pTemp-1) = L'\0';
  3369. *pTemp = L'\0';
  3370. return(TotalSize-1);
  3371. }
  3372. SCESTATUS
  3373. ScepAllocateAndCopy(
  3374. OUT PWSTR *Buffer,
  3375. OUT PDWORD BufSize,
  3376. IN DWORD MaxSize,
  3377. IN PWSTR SrcBuf
  3378. )
  3379. /* ++
  3380. Routine Description:
  3381. Arguments:
  3382. Return value:
  3383. -- */
  3384. {
  3385. *BufSize = 0;
  3386. *Buffer = (PWSTR)ScepAlloc( (UINT)0, MaxSize*sizeof(WCHAR));
  3387. if ( *Buffer == NULL ) {
  3388. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  3389. }
  3390. swprintf(*Buffer, L"%s", SrcBuf);
  3391. *BufSize = wcslen(*Buffer);
  3392. return(SCESTATUS_SUCCESS);
  3393. }
  3394. SCESTATUS
  3395. SceInfpBreakTextIntoMultiFields(
  3396. IN PWSTR szText,
  3397. IN DWORD dLen,
  3398. OUT LPDWORD pnFields,
  3399. OUT LPDWORD *arrOffset
  3400. )
  3401. /*
  3402. If the text length is greater than MAX_STRING_LENGTH-1, this routine will
  3403. find out how many "blocks" the text can be break into (each block is less
  3404. than MAX_STRING_LENGTH-1), and the starting offsets of each block.
  3405. Setupapi has string length limit of MAX_STRING_LENGTH per field in a inf
  3406. file. SCE use setupapi to parse security templates which contain security
  3407. descriptors in text format which can have unlimited aces. So when SCE saves
  3408. text format of security descriptors into a inf file, it will break the text
  3409. into multiple fields if the length is over limit. Setupapi does not have
  3410. limit on number of fields per line.
  3411. The break point occurs when the following characters are encountered in the
  3412. text: ) ( ; " or space
  3413. */
  3414. {
  3415. SCESTATUS rc=SCESTATUS_SUCCESS;
  3416. DWORD nFields;
  3417. DWORD nProc;
  3418. DWORD * newBuffer=NULL;
  3419. DWORD i;
  3420. if ( !pnFields || !arrOffset ) {
  3421. return(SCESTATUS_INVALID_PARAMETER);
  3422. }
  3423. *pnFields = 0;
  3424. *arrOffset = NULL;
  3425. if ( !szText || dLen == 0 ) {
  3426. return(SCESTATUS_SUCCESS);
  3427. }
  3428. //
  3429. // initialize one field always
  3430. //
  3431. nFields = 1;
  3432. *arrOffset = (DWORD *)ScepAlloc(0, nFields*sizeof(DWORD));
  3433. if ( *arrOffset ) {
  3434. (*arrOffset)[0] = 0;
  3435. if ( dLen > MAX_STRING_LENGTH-1 ) {
  3436. //
  3437. // loop through the text
  3438. //
  3439. nProc = (*arrOffset)[nFields-1] + MAX_STRING_LENGTH-2;
  3440. while ( SCESTATUS_SUCCESS == rc && nProc < dLen ) {
  3441. while ( nProc > (*arrOffset)[nFields-1] ) {
  3442. //
  3443. // looking for the break point
  3444. //
  3445. if ( L')' == *(szText+nProc) ||
  3446. L'(' == *(szText+nProc) ||
  3447. L';' == *(szText+nProc) ||
  3448. L' ' == *(szText+nProc) ||
  3449. L'\"' == *(szText+nProc) ) {
  3450. break;
  3451. } else {
  3452. nProc--;
  3453. }
  3454. }
  3455. if ( nProc <= (*arrOffset)[nFields-1] ) {
  3456. //
  3457. // no break point found, then just use MAX_STRING_LENGTH-2
  3458. //
  3459. nProc = (*arrOffset)[nFields-1]+MAX_STRING_LENGTH-2;
  3460. } else {
  3461. //
  3462. // else find a break poin at offset nProc, the next block
  3463. // starts at nProc+1
  3464. //
  3465. nProc++;
  3466. }
  3467. nFields++;
  3468. newBuffer = (DWORD *)ScepAlloc( 0, nFields*sizeof(DWORD));
  3469. if ( newBuffer ) {
  3470. for ( i=0; i<nFields-1; i++ ) {
  3471. newBuffer[i] = (*arrOffset)[i];
  3472. }
  3473. ScepFree(*arrOffset);
  3474. //
  3475. // set the offset to the last element
  3476. //
  3477. newBuffer[nFields-1] = nProc;
  3478. *arrOffset = newBuffer;
  3479. nProc = (*arrOffset)[nFields-1] + MAX_STRING_LENGTH-2;
  3480. } else {
  3481. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3482. }
  3483. }
  3484. }
  3485. *pnFields = nFields;
  3486. } else {
  3487. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3488. }
  3489. if ( SCESTATUS_SUCCESS != rc ) {
  3490. //
  3491. // if error occurs, free memory and clear the output buffer
  3492. //
  3493. *pnFields = 0;
  3494. if ( *arrOffset ) {
  3495. ScepFree(*arrOffset);
  3496. }
  3497. *arrOffset = NULL;
  3498. }
  3499. return(rc);
  3500. }
  3501. SCESTATUS
  3502. SceInfpWriteKerberosPolicy(
  3503. IN PCWSTR ProfileName,
  3504. IN PSCE_KERBEROS_TICKET_INFO pKerberosInfo,
  3505. IN BOOL bOverwrite,
  3506. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  3507. )
  3508. /*++
  3509. Routine Description:
  3510. This routine writes kerberos policy settings information to the INF file
  3511. in section [Kerberos Policy].
  3512. Arguments:
  3513. ProfileName - The profile to write to
  3514. pKerberosInfo - the Kerberos policy info (SCP) to write.
  3515. Errlog - A buffer to hold all error codes/text encountered when
  3516. parsing the INF file. If Errlog is NULL, no further error
  3517. information is returned except the return DWORD
  3518. Return value:
  3519. SCESTATUS - SCESTATUS_SUCCESS
  3520. SCESTATUS_NOT_ENOUGH_RESOURCE
  3521. SCESTATUS_INVALID_PARAMETER
  3522. SCESTATUS_CORRUPT_PROFILE
  3523. SCESTATUS_INVALID_DATA
  3524. --*/
  3525. {
  3526. SCESTATUS rc=SCESTATUS_SUCCESS;
  3527. SCE_KEY_LOOKUP AccessSCPLookup[] = {
  3528. {(PWSTR)TEXT("MaxTicketAge"), offsetof(struct _SCE_KERBEROS_TICKET_INFO_, MaxTicketAge), 'D'},
  3529. {(PWSTR)TEXT("MaxRenewAge"), offsetof(struct _SCE_KERBEROS_TICKET_INFO_, MaxRenewAge), 'D'},
  3530. {(PWSTR)TEXT("MaxServiceAge"), offsetof(struct _SCE_KERBEROS_TICKET_INFO_, MaxServiceAge), 'D'},
  3531. {(PWSTR)TEXT("MaxClockSkew"),offsetof(struct _SCE_KERBEROS_TICKET_INFO_, MaxClockSkew), 'D'},
  3532. {(PWSTR)TEXT("TicketValidateClient"), offsetof(struct _SCE_KERBEROS_TICKET_INFO_, TicketValidateClient), 'D'}
  3533. };
  3534. DWORD cAccess = sizeof(AccessSCPLookup) / sizeof(SCE_KEY_LOOKUP);
  3535. DWORD i, j;
  3536. PWSTR EachLine[10];
  3537. DWORD EachSize[10];
  3538. UINT Offset;
  3539. DWORD Len;
  3540. DWORD Value;
  3541. DWORD TotalSize=0;
  3542. if (!ProfileName ) {
  3543. return(SCESTATUS_INVALID_PARAMETER);
  3544. }
  3545. if ( !pKerberosInfo ) {
  3546. //
  3547. // if no kerberos information to write, just return success
  3548. // empty the section in the file
  3549. //
  3550. if ( bOverwrite ) {
  3551. WritePrivateProfileString(
  3552. szKerberosPolicy,
  3553. NULL,
  3554. NULL,
  3555. ProfileName
  3556. );
  3557. }
  3558. return(SCESTATUS_SUCCESS);
  3559. }
  3560. for ( i=0, j=0; i<cAccess; i++) {
  3561. EachLine[i] = NULL;
  3562. EachSize[i] = 0;
  3563. //
  3564. // get settings in AccessLookup table
  3565. //
  3566. Offset = AccessSCPLookup[i].Offset;
  3567. Value = 0;
  3568. Len = wcslen(AccessSCPLookup[i].KeyString);
  3569. switch ( AccessSCPLookup[i].BufferType ) {
  3570. case 'D':
  3571. //
  3572. // Int Field
  3573. //
  3574. Value = *((DWORD *)((CHAR *)pKerberosInfo+Offset));
  3575. if ( Value != SCE_NO_VALUE ) {
  3576. EachSize[j] = Len+15;
  3577. }
  3578. break;
  3579. default:
  3580. //
  3581. // should not occur
  3582. //
  3583. break;
  3584. }
  3585. if ( EachSize[j] <= 0 )
  3586. continue;
  3587. if ( bOverwrite ) {
  3588. Len=(EachSize[j]+1)*sizeof(WCHAR);
  3589. EachLine[j] = (PWSTR)ScepAlloc( LMEM_ZEROINIT, Len);
  3590. if ( EachLine[j] == NULL ) {
  3591. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3592. goto Done;
  3593. }
  3594. if ( AccessSCPLookup[i].BufferType == 'D' ) {
  3595. swprintf(EachLine[j], L"%s = %d", AccessSCPLookup[i].KeyString, Value);
  3596. EachSize[j] = wcslen(EachLine[j]);
  3597. }
  3598. } else {
  3599. //
  3600. // in append mode, write one string at a time
  3601. //
  3602. ScepWriteOneIntValueToProfile(
  3603. ProfileName,
  3604. szKerberosPolicy,
  3605. AccessSCPLookup[i].KeyString,
  3606. Value
  3607. );
  3608. }
  3609. TotalSize += EachSize[j]+1;
  3610. j++;
  3611. }
  3612. //
  3613. // writes the profile section
  3614. //
  3615. if ( bOverwrite ) {
  3616. if ( j > 0 ) {
  3617. rc = SceInfpWriteInfSection(
  3618. ProfileName,
  3619. szKerberosPolicy,
  3620. TotalSize+1,
  3621. EachLine,
  3622. &EachSize[0],
  3623. 0,
  3624. j-1,
  3625. Errlog
  3626. );
  3627. } else {
  3628. WritePrivateProfileSection(
  3629. szKerberosPolicy,
  3630. NULL,
  3631. ProfileName);
  3632. }
  3633. }
  3634. Done:
  3635. for ( i=0; i<cAccess; i++ ) {
  3636. if ( EachLine[i] != NULL ) {
  3637. ScepFree(EachLine[i]);
  3638. }
  3639. EachLine[i] = NULL;
  3640. EachSize[i] = 0;
  3641. }
  3642. return(rc);
  3643. }
  3644. SCESTATUS
  3645. SceInfpWriteRegistryValues(
  3646. IN PCWSTR ProfileName,
  3647. IN PSCE_REGISTRY_VALUE_INFO pRegValues,
  3648. IN DWORD ValueCount,
  3649. IN BOOL bOverwrite,
  3650. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  3651. )
  3652. /*++
  3653. Routine Description:
  3654. This routine writes registry values to the INF file in section
  3655. [Registry Values].
  3656. Arguments:
  3657. ProfileName - The profile to write to
  3658. pRegValues - the registry values to write (in the format of ValueName=Value)
  3659. ValueCount - the number of values to write
  3660. Errlog - A buffer to hold all error codes/text encountered when
  3661. parsing the INF file. If Errlog is NULL, no further error
  3662. information is returned except the return DWORD
  3663. Return value:
  3664. SCESTATUS - SCESTATUS_SUCCESS
  3665. SCESTATUS_NOT_ENOUGH_RESOURCE
  3666. SCESTATUS_INVALID_PARAMETER
  3667. SCESTATUS_CORRUPT_PROFILE
  3668. SCESTATUS_INVALID_DATA
  3669. --*/
  3670. {
  3671. SCESTATUS rc=SCESTATUS_SUCCESS;
  3672. PSCE_NAME_LIST pNameList=NULL;
  3673. DWORD TotalSize=0;
  3674. DWORD i, ObjectSize;
  3675. if (!ProfileName ) {
  3676. return(SCESTATUS_INVALID_PARAMETER);
  3677. }
  3678. if ( !pRegValues || 0 == ValueCount ) {
  3679. //
  3680. // if no value to write, just return success
  3681. // empty the section in the file
  3682. //
  3683. if ( bOverwrite ) {
  3684. WritePrivateProfileString(
  3685. szRegistryValues,
  3686. NULL,
  3687. NULL,
  3688. ProfileName
  3689. );
  3690. }
  3691. return(SCESTATUS_SUCCESS);
  3692. }
  3693. for ( i=0; i<ValueCount; i++) {
  3694. //
  3695. // Get string fields. Don't care the key name or if it exist.
  3696. // Must have 3 fields each line.
  3697. //
  3698. rc = SceInfpWriteOneValue(
  3699. ProfileName,
  3700. pRegValues[i],
  3701. bOverwrite,
  3702. &pNameList,
  3703. &ObjectSize
  3704. );
  3705. if ( rc != SCESTATUS_SUCCESS ) {
  3706. ScepBuildErrorLogInfo(
  3707. rc,
  3708. Errlog,
  3709. SCEERR_WRITE_INFO,
  3710. pRegValues[i].FullValueName
  3711. );
  3712. goto Done;
  3713. }
  3714. TotalSize += ObjectSize + 1;
  3715. }
  3716. //
  3717. // write to this profile's section
  3718. //
  3719. if ( bOverwrite ) {
  3720. rc = SceInfpWriteListSection(
  3721. ProfileName,
  3722. szRegistryValues,
  3723. TotalSize+1,
  3724. pNameList,
  3725. 0,
  3726. Errlog
  3727. );
  3728. if ( rc != SCESTATUS_SUCCESS )
  3729. ScepBuildErrorLogInfo(
  3730. rc,
  3731. Errlog,
  3732. SCEERR_WRITE_INFO,
  3733. szRegistryValues
  3734. );
  3735. }
  3736. Done:
  3737. ScepFreeNameList(pNameList);
  3738. rc = ScepDosErrorToSceStatus(rc);
  3739. return(rc);
  3740. }
  3741. DWORD
  3742. SceInfpWriteOneValue(
  3743. IN PCWSTR ProfileName,
  3744. IN SCE_REGISTRY_VALUE_INFO RegValue,
  3745. IN BOOL bOverwrite,
  3746. OUT PSCE_NAME_LIST *pNameList,
  3747. OUT PDWORD ObjectSize
  3748. )
  3749. /* ++
  3750. Routine Description:
  3751. This routine builds registry valueName=value for one registry value
  3752. into the name list. Each value represents one line in the INF file.
  3753. Arguments:
  3754. RegValue - The registry value name and the value
  3755. pNameList - The output string list.
  3756. ObjectSize - size of this line
  3757. Return value:
  3758. SCESTATUS - SCESTATUS_SUCCESS
  3759. SCESTATUS_NOT_ENOUGH_RESOURCE
  3760. SCESTATUS_INVALID_PARAMETER
  3761. SCESTATUS_BAD_FORMAT
  3762. SCESTATUS_INVALID_DATA
  3763. -- */
  3764. {
  3765. DWORD rc=ERROR_SUCCESS;
  3766. PWSTR OneLine;
  3767. if ( !pNameList || !ObjectSize ) {
  3768. return(ERROR_INVALID_PARAMETER);
  3769. }
  3770. *ObjectSize = 0;
  3771. if ( RegValue.FullValueName && RegValue.Value ) {
  3772. if ( bOverwrite ) {
  3773. *ObjectSize = wcslen(RegValue.FullValueName);
  3774. }
  3775. if ( RegValue.ValueType == REG_SZ ||
  3776. RegValue.ValueType == REG_EXPAND_SZ ) {
  3777. // need to add "" around the string
  3778. *ObjectSize += (5+wcslen(RegValue.Value));
  3779. } else {
  3780. //
  3781. // to be safe, add more spaces to the buffer
  3782. // because ValueType can be "-1" now
  3783. //
  3784. *ObjectSize += (6+wcslen(RegValue.Value));
  3785. }
  3786. OneLine = (PWSTR)ScepAlloc(0, (*ObjectSize+1)*sizeof(WCHAR));
  3787. if ( OneLine ) {
  3788. if ( bOverwrite ) {
  3789. if ( RegValue.ValueType == REG_SZ ||
  3790. RegValue.ValueType == REG_EXPAND_SZ ) {
  3791. swprintf(OneLine, L"%s=%1d,\"%s\"\0", RegValue.FullValueName,
  3792. RegValue.ValueType, RegValue.Value);
  3793. } else {
  3794. swprintf(OneLine, L"%s=%1d,%s\0", RegValue.FullValueName,
  3795. RegValue.ValueType, RegValue.Value);
  3796. }
  3797. } else {
  3798. if ( RegValue.ValueType == REG_SZ ||
  3799. RegValue.ValueType == REG_EXPAND_SZ ) {
  3800. swprintf(OneLine, L"%1d,\"%s\"\0", RegValue.ValueType, RegValue.Value);
  3801. } else {
  3802. swprintf(OneLine, L"%1d,%s\0", RegValue.ValueType, RegValue.Value);
  3803. }
  3804. }
  3805. OneLine[*ObjectSize] = L'\0';
  3806. if ( bOverwrite ) {
  3807. rc = ScepAddToNameList(pNameList, OneLine, *ObjectSize);
  3808. } else {
  3809. //
  3810. // append mode, write one value at a time
  3811. //
  3812. WritePrivateProfileString( szRegistryValues,
  3813. RegValue.FullValueName,
  3814. OneLine,
  3815. ProfileName
  3816. );
  3817. }
  3818. ScepFree(OneLine);
  3819. } else {
  3820. rc = ERROR_NOT_ENOUGH_MEMORY;
  3821. }
  3822. }
  3823. return(rc);
  3824. }
  3825. SCESTATUS
  3826. WINAPI
  3827. SceSvcSetInformationTemplate(
  3828. IN PCWSTR TemplateName,
  3829. IN PCWSTR ServiceName,
  3830. IN BOOL bExact,
  3831. IN PSCESVC_CONFIGURATION_INFO ServiceInfo
  3832. )
  3833. /*
  3834. Routine Description:
  3835. Writes information to the template in section <ServiceName>. The information is
  3836. stored in ServiceInfo in the format of Key and Value. If bExact is set, only
  3837. exact matched keys are overwritten, else all section is overwritten by the info
  3838. in ServiceInfo.
  3839. When ServiceInfo is NULL and bExact is set, delete the entire section
  3840. Arguments:
  3841. TemplateName - the inf template name to write to
  3842. ServiceName - the section name to write to
  3843. bExact - TRUE = all existing information in the section is erased
  3844. ServiceInfo - the information to write
  3845. Return Value:
  3846. SCE status of this operation
  3847. */
  3848. {
  3849. if ( TemplateName == NULL || ServiceName == NULL ||
  3850. (ServiceInfo == NULL && !bExact ) ) {
  3851. return(SCESTATUS_INVALID_PARAMETER);
  3852. }
  3853. DWORD i;
  3854. if ( ServiceInfo != NULL ) {
  3855. for ( i=0; i<ServiceInfo->Count; i++ ) {
  3856. if ( ServiceInfo->Lines[i].Key == NULL ) {
  3857. return(SCESTATUS_INVALID_DATA);
  3858. }
  3859. }
  3860. }
  3861. //
  3862. // always write [Version] section.
  3863. //
  3864. WCHAR tmp[64];
  3865. memset(tmp, 0, 64*2);
  3866. wcscpy(tmp, L"signature=\"$CHICAGO$\"");
  3867. swprintf(tmp+wcslen(tmp)+1,L"Revision=%d\0\0",
  3868. SCE_TEMPLATE_MAX_SUPPORTED_VERSION);
  3869. WritePrivateProfileSection(
  3870. L"Version",
  3871. tmp,
  3872. TemplateName);
  3873. SCESTATUS rc=SCESTATUS_SUCCESS;
  3874. if ( (bExact && ServiceInfo == NULL) || !bExact ) {
  3875. //
  3876. // delete the entire section
  3877. //
  3878. if ( !WritePrivateProfileString(ServiceName, NULL, NULL, TemplateName) ) {
  3879. rc = ScepDosErrorToSceStatus(GetLastError());
  3880. }
  3881. }
  3882. if ( ServiceInfo == NULL ) {
  3883. return(rc);
  3884. }
  3885. if ( rc == SCESTATUS_SUCCESS ) {
  3886. //
  3887. // process each key/value in ServiceInfo
  3888. //
  3889. for ( i=0; i<ServiceInfo->Count; i++ ) {
  3890. if ( !WritePrivateProfileString(ServiceName,
  3891. ServiceInfo->Lines[i].Key,
  3892. ServiceInfo->Lines[i].Value,
  3893. TemplateName
  3894. ) ) {
  3895. rc = ScepDosErrorToSceStatus(GetLastError());
  3896. break;
  3897. }
  3898. }
  3899. }
  3900. //
  3901. // need to recover the crash - WMI
  3902. //
  3903. return(rc);
  3904. }
  3905. DWORD
  3906. ScepWritePrivateProfileSection(
  3907. IN LPCWSTR SectionName,
  3908. IN LPTSTR pData,
  3909. IN LPCWSTR FileName,
  3910. IN BOOL bOverwrite)
  3911. /*
  3912. Description:
  3913. This function is to provide the same function as WritePrivateProfileSection
  3914. and exceed the 32K limit of that function.
  3915. If the file doesn't exist, the file is always created in UNICODE.
  3916. If the file does exist and it's in UNICODE format (the first two bytes are
  3917. 0xFF, 0xFE), the data will be saved to the file in UNICODE.
  3918. If the file does exist and it's in ANSI format, the data will be saved to
  3919. the file in ANSI format.
  3920. Note, this function assumes that the file is exclusively accessed. It's not
  3921. an atomic operation as WritePrivateProfileSection. But since this is a
  3922. private function implemented for SCE only and SCE always uses temporary
  3923. files (exclusive for each client), there is no problem doing this way.
  3924. Note 2, new data section is always added to the end of the file. Existing
  3925. data in the section will be moved to the end of the file as well.
  3926. Arguments:
  3927. SectionName - the section name to write data to
  3928. FileName - the full path file name to write data to
  3929. pData - data in MULTI-SZ format (with no size limit)
  3930. bOverwrite - TRUE=data will overwrite entire section in the file
  3931. */
  3932. {
  3933. if ( SectionName == NULL || FileName == NULL ) {
  3934. return ERROR_INVALID_PARAMETER;
  3935. }
  3936. DWORD rc=ERROR_SUCCESS;
  3937. //
  3938. // check to see if the file exist
  3939. //
  3940. if ( 0xFFFFFFFF != GetFileAttributes(FileName) ) {
  3941. //
  3942. // file eixsts.
  3943. //
  3944. if ( !bOverwrite && pData != NULL ) {
  3945. //
  3946. // Need to check if the same section exists and if so
  3947. // append the data
  3948. //
  3949. rc = ScepAppendProfileSection(SectionName, FileName, pData);
  3950. } else {
  3951. //
  3952. // the existint data, if any, is not interesting. delete it
  3953. // if the section does not exist at all, the next call won't fail
  3954. //
  3955. if ( !WritePrivateProfileSection(
  3956. SectionName,
  3957. NULL,
  3958. FileName
  3959. ) ) {
  3960. rc = GetLastError();
  3961. } else if ( pData ) {
  3962. //
  3963. // now write the new data in
  3964. //
  3965. rc = ScepOverwriteProfileSection(SectionName,
  3966. FileName,
  3967. pData,
  3968. SCEP_PROFILE_WRITE_SECTIONNAME,
  3969. NULL);
  3970. }
  3971. }
  3972. } else if ( pData ) {
  3973. //
  3974. // the file does not exist, no need to empty existing data
  3975. //
  3976. rc = ScepOverwriteProfileSection(SectionName,
  3977. FileName,
  3978. pData,
  3979. SCEP_PROFILE_WRITE_SECTIONNAME,
  3980. NULL);
  3981. }
  3982. return rc;
  3983. }
  3984. DWORD
  3985. ScepAppendProfileSection(
  3986. IN LPCWSTR SectionName,
  3987. IN LPCWSTR FileName,
  3988. IN LPTSTR pData
  3989. )
  3990. /*
  3991. Description:
  3992. Append the data to the section if the section exists, otherwise, create
  3993. the section and add data to it.
  3994. Arguments:
  3995. SectionName - the section name
  3996. FileName - the file name
  3997. pData - the data to append
  3998. */
  3999. {
  4000. DWORD rc=ERROR_SUCCESS;
  4001. DWORD dwSize;
  4002. PWSTR lpExisting = NULL;
  4003. WCHAR szBuffer[256];
  4004. DWORD nSize=256;
  4005. BOOL bSection=TRUE;
  4006. lpExisting = szBuffer;
  4007. szBuffer[0] = L'\0';
  4008. szBuffer[1] = L'\0';
  4009. PSCEP_SPLAY_TREE pKeys=NULL;
  4010. do {
  4011. //
  4012. // check if the section already exist
  4013. //
  4014. dwSize = GetPrivateProfileSection(SectionName, lpExisting, nSize, FileName );
  4015. if ( dwSize == 0 ) {
  4016. //
  4017. // either failed or the section does not exist
  4018. //
  4019. rc = GetLastError();
  4020. if ( ERROR_FILE_NOT_FOUND == rc ) {
  4021. //
  4022. // the file or section does not exist
  4023. //
  4024. rc = ERROR_SUCCESS;
  4025. break;
  4026. }
  4027. } else if ( dwSize < nSize - 2 ) {
  4028. //
  4029. // data get copied ok because the whole buffer is filled
  4030. //
  4031. break;
  4032. } else {
  4033. //
  4034. // buffer is not big enough, reallocate heap
  4035. //
  4036. if ( lpExisting && lpExisting != szBuffer ) {
  4037. LocalFree(lpExisting);
  4038. }
  4039. nSize += 256;
  4040. lpExisting = (PWSTR)LocalAlloc(LPTR, nSize*sizeof(TCHAR));
  4041. if ( lpExisting == NULL ) {
  4042. rc = ERROR_NOT_ENOUGH_MEMORY;
  4043. }
  4044. }
  4045. } while ( rc == ERROR_SUCCESS );
  4046. if ( ERROR_SUCCESS == rc && lpExisting[0] != L'\0') {
  4047. //
  4048. // now delete the existing section (to make sure the section will
  4049. // always be at the end)
  4050. //
  4051. if ( !WritePrivateProfileSection(
  4052. SectionName,
  4053. NULL,
  4054. FileName
  4055. ) ) {
  4056. //
  4057. // fail to delete the section
  4058. //
  4059. rc = GetLastError();
  4060. } else {
  4061. //
  4062. // save the new data first
  4063. //
  4064. pKeys = ScepSplayInitialize(SplayNodeStringType);
  4065. rc = ScepOverwriteProfileSection(SectionName,
  4066. FileName,
  4067. pData,
  4068. SCEP_PROFILE_WRITE_SECTIONNAME |
  4069. SCEP_PROFILE_GENERATE_KEYS,
  4070. pKeys
  4071. );
  4072. if ( ERROR_SUCCESS == rc ) {
  4073. //
  4074. // now append the old data and check for duplicate
  4075. //
  4076. rc = ScepOverwriteProfileSection(SectionName,
  4077. FileName,
  4078. lpExisting,
  4079. SCEP_PROFILE_CHECK_DUP,
  4080. pKeys
  4081. );
  4082. }
  4083. if ( pKeys ) {
  4084. ScepSplayFreeTree( &pKeys, TRUE );
  4085. }
  4086. }
  4087. } else if ( ERROR_SUCCESS == rc ) {
  4088. //
  4089. // now write the new data
  4090. //
  4091. rc = ScepOverwriteProfileSection(SectionName,
  4092. FileName,
  4093. pData,
  4094. SCEP_PROFILE_WRITE_SECTIONNAME,
  4095. NULL
  4096. );
  4097. }
  4098. //
  4099. // free existing data buffer
  4100. //
  4101. if ( lpExisting && (lpExisting != szBuffer) ) {
  4102. LocalFree(lpExisting);
  4103. }
  4104. return rc;
  4105. }
  4106. DWORD
  4107. ScepOverwriteProfileSection(
  4108. IN LPCWSTR SectionName,
  4109. IN LPCWSTR FileName,
  4110. IN LPTSTR pData,
  4111. IN DWORD dwFlags,
  4112. IN OUT PSCEP_SPLAY_TREE pKeys OPTIONAL
  4113. )
  4114. /*
  4115. Description:
  4116. Writes data to the section. Old data in the section will be overwritten.
  4117. Arguments:
  4118. SectionName - section name to write to
  4119. FileName - file name
  4120. pData - data to write
  4121. dwFlags - flags (write section name, generate keys, check duplicate)
  4122. pKeys - the keys to generate or check duplicate
  4123. */
  4124. {
  4125. DWORD rc=ERROR_SUCCESS;
  4126. HANDLE hFile=INVALID_HANDLE_VALUE;
  4127. BOOL bUnicode;
  4128. DWORD dwBytesWritten;
  4129. //
  4130. // try create the new file
  4131. //
  4132. hFile = CreateFile(FileName,
  4133. GENERIC_READ | GENERIC_WRITE,
  4134. 0,
  4135. NULL,
  4136. CREATE_NEW,
  4137. FILE_ATTRIBUTE_NORMAL,
  4138. NULL);
  4139. if (hFile != INVALID_HANDLE_VALUE) {
  4140. //
  4141. // this is a new file, created successfully.
  4142. // now make it UNICODE
  4143. //
  4144. BYTE tmpBuf[3];
  4145. tmpBuf[0] = 0xFF;
  4146. tmpBuf[1] = 0xFE;
  4147. tmpBuf[2] = 0;
  4148. if ( !WriteFile (hFile, (LPCVOID)&tmpBuf, 2,
  4149. &dwBytesWritten,
  4150. NULL) )
  4151. return GetLastError();
  4152. bUnicode = TRUE;
  4153. } else {
  4154. //
  4155. // open the file exclusively
  4156. //
  4157. hFile = CreateFile(FileName,
  4158. GENERIC_READ | GENERIC_WRITE,
  4159. 0,
  4160. NULL,
  4161. OPEN_ALWAYS,
  4162. FILE_ATTRIBUTE_NORMAL,
  4163. NULL);
  4164. if (hFile != INVALID_HANDLE_VALUE) {
  4165. SetFilePointer (hFile, 0, NULL, FILE_BEGIN);
  4166. //
  4167. // check the first byte of the file to see if it's UNICODE
  4168. //
  4169. BYTE tmpBytes[3];
  4170. tmpBytes[0] = 0;
  4171. tmpBytes[1] = 0;
  4172. if ( ReadFile(hFile, (LPVOID)tmpBytes, 2, &dwBytesWritten, NULL ) &&
  4173. dwBytesWritten == 2 ) {
  4174. if ( tmpBytes[0] == 0xFF && tmpBytes[1] == 0xFE ) {
  4175. bUnicode = TRUE;
  4176. } else {
  4177. bUnicode = FALSE;
  4178. }
  4179. } else {
  4180. //
  4181. // if fails to verify the file, assume it's UNICODE
  4182. //
  4183. bUnicode = TRUE;
  4184. }
  4185. }
  4186. }
  4187. PWSTR pKeyStr=NULL;
  4188. if (hFile != INVALID_HANDLE_VALUE) {
  4189. SetFilePointer (hFile, 0, NULL, FILE_END);
  4190. if ( dwFlags & SCEP_PROFILE_WRITE_SECTIONNAME ) {
  4191. //
  4192. // save the section name first
  4193. //
  4194. rc = ScepWriteStrings(hFile, bUnicode, L"[", 1, (PWSTR)SectionName, 0, L"]", 1, TRUE);
  4195. }
  4196. if ( ERROR_SUCCESS == rc ) {
  4197. LPTSTR pTemp=pData;
  4198. LPTSTR pTemp1=pData;
  4199. BOOL bExists, bKeyCopied;
  4200. DWORD rc1;
  4201. DWORD Len;
  4202. //
  4203. // write each string in the MULTI-SZ string separately, with a \r\n
  4204. //
  4205. while ( *pTemp1 ) {
  4206. //
  4207. // count to the \0
  4208. //
  4209. bKeyCopied = FALSE;
  4210. if ( pKeyStr ) {
  4211. LocalFree(pKeyStr);
  4212. pKeyStr = NULL;
  4213. }
  4214. while (*pTemp) {
  4215. if ( pKeys &&
  4216. ( (dwFlags & SCEP_PROFILE_GENERATE_KEYS) ||
  4217. (dwFlags & SCEP_PROFILE_CHECK_DUP) ) &&
  4218. !bKeyCopied &&
  4219. (*pTemp == L'=' || *pTemp == L',') ) {
  4220. //
  4221. // there is a key to remember
  4222. //
  4223. Len = (DWORD)(pTemp-pTemp1);
  4224. pKeyStr = (PWSTR)ScepAlloc(LPTR, (Len+1)*sizeof(WCHAR));
  4225. if ( pKeyStr ) {
  4226. wcsncpy(pKeyStr, pTemp1, pTemp-pTemp1);
  4227. bKeyCopied = TRUE;
  4228. } else {
  4229. rc = ERROR_NOT_ENOUGH_MEMORY;
  4230. break;
  4231. }
  4232. }
  4233. pTemp++;
  4234. }
  4235. if ( ERROR_SUCCESS != rc )
  4236. break;
  4237. if ( bKeyCopied ) {
  4238. if ( dwFlags & SCEP_PROFILE_GENERATE_KEYS ) {
  4239. //
  4240. // add it to the splay list
  4241. //
  4242. rc1 = ScepSplayInsert( (PVOID)pKeyStr, pKeys, &bExists );
  4243. } else if ( dwFlags & SCEP_PROFILE_CHECK_DUP ) {
  4244. //
  4245. // check if the key already exists in the splay list
  4246. //
  4247. if ( ScepSplayValueExist( (PVOID)pKeyStr, pKeys) ) {
  4248. //
  4249. // this is a duplicate entry, continue
  4250. //
  4251. pTemp++;
  4252. pTemp1 = pTemp;
  4253. continue;
  4254. }
  4255. }
  4256. }
  4257. Len = (DWORD)(pTemp-pTemp1);
  4258. rc = ScepWriteStrings(hFile,
  4259. bUnicode, // write it in UNICODE or ANSI
  4260. NULL, // no prefix
  4261. 0,
  4262. pTemp1, // the string
  4263. Len,
  4264. NULL, // no suffix
  4265. 0,
  4266. TRUE // add \r\n
  4267. );
  4268. if ( ERROR_SUCCESS != rc )
  4269. break;
  4270. pTemp++;
  4271. pTemp1 = pTemp;
  4272. }
  4273. }
  4274. CloseHandle (hFile);
  4275. } else {
  4276. rc = GetLastError();
  4277. }
  4278. if ( pKeyStr ) {
  4279. LocalFree(pKeyStr);
  4280. }
  4281. return rc;
  4282. }
  4283. DWORD
  4284. ScepWriteStrings(
  4285. IN HANDLE hFile,
  4286. IN BOOL bUnicode,
  4287. IN PWSTR szPrefix OPTIONAL,
  4288. IN DWORD dwPrefixLen,
  4289. IN PWSTR szString,
  4290. IN DWORD dwStrLen,
  4291. IN PWSTR szSuffix OPTIONAL,
  4292. IN DWORD dwSuffixLen,
  4293. IN BOOL bCRLF
  4294. )
  4295. /*
  4296. Description:
  4297. Write data to the file. Data can have prefix and/or suffix, and followed
  4298. by a \r\n optionally.
  4299. Data will be write in UNICODE or ANSI format based on the input paramter
  4300. bUnicode. If ANSI format is desired, the wide chars are converted to
  4301. multi-byte buffers then write to the file.
  4302. Arguments:
  4303. hFile - file handle
  4304. bUnicode - the file format (UNICODE=TRUE or ANSI=FALSE)
  4305. szPrefix - the optional prefix string
  4306. dwPrefixLen - the optional prefix string length (in wchars)
  4307. szString - the string to write
  4308. dwStrLen - the string length
  4309. szSuffix - the optional suffix string
  4310. dwSuffixLen - the optional suffix string length (in wchars)
  4311. bCRLF - if \r\n should be added
  4312. */
  4313. {
  4314. DWORD rc=ERROR_SUCCESS;
  4315. PWSTR pwBuffer=NULL;
  4316. DWORD dwTotal=0;
  4317. PVOID pBuf=NULL;
  4318. PCHAR pStr=NULL;
  4319. DWORD dwBytes=0;
  4320. //
  4321. // validate parameters
  4322. //
  4323. if ( hFile == NULL || szString == NULL ) {
  4324. return ERROR_INVALID_PARAMETER;
  4325. }
  4326. if ( szPrefix && dwPrefixLen == 0 ) {
  4327. dwPrefixLen = wcslen(szPrefix);
  4328. }
  4329. if ( szSuffix && dwSuffixLen == 0 ) {
  4330. dwSuffixLen = wcslen(szSuffix);
  4331. }
  4332. if ( dwStrLen == 0 ) {
  4333. dwStrLen = wcslen(szString);
  4334. }
  4335. //
  4336. // get total length
  4337. //
  4338. dwTotal = dwPrefixLen + dwStrLen + dwSuffixLen;
  4339. if ( dwTotal == 0 && !bCRLF ) {
  4340. //
  4341. // nothing to write
  4342. //
  4343. return ERROR_SUCCESS;
  4344. }
  4345. if ( bCRLF ) {
  4346. //
  4347. // add \r\n
  4348. //
  4349. dwTotal += 2;
  4350. }
  4351. //
  4352. // allocate buffer
  4353. //
  4354. pwBuffer = (PWSTR)LocalAlloc(LPTR, (dwTotal+1)*sizeof(TCHAR));
  4355. if ( pwBuffer == NULL ) {
  4356. return ERROR_NOT_ENOUGH_MEMORY;
  4357. }
  4358. //
  4359. // copy all data to the buffer
  4360. //
  4361. if ( szPrefix ) {
  4362. wcsncpy(pwBuffer, szPrefix, dwPrefixLen);
  4363. }
  4364. wcsncat(pwBuffer, szString, dwStrLen);
  4365. if ( szSuffix ) {
  4366. wcsncat(pwBuffer, szSuffix, dwSuffixLen);
  4367. }
  4368. if ( bCRLF ) {
  4369. wcscat(pwBuffer, c_szCRLF);
  4370. }
  4371. if ( !bUnicode ) {
  4372. //
  4373. // convert WCHAR into ANSI
  4374. //
  4375. dwBytes = WideCharToMultiByte(CP_THREAD_ACP,
  4376. 0,
  4377. pwBuffer,
  4378. dwTotal,
  4379. NULL,
  4380. 0,
  4381. NULL,
  4382. NULL
  4383. );
  4384. if ( dwBytes > 0 ) {
  4385. //
  4386. // allocate buffer
  4387. //
  4388. pStr = (PCHAR)LocalAlloc(LPTR, dwBytes+1);
  4389. if ( pStr == NULL ) {
  4390. rc = ERROR_NOT_ENOUGH_MEMORY;
  4391. } else {
  4392. dwBytes = WideCharToMultiByte(CP_THREAD_ACP,
  4393. 0,
  4394. pwBuffer,
  4395. dwTotal,
  4396. pStr,
  4397. dwBytes,
  4398. NULL,
  4399. NULL
  4400. );
  4401. if ( dwBytes > 0 ) {
  4402. pBuf = (PVOID)pStr;
  4403. } else {
  4404. rc = GetLastError();
  4405. }
  4406. }
  4407. } else {
  4408. rc = GetLastError();
  4409. }
  4410. } else {
  4411. //
  4412. // write in UNICODE, use the existing buffer
  4413. //
  4414. pBuf = (PVOID)pwBuffer;
  4415. dwBytes = dwTotal*sizeof(WCHAR);
  4416. }
  4417. //
  4418. // write to the file
  4419. //
  4420. DWORD dwBytesWritten=0;
  4421. if ( pBuf ) {
  4422. if ( WriteFile (hFile, (LPCVOID)pBuf, dwBytes,
  4423. &dwBytesWritten,
  4424. NULL) ) {
  4425. if ( dwBytesWritten != dwBytes ) {
  4426. //
  4427. // not all data is written
  4428. //
  4429. rc = ERROR_INVALID_DATA;
  4430. }
  4431. } else {
  4432. rc = GetLastError();
  4433. }
  4434. }
  4435. if ( pStr ) {
  4436. LocalFree(pStr);
  4437. }
  4438. //
  4439. // free buffer
  4440. //
  4441. LocalFree(pwBuffer);
  4442. return(rc);
  4443. }