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

5569 lines
152 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. TRUE,
  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] = {0};
  1169. DWORD EachSize[25] = {0};
  1170. DWORD Len;
  1171. if (ProfileName == NULL || pSCEinfo == NULL )
  1172. return(SCESTATUS_INVALID_PARAMETER);
  1173. for ( i=0, j=0; i<cAccess; i++) {
  1174. //
  1175. // get settings in AccessLookup table
  1176. //
  1177. Offset = AccessSCPLookup[i].Offset;
  1178. Value = 0;
  1179. Strvalue = NULL;
  1180. Len = wcslen(AccessSCPLookup[i].KeyString);
  1181. switch ( AccessSCPLookup[i].BufferType ) {
  1182. case 'B':
  1183. //
  1184. // Int Field
  1185. //
  1186. Value = *((BOOL *)((CHAR *)pSCEinfo+Offset)) ? 1 : 0;
  1187. EachSize[j] = Len+5;
  1188. break;
  1189. case 'D':
  1190. //
  1191. // Int Field
  1192. //
  1193. Value = *((DWORD *)((CHAR *)pSCEinfo+Offset));
  1194. if ( Value != SCE_NO_VALUE )
  1195. EachSize[j] = Len+15;
  1196. break;
  1197. default:
  1198. //
  1199. // String Field
  1200. //
  1201. switch( AccessSCPLookup[i].BufferType ) {
  1202. case 'A':
  1203. Strvalue = pSCEinfo->NewAdministratorName;
  1204. break;
  1205. case 'G':
  1206. Strvalue = pSCEinfo->NewGuestName;
  1207. break;
  1208. default:
  1209. Strvalue = *((PWSTR *)((CHAR *)pSCEinfo+Offset));
  1210. break;
  1211. }
  1212. if ( Strvalue != NULL ) {
  1213. EachSize[j] = Len+5+wcslen(Strvalue);
  1214. }
  1215. break;
  1216. }
  1217. if ( EachSize[j] <= 0 )
  1218. continue;
  1219. if ( bOverwrite ) {
  1220. Len=(EachSize[j]+1)*sizeof(WCHAR);
  1221. EachLine[j] = (PWSTR)ScepAlloc( LMEM_ZEROINIT, Len);
  1222. if ( EachLine[j] == NULL ) {
  1223. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1224. goto Done;
  1225. }
  1226. if (AccessSCPLookup[i].BufferType != 'B' &&
  1227. AccessSCPLookup[i].BufferType != 'D') {
  1228. swprintf(EachLine[j], L"%s = \"%s\"", AccessSCPLookup[i].KeyString, Strvalue);
  1229. } else {
  1230. swprintf(EachLine[j], L"%s = %d", AccessSCPLookup[i].KeyString, Value);
  1231. EachSize[j] = wcslen(EachLine[j]);
  1232. }
  1233. } else {
  1234. //
  1235. // in append mode, we have to write each line separately
  1236. //
  1237. if (AccessSCPLookup[i].BufferType == 'B' ||
  1238. AccessSCPLookup[i].BufferType == 'D') {
  1239. ScepWriteOneIntValueToProfile(
  1240. ProfileName,
  1241. szSystemAccess,
  1242. AccessSCPLookup[i].KeyString,
  1243. Value
  1244. );
  1245. } else if ( Strvalue ) {
  1246. WritePrivateProfileString (szSystemAccess,
  1247. AccessSCPLookup[i].KeyString,
  1248. Strvalue,
  1249. ProfileName);
  1250. }
  1251. }
  1252. TotalSize += EachSize[j]+1;
  1253. j++;
  1254. }
  1255. //
  1256. // writes the profile section
  1257. //
  1258. if ( bOverwrite ) {
  1259. if ( j > 0 ) {
  1260. rc = SceInfpWriteInfSection(
  1261. ProfileName,
  1262. szSystemAccess,
  1263. TotalSize+1,
  1264. EachLine,
  1265. &EachSize[0],
  1266. 0,
  1267. j-1,
  1268. Errlog
  1269. );
  1270. } else {
  1271. WritePrivateProfileSection(
  1272. szSystemAccess,
  1273. NULL,
  1274. ProfileName);
  1275. }
  1276. }
  1277. Done:
  1278. for ( i=0; i<cAccess; i++ ) {
  1279. if ( EachLine[i] != NULL ) {
  1280. ScepFree(EachLine[i]);
  1281. }
  1282. EachLine[i] = NULL;
  1283. EachSize[i] = 0;
  1284. }
  1285. return(rc);
  1286. }
  1287. SCESTATUS
  1288. SceInfpWritePrivileges(
  1289. IN PCWSTR ProfileName,
  1290. IN PSCE_PRIVILEGE_ASSIGNMENT pPrivileges,
  1291. IN BOOL bOverwrite,
  1292. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1293. )
  1294. /* ++
  1295. Routine Description:
  1296. This routine writes privilege assignments info from the SCP buffer
  1297. into the INF file in section [Privilege Rights].
  1298. Arguments:
  1299. ProfileName - the inf profile name
  1300. pPrivileges - the privilege assignment buffer.
  1301. Errlog - The error list encountered inside inf processing.
  1302. Return value:
  1303. SCESTATUS - SCESTATUS_SUCCESS
  1304. SCESTATUS_NOT_ENOUGH_RESOURCE
  1305. SCESTATUS_INVALID_PARAMETER
  1306. SCESTATUS_BAD_FORMAT
  1307. SCESTATUS_INVALID_DATA
  1308. -- */
  1309. {
  1310. SCESTATUS rc;
  1311. PSCE_PRIVILEGE_ASSIGNMENT pCurRight=NULL;
  1312. PSCE_NAME_LIST pNameList=NULL;
  1313. LONG Keysize;
  1314. PWSTR Strvalue=NULL;
  1315. DWORD TotalSize;
  1316. //
  1317. // [Privilege Rights] section
  1318. //
  1319. if (ProfileName == NULL )
  1320. return(SCESTATUS_INVALID_PARAMETER);
  1321. if ( pPrivileges == NULL ) {
  1322. //
  1323. // the buffer doesn't contain any privileges
  1324. // empty the section in the file
  1325. //
  1326. if ( bOverwrite ) {
  1327. WritePrivateProfileString(
  1328. szPrivilegeRights,
  1329. NULL,
  1330. NULL,
  1331. ProfileName
  1332. );
  1333. }
  1334. return(SCESTATUS_SUCCESS);
  1335. }
  1336. //
  1337. // open lsa policy handle for sid/name lookup
  1338. //
  1339. LSA_HANDLE LsaHandle=NULL;
  1340. rc = RtlNtStatusToDosError(
  1341. ScepOpenLsaPolicy(
  1342. POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION,
  1343. &LsaHandle,
  1344. TRUE
  1345. ));
  1346. if ( ERROR_SUCCESS != rc ) {
  1347. ScepBuildErrorLogInfo(
  1348. rc,
  1349. Errlog,
  1350. SCEERR_ADD,
  1351. TEXT("LSA")
  1352. );
  1353. return(ScepDosErrorToSceStatus(rc));
  1354. }
  1355. for (pCurRight=pPrivileges, TotalSize=0;
  1356. pCurRight != NULL;
  1357. pCurRight = pCurRight->Next) {
  1358. //
  1359. // Each privilege assignment contains the privilege's name and a list
  1360. // of user/groups to assign to.
  1361. //
  1362. Keysize = SceInfpConvertNameListToString(
  1363. LsaHandle,
  1364. pCurRight->Name,
  1365. pCurRight->AssignedTo,
  1366. bOverwrite,
  1367. &Strvalue,
  1368. Errlog
  1369. );
  1370. if ( Keysize >= 0 && Strvalue ) {
  1371. if ( bOverwrite ) {
  1372. rc = ScepAddToNameList(&pNameList, Strvalue, Keysize);
  1373. if ( rc != SCESTATUS_SUCCESS ) { //win32 error code
  1374. ScepBuildErrorLogInfo(
  1375. rc,
  1376. Errlog,
  1377. SCEERR_ADD,
  1378. pCurRight->Name
  1379. );
  1380. goto Done;
  1381. }
  1382. TotalSize += Keysize + 1;
  1383. } else {
  1384. //
  1385. // in append mode, write one line at a time
  1386. //
  1387. WritePrivateProfileString( szPrivilegeRights,
  1388. pCurRight->Name,
  1389. Strvalue,
  1390. ProfileName
  1391. );
  1392. }
  1393. } else if ( Keysize == -1 ) {
  1394. rc = ERROR_EXTENDED_ERROR;
  1395. goto Done;
  1396. }
  1397. ScepFree(Strvalue);
  1398. Strvalue = NULL;
  1399. }
  1400. //
  1401. // writes the profile section
  1402. //
  1403. if ( bOverwrite ) {
  1404. rc = SceInfpWriteListSection(
  1405. ProfileName,
  1406. szPrivilegeRights,
  1407. TotalSize+1,
  1408. pNameList,
  1409. 0, // do not overwrite section, do not add equal sign
  1410. Errlog
  1411. );
  1412. }
  1413. Done:
  1414. if ( Strvalue != NULL )
  1415. ScepFree(Strvalue);
  1416. ScepFreeNameList(pNameList);
  1417. if ( LsaHandle ) {
  1418. LsaClose(LsaHandle);
  1419. }
  1420. return( ScepDosErrorToSceStatus(rc) );
  1421. }
  1422. SCESTATUS
  1423. SceInfpWriteUserSettings(
  1424. IN PCWSTR ProfileName,
  1425. IN PSCE_NAME_LIST pProfiles,
  1426. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1427. )
  1428. /* ++
  1429. Routine Description:
  1430. This routine writes user settings information from the SCP buffer
  1431. into the INF file in section [Account Profiles].
  1432. Arguments:
  1433. ProfileName - the inf profile name
  1434. pProfiles - a list of profiles to write to the section.
  1435. Errlog - The error list encountered inside inf processing.
  1436. Return value:
  1437. SCESTATUS - SCESTATUS_SUCCESS
  1438. SCESTATUS_OTHER_ERROR
  1439. -- */
  1440. {
  1441. DWORD rc;
  1442. PSCE_NAME_LIST pCurProfile;
  1443. DWORD TotalSize;
  1444. if (ProfileName == NULL )
  1445. return(SCESTATUS_INVALID_PARAMETER);
  1446. if ( pProfiles == NULL )
  1447. return(SCESTATUS_SUCCESS);
  1448. for (pCurProfile=pProfiles, TotalSize=0;
  1449. pCurProfile != NULL;
  1450. pCurProfile = pCurProfile->Next) {
  1451. TotalSize += wcslen(pCurProfile->Name) + 3; // " ="
  1452. }
  1453. //
  1454. // write the accountProfile section
  1455. //
  1456. rc = SceInfpWriteListSection(
  1457. ProfileName,
  1458. szAccountProfiles,
  1459. TotalSize+1,
  1460. pProfiles,
  1461. SCEINF_ADD_EQUAL_SIGN,
  1462. Errlog
  1463. );
  1464. if ( rc != NO_ERROR ) {
  1465. ScepBuildErrorLogInfo(rc, Errlog,
  1466. SCEERR_WRITE_INFO,
  1467. szAccountProfiles
  1468. );
  1469. return(ScepDosErrorToSceStatus(rc));
  1470. } else
  1471. return(SCESTATUS_SUCCESS);
  1472. }
  1473. SCESTATUS
  1474. SceInfpWriteGroupMembership(
  1475. IN PCWSTR ProfileName,
  1476. IN PSCE_GROUP_MEMBERSHIP pGroupMembership,
  1477. IN BOOL bOverwrite,
  1478. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1479. )
  1480. /* ++
  1481. Routine Description:
  1482. This routine writes group membership information to the SCP INF file in
  1483. [Group Membership] section.
  1484. Arguments:
  1485. ProfileName - the INF profile name
  1486. pGroupMembership - the group membership info
  1487. Errlog - the error list for errors encountered in this routine.
  1488. Return value:
  1489. SCESTATUS - SCESTATUS_SUCCESS
  1490. SCESTATUS_NOT_ENOUGH_RESOURCE
  1491. SCESTATUS_INVALID_PARAMETER
  1492. SCESTATUS_BAD_FORMAT
  1493. SCESTATUS_INVALID_DATA
  1494. -- */
  1495. {
  1496. PSCE_GROUP_MEMBERSHIP pGroupMembers=NULL;
  1497. PWSTR Strvalue=NULL;
  1498. LONG Keysize;
  1499. SCESTATUS rc=SCESTATUS_SUCCESS;
  1500. DWORD TotalSize;
  1501. PSCE_NAME_LIST pNameList=NULL;
  1502. PWSTR Keyname=NULL;
  1503. DWORD Len;
  1504. PWSTR SidString=NULL;
  1505. if (ProfileName == NULL )
  1506. return(SCESTATUS_INVALID_PARAMETER);
  1507. if ( pGroupMembership == NULL ) {
  1508. //
  1509. // the buffer doesn't contain any groups
  1510. // empty the section in the file
  1511. //
  1512. if ( bOverwrite ) {
  1513. WritePrivateProfileString(
  1514. szGroupMembership,
  1515. NULL,
  1516. NULL,
  1517. ProfileName
  1518. );
  1519. }
  1520. return(SCESTATUS_SUCCESS);
  1521. }
  1522. //
  1523. // open lsa policy handle for sid/name lookup
  1524. //
  1525. LSA_HANDLE LsaHandle=NULL;
  1526. rc = RtlNtStatusToDosError(
  1527. ScepOpenLsaPolicy(
  1528. POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION,
  1529. &LsaHandle,
  1530. TRUE
  1531. ));
  1532. if ( ERROR_SUCCESS != rc ) {
  1533. ScepBuildErrorLogInfo(
  1534. rc,
  1535. Errlog,
  1536. SCEERR_ADD,
  1537. TEXT("LSA")
  1538. );
  1539. return(ScepDosErrorToSceStatus(rc));
  1540. }
  1541. //
  1542. // process each group in the list
  1543. //
  1544. for ( pGroupMembers=pGroupMembership, TotalSize=0;
  1545. pGroupMembers != NULL;
  1546. pGroupMembers = pGroupMembers->Next ) {
  1547. if ( (pGroupMembers->Status & SCE_GROUP_STATUS_NC_MEMBERS) &&
  1548. (pGroupMembers->Status & SCE_GROUP_STATUS_NC_MEMBEROF) ) {
  1549. continue;
  1550. }
  1551. if ( SidString ) {
  1552. LocalFree(SidString);
  1553. SidString = NULL;
  1554. }
  1555. Len = 0;
  1556. if ( wcschr(pGroupMembers->GroupName, L'\\') ) {
  1557. //
  1558. // convert group name into *SID format
  1559. //
  1560. ScepConvertNameToSidString(
  1561. LsaHandle,
  1562. pGroupMembers->GroupName,
  1563. FALSE,
  1564. &SidString,
  1565. &Len
  1566. );
  1567. }
  1568. else {
  1569. if ( ScepLookupWellKnownName(
  1570. pGroupMembers->GroupName,
  1571. LsaHandle,
  1572. &SidString) ) {
  1573. Len = wcslen(SidString);
  1574. }
  1575. }
  1576. if ( SidString == NULL ) {
  1577. Len = wcslen(pGroupMembers->GroupName);
  1578. }
  1579. Keyname = (PWSTR)ScepAlloc( 0, (Len+15)*sizeof(WCHAR));
  1580. if ( Keyname == NULL ) {
  1581. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1582. goto Done;
  1583. }
  1584. if ( SidString ) {
  1585. wcsncpy(Keyname, SidString, Len);
  1586. } else {
  1587. wcsncpy(Keyname, pGroupMembers->GroupName, Len);
  1588. }
  1589. if ( !(pGroupMembers->Status & SCE_GROUP_STATUS_NC_MEMBERS) ) {
  1590. wcscpy(Keyname+Len, szMembers);
  1591. Keyname[Len+9] = L'\0';
  1592. //
  1593. // convert the member list into a string
  1594. //
  1595. Keysize = SceInfpConvertNameListToString(
  1596. LsaHandle,
  1597. Keyname,
  1598. pGroupMembers->pMembers,
  1599. bOverwrite,
  1600. &Strvalue,
  1601. Errlog
  1602. );
  1603. if ( Keysize >= 0 && Strvalue ) {
  1604. if ( bOverwrite ) {
  1605. rc = ScepAddToNameList(&pNameList, Strvalue, Keysize);
  1606. if ( rc != SCESTATUS_SUCCESS ) {
  1607. ScepBuildErrorLogInfo(
  1608. rc,
  1609. Errlog,
  1610. SCEERR_ADD_MEMBERS,
  1611. pGroupMembers->GroupName
  1612. );
  1613. rc = ScepDosErrorToSceStatus(rc);
  1614. goto Done;
  1615. }
  1616. } else {
  1617. //
  1618. // append mode, write one line at a time
  1619. //
  1620. WritePrivateProfileString( szGroupMembership,
  1621. Keyname,
  1622. Strvalue,
  1623. ProfileName
  1624. );
  1625. }
  1626. TotalSize += Keysize + 1;
  1627. } else if ( Keysize == -1 ) {
  1628. rc = SCESTATUS_OTHER_ERROR;
  1629. goto Done;
  1630. }
  1631. ScepFree(Strvalue);
  1632. Strvalue = NULL;
  1633. }
  1634. if ( !(pGroupMembers->Status & SCE_GROUP_STATUS_NC_MEMBEROF) ) {
  1635. //
  1636. // convert the memberof list into a string
  1637. //
  1638. wcscpy(Keyname+Len, szMemberof);
  1639. Keyname[Len+10] = L'\0';
  1640. Keysize = SceInfpConvertNameListToString(
  1641. LsaHandle,
  1642. Keyname,
  1643. pGroupMembers->pMemberOf,
  1644. bOverwrite,
  1645. &Strvalue,
  1646. Errlog
  1647. );
  1648. if ( Keysize >= 0 && Strvalue ) {
  1649. if ( bOverwrite ) {
  1650. rc = ScepAddToNameList(&pNameList, Strvalue, Keysize);
  1651. if ( rc != SCESTATUS_SUCCESS ) {
  1652. ScepBuildErrorLogInfo(
  1653. rc,
  1654. Errlog,
  1655. SCEERR_ADD_MEMBEROF,
  1656. pGroupMembers->GroupName
  1657. );
  1658. rc = ScepDosErrorToSceStatus(rc);
  1659. goto Done;
  1660. }
  1661. } else {
  1662. //
  1663. // in append mode, write one line at a time
  1664. //
  1665. WritePrivateProfileString( szGroupMembership,
  1666. Keyname,
  1667. Strvalue,
  1668. ProfileName
  1669. );
  1670. }
  1671. TotalSize += Keysize + 1;
  1672. } else if ( Keysize == -1 ) {
  1673. rc = SCESTATUS_OTHER_ERROR;
  1674. goto Done;
  1675. }
  1676. ScepFree(Strvalue);
  1677. Strvalue = NULL;
  1678. }
  1679. }
  1680. //
  1681. // write to this profile's section
  1682. //
  1683. if ( bOverwrite ) {
  1684. rc = SceInfpWriteListSection(
  1685. ProfileName,
  1686. szGroupMembership,
  1687. TotalSize+1,
  1688. pNameList,
  1689. 0,
  1690. Errlog
  1691. );
  1692. rc = ScepDosErrorToSceStatus(rc);
  1693. }
  1694. Done:
  1695. if ( Keyname != NULL )
  1696. ScepFree(Keyname);
  1697. if ( Strvalue != NULL )
  1698. ScepFree(Strvalue);
  1699. if ( SidString ) {
  1700. LocalFree(SidString);
  1701. }
  1702. ScepFreeNameList(pNameList);
  1703. if ( LsaHandle ) {
  1704. LsaClose(LsaHandle);
  1705. }
  1706. return(rc);
  1707. }
  1708. SCESTATUS
  1709. SceInfpWriteObjects(
  1710. IN PCWSTR ProfileName,
  1711. IN PCWSTR SectionName,
  1712. IN PSCE_OBJECT_ARRAY pObjects,
  1713. IN BOOL bOverwrite,
  1714. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1715. )
  1716. /* ++
  1717. Routine Description:
  1718. This routine writes registry or files security information (names and
  1719. security descriptors) into the INF SCP file in the section provided.
  1720. Arguments:
  1721. ProfileName - the SCP INF file name
  1722. SectionName - a individual section name to retrieve. NULL = all sections for
  1723. the area.
  1724. pObjects - the buffer of objects to write.
  1725. Errlog - the cummulative error list to hold errors encountered in this routine.
  1726. Return value:
  1727. SCESTATUS - SCESTATUS_SUCCESS
  1728. SCESTATUS_NOT_ENOUGH_RESOURCE
  1729. SCESTATUS_INVALID_PARAMETER
  1730. SCESTATUS_BAD_FORMAT
  1731. SCESTATUS_INVALID_DATA
  1732. -- */
  1733. {
  1734. SCESTATUS rc=SCESTATUS_SUCCESS;
  1735. PSCE_NAME_LIST pNameList=NULL;
  1736. DWORD TotalSize=0;
  1737. DWORD i, ObjectSize;
  1738. if (ProfileName == NULL || SectionName == NULL )
  1739. return(SCESTATUS_INVALID_PARAMETER);
  1740. if ( pObjects == NULL || pObjects->Count == 0 ) {
  1741. //
  1742. // the buffer doesn't contain any objects
  1743. // empty the section in the file
  1744. //
  1745. if ( bOverwrite ) {
  1746. WritePrivateProfileString(
  1747. SectionName,
  1748. NULL,
  1749. NULL,
  1750. ProfileName
  1751. );
  1752. }
  1753. return(SCESTATUS_SUCCESS);
  1754. }
  1755. for ( i=0; i<pObjects->Count; i++) {
  1756. //
  1757. // Get string fields. Don't care the key name or if it exist.
  1758. // Must have 3 fields each line.
  1759. //
  1760. rc = SceInfpWriteOneObject(
  1761. pObjects->pObjectArray[i],
  1762. &pNameList,
  1763. &ObjectSize,
  1764. Errlog
  1765. );
  1766. if ( rc != SCESTATUS_SUCCESS ) {
  1767. ScepBuildErrorLogInfo(
  1768. rc,
  1769. Errlog,
  1770. SCEERR_WRITE_INFO,
  1771. pObjects->pObjectArray[i]->Name
  1772. );
  1773. goto Done;
  1774. }
  1775. TotalSize += ObjectSize + 1;
  1776. }
  1777. //
  1778. // write to this profile's section
  1779. //
  1780. rc = SceInfpWriteListSection(
  1781. ProfileName,
  1782. SectionName,
  1783. TotalSize+1,
  1784. pNameList,
  1785. bOverwrite ? 0 : SCEINF_APPEND_SECTION,
  1786. Errlog
  1787. );
  1788. if ( rc != SCESTATUS_SUCCESS ) {
  1789. ScepBuildErrorLogInfo(
  1790. rc,
  1791. Errlog,
  1792. SCEERR_WRITE_INFO,
  1793. SectionName
  1794. );
  1795. }
  1796. Done:
  1797. ScepFreeNameList(pNameList);
  1798. rc = ScepDosErrorToSceStatus(rc);
  1799. return(rc);
  1800. }
  1801. SCESTATUS
  1802. SceInfpWriteServices(
  1803. IN PCWSTR ProfileName,
  1804. IN PCWSTR SectionName,
  1805. IN PSCE_SERVICES pServices,
  1806. IN BOOL bOverwrite,
  1807. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1808. )
  1809. /* ++
  1810. Routine Description:
  1811. This routine writes system services general settings (startup and
  1812. security descriptors) into the INF SCP file in the section provided.
  1813. Arguments:
  1814. ProfileName - the SCP INF file name
  1815. SectionName - a individual section name to retrieve. NULL = all sections for
  1816. the area.
  1817. pServices - the buffer of services to write.
  1818. Errlog - the cummulative error list to hold errors encountered in this routine.
  1819. Return value:
  1820. SCESTATUS - SCESTATUS_SUCCESS
  1821. SCESTATUS_NOT_ENOUGH_RESOURCE
  1822. SCESTATUS_INVALID_PARAMETER
  1823. SCESTATUS_BAD_FORMAT
  1824. SCESTATUS_INVALID_DATA
  1825. -- */
  1826. {
  1827. SCESTATUS rc=SCESTATUS_SUCCESS;
  1828. PSCE_NAME_LIST pNameList=NULL;
  1829. PSCE_SERVICES pNode;
  1830. DWORD TotalSize=0;
  1831. DWORD ObjectSize;
  1832. if (ProfileName == NULL || SectionName == NULL )
  1833. return(SCESTATUS_INVALID_PARAMETER);
  1834. if ( pServices == NULL ) {
  1835. //
  1836. // the buffer doesn't contain any services
  1837. // empty the section in the file
  1838. //
  1839. if ( bOverwrite ) {
  1840. WritePrivateProfileString(
  1841. SectionName,
  1842. NULL,
  1843. NULL,
  1844. ProfileName
  1845. );
  1846. }
  1847. return(SCESTATUS_SUCCESS);
  1848. }
  1849. for ( pNode=pServices; pNode != NULL; pNode = pNode->Next) {
  1850. //
  1851. // write string fields.
  1852. //
  1853. rc = SceInfpWriteOneService(
  1854. pNode,
  1855. &pNameList,
  1856. &ObjectSize,
  1857. Errlog
  1858. );
  1859. if ( rc != SCESTATUS_SUCCESS ) {
  1860. ScepBuildErrorLogInfo(
  1861. rc,
  1862. Errlog,
  1863. SCEERR_WRITE_INFO,
  1864. pNode->ServiceName
  1865. );
  1866. goto Done;
  1867. }
  1868. TotalSize += ObjectSize + 1;
  1869. }
  1870. //
  1871. // write to this profile's section
  1872. //
  1873. rc = SceInfpWriteListSection(
  1874. ProfileName,
  1875. SectionName,
  1876. TotalSize+1,
  1877. pNameList,
  1878. bOverwrite ? 0 : SCEINF_APPEND_SECTION,
  1879. Errlog
  1880. );
  1881. if ( rc != SCESTATUS_SUCCESS ) {
  1882. ScepBuildErrorLogInfo(
  1883. rc,
  1884. Errlog,
  1885. SCEERR_WRITE_INFO,
  1886. SectionName
  1887. );
  1888. }
  1889. Done:
  1890. ScepFreeNameList(pNameList);
  1891. rc = ScepDosErrorToSceStatus(rc);
  1892. return(rc);
  1893. }
  1894. DWORD
  1895. SceInfpWriteOneObject(
  1896. IN PSCE_OBJECT_SECURITY pObject,
  1897. OUT PSCE_NAME_LIST *pNameList,
  1898. OUT PDWORD ObjectSize,
  1899. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1900. )
  1901. /* ++
  1902. Routine Description:
  1903. This routine builds security descriptor text for one object (a registry key,
  1904. or a file) into the name list. Each object represents one line in the INF file.
  1905. Arguments:
  1906. pObject - The object's security settings
  1907. pNameList - The output string list.
  1908. TotalSize - the total size of the list
  1909. Errlog - The cummulative error list for errors encountered in this routine
  1910. Return value:
  1911. SCESTATUS - SCESTATUS_SUCCESS
  1912. SCESTATUS_NOT_ENOUGH_RESOURCE
  1913. SCESTATUS_INVALID_PARAMETER
  1914. SCESTATUS_BAD_FORMAT
  1915. SCESTATUS_INVALID_DATA
  1916. -- */
  1917. {
  1918. DWORD rc;
  1919. PWSTR Strvalue=NULL;
  1920. PWSTR SDspec=NULL;
  1921. DWORD SDsize=0;
  1922. DWORD nFields;
  1923. DWORD *aFieldOffset=NULL;
  1924. DWORD i;
  1925. *ObjectSize = 0;
  1926. if ( pObject == NULL )
  1927. return(ERROR_SUCCESS);
  1928. if ( pObject->pSecurityDescriptor != NULL ) {
  1929. //
  1930. // convert security to text
  1931. //
  1932. rc = ConvertSecurityDescriptorToText(
  1933. pObject->pSecurityDescriptor,
  1934. pObject->SeInfo,
  1935. &SDspec,
  1936. &SDsize
  1937. );
  1938. if ( rc != NO_ERROR ) {
  1939. ScepBuildErrorLogInfo(
  1940. rc,
  1941. Errlog,
  1942. SCEERR_BUILD_SD,
  1943. pObject->Name
  1944. );
  1945. return(rc);
  1946. }
  1947. }
  1948. //
  1949. // The Registry/File INF layout must have more than 3 fields for each line.
  1950. // The first field is the key/file name, the 2nd field is the status
  1951. // flag, and the 3rd field and after is the security descriptor in text
  1952. //
  1953. //
  1954. // security descriptor in text is broken into multiple fields if the length
  1955. // is greater than MAX_STRING_LENGTH (the limit of setupapi). The break point
  1956. // is at the following characters: ) ( ; " or space
  1957. //
  1958. rc = SceInfpBreakTextIntoMultiFields(SDspec, SDsize, &nFields, &aFieldOffset);
  1959. if ( SCESTATUS_SUCCESS != rc ) {
  1960. rc = ScepSceStatusToDosError(rc);
  1961. goto Done;
  1962. }
  1963. //
  1964. // each extra field will use 3 more chars : ,"<field>"
  1965. //
  1966. *ObjectSize = wcslen(pObject->Name)+5 + SDsize;
  1967. if ( nFields ) {
  1968. *ObjectSize += 3*nFields;
  1969. } else {
  1970. *ObjectSize += 2;
  1971. }
  1972. //
  1973. // allocate the output buffer
  1974. //
  1975. Strvalue = (PWSTR)ScepAlloc(LMEM_ZEROINIT, (*ObjectSize+1) * sizeof(WCHAR) );
  1976. if ( Strvalue == NULL ) {
  1977. rc = ERROR_NOT_ENOUGH_MEMORY;
  1978. goto Done;
  1979. }
  1980. //
  1981. // copy data into the buffer
  1982. //
  1983. if ( SDspec != NULL ) {
  1984. if ( nFields == 0 || !aFieldOffset ) {
  1985. swprintf(Strvalue, L"\"%s\",%1d,\"%s\"", pObject->Name, pObject->Status, SDspec);
  1986. } else {
  1987. //
  1988. // loop through the fields
  1989. //
  1990. swprintf(Strvalue, L"\"%s\",%1d\0", pObject->Name, pObject->Status);
  1991. for ( i=0; i<nFields; i++ ) {
  1992. if ( aFieldOffset[i] < SDsize ) {
  1993. wcscat(Strvalue, L",\"");
  1994. if ( i == nFields-1 ) {
  1995. //
  1996. // the last field
  1997. //
  1998. wcscat(Strvalue, SDspec+aFieldOffset[i]);
  1999. } else {
  2000. wcsncat(Strvalue, SDspec+aFieldOffset[i],
  2001. aFieldOffset[i+1]-aFieldOffset[i]);
  2002. }
  2003. wcscat(Strvalue, L"\"");
  2004. }
  2005. }
  2006. }
  2007. } else
  2008. swprintf(Strvalue, L"\"%s\",%1d,\"\"", pObject->Name, pObject->Status);
  2009. rc = ScepAddToNameList(pNameList, Strvalue, *ObjectSize);
  2010. ScepFree(Strvalue);
  2011. Done:
  2012. if ( aFieldOffset ) {
  2013. ScepFree(aFieldOffset);
  2014. }
  2015. if ( SDspec != NULL )
  2016. ScepFree(SDspec);
  2017. return(rc);
  2018. }
  2019. DWORD
  2020. SceInfpWriteOneService(
  2021. IN PSCE_SERVICES pService,
  2022. OUT PSCE_NAME_LIST *pNameList,
  2023. OUT PDWORD ObjectSize,
  2024. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2025. )
  2026. /* ++
  2027. Routine Description:
  2028. This routine builds security descriptor text for one object (a registry key,
  2029. or a file) into the name list. Each object represents one line in the INF file.
  2030. Arguments:
  2031. pService - The service's general setting
  2032. pNameList - The output string list.
  2033. TotalSize - the total size of the list
  2034. Errlog - The cummulative error list for errors encountered in this routine
  2035. Return value:
  2036. Win32 error
  2037. -- */
  2038. {
  2039. DWORD rc;
  2040. PWSTR Strvalue=NULL;
  2041. PWSTR SDspec=NULL;
  2042. DWORD SDsize=0;
  2043. DWORD nFields;
  2044. DWORD *aFieldOffset=NULL;
  2045. DWORD i;
  2046. *ObjectSize = 0;
  2047. if ( pService == NULL )
  2048. return(ERROR_SUCCESS);
  2049. if ( pService->General.pSecurityDescriptor != NULL ) {
  2050. //
  2051. // convert security to text
  2052. //
  2053. rc = ConvertSecurityDescriptorToText(
  2054. pService->General.pSecurityDescriptor,
  2055. pService->SeInfo,
  2056. &SDspec,
  2057. &SDsize
  2058. );
  2059. if ( rc != NO_ERROR ) {
  2060. ScepBuildErrorLogInfo(
  2061. rc,
  2062. Errlog,
  2063. SCEERR_BUILD_SD,
  2064. pService->ServiceName
  2065. );
  2066. return(rc);
  2067. }
  2068. }
  2069. //
  2070. // The service INF layout must have 3 or more fields for each line.
  2071. // The first field is the service name, the 2nd field is the startup
  2072. // flag, and the 3rd field and after is the security descriptor in text
  2073. //
  2074. //
  2075. // security descriptor in text is broken into multiple fields if the length
  2076. // is greater than MAX_STRING_LENGTH (the limit of setupapi). The break point
  2077. // is at the following characters: ) ( ; " or space
  2078. //
  2079. rc = SceInfpBreakTextIntoMultiFields(SDspec, SDsize, &nFields, &aFieldOffset);
  2080. if ( SCESTATUS_SUCCESS != rc ) {
  2081. rc = ScepSceStatusToDosError(rc);
  2082. goto Done;
  2083. }
  2084. //
  2085. // each extra field will use 3 more chars : ,"<field>"
  2086. //
  2087. *ObjectSize = wcslen(pService->ServiceName)+5 + SDsize;
  2088. if ( nFields ) {
  2089. *ObjectSize += 3*nFields;
  2090. } else {
  2091. *ObjectSize += 2;
  2092. }
  2093. //
  2094. // allocate the output buffer
  2095. //
  2096. Strvalue = (PWSTR)ScepAlloc(LMEM_ZEROINIT, (*ObjectSize+1) * sizeof(WCHAR) );
  2097. if ( Strvalue == NULL ) {
  2098. rc = ERROR_NOT_ENOUGH_MEMORY;
  2099. goto Done;
  2100. }
  2101. //
  2102. // copy data into the buffer
  2103. //
  2104. if ( SDspec != NULL ) {
  2105. if ( nFields == 0 || !aFieldOffset ) {
  2106. //
  2107. // to represent "not configured"
  2108. // 0 is used in the database
  2109. // "" is used in the inf template
  2110. // so just generate "" instead of "0" for startup type
  2111. //
  2112. if (pService->Startup == 0) {
  2113. swprintf(Strvalue, L"\"%s\",,\"%s\"", pService->ServiceName, SDspec);
  2114. }
  2115. else {
  2116. swprintf(Strvalue, L"\"%s\",%1d,\"%s\"", pService->ServiceName,
  2117. pService->Startup, SDspec);
  2118. }
  2119. } else {
  2120. //
  2121. // loop through the fields
  2122. //
  2123. if (pService->Startup == 0) {
  2124. swprintf(Strvalue, L"\"%s\",\0", pService->ServiceName);
  2125. }
  2126. else {
  2127. swprintf(Strvalue, L"\"%s\",%1d\0", pService->ServiceName, pService->Startup);
  2128. }
  2129. for ( i=0; i<nFields; i++ ) {
  2130. if ( aFieldOffset[i] < SDsize ) {
  2131. wcscat(Strvalue, L",\"");
  2132. if ( i == nFields-1 ) {
  2133. //
  2134. // the last field
  2135. //
  2136. wcscat(Strvalue, SDspec+aFieldOffset[i]);
  2137. } else {
  2138. wcsncat(Strvalue, SDspec+aFieldOffset[i],
  2139. aFieldOffset[i+1]-aFieldOffset[i]);
  2140. }
  2141. wcscat(Strvalue, L"\"");
  2142. }
  2143. }
  2144. }
  2145. } else {
  2146. if (pService->Startup == 0) {
  2147. swprintf(Strvalue, L"\"%s\",,\"\"", pService->ServiceName);
  2148. }
  2149. else {
  2150. swprintf(Strvalue, L"\"%s\",%1d,\"\"", pService->ServiceName, pService->Startup);
  2151. }
  2152. }
  2153. rc = ScepAddToNameList(pNameList, Strvalue, *ObjectSize);
  2154. ScepFree(Strvalue);
  2155. Done:
  2156. if ( aFieldOffset ) {
  2157. ScepFree(aFieldOffset);
  2158. }
  2159. if ( SDspec != NULL )
  2160. ScepFree(SDspec);
  2161. return(rc);
  2162. }
  2163. SCESTATUS
  2164. SceInfpWriteAuditing(
  2165. IN PCWSTR ProfileName,
  2166. IN PSCE_PROFILE_INFO pSCEinfo,
  2167. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2168. )
  2169. /* ++
  2170. Routine Description:
  2171. This routine writes system auditing information into the SCP INF file
  2172. in [System Log], [Security Log], [Application Log], [Event Audit],
  2173. [Registry Audit], and [File Audit] sections.
  2174. Arguments:
  2175. ProfileName - The INF profile's name
  2176. pSCEinfo - the info buffer to write.
  2177. Errlog - The cummulative error list to hold errors encountered in this routine.
  2178. Return value:
  2179. SCESTATUS - SCESTATUS_SUCCESS
  2180. SCESTATUS_NOT_ENOUGH_RESOURCE
  2181. SCESTATUS_INVALID_PARAMETER
  2182. SCESTATUS_BAD_FORMAT
  2183. SCESTATUS_INVALID_DATA
  2184. -- */
  2185. {
  2186. SCESTATUS rc;
  2187. DWORD LogSize;
  2188. DWORD Periods;
  2189. DWORD RetentionDays;
  2190. DWORD RestrictGuest;
  2191. PCWSTR szAuditLog;
  2192. DWORD i, j;
  2193. PWSTR EachLine[10];
  2194. DWORD EachSize[10];
  2195. DWORD TotalSize=0;
  2196. if (ProfileName == NULL || pSCEinfo == NULL )
  2197. return(SCESTATUS_INVALID_PARAMETER);
  2198. //
  2199. // Writes Log setting for system log, security log and application log
  2200. //
  2201. for ( i=0; i<3; i++) {
  2202. // get the section name
  2203. switch (i) {
  2204. case 0:
  2205. szAuditLog = szAuditSystemLog;
  2206. break;
  2207. case 1:
  2208. szAuditLog = szAuditSecurityLog;
  2209. break;
  2210. default:
  2211. szAuditLog = szAuditApplicationLog;
  2212. break;
  2213. }
  2214. // set audit log setting
  2215. LogSize = pSCEinfo->MaximumLogSize[i];
  2216. Periods = pSCEinfo->AuditLogRetentionPeriod[i];
  2217. RetentionDays = pSCEinfo->RetentionDays[i];
  2218. RestrictGuest = pSCEinfo->RestrictGuestAccess[i];
  2219. //
  2220. // writes the setting to the section
  2221. //
  2222. rc = SceInfpWriteAuditLogSetting(
  2223. ProfileName,
  2224. szAuditLog,
  2225. LogSize,
  2226. Periods,
  2227. RetentionDays,
  2228. RestrictGuest,
  2229. Errlog
  2230. );
  2231. if ( rc != SCESTATUS_SUCCESS )
  2232. return(rc);
  2233. }
  2234. //
  2235. // fill the array
  2236. //
  2237. for (i=0; i<10; i++) {
  2238. EachLine[i] = NULL;
  2239. EachSize[i] = 25;
  2240. }
  2241. j = 0;
  2242. //
  2243. // process each attribute for event auditing
  2244. //
  2245. // AuditSystemEvents
  2246. //
  2247. if ( pSCEinfo->AuditSystemEvents != SCE_NO_VALUE ) {
  2248. EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
  2249. if ( EachLine[j] != NULL ) {
  2250. swprintf(EachLine[j], L"AuditSystemEvents = %d\0", pSCEinfo->AuditSystemEvents);
  2251. EachSize[j] = wcslen(EachLine[j]);
  2252. TotalSize += EachSize[j] + 1;
  2253. j++;
  2254. } else {
  2255. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2256. goto Done;
  2257. }
  2258. }
  2259. // AuditLogonEvents
  2260. if ( pSCEinfo->AuditLogonEvents != SCE_NO_VALUE ) {
  2261. EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
  2262. if ( EachLine[j] != NULL ) {
  2263. swprintf(EachLine[j], L"AuditLogonEvents = %d\0", pSCEinfo->AuditLogonEvents);
  2264. EachSize[j] = wcslen(EachLine[j]);
  2265. TotalSize += EachSize[j] + 1;
  2266. j++;
  2267. } else {
  2268. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2269. goto Done;
  2270. }
  2271. }
  2272. // AuditObjectAccess
  2273. if ( pSCEinfo->AuditObjectAccess != SCE_NO_VALUE ) {
  2274. EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
  2275. if ( EachLine[j] != NULL ) {
  2276. swprintf(EachLine[j], L"AuditObjectAccess = %d\0", pSCEinfo->AuditObjectAccess);
  2277. EachSize[j] = wcslen(EachLine[j]);
  2278. TotalSize += EachSize[j] + 1;
  2279. j++;
  2280. } else {
  2281. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2282. goto Done;
  2283. }
  2284. }
  2285. // AuditPrivilegeUse
  2286. if ( pSCEinfo->AuditPrivilegeUse != SCE_NO_VALUE ) {
  2287. EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
  2288. if ( EachLine[j] != NULL ) {
  2289. swprintf(EachLine[j], L"AuditPrivilegeUse = %d\0", pSCEinfo->AuditPrivilegeUse);
  2290. EachSize[j] = wcslen(EachLine[j]);
  2291. TotalSize += EachSize[j] + 1;
  2292. j++;
  2293. } else {
  2294. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2295. goto Done;
  2296. }
  2297. }
  2298. // AuditPolicyChange
  2299. if ( pSCEinfo->AuditPolicyChange != SCE_NO_VALUE ) {
  2300. EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
  2301. if ( EachLine[j] != NULL ) {
  2302. swprintf(EachLine[j], L"AuditPolicyChange = %d\0", pSCEinfo->AuditPolicyChange);
  2303. EachSize[j] = wcslen(EachLine[j]);
  2304. TotalSize += EachSize[j] + 1;
  2305. j++;
  2306. } else {
  2307. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2308. goto Done;
  2309. }
  2310. }
  2311. // AuditAccountManage
  2312. if ( pSCEinfo->AuditAccountManage != SCE_NO_VALUE ) {
  2313. EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
  2314. if ( EachLine[j] != NULL ) {
  2315. swprintf(EachLine[j], L"AuditAccountManage = %d\0", pSCEinfo->AuditAccountManage);
  2316. EachSize[j] = wcslen(EachLine[j]);
  2317. TotalSize += EachSize[j] + 1;
  2318. j++;
  2319. } else {
  2320. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2321. goto Done;
  2322. }
  2323. }
  2324. // AuditprocessTracking
  2325. if ( pSCEinfo->AuditProcessTracking != SCE_NO_VALUE ) {
  2326. EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
  2327. if ( EachLine[j] != NULL ) {
  2328. swprintf(EachLine[j], L"AuditProcessTracking = %d\0", pSCEinfo->AuditProcessTracking);
  2329. EachSize[j] = wcslen(EachLine[j]);
  2330. TotalSize += EachSize[j] + 1;
  2331. j++;
  2332. } else {
  2333. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2334. goto Done;
  2335. }
  2336. }
  2337. // AuditDSAccess
  2338. if ( pSCEinfo->AuditDSAccess != SCE_NO_VALUE ) {
  2339. EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
  2340. if ( EachLine[j] != NULL ) {
  2341. swprintf(EachLine[j], L"AuditDSAccess = %d\0", pSCEinfo->AuditDSAccess);
  2342. EachSize[j] = wcslen(EachLine[j]);
  2343. TotalSize += EachSize[j] + 1;
  2344. j++;
  2345. } else {
  2346. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2347. goto Done;
  2348. }
  2349. }
  2350. // AuditAccountLogon
  2351. if ( pSCEinfo->AuditAccountLogon != SCE_NO_VALUE ) {
  2352. EachLine[j] = (PWSTR)ScepAlloc((UINT)0, EachSize[j]*sizeof(WCHAR));
  2353. if ( EachLine[j] != NULL ) {
  2354. swprintf(EachLine[j], L"AuditAccountLogon = %d\0", pSCEinfo->AuditAccountLogon);
  2355. EachSize[j] = wcslen(EachLine[j]);
  2356. TotalSize += EachSize[j] + 1;
  2357. j++;
  2358. } else {
  2359. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2360. goto Done;
  2361. }
  2362. }
  2363. //
  2364. // Writes the section
  2365. //
  2366. if ( j > 0 ) {
  2367. rc = SceInfpWriteInfSection(
  2368. ProfileName,
  2369. szAuditEvent,
  2370. TotalSize+1,
  2371. EachLine,
  2372. &EachSize[0],
  2373. 0,
  2374. j-1,
  2375. Errlog
  2376. );
  2377. } else {
  2378. WritePrivateProfileSection(
  2379. szAuditEvent,
  2380. NULL,
  2381. ProfileName);
  2382. }
  2383. Done:
  2384. for ( i=0; i<10; i++ )
  2385. if ( EachLine[i] != NULL ) {
  2386. ScepFree(EachLine[i]);
  2387. }
  2388. return(rc);
  2389. }
  2390. SCESTATUS
  2391. SceInfpAppendAuditing(
  2392. IN PCWSTR ProfileName,
  2393. IN PSCE_PROFILE_INFO pSCEinfo,
  2394. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2395. )
  2396. {
  2397. SCESTATUS rc=SCESTATUS_SUCCESS;
  2398. DWORD Value;
  2399. SCE_KEY_LOOKUP AuditSCPLookup[] = {
  2400. {(PWSTR)TEXT("AuditSystemEvents"), offsetof(struct _SCE_PROFILE_INFO, AuditSystemEvents), 'D'},
  2401. {(PWSTR)TEXT("AuditLogonEvents"), offsetof(struct _SCE_PROFILE_INFO, AuditLogonEvents), 'D'},
  2402. {(PWSTR)TEXT("AuditObjectAccess"), offsetof(struct _SCE_PROFILE_INFO, AuditObjectAccess), 'D'},
  2403. {(PWSTR)TEXT("AuditPrivilegeUse"), offsetof(struct _SCE_PROFILE_INFO, AuditPrivilegeUse), 'D'},
  2404. {(PWSTR)TEXT("AuditPolicyChange"), offsetof(struct _SCE_PROFILE_INFO, AuditPolicyChange), 'D'},
  2405. {(PWSTR)TEXT("AuditAccountManage"), offsetof(struct _SCE_PROFILE_INFO, AuditAccountManage), 'D'},
  2406. {(PWSTR)TEXT("AuditProcessTracking"), offsetof(struct _SCE_PROFILE_INFO, AuditProcessTracking), 'D'},
  2407. {(PWSTR)TEXT("AuditDSAccess"), offsetof(struct _SCE_PROFILE_INFO, AuditDSAccess), 'D'},
  2408. {(PWSTR)TEXT("AuditAccountLogon"), offsetof(struct _SCE_PROFILE_INFO, AuditAccountLogon), 'D'}
  2409. };
  2410. DWORD cAudit = sizeof(AuditSCPLookup) / sizeof(SCE_KEY_LOOKUP);
  2411. PCWSTR szAuditLog;
  2412. DWORD i;
  2413. UINT Offset;
  2414. if (ProfileName == NULL || pSCEinfo == NULL )
  2415. return(SCESTATUS_INVALID_PARAMETER);
  2416. for ( i=0; i<3; i++) {
  2417. // get the section name
  2418. switch (i) {
  2419. case 0:
  2420. szAuditLog = szAuditSystemLog;
  2421. break;
  2422. case 1:
  2423. szAuditLog = szAuditSecurityLog;
  2424. break;
  2425. default:
  2426. szAuditLog = szAuditApplicationLog;
  2427. break;
  2428. }
  2429. ScepWriteOneIntValueToProfile(
  2430. ProfileName,
  2431. szAuditLog,
  2432. L"MaximumLogSize",
  2433. pSCEinfo->MaximumLogSize[i]
  2434. );
  2435. ScepWriteOneIntValueToProfile(
  2436. ProfileName,
  2437. szAuditLog,
  2438. L"AuditLogRetentionPeriod",
  2439. pSCEinfo->AuditLogRetentionPeriod[i]
  2440. );
  2441. ScepWriteOneIntValueToProfile(
  2442. ProfileName,
  2443. szAuditLog,
  2444. L"RetentionDays",
  2445. pSCEinfo->RetentionDays[i]
  2446. );
  2447. ScepWriteOneIntValueToProfile(
  2448. ProfileName,
  2449. szAuditLog,
  2450. L"RestrictGuestAccess",
  2451. pSCEinfo->RestrictGuestAccess[i]
  2452. );
  2453. }
  2454. for ( i=0; i<cAudit; i++) {
  2455. //
  2456. // get settings in AuditLookup table
  2457. //
  2458. Offset = AuditSCPLookup[i].Offset;
  2459. switch ( AuditSCPLookup[i].BufferType ) {
  2460. case 'D':
  2461. //
  2462. // Int Field
  2463. //
  2464. Value = *((DWORD *)((CHAR *)pSCEinfo+Offset));
  2465. ScepWriteOneIntValueToProfile(
  2466. ProfileName,
  2467. szAuditEvent,
  2468. AuditSCPLookup[i].KeyString,
  2469. Value
  2470. );
  2471. break;
  2472. default:
  2473. break;
  2474. }
  2475. }
  2476. return(rc);
  2477. }
  2478. SCESTATUS
  2479. ScepWriteOneIntValueToProfile(
  2480. IN PCWSTR InfFileName,
  2481. IN PCWSTR InfSectionName,
  2482. IN PWSTR KeyName,
  2483. IN DWORD Value
  2484. )
  2485. {
  2486. WCHAR TmpBuf[15];
  2487. if ( Value == SCE_NO_VALUE ) {
  2488. return(SCESTATUS_SUCCESS);
  2489. }
  2490. swprintf(TmpBuf, L"%d\0", Value);
  2491. WritePrivateProfileString( InfSectionName,
  2492. KeyName,
  2493. TmpBuf,
  2494. InfFileName
  2495. );
  2496. return(SCESTATUS_SUCCESS);
  2497. }
  2498. SCESTATUS
  2499. SceInfpWriteAuditLogSetting(
  2500. IN PCWSTR InfFileName,
  2501. IN PCWSTR InfSectionName,
  2502. IN DWORD LogSize,
  2503. IN DWORD Periods,
  2504. IN DWORD RetentionDays,
  2505. IN DWORD RestrictGuest,
  2506. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2507. )
  2508. /* ++
  2509. Routine Description:
  2510. This routine retrieves audit log setting from the INF file (SCP and SAP)
  2511. based on the SectionName passed in. The audit log settings include MaximumSize,
  2512. RetentionPeriod and RetentionDays. There are 3 different logs (system,
  2513. security, and application) which all have the same setting. The information
  2514. returned in in LogSize, Periods, RetentionDays. These 3 output arguments will
  2515. be reset at the begining of the routine. So if error occurs after the reset,
  2516. the original values won't be set back.
  2517. Arguments:
  2518. InfFileName - The INF file name to write to
  2519. InfSectionName - Log section name (SAdtSystemLog, SAdtSecurityLog, SAdtApplicationLog)
  2520. LogSize - The maximum size of the log
  2521. Periods - The retention period of the log
  2522. RetentionDays - The number of days for log retention
  2523. Errlog - The error list
  2524. Return value:
  2525. SCESTATUS - SCESTATUS_SUCCESS
  2526. SCESTATUS_NOT_ENOUGH_RESOURCE
  2527. SCESTATUS_INVALID_PARAMETER
  2528. SCESTATUS_BAD_FORMAT
  2529. SCESTATUS_INVALID_DATA
  2530. -- */
  2531. {
  2532. SCESTATUS rc=SCESTATUS_SUCCESS;
  2533. PWSTR EachLine[4];
  2534. DWORD EachSize[4];
  2535. DWORD TotalSize=0;
  2536. DWORD i;
  2537. if (InfFileName == NULL || InfSectionName == NULL )
  2538. return(SCESTATUS_INVALID_PARAMETER);
  2539. //
  2540. // initialize and fill the array
  2541. //
  2542. for ( i=0; i<4; i++ ) {
  2543. EachLine[i] = NULL;
  2544. EachSize[i] = 37;
  2545. }
  2546. i = 0;
  2547. if ( LogSize != (DWORD)SCE_NO_VALUE ) {
  2548. EachLine[i] = (PWSTR)ScepAlloc((UINT)0, EachSize[i]*sizeof(WCHAR));
  2549. if ( EachLine[i] != NULL ) {
  2550. swprintf(EachLine[i], L"MaximumLogSize = %d", LogSize);
  2551. EachSize[i] = wcslen(EachLine[i]);
  2552. TotalSize += EachSize[i] + 1;
  2553. i++;
  2554. } else {
  2555. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2556. goto Done;
  2557. }
  2558. }
  2559. if ( Periods != (DWORD)SCE_NO_VALUE ) {
  2560. EachLine[i] = (PWSTR)ScepAlloc((UINT)0, EachSize[i]*sizeof(WCHAR));
  2561. if ( EachLine[i] != NULL ) {
  2562. swprintf(EachLine[i], L"AuditLogRetentionPeriod = %d", Periods);
  2563. EachSize[i] = wcslen(EachLine[i]);
  2564. TotalSize += EachSize[i] + 1;
  2565. i++;
  2566. } else {
  2567. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2568. goto Done;
  2569. }
  2570. }
  2571. if ( RetentionDays != (DWORD)SCE_NO_VALUE ) {
  2572. EachLine[i] = (PWSTR)ScepAlloc((UINT)0, EachSize[i]*sizeof(WCHAR));
  2573. if ( EachLine[i] != NULL ) {
  2574. swprintf(EachLine[i], L"RetentionDays = %d", RetentionDays);
  2575. EachSize[i] = wcslen(EachLine[i]);
  2576. TotalSize += EachSize[i] + 1;
  2577. i++;
  2578. } else {
  2579. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2580. goto Done;
  2581. }
  2582. }
  2583. if ( RestrictGuest != (DWORD)SCE_NO_VALUE ) {
  2584. EachLine[i] = (PWSTR)ScepAlloc((UINT)0, EachSize[i]*sizeof(WCHAR));
  2585. if ( EachLine[i] != NULL ) {
  2586. swprintf(EachLine[i], L"RestrictGuestAccess = %d", RestrictGuest);
  2587. EachSize[i] = wcslen(EachLine[i]);
  2588. TotalSize += EachSize[i] + 1;
  2589. i++;
  2590. } else {
  2591. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2592. goto Done;
  2593. }
  2594. }
  2595. //
  2596. // write this section
  2597. //
  2598. if ( i == 0 ) {
  2599. //
  2600. // all settings are not configured
  2601. // delete the section
  2602. //
  2603. WritePrivateProfileString(
  2604. InfSectionName,
  2605. NULL,
  2606. NULL,
  2607. InfFileName
  2608. );
  2609. } else {
  2610. rc = SceInfpWriteInfSection(
  2611. InfFileName,
  2612. InfSectionName,
  2613. TotalSize+1,
  2614. EachLine,
  2615. &EachSize[0],
  2616. 0,
  2617. i-1,
  2618. Errlog
  2619. );
  2620. }
  2621. Done:
  2622. if ( rc != SCESTATUS_SUCCESS ) {
  2623. ScepBuildErrorLogInfo(
  2624. ScepSceStatusToDosError(rc),
  2625. Errlog,
  2626. SCEERR_WRITE_INFO,
  2627. InfSectionName
  2628. );
  2629. }
  2630. //
  2631. // free memory
  2632. //
  2633. for ( i=0; i<4; i++ ) {
  2634. if ( EachLine[i] != NULL )
  2635. ScepFree(EachLine[i]);
  2636. }
  2637. return(rc);
  2638. }
  2639. SCESTATUS
  2640. SceInfpWriteInfSection(
  2641. IN PCWSTR InfFileName,
  2642. IN PCWSTR InfSectionName,
  2643. IN DWORD TotalSize,
  2644. IN PWSTR *EachLineStr,
  2645. IN DWORD *EachLineSize,
  2646. IN DWORD StartIndex,
  2647. IN DWORD EndIndex,
  2648. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2649. )
  2650. /* ++
  2651. Routine Description:
  2652. This routine writes information in a array (each element in the array
  2653. represents a line in the section) to the section specified by
  2654. InfSectionName in the file specified by InfFileName. TotalSize is used
  2655. to allocate a block of memory for writing.
  2656. Arguments:
  2657. InfFileName - the INF file name
  2658. InfSectionName - the section into which to write information
  2659. TotalSize - The size of the buffer required to write
  2660. EachLineStr - a array of strings (each element represents a line )
  2661. EachLineSize - a array of numbers (each number is the size of the corresponding
  2662. element in EachLineStr).
  2663. StartIndex - The first index of the array
  2664. EndIndex - The last index of the array
  2665. Errlog - The list of errors
  2666. Return value:
  2667. Win32 error code
  2668. -- */
  2669. {
  2670. PWSTR SectionString=NULL;
  2671. PWSTR pTemp;
  2672. DWORD i;
  2673. BOOL status;
  2674. DWORD rc = NO_ERROR;
  2675. if (InfFileName == NULL || InfSectionName == NULL ||
  2676. EachLineStr == NULL || EachLineSize == NULL )
  2677. return(SCESTATUS_INVALID_PARAMETER);
  2678. if ( TotalSize > 1 ) {
  2679. SectionString = (PWSTR)ScepAlloc( (UINT)0, (TotalSize+1)*sizeof(WCHAR));
  2680. if ( SectionString == NULL ) {
  2681. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2682. return(rc);
  2683. }
  2684. pTemp = SectionString;
  2685. for ( i=StartIndex; i<=EndIndex; i++) {
  2686. if ( EachLineStr[i] != NULL && EachLineSize[i] > 0 ) {
  2687. wcsncpy(pTemp, EachLineStr[i], EachLineSize[i]);
  2688. pTemp += EachLineSize[i];
  2689. *pTemp = L'\0';
  2690. pTemp++;
  2691. }
  2692. }
  2693. *pTemp = L'\0';
  2694. //
  2695. // writes the profile section, the following call should empty the section then
  2696. // add all keys in SectionString to the section.
  2697. //
  2698. status = WritePrivateProfileSection(
  2699. InfSectionName,
  2700. SectionString,
  2701. InfFileName
  2702. );
  2703. if ( status == FALSE ) {
  2704. rc = GetLastError();
  2705. ScepBuildErrorLogInfo(
  2706. rc,
  2707. Errlog,
  2708. SCEERR_WRITE_INFO,
  2709. InfSectionName
  2710. );
  2711. }
  2712. ScepFree(SectionString);
  2713. SectionString = NULL;
  2714. }
  2715. return(ScepDosErrorToSceStatus(rc));
  2716. }
  2717. DWORD
  2718. SceInfpWriteListSection(
  2719. IN PCWSTR InfFileName,
  2720. IN PCWSTR InfSectionName,
  2721. IN DWORD TotalSize,
  2722. IN PSCE_NAME_LIST ListLines,
  2723. IN DWORD Option,
  2724. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2725. )
  2726. /* ++
  2727. Routine Description:
  2728. This routine writes information in a PSCE_NAME_LIST type list (each node
  2729. in the list represents a line in the section) to the section specified
  2730. by InfSectionName in the file specified by InfFileName. TotalSize is used
  2731. to allocate a block of memory for writing.
  2732. Arguments:
  2733. InfFileName - the INF file name
  2734. InfSectionName - the section into which to write information
  2735. TotalSize - The size of the buffer required to write
  2736. ListLines - The list of each line's text
  2737. Errlog - The list of errors
  2738. Return value:
  2739. Win32 error code
  2740. -- */
  2741. {
  2742. PWSTR SectionString=NULL;
  2743. PWSTR pTemp;
  2744. PSCE_NAME_LIST pName;
  2745. BOOL status;
  2746. DWORD rc=NO_ERROR;
  2747. DWORD Len;
  2748. if ( TotalSize > 1 ) {
  2749. SectionString = (PWSTR)ScepAlloc( (UINT)0, TotalSize*sizeof(WCHAR));
  2750. if ( SectionString == NULL ) {
  2751. rc = ERROR_NOT_ENOUGH_MEMORY;
  2752. return(rc);
  2753. }
  2754. pTemp = SectionString;
  2755. for ( pName=ListLines; pName != NULL; pName = pName->Next ) {
  2756. Len = wcslen(pName->Name);
  2757. wcsncpy(pTemp, pName->Name, Len);
  2758. pTemp += Len;
  2759. if ( Option & SCEINF_ADD_EQUAL_SIGN ) {
  2760. *pTemp++ = L' ';
  2761. *pTemp++ = L'=';
  2762. }
  2763. *pTemp++ = L'\0';
  2764. }
  2765. *pTemp = L'\0';
  2766. /*
  2767. if ( !( Option & SCEINF_APPEND_SECTION ) ) {
  2768. //
  2769. // empty the section first
  2770. //
  2771. WritePrivateProfileString(
  2772. InfSectionName,
  2773. NULL,
  2774. NULL,
  2775. InfFileName
  2776. );
  2777. }
  2778. //
  2779. // write the section
  2780. //
  2781. status = WritePrivateProfileSection(
  2782. InfSectionName,
  2783. SectionString,
  2784. InfFileName
  2785. );
  2786. */
  2787. //
  2788. // write the section
  2789. //
  2790. rc = ScepWritePrivateProfileSection(
  2791. InfSectionName,
  2792. SectionString,
  2793. InfFileName,
  2794. ( Option & SCEINF_APPEND_SECTION ) ? FALSE : TRUE
  2795. );
  2796. ScepFree(SectionString);
  2797. SectionString = NULL;
  2798. // if ( status == FALSE ) {
  2799. // rc = GetLastError();
  2800. if ( ERROR_SUCCESS != rc ) {
  2801. ScepBuildErrorLogInfo(
  2802. rc,
  2803. Errlog,
  2804. SCEERR_WRITE_INFO,
  2805. InfSectionName
  2806. );
  2807. }
  2808. }
  2809. return(rc);
  2810. }
  2811. LONG
  2812. SceInfpConvertNameListToString(
  2813. IN LSA_HANDLE LsaPolicy,
  2814. IN PCWSTR KeyText,
  2815. IN PSCE_NAME_LIST Fields,
  2816. IN BOOL bOverwrite,
  2817. OUT PWSTR *Strvalue,
  2818. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2819. )
  2820. /* ++
  2821. Routine Description:
  2822. This routine converts names in a name list to comma delimited string.
  2823. The format of the returned string is KeyText = f1,f2,f3,f4... where
  2824. f1..fn are names in the name list.
  2825. Arguments:
  2826. KeyText - a string represents the key (left side of the = sign)
  2827. Fields - The name list
  2828. Strvalue - The output string
  2829. Errlog - The error list
  2830. Return value:
  2831. Length of the output string if successful. -1 if error.
  2832. -- */
  2833. {
  2834. DWORD TotalSize;
  2835. DWORD Strsize;
  2836. PWSTR pTemp = NULL;
  2837. PSCE_NAME_LIST pName;
  2838. SCE_TEMP_NODE *tmpArray=NULL, *pa=NULL;
  2839. DWORD i=0,j;
  2840. DWORD cntAllocated=0;
  2841. DWORD rc=ERROR_SUCCESS;
  2842. //
  2843. // count the total size of all fields
  2844. //
  2845. for ( pName=Fields, TotalSize=0; pName != NULL; pName = pName->Next ) {
  2846. if (pName->Name[0] == L'\0') {
  2847. continue;
  2848. }
  2849. if ( i >= cntAllocated ) {
  2850. //
  2851. // array is not enough, reallocate
  2852. //
  2853. tmpArray = (SCE_TEMP_NODE *)ScepAlloc(LPTR, (cntAllocated+16)*sizeof(SCE_TEMP_NODE));
  2854. if ( tmpArray ) {
  2855. //
  2856. // move pointers from the old array to the new array
  2857. //
  2858. if ( pa ) {
  2859. for ( j=0; j<cntAllocated; j++ ) {
  2860. tmpArray[j].Name = pa[j].Name;
  2861. tmpArray[j].Len = pa[j].Len;
  2862. tmpArray[j].bFree = pa[j].bFree;
  2863. }
  2864. ScepFree(pa);
  2865. }
  2866. pa = tmpArray;
  2867. tmpArray = NULL;
  2868. cntAllocated += 16;
  2869. } else {
  2870. rc = ERROR_NOT_ENOUGH_MEMORY;
  2871. break;
  2872. }
  2873. }
  2874. pTemp = NULL;
  2875. if ( wcschr(pName->Name, L'\\') &&
  2876. LsaPolicy ) {
  2877. //
  2878. // check if the name has a '\' in it, it should be translated to
  2879. // *SID
  2880. //
  2881. ScepConvertNameToSidString(LsaPolicy, pName->Name, FALSE, &pTemp, &Strsize);
  2882. if ( pTemp ) {
  2883. pa[i].Name = pTemp;
  2884. pa[i].bFree = TRUE;
  2885. } else {
  2886. pa[i].Name = pName->Name;
  2887. pa[i].bFree = FALSE;
  2888. Strsize = wcslen(pName->Name);
  2889. }
  2890. } else {
  2891. if ( ScepLookupWellKnownName(
  2892. pName->Name,
  2893. LsaPolicy,
  2894. &pTemp) ) {
  2895. pa[i].Name = pTemp;
  2896. pa[i].bFree = TRUE;
  2897. Strsize = wcslen(pTemp);
  2898. }
  2899. else {
  2900. pa[i].Name = pName->Name;
  2901. pa[i].bFree = FALSE;
  2902. Strsize = wcslen(pName->Name);
  2903. }
  2904. }
  2905. pa[i].Len = Strsize;
  2906. TotalSize += Strsize + 1;
  2907. i++;
  2908. }
  2909. if ( ERROR_SUCCESS == rc ) {
  2910. //
  2911. // The format of the string is
  2912. // KeyText = f1,f2,f3,....
  2913. //
  2914. if ( bOverwrite ) {
  2915. Strsize = 3 + wcslen(KeyText);
  2916. if ( TotalSize > 0 )
  2917. TotalSize += Strsize;
  2918. else
  2919. TotalSize = Strsize;
  2920. } else {
  2921. Strsize = 0;
  2922. }
  2923. *Strvalue = (PWSTR)ScepAlloc((UINT)0, (TotalSize+1)*sizeof(WCHAR));
  2924. if ( *Strvalue == NULL ) {
  2925. rc = ERROR_NOT_ENOUGH_MEMORY;
  2926. } else {
  2927. if ( bOverwrite ) {
  2928. swprintf(*Strvalue, L"%s = ", KeyText);
  2929. }
  2930. pTemp = *Strvalue + Strsize;
  2931. for (j=0; j<i; j++) {
  2932. if ( pa[j].Name ) {
  2933. wcscpy(pTemp, pa[j].Name);
  2934. pTemp += pa[j].Len;
  2935. *pTemp = L',';
  2936. pTemp++;
  2937. }
  2938. }
  2939. if ( pTemp != (*Strvalue+Strsize) ) {
  2940. *(pTemp-1) = L'\0';
  2941. }
  2942. *pTemp = L'\0';
  2943. }
  2944. }
  2945. if ( pa ) {
  2946. for ( j=0; j<i; j++ ) {
  2947. if ( pa[j].Name && pa[j].bFree ) {
  2948. ScepFree(pa[j].Name);
  2949. }
  2950. }
  2951. ScepFree(pa);
  2952. }
  2953. if ( rc != ERROR_SUCCESS ) {
  2954. return(-1);
  2955. } else if ( TotalSize == 0 ) {
  2956. return(TotalSize);
  2957. } else {
  2958. return(TotalSize-1);
  2959. }
  2960. }
  2961. #if 0
  2962. SCESTATUS
  2963. WINAPI
  2964. SceWriteUserSection(
  2965. IN PCWSTR InfProfileName,
  2966. IN PWSTR Name,
  2967. IN PSCE_USER_PROFILE pProfile,
  2968. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2969. )
  2970. /* ++
  2971. Routine Description:
  2972. Arguments:
  2973. Return Value:
  2974. -- */
  2975. {
  2976. PWSTR InfSectionName=NULL;
  2977. SCESTATUS rc;
  2978. PWSTR EachLine[12];
  2979. DWORD EachSize[12];
  2980. DWORD TotalSize;
  2981. TCHAR Keyname[SCE_KEY_MAX_LENGTH];
  2982. DWORD Value;
  2983. LONG Keysize, i;
  2984. PSCE_LOGON_HOUR pLogonHour=NULL;
  2985. PWSTR Strvalue=NULL;
  2986. if ( InfProfileName == NULL ||
  2987. Name == NULL ||
  2988. pProfile == NULL ) {
  2989. return(SCESTATUS_INVALID_PARAMETER);
  2990. }
  2991. //
  2992. // process each detail profile section
  2993. //
  2994. for ( i=0; i<12; i++ ) {
  2995. EachLine[i] = NULL;
  2996. EachSize[i] = 0;
  2997. }
  2998. TotalSize=0;
  2999. memset(Keyname, '\0', SCE_KEY_MAX_LENGTH*sizeof(WCHAR));
  3000. i = 0;
  3001. InfSectionName = (PWSTR)ScepAlloc(LMEM_ZEROINIT, (wcslen(Name)+12)*sizeof(WCHAR));
  3002. if ( InfSectionName == NULL )
  3003. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  3004. swprintf(InfSectionName, L"UserProfile %s", Name);
  3005. //
  3006. // initialize the error log buffer
  3007. //
  3008. if ( Errlog ) {
  3009. *Errlog = NULL;
  3010. }
  3011. if ( pProfile->DisallowPasswordChange != SCE_NO_VALUE ) {
  3012. // DisallowPasswordChange
  3013. Value = pProfile->DisallowPasswordChange == 0 ? 0 : 1;
  3014. swprintf(Keyname, L"DisallowPasswordChange = %d", Value);
  3015. rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], 30, Keyname );
  3016. if ( rc != SCESTATUS_SUCCESS) {
  3017. ScepBuildErrorLogInfo(
  3018. ScepSceStatusToDosError(rc),
  3019. Errlog,
  3020. SCEERR_ADDTO,
  3021. L"DisallowPasswordChange",
  3022. InfSectionName
  3023. );
  3024. goto Done;
  3025. }
  3026. TotalSize += EachSize[i]+1;
  3027. i++;
  3028. }
  3029. if ( pProfile->NeverExpirePassword != SCE_NO_VALUE ||
  3030. pProfile->ForcePasswordChange != SCE_NO_VALUE ) {
  3031. // PasswordChangeStyle
  3032. if ( pProfile->NeverExpirePassword != SCE_NO_VALUE &&
  3033. pProfile->NeverExpirePassword != 0 )
  3034. Value = 1;
  3035. else {
  3036. if ( pProfile->ForcePasswordChange != SCE_NO_VALUE &&
  3037. pProfile->ForcePasswordChange != 0 )
  3038. Value = 2;
  3039. else
  3040. Value = 0;
  3041. }
  3042. swprintf(Keyname, L"PasswordChangeStyle = %d", Value);
  3043. rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], 30, Keyname );
  3044. if ( rc != SCESTATUS_SUCCESS) {
  3045. ScepBuildErrorLogInfo(
  3046. ScepSceStatusToDosError(rc),
  3047. Errlog,
  3048. SCEERR_ADDTO,
  3049. L"PasswordChangeStyle",
  3050. InfSectionName
  3051. );
  3052. goto Done;
  3053. }
  3054. TotalSize += EachSize[i]+1;
  3055. i++;
  3056. }
  3057. if ( pProfile->AccountDisabled != SCE_NO_VALUE ) {
  3058. // AccountDisabled
  3059. Value = pProfile->AccountDisabled == 0 ? 0 : 1;
  3060. swprintf(Keyname, L"AccountDisabled = %d", Value);
  3061. rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], 30, Keyname );
  3062. if ( rc != SCESTATUS_SUCCESS) {
  3063. ScepBuildErrorLogInfo(
  3064. ScepSceStatusToDosError(rc),
  3065. Errlog,
  3066. SCEERR_ADDTO,
  3067. L"AccountDisabled",
  3068. InfSectionName
  3069. );
  3070. goto Done;
  3071. }
  3072. TotalSize += EachSize[i]+1;
  3073. i++;
  3074. }
  3075. if ( pProfile->UserProfile != NULL ) {
  3076. // UserProfile
  3077. swprintf(Keyname, L"UserProfile = %s", pProfile->UserProfile);
  3078. rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], wcslen(Keyname)+10, Keyname );
  3079. if ( rc != SCESTATUS_SUCCESS) {
  3080. ScepBuildErrorLogInfo(
  3081. ScepSceStatusToDosError(rc),
  3082. Errlog,
  3083. SCEERR_ADDTO,
  3084. L"UserProfile",
  3085. InfSectionName
  3086. );
  3087. goto Done;
  3088. }
  3089. TotalSize += EachSize[i]+1;
  3090. i++;
  3091. }
  3092. if ( pProfile->LogonScript != NULL ) {
  3093. // LogonScript
  3094. swprintf(Keyname, L"LogonScript = %s", pProfile->LogonScript);
  3095. rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], wcslen(Keyname)+10, Keyname );
  3096. if ( rc != SCESTATUS_SUCCESS) {
  3097. ScepBuildErrorLogInfo(
  3098. ScepSceStatusToDosError(rc),
  3099. Errlog,
  3100. SCEERR_ADDTO,
  3101. L"LogonScript",
  3102. InfSectionName
  3103. );
  3104. goto Done;
  3105. }
  3106. TotalSize += EachSize[i]+1;
  3107. i++;
  3108. }
  3109. if ( pProfile->HomeDir != NULL ) {
  3110. // HomeDir
  3111. swprintf(Keyname, L"HomeDir = %s", pProfile->HomeDir);
  3112. rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], wcslen(Keyname)+10, Keyname );
  3113. if ( rc != SCESTATUS_SUCCESS) {
  3114. ScepBuildErrorLogInfo(
  3115. ScepSceStatusToDosError(rc),
  3116. Errlog,
  3117. SCEERR_ADDTO,
  3118. L"HomeDir",
  3119. InfSectionName
  3120. );
  3121. goto Done;
  3122. }
  3123. TotalSize += EachSize[i]+1;
  3124. i++;
  3125. }
  3126. if ( pProfile->pLogonHours != NULL ) {
  3127. // LogonHours
  3128. swprintf(Keyname, L"LogonHours = ");
  3129. Keysize = wcslen(Keyname);
  3130. for ( pLogonHour=pProfile->pLogonHours;
  3131. pLogonHour != NULL;
  3132. pLogonHour = pLogonHour->Next) {
  3133. swprintf(&Keyname[Keysize], L"%d,%d,",pLogonHour->Start,
  3134. pLogonHour->End);
  3135. Keysize += ((pLogonHour->Start < 9) ? 2 : 3) +
  3136. ((pLogonHour->End < 9 ) ? 2 : 3);
  3137. }
  3138. // turn off the last comma
  3139. Keyname[Keysize-1] = L'\0';
  3140. rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], Keysize+5, Keyname );
  3141. if ( rc != SCESTATUS_SUCCESS) {
  3142. ScepBuildErrorLogInfo(
  3143. ScepSceStatusToDosError(rc),
  3144. Errlog,
  3145. SCEERR_ADDTO,
  3146. L"LogonHours",
  3147. InfSectionName
  3148. );
  3149. goto Done;
  3150. }
  3151. TotalSize += EachSize[i]+1;
  3152. i++;
  3153. }
  3154. if ( pProfile->pWorkstations.Buffer != NULL ) {
  3155. // Workstations
  3156. Keysize = SceInfpConvertMultiSZToString(
  3157. L"Workstations",
  3158. pProfile->pWorkstations,
  3159. &Strvalue,
  3160. Errlog
  3161. );
  3162. if ( Keysize > 0 ) {
  3163. EachLine[i] = Strvalue;
  3164. EachSize[i] = Keysize;
  3165. Strvalue = NULL;
  3166. } else {
  3167. rc = SCESTATUS_OTHER_ERROR;
  3168. ScepFree(Strvalue);
  3169. Strvalue = NULL;
  3170. goto Done;
  3171. }
  3172. if ( rc != SCESTATUS_SUCCESS) {
  3173. ScepBuildErrorLogInfo(
  3174. ScepSceStatusToDosError(rc),
  3175. Errlog,
  3176. SCEERR_ADDTO,
  3177. L"WorkstationRestricitons",
  3178. InfSectionName
  3179. );
  3180. goto Done;
  3181. }
  3182. TotalSize += EachSize[i]+1;
  3183. i++;
  3184. }
  3185. if ( pProfile->pGroupsBelongsTo != NULL ) {
  3186. // GroupsBelongsTo
  3187. Keysize = SceInfpConvertNameListToString(
  3188. NULL,
  3189. L"GroupsBelongsTo",
  3190. pProfile->pGroupsBelongsTo,
  3191. TRUE,
  3192. &Strvalue,
  3193. Errlog
  3194. );
  3195. if ( Keysize > 0 ) {
  3196. EachLine[i] = Strvalue;
  3197. EachSize[i] = Keysize;
  3198. Strvalue = NULL;
  3199. } else {
  3200. rc = SCESTATUS_OTHER_ERROR;
  3201. ScepFree(Strvalue);
  3202. Strvalue = NULL;
  3203. goto Done;
  3204. }
  3205. if ( rc != SCESTATUS_SUCCESS) {
  3206. ScepBuildErrorLogInfo(
  3207. ScepSceStatusToDosError(rc),
  3208. Errlog,
  3209. SCEERR_ADDTO,
  3210. L"GroupsBelongsTo",
  3211. InfSectionName
  3212. );
  3213. goto Done;
  3214. }
  3215. TotalSize += EachSize[i]+1;
  3216. i++;
  3217. }
  3218. if ( pProfile->pAssignToUsers != NULL ) {
  3219. // AssignToUsers
  3220. Keysize = SceInfpConvertNameListToString(
  3221. NULL,
  3222. L"AssignToUsers",
  3223. pProfile->pAssignToUsers,
  3224. TRUE,
  3225. &Strvalue,
  3226. Errlog
  3227. );
  3228. if ( Keysize > 0 ) {
  3229. EachLine[i] = Strvalue;
  3230. EachSize[i] = Keysize;
  3231. Strvalue = NULL;
  3232. } else {
  3233. rc = SCESTATUS_OTHER_ERROR;
  3234. ScepFree(Strvalue);
  3235. Strvalue = NULL;
  3236. goto Done;
  3237. }
  3238. } else {
  3239. swprintf(Keyname, L"AssignToUsers = ");
  3240. rc = ScepAllocateAndCopy(&EachLine[i], &EachSize[i], 30, Keyname );
  3241. }
  3242. if ( rc != SCESTATUS_SUCCESS) {
  3243. ScepBuildErrorLogInfo(
  3244. ScepSceStatusToDosError(rc),
  3245. Errlog,
  3246. SCEERR_ADDTO,
  3247. L"AssignToUsers",
  3248. InfSectionName
  3249. );
  3250. goto Done;
  3251. }
  3252. TotalSize += EachSize[i]+1;
  3253. i++;
  3254. if ( pProfile->pHomeDirSecurity != NULL ) {
  3255. // HomeDirSecurity
  3256. rc = ConvertSecurityDescriptorToText(
  3257. pProfile->pHomeDirSecurity,
  3258. pProfile->HomeSeInfo,
  3259. &Strvalue,
  3260. (PULONG)&Keysize
  3261. );
  3262. if ( rc == NO_ERROR ) {
  3263. EachSize[i] = Keysize + 21;
  3264. EachLine[i] = (PWSTR)ScepAlloc( 0, EachSize[i]*sizeof(WCHAR));
  3265. if ( EachLine[i] != NULL ) {
  3266. swprintf(EachLine[i], L"HomeDirSecurity = \"%s\"", Strvalue);
  3267. EachLine[i][EachSize[i]-1] = L'\0';
  3268. } else
  3269. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3270. ScepFree(Strvalue);
  3271. Strvalue = NULL;
  3272. } else {
  3273. ScepBuildErrorLogInfo(
  3274. rc,
  3275. Errlog,
  3276. SCEERR_ADD,
  3277. L"HomeDirSecurity",
  3278. InfSectionName
  3279. );
  3280. rc = ScepDosErrorToSceStatus(rc);
  3281. }
  3282. if ( rc != SCESTATUS_SUCCESS )
  3283. goto Done;
  3284. TotalSize += EachSize[i]+1;
  3285. i++;
  3286. }
  3287. if ( pProfile->pTempDirSecurity != NULL ) {
  3288. // TempDirSecurity
  3289. rc = ConvertSecurityDescriptorToText(
  3290. pProfile->pTempDirSecurity,
  3291. pProfile->TempSeInfo,
  3292. &Strvalue,
  3293. (PULONG)&Keysize
  3294. );
  3295. if ( rc == NO_ERROR ) {
  3296. EachSize[i] = Keysize + 21;
  3297. EachLine[i] = (PWSTR)ScepAlloc( 0, EachSize[i]*sizeof(WCHAR));
  3298. if ( EachLine[i] != NULL ) {
  3299. swprintf(EachLine[i], L"TempDirSecurity = \"%s\"", Strvalue);
  3300. EachLine[i][EachSize[i]-1] = L'\0';
  3301. } else
  3302. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3303. ScepFree(Strvalue);
  3304. Strvalue = NULL;
  3305. } else {
  3306. ScepBuildErrorLogInfo(
  3307. rc,
  3308. Errlog,
  3309. SCEERR_ADDTO,
  3310. L"TempDirSecurity",
  3311. InfSectionName
  3312. );
  3313. rc = ScepDosErrorToSceStatus(rc);
  3314. }
  3315. if ( rc != SCESTATUS_SUCCESS )
  3316. goto Done;
  3317. TotalSize += EachSize[i]+1;
  3318. i++;
  3319. }
  3320. //
  3321. // write to this profile's section
  3322. //
  3323. rc = SceInfpWriteInfSection(
  3324. InfProfileName,
  3325. InfSectionName,
  3326. TotalSize+1,
  3327. EachLine,
  3328. &EachSize[0],
  3329. 0,
  3330. i-1,
  3331. Errlog
  3332. );
  3333. if ( rc != SCESTATUS_SUCCESS )
  3334. goto Done;
  3335. Done:
  3336. if ( InfSectionName != NULL )
  3337. ScepFree(InfSectionName);
  3338. if ( Strvalue != NULL )
  3339. ScepFree(Strvalue);
  3340. for ( i=0; i<12; i++ )
  3341. if ( EachLine[i] != NULL )
  3342. ScepFree(EachLine[i]);
  3343. return(rc);
  3344. }
  3345. #endif
  3346. LONG
  3347. SceInfpConvertMultiSZToString(
  3348. IN PCWSTR KeyText,
  3349. IN UNICODE_STRING Fields,
  3350. OUT PWSTR *Strvalue,
  3351. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  3352. )
  3353. /* ++
  3354. Routine Description:
  3355. This routine converts names in a unicode string in Multi-SZ format
  3356. (separated by NULLs) to comma delimited string. The format of the
  3357. returned string is KeyText = f1,f2,f3,f4... where f1..fn are names
  3358. in the unicode string.
  3359. Arguments:
  3360. KeyText - a string represents the key (left side of the = sign)
  3361. Fields - The Multi-SZ string
  3362. Strvalue - The output string
  3363. Errlog - The error list
  3364. Return value:
  3365. Length of the output string if successful. -1 if error.
  3366. -- */
  3367. {
  3368. DWORD TotalSize;
  3369. DWORD Strsize;
  3370. PWSTR pTemp = NULL;
  3371. PWSTR pField=NULL;
  3372. //
  3373. // The format of the string is
  3374. // KeyText = f1,f2,f3,....
  3375. //
  3376. Strsize = 3 + wcslen(KeyText);
  3377. TotalSize = Fields.Length/2 + Strsize;
  3378. *Strvalue = (PWSTR)ScepAlloc((UINT)0, (TotalSize+1)*sizeof(WCHAR));
  3379. if ( *Strvalue == NULL ) {
  3380. return(-1);
  3381. }
  3382. swprintf(*Strvalue, L"%s = ", KeyText);
  3383. pTemp = *Strvalue + Strsize;
  3384. pField = Fields.Buffer;
  3385. while ( pField != NULL && pField[0] ) {
  3386. wcscpy(pTemp, pField);
  3387. Strsize = wcslen(pField);
  3388. pField += Strsize+1;
  3389. pTemp += Strsize;
  3390. *pTemp = L',';
  3391. pTemp++;
  3392. }
  3393. *(pTemp-1) = L'\0';
  3394. *pTemp = L'\0';
  3395. return(TotalSize-1);
  3396. }
  3397. SCESTATUS
  3398. ScepAllocateAndCopy(
  3399. OUT PWSTR *Buffer,
  3400. OUT PDWORD BufSize,
  3401. IN DWORD MaxSize,
  3402. IN PWSTR SrcBuf
  3403. )
  3404. /* ++
  3405. Routine Description:
  3406. Arguments:
  3407. Return value:
  3408. -- */
  3409. {
  3410. *BufSize = 0;
  3411. *Buffer = (PWSTR)ScepAlloc( (UINT)0, MaxSize*sizeof(WCHAR));
  3412. if ( *Buffer == NULL ) {
  3413. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  3414. }
  3415. wcscpy(*Buffer, SrcBuf);
  3416. *BufSize = wcslen(*Buffer);
  3417. return(SCESTATUS_SUCCESS);
  3418. }
  3419. SCESTATUS
  3420. SceInfpBreakTextIntoMultiFields(
  3421. IN PWSTR szText,
  3422. IN DWORD dLen,
  3423. OUT LPDWORD pnFields,
  3424. OUT LPDWORD *arrOffset
  3425. )
  3426. /*
  3427. If the text length is greater than MAX_STRING_LENGTH-1, this routine will
  3428. find out how many "blocks" the text can be break into (each block is less
  3429. than MAX_STRING_LENGTH-1), and the starting offsets of each block.
  3430. Setupapi has string length limit of MAX_STRING_LENGTH per field in a inf
  3431. file. SCE use setupapi to parse security templates which contain security
  3432. descriptors in text format which can have unlimited aces. So when SCE saves
  3433. text format of security descriptors into a inf file, it will break the text
  3434. into multiple fields if the length is over limit. Setupapi does not have
  3435. limit on number of fields per line.
  3436. The break point occurs when the following characters are encountered in the
  3437. text: ) ( ; " or space
  3438. */
  3439. {
  3440. SCESTATUS rc=SCESTATUS_SUCCESS;
  3441. DWORD nFields;
  3442. DWORD nProc;
  3443. DWORD * newBuffer=NULL;
  3444. DWORD i;
  3445. if ( !pnFields || !arrOffset ) {
  3446. return(SCESTATUS_INVALID_PARAMETER);
  3447. }
  3448. *pnFields = 0;
  3449. *arrOffset = NULL;
  3450. if ( !szText || dLen == 0 ) {
  3451. return(SCESTATUS_SUCCESS);
  3452. }
  3453. //
  3454. // initialize one field always
  3455. //
  3456. nFields = 1;
  3457. *arrOffset = (DWORD *)ScepAlloc(0, nFields*sizeof(DWORD));
  3458. if ( *arrOffset ) {
  3459. (*arrOffset)[0] = 0;
  3460. if ( dLen > MAX_STRING_LENGTH-1 ) {
  3461. //
  3462. // loop through the text
  3463. //
  3464. nProc = (*arrOffset)[nFields-1] + MAX_STRING_LENGTH-2;
  3465. while ( SCESTATUS_SUCCESS == rc && nProc < dLen ) {
  3466. while ( nProc > (*arrOffset)[nFields-1] ) {
  3467. //
  3468. // looking for the break point
  3469. //
  3470. if ( L')' == *(szText+nProc) ||
  3471. L'(' == *(szText+nProc) ||
  3472. L';' == *(szText+nProc) ||
  3473. L' ' == *(szText+nProc) ||
  3474. L'\"' == *(szText+nProc) ) {
  3475. break;
  3476. } else {
  3477. nProc--;
  3478. }
  3479. }
  3480. if ( nProc <= (*arrOffset)[nFields-1] ) {
  3481. //
  3482. // no break point found, then just use MAX_STRING_LENGTH-2
  3483. //
  3484. nProc = (*arrOffset)[nFields-1]+MAX_STRING_LENGTH-2;
  3485. } else {
  3486. //
  3487. // else find a break poin at offset nProc, the next block
  3488. // starts at nProc+1
  3489. //
  3490. nProc++;
  3491. }
  3492. nFields++;
  3493. newBuffer = (DWORD *)ScepAlloc( 0, nFields*sizeof(DWORD));
  3494. if ( newBuffer ) {
  3495. for ( i=0; i<nFields-1; i++ ) {
  3496. newBuffer[i] = (*arrOffset)[i];
  3497. }
  3498. ScepFree(*arrOffset);
  3499. //
  3500. // set the offset to the last element
  3501. //
  3502. newBuffer[nFields-1] = nProc;
  3503. *arrOffset = newBuffer;
  3504. nProc = (*arrOffset)[nFields-1] + MAX_STRING_LENGTH-2;
  3505. } else {
  3506. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3507. }
  3508. }
  3509. }
  3510. *pnFields = nFields;
  3511. } else {
  3512. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3513. }
  3514. if ( SCESTATUS_SUCCESS != rc ) {
  3515. //
  3516. // if error occurs, free memory and clear the output buffer
  3517. //
  3518. *pnFields = 0;
  3519. if ( *arrOffset ) {
  3520. ScepFree(*arrOffset);
  3521. }
  3522. *arrOffset = NULL;
  3523. }
  3524. return(rc);
  3525. }
  3526. SCESTATUS
  3527. SceInfpWriteKerberosPolicy(
  3528. IN PCWSTR ProfileName,
  3529. IN PSCE_KERBEROS_TICKET_INFO pKerberosInfo,
  3530. IN BOOL bOverwrite,
  3531. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  3532. )
  3533. /*++
  3534. Routine Description:
  3535. This routine writes kerberos policy settings information to the INF file
  3536. in section [Kerberos Policy].
  3537. Arguments:
  3538. ProfileName - The profile to write to
  3539. pKerberosInfo - the Kerberos policy info (SCP) to write.
  3540. Errlog - A buffer to hold all error codes/text encountered when
  3541. parsing the INF file. If Errlog is NULL, no further error
  3542. information is returned except the return DWORD
  3543. Return value:
  3544. SCESTATUS - SCESTATUS_SUCCESS
  3545. SCESTATUS_NOT_ENOUGH_RESOURCE
  3546. SCESTATUS_INVALID_PARAMETER
  3547. SCESTATUS_CORRUPT_PROFILE
  3548. SCESTATUS_INVALID_DATA
  3549. --*/
  3550. {
  3551. SCESTATUS rc=SCESTATUS_SUCCESS;
  3552. SCE_KEY_LOOKUP AccessSCPLookup[] = {
  3553. {(PWSTR)TEXT("MaxTicketAge"), offsetof(struct _SCE_KERBEROS_TICKET_INFO_, MaxTicketAge), 'D'},
  3554. {(PWSTR)TEXT("MaxRenewAge"), offsetof(struct _SCE_KERBEROS_TICKET_INFO_, MaxRenewAge), 'D'},
  3555. {(PWSTR)TEXT("MaxServiceAge"), offsetof(struct _SCE_KERBEROS_TICKET_INFO_, MaxServiceAge), 'D'},
  3556. {(PWSTR)TEXT("MaxClockSkew"),offsetof(struct _SCE_KERBEROS_TICKET_INFO_, MaxClockSkew), 'D'},
  3557. {(PWSTR)TEXT("TicketValidateClient"), offsetof(struct _SCE_KERBEROS_TICKET_INFO_, TicketValidateClient), 'D'}
  3558. };
  3559. DWORD cAccess = sizeof(AccessSCPLookup) / sizeof(SCE_KEY_LOOKUP);
  3560. DWORD i, j;
  3561. PWSTR EachLine[10] = {0};
  3562. DWORD EachSize[10] = {0};
  3563. UINT Offset;
  3564. DWORD Len;
  3565. DWORD Value;
  3566. DWORD TotalSize=0;
  3567. if (!ProfileName ) {
  3568. return(SCESTATUS_INVALID_PARAMETER);
  3569. }
  3570. if ( !pKerberosInfo ) {
  3571. //
  3572. // if no kerberos information to write, just return success
  3573. // empty the section in the file
  3574. //
  3575. if ( bOverwrite ) {
  3576. WritePrivateProfileString(
  3577. szKerberosPolicy,
  3578. NULL,
  3579. NULL,
  3580. ProfileName
  3581. );
  3582. }
  3583. return(SCESTATUS_SUCCESS);
  3584. }
  3585. for ( i=0, j=0; i<cAccess; i++) {
  3586. //
  3587. // get settings in AccessLookup table
  3588. //
  3589. Offset = AccessSCPLookup[i].Offset;
  3590. Value = 0;
  3591. Len = wcslen(AccessSCPLookup[i].KeyString);
  3592. switch ( AccessSCPLookup[i].BufferType ) {
  3593. case 'D':
  3594. //
  3595. // Int Field
  3596. //
  3597. Value = *((DWORD *)((CHAR *)pKerberosInfo+Offset));
  3598. if ( Value != SCE_NO_VALUE ) {
  3599. EachSize[j] = Len+15;
  3600. }
  3601. break;
  3602. default:
  3603. //
  3604. // should not occur
  3605. //
  3606. break;
  3607. }
  3608. if ( EachSize[j] <= 0 )
  3609. continue;
  3610. if ( bOverwrite ) {
  3611. Len=(EachSize[j]+1)*sizeof(WCHAR);
  3612. EachLine[j] = (PWSTR)ScepAlloc( LMEM_ZEROINIT, Len);
  3613. if ( EachLine[j] == NULL ) {
  3614. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3615. goto Done;
  3616. }
  3617. if ( AccessSCPLookup[i].BufferType == 'D' ) {
  3618. swprintf(EachLine[j], L"%s = %d", AccessSCPLookup[i].KeyString, Value);
  3619. EachSize[j] = wcslen(EachLine[j]);
  3620. }
  3621. } else {
  3622. //
  3623. // in append mode, write one string at a time
  3624. //
  3625. ScepWriteOneIntValueToProfile(
  3626. ProfileName,
  3627. szKerberosPolicy,
  3628. AccessSCPLookup[i].KeyString,
  3629. Value
  3630. );
  3631. }
  3632. TotalSize += EachSize[j]+1;
  3633. j++;
  3634. }
  3635. //
  3636. // writes the profile section
  3637. //
  3638. if ( bOverwrite ) {
  3639. if ( j > 0 ) {
  3640. rc = SceInfpWriteInfSection(
  3641. ProfileName,
  3642. szKerberosPolicy,
  3643. TotalSize+1,
  3644. EachLine,
  3645. &EachSize[0],
  3646. 0,
  3647. j-1,
  3648. Errlog
  3649. );
  3650. } else {
  3651. WritePrivateProfileSection(
  3652. szKerberosPolicy,
  3653. NULL,
  3654. ProfileName);
  3655. }
  3656. }
  3657. Done:
  3658. for ( i=0; i<cAccess; i++ ) {
  3659. if ( EachLine[i] != NULL ) {
  3660. ScepFree(EachLine[i]);
  3661. }
  3662. EachLine[i] = NULL;
  3663. EachSize[i] = 0;
  3664. }
  3665. return(rc);
  3666. }
  3667. SCESTATUS
  3668. SceInfpWriteRegistryValues(
  3669. IN PCWSTR ProfileName,
  3670. IN PSCE_REGISTRY_VALUE_INFO pRegValues,
  3671. IN DWORD ValueCount,
  3672. IN BOOL bOverwrite,
  3673. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  3674. )
  3675. /*++
  3676. Routine Description:
  3677. This routine writes registry values to the INF file in section
  3678. [Registry Values].
  3679. Arguments:
  3680. ProfileName - The profile to write to
  3681. pRegValues - the registry values to write (in the format of ValueName=Value)
  3682. ValueCount - the number of values to write
  3683. Errlog - A buffer to hold all error codes/text encountered when
  3684. parsing the INF file. If Errlog is NULL, no further error
  3685. information is returned except the return DWORD
  3686. Return value:
  3687. SCESTATUS - SCESTATUS_SUCCESS
  3688. SCESTATUS_NOT_ENOUGH_RESOURCE
  3689. SCESTATUS_INVALID_PARAMETER
  3690. SCESTATUS_CORRUPT_PROFILE
  3691. SCESTATUS_INVALID_DATA
  3692. --*/
  3693. {
  3694. SCESTATUS rc=SCESTATUS_SUCCESS;
  3695. PSCE_NAME_LIST pNameList=NULL;
  3696. DWORD TotalSize=0;
  3697. DWORD i, ObjectSize;
  3698. if (!ProfileName ) {
  3699. return(SCESTATUS_INVALID_PARAMETER);
  3700. }
  3701. if ( !pRegValues || 0 == ValueCount ) {
  3702. //
  3703. // if no value to write, just return success
  3704. // empty the section in the file
  3705. //
  3706. if ( bOverwrite ) {
  3707. WritePrivateProfileString(
  3708. szRegistryValues,
  3709. NULL,
  3710. NULL,
  3711. ProfileName
  3712. );
  3713. }
  3714. return(SCESTATUS_SUCCESS);
  3715. }
  3716. for ( i=0; i<ValueCount; i++) {
  3717. //
  3718. // Get string fields. Don't care the key name or if it exist.
  3719. // Must have 3 fields each line.
  3720. //
  3721. rc = SceInfpWriteOneValue(
  3722. ProfileName,
  3723. pRegValues[i],
  3724. bOverwrite,
  3725. &pNameList,
  3726. &ObjectSize
  3727. );
  3728. if ( rc != SCESTATUS_SUCCESS ) {
  3729. ScepBuildErrorLogInfo(
  3730. rc,
  3731. Errlog,
  3732. SCEERR_WRITE_INFO,
  3733. pRegValues[i].FullValueName
  3734. );
  3735. goto Done;
  3736. }
  3737. TotalSize += ObjectSize + 1;
  3738. }
  3739. //
  3740. // write to this profile's section
  3741. //
  3742. if ( bOverwrite ) {
  3743. rc = SceInfpWriteListSection(
  3744. ProfileName,
  3745. szRegistryValues,
  3746. TotalSize+1,
  3747. pNameList,
  3748. 0,
  3749. Errlog
  3750. );
  3751. if ( rc != SCESTATUS_SUCCESS )
  3752. ScepBuildErrorLogInfo(
  3753. rc,
  3754. Errlog,
  3755. SCEERR_WRITE_INFO,
  3756. szRegistryValues
  3757. );
  3758. }
  3759. Done:
  3760. ScepFreeNameList(pNameList);
  3761. rc = ScepDosErrorToSceStatus(rc);
  3762. return(rc);
  3763. }
  3764. DWORD
  3765. SceInfpWriteOneValue(
  3766. IN PCWSTR ProfileName,
  3767. IN SCE_REGISTRY_VALUE_INFO RegValue,
  3768. IN BOOL bOverwrite,
  3769. OUT PSCE_NAME_LIST *pNameList,
  3770. OUT PDWORD ObjectSize
  3771. )
  3772. /* ++
  3773. Routine Description:
  3774. This routine builds registry valueName=value for one registry value
  3775. into the name list. Each value represents one line in the INF file.
  3776. Arguments:
  3777. RegValue - The registry value name and the value
  3778. pNameList - The output string list.
  3779. ObjectSize - size of this line
  3780. Return value:
  3781. SCESTATUS - SCESTATUS_SUCCESS
  3782. SCESTATUS_NOT_ENOUGH_RESOURCE
  3783. SCESTATUS_INVALID_PARAMETER
  3784. SCESTATUS_BAD_FORMAT
  3785. SCESTATUS_INVALID_DATA
  3786. -- */
  3787. {
  3788. DWORD rc=ERROR_SUCCESS;
  3789. PWSTR OneLine;
  3790. if ( !pNameList || !ObjectSize ) {
  3791. return(ERROR_INVALID_PARAMETER);
  3792. }
  3793. *ObjectSize = 0;
  3794. if ( RegValue.FullValueName && RegValue.Value ) {
  3795. if ( bOverwrite ) {
  3796. *ObjectSize = wcslen(RegValue.FullValueName);
  3797. }
  3798. if ( RegValue.ValueType == REG_SZ ||
  3799. RegValue.ValueType == REG_EXPAND_SZ ) {
  3800. // need to add "" around the string
  3801. *ObjectSize += (5+wcslen(RegValue.Value));
  3802. } else {
  3803. //
  3804. // to be safe, add more spaces to the buffer
  3805. // because ValueType can be "-1" now
  3806. //
  3807. *ObjectSize += (6+wcslen(RegValue.Value));
  3808. }
  3809. OneLine = (PWSTR)ScepAlloc(0, (*ObjectSize+1)*sizeof(WCHAR));
  3810. if ( OneLine ) {
  3811. if ( bOverwrite ) {
  3812. if ( RegValue.ValueType == REG_SZ ||
  3813. RegValue.ValueType == REG_EXPAND_SZ ) {
  3814. swprintf(OneLine, L"%s=%1d,\"%s\"\0", RegValue.FullValueName,
  3815. RegValue.ValueType, RegValue.Value);
  3816. } else {
  3817. swprintf(OneLine, L"%s=%1d,%s\0", RegValue.FullValueName,
  3818. RegValue.ValueType, RegValue.Value);
  3819. }
  3820. } else {
  3821. if ( RegValue.ValueType == REG_SZ ||
  3822. RegValue.ValueType == REG_EXPAND_SZ ) {
  3823. swprintf(OneLine, L"%1d,\"%s\"\0", RegValue.ValueType, RegValue.Value);
  3824. } else {
  3825. swprintf(OneLine, L"%1d,%s\0", RegValue.ValueType, RegValue.Value);
  3826. }
  3827. }
  3828. OneLine[*ObjectSize] = L'\0';
  3829. if ( bOverwrite ) {
  3830. rc = ScepAddToNameList(pNameList, OneLine, *ObjectSize);
  3831. } else {
  3832. //
  3833. // append mode, write one value at a time
  3834. //
  3835. WritePrivateProfileString( szRegistryValues,
  3836. RegValue.FullValueName,
  3837. OneLine,
  3838. ProfileName
  3839. );
  3840. }
  3841. ScepFree(OneLine);
  3842. } else {
  3843. rc = ERROR_NOT_ENOUGH_MEMORY;
  3844. }
  3845. }
  3846. return(rc);
  3847. }
  3848. SCESTATUS
  3849. WINAPI
  3850. SceSvcSetInformationTemplate(
  3851. IN PCWSTR TemplateName,
  3852. IN PCWSTR ServiceName,
  3853. IN BOOL bExact,
  3854. IN PSCESVC_CONFIGURATION_INFO ServiceInfo
  3855. )
  3856. /*
  3857. Routine Description:
  3858. Writes information to the template in section <ServiceName>. The information is
  3859. stored in ServiceInfo in the format of Key and Value. If bExact is set, only
  3860. exact matched keys are overwritten, else all section is overwritten by the info
  3861. in ServiceInfo.
  3862. When ServiceInfo is NULL and bExact is set, delete the entire section
  3863. Arguments:
  3864. TemplateName - the inf template name to write to
  3865. ServiceName - the section name to write to
  3866. bExact - TRUE = all existing information in the section is erased
  3867. ServiceInfo - the information to write
  3868. Return Value:
  3869. SCE status of this operation
  3870. */
  3871. {
  3872. if ( TemplateName == NULL || ServiceName == NULL ||
  3873. (ServiceInfo == NULL && !bExact ) ) {
  3874. return(SCESTATUS_INVALID_PARAMETER);
  3875. }
  3876. DWORD i;
  3877. if ( ServiceInfo != NULL ) {
  3878. for ( i=0; i<ServiceInfo->Count; i++ ) {
  3879. if ( ServiceInfo->Lines[i].Key == NULL ) {
  3880. return(SCESTATUS_INVALID_DATA);
  3881. }
  3882. }
  3883. }
  3884. //
  3885. // always write [Version] section.
  3886. //
  3887. WCHAR tmp[64];
  3888. memset(tmp, 0, 64*2);
  3889. wcscpy(tmp, L"signature=\"$CHICAGO$\"");
  3890. swprintf(tmp+wcslen(tmp)+1,L"Revision=%d\0\0",
  3891. SCE_TEMPLATE_MAX_SUPPORTED_VERSION);
  3892. WritePrivateProfileSection(
  3893. L"Version",
  3894. tmp,
  3895. TemplateName);
  3896. SCESTATUS rc=SCESTATUS_SUCCESS;
  3897. if ( (bExact && ServiceInfo == NULL) || !bExact ) {
  3898. //
  3899. // delete the entire section
  3900. //
  3901. if ( !WritePrivateProfileString(ServiceName, NULL, NULL, TemplateName) ) {
  3902. rc = ScepDosErrorToSceStatus(GetLastError());
  3903. }
  3904. }
  3905. if ( ServiceInfo == NULL ) {
  3906. return(rc);
  3907. }
  3908. if ( rc == SCESTATUS_SUCCESS ) {
  3909. //
  3910. // process each key/value in ServiceInfo
  3911. //
  3912. for ( i=0; i<ServiceInfo->Count; i++ ) {
  3913. if ( !WritePrivateProfileString(ServiceName,
  3914. ServiceInfo->Lines[i].Key,
  3915. ServiceInfo->Lines[i].Value,
  3916. TemplateName
  3917. ) ) {
  3918. rc = ScepDosErrorToSceStatus(GetLastError());
  3919. break;
  3920. }
  3921. }
  3922. }
  3923. //
  3924. // need to recover the crash - WMI
  3925. //
  3926. return(rc);
  3927. }
  3928. DWORD
  3929. ScepWritePrivateProfileSection(
  3930. IN LPCWSTR SectionName,
  3931. IN LPTSTR pData,
  3932. IN LPCWSTR FileName,
  3933. IN BOOL bOverwrite)
  3934. /*
  3935. Description:
  3936. This function is to provide the same function as WritePrivateProfileSection
  3937. and exceed the 32K limit of that function.
  3938. If the file doesn't exist, the file is always created in UNICODE.
  3939. If the file does exist and it's in UNICODE format (the first two bytes are
  3940. 0xFF, 0xFE), the data will be saved to the file in UNICODE.
  3941. If the file does exist and it's in ANSI format, the data will be saved to
  3942. the file in ANSI format.
  3943. Note, this function assumes that the file is exclusively accessed. It's not
  3944. an atomic operation as WritePrivateProfileSection. But since this is a
  3945. private function implemented for SCE only and SCE always uses temporary
  3946. files (exclusive for each client), there is no problem doing this way.
  3947. Note 2, new data section is always added to the end of the file. Existing
  3948. data in the section will be moved to the end of the file as well.
  3949. Arguments:
  3950. SectionName - the section name to write data to
  3951. FileName - the full path file name to write data to
  3952. pData - data in MULTI-SZ format (with no size limit)
  3953. bOverwrite - TRUE=data will overwrite entire section in the file
  3954. */
  3955. {
  3956. if ( SectionName == NULL || FileName == NULL ) {
  3957. return ERROR_INVALID_PARAMETER;
  3958. }
  3959. DWORD rc=ERROR_SUCCESS;
  3960. //
  3961. // check to see if the file exist
  3962. //
  3963. if ( 0xFFFFFFFF != GetFileAttributes(FileName) ) {
  3964. //
  3965. // file eixsts.
  3966. //
  3967. if ( !bOverwrite && pData != NULL ) {
  3968. //
  3969. // Need to check if the same section exists and if so
  3970. // append the data
  3971. //
  3972. rc = ScepAppendProfileSection(SectionName, FileName, pData);
  3973. } else {
  3974. //
  3975. // the existint data, if any, is not interesting. delete it
  3976. // if the section does not exist at all, the next call won't fail
  3977. //
  3978. if ( !WritePrivateProfileSection(
  3979. SectionName,
  3980. NULL,
  3981. FileName
  3982. ) ) {
  3983. rc = GetLastError();
  3984. } else if ( pData ) {
  3985. //
  3986. // now write the new data in
  3987. //
  3988. rc = ScepOverwriteProfileSection(SectionName,
  3989. FileName,
  3990. pData,
  3991. SCEP_PROFILE_WRITE_SECTIONNAME,
  3992. NULL);
  3993. }
  3994. }
  3995. } else if ( pData ) {
  3996. //
  3997. // the file does not exist, no need to empty existing data
  3998. //
  3999. rc = ScepOverwriteProfileSection(SectionName,
  4000. FileName,
  4001. pData,
  4002. SCEP_PROFILE_WRITE_SECTIONNAME,
  4003. NULL);
  4004. }
  4005. return rc;
  4006. }
  4007. DWORD
  4008. ScepAppendProfileSection(
  4009. IN LPCWSTR SectionName,
  4010. IN LPCWSTR FileName,
  4011. IN LPTSTR pData
  4012. )
  4013. /*
  4014. Description:
  4015. Append the data to the section if the section exists, otherwise, create
  4016. the section and add data to it.
  4017. Arguments:
  4018. SectionName - the section name
  4019. FileName - the file name
  4020. pData - the data to append
  4021. */
  4022. {
  4023. DWORD rc=ERROR_SUCCESS;
  4024. DWORD dwSize;
  4025. PWSTR lpExisting = NULL;
  4026. WCHAR szBuffer[256];
  4027. DWORD nSize=256;
  4028. BOOL bSection=TRUE;
  4029. lpExisting = szBuffer;
  4030. szBuffer[0] = L'\0';
  4031. szBuffer[1] = L'\0';
  4032. PSCEP_SPLAY_TREE pKeys=NULL;
  4033. do {
  4034. //
  4035. // check if the section already exist
  4036. //
  4037. dwSize = GetPrivateProfileSection(SectionName, lpExisting, nSize, FileName );
  4038. if ( dwSize == 0 ) {
  4039. //
  4040. // either failed or the section does not exist
  4041. //
  4042. rc = GetLastError();
  4043. if ( ERROR_FILE_NOT_FOUND == rc ) {
  4044. //
  4045. // the file or section does not exist
  4046. //
  4047. rc = ERROR_SUCCESS;
  4048. break;
  4049. }
  4050. } else if ( dwSize < nSize - 2 ) {
  4051. //
  4052. // data get copied ok because the whole buffer is filled
  4053. //
  4054. break;
  4055. } else {
  4056. //
  4057. // buffer is not big enough, reallocate heap
  4058. //
  4059. if ( lpExisting && lpExisting != szBuffer ) {
  4060. LocalFree(lpExisting);
  4061. }
  4062. nSize += 256;
  4063. lpExisting = (PWSTR)LocalAlloc(LPTR, nSize*sizeof(TCHAR));
  4064. if ( lpExisting == NULL ) {
  4065. rc = ERROR_NOT_ENOUGH_MEMORY;
  4066. }
  4067. }
  4068. } while ( rc == ERROR_SUCCESS );
  4069. if ( ERROR_SUCCESS == rc && lpExisting[0] != L'\0') {
  4070. //
  4071. // now delete the existing section (to make sure the section will
  4072. // always be at the end)
  4073. //
  4074. if ( !WritePrivateProfileSection(
  4075. SectionName,
  4076. NULL,
  4077. FileName
  4078. ) ) {
  4079. //
  4080. // fail to delete the section
  4081. //
  4082. rc = GetLastError();
  4083. } else {
  4084. //
  4085. // save the new data first
  4086. //
  4087. pKeys = ScepSplayInitialize(SplayNodeStringType);
  4088. rc = ScepOverwriteProfileSection(SectionName,
  4089. FileName,
  4090. pData,
  4091. SCEP_PROFILE_WRITE_SECTIONNAME |
  4092. SCEP_PROFILE_GENERATE_KEYS,
  4093. pKeys
  4094. );
  4095. if ( ERROR_SUCCESS == rc ) {
  4096. //
  4097. // now append the old data and check for duplicate
  4098. //
  4099. rc = ScepOverwriteProfileSection(SectionName,
  4100. FileName,
  4101. lpExisting,
  4102. SCEP_PROFILE_CHECK_DUP,
  4103. pKeys
  4104. );
  4105. }
  4106. if ( pKeys ) {
  4107. ScepSplayFreeTree( &pKeys, TRUE );
  4108. }
  4109. }
  4110. } else if ( ERROR_SUCCESS == rc ) {
  4111. //
  4112. // now write the new data
  4113. //
  4114. rc = ScepOverwriteProfileSection(SectionName,
  4115. FileName,
  4116. pData,
  4117. SCEP_PROFILE_WRITE_SECTIONNAME,
  4118. NULL
  4119. );
  4120. }
  4121. //
  4122. // free existing data buffer
  4123. //
  4124. if ( lpExisting && (lpExisting != szBuffer) ) {
  4125. LocalFree(lpExisting);
  4126. }
  4127. return rc;
  4128. }
  4129. DWORD
  4130. ScepOverwriteProfileSection(
  4131. IN LPCWSTR SectionName,
  4132. IN LPCWSTR FileName,
  4133. IN LPTSTR pData,
  4134. IN DWORD dwFlags,
  4135. IN OUT PSCEP_SPLAY_TREE pKeys OPTIONAL
  4136. )
  4137. /*
  4138. Description:
  4139. Writes data to the section. Old data in the section will be overwritten.
  4140. Arguments:
  4141. SectionName - section name to write to
  4142. FileName - file name
  4143. pData - data to write
  4144. dwFlags - flags (write section name, generate keys, check duplicate)
  4145. pKeys - the keys to generate or check duplicate
  4146. */
  4147. {
  4148. DWORD rc=ERROR_SUCCESS;
  4149. HANDLE hFile=INVALID_HANDLE_VALUE;
  4150. BOOL bUnicode;
  4151. DWORD dwBytesWritten;
  4152. //
  4153. // try create the new file
  4154. //
  4155. hFile = CreateFile(FileName,
  4156. GENERIC_READ | GENERIC_WRITE,
  4157. 0,
  4158. NULL,
  4159. CREATE_NEW,
  4160. FILE_ATTRIBUTE_NORMAL,
  4161. NULL);
  4162. if (hFile != INVALID_HANDLE_VALUE) {
  4163. //
  4164. // this is a new file, created successfully.
  4165. // now make it UNICODE
  4166. //
  4167. BYTE tmpBuf[3];
  4168. tmpBuf[0] = 0xFF;
  4169. tmpBuf[1] = 0xFE;
  4170. tmpBuf[2] = 0;
  4171. if ( !WriteFile (hFile, (LPCVOID)tmpBuf, 2,
  4172. &dwBytesWritten,
  4173. NULL) )
  4174. {
  4175. CloseHandle (hFile);
  4176. return GetLastError();
  4177. }
  4178. bUnicode = TRUE;
  4179. } else {
  4180. //
  4181. // open the file exclusively
  4182. //
  4183. hFile = CreateFile(FileName,
  4184. GENERIC_READ | GENERIC_WRITE,
  4185. 0,
  4186. NULL,
  4187. OPEN_ALWAYS,
  4188. FILE_ATTRIBUTE_NORMAL,
  4189. NULL);
  4190. if (hFile != INVALID_HANDLE_VALUE) {
  4191. SetFilePointer (hFile, 0, NULL, FILE_BEGIN);
  4192. //
  4193. // check the first byte of the file to see if it's UNICODE
  4194. //
  4195. BYTE tmpBytes[3];
  4196. tmpBytes[0] = 0;
  4197. tmpBytes[1] = 0;
  4198. if ( ReadFile(hFile, (LPVOID)tmpBytes, 2, &dwBytesWritten, NULL ) &&
  4199. dwBytesWritten == 2 ) {
  4200. if ( tmpBytes[0] == 0xFF && tmpBytes[1] == 0xFE ) {
  4201. bUnicode = TRUE;
  4202. } else {
  4203. bUnicode = FALSE;
  4204. }
  4205. } else {
  4206. //
  4207. // if fails to verify the file, assume it's UNICODE
  4208. //
  4209. bUnicode = TRUE;
  4210. }
  4211. }
  4212. }
  4213. PWSTR pKeyStr=NULL;
  4214. BOOL bSkipGenKey = FALSE;
  4215. if (hFile != INVALID_HANDLE_VALUE) {
  4216. SetFilePointer (hFile, 0, NULL, FILE_END);
  4217. if ( dwFlags & SCEP_PROFILE_WRITE_SECTIONNAME ) {
  4218. //
  4219. // save the section name first
  4220. //
  4221. rc = ScepWriteStrings(hFile, bUnicode, L"[", 1, (PWSTR)SectionName, 0, L"]", 1, TRUE);
  4222. }
  4223. if(( 0 == wcscmp(SectionName, szFileSecurity)) ||
  4224. ( 0 == wcscmp(SectionName, szRegistryKeys)) ||
  4225. ( 0 == wcscmp(SectionName, szServiceGeneral)) ){
  4226. bSkipGenKey = TRUE;
  4227. }
  4228. if ( ERROR_SUCCESS == rc ) {
  4229. LPTSTR pTemp=pData;
  4230. LPTSTR pTemp1=pData;
  4231. BOOL bExists, bKeyCopied;
  4232. DWORD rc1;
  4233. DWORD Len;
  4234. //
  4235. // write each string in the MULTI-SZ string separately, with a \r\n
  4236. //
  4237. while ( *pTemp1 ) {
  4238. //
  4239. // count to the \0
  4240. //
  4241. bKeyCopied = FALSE;
  4242. if ( pKeyStr ) {
  4243. LocalFree(pKeyStr);
  4244. pKeyStr = NULL;
  4245. }
  4246. while (*pTemp) {
  4247. if ( pKeys &&
  4248. ( (dwFlags & SCEP_PROFILE_GENERATE_KEYS) ||
  4249. (dwFlags & SCEP_PROFILE_CHECK_DUP) ) &&
  4250. !bKeyCopied &&
  4251. (*pTemp == L'=' || *pTemp == L',') ) {
  4252. if(bSkipGenKey && *pTemp == L'='){
  4253. pTemp1 = ++pTemp;
  4254. continue;
  4255. }
  4256. //
  4257. // there is a key to remember
  4258. //
  4259. Len = (DWORD)(pTemp-pTemp1);
  4260. pKeyStr = (PWSTR)ScepAlloc(LPTR, (Len+1)*sizeof(WCHAR));
  4261. if ( pKeyStr ) {
  4262. wcsncpy(pKeyStr, pTemp1, pTemp-pTemp1);
  4263. bKeyCopied = TRUE;
  4264. } else {
  4265. rc = ERROR_NOT_ENOUGH_MEMORY;
  4266. break;
  4267. }
  4268. }
  4269. pTemp++;
  4270. }
  4271. if ( ERROR_SUCCESS != rc )
  4272. break;
  4273. if ( bKeyCopied ) {
  4274. if ( dwFlags & SCEP_PROFILE_GENERATE_KEYS ) {
  4275. //
  4276. // add it to the splay list
  4277. //
  4278. rc1 = ScepSplayInsert( (PVOID)pKeyStr, pKeys, &bExists );
  4279. } else if ( dwFlags & SCEP_PROFILE_CHECK_DUP ) {
  4280. //
  4281. // check if the key already exists in the splay list
  4282. //
  4283. if ( ScepSplayValueExist( (PVOID)pKeyStr, pKeys) ) {
  4284. //
  4285. // this is a duplicate entry, continue
  4286. //
  4287. pTemp++;
  4288. pTemp1 = pTemp;
  4289. continue;
  4290. }
  4291. }
  4292. }
  4293. Len = (DWORD)(pTemp-pTemp1);
  4294. rc = ScepWriteStrings(hFile,
  4295. bUnicode, // write it in UNICODE or ANSI
  4296. NULL, // no prefix
  4297. 0,
  4298. pTemp1, // the string
  4299. Len,
  4300. NULL, // no suffix
  4301. 0,
  4302. TRUE // add \r\n
  4303. );
  4304. if ( ERROR_SUCCESS != rc )
  4305. break;
  4306. pTemp++;
  4307. pTemp1 = pTemp;
  4308. }
  4309. }
  4310. CloseHandle (hFile);
  4311. } else {
  4312. rc = GetLastError();
  4313. }
  4314. if ( pKeyStr ) {
  4315. LocalFree(pKeyStr);
  4316. }
  4317. return rc;
  4318. }
  4319. DWORD
  4320. ScepWriteStrings(
  4321. IN HANDLE hFile,
  4322. IN BOOL bUnicode,
  4323. IN PWSTR szPrefix OPTIONAL,
  4324. IN DWORD dwPrefixLen,
  4325. IN PWSTR szString,
  4326. IN DWORD dwStrLen,
  4327. IN PWSTR szSuffix OPTIONAL,
  4328. IN DWORD dwSuffixLen,
  4329. IN BOOL bCRLF
  4330. )
  4331. /*
  4332. Description:
  4333. Write data to the file. Data can have prefix and/or suffix, and followed
  4334. by a \r\n optionally.
  4335. Data will be write in UNICODE or ANSI format based on the input paramter
  4336. bUnicode. If ANSI format is desired, the wide chars are converted to
  4337. multi-byte buffers then write to the file.
  4338. Arguments:
  4339. hFile - file handle
  4340. bUnicode - the file format (UNICODE=TRUE or ANSI=FALSE)
  4341. szPrefix - the optional prefix string
  4342. dwPrefixLen - the optional prefix string length (in wchars)
  4343. szString - the string to write
  4344. dwStrLen - the string length
  4345. szSuffix - the optional suffix string
  4346. dwSuffixLen - the optional suffix string length (in wchars)
  4347. bCRLF - if \r\n should be added
  4348. */
  4349. {
  4350. DWORD rc=ERROR_SUCCESS;
  4351. PWSTR pwBuffer=NULL;
  4352. DWORD dwTotal=0;
  4353. PVOID pBuf=NULL;
  4354. PCHAR pStr=NULL;
  4355. DWORD dwBytes=0;
  4356. //
  4357. // validate parameters
  4358. //
  4359. if ( hFile == NULL || szString == NULL ) {
  4360. return ERROR_INVALID_PARAMETER;
  4361. }
  4362. if ( szPrefix && dwPrefixLen == 0 ) {
  4363. dwPrefixLen = wcslen(szPrefix);
  4364. }
  4365. if ( szSuffix && dwSuffixLen == 0 ) {
  4366. dwSuffixLen = wcslen(szSuffix);
  4367. }
  4368. if ( dwStrLen == 0 ) {
  4369. dwStrLen = wcslen(szString);
  4370. }
  4371. //
  4372. // get total length
  4373. //
  4374. dwTotal = dwPrefixLen + dwStrLen + dwSuffixLen;
  4375. if ( dwTotal == 0 && !bCRLF ) {
  4376. //
  4377. // nothing to write
  4378. //
  4379. return ERROR_SUCCESS;
  4380. }
  4381. if ( bCRLF ) {
  4382. //
  4383. // add \r\n
  4384. //
  4385. dwTotal += 2;
  4386. }
  4387. //
  4388. // allocate buffer
  4389. //
  4390. pwBuffer = (PWSTR)LocalAlloc(LPTR, (dwTotal+1)*sizeof(TCHAR));
  4391. if ( pwBuffer == NULL ) {
  4392. return ERROR_NOT_ENOUGH_MEMORY;
  4393. }
  4394. //
  4395. // copy all data to the buffer
  4396. //
  4397. if ( szPrefix ) {
  4398. wcsncpy(pwBuffer, szPrefix, dwPrefixLen);
  4399. }
  4400. wcsncat(pwBuffer, szString, dwStrLen);
  4401. if ( szSuffix ) {
  4402. wcsncat(pwBuffer, szSuffix, dwSuffixLen);
  4403. }
  4404. if ( bCRLF ) {
  4405. wcscat(pwBuffer, c_szCRLF);
  4406. }
  4407. if ( !bUnicode ) {
  4408. //
  4409. // convert WCHAR into ANSI
  4410. //
  4411. dwBytes = WideCharToMultiByte(CP_THREAD_ACP,
  4412. 0,
  4413. pwBuffer,
  4414. dwTotal,
  4415. NULL,
  4416. 0,
  4417. NULL,
  4418. NULL
  4419. );
  4420. if ( dwBytes > 0 ) {
  4421. //
  4422. // allocate buffer
  4423. //
  4424. pStr = (PCHAR)LocalAlloc(LPTR, dwBytes+1);
  4425. if ( pStr == NULL ) {
  4426. rc = ERROR_NOT_ENOUGH_MEMORY;
  4427. } else {
  4428. dwBytes = WideCharToMultiByte(CP_THREAD_ACP,
  4429. 0,
  4430. pwBuffer,
  4431. dwTotal,
  4432. pStr,
  4433. dwBytes,
  4434. NULL,
  4435. NULL
  4436. );
  4437. if ( dwBytes > 0 ) {
  4438. pBuf = (PVOID)pStr;
  4439. } else {
  4440. rc = GetLastError();
  4441. }
  4442. }
  4443. } else {
  4444. rc = GetLastError();
  4445. }
  4446. } else {
  4447. //
  4448. // write in UNICODE, use the existing buffer
  4449. //
  4450. pBuf = (PVOID)pwBuffer;
  4451. dwBytes = dwTotal*sizeof(WCHAR);
  4452. }
  4453. //
  4454. // write to the file
  4455. //
  4456. DWORD dwBytesWritten=0;
  4457. if ( pBuf ) {
  4458. if ( WriteFile (hFile, (LPCVOID)pBuf, dwBytes,
  4459. &dwBytesWritten,
  4460. NULL) ) {
  4461. if ( dwBytesWritten != dwBytes ) {
  4462. //
  4463. // not all data is written
  4464. //
  4465. rc = ERROR_INVALID_DATA;
  4466. }
  4467. } else {
  4468. rc = GetLastError();
  4469. }
  4470. }
  4471. if ( pStr ) {
  4472. LocalFree(pStr);
  4473. }
  4474. //
  4475. // free buffer
  4476. //
  4477. LocalFree(pwBuffer);
  4478. return(rc);
  4479. }