Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3430 lines
94 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1998.
  5. //
  6. // File: util.cpp
  7. //
  8. // Contents: Miscellaneous utility functions
  9. //
  10. // History:
  11. //
  12. //---------------------------------------------------------------------------
  13. #include "stdafx.h"
  14. #include "util.h"
  15. #include "wrapper.h"
  16. #include "defvals.h"
  17. #include "resource.h"
  18. #include <io.h>
  19. #include "snapmgr.h"
  20. extern "C" {
  21. #include "getuser.h"
  22. }
  23. //////////////////////////////////////////////////////////////////////////////////////////
  24. // CWriteHmtlFile body.
  25. //
  26. //+-------------------------------------------------------------------------------------------
  27. // CWriteHtmlFile::CWriteHtmlFile
  28. //
  29. // Initialize the class.
  30. //
  31. //--------------------------------------------------------------------------------------------
  32. CWriteHtmlFile::CWriteHtmlFile()
  33. {
  34. m_hFileHandle = INVALID_HANDLE_VALUE;
  35. m_bErrored = FALSE;
  36. }
  37. //+-------------------------------------------------------------------------------------------
  38. // CWriteHtmlFile::~CWriteHtmlFile
  39. //
  40. // Write the end of the html file and close the handle.
  41. //
  42. //--------------------------------------------------------------------------------------------
  43. CWriteHtmlFile::~CWriteHtmlFile()
  44. {
  45. //
  46. // Close the file handle, but don't delete the HTML file, unless there was an
  47. // error during some write proccess.
  48. //
  49. Close(m_bErrored);
  50. }
  51. //+-------------------------------------------------------------------------------------------
  52. // CWriteHtmlFile::Close
  53. //
  54. // Closes the HTML file handle, if [bDelete] is true then the file is deleted.
  55. //
  56. // Arguments: [bDelete] - Close and delete the file.
  57. //
  58. // Returns: ERROR_SUCCESS;
  59. //--------------------------------------------------------------------------------------------
  60. DWORD
  61. CWriteHtmlFile::Close( BOOL bDelete )
  62. {
  63. if(m_hFileHandle == INVALID_HANDLE_VALUE){
  64. return ERROR_SUCCESS;
  65. }
  66. if(bDelete){
  67. CloseHandle(m_hFileHandle);
  68. DeleteFile(m_strFileName );
  69. } else {
  70. Write( IDS_HTMLERR_END );
  71. CloseHandle( m_hFileHandle );
  72. }
  73. m_hFileHandle = INVALID_HANDLE_VALUE;
  74. return ERROR_SUCCESS;
  75. }
  76. //+-------------------------------------------------------------------------------------------
  77. // CWriteHtmlFile::GetFileName
  78. //
  79. // Copies the file name associated with this class to [pstrFileName].
  80. //
  81. // Arguments: [pstrFileName] - A CString object which will contain the file name
  82. // on return.
  83. //
  84. // Returns: 0 - If Create has not been called, or the HTML file is invalid for
  85. // some reason. This could be caused by a bad write.
  86. // The size in characters of the file name.
  87. //
  88. //--------------------------------------------------------------------------------------------
  89. int CWriteHtmlFile::GetFileName( LPTSTR pszFileName, UINT nSize )
  90. {
  91. if(m_strFileName.IsEmpty() || m_hFileHandle == INVALID_HANDLE_VALUE || m_bErrored){
  92. return 0;
  93. }
  94. if(pszFileName && (int)nSize > m_strFileName.GetLength()){
  95. lstrcpy(pszFileName, m_strFileName);
  96. }
  97. return m_strFileName.GetLength();
  98. }
  99. //+-------------------------------------------------------------------------------------------
  100. // CWriteHtmlFile::Write
  101. //
  102. // Writes a string resource to the html file at the current file position.
  103. //
  104. // Arguments: [uRes] - The String resource to load and write to the html.
  105. //
  106. // Returns: If the string can't be loaded then an error will be returned.
  107. // See CWriteHtmlFile::Write( LPCTSTR ) for other errors.
  108. //--------------------------------------------------------------------------------------------
  109. DWORD
  110. CWriteHtmlFile::Write( UINT uRes )
  111. {
  112. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  113. CString str;
  114. if( !str.LoadString(uRes) ){
  115. return GetLastError();
  116. }
  117. #if defined(UNICODE) || defined(_UNICODE)
  118. if ( uRes == IDS_HTMLERR_HEADER ){
  119. WCHAR wszByteOrderMark[2] = {0xFEFF, 0x0000};
  120. CString strByteOrderMark = wszByteOrderMark;
  121. return Write( strByteOrderMark + str );
  122. } else
  123. #endif
  124. return Write( str );
  125. }
  126. //+-------------------------------------------------------------------------------------------
  127. // CWriteHtmlFile::Write
  128. //
  129. // Writes a string to an html file.
  130. //
  131. // Arguments: [pszString] - The string to write.
  132. //
  133. // Returns: ERROR_NOT_READ - if Create has not been called, or the file could not
  134. // not be created.
  135. // Other errors returned by WriteFile();
  136. //--------------------------------------------------------------------------------------------
  137. DWORD
  138. CWriteHtmlFile::Write(LPCTSTR pszString, ... )
  139. {
  140. if(m_hFileHandle == INVALID_HANDLE_VALUE)
  141. {
  142. return ERROR_NOT_READY;
  143. }
  144. TCHAR szWrite[2048];
  145. va_list marker;
  146. va_start(marker, pszString);
  147. #if defined(UNICODE) || defined(_UNICODE)
  148. vswprintf( szWrite, pszString, marker );
  149. #else
  150. vsprintf( szWrite, pszString, marker );
  151. #endif
  152. va_end(marker);
  153. DWORD dwRight;
  154. if( !WriteFile( m_hFileHandle, szWrite, sizeof(TCHAR) * lstrlen(szWrite), &dwRight, NULL) )
  155. {
  156. //
  157. // Check the error state of the right. Set m_bErrored if there was something wrong
  158. // with the write.
  159. //
  160. dwRight = GetLastError();
  161. if(dwRight != ERROR_SUCCESS)
  162. {
  163. m_bErrored = TRUE;
  164. }
  165. }
  166. else
  167. {
  168. dwRight = ERROR_SUCCESS;
  169. }
  170. return dwRight;
  171. }
  172. DWORD
  173. CWriteHtmlFile::CopyTextFile(
  174. LPCTSTR pszFile,
  175. DWORD dwPosLow,
  176. BOOL bInterpret
  177. )
  178. {
  179. HANDLE handle;
  180. //
  181. // Try to open the file for reading.
  182. //
  183. handle = ExpandAndCreateFile( pszFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL );
  184. if(handle == INVALID_HANDLE_VALUE)
  185. {
  186. return GetLastError();
  187. }
  188. LONG dwPosHigh = 0;
  189. WCHAR szText[256];
  190. char szRead[256];
  191. BOOL IsMulti;
  192. DWORD isUnicode;
  193. //
  194. // Determine if the file is a unicode text file.
  195. //
  196. ReadFile(handle, szText, 100 * sizeof(WCHAR), (DWORD *)&dwPosHigh, NULL );
  197. if(dwPosHigh )
  198. {
  199. isUnicode = IsTextUnicode( szText, dwPosHigh, NULL );
  200. }
  201. //
  202. // Set the pos we want to start from
  203. //
  204. dwPosHigh = 0;
  205. SetFilePointer( handle, dwPosLow, &dwPosHigh, FILE_BEGIN );
  206. if( GetLastError() != ERROR_SUCCESS )
  207. {
  208. return GetLastError();
  209. }
  210. DWORD dwErr = ERROR_SUCCESS;
  211. do
  212. {
  213. start:
  214. //
  215. // Read 254 total bytes from the file. We don't care about the error returned
  216. // by read, as long as read does not set dwPosHigh to something.
  217. //
  218. dwPosHigh = 0;
  219. ReadFile( handle, szRead, 254, (DWORD *)&dwPosHigh, NULL );
  220. //
  221. // If the file is not considered unicode then convert it to a unicode file.
  222. //
  223. ZeroMemory(szText, sizeof(WCHAR) * 256);
  224. if(!isUnicode)
  225. {
  226. dwPosHigh = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szRead, dwPosHigh, szText, 255 );
  227. }
  228. else
  229. {
  230. //
  231. // Just copy the text to the szText buffer and get the number of UNICODE
  232. // characters.
  233. //
  234. memcpy(szText, szRead, dwPosHigh);
  235. dwPosHigh = wcslen(szText);
  236. }
  237. PWSTR pszWrite = szText;
  238. LONG i = 0;
  239. if( bInterpret )
  240. {
  241. //
  242. // Write out line breaks.
  243. //
  244. for(;i < dwPosHigh; i++)
  245. {
  246. //Bug 141526, Yanggao, 3/20/2001
  247. if( L'<' == szText[i] )
  248. {
  249. szText[i] = 0;
  250. Write(pszWrite);
  251. Write(L"&lt");
  252. pszWrite = &(szText[i + 1]);
  253. }
  254. if( L'\r' == szText[i] || L'\n' == szText[i] )
  255. {
  256. if( i + 1 >= dwPosHigh )
  257. {
  258. szText[i] = 0;
  259. Write(pszWrite);
  260. SetFilePointer( handle, -(isUnicode ? 2:1), NULL, FILE_CURRENT);
  261. //
  262. // Read once again.
  263. //
  264. goto start;
  265. }
  266. //
  267. // Check to see if this is a valid line break
  268. //
  269. i++;
  270. if( L'\r' == szText[i] || L'\n' == szText[i] &&
  271. szText[i] != szText[i - 1] )
  272. {
  273. szText[i - 1] = 0;
  274. dwErr = Write( pszWrite );
  275. if( dwErr != ERROR_SUCCESS)
  276. {
  277. break;
  278. }
  279. dwErr = Write( L"<BR>" );
  280. if( dwErr != ERROR_SUCCESS)
  281. {
  282. break;
  283. }
  284. pszWrite = &(szText[i + 1]);
  285. }
  286. else
  287. {
  288. //
  289. // This is not a valid line break, contintue with check with next character
  290. //
  291. i--;
  292. }
  293. }
  294. }
  295. }
  296. //
  297. // Write the rest of the text.
  298. //
  299. if(dwErr == ERROR_SUCCESS)
  300. {
  301. Write( pszWrite );
  302. }
  303. else
  304. {
  305. break;
  306. }
  307. } while( dwPosHigh );
  308. CloseHandle(handle );
  309. return ERROR_SUCCESS;
  310. }
  311. //+-------------------------------------------------------------------------------------------
  312. // CWriteHtmlFile::Create
  313. //
  314. // Creates an html file, and starts the write proccess. If [pszFile] is null, then
  315. // this function creates a temporary file in the GetTempPath() directory with a name
  316. // like SCE###.HTM
  317. //
  318. // Arguments: [pszFile] - Optional parameter for file name
  319. //
  320. // returns: ERROR_SUCCESS - If creating the file was successful.
  321. // If the file exists then ERROR_FILE_EXISTS is returned.
  322. //
  323. //--------------------------------------------------------------------------------------------
  324. DWORD CWriteHtmlFile::Create(LPCTSTR pszFile )
  325. {
  326. if(!pszFile){
  327. //
  328. // Create a temporary file name.
  329. //
  330. DWORD dwSize = GetTempPath(0, NULL);
  331. if(dwSize){
  332. TCHAR szTempFile[512];
  333. //
  334. // Get the temp path.
  335. //
  336. LPTSTR pszPath = (LPTSTR)LocalAlloc( 0, (dwSize + 1) * sizeof(TCHAR));
  337. if(!pszPath){
  338. return ERROR_OUTOFMEMORY;
  339. }
  340. GetTempPath( dwSize + 1, pszPath );
  341. pszPath[dwSize - 1] = 0;
  342. if( GetTempFileName( pszPath, TEXT("SCE"), 0, szTempFile) ){
  343. LocalFree(pszPath);
  344. //
  345. // Create the temporary file.
  346. //
  347. DeleteFile( szTempFile );
  348. int i = lstrlen(szTempFile);
  349. while(i--){
  350. if( szTempFile[i] == L'.' ){
  351. break;
  352. }
  353. }
  354. if(i + 3 >= lstrlen(szTempFile)){
  355. return ERROR_OUTOFMEMORY;
  356. }
  357. //
  358. // We want to create an html file.
  359. //
  360. i++;
  361. szTempFile[i] = L'h';
  362. szTempFile[i + 1] = L't';
  363. szTempFile[i + 2] = L'm';
  364. m_strFileName = szTempFile;
  365. } else {
  366. LocalFree(pszPath);
  367. }
  368. }
  369. } else {
  370. m_strFileName = pszFile;
  371. }
  372. if(m_strFileName.IsEmpty()){
  373. return ERROR_FILE_NOT_FOUND;
  374. }
  375. //
  376. // Open the file for writing
  377. //
  378. m_hFileHandle = ExpandAndCreateFile( m_strFileName,
  379. GENERIC_WRITE,
  380. FILE_SHARE_READ,
  381. NULL,
  382. CREATE_ALWAYS,
  383. FILE_ATTRIBUTE_TEMPORARY,
  384. NULL
  385. );
  386. if(m_hFileHandle == INVALID_HANDLE_VALUE){
  387. return GetLastError();
  388. }
  389. //
  390. // Write HTML header
  391. //
  392. return Write( IDS_HTMLERR_HEADER );
  393. }
  394. //+--------------------------------------------------------------------------
  395. //
  396. // Function: MyRegQueryValue
  397. //
  398. // Synopsis: Reads a registry value into [*Value]
  399. //
  400. //
  401. // Arguments: [hKeyRoot] -
  402. // [SubKey] -
  403. // [ValueName] -
  404. // [Value] -
  405. // [pRegType] -
  406. //
  407. // Modifies: *[Value]
  408. // *[pRegType]
  409. //
  410. // History:
  411. //
  412. //---------------------------------------------------------------------------
  413. DWORD MyRegQueryValue( HKEY hKeyRoot,
  414. LPCTSTR SubKey,
  415. LPCTSTR ValueName,
  416. PVOID *Value,
  417. LPDWORD pRegType )
  418. {
  419. DWORD Rcode;
  420. DWORD dSize=0;
  421. HKEY hKey=NULL;
  422. BOOL FreeMem=FALSE;
  423. if (( Rcode = RegOpenKeyEx(hKeyRoot, SubKey, 0,
  424. KEY_READ, &hKey )) == ERROR_SUCCESS ) {
  425. if (( Rcode = RegQueryValueEx(hKey, ValueName, 0,
  426. pRegType, NULL,
  427. &dSize )) == ERROR_SUCCESS ) {
  428. switch (*pRegType) {
  429. case REG_DWORD:
  430. case REG_DWORD_BIG_ENDIAN:
  431. Rcode = RegQueryValueEx(hKey, ValueName, 0,
  432. pRegType, (BYTE *)(*Value),
  433. &dSize );
  434. if ( Rcode != ERROR_SUCCESS ) {
  435. if ( *Value != NULL )
  436. *((BYTE *)(*Value)) = 0;
  437. }
  438. break;
  439. case REG_SZ:
  440. case REG_EXPAND_SZ:
  441. case REG_MULTI_SZ:
  442. if ( *Value == NULL ) {
  443. *Value = (PVOID)LocalAlloc( LPTR, (dSize+1)*sizeof(TCHAR));
  444. FreeMem = TRUE;
  445. }
  446. if ( *Value == NULL ) {
  447. Rcode = ERROR_NOT_ENOUGH_MEMORY;
  448. } else {
  449. Rcode = RegQueryValueEx(hKey,ValueName,0,
  450. pRegType,(BYTE *)(*Value),
  451. &dSize );
  452. if ( (Rcode != ERROR_SUCCESS) && FreeMem ) {
  453. LocalFree(*Value);
  454. *Value = NULL;
  455. }
  456. }
  457. break;
  458. default:
  459. Rcode = ERROR_INVALID_DATATYPE;
  460. break;
  461. }
  462. }
  463. }
  464. if ( hKey ) {
  465. RegCloseKey( hKey );
  466. }
  467. return(Rcode);
  468. }
  469. //+--------------------------------------------------------------------------
  470. //
  471. // Function: MyRegSetValue
  472. //
  473. // Synopsis: Writes a registry value into [*Value]
  474. //
  475. //
  476. // Arguments: [hKeyRoot] -
  477. // [SubKey] -
  478. // [ValueName] -
  479. // [Value] -
  480. // [cbValue] -
  481. // [pRegType] -
  482. //
  483. //
  484. // History:
  485. //
  486. //---------------------------------------------------------------------------
  487. DWORD MyRegSetValue( HKEY hKeyRoot,
  488. LPCTSTR SubKey,
  489. LPCTSTR ValueName,
  490. const BYTE *Value,
  491. const DWORD cbValue,
  492. const DWORD pRegType )
  493. {
  494. DWORD Rcode=0;
  495. HKEY hKey=NULL;
  496. BOOL FreeMem=FALSE;
  497. if (( Rcode = RegCreateKeyEx(hKeyRoot,
  498. SubKey,
  499. 0,
  500. 0,
  501. 0,
  502. KEY_READ|KEY_SET_VALUE|KEY_CREATE_SUB_KEY,
  503. NULL,
  504. &hKey,
  505. NULL)) == ERROR_SUCCESS ) {
  506. Rcode = RegSetValueEx(hKey,
  507. ValueName,
  508. 0,
  509. pRegType,
  510. Value,
  511. cbValue );
  512. }
  513. if ( hKey ) {
  514. RegCloseKey( hKey );
  515. }
  516. return(Rcode);
  517. }
  518. BOOL FilePathExist(LPCTSTR Name, BOOL IsPath, int Flag)
  519. // Flag = 0 - check file, Flag = 1 - check path
  520. {
  521. // TODO:
  522. struct _wfinddata_t FileInfo;
  523. intptr_t hFile;
  524. BOOL bExist = FALSE;
  525. if ( (IsPath && Flag == 1) ||
  526. (!IsPath && Flag == 0) ) {
  527. // must be exact match
  528. hFile = _wfindfirst((LPTSTR)Name, &FileInfo);
  529. if ( hFile != -1 ) {// find it
  530. if ( FileInfo.attrib & _A_SUBDIR ) {
  531. if ( Flag == 1)
  532. bExist = TRUE;
  533. } else if ( Flag == 0 )
  534. bExist = TRUE;
  535. }
  536. _findclose(hFile);
  537. return bExist;
  538. }
  539. if ( IsPath && Flag == 0 ) {
  540. // invalid parameter
  541. return bExist;
  542. }
  543. // IsPath = FALSE and Flag == 1 (a file name is passed in and search for its path)
  544. CString tmpstr = CString(Name);
  545. int nPos = tmpstr.ReverseFind(L'\\');
  546. if ( nPos > 2 ) {
  547. hFile = _wfindfirst(tmpstr.GetBufferSetLength(nPos), &FileInfo);
  548. if ( hFile != -1 && FileInfo.attrib & _A_SUBDIR )
  549. bExist = TRUE;
  550. _findclose(hFile);
  551. } else if ( nPos == 2 && Name[1] == L':')
  552. bExist = TRUE;
  553. return bExist;
  554. }
  555. //+--------------------------------------------------------------------------
  556. //
  557. // Function: MyFormatResMessage
  558. //
  559. // Synopsis: Creates an error message combining a description of an error
  560. // returned from an SCE function (in rc), the extended description
  561. // of that error (in errBuf), and a custom error message
  562. // (in residMessage)
  563. //
  564. // Arguments: [rc] - The return code of an SCE function
  565. // [residMessage] - the resource id of the base error message
  566. // [errBuf] - Extended error info returned from an SCE function
  567. // [strOut] - A CString to hold the formatted message
  568. //
  569. // Modifies: [strOut]
  570. //
  571. // History:
  572. //
  573. //---------------------------------------------------------------------------
  574. void
  575. MyFormatResMessage(SCESTATUS rc, // in
  576. UINT residMessage, // in
  577. PSCE_ERROR_LOG_INFO errBuf,// in, optional
  578. CString& strOut) // out
  579. {
  580. CString strMessage;
  581. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  582. //
  583. // If the LoadResource fails then strMessage will be empty
  584. // It'll still be better to format the rest of the message than
  585. // to return an empty strOut.
  586. //
  587. strMessage.LoadString(residMessage);
  588. MyFormatMessage(rc,strMessage,errBuf,strOut);
  589. }
  590. //+--------------------------------------------------------------------------
  591. //
  592. // Function: MyFormatMessage
  593. //
  594. // Synopsis: Creates an error message combining a description of an error
  595. // returned from an SCE function (in rc), the extended description
  596. // of that error (in errBuf), and a custom error message (in mes)
  597. //
  598. // Arguments: [rc] - The return code of an SCE function
  599. // [mes] - The base message
  600. // [errBuf] - Extended error info returned from an SCE function
  601. // [strOut] - A CString to hold the formatted message
  602. //
  603. // Modifies: [strOut]
  604. //
  605. // History:
  606. //
  607. //---------------------------------------------------------------------------
  608. void
  609. MyFormatMessage(SCESTATUS rc, // in
  610. LPCTSTR mes, // in
  611. PSCE_ERROR_LOG_INFO errBuf, // in, optional
  612. CString& strOut) // out
  613. {
  614. LPVOID lpMsgBuf=NULL;
  615. if ( rc != SCESTATUS_SUCCESS ) {
  616. //
  617. // translate SCESTATUS into DWORD
  618. //
  619. DWORD win32 = SceStatusToDosError(rc);
  620. //
  621. // get error description of rc
  622. //
  623. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  624. NULL,
  625. win32,
  626. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  627. (LPTSTR)&lpMsgBuf,
  628. 0,
  629. NULL
  630. );
  631. }
  632. if ( lpMsgBuf != NULL ) {
  633. strOut = (LPTSTR)lpMsgBuf;
  634. LocalFree(lpMsgBuf);
  635. lpMsgBuf = NULL;
  636. } else {
  637. strOut.Empty();
  638. }
  639. strOut += mes;
  640. strOut += L"\n";
  641. //
  642. // Loop through the error buffers and append each of them to strOut
  643. //
  644. for (PSCE_ERROR_LOG_INFO pErr = errBuf;
  645. pErr != NULL;
  646. pErr = pErr->next) {
  647. if (NULL == pErr) {
  648. continue;
  649. }
  650. if ( pErr->rc != NO_ERROR) {
  651. FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  652. NULL,
  653. pErr->rc,
  654. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  655. (LPTSTR)&lpMsgBuf,
  656. 0,
  657. NULL
  658. );
  659. if ( lpMsgBuf ) {
  660. strOut += (LPTSTR)lpMsgBuf;
  661. LocalFree(lpMsgBuf);
  662. lpMsgBuf = NULL;
  663. }
  664. }
  665. if (pErr->buffer) {
  666. strOut += pErr->buffer;
  667. strOut += L"\n";
  668. }
  669. }
  670. }
  671. DWORD
  672. FormatDBErrorMessage(
  673. SCESTATUS sceStatus,
  674. LPCTSTR pszDatabase,
  675. CString &strOut
  676. )
  677. {
  678. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  679. UINT uErr = 0;
  680. switch (sceStatus) {
  681. case SCESTATUS_SUCCESS:
  682. return ERROR_INVALID_PARAMETER;
  683. case SCESTATUS_INVALID_DATA:
  684. uErr = IDS_DBERR_INVALID_DATA;
  685. break;
  686. case SCESTATUS_PROFILE_NOT_FOUND:
  687. uErr = IDS_DBERR5_PROFILE_NOT_FOUND;
  688. break;
  689. case SCESTATUS_BAD_FORMAT:
  690. uErr = IDS_DBERR_BAD_FORMAT;
  691. break;
  692. case SCESTATUS_BUFFER_TOO_SMALL:
  693. case SCESTATUS_NOT_ENOUGH_RESOURCE:
  694. uErr = IDS_DBERR_NOT_ENOUGH_RESOURCE;
  695. break;
  696. case SCESTATUS_ACCESS_DENIED:
  697. uErr = IDS_DBERR5_ACCESS_DENIED;
  698. break;
  699. case SCESTATUS_NO_TEMPLATE_GIVEN:
  700. uErr = IDS_DBERR_NO_TEMPLATE_GIVEN;
  701. break;
  702. case SCESTATUS_SPECIAL_ACCOUNT: //Raid #589139,XPSP1 DCR, yanggao, 4/12/2002.
  703. uErr = IDS_DBERR5_ACCESS_DENIED;
  704. break;
  705. default:
  706. uErr = IDS_DBERR_OTHER_ERROR;
  707. }
  708. if ( strOut.LoadString(uErr) ) {
  709. return ERROR_SUCCESS;
  710. }
  711. return ERROR_INVALID_PARAMETER;
  712. }
  713. DWORD SceStatusToDosError(SCESTATUS SceStatus)
  714. {
  715. switch (SceStatus) {
  716. case SCESTATUS_SUCCESS:
  717. return(NO_ERROR);
  718. case SCESTATUS_OTHER_ERROR:
  719. return(ERROR_EXTENDED_ERROR);
  720. case SCESTATUS_INVALID_PARAMETER:
  721. return(ERROR_INVALID_PARAMETER);
  722. case SCESTATUS_RECORD_NOT_FOUND:
  723. return(ERROR_RESOURCE_DATA_NOT_FOUND);
  724. case SCESTATUS_INVALID_DATA:
  725. return(ERROR_INVALID_DATA);
  726. case SCESTATUS_OBJECT_EXIST:
  727. return(ERROR_FILE_EXISTS);
  728. case SCESTATUS_BUFFER_TOO_SMALL:
  729. return(ERROR_INSUFFICIENT_BUFFER);
  730. case SCESTATUS_PROFILE_NOT_FOUND:
  731. return(ERROR_FILE_NOT_FOUND);
  732. case SCESTATUS_BAD_FORMAT:
  733. return(ERROR_BAD_FORMAT);
  734. case SCESTATUS_NOT_ENOUGH_RESOURCE:
  735. return(ERROR_NOT_ENOUGH_MEMORY);
  736. case SCESTATUS_ACCESS_DENIED:
  737. case SCESTATUS_SPECIAL_ACCOUNT: //Raid #589139,XPSP1 DCR, yanggao, 4/12/2002.
  738. return(ERROR_ACCESS_DENIED);
  739. case SCESTATUS_CANT_DELETE:
  740. return(ERROR_CURRENT_DIRECTORY);
  741. case SCESTATUS_PREFIX_OVERFLOW:
  742. return(ERROR_BUFFER_OVERFLOW);
  743. case SCESTATUS_ALREADY_RUNNING:
  744. return(ERROR_SERVICE_ALREADY_RUNNING);
  745. default:
  746. return(ERROR_EXTENDED_ERROR);
  747. }
  748. }
  749. //+--------------------------------------------------------------------------
  750. //
  751. // Function: CreateNewProfile
  752. //
  753. // Synopsis: Create a new tempate with default values in the ProfileName location
  754. //
  755. // Returns: TRUE if a template ends up in the ProfileName file
  756. // FALSE otherwise
  757. //
  758. // History:
  759. //
  760. //---------------------------------------------------------------------------
  761. BOOL CreateNewProfile(CString ProfileName,PSCE_PROFILE_INFO *ppspi)
  762. {
  763. SCESTATUS status;
  764. SCE_PROFILE_INFO *pTemplate;
  765. //
  766. // profile name must end with .inf
  767. //
  768. int nLen = ProfileName.GetLength ();
  769. // start searching at the last 4 position
  770. if ( ProfileName.Find (L".inf", nLen-4) != nLen-4 )
  771. {
  772. return FALSE;
  773. }
  774. //
  775. // if the profile already exists then we don't need to do anything
  776. //
  777. if ( FilePathExist( (LPCTSTR)ProfileName, FALSE, 0) ) {
  778. return TRUE;
  779. }
  780. //
  781. // Make sure the directory for the profile exists
  782. //
  783. status = SceCreateDirectory(ProfileName,FALSE,NULL);
  784. if (SCESTATUS_SUCCESS != status) {
  785. return FALSE;
  786. }
  787. pTemplate = (SCE_PROFILE_INFO*)LocalAlloc(LPTR,sizeof(SCE_PROFILE_INFO));
  788. if (!pTemplate) {
  789. return FALSE;
  790. }
  791. #ifdef FILL_WITH_DEFAULT_VALUES
  792. SCE_PROFILE_INFO *pDefault = GetDefaultTemplate();
  793. //
  794. // Fill with default values
  795. //
  796. pTemplate->Type = SCE_ENGINE_SCP;
  797. #define CD(X) pTemplate->X = pDefault->X;
  798. #else // !FILL_WITH_DEFAULT_VALUES
  799. #define CD(X) pTemplate->X = SCE_NO_VALUE;
  800. #endif // !FILL_WITH_DEFAULT_VALUES
  801. CD(MinimumPasswordAge);
  802. CD(MaximumPasswordAge);
  803. CD(MinimumPasswordLength);
  804. CD(PasswordComplexity);
  805. CD(PasswordHistorySize);
  806. CD(LockoutBadCount);
  807. CD(ResetLockoutCount);
  808. CD(LockoutDuration);
  809. CD(RequireLogonToChangePassword);
  810. CD(ForceLogoffWhenHourExpire);
  811. CD(EnableAdminAccount);
  812. CD(EnableGuestAccount);
  813. // These members aren't declared in NT4
  814. CD(ClearTextPassword);
  815. CD(AuditDSAccess);
  816. CD(AuditAccountLogon);
  817. CD(LSAAnonymousNameLookup);
  818. CD(MaximumLogSize[0]);
  819. CD(MaximumLogSize[1]);
  820. CD(MaximumLogSize[2]);
  821. CD(AuditLogRetentionPeriod[0]);
  822. CD(AuditLogRetentionPeriod[1]);
  823. CD(AuditLogRetentionPeriod[2]);
  824. CD(RetentionDays[0]);
  825. CD(RetentionDays[1]);
  826. CD(RetentionDays[2]);
  827. CD(RestrictGuestAccess[0]);
  828. CD(RestrictGuestAccess[1]);
  829. CD(RestrictGuestAccess[2]);
  830. CD(AuditSystemEvents);
  831. CD(AuditLogonEvents);
  832. CD(AuditObjectAccess);
  833. CD(AuditPrivilegeUse);
  834. CD(AuditPolicyChange);
  835. CD(AuditAccountManage);
  836. CD(AuditProcessTracking);
  837. #ifdef FILL_WITH_DEFAULT_VALUES
  838. //
  839. // These two are strings rather than DWORDs
  840. //
  841. if (pDefault->NewAdministratorName) {
  842. pTemplate->NewAdministratorName =
  843. (LPTSTR) LocalAlloc(LPTR,(lstrlen(pDefault->NewAdministratorName)+1)*sizeof(TCHAR));
  844. if (pTemplate->NewAdministratorName) {
  845. lstrcpy(pTemplate->NewAdministratorName,
  846. pDefault->NewAdministratorName);
  847. }
  848. }
  849. if (pDefault->NewGuestName) {
  850. pTemplate->NewGuestName =
  851. (LPTSTR) LocalAlloc(LPTR,(lstrlen(pDefault->NewGuestName)+1)*sizeof(TCHAR));
  852. if (pTemplate->NewGuestName) {
  853. lstrcpy(pTemplate->NewGuestName,
  854. pDefault->NewGuestName);
  855. }
  856. }
  857. #endif // FILL_WITH_DEFAULT_VALUES
  858. #undef CD
  859. status = SceWriteSecurityProfileInfo(ProfileName,
  860. AREA_ALL,
  861. pTemplate,
  862. NULL);
  863. if (ppspi) {
  864. *ppspi = pTemplate;
  865. } else {
  866. SceFreeProfileMemory(pTemplate);
  867. }
  868. return (SCESTATUS_SUCCESS == status);
  869. }
  870. BOOL
  871. VerifyKerberosInfo(PSCE_PROFILE_INFO pspi) {
  872. if (pspi->pKerberosInfo) {
  873. return TRUE;
  874. }
  875. pspi->pKerberosInfo = (PSCE_KERBEROS_TICKET_INFO)
  876. LocalAlloc(LPTR,sizeof(SCE_KERBEROS_TICKET_INFO));
  877. if (pspi->pKerberosInfo) {
  878. pspi->pKerberosInfo->MaxTicketAge = SCE_NO_VALUE;
  879. pspi->pKerberosInfo->MaxRenewAge = SCE_NO_VALUE;
  880. pspi->pKerberosInfo->MaxServiceAge = SCE_NO_VALUE;
  881. pspi->pKerberosInfo->MaxClockSkew = SCE_NO_VALUE;
  882. pspi->pKerberosInfo->TicketValidateClient = SCE_NO_VALUE;
  883. return TRUE;
  884. }
  885. return FALSE;
  886. }
  887. BOOL
  888. SetProfileInfo(LONG_PTR dwItem,LONG_PTR dwNew,PEDITTEMPLATE pEdit) {
  889. if (!pEdit) {
  890. return FALSE;
  891. }
  892. pEdit->SetDirty(AREA_SECURITY_POLICY);
  893. switch (dwItem) {
  894. case IDS_MAX_PAS_AGE:
  895. pEdit->pTemplate->MaximumPasswordAge = (DWORD)PtrToUlong((PVOID)dwNew);
  896. break;
  897. case IDS_MIN_PAS_AGE:
  898. pEdit->pTemplate->MinimumPasswordAge = (DWORD)PtrToUlong((PVOID)dwNew);
  899. break;
  900. case IDS_MIN_PAS_LEN:
  901. pEdit->pTemplate->MinimumPasswordLength = (DWORD)PtrToUlong((PVOID)dwNew);
  902. break;
  903. case IDS_PAS_UNIQUENESS:
  904. pEdit->pTemplate->PasswordHistorySize = (DWORD)PtrToUlong((PVOID)dwNew);
  905. break;
  906. case IDS_PAS_COMPLEX:
  907. pEdit->pTemplate->PasswordComplexity = (DWORD)PtrToUlong((PVOID)dwNew);
  908. break;
  909. case IDS_REQ_LOGON:
  910. pEdit->pTemplate->RequireLogonToChangePassword = (DWORD)PtrToUlong((PVOID)dwNew);
  911. break;
  912. case IDS_LOCK_COUNT:
  913. pEdit->pTemplate->LockoutBadCount = (DWORD)PtrToUlong((PVOID)dwNew);
  914. break;
  915. case IDS_LOCK_RESET_COUNT:
  916. pEdit->pTemplate->ResetLockoutCount = (DWORD)PtrToUlong((PVOID)dwNew);
  917. break;
  918. case IDS_LOCK_DURATION:
  919. pEdit->pTemplate->LockoutDuration = (DWORD)PtrToUlong((PVOID)dwNew);
  920. break;
  921. case IDS_FORCE_LOGOFF:
  922. pEdit->pTemplate->ForceLogoffWhenHourExpire = (DWORD)PtrToUlong((PVOID)dwNew);
  923. break;
  924. case IDS_ENABLE_ADMIN:
  925. pEdit->pTemplate->EnableAdminAccount = (DWORD)PtrToUlong((PVOID)dwNew);
  926. break;
  927. case IDS_ENABLE_GUEST:
  928. pEdit->pTemplate->EnableGuestAccount = (DWORD)PtrToUlong((PVOID)dwNew);
  929. break;
  930. case IDS_LSA_ANON_LOOKUP:
  931. pEdit->pTemplate->LSAAnonymousNameLookup = (DWORD)PtrToUlong((PVOID)dwNew);
  932. break;
  933. case IDS_NEW_ADMIN:
  934. if (pEdit->pTemplate->NewAdministratorName) {
  935. LocalFree(pEdit->pTemplate->NewAdministratorName);
  936. }
  937. if (dwNew && (dwNew != (LONG_PTR)ULongToPtr(SCE_NO_VALUE))) {
  938. pEdit->pTemplate->NewAdministratorName = (PWSTR)LocalAlloc(LPTR,(lstrlen((PWSTR)dwNew)+1)*sizeof(WCHAR));
  939. if (pEdit->pTemplate->NewAdministratorName) {
  940. lstrcpy(pEdit->pTemplate->NewAdministratorName,(PWSTR)dwNew);
  941. }
  942. } else {
  943. pEdit->pTemplate->NewAdministratorName = NULL;
  944. }
  945. break;
  946. case IDS_NEW_GUEST:
  947. if (pEdit->pTemplate->NewGuestName) {
  948. LocalFree(pEdit->pTemplate->NewGuestName);
  949. }
  950. if (dwNew && (dwNew != (LONG_PTR)ULongToPtr(SCE_NO_VALUE))) {
  951. pEdit->pTemplate->NewGuestName = (PWSTR)LocalAlloc(LPTR,(lstrlen((PWSTR)dwNew)+1)*sizeof(WCHAR));
  952. if (pEdit->pTemplate->NewGuestName) {
  953. lstrcpy(pEdit->pTemplate->NewGuestName,(PWSTR)dwNew);
  954. }
  955. } else {
  956. pEdit->pTemplate->NewGuestName = NULL;
  957. }
  958. break;
  959. case IDS_SYS_LOG_MAX:
  960. pEdit->pTemplate->MaximumLogSize[EVENT_TYPE_SYSTEM] = (DWORD)PtrToUlong((PVOID)dwNew);
  961. break;
  962. case IDS_SYS_LOG_RET:
  963. pEdit->pTemplate->AuditLogRetentionPeriod[EVENT_TYPE_SYSTEM] = (DWORD)PtrToUlong((PVOID)dwNew);
  964. break;
  965. case IDS_SYS_LOG_DAYS:
  966. pEdit->pTemplate->RetentionDays[EVENT_TYPE_SYSTEM] = (DWORD)PtrToUlong((PVOID)dwNew);
  967. break;
  968. case IDS_SEC_LOG_MAX:
  969. pEdit->pTemplate->MaximumLogSize[EVENT_TYPE_SECURITY] = (DWORD)PtrToUlong((PVOID)dwNew);
  970. break;
  971. case IDS_SEC_LOG_RET:
  972. pEdit->pTemplate->AuditLogRetentionPeriod[EVENT_TYPE_SECURITY] = (DWORD)PtrToUlong((PVOID)dwNew);
  973. break;
  974. case IDS_SEC_LOG_DAYS:
  975. pEdit->pTemplate->RetentionDays[EVENT_TYPE_SECURITY] = (DWORD)PtrToUlong((PVOID)dwNew);
  976. break;
  977. case IDS_APP_LOG_MAX:
  978. pEdit->pTemplate->MaximumLogSize[EVENT_TYPE_APP] = (DWORD)PtrToUlong((PVOID)dwNew);
  979. break;
  980. case IDS_APP_LOG_RET:
  981. pEdit->pTemplate->AuditLogRetentionPeriod[EVENT_TYPE_APP] = (DWORD)PtrToUlong((PVOID)dwNew);
  982. break;
  983. case IDS_APP_LOG_DAYS:
  984. pEdit->pTemplate->RetentionDays[EVENT_TYPE_APP] = (DWORD)PtrToUlong((PVOID)dwNew);
  985. break;
  986. case IDS_SYSTEM_EVENT:
  987. pEdit->pTemplate->AuditSystemEvents = (DWORD)PtrToUlong((PVOID)dwNew);
  988. break;
  989. case IDS_LOGON_EVENT:
  990. pEdit->pTemplate->AuditLogonEvents = (DWORD)PtrToUlong((PVOID)dwNew);
  991. break;
  992. case IDS_OBJECT_ACCESS:
  993. pEdit->pTemplate->AuditObjectAccess = (DWORD)PtrToUlong((PVOID)dwNew);
  994. break;
  995. case IDS_PRIVILEGE_USE:
  996. pEdit->pTemplate->AuditPrivilegeUse = (DWORD)PtrToUlong((PVOID)dwNew);
  997. break;
  998. case IDS_POLICY_CHANGE:
  999. pEdit->pTemplate->AuditPolicyChange = (DWORD)PtrToUlong((PVOID)dwNew);
  1000. break;
  1001. case IDS_ACCOUNT_MANAGE:
  1002. pEdit->pTemplate->AuditAccountManage = (DWORD)PtrToUlong((PVOID)dwNew);
  1003. break;
  1004. case IDS_PROCESS_TRACK:
  1005. pEdit->pTemplate->AuditProcessTracking = (DWORD)PtrToUlong((PVOID)dwNew);
  1006. break;
  1007. case IDS_DIRECTORY_ACCESS:
  1008. pEdit->pTemplate->AuditDSAccess = (DWORD)PtrToUlong((PVOID)dwNew);
  1009. break;
  1010. case IDS_ACCOUNT_LOGON:
  1011. pEdit->pTemplate->AuditAccountLogon = (DWORD)PtrToUlong((PVOID)dwNew);
  1012. break;
  1013. case IDS_SYS_LOG_GUEST:
  1014. pEdit->pTemplate->RestrictGuestAccess[EVENT_TYPE_SYSTEM] = (DWORD)PtrToUlong((PVOID)dwNew);
  1015. break;
  1016. case IDS_SEC_LOG_GUEST:
  1017. pEdit->pTemplate->RestrictGuestAccess[EVENT_TYPE_SECURITY] = (DWORD)PtrToUlong((PVOID)dwNew);
  1018. break;
  1019. case IDS_APP_LOG_GUEST:
  1020. pEdit->pTemplate->RestrictGuestAccess[EVENT_TYPE_APP] = (DWORD)PtrToUlong((PVOID)dwNew);
  1021. break;
  1022. case IDS_CLEAR_PASSWORD:
  1023. pEdit->pTemplate->ClearTextPassword = (DWORD)PtrToUlong((PVOID)dwNew);
  1024. break;
  1025. case IDS_KERBEROS_MAX_SERVICE:
  1026. if (VerifyKerberosInfo(pEdit->pTemplate)) {
  1027. pEdit->pTemplate->pKerberosInfo->MaxServiceAge = (DWORD)PtrToUlong((PVOID)dwNew);
  1028. }
  1029. break;
  1030. case IDS_KERBEROS_MAX_CLOCK:
  1031. if (VerifyKerberosInfo( pEdit->pTemplate)) {
  1032. pEdit->pTemplate->pKerberosInfo->MaxClockSkew = (DWORD)PtrToUlong((PVOID)dwNew);
  1033. }
  1034. break;
  1035. case IDS_KERBEROS_VALIDATE_CLIENT:
  1036. if (VerifyKerberosInfo( pEdit->pTemplate)) {
  1037. pEdit->pTemplate->pKerberosInfo->TicketValidateClient = (DWORD)PtrToUlong((PVOID)dwNew);
  1038. }
  1039. break;
  1040. case IDS_KERBEROS_MAX_AGE:
  1041. if (VerifyKerberosInfo( pEdit->pTemplate)) {
  1042. pEdit->pTemplate->pKerberosInfo->MaxTicketAge = (DWORD)PtrToUlong((PVOID)dwNew);
  1043. }
  1044. break;
  1045. case IDS_KERBEROS_RENEWAL:
  1046. if (VerifyKerberosInfo( pEdit->pTemplate)) {
  1047. pEdit->pTemplate->pKerberosInfo->MaxRenewAge = (DWORD)PtrToUlong((PVOID)dwNew);
  1048. }
  1049. break;
  1050. default:
  1051. return FALSE;
  1052. }
  1053. return TRUE;
  1054. }
  1055. //
  1056. // FUNCTION: ErrorHandlerEx(WORD, LPSTR)
  1057. //
  1058. // PURPOSE: Calls GetLastError() and uses FormatMessage() to display the
  1059. // textual information of the error code along with the file
  1060. // and line number.
  1061. //
  1062. // PARAMETERS:
  1063. // wLine - line number where the error occured
  1064. // lpszFile - file where the error occured
  1065. //
  1066. // RETURN VALUE:
  1067. // none
  1068. //
  1069. // COMMENTS:
  1070. // This function has a macro ErrorHandler() which handles filling in
  1071. // the line number and file name where the error occured. ErrorHandler()
  1072. // is always used instead of calling this function directly.
  1073. //
  1074. void ErrorHandlerEx( WORD wLine, LPTSTR lpszFile )
  1075. {
  1076. LPVOID lpvMessage;
  1077. DWORD dwError;
  1078. TCHAR szBuffer[256];
  1079. // The the text of the error message
  1080. dwError = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  1081. FORMAT_MESSAGE_FROM_SYSTEM,
  1082. NULL,
  1083. GetLastError(),
  1084. MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
  1085. (LPTSTR)&lpvMessage,
  1086. 0,
  1087. NULL);
  1088. // Check to see if an error occured calling FormatMessage()
  1089. if (0 == dwError) {
  1090. wsprintf(szBuffer, TEXT("An error occured calling FormatMessage().")
  1091. TEXT("Error Code %d"), GetLastError());
  1092. MessageBox(NULL, szBuffer, TEXT("Security Configuration Editor"), MB_ICONSTOP |
  1093. MB_ICONEXCLAMATION);
  1094. return;
  1095. }
  1096. // Display the error message
  1097. wsprintf(szBuffer, TEXT("Generic, Line=%d, File=%s"), wLine, lpszFile);
  1098. MessageBox(NULL, (LPTSTR)lpvMessage, szBuffer, MB_ICONEXCLAMATION | MB_OK);
  1099. return;
  1100. }
  1101. BOOL
  1102. GetSceStatusString(SCESTATUS status, CString *strStatus) {
  1103. AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
  1104. if (!strStatus || (status > SCESTATUS_SERVICE_NOT_SUPPORT)) {
  1105. return false;
  1106. }
  1107. return strStatus->LoadString(status + IDS_SCESTATUS_SUCCESS);
  1108. }
  1109. //+---------------------------------------------------------------------------------------------
  1110. // EnumLangProc
  1111. //
  1112. // Creates the lanuage ID for the resource attached to the DLL. The function only enumerates
  1113. // on lanuage.
  1114. //
  1115. // Arguments: - See help on EnumResLangProc in the SDK Doc.
  1116. //
  1117. // Returns: - Returns FALSE because we only want the very first lanuage enumerated.
  1118. //
  1119. //+---------------------------------------------------------------------------------------------
  1120. BOOL CALLBACK EnumLangProc(
  1121. HMODULE hMod,
  1122. LPCTSTR pszType,
  1123. LPCTSTR pszName,
  1124. WORD wIDLanguage,
  1125. LONG_PTR lParam
  1126. )
  1127. {
  1128. //
  1129. // We only want the very first enumerated type, so create the language ID
  1130. // and exit this enumeration.
  1131. //
  1132. *((DWORD *)lParam) = wIDLanguage;
  1133. return FALSE;
  1134. }
  1135. bool
  1136. GetRightDisplayName(LPCTSTR szSystemName, LPCTSTR szName, LPTSTR szDisp, LPDWORD lpcbDisp) {
  1137. LPTSTR szLCName;
  1138. DWORD dwLang;
  1139. int i;
  1140. if (!szDisp || !szName) {
  1141. return false;
  1142. }
  1143. //
  1144. // Enumerate our resource to find out what language the resource is in.
  1145. //
  1146. DWORD dwDefaultLang;
  1147. if( !EnumResourceLanguages(
  1148. (HMODULE)AfxGetInstanceHandle(),
  1149. MAKEINTRESOURCE(RT_VERSION),
  1150. MAKEINTRESOURCE(VS_VERSION_INFO),
  1151. &EnumLangProc,
  1152. (LPARAM)&dwDefaultLang
  1153. ) ){
  1154. if(GetLastError() != ERROR_SUCCESS){
  1155. //
  1156. // Default to system language if enumerating the version language
  1157. // was unsuccessful.
  1158. dwDefaultLang = MAKELANGID(LANG_NEUTRAL, 0);
  1159. }
  1160. }
  1161. dwDefaultLang = MAKELANGID( dwDefaultLang, SUBLANG_DEFAULT);
  1162. LCID langID = MAKELCID( dwDefaultLang, SORT_DEFAULT);
  1163. LCID langDefault = GetThreadLocale();
  1164. SetThreadLocale( langID );
  1165. *lpcbDisp = dwDefaultLang;
  1166. DWORD cBufSize=*lpcbDisp;
  1167. BOOL bFound;
  1168. bFound = LookupPrivilegeDisplayName(szSystemName,szName,szDisp,lpcbDisp,&dwLang);
  1169. if ( bFound && dwDefaultLang != dwLang && szSystemName ) {
  1170. // not the language I am looking for
  1171. // search on local system
  1172. *lpcbDisp = cBufSize;
  1173. bFound = LookupPrivilegeDisplayName(NULL,szName,szDisp,lpcbDisp,&dwLang);
  1174. }
  1175. SetThreadLocale(langDefault);
  1176. if (!bFound) {
  1177. if (0 == lstrcmpi(szName,L"senetworklogonright")) {
  1178. LoadString(AfxGetInstanceHandle(),IDS_SE_NETWORK_LOGON_RIGHT,szDisp,*lpcbDisp);
  1179. } else if (0 == lstrcmpi(szName,L"seinteractivelogonright")) {
  1180. LoadString(AfxGetInstanceHandle(),IDS_SE_INTERACTIVE_LOGON_RIGHT,szDisp,*lpcbDisp);
  1181. } else if (0 == lstrcmpi(szName,L"sebatchlogonright")) {
  1182. LoadString(AfxGetInstanceHandle(),IDS_SE_BATCH_LOGON_RIGHT,szDisp,*lpcbDisp);
  1183. } else if (0 == lstrcmpi(szName,L"seservicelogonright")) {
  1184. LoadString(AfxGetInstanceHandle(),IDS_SE_SERVICE_LOGON_RIGHT,szDisp,*lpcbDisp);
  1185. } else if (0 == lstrcmpi(szName,L"sedenyinteractivelogonright")) {
  1186. LoadString(AfxGetInstanceHandle(),IDS_DENY_LOGON_LOCALLY,szDisp,*lpcbDisp);
  1187. } else if (0 == lstrcmpi(szName,L"sedenynetworklogonright")) {
  1188. LoadString(AfxGetInstanceHandle(),IDS_DENY_LOGON_NETWORK,szDisp,*lpcbDisp);
  1189. } else if (0 == lstrcmpi(szName,L"sedenyservicelogonright")) {
  1190. LoadString(AfxGetInstanceHandle(),IDS_DENY_LOGON_SERVICE,szDisp,*lpcbDisp);
  1191. } else if (0 == lstrcmpi(szName,L"sedenybatchlogonright")) {
  1192. LoadString(AfxGetInstanceHandle(),IDS_DENY_LOGON_BATCH,szDisp,*lpcbDisp);
  1193. } else if (0 == lstrcmpi(szName,L"sedenyremoteinteractivelogonright")) {
  1194. LoadString(AfxGetInstanceHandle(),IDS_DENY_REMOTE_INTERACTIVE_LOGON,szDisp,*lpcbDisp);
  1195. } else if (0 == lstrcmpi(szName,L"seremoteinteractivelogonright")) {
  1196. LoadString(AfxGetInstanceHandle(),IDS_REMOTE_INTERACTIVE_LOGON,szDisp,*lpcbDisp);
  1197. } else {
  1198. lstrcpyn(szDisp,szName,*lpcbDisp);
  1199. }
  1200. }
  1201. return true;
  1202. }
  1203. #define DPI(X) {str.Format(L"%S: %d\n",#X,pInfo->X);OutputDebugString(str);}
  1204. void DumpProfileInfo(PSCE_PROFILE_INFO pInfo) {
  1205. CString str;
  1206. PSCE_PRIVILEGE_ASSIGNMENT ppa;
  1207. PSCE_NAME_LIST pName;
  1208. PSCE_GROUP_MEMBERSHIP pgm;
  1209. if (!pInfo) {
  1210. return;
  1211. }
  1212. DPI(MinimumPasswordAge);
  1213. DPI(MaximumPasswordAge);
  1214. DPI(MinimumPasswordLength);
  1215. DPI(PasswordComplexity);
  1216. DPI(PasswordHistorySize);
  1217. DPI(LockoutBadCount);
  1218. DPI(ResetLockoutCount);
  1219. DPI(LockoutDuration);
  1220. DPI(RequireLogonToChangePassword);
  1221. DPI(ForceLogoffWhenHourExpire);
  1222. DPI(EnableAdminAccount);
  1223. DPI(EnableGuestAccount);
  1224. DPI(ClearTextPassword);
  1225. DPI(AuditDSAccess);
  1226. DPI(AuditAccountLogon);
  1227. DPI(LSAAnonymousNameLookup);
  1228. // DPI(EventAuditingOnOff);
  1229. DPI(AuditSystemEvents);
  1230. DPI(AuditLogonEvents);
  1231. DPI(AuditObjectAccess);
  1232. DPI(AuditPrivilegeUse);
  1233. DPI(AuditPolicyChange);
  1234. DPI(AuditAccountManage);
  1235. DPI(AuditProcessTracking);
  1236. if (pInfo->NewGuestName) {
  1237. OutputDebugString(L"NewGuestName: ");
  1238. if ((DWORD_PTR)ULongToPtr(SCE_NO_VALUE) == (DWORD_PTR)pInfo->NewGuestName) {
  1239. OutputDebugString(L"[[undefined]]");
  1240. } else {
  1241. OutputDebugString(pInfo->NewGuestName);
  1242. }
  1243. OutputDebugString(L"\n");
  1244. } else {
  1245. OutputDebugString(L"NewGuestName: [[absent]]\n");
  1246. }
  1247. if (pInfo->NewAdministratorName) {
  1248. OutputDebugString(L"NewAdministratorName: ");
  1249. if ((DWORD_PTR)ULongToPtr(SCE_NO_VALUE) == (DWORD_PTR)pInfo->NewAdministratorName) {
  1250. OutputDebugString(L"[[undefined]]");
  1251. } else {
  1252. OutputDebugString(pInfo->NewAdministratorName);
  1253. }
  1254. OutputDebugString(L"\n");
  1255. } else {
  1256. OutputDebugString(L"NewGuestName: [[absent]]\n");
  1257. }
  1258. OutputDebugString(L"\n");
  1259. switch(pInfo->Type) {
  1260. case SCE_ENGINE_SCP:
  1261. ppa = pInfo->OtherInfo.scp.u.pInfPrivilegeAssignedTo;
  1262. break;
  1263. case SCE_ENGINE_SAP:
  1264. ppa = pInfo->OtherInfo.sap.pPrivilegeAssignedTo;
  1265. break;
  1266. case SCE_ENGINE_SMP:
  1267. ppa = pInfo->OtherInfo.smp.pPrivilegeAssignedTo;
  1268. break;
  1269. case SCE_ENGINE_SYSTEM:
  1270. ppa = NULL;
  1271. break;
  1272. default:
  1273. OutputDebugString(L"!!!Unknown Template Type!!!\n");
  1274. ppa = NULL;
  1275. break;
  1276. }
  1277. while(ppa) {
  1278. OutputDebugString(ppa->Name);
  1279. OutputDebugString(L":");
  1280. pName = ppa->AssignedTo;
  1281. while(pName) {
  1282. OutputDebugString(pName->Name);
  1283. OutputDebugString(L",");
  1284. pName = pName->Next;
  1285. }
  1286. ppa = ppa->Next;
  1287. OutputDebugString(L"\n");
  1288. }
  1289. OutputDebugString(L"\n");
  1290. PSCE_REGISTRY_VALUE_INFO aRegValues;
  1291. for(DWORD i = 0; i< pInfo->RegValueCount;i++) {
  1292. OutputDebugString(pInfo->aRegValues[i].FullValueName);
  1293. OutputDebugString(L":");
  1294. switch(pInfo->aRegValues[i].ValueType) {
  1295. case SCE_REG_DISPLAY_STRING:
  1296. OutputDebugString(pInfo->aRegValues[i].Value);
  1297. break;
  1298. default:
  1299. str.Format(L"%d",(ULONG_PTR)pInfo->aRegValues[i].Value);
  1300. OutputDebugString(str);
  1301. }
  1302. OutputDebugString(L"\n");
  1303. }
  1304. OutputDebugString(L"\n");
  1305. pgm = pInfo->pGroupMembership;
  1306. while(pgm) {
  1307. OutputDebugString(L"\nGROUP: ");
  1308. OutputDebugString(pgm->GroupName);
  1309. OutputDebugString(L"\nMembers: ");
  1310. pName = pgm->pMembers;
  1311. while(pName) {
  1312. OutputDebugString(pName->Name);
  1313. OutputDebugString(L",");
  1314. pName = pName->Next;
  1315. }
  1316. OutputDebugString(L"\nMember Of: ");
  1317. pName = pgm->pMemberOf;
  1318. while(pName) {
  1319. OutputDebugString(pName->Name);
  1320. OutputDebugString(L",");
  1321. pName = pName->Next;
  1322. }
  1323. OutputDebugString(L"\n");
  1324. pgm = pgm->Next;
  1325. }
  1326. OutputDebugString(L"\nGROUP: ");
  1327. }
  1328. HRESULT MyMakeSelfRelativeSD(
  1329. PSECURITY_DESCRIPTOR psdOriginal,
  1330. PSECURITY_DESCRIPTOR* ppsdNew )
  1331. {
  1332. ASSERT( NULL != psdOriginal );
  1333. if ( NULL == psdOriginal || NULL == ppsdNew ) {
  1334. return E_INVALIDARG;
  1335. }
  1336. // we have to find out whether the original is already self-relative
  1337. SECURITY_DESCRIPTOR_CONTROL sdc = 0;
  1338. DWORD dwRevision = 0;
  1339. if ( !GetSecurityDescriptorControl( psdOriginal, &sdc, &dwRevision ) ) {
  1340. ASSERT( FALSE );
  1341. DWORD err = GetLastError();
  1342. return HRESULT_FROM_WIN32( err );
  1343. }
  1344. DWORD cb = GetSecurityDescriptorLength( psdOriginal ) + 20;
  1345. PSECURITY_DESCRIPTOR psdSelfRelativeCopy = (PSECURITY_DESCRIPTOR)LocalAlloc( LMEM_ZEROINIT, cb );
  1346. if (NULL == psdSelfRelativeCopy) {
  1347. return E_UNEXPECTED; // just in case the exception is ignored
  1348. }
  1349. if ( sdc & SE_SELF_RELATIVE )
  1350. // the original is in self-relative format, just byte-copy it
  1351. {
  1352. memcpy( psdSelfRelativeCopy, psdOriginal, cb - 20 );
  1353. } else if ( !MakeSelfRelativeSD( psdOriginal, psdSelfRelativeCopy, &cb ) )
  1354. // the original is in absolute format, convert-copy it
  1355. {
  1356. ASSERT( FALSE );
  1357. VERIFY( NULL == LocalFree( psdSelfRelativeCopy ) );
  1358. DWORD err = GetLastError();
  1359. return HRESULT_FROM_WIN32( err );
  1360. }
  1361. *ppsdNew = psdSelfRelativeCopy;
  1362. return S_OK;
  1363. }
  1364. PSCE_NAME_STATUS_LIST
  1365. MergeNameStatusList(PSCE_NAME_LIST pTemplate, PSCE_NAME_LIST pInspect)
  1366. {
  1367. PSCE_NAME_LIST pTemp1;
  1368. PSCE_NAME_STATUS_LIST plMerge=NULL, pTemp2;
  1369. SCESTATUS rc=SCESTATUS_SUCCESS;
  1370. for ( pTemp1=pTemplate; pTemp1; pTemp1=pTemp1->Next ) {
  1371. rc = SceAddToNameStatusList(&plMerge, pTemp1->Name, 0, MERGED_TEMPLATE );
  1372. if ( SCESTATUS_SUCCESS != rc )
  1373. break;
  1374. }
  1375. if ( SCESTATUS_SUCCESS == rc ) {
  1376. for ( pTemp1=pInspect; pTemp1; pTemp1=pTemp1->Next ) {
  1377. for ( pTemp2=plMerge; pTemp2 != NULL ; pTemp2=pTemp2->Next ) {
  1378. if ( pTemp2->Status & MERGED_INSPECT ) {
  1379. // this one is processed
  1380. continue;
  1381. } else if ( _wcsicmp(pTemp1->Name, pTemp2->Name) == 0 ) {
  1382. // find a match
  1383. pTemp2->Status = MERGED_TEMPLATE | MERGED_INSPECT;
  1384. break;
  1385. }
  1386. }
  1387. if ( !pTemp2 ) {
  1388. // did not find the match, add this one in
  1389. rc = SceAddToNameStatusList(&plMerge, pTemp1->Name, 0, MERGED_INSPECT );
  1390. if ( SCESTATUS_SUCCESS != rc )
  1391. break;
  1392. }
  1393. }
  1394. }
  1395. if ( SCESTATUS_SUCCESS == rc ) {
  1396. return plMerge;
  1397. } else {
  1398. SceFreeMemory(plMerge, SCE_STRUCT_NAME_STATUS_LIST);
  1399. return NULL;
  1400. }
  1401. }
  1402. SCESTATUS
  1403. ConvertMultiSzToDelim(
  1404. IN PWSTR pValue,
  1405. IN DWORD Len,
  1406. IN WCHAR DelimFrom,
  1407. IN WCHAR Delim
  1408. )
  1409. /*
  1410. Convert the multi-sz delimiter \0 to space
  1411. */
  1412. {
  1413. DWORD i;
  1414. for ( i=0; i<Len && pValue; i++) {
  1415. // if ( *(pValue+i) == L'\0' && *(pValue+i+1) != L'\0') {
  1416. if ( *(pValue+i) == DelimFrom && i+1 < Len &&
  1417. *(pValue+i+1) != L'\0' ) {
  1418. //
  1419. // a NULL delimiter is encounted and it's not the end (double NULL)
  1420. //
  1421. *(pValue+i) = Delim;
  1422. }
  1423. }
  1424. return(SCESTATUS_SUCCESS);
  1425. }
  1426. DWORD
  1427. SceRegEnumAllValues(
  1428. IN OUT PDWORD pCount,
  1429. IN OUT PSCE_REGISTRY_VALUE_INFO *paRegValues
  1430. )
  1431. /*
  1432. */
  1433. {
  1434. DWORD Win32Rc;
  1435. HKEY hKey=NULL;
  1436. PSCE_NAME_STATUS_LIST pnsList=NULL;
  1437. DWORD nAdded=0;
  1438. Win32Rc = RegOpenKeyEx(
  1439. HKEY_LOCAL_MACHINE,
  1440. SCE_ROOT_REGVALUE_PATH,
  1441. 0,
  1442. KEY_READ,
  1443. &hKey
  1444. );
  1445. DWORD cSubKeys = 0;
  1446. DWORD nMaxLen;
  1447. if ( Win32Rc == ERROR_SUCCESS ) {
  1448. //
  1449. // enumerate all subkeys of the key
  1450. //
  1451. Win32Rc = RegQueryInfoKey (
  1452. hKey,
  1453. NULL,
  1454. NULL,
  1455. NULL,
  1456. &cSubKeys,
  1457. &nMaxLen,
  1458. NULL,
  1459. NULL,
  1460. NULL,
  1461. NULL,
  1462. NULL,
  1463. NULL
  1464. );
  1465. }
  1466. if ( Win32Rc == ERROR_SUCCESS && cSubKeys > 0 ) {
  1467. PWSTR szName = (PWSTR)LocalAlloc(0, (nMaxLen+2)*sizeof(WCHAR));
  1468. if ( !szName ) {
  1469. Win32Rc = ERROR_NOT_ENOUGH_MEMORY;
  1470. } else {
  1471. DWORD BufSize;
  1472. DWORD index = 0;
  1473. DWORD RegType;
  1474. do {
  1475. BufSize = nMaxLen+1;
  1476. Win32Rc = RegEnumKeyEx(
  1477. hKey,
  1478. index,
  1479. szName,
  1480. &BufSize,
  1481. NULL,
  1482. NULL,
  1483. NULL,
  1484. NULL);
  1485. if ( ERROR_SUCCESS == Win32Rc ) {
  1486. index++;
  1487. //
  1488. // get the full registry key name and Valuetype
  1489. //
  1490. cSubKeys = REG_SZ;
  1491. PDWORD pType = &cSubKeys;
  1492. //
  1493. // query ValueType, if error, default REG_SZ
  1494. //
  1495. MyRegQueryValue( hKey,
  1496. szName,
  1497. SCE_REG_VALUE_TYPE,
  1498. (PVOID *)&pType,
  1499. &RegType );
  1500. if ( cSubKeys < REG_SZ || cSubKeys > REG_MULTI_SZ ) {
  1501. cSubKeys = REG_SZ;
  1502. }
  1503. //
  1504. // convert the path name
  1505. //
  1506. ConvertMultiSzToDelim(szName, BufSize, L'/', L'\\');
  1507. //
  1508. // compare with the input array, if not exist,
  1509. // add it
  1510. //
  1511. for ( DWORD i=0; i<*pCount; i++ ) {
  1512. if ( (*paRegValues)[i].FullValueName &&
  1513. _wcsicmp(szName, (*paRegValues)[i].FullValueName) == 0 ) {
  1514. break;
  1515. }
  1516. }
  1517. if ( i >= *pCount ) {
  1518. //
  1519. // did not find a match, add it
  1520. //
  1521. if ( SCESTATUS_SUCCESS != SceAddToNameStatusList(&pnsList,
  1522. szName,
  1523. BufSize,
  1524. cSubKeys) ) {
  1525. Win32Rc = ERROR_NOT_ENOUGH_MEMORY;
  1526. break;
  1527. }
  1528. nAdded++;
  1529. }
  1530. } else if ( ERROR_NO_MORE_ITEMS != Win32Rc ) {
  1531. break;
  1532. }
  1533. } while ( Win32Rc != ERROR_NO_MORE_ITEMS );
  1534. if ( Win32Rc == ERROR_NO_MORE_ITEMS ) {
  1535. Win32Rc = ERROR_SUCCESS;
  1536. }
  1537. //
  1538. // free the enumeration buffer
  1539. //
  1540. LocalFree(szName);
  1541. }
  1542. }
  1543. if ( hKey ) {
  1544. RegCloseKey(hKey);
  1545. }
  1546. if ( ERROR_SUCCESS == Win32Rc ) {
  1547. //
  1548. // add the name list to the output arrays
  1549. //
  1550. DWORD nNewCount = *pCount + nAdded;
  1551. PSCE_REGISTRY_VALUE_INFO aNewArray;
  1552. if ( nNewCount ) {
  1553. aNewArray = (PSCE_REGISTRY_VALUE_INFO)LocalAlloc(0, nNewCount*sizeof(SCE_REGISTRY_VALUE_INFO));
  1554. if ( aNewArray ) {
  1555. ZeroMemory(aNewArray, nNewCount * sizeof(SCE_REGISTRY_VALUE_INFO));
  1556. memcpy( aNewArray, *paRegValues, *pCount * sizeof( SCE_REGISTRY_VALUE_INFO ) );
  1557. DWORD i;
  1558. i=0;
  1559. for ( PSCE_NAME_STATUS_LIST pns=pnsList;
  1560. pns; pns=pns->Next ) {
  1561. if ( pns->Name && i < nAdded ) {
  1562. aNewArray[*pCount+i].FullValueName = pns->Name;
  1563. pns->Name = NULL;
  1564. aNewArray[*pCount+i].Value = NULL;
  1565. aNewArray[*pCount+i].ValueType = pns->Status;
  1566. aNewArray[*pCount+i].Status = SCE_STATUS_NOT_CONFIGURED;
  1567. i++;
  1568. }
  1569. }
  1570. //
  1571. // free the original array
  1572. // all components in the array are already transferred to the new array
  1573. //
  1574. LocalFree(*paRegValues);
  1575. *pCount = nNewCount;
  1576. *paRegValues = aNewArray;
  1577. } else {
  1578. Win32Rc = ERROR_NOT_ENOUGH_MEMORY;
  1579. }
  1580. }
  1581. }
  1582. //
  1583. // free the name status list
  1584. //
  1585. SceFreeMemory(pnsList, SCE_STRUCT_NAME_STATUS_LIST);
  1586. return( Win32Rc );
  1587. }
  1588. DWORD
  1589. GetGroupStatus(
  1590. DWORD status,
  1591. int flag
  1592. )
  1593. {
  1594. DWORD NewStatus;
  1595. switch ( flag ) {
  1596. case STATUS_GROUP_RECORD:
  1597. if (status & SCE_GROUP_STATUS_NC_MEMBERS) {
  1598. NewStatus = SCE_STATUS_NOT_CONFIGURED;
  1599. } else if ( (status & SCE_GROUP_STATUS_MEMBERS_MISMATCH) ||
  1600. (status & SCE_GROUP_STATUS_MEMBEROF_MISMATCH)) {
  1601. NewStatus = SCE_STATUS_MISMATCH;
  1602. } else if (status & SCE_GROUP_STATUS_NOT_ANALYZED) {
  1603. NewStatus = SCE_STATUS_NOT_ANALYZED;
  1604. } else if (status & SCE_GROUP_STATUS_ERROR_ANALYZED) {
  1605. NewStatus = SCE_STATUS_ERROR_NOT_AVAILABLE;
  1606. } else {
  1607. NewStatus = SCE_STATUS_GOOD;
  1608. }
  1609. break;
  1610. case STATUS_GROUP_MEMBERS:
  1611. if ( status & SCE_GROUP_STATUS_NOT_ANALYZED ) {
  1612. NewStatus = SCE_STATUS_NOT_ANALYZED; //do not display any status;
  1613. } else {
  1614. if ( status & SCE_GROUP_STATUS_NC_MEMBERS ) {
  1615. NewStatus = SCE_STATUS_NOT_CONFIGURED;
  1616. } else if ( status & SCE_GROUP_STATUS_MEMBERS_MISMATCH ) {
  1617. NewStatus = SCE_STATUS_MISMATCH;
  1618. } else if (status & SCE_GROUP_STATUS_ERROR_ANALYZED) {
  1619. NewStatus = SCE_STATUS_ERROR_NOT_AVAILABLE;
  1620. } else {
  1621. NewStatus = SCE_STATUS_GOOD;
  1622. }
  1623. }
  1624. break;
  1625. case STATUS_GROUP_MEMBEROF:
  1626. if ( status & SCE_GROUP_STATUS_NOT_ANALYZED ) {
  1627. NewStatus = SCE_STATUS_NOT_ANALYZED; // do not display any status;
  1628. } else {
  1629. if ( status & SCE_GROUP_STATUS_NC_MEMBEROF ) {
  1630. NewStatus = SCE_STATUS_NOT_CONFIGURED;
  1631. } else if ( status & SCE_GROUP_STATUS_MEMBEROF_MISMATCH ) {
  1632. NewStatus = SCE_STATUS_MISMATCH;
  1633. } else if (status & SCE_GROUP_STATUS_ERROR_ANALYZED) {
  1634. NewStatus = SCE_STATUS_ERROR_NOT_AVAILABLE;
  1635. } else {
  1636. NewStatus = SCE_STATUS_GOOD;
  1637. }
  1638. }
  1639. break;
  1640. default:
  1641. NewStatus = 0;
  1642. break;
  1643. }
  1644. return NewStatus;
  1645. }
  1646. //+--------------------------------------------------------------------------
  1647. //
  1648. // Function: AllocGetTempFileName
  1649. //
  1650. // Synopsis: Allocate and return a string with a temporary file name.
  1651. //
  1652. // Returns: The temporary file name, or 0 if a temp file can't be found
  1653. //
  1654. // History:
  1655. //
  1656. //---------------------------------------------------------------------------
  1657. LPTSTR
  1658. AllocGetTempFileName() {
  1659. DWORD dw;
  1660. CString strPath;
  1661. CString strFile;
  1662. LPTSTR szPath;
  1663. LPTSTR szFile;
  1664. //
  1665. // Get a temporary directory path in strPath
  1666. // If our buffer isn't large enough then keep reallocating until it is
  1667. //
  1668. dw = MAX_PATH;
  1669. do {
  1670. szPath = strPath.GetBuffer(dw);
  1671. dw = GetTempPath(MAX_PATH,szPath);
  1672. strPath.ReleaseBuffer();
  1673. } while (dw > (DWORD)strPath.GetLength() );
  1674. //
  1675. // Can't get a path to the temporary directory
  1676. //
  1677. if (!dw) {
  1678. return 0;
  1679. }
  1680. //
  1681. // Get a temporary file in that directory
  1682. //
  1683. szFile = strFile.GetBuffer(dw+MAX_PATH);
  1684. if (!GetTempFileName(szPath,L"SCE",0,szFile)) {
  1685. return 0;
  1686. }
  1687. strFile.ReleaseBuffer();
  1688. szFile = (LPTSTR)LocalAlloc(LPTR,(strFile.GetLength()+1)*sizeof(TCHAR));
  1689. if (!szFile) {
  1690. return 0;
  1691. }
  1692. lstrcpy(szFile,(LPCTSTR)strFile);
  1693. return szFile;
  1694. }
  1695. // If the given environment variable exists as the first part of the path,
  1696. // then the environment variable is inserted into the output buffer.
  1697. //
  1698. // Returns TRUE if pszResult is filled in.
  1699. //
  1700. // Example: Input -- C:\WINNT\SYSTEM32\FOO.TXT -and- lpEnvVar = %SYSTEMROOT%
  1701. // Output -- %SYSTEMROOT%\SYSTEM32\FOO.TXT
  1702. BOOL UnExpandEnvironmentString(LPCTSTR pszPath, LPCTSTR pszEnvVar, LPTSTR pszResult, UINT cbResult)
  1703. {
  1704. TCHAR szEnvVar[MAX_PATH];
  1705. DWORD dwEnvVar = ExpandEnvironmentStrings(pszEnvVar, szEnvVar, ARRAYSIZE(szEnvVar)) - 1; // don't count the NULL
  1706. if (CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE,
  1707. szEnvVar, dwEnvVar, pszPath, dwEnvVar) == 2) {
  1708. if (lstrlen(pszPath) + dwEnvVar < cbResult) {
  1709. lstrcpy(pszResult, pszEnvVar);
  1710. lstrcat(pszResult, pszPath + dwEnvVar);
  1711. return TRUE;
  1712. }
  1713. }
  1714. return FALSE;
  1715. }
  1716. //+--------------------------------------------------------------------------
  1717. //
  1718. // Function: UnexpandEnvironmentVariables
  1719. //
  1720. // Synopsis: Given a path, contract any leading members to use matching
  1721. // environment variables, if any
  1722. //
  1723. // Arguments:
  1724. // [szPath] - The path to expand
  1725. //
  1726. // Returns: The newly allocated path (NULL if no changes are made)
  1727. //
  1728. // History:
  1729. //
  1730. //---------------------------------------------------------------------------
  1731. LPTSTR
  1732. UnexpandEnvironmentVariables(LPCTSTR szPath) {
  1733. UINT cbNew;
  1734. LPTSTR szNew;
  1735. LPTSTR mszEnvVars;
  1736. LPTSTR szEnvVar;
  1737. DWORD dwEnvType;
  1738. BOOL bExpanded;
  1739. CString strKey;
  1740. CString strValueName;
  1741. CString str;
  1742. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1743. if (!strKey.LoadString(IDS_SECEDIT_KEY) ||
  1744. !strValueName.LoadString(IDS_ENV_VARS_REG_VALUE)) {
  1745. return NULL;
  1746. }
  1747. //
  1748. // Allocate memory for the new path
  1749. //
  1750. cbNew = lstrlen(szPath)+MAX_PATH+1;
  1751. szNew = (LPTSTR) LocalAlloc(LPTR,cbNew * sizeof(TCHAR));
  1752. if (!szNew) {
  1753. return NULL;
  1754. }
  1755. //
  1756. // Get Vars to expand from the registry
  1757. //
  1758. mszEnvVars = NULL;
  1759. if (ERROR_SUCCESS != MyRegQueryValue(HKEY_LOCAL_MACHINE, // hKeyRoot
  1760. strKey, // SubKey
  1761. strValueName, // ValueName
  1762. (LPVOID *)&mszEnvVars, // Value
  1763. &dwEnvType)) { // Reg Type
  1764. //
  1765. // Can't get any variables to expand
  1766. //
  1767. LocalFree(szNew);
  1768. return NULL;
  1769. }
  1770. //
  1771. // We need a multi-sz with the variables to replace in it
  1772. //
  1773. if (REG_MULTI_SZ != dwEnvType || mszEnvVars == NULL) //Bug350194, Yang Gao, 3/23/2001
  1774. {
  1775. LocalFree(szNew);
  1776. return NULL;
  1777. }
  1778. bExpanded = FALSE;
  1779. //
  1780. // Start at the beginning of the multi-sz block
  1781. //
  1782. szEnvVar = mszEnvVars;
  1783. while (*szEnvVar) {
  1784. if (UnExpandEnvironmentString(szPath,szEnvVar,szNew,cbNew)) {
  1785. //
  1786. // We can only unexpand (successfully) once
  1787. //
  1788. bExpanded = TRUE;
  1789. break;
  1790. }
  1791. //
  1792. // Advance szEnvVar to the end of this string
  1793. //
  1794. while (*szEnvVar) {
  1795. szEnvVar++;
  1796. }
  1797. //
  1798. // And the beginning of the next
  1799. //
  1800. szEnvVar++;
  1801. }
  1802. if (mszEnvVars) {
  1803. LocalFree(mszEnvVars);
  1804. }
  1805. if (!bExpanded) {
  1806. LocalFree(szNew);
  1807. szNew = NULL;
  1808. }
  1809. return szNew;
  1810. }
  1811. //+--------------------------------------------------------------------------
  1812. //
  1813. // Function: IsSystemDatabase
  1814. //
  1815. // Synopsis: Determine if a specific databse is the system database or a private one
  1816. //
  1817. // Arguments:
  1818. // [szDBPath] - The database path to check
  1819. //
  1820. // Returns: True if szDBPath is the system database, false otherwise
  1821. //
  1822. // History:
  1823. //
  1824. //---------------------------------------------------------------------------
  1825. BOOL
  1826. IsSystemDatabase(LPCTSTR szDBPath) {
  1827. CString szSysDB;
  1828. BOOL bIsSysDB;
  1829. DWORD rc;
  1830. DWORD RegType;
  1831. if (!szDBPath) {
  1832. return FALSE;
  1833. }
  1834. //Raid bug 261450, Yang Gao, 3/30/2001
  1835. if (FAILED(GetSystemDatabase(&szSysDB))) {
  1836. return FALSE;
  1837. }
  1838. //
  1839. // We found an appropriate szSysDB, so compare it with szDBPath
  1840. //
  1841. if (lstrcmp(szDBPath,szSysDB) == 0) {
  1842. bIsSysDB = TRUE;
  1843. } else {
  1844. bIsSysDB = FALSE;
  1845. }
  1846. return bIsSysDB;
  1847. }
  1848. //+--------------------------------------------------------------------------
  1849. //
  1850. // Function: GetSystemDatabase
  1851. //
  1852. // Synopsis: Get the name of the current system database
  1853. //
  1854. // Arguments:
  1855. // [szDBPath] - [in/out] a pointer for the name of the system database
  1856. // The caller is responsible for freeing it.
  1857. //
  1858. //
  1859. // Returns: S_OK if the system database is found, otherwise an error
  1860. //
  1861. // History:
  1862. //
  1863. //---------------------------------------------------------------------------
  1864. HRESULT
  1865. GetSystemDatabase(CString *szDBPath)
  1866. {
  1867. if (!szDBPath)
  1868. {
  1869. return E_INVALIDARG;
  1870. }
  1871. //Raid bug 261450, Yang Gao, 3/30/2001
  1872. CString sAppend;
  1873. sAppend.LoadString( IDS_DB_DEFAULT );
  1874. PWSTR pszPath = (LPTSTR)LocalAlloc( 0, (MAX_PATH + sAppend.GetLength() + 1) * sizeof(WCHAR));
  1875. if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_WINDOWS, NULL, 0, pszPath)))
  1876. {
  1877. wcscpy( &(pszPath[lstrlen(pszPath)]), sAppend );
  1878. *szDBPath = pszPath;
  1879. if (pszPath)
  1880. {
  1881. LocalFree(pszPath);
  1882. pszPath = NULL;
  1883. }
  1884. return S_OK;
  1885. }
  1886. if (pszPath)
  1887. {
  1888. LocalFree(pszPath);
  1889. pszPath = NULL;
  1890. }
  1891. return E_FAIL;
  1892. }
  1893. //+--------------------------------------------------------------------------
  1894. //
  1895. // Function: ObjectStatusToString
  1896. //
  1897. // Synopsis: Convert an object status value to a printable string
  1898. //
  1899. // Arguments:
  1900. // [status] - [in] The status value to convert
  1901. // [str] - [out] The string to store the value in
  1902. //
  1903. //
  1904. //---------------------------------------------------------------------------
  1905. UINT
  1906. ObjectStatusToString(DWORD status, CString *strStatus) {
  1907. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  1908. if ( status & SCE_STATUS_PERMISSION_MISMATCH ) {
  1909. status = IDS_MISMATCH;
  1910. } else if (status & SCE_STATUS_AUDIT_MISMATCH) {
  1911. status = IDS_MISMATCH;
  1912. } else {
  1913. status &= 0x0F;
  1914. switch(status){
  1915. case SCE_STATUS_NOT_ANALYZED:
  1916. status = IDS_NOT_ANALYZED;
  1917. break;
  1918. case SCE_STATUS_GOOD:
  1919. status = IDS_OK ;
  1920. break;
  1921. case SCE_STATUS_MISMATCH:
  1922. status = IDS_MISMATCH;
  1923. break;
  1924. case SCE_STATUS_NOT_CONFIGURED:
  1925. //
  1926. // BUG 119215: The Analysis UI should never show "Not Defined"
  1927. // for the security of existing system objects
  1928. //
  1929. status = IDS_NOT_ANALYZED;
  1930. break;
  1931. case SCE_STATUS_CHILDREN_CONFIGURED:
  1932. status = IDS_CHILDREN_CONFIGURED;
  1933. break;
  1934. case SCE_STATUS_ERROR_NOT_AVAILABLE:
  1935. status = IDS_NOT_AVAILABLE;
  1936. break;
  1937. case SCE_STATUS_NEW_SERVICE:
  1938. status = IDS_NEW_SERVICE;
  1939. break;
  1940. default:
  1941. //
  1942. // We shouldn't get here, but for some reason we keep doing so
  1943. //
  1944. status = IDS_MISMATCH;
  1945. break;
  1946. }
  1947. }
  1948. if(strStatus){
  1949. strStatus->LoadString(status);
  1950. }
  1951. return status;
  1952. }
  1953. //+--------------------------------------------------------------------------
  1954. //
  1955. // Function: IsSecurityTemplate
  1956. //
  1957. // Synopsis: Validates a file to see if the file is a security template.
  1958. //
  1959. // Arguments: [pszFileName] - The full path to the file to check.
  1960. //
  1961. // Returns: FALSE if the file does not exist or is not a valid
  1962. // security template.
  1963. //
  1964. // TRUE if successful.
  1965. // History:
  1966. //
  1967. //---------------------------------------------------------------------------
  1968. BOOL
  1969. IsSecurityTemplate(
  1970. LPCTSTR pszFileName
  1971. )
  1972. {
  1973. if(!pszFileName){
  1974. return FALSE;
  1975. }
  1976. HANDLE hProfile;
  1977. SCESTATUS rc;
  1978. //
  1979. // Open the profile.
  1980. //
  1981. rc = SceOpenProfile(
  1982. pszFileName,
  1983. SCE_INF_FORMAT,
  1984. &hProfile
  1985. );
  1986. if(rc == SCESTATUS_SUCCESS && hProfile){
  1987. PSCE_PROFILE_INFO ProfileInfo = NULL;
  1988. PSCE_ERROR_LOG_INFO ErrBuf = NULL;
  1989. //
  1990. // The profile will be validated by trying to load all the security areas.
  1991. //
  1992. rc = SceGetSecurityProfileInfo(hProfile,
  1993. SCE_ENGINE_SCP,
  1994. AREA_ALL,
  1995. &ProfileInfo,
  1996. &ErrBuf);
  1997. if(ErrBuf){
  1998. rc = SCESTATUS_INVALID_DATA;
  1999. }
  2000. //
  2001. // Free up the memory.
  2002. //
  2003. SceFreeMemory((PVOID)ErrBuf, SCE_STRUCT_ERROR_LOG_INFO);
  2004. ErrBuf = NULL;
  2005. if ( ProfileInfo != NULL ) {
  2006. SceFreeMemory((PVOID)ProfileInfo, AREA_ALL);
  2007. LocalFree(ProfileInfo);
  2008. }
  2009. SceCloseProfile(&hProfile);
  2010. //
  2011. // return TRUE if everything is successful.
  2012. //
  2013. if(rc != SCESTATUS_INVALID_DATA){
  2014. return TRUE;
  2015. }
  2016. }
  2017. return FALSE;
  2018. }
  2019. //+--------------------------------------------------------------------------
  2020. //
  2021. // Function: WriteSprintf
  2022. //
  2023. // Synopsis: Writes formated [pszStr] to [pStm].
  2024. //
  2025. // Arguments: [pStm] - Stream to write to.
  2026. // [pszStr] - Format string to write.
  2027. // [...] - printf formating
  2028. //
  2029. // Returns: The total number of bytes written.
  2030. //
  2031. // History:
  2032. //
  2033. //---------------------------------------------------------------------------
  2034. int WriteSprintf( IStream *pStm, LPCTSTR pszStr, ...)
  2035. {
  2036. TCHAR szWrite[512];
  2037. va_list marker;
  2038. va_start(marker, pszStr);
  2039. vswprintf(szWrite, pszStr, marker);
  2040. va_end(marker);
  2041. ULONG nBytesWritten;
  2042. int iLen = lstrlen(szWrite);
  2043. if(pStm){
  2044. pStm->Write( szWrite, iLen * sizeof(TCHAR), &nBytesWritten );
  2045. return nBytesWritten;
  2046. }
  2047. return iLen;
  2048. }
  2049. //+--------------------------------------------------------------------------
  2050. //
  2051. // Function: ReadSprintf
  2052. //
  2053. // Synopsis: Reads formated [pszStr] from [pStm].
  2054. // supported character switches are
  2055. // 'd' - integer pointer.
  2056. //
  2057. // Arguments: [pStm] - Stream to read from.
  2058. // [pszStr] - Format string to test.
  2059. // [...] - pointer to the types defined by format
  2060. // specification types.
  2061. //
  2062. // Returns: Total number of bytes read from the stream
  2063. //
  2064. // History:
  2065. //
  2066. //---------------------------------------------------------------------------
  2067. int
  2068. ReadSprintf( IStream *pStm, LPCTSTR pszStr, ...)
  2069. {
  2070. if(!pStm || !pszStr){
  2071. return -1;
  2072. }
  2073. va_list marker;
  2074. va_start(marker, pszStr);
  2075. TCHAR szRead[256];
  2076. TCHAR szConv[512];
  2077. ULONG uRead = 0;
  2078. int i = 0;
  2079. LPCTSTR pszNext = szRead;
  2080. int iTotalRead = 0;
  2081. // Get the current seek position.
  2082. ULARGE_INTEGER liBack = { 0 };
  2083. LARGE_INTEGER liCur = { 0 };
  2084. pStm->Seek( liCur, STREAM_SEEK_CUR, &liBack);
  2085. #define INCBUFFER(sz)\
  2086. if(uRead){\
  2087. (sz)++;\
  2088. uRead--;\
  2089. } else {\
  2090. pStm->Read(szRead, 256 * sizeof(TCHAR), &uRead);\
  2091. uRead = uRead/sizeof(TCHAR);\
  2092. (sz) = szRead;\
  2093. }\
  2094. iTotalRead++;
  2095. while(*pszStr){
  2096. if(!uRead){
  2097. // Read information into buffer.
  2098. pStm->Read( szRead, 256 * sizeof(TCHAR), &uRead);
  2099. pszNext = szRead;
  2100. uRead = uRead/sizeof(TCHAR);
  2101. if(!uRead){
  2102. iTotalRead = -1;
  2103. break;
  2104. }
  2105. }
  2106. if(*pszStr == '%'){
  2107. pszStr++;
  2108. switch( *pszStr ){
  2109. case 'd':
  2110. // read integer.
  2111. pszStr++;
  2112. i = 0;
  2113. // copy number to our own buffer.
  2114. while( (*pszNext >= L'0' && *pszNext <= L'9') ){
  2115. szConv[i++] = *pszNext;
  2116. INCBUFFER( pszNext );
  2117. }
  2118. szConv[i] = 0;
  2119. // convert string to integer.
  2120. *(va_arg(marker, int *)) = _wtol(szConv);
  2121. continue;
  2122. case 's':
  2123. pszStr++;
  2124. i = 0;
  2125. // we have to have some kind of terminating character se we will use the
  2126. // next value in pszStr.
  2127. while( *pszNext && (*pszNext != *pszStr) ){
  2128. szConv[i++] = *pszNext;
  2129. INCBUFFER( pszNext );
  2130. }
  2131. if(*pszNext == *pszStr){
  2132. INCBUFFER( pszNext );
  2133. }
  2134. // copy the string value.
  2135. szConv[i] = 0;
  2136. if( i ){
  2137. LPTSTR pNew = (LPTSTR)LocalAlloc(0, sizeof(TCHAR) * (i + 1));
  2138. if(NULL != pNew){
  2139. lstrcpy(pNew, szConv);
  2140. }
  2141. LPTSTR *pArg;
  2142. pArg = (va_arg(marker, LPTSTR *));
  2143. if (pArg) {
  2144. *pArg = pNew;
  2145. }
  2146. } else {
  2147. va_arg(marker, LPTSTR *);
  2148. }
  2149. pszStr++;
  2150. continue;
  2151. }
  2152. }
  2153. // check to make sure we are at the correct position in the file.
  2154. if(*pszStr != *pszNext){
  2155. iTotalRead = -1;
  2156. break;
  2157. }
  2158. pszStr++;
  2159. // increment buffer pointer.
  2160. INCBUFFER( pszNext );
  2161. }
  2162. va_end(marker);
  2163. // Reset streem seek pointer.
  2164. liCur.LowPart = liBack.LowPart;
  2165. if(iTotalRead >= 0){
  2166. liCur.LowPart += iTotalRead * sizeof(TCHAR);
  2167. }
  2168. liCur.HighPart = liBack.HighPart;
  2169. pStm->Seek(liCur, STREAM_SEEK_SET, NULL);
  2170. return iTotalRead;
  2171. #undef INCBUFFER
  2172. }
  2173. //+--------------------------------------------------------------------------------
  2174. // FileCreateError
  2175. //
  2176. // This function tries to create a new file use [pszFile]. It will display a
  2177. // message to the user if the file cannot be created.
  2178. //
  2179. // Arguments: [pszFile] - Full path of file to create.
  2180. // [dwFlags] - Flags
  2181. // FCE_IGNORE_FILEEXISTS - Ignore File exists error, and
  2182. // delete the file.
  2183. //
  2184. // Returns: IDYES the file can be created
  2185. // IDNo The file cannot be created
  2186. DWORD
  2187. FileCreateError(
  2188. LPCTSTR pszFile,
  2189. DWORD dwFlags
  2190. )
  2191. {
  2192. if(!pszFile){
  2193. return ERROR_INVALID_PARAMETER;
  2194. }
  2195. HANDLE hFile;
  2196. DWORD dwErr = IDNO;
  2197. //
  2198. // Try to create the file.
  2199. //
  2200. hFile = ExpandAndCreateFile(
  2201. pszFile,
  2202. GENERIC_WRITE,
  2203. 0,
  2204. NULL,
  2205. CREATE_NEW,
  2206. FILE_ATTRIBUTE_ARCHIVE,
  2207. NULL
  2208. );
  2209. if(hFile == INVALID_HANDLE_VALUE){
  2210. //
  2211. // Post error message to user.
  2212. //
  2213. dwErr = GetLastError();
  2214. LPTSTR pszErr;
  2215. CString strErr;
  2216. FormatMessage(
  2217. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  2218. FORMAT_MESSAGE_FROM_SYSTEM,
  2219. NULL,
  2220. dwErr,
  2221. 0,
  2222. (LPTSTR)&pszErr,
  2223. 0,
  2224. NULL
  2225. );
  2226. strErr = pszErr;
  2227. strErr += pszFile;
  2228. if(pszErr){
  2229. LocalFree(pszErr);
  2230. }
  2231. switch(dwErr){
  2232. case ERROR_ALREADY_EXISTS:
  2233. case ERROR_FILE_EXISTS:
  2234. if( dwFlags & FCE_IGNORE_FILEEXISTS ){
  2235. dwErr = IDYES;
  2236. break;
  2237. }
  2238. //
  2239. // Confirm overwrite.
  2240. //
  2241. strErr.Format(IDS_FILE_EXISTS_FMT, pszFile);
  2242. dwErr = AfxMessageBox(
  2243. strErr,
  2244. MB_YESNO
  2245. );
  2246. break;
  2247. default:
  2248. //
  2249. // The file cannot be created.
  2250. //
  2251. AfxMessageBox(
  2252. strErr,
  2253. MB_OK
  2254. );
  2255. dwErr = IDNO;
  2256. break;
  2257. }
  2258. } else {
  2259. //
  2260. // It's OK to create the file.
  2261. //
  2262. ::CloseHandle( hFile );
  2263. DeleteFile(pszFile);
  2264. dwErr = IDYES;
  2265. }
  2266. return dwErr;
  2267. }
  2268. //+--------------------------------------------------------------------------
  2269. //
  2270. // Function: IsDBCSPath
  2271. //
  2272. // Synopsis: Check if a path contains DBCS characters
  2273. //
  2274. // Arguments: [pszFile] - [in] The path to check
  2275. //
  2276. // Returns: TRUE if pszFile contains characters that can't be
  2277. // represented by a LPSTR
  2278. //
  2279. // FALSE if pszFile only contains characters that can
  2280. // be represented by a LPSTR
  2281. //
  2282. //
  2283. //+--------------------------------------------------------------------------
  2284. BOOL
  2285. IsDBCSPath(LPCTSTR szWideFile) {
  2286. while(*szWideFile) {
  2287. if (*szWideFile >= 256) {
  2288. return TRUE;
  2289. }
  2290. szWideFile++;
  2291. }
  2292. return FALSE;
  2293. /*
  2294. LPSTR szMBFile;
  2295. int nMBFile;
  2296. BOOL bUsedDefaultChar = FALSE;
  2297. nMBFile = sizeof(LPSTR)*(lstrlen(szWideFile));
  2298. szMBFile = (LPSTR)LocalAlloc(LPTR,nMBFile+1);
  2299. if (szMBFile) {
  2300. WideCharToMultiByte( CP_ACP,
  2301. 0,
  2302. szWideFile,
  2303. -1,
  2304. szMBFile,
  2305. nMBFile,
  2306. NULL,
  2307. &bUsedDefaultChar);
  2308. LocalFree(szMBFile);
  2309. }
  2310. return bUsedDefaultChar;
  2311. */
  2312. }
  2313. //+--------------------------------------------------------------------------
  2314. //
  2315. // Function: GetSeceditHelpFilename
  2316. //
  2317. // Synopsis: Return the fully qualified path the help file for Secedit
  2318. //
  2319. // Arguments: None
  2320. //
  2321. // Returns: a CString containing the fully qualified help file name.
  2322. //
  2323. //
  2324. //+--------------------------------------------------------------------------
  2325. CString GetSeceditHelpFilename()
  2326. {
  2327. static CString helpFileName;
  2328. if ( helpFileName.IsEmpty () )
  2329. {
  2330. UINT result = ::GetSystemWindowsDirectory (
  2331. helpFileName.GetBufferSetLength (MAX_PATH+1), MAX_PATH);
  2332. ASSERT(result != 0 && result <= MAX_PATH);
  2333. helpFileName.ReleaseBuffer ();
  2334. helpFileName += L"\\help\\wsecedit.hlp";
  2335. }
  2336. return helpFileName;
  2337. }
  2338. //+--------------------------------------------------------------------------
  2339. //
  2340. // Function: GetGpeditHelpFilename
  2341. //
  2342. // Synopsis: Return the fully qualified path the help file for Secedit
  2343. //
  2344. // Arguments: None
  2345. //
  2346. // Returns: a CString containing the fully qualified help file name.
  2347. //
  2348. //
  2349. //+--------------------------------------------------------------------------
  2350. CString GetGpeditHelpFilename()
  2351. {
  2352. static CString helpFileName;
  2353. if ( helpFileName.IsEmpty () )
  2354. {
  2355. UINT result = ::GetSystemWindowsDirectory (
  2356. helpFileName.GetBufferSetLength (MAX_PATH+1), MAX_PATH);
  2357. ASSERT(result != 0 && result <= MAX_PATH);
  2358. helpFileName.ReleaseBuffer ();
  2359. helpFileName += L"\\help\\gpedit.hlp";
  2360. }
  2361. return helpFileName;
  2362. }
  2363. //+--------------------------------------------------------------------------
  2364. //
  2365. // Function: ExpandEnvironmentStringWrapper
  2366. //
  2367. // Synopsis: Takes an LPTSTR and expands the enviroment variables in it
  2368. //
  2369. // Arguments: Pointer to the string to expand.
  2370. //
  2371. // Returns: a CString containing the fully expanded string.
  2372. //
  2373. //+--------------------------------------------------------------------------
  2374. CString ExpandEnvironmentStringWrapper(LPCTSTR psz)
  2375. {
  2376. LPTSTR pszBuffer = NULL;
  2377. DWORD dwExpanded = 0;
  2378. CString sz;
  2379. dwExpanded = ExpandEnvironmentStrings(psz, NULL, 0);
  2380. pszBuffer = sz.GetBuffer(dwExpanded);
  2381. ExpandEnvironmentStrings(psz, pszBuffer, dwExpanded);
  2382. sz.ReleaseBuffer(dwExpanded);
  2383. return (sz);
  2384. }
  2385. //+--------------------------------------------------------------------------
  2386. //
  2387. // Function: ExpandAndCreateFile
  2388. //
  2389. // Synopsis: Just does a normal CreateFile(), but expands the filename before
  2390. // creating the file.
  2391. //
  2392. // Arguments: Same as CreateFile().
  2393. //
  2394. // Returns: HANDLE to the created file.
  2395. //
  2396. //+--------------------------------------------------------------------------
  2397. HANDLE WINAPI ExpandAndCreateFile (
  2398. LPCTSTR lpFileName,
  2399. DWORD dwDesiredAccess,
  2400. DWORD dwShareMode,
  2401. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  2402. DWORD dwCreationDisposition,
  2403. DWORD dwFlagsAndAttributes,
  2404. HANDLE hTemplateFile
  2405. )
  2406. {
  2407. HANDLE hRet = INVALID_HANDLE_VALUE;
  2408. CString sz;
  2409. sz = ExpandEnvironmentStringWrapper(lpFileName);
  2410. return (CreateFile(
  2411. sz,
  2412. dwDesiredAccess,
  2413. dwShareMode,
  2414. lpSecurityAttributes,
  2415. dwCreationDisposition,
  2416. dwFlagsAndAttributes,
  2417. hTemplateFile));
  2418. }
  2419. //**********************************************************************
  2420. //
  2421. // FUNCTION: IsAdmin - This function checks the token of the
  2422. // calling thread to see if the caller belongs to
  2423. // the Administrators group.
  2424. //
  2425. // PARAMETERS: none
  2426. //
  2427. // RETURN VALUE: TRUE if the caller is an administrator on the local
  2428. // machine. Otherwise, FALSE.
  2429. //
  2430. //**********************************************************************
  2431. BOOL IsAdmin(void) {
  2432. HANDLE hAccessToken = NULL;
  2433. PTOKEN_GROUPS ptgGroups = NULL;
  2434. DWORD cbGroups = 0;
  2435. PSID psidAdmin = NULL;
  2436. UINT i;
  2437. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  2438. // assume the caller is not an administrator
  2439. BOOL bIsAdmin = FALSE;
  2440. __try {
  2441. if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE,
  2442. &hAccessToken)) {
  2443. if (GetLastError() != ERROR_NO_TOKEN)
  2444. __leave;
  2445. // retry against process token if no thread token exists
  2446. if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY,
  2447. &hAccessToken))
  2448. __leave;
  2449. }
  2450. // determine required size of buffer for token information
  2451. if (GetTokenInformation(hAccessToken, TokenGroups, NULL, 0,
  2452. &cbGroups)) {
  2453. // call should have failed due to zero-length buffer
  2454. __leave;
  2455. } else {
  2456. // call should have failed due to zero-length buffer
  2457. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  2458. __leave;
  2459. }
  2460. // allocate a buffer to hold the token groups
  2461. ptgGroups = (PTOKEN_GROUPS) HeapAlloc(GetProcessHeap(), 0,
  2462. cbGroups);
  2463. if (!ptgGroups)
  2464. __leave;
  2465. // call GetTokenInformation() again to actually retrieve the groups
  2466. if (!GetTokenInformation(hAccessToken, TokenGroups, ptgGroups,
  2467. cbGroups, &cbGroups))
  2468. __leave;
  2469. // create a SID for the local administrators group
  2470. if (!AllocateAndInitializeSid(&siaNtAuthority, 2,
  2471. SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
  2472. 0, 0, 0, 0, 0, 0, &psidAdmin))
  2473. __leave;
  2474. // scan the token's groups and compare the SIDs to the admin SID
  2475. for (i = 0; i < ptgGroups->GroupCount; i++) {
  2476. if (EqualSid(psidAdmin, ptgGroups->Groups[i].Sid)) {
  2477. bIsAdmin = TRUE;
  2478. break;
  2479. }
  2480. }
  2481. } __finally {
  2482. // free resources
  2483. if (hAccessToken)
  2484. CloseHandle(hAccessToken);
  2485. if (ptgGroups)
  2486. HeapFree(GetProcessHeap(), 0, ptgGroups);
  2487. if (psidAdmin)
  2488. FreeSid(psidAdmin);
  2489. }
  2490. return bIsAdmin;
  2491. }
  2492. //+--------------------------------------------------------------------------
  2493. //
  2494. // Function: MultiSZToSZ
  2495. //
  2496. // Synopsis: Converts a multiline string to a comma delimited normal string
  2497. //
  2498. // Returns: The converted string
  2499. //
  2500. //+--------------------------------------------------------------------------
  2501. PWSTR MultiSZToSZ(PCWSTR sz)
  2502. {
  2503. PWSTR szOut = NULL;
  2504. ASSERT(sz);
  2505. if (!sz)
  2506. {
  2507. return NULL;
  2508. }
  2509. //Bug 349000, Yang Gao, 3/23/2001
  2510. long i = 0;
  2511. long j = 0;
  2512. while( L'\0' != sz[i] )
  2513. {
  2514. if( L',' == sz[i] )
  2515. j++;
  2516. i++;
  2517. }
  2518. szOut = (PWSTR) LocalAlloc(LPTR,(lstrlen(sz)+j*2+1)*sizeof(wchar_t)); //Raid #376228, 4/25/2001
  2519. if (!szOut)
  2520. {
  2521. return NULL;
  2522. }
  2523. for(i=0,j=0; sz[i] != L'\0'; i++)
  2524. {
  2525. if( L'\n' == sz[i] )
  2526. {
  2527. szOut[j++] = MULTISZ_DELIMITER;
  2528. continue;
  2529. }
  2530. if( L'\r' == sz[i] )
  2531. {
  2532. continue; // ignore it
  2533. }
  2534. if( L',' == sz[i] )
  2535. {
  2536. szOut[j++] = MULTISZ_QUOTE;
  2537. szOut[j++] = sz[i];
  2538. szOut[j++] = MULTISZ_QUOTE;
  2539. continue;
  2540. }
  2541. szOut[j++] = sz[i];
  2542. }
  2543. return szOut;
  2544. }
  2545. //+--------------------------------------------------------------------------
  2546. //
  2547. // Function: SZToMultiSZ
  2548. //
  2549. // Synopsis: Converts a comma delimited string to a multiline string
  2550. //
  2551. // Returns: The converted string
  2552. //
  2553. //+--------------------------------------------------------------------------
  2554. PWSTR SZToMultiSZ(PCWSTR sz)
  2555. {
  2556. PWSTR szOut = NULL;
  2557. ASSERT(sz);
  2558. if (!sz)
  2559. {
  2560. return NULL;
  2561. }
  2562. //
  2563. // Calculate the length of the expanded string
  2564. //
  2565. int cSZ = 0;
  2566. for (int i = 0;sz[i] != L'\0'; i++)
  2567. {
  2568. if (MULTISZ_DELIMITER == sz[i])
  2569. {
  2570. //
  2571. // Delimiter expands into an extra character so count it twice
  2572. //
  2573. cSZ++;
  2574. }
  2575. cSZ++;
  2576. }
  2577. szOut = (PWSTR) LocalAlloc(LPTR,(cSZ+1)*sizeof(wchar_t));
  2578. if (!szOut)
  2579. {
  2580. return NULL;
  2581. }
  2582. BOOL qflag = FALSE;
  2583. for(int i=0, c=0; sz[i] != L'\0'; i++)
  2584. {
  2585. //Bug 349000, Yang Gao, 3/23/2001
  2586. if( MULTISZ_QUOTE == sz[i] && MULTISZ_DELIMITER == sz[i+1] )
  2587. {
  2588. qflag = TRUE;
  2589. continue;
  2590. }
  2591. if( MULTISZ_DELIMITER == sz[i] && MULTISZ_QUOTE == sz[i+1] && qflag )
  2592. {
  2593. szOut[c++] = sz[i];
  2594. i++;
  2595. qflag = FALSE;
  2596. continue;
  2597. }
  2598. qflag = FALSE;
  2599. if (MULTISZ_DELIMITER == sz[i])
  2600. {
  2601. szOut[c++] = L'\r';
  2602. szOut[c++] = L'\n';
  2603. }
  2604. else
  2605. {
  2606. szOut[c++] = sz[i];
  2607. }
  2608. }
  2609. return szOut;
  2610. }
  2611. //+--------------------------------------------------------------------------
  2612. //
  2613. // Function: MultiSZToDisp
  2614. //
  2615. // Synopsis: Converts a comma delimited multiline string to a display string
  2616. //
  2617. // Returns: The converted string
  2618. // Bug 349000, Yang Gao, 3/23/2001
  2619. //+--------------------------------------------------------------------------
  2620. void MultiSZToDisp(PCWSTR sz, CString &pszOut)
  2621. {
  2622. ASSERT(sz);
  2623. if (!sz)
  2624. {
  2625. return;
  2626. }
  2627. //
  2628. // Calculate the length of the expanded string
  2629. //
  2630. int cSZ = 0;
  2631. for (int i = 0;sz[i] != L'\0'; i++)
  2632. {
  2633. if (MULTISZ_DELIMITER == sz[i])
  2634. {
  2635. //
  2636. // Delimiter expands into an extra character so count it twice
  2637. //
  2638. cSZ++;
  2639. }
  2640. cSZ++;
  2641. }
  2642. PWSTR szOut;
  2643. szOut = (PWSTR) LocalAlloc(LPTR,(cSZ+1)*sizeof(wchar_t));
  2644. if (!szOut)
  2645. {
  2646. return;
  2647. }
  2648. BOOL qflag = FALSE;
  2649. for(int i=0, c=0; sz[i] != L'\0'; i++)
  2650. {
  2651. if( MULTISZ_QUOTE == sz[i] && MULTISZ_DELIMITER == sz[i+1] )
  2652. {
  2653. qflag = TRUE;
  2654. continue;
  2655. }
  2656. if( MULTISZ_DELIMITER == sz[i] && MULTISZ_QUOTE == sz[i+1] && qflag )
  2657. {
  2658. szOut[c++] = sz[i];
  2659. i++;
  2660. qflag = FALSE;
  2661. continue;
  2662. }
  2663. qflag = FALSE;
  2664. szOut[c++] = sz[i];
  2665. }
  2666. pszOut = szOut;
  2667. LocalFree(szOut);
  2668. return;
  2669. }
  2670. SCE_PROFILE_INFO *g_pDefaultTemplate = NULL;
  2671. SCE_PROFILE_INFO *
  2672. GetDefaultTemplate() {
  2673. SCE_PROFILE_INFO *pspi = NULL;
  2674. DWORD RegType = 0;
  2675. SCESTATUS rc = 0;
  2676. LPTSTR szInfFile = NULL;
  2677. PVOID pHandle = NULL;
  2678. if (g_pDefaultTemplate) {
  2679. return g_pDefaultTemplate;
  2680. }
  2681. rc = MyRegQueryValue(HKEY_LOCAL_MACHINE,
  2682. SCE_REGISTRY_KEY,
  2683. SCE_REGISTRY_DEFAULT_TEMPLATE,
  2684. (PVOID *)&szInfFile,
  2685. &RegType );
  2686. if (ERROR_SUCCESS != rc) {
  2687. if (szInfFile) {
  2688. LocalFree(szInfFile);
  2689. szInfFile = NULL;
  2690. }
  2691. return NULL;
  2692. }
  2693. if (EngineOpenProfile(szInfFile,OPEN_PROFILE_CONFIGURE,&pHandle) != SCESTATUS_SUCCESS) {
  2694. LocalFree(szInfFile);
  2695. szInfFile = NULL;
  2696. return NULL;
  2697. }
  2698. LocalFree(szInfFile);
  2699. szInfFile = NULL;
  2700. rc = SceGetSecurityProfileInfo(pHandle,
  2701. SCE_ENGINE_SCP,
  2702. AREA_ALL,
  2703. &pspi,
  2704. NULL
  2705. );
  2706. SceCloseProfile(&pHandle);
  2707. if (SCESTATUS_SUCCESS != rc) {
  2708. //
  2709. // expand registry value section based on registry values list on local machine
  2710. //
  2711. SceRegEnumAllValues(
  2712. &(pspi->RegValueCount),
  2713. &(pspi->aRegValues)
  2714. );
  2715. #define PD(X,Y) if (pspi->X == SCE_NO_VALUE) { pspi->X = Y; }
  2716. PD(MaximumPasswordAge,MAX_PASS_AGE_DEFAULT)
  2717. PD(MinimumPasswordAge,MIN_PASS_AGE_DEFAULT)
  2718. PD(MinimumPasswordLength,MIN_PASS_LENGTH_DEFAULT)
  2719. PD(PasswordHistorySize,PASS_HISTORY_SIZE_DEFAULT)
  2720. PD(PasswordComplexity,PASS_COMPLEXITY_DEFAULT)
  2721. PD(RequireLogonToChangePassword,REQUIRE_LOGIN_DEFAULT)
  2722. PD(LockoutBadCount,LOCKOUT_BAD_COUNT_DEFAULT)
  2723. PD(ResetLockoutCount,RESET_LOCKOUT_COUNT_DEFAULT)
  2724. PD(LockoutDuration,LOCKOUT_DURATION_DEFAULT)
  2725. PD(AuditSystemEvents,AUDIT_SYSTEM_EVENTS_DEFAULT)
  2726. PD(AuditLogonEvents,AUDIT_LOGON_EVENTS_DEFAULT)
  2727. PD(AuditObjectAccess,AUDIT_OBJECT_ACCESS_DEFAULT)
  2728. PD(AuditPrivilegeUse,AUDIT_PRIVILEGE_USE_DEFAULT)
  2729. PD(AuditPolicyChange,AUDIT_POLICY_CHANGE_DEFAULT)
  2730. PD(AuditAccountManage,AUDIT_ACCOUNT_MANAGE_DEFAULT)
  2731. PD(AuditProcessTracking,AUDIT_PROCESS_TRACKING_DEFAULT)
  2732. PD(AuditDSAccess,AUDIT_DS_ACCESS_DEFAULT)
  2733. PD(AuditAccountLogon,AUDIT_ACCOUNT_LOGON_DEFAULT)
  2734. PD(ForceLogoffWhenHourExpire,FORCE_LOGOFF_DEFAULT)
  2735. PD(EnableAdminAccount,ENABLE_ADMIN_DEFAULT)
  2736. PD(EnableGuestAccount,ENABLE_GUEST_DEFAULT)
  2737. PD(LSAAnonymousNameLookup,LSA_ANON_LOOKUP_DEFAULT)
  2738. PD(MaximumLogSize[EVENT_TYPE_SYSTEM],SYS_MAX_LOG_SIZE_DEFAULT)
  2739. PD(MaximumLogSize[EVENT_TYPE_APP],APP_MAX_LOG_SIZE_DEFAULT)
  2740. PD(MaximumLogSize[EVENT_TYPE_SECURITY],SEC_MAX_LOG_SIZE_DEFAULT)
  2741. PD(AuditLogRetentionPeriod[EVENT_TYPE_SYSTEM],SYS_LOG_RETENTION_PERIOD_DEFAULT)
  2742. PD(AuditLogRetentionPeriod[EVENT_TYPE_APP],APP_LOG_RETENTION_PERIOD_DEFAULT)
  2743. PD(AuditLogRetentionPeriod[EVENT_TYPE_SECURITY],SEC_LOG_RETENTION_PERIOD_DEFAULT)
  2744. PD(RetentionDays[EVENT_TYPE_APP],APP_LOG_RETENTION_DAYS_DEFAULT)
  2745. PD(RetentionDays[EVENT_TYPE_SYSTEM],SYS_LOG_RETENTION_DAYS_DEFAULT)
  2746. PD(RetentionDays[EVENT_TYPE_SECURITY],SEC_LOG_RETENTION_DAYS_DEFAULT)
  2747. PD(RestrictGuestAccess[EVENT_TYPE_APP],APP_RESTRICT_GUEST_ACCESS_DEFAULT)
  2748. PD(RestrictGuestAccess[EVENT_TYPE_SYSTEM],SYS_RESTRICT_GUEST_ACCESS_DEFAULT)
  2749. PD(RestrictGuestAccess[EVENT_TYPE_SECURITY],SEC_RESTRICT_GUEST_ACCESS_DEFAULT)
  2750. if (pspi->pFiles.pAllNodes->Count == 0) {
  2751. DWORD SDSize = 0;
  2752. pspi->pFiles.pAllNodes->Count = 1;
  2753. pspi->pFiles.pAllNodes->pObjectArray[0] =
  2754. (PSCE_OBJECT_SECURITY) LocalAlloc(LPTR,sizeof(SCE_OBJECT_SECURITY));
  2755. if (pspi->pFiles.pAllNodes->pObjectArray[0]) {
  2756. SceSvcConvertTextToSD (
  2757. FILE_SYSTEM_SECURITY_DEFAULT,
  2758. &(pspi->pFiles.pAllNodes->pObjectArray[0]->pSecurityDescriptor),
  2759. &SDSize,
  2760. &(pspi->pFiles.pAllNodes->pObjectArray[0]->SeInfo)
  2761. );
  2762. }
  2763. }
  2764. if (pspi->pRegistryKeys.pAllNodes->Count == 0) {
  2765. DWORD SDSize = 0;
  2766. pspi->pRegistryKeys.pAllNodes->Count = 1;
  2767. pspi->pRegistryKeys.pAllNodes->pObjectArray[0] =
  2768. (PSCE_OBJECT_SECURITY) LocalAlloc(LPTR,sizeof(SCE_OBJECT_SECURITY));
  2769. if (pspi->pRegistryKeys.pAllNodes->pObjectArray[0]) {
  2770. SceSvcConvertTextToSD (
  2771. REGISTRY_SECURITY_DEFAULT,
  2772. &(pspi->pRegistryKeys.pAllNodes->pObjectArray[0]->pSecurityDescriptor),
  2773. &SDSize,
  2774. &(pspi->pRegistryKeys.pAllNodes->pObjectArray[0]->SeInfo)
  2775. );
  2776. }
  2777. }
  2778. if (pspi->pServices->General.pSecurityDescriptor == NULL) {
  2779. DWORD SDSize = 0;
  2780. SceSvcConvertTextToSD (
  2781. SERVICE_SECURITY_DEFAULT,
  2782. &(pspi->pServices->General.pSecurityDescriptor),
  2783. &SDSize,
  2784. &(pspi->pServices->SeInfo)
  2785. );
  2786. }
  2787. }
  2788. g_pDefaultTemplate = pspi;
  2789. return pspi;
  2790. }
  2791. HRESULT
  2792. GetDefaultFileSecurity(PSECURITY_DESCRIPTOR *ppSD,
  2793. SECURITY_INFORMATION *pSeInfo) {
  2794. SCE_PROFILE_INFO *pspi = NULL;
  2795. ASSERT(ppSD);
  2796. ASSERT(pSeInfo);
  2797. if (!ppSD || !pSeInfo) {
  2798. return E_INVALIDARG;
  2799. }
  2800. pspi = GetDefaultTemplate();
  2801. *ppSD = NULL;
  2802. *pSeInfo = 0;
  2803. if (!pspi) {
  2804. return E_FAIL;
  2805. }
  2806. if (!pspi->pFiles.pAllNodes) {
  2807. return E_FAIL;
  2808. }
  2809. if (pspi->pFiles.pAllNodes->Count == 0) {
  2810. return E_FAIL;
  2811. }
  2812. *pSeInfo = pspi->pFiles.pAllNodes->pObjectArray[0]->SeInfo;
  2813. return MyMakeSelfRelativeSD(pspi->pFiles.pAllNodes->pObjectArray[0]->pSecurityDescriptor,
  2814. ppSD);
  2815. }
  2816. HRESULT
  2817. GetDefaultRegKeySecurity(PSECURITY_DESCRIPTOR *ppSD,
  2818. SECURITY_INFORMATION *pSeInfo) {
  2819. SCE_PROFILE_INFO *pspi = NULL;
  2820. ASSERT(ppSD);
  2821. ASSERT(pSeInfo);
  2822. if (!ppSD || !pSeInfo) {
  2823. return E_INVALIDARG;
  2824. }
  2825. pspi = GetDefaultTemplate();
  2826. *ppSD = NULL;
  2827. *pSeInfo = 0;
  2828. if (!pspi) {
  2829. return E_FAIL;
  2830. }
  2831. if (!pspi->pRegistryKeys.pAllNodes) {
  2832. return E_FAIL;
  2833. }
  2834. if (pspi->pRegistryKeys.pAllNodes->Count == 0) {
  2835. return E_FAIL;
  2836. }
  2837. *pSeInfo = pspi->pRegistryKeys.pAllNodes->pObjectArray[0]->SeInfo;
  2838. return MyMakeSelfRelativeSD(pspi->pRegistryKeys.pAllNodes->pObjectArray[0]->pSecurityDescriptor,
  2839. ppSD);
  2840. }
  2841. HRESULT
  2842. GetDefaultServiceSecurity(PSECURITY_DESCRIPTOR *ppSD,
  2843. SECURITY_INFORMATION *pSeInfo) {
  2844. SCE_PROFILE_INFO *pspi = NULL;
  2845. ASSERT(ppSD);
  2846. ASSERT(pSeInfo);
  2847. if (!ppSD || !pSeInfo) {
  2848. return E_INVALIDARG;
  2849. }
  2850. pspi = GetDefaultTemplate();
  2851. *ppSD = NULL;
  2852. *pSeInfo = 0;
  2853. if (!pspi) {
  2854. return E_FAIL;
  2855. }
  2856. if (!pspi->pServices) {
  2857. return E_FAIL;
  2858. }
  2859. *pSeInfo = pspi->pServices->SeInfo;
  2860. return MyMakeSelfRelativeSD(pspi->pServices->General.pSecurityDescriptor,
  2861. ppSD);
  2862. }
  2863. BOOL
  2864. GetSecureWizardName(
  2865. OUT LPTSTR *ppstrPathName OPTIONAL,
  2866. OUT LPTSTR *ppstrDisplayName OPTIONAL
  2867. )
  2868. {
  2869. BOOL b=FALSE;
  2870. if ( ppstrPathName == NULL && ppstrDisplayName == NULL) return FALSE;
  2871. if ( ppstrPathName )
  2872. *ppstrPathName = NULL;
  2873. if ( ppstrDisplayName )
  2874. *ppstrDisplayName = NULL;
  2875. #define SCE_WIZARD_PATH SCE_ROOT_PATH TEXT("\\Wizard")
  2876. DWORD rc;
  2877. DWORD RegType;
  2878. LPVOID pValue=NULL;
  2879. PWSTR pPathName = NULL;
  2880. rc = MyRegQueryValue(HKEY_LOCAL_MACHINE,
  2881. SCE_WIZARD_PATH,
  2882. TEXT("Path"),
  2883. &pValue,
  2884. &RegType
  2885. );
  2886. if ( ERROR_SUCCESS == rc && pValue &&
  2887. (RegType == REG_SZ ||
  2888. RegType == REG_EXPAND_SZ) ) {
  2889. if ( RegType == REG_EXPAND_SZ ) {
  2890. //
  2891. // Expand the environment variable
  2892. //
  2893. DWORD dSize = ExpandEnvironmentStrings((LPTSTR)pValue, NULL, 0);
  2894. if ( dSize > 0 ) {
  2895. pPathName = (PWSTR)LocalAlloc(LPTR, (dSize+1)*sizeof(WCHAR));
  2896. if ( pPathName ) {
  2897. ExpandEnvironmentStrings((LPTSTR)pValue, pPathName, dSize);
  2898. } else {
  2899. LocalFree(pValue);
  2900. return FALSE;
  2901. }
  2902. } else {
  2903. LocalFree(pValue);
  2904. return FALSE;
  2905. }
  2906. } else {
  2907. //
  2908. // just simply take the string
  2909. //
  2910. pPathName = (LPTSTR)pValue;
  2911. pValue = NULL;
  2912. }
  2913. if ( ppstrDisplayName ) {
  2914. //
  2915. // now query the display name (menu name) from the binary
  2916. // binary name is stored in pPathName (can't be NULL)
  2917. //
  2918. DWORD dwHandle=0;
  2919. DWORD dwSize = GetFileVersionInfoSize(pPathName, &dwHandle);
  2920. if ( dwSize > 0 ) {
  2921. LPVOID pBuffer = (LPVOID)LocalAlloc(LPTR, dwSize+1);
  2922. if ( pBuffer ) {
  2923. if ( GetFileVersionInfo(pPathName, 0, dwSize, pBuffer) ) {
  2924. PVOID lpInfo = 0;
  2925. UINT cch = 0;
  2926. CString key;
  2927. WCHAR szBuffer[10];
  2928. CString keyBase;
  2929. wsprintf (szBuffer, L"%04X", GetUserDefaultLangID ());
  2930. wcscat (szBuffer, L"04B0");
  2931. keyBase = L"\\StringFileInfo\\";
  2932. keyBase += szBuffer;
  2933. keyBase += L"\\";
  2934. key = keyBase + L"FileDescription";
  2935. if ( VerQueryValue (pBuffer, const_cast <PWSTR>((PCWSTR) key), &lpInfo, &cch) ) {
  2936. *ppstrDisplayName = (PWSTR)LocalAlloc(LPTR,(cch+1)*sizeof(WCHAR));
  2937. if ( *ppstrDisplayName ) {
  2938. wcscpy(*ppstrDisplayName, (PWSTR)lpInfo);
  2939. b=TRUE;
  2940. }
  2941. }
  2942. }
  2943. LocalFree(pBuffer);
  2944. }
  2945. }
  2946. }
  2947. //
  2948. // get the binary name
  2949. //
  2950. if ( ppstrPathName ) {
  2951. *ppstrPathName = pPathName;
  2952. pPathName = NULL;
  2953. b=TRUE;
  2954. }
  2955. }
  2956. if ( pPathName && (pPathName != pValue ) ) {
  2957. LocalFree(pPathName);
  2958. }
  2959. if ( pValue ) {
  2960. LocalFree(pValue);
  2961. }
  2962. return b;
  2963. }