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.

1113 lines
26 KiB

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include "resource.h"
  4. #include <tapi.h>
  5. #include <objbase.h>
  6. #include <activeds.h>
  7. #include <lmerr.h>
  8. #include "util.h"
  9. #include "parser.h"
  10. #include "mmcmgmt.h"
  11. const TCHAR gszUserDNFmt[] = TEXT("WinNT://%s/%s,user");
  12. // Unicode to Unicode
  13. void Convert (LPWSTR wszIn, LPWSTR * pwszOut)
  14. {
  15. if (NULL == wszIn)
  16. {
  17. * pwszOut = NULL;
  18. return;
  19. }
  20. *pwszOut = new WCHAR [ wcslen (wszIn) + 1 ];
  21. if (*pwszOut)
  22. {
  23. wcscpy (*pwszOut, wszIn);
  24. }
  25. return;
  26. }
  27. // Ansi to Unicode
  28. void Convert (LPSTR szIn, LPWSTR * pwszOut)
  29. {
  30. if (NULL == szIn)
  31. {
  32. * pwszOut = NULL;
  33. return;
  34. }
  35. *pwszOut = new WCHAR [ strlen (szIn) + 1 ];
  36. if (*pwszOut)
  37. {
  38. if (0 == MultiByteToWideChar(
  39. CP_ACP,
  40. 0,
  41. szIn,
  42. -1,
  43. *pwszOut,
  44. strlen (szIn) + 1
  45. )
  46. )
  47. {
  48. // the conversion failed
  49. delete [] *pwszOut;
  50. *pwszOut = NULL;
  51. }
  52. }
  53. return;
  54. }
  55. void UnicodeToOEM (LPWSTR wszIn, LPSTR *pszOut)
  56. {
  57. int iSize;
  58. if (NULL == wszIn)
  59. {
  60. * pszOut = NULL;
  61. return;
  62. }
  63. // get the required buffer size
  64. iSize = WideCharToMultiByte(
  65. CP_OEMCP,
  66. 0,
  67. wszIn,
  68. -1,
  69. NULL,
  70. 0,
  71. NULL,
  72. NULL
  73. );
  74. if (0 == iSize)
  75. {
  76. *pszOut = NULL;
  77. }
  78. else
  79. {
  80. *pszOut = new char [ iSize ];
  81. if (*pszOut)
  82. {
  83. if ( 0 == WideCharToMultiByte(
  84. CP_OEMCP,
  85. 0,
  86. wszIn,
  87. -1,
  88. *pszOut,
  89. iSize,
  90. NULL,
  91. NULL
  92. )
  93. )
  94. {
  95. // the conversion failed
  96. delete [] *pszOut;
  97. *pszOut = NULL;
  98. }
  99. }
  100. }
  101. return;
  102. }
  103. int MessagePrint(
  104. LPTSTR szText,
  105. LPTSTR szTitle
  106. )
  107. {
  108. LPTSTR szOutput = NULL;
  109. LPWSTR wszOutput = NULL;
  110. LPSTR szOemOutput = NULL;
  111. // make it one TCHAR string
  112. szOutput = new TCHAR [ _tcslen(szText) + _tcslen(szTitle) + 3 ];
  113. if (!szOutput)
  114. return -1;
  115. _stprintf ( szOutput, _T("%s\n%s\n"), szTitle, szText );
  116. // convert the string to unicode
  117. Convert (szOutput, &wszOutput);
  118. delete [] szOutput;
  119. if (!wszOutput)
  120. return -1;
  121. // convert to OEM for printing
  122. UnicodeToOEM (wszOutput, &szOemOutput);
  123. delete [] wszOutput;
  124. if (!szOemOutput)
  125. return -1;
  126. // now print
  127. printf ("%s", szOemOutput);
  128. delete [] szOemOutput;
  129. return 0;
  130. }
  131. int MessagePrintIds (
  132. int idsText
  133. )
  134. {
  135. CIds IdsTitle (IDS_PRODUCTNAME);
  136. CIds IdsText ( idsText );
  137. if ( IdsTitle.StringFound () && IdsText.StringFound () )
  138. {
  139. return MessagePrint (
  140. IdsText.GetString (),
  141. IdsTitle.GetString ()
  142. );
  143. }
  144. return 0;
  145. }
  146. //
  147. // Report an error resource string with one %s in it
  148. //
  149. void ReportSz1 (
  150. HANDLE hLogFile,
  151. UINT idsError,
  152. LPTSTR szParam
  153. )
  154. {
  155. TCHAR szText[256];
  156. TCHAR szBuf2[128];
  157. CIds IdsError (idsError);
  158. CIds IdsTitle (IDS_PRODUCTNAME);
  159. if ( IdsError.StringFound () && IdsTitle.StringFound () )
  160. {
  161. _tcsncpy (szBuf2, szParam, sizeof(szBuf2) / sizeof(TCHAR));
  162. szBuf2[sizeof(szBuf2) / sizeof(TCHAR) - 1] = 0;
  163. wsprintf (szText, IdsError.GetString (), szBuf2);
  164. if (hLogFile != NULL && hLogFile != INVALID_HANDLE_VALUE)
  165. {
  166. char szAnsiBuf[256];
  167. DWORD dwNumOfBytesWritten;
  168. WideCharToMultiByte (
  169. CP_ACP,
  170. 0,
  171. szText,
  172. -1,
  173. szAnsiBuf,
  174. sizeof(szAnsiBuf),
  175. NULL,
  176. NULL
  177. );
  178. lstrcatA (szAnsiBuf, "\n");
  179. WriteFile (
  180. hLogFile,
  181. szAnsiBuf,
  182. lstrlenA (szAnsiBuf),
  183. &dwNumOfBytesWritten,
  184. NULL
  185. );
  186. }
  187. else
  188. {
  189. MessagePrint (szText, IdsTitle.GetString ());
  190. }
  191. }
  192. }
  193. //
  194. // IsValidDomainUser
  195. // Check if a domain user like redmond\jonsmith specified in szDomainUser
  196. // is valid or not. returns S_FALSE if it is invalid, S_OK for valid user.
  197. //
  198. // szFullName ---- To return the user's full name
  199. // cch ---- count of characters pointed to by szFullName
  200. //
  201. // if szFullName is NULL or cch is zero, no full name is returned
  202. //
  203. HRESULT IsValidDomainUser (
  204. LPCTSTR szDomainUser,
  205. LPTSTR szFullName,
  206. DWORD cch
  207. )
  208. {
  209. HRESULT hr = S_OK;
  210. TCHAR szDN[256];
  211. TCHAR szDomain[256];
  212. LPTSTR szSep;
  213. LPCTSTR szUser;
  214. DWORD dw;
  215. IADsUser * pUser = NULL;
  216. BSTR bstrFullName = NULL;
  217. // Sanity check
  218. if (szDomainUser == NULL || szDomainUser[0] == 0)
  219. {
  220. hr = S_FALSE;
  221. goto ExitHere;
  222. }
  223. //
  224. // Construct the user DN as <WINNT://domain/user,user>
  225. //
  226. szSep = _tcschr (szDomainUser, TEXT('\\'));
  227. if (szSep == NULL)
  228. {
  229. // No '\' is given, assume a local user ,domain is local computer
  230. szUser = szDomainUser;
  231. dw = sizeof(szDomain)/sizeof(TCHAR);
  232. if (GetComputerName (szDomain, &dw) == 0)
  233. {
  234. hr = HRESULT_FROM_WIN32 (GetLastError ());
  235. goto ExitHere;
  236. }
  237. }
  238. else
  239. {
  240. // assume invalid domain name if longer than 255
  241. if (szSep - szDomainUser >= sizeof(szDomain)/sizeof(TCHAR))
  242. {
  243. hr = S_FALSE;
  244. goto ExitHere;
  245. }
  246. _tcsncpy (szDomain, szDomainUser, szSep - szDomainUser);
  247. szDomain[szSep - szDomainUser] = 0;
  248. szUser = szSep + 1;
  249. }
  250. if (_tcslen (gszUserDNFmt) + _tcslen (szDomain) + _tcslen (szUser) >
  251. sizeof(szDN) / sizeof(TCHAR))
  252. {
  253. hr = S_FALSE;
  254. goto ExitHere;
  255. }
  256. wsprintf (szDN, gszUserDNFmt, szDomain, szUser);
  257. //
  258. // Try to bind to the user object
  259. //
  260. hr = ADsGetObject (szDN, IID_IADsUser, (void **)&pUser);
  261. if (FAILED(hr))
  262. {
  263. if (hr == E_ADS_INVALID_USER_OBJECT ||
  264. hr == E_ADS_UNKNOWN_OBJECT ||
  265. hr == E_ADS_BAD_PATHNAME ||
  266. HRESULT_CODE(hr) == NERR_UserNotFound)
  267. {
  268. hr = S_FALSE; // The user does not exist
  269. }
  270. goto ExitHere;
  271. }
  272. //
  273. // If the user exists, get its full name
  274. //
  275. if (cch > 0)
  276. {
  277. hr = pUser->get_FullName (&bstrFullName);
  278. szFullName[0] = 0;
  279. if (hr == S_OK)
  280. {
  281. _tcsncpy (szFullName, bstrFullName, cch);
  282. szFullName[cch - 1] = 0;
  283. }
  284. }
  285. ExitHere:
  286. if (pUser)
  287. {
  288. pUser->Release();
  289. }
  290. if (bstrFullName)
  291. {
  292. SysFreeString (bstrFullName);
  293. }
  294. return hr;
  295. }
  296. LPTSTR AppendStringAndFree (LPTSTR szOld, LPTSTR szToAppend)
  297. {
  298. LPTSTR szNew;
  299. DWORD dwLen;
  300. dwLen = ((szOld == NULL) ? 0 : _tcslen (szOld)) + _tcslen (szToAppend) + 1;
  301. szNew = new TCHAR[dwLen * sizeof(TCHAR)];
  302. if (szNew == NULL)
  303. {
  304. goto ExitHere;
  305. }
  306. if (szOld)
  307. {
  308. _tcscpy (szNew, szOld);
  309. _tcscat (szNew, szToAppend);
  310. }
  311. else
  312. {
  313. _tcscpy (szNew, szToAppend);
  314. }
  315. ExitHere:
  316. if (szOld)
  317. {
  318. delete [] szOld;
  319. }
  320. return szNew;
  321. }
  322. void
  323. TsecCommandLine::ParseCommandLine (LPTSTR szCommand)
  324. {
  325. if (szCommand == NULL)
  326. {
  327. goto ExitHere;
  328. }
  329. //
  330. // Skip the first segment which is the executable itself
  331. //
  332. if (*szCommand == TEXT('\"'))
  333. {
  334. ++szCommand;
  335. while (*szCommand &&
  336. *szCommand != TEXT('\"'))
  337. {
  338. ++szCommand;
  339. }
  340. if (*szCommand == TEXT('\"'))
  341. {
  342. ++szCommand;
  343. }
  344. }
  345. else
  346. {
  347. while (
  348. *szCommand &&
  349. *szCommand != TEXT(' ') &&
  350. *szCommand != TEXT('\t') &&
  351. *szCommand != 0x0a &&
  352. *szCommand != 0x0d)
  353. {
  354. ++szCommand;
  355. }
  356. }
  357. while (*szCommand)
  358. {
  359. //
  360. // Search for / or - as the start of option
  361. //
  362. while (*szCommand &&
  363. *szCommand != TEXT('/') &&
  364. *szCommand != TEXT('-')
  365. )
  366. {
  367. szCommand++;
  368. }
  369. if (*szCommand == 0)
  370. {
  371. break;
  372. }
  373. ++szCommand;
  374. //
  375. // -h, -H, -? means help
  376. //
  377. if (*szCommand == TEXT('h') ||
  378. *szCommand == TEXT('H') ||
  379. *szCommand == TEXT('?'))
  380. {
  381. ++szCommand;
  382. if (*szCommand == TEXT(' ') ||
  383. *szCommand == TEXT('\t') ||
  384. *szCommand == 0x0a ||
  385. *szCommand == 0x0 ||
  386. *szCommand == 0x0d)
  387. {
  388. m_fShowHelp = TRUE;
  389. }
  390. else
  391. {
  392. m_fError = TRUE;
  393. m_fShowHelp = TRUE;
  394. }
  395. }
  396. //
  397. // -v or -V followed by white space means validating only
  398. //
  399. else if (*szCommand == TEXT('v') ||
  400. *szCommand == TEXT('V'))
  401. {
  402. ++szCommand;
  403. if (*szCommand == TEXT(' ') ||
  404. *szCommand == TEXT('\t') ||
  405. *szCommand == 0x0a ||
  406. *szCommand == 0x0 ||
  407. *szCommand == 0x0d)
  408. {
  409. m_fValidateOnly = TRUE;
  410. }
  411. else
  412. {
  413. m_fError = TRUE;
  414. m_fShowHelp = TRUE;
  415. }
  416. }
  417. //
  418. // -u, -U means to validate domain user account
  419. //
  420. else if (*szCommand == TEXT('u') ||
  421. *szCommand == TEXT('U'))
  422. {
  423. ++szCommand;
  424. if (*szCommand == TEXT(' ') ||
  425. *szCommand == TEXT('\t') ||
  426. *szCommand == 0x0a ||
  427. *szCommand == 0x0 ||
  428. *szCommand == 0x0d)
  429. {
  430. m_fValidateDU = TRUE;
  431. }
  432. else
  433. {
  434. m_fError = TRUE;
  435. m_fShowHelp = TRUE;
  436. }
  437. }
  438. //
  439. // -d or -D followed by white space means dump current configuration
  440. //
  441. else if (*szCommand == TEXT('d') ||
  442. *szCommand == TEXT('D'))
  443. {
  444. ++szCommand;
  445. if (*szCommand == TEXT(' ') ||
  446. *szCommand == TEXT('\t') ||
  447. *szCommand == 0x0a ||
  448. *szCommand == 0x0 ||
  449. *szCommand == 0x0d)
  450. {
  451. m_fDumpConfig = TRUE;
  452. }
  453. else
  454. {
  455. m_fError = TRUE;
  456. m_fShowHelp = TRUE;
  457. }
  458. }
  459. //
  460. // -f is followed by a xml file name
  461. //
  462. else if (*szCommand == TEXT('f') ||
  463. *szCommand == TEXT('F'))
  464. {
  465. ++szCommand;
  466. // skip white spaces
  467. while (*szCommand != 0 && (
  468. *szCommand == TEXT(' ') ||
  469. *szCommand == TEXT('\t') ||
  470. *szCommand == 0x0a ||
  471. *szCommand == 0x0d))
  472. {
  473. ++szCommand;
  474. }
  475. if (*szCommand == 0)
  476. {
  477. // no file name specified for -f, error
  478. m_fError = TRUE;
  479. }
  480. else
  481. {
  482. LPTSTR szBeg;
  483. int cch;
  484. szBeg = szCommand;
  485. cch = 0;
  486. // A quote means file name might contain space
  487. // search until the matchint quote of end
  488. if (*szCommand == TEXT('\"'))
  489. {
  490. ++szCommand;
  491. while (*szCommand != 0 &&
  492. *szCommand != TEXT('\"'))
  493. {
  494. ++szCommand;
  495. ++cch;
  496. }
  497. }
  498. else
  499. {
  500. while (*szCommand != 0 &&
  501. *szCommand != TEXT(' ') &&
  502. *szCommand != TEXT('\t') &&
  503. *szCommand != TEXT('\r') &&
  504. *szCommand != TEXT('\n'))
  505. {
  506. ++szCommand;
  507. ++cch;
  508. }
  509. }
  510. if (cch == 0)
  511. {
  512. m_fError = TRUE;
  513. }
  514. else
  515. {
  516. m_szInFile = new TCHAR[cch+1];
  517. if (m_szInFile != NULL)
  518. {
  519. memcpy (m_szInFile, szBeg, cch * sizeof(TCHAR));
  520. m_szInFile[cch] = 0;
  521. }
  522. }
  523. }
  524. }
  525. else if(*szCommand)
  526. {
  527. m_fError = TRUE;
  528. ++szCommand;
  529. }
  530. }
  531. ExitHere:
  532. return;
  533. }
  534. int _cdecl wmain( void )
  535. {
  536. HRESULT hr = S_OK;
  537. BOOL bUninit = FALSE;
  538. CXMLParser parser;
  539. CXMLUser * pCurUser = NULL, *pNextUser;
  540. CMMCManagement * pMmc = NULL;
  541. BOOL bNoMerge, bRemove, bPID;
  542. TCHAR szBufDU[256];
  543. TCHAR szBufFN[256];
  544. TCHAR szBufAddr[128];
  545. DWORD dwPID;
  546. HWND hwndDump = NULL;
  547. HANDLE hLogFile = INVALID_HANDLE_VALUE;
  548. BOOL bRecordedError = FALSE, bValidUser;
  549. TsecCommandLine cmd (GetCommandLine ());
  550. CXMLLine * pCurLine = NULL, * pNextLine;
  551. //
  552. // Create a dump window so that tlist.exe will report a title
  553. //
  554. if (LoadString (
  555. GetModuleHandle(NULL),
  556. IDS_PRODUCTNAME,
  557. szBufFN,
  558. sizeof(szBufFN)/sizeof(TCHAR)))
  559. {
  560. hwndDump = CreateWindow (
  561. TEXT("STATIC"),
  562. szBufFN,
  563. 0,
  564. 0, 0, 0, 0,
  565. NULL,
  566. NULL,
  567. NULL,
  568. NULL
  569. );
  570. }
  571. //
  572. // Check the command line options
  573. //
  574. if (cmd.FError () ||
  575. cmd.FShowHelp () ||
  576. !cmd.FDumpConfig () && !cmd.FHasFile () ||
  577. cmd.FDumpConfig () && cmd.FHasFile () ||
  578. ( cmd.FValidateOnly () || cmd.FValidateUser () ) && !cmd.FHasFile ()
  579. )
  580. {
  581. cmd.PrintUsage();
  582. goto ExitHere;
  583. }
  584. hr = CoInitializeEx (
  585. NULL,
  586. COINIT_MULTITHREADED
  587. );
  588. if (FAILED (hr))
  589. {
  590. goto ExitHere;
  591. }
  592. bUninit = TRUE;
  593. //
  594. // Prepare the MMC component
  595. //
  596. pMmc = new CMMCManagement ();
  597. if (pMmc == NULL)
  598. {
  599. hr = TSECERR_NOMEM;
  600. goto ExitHere;
  601. }
  602. hr = pMmc->GetMMCData ();
  603. if (FAILED(hr))
  604. {
  605. goto ExitHere;
  606. }
  607. //
  608. // Dump the current config if this option was present
  609. //
  610. if ( cmd.FDumpConfig() )
  611. {
  612. hr = pMmc->DisplayMMCData ();
  613. goto ExitHere;
  614. }
  615. //
  616. // Set the XML file name and parse it, report error if any
  617. //
  618. hr = parser.SetXMLFile (cmd.GetInFileName ());
  619. if (FAILED (hr))
  620. {
  621. goto ExitHere;
  622. }
  623. hr = parser.Parse ();
  624. // Report parsing error if any
  625. if (hr == TSECERR_INVALFILEFORMAT)
  626. {
  627. hr = parser.ReportParsingError ();
  628. goto ExitHere;
  629. }
  630. if (FAILED (hr))
  631. {
  632. goto ExitHere;
  633. }
  634. //
  635. // Create the log file for reporting errors during
  636. // MMC processing
  637. //
  638. hLogFile = CreateFile (
  639. _T("tsecimp.log"),
  640. GENERIC_WRITE,
  641. 0,
  642. NULL,
  643. CREATE_ALWAYS,
  644. FILE_ATTRIBUTE_NORMAL,
  645. NULL
  646. );
  647. if (hLogFile == INVALID_HANDLE_VALUE)
  648. {
  649. hr = HRESULT_FROM_WIN32(GetLastError());
  650. goto ExitHere;
  651. }
  652. //
  653. // Loop through each user and device, based on the user's
  654. // request, add or remove lines
  655. //
  656. hr = parser.GetFirstUser (&pCurUser);
  657. if (FAILED(hr))
  658. {
  659. goto ExitHere;
  660. }
  661. while (pCurUser != NULL)
  662. {
  663. if (FAILED(hr = pCurUser->GetDomainUser(
  664. szBufDU, sizeof(szBufDU)/sizeof(TCHAR))) ||
  665. FAILED(hr = pCurUser->GetFriendlyName(
  666. szBufFN, sizeof(szBufFN)/sizeof(TCHAR))))
  667. {
  668. goto ExitHere;
  669. }
  670. bValidUser = TRUE;
  671. if (cmd.FValidateUser())
  672. {
  673. hr = IsValidDomainUser(
  674. szBufDU,
  675. szBufAddr, // Borrowing szBufAddr for returning full name
  676. sizeof(szBufAddr) / sizeof(TCHAR)
  677. );
  678. if (FAILED(hr))
  679. {
  680. goto ExitHere;
  681. }
  682. // Not a valid domain user, report it
  683. if (hr == S_FALSE)
  684. {
  685. // domain user <%s> is invalid
  686. ReportSz1 (hLogFile, IDS_INVALIDUSER, szBufDU);
  687. bRecordedError = TRUE;
  688. bValidUser = FALSE;
  689. }
  690. if (szBufFN[0] == 0)
  691. {
  692. if (szBufAddr[0] != 0)
  693. {
  694. // Got a friendly name from DS, use it
  695. _tcscpy (szBufFN, szBufAddr);
  696. }
  697. }
  698. }
  699. // Still got no friendly name? use the domain user name
  700. if (szBufFN[0] == 0)
  701. {
  702. _tcscpy (szBufFN, szBufDU);
  703. }
  704. hr = pCurUser->IsNoMerge (&bNoMerge);
  705. if (FAILED(hr))
  706. {
  707. goto ExitHere;
  708. }
  709. if (bNoMerge && !cmd.FValidateOnly())
  710. {
  711. hr = pMmc->RemoveLinesForUser(szBufDU);
  712. if (FAILED(hr))
  713. {
  714. goto ExitHere;
  715. }
  716. }
  717. //
  718. // Loop through each line, add or remove the device
  719. //
  720. if (pCurLine)
  721. {
  722. delete pCurLine;
  723. }
  724. hr = pCurUser->GetFirstLine (&pCurLine);
  725. if (FAILED(hr))
  726. {
  727. goto ExitHere;
  728. }
  729. while (pCurLine != NULL)
  730. {
  731. if (FAILED(hr = pCurLine->IsRemove(&bRemove)) ||
  732. FAILED(hr = pCurLine->IsPermanentID(&bPID)))
  733. {
  734. goto ExitHere;
  735. }
  736. if (bPID)
  737. {
  738. hr = pCurLine->GetPermanentID(&dwPID);
  739. }
  740. else
  741. {
  742. hr = pCurLine->GetAddress(
  743. szBufAddr,
  744. sizeof(szBufAddr)/sizeof(TCHAR)
  745. );
  746. }
  747. if (FAILED(hr))
  748. {
  749. goto ExitHere;
  750. }
  751. if (!cmd.FValidateOnly() && bValidUser)
  752. {
  753. if (bRemove)
  754. {
  755. if (bPID)
  756. {
  757. hr = pMmc->RemoveLinePIDForUser (
  758. dwPID,
  759. szBufDU
  760. );
  761. }
  762. else
  763. {
  764. hr = pMmc->RemoveLineAddrForUser (
  765. szBufAddr,
  766. szBufDU
  767. );
  768. }
  769. }
  770. else
  771. {
  772. if (bPID)
  773. {
  774. hr = pMmc->AddLinePIDForUser (
  775. dwPID,
  776. szBufDU,
  777. szBufFN
  778. );
  779. }
  780. else
  781. {
  782. hr = pMmc->AddLineAddrForUser (
  783. szBufAddr,
  784. szBufDU,
  785. szBufFN
  786. );
  787. }
  788. }
  789. }
  790. else
  791. {
  792. if (bPID)
  793. {
  794. hr = pMmc->IsValidPID (dwPID);
  795. }
  796. else
  797. {
  798. hr = pMmc->IsValidAddress (szBufAddr);
  799. }
  800. }
  801. if( hr == S_FALSE || hr == TSECERR_DEVLOCALONLY)
  802. {
  803. // An invalid permanent ID or address is given
  804. // report the error and quit
  805. TCHAR szText[256];
  806. CIds IdsTitle (IDS_PRODUCTNAME);
  807. if ( IdsTitle.StringFound () )
  808. {
  809. szText[0] = 0;
  810. if (bPID)
  811. {
  812. CIds IdsError (TSECERR_DEVLOCALONLY ? IDS_LOCALONLYPID : IDS_INVALPID);
  813. if ( IdsError.StringFound () )
  814. {
  815. wsprintf (szText, IdsError.GetString (), dwPID);
  816. }
  817. }
  818. else if (!bPID)
  819. {
  820. CIds IdsError (TSECERR_DEVLOCALONLY ? IDS_LOCALONLYADDR : IDS_INVALADDR);
  821. if ( IdsError.StringFound () )
  822. {
  823. wsprintf (szText, IdsError.GetString (), szBufAddr);
  824. }
  825. }
  826. if (hLogFile != NULL && hLogFile != INVALID_HANDLE_VALUE)
  827. {
  828. char szAnsiBuf[256];
  829. DWORD dwNumOfBytesWritten;
  830. WideCharToMultiByte (
  831. CP_ACP,
  832. 0,
  833. szText,
  834. -1,
  835. szAnsiBuf,
  836. sizeof(szAnsiBuf),
  837. NULL,
  838. NULL
  839. );
  840. lstrcatA (szAnsiBuf, "\n");
  841. WriteFile (
  842. hLogFile,
  843. szAnsiBuf,
  844. lstrlenA (szAnsiBuf),
  845. &dwNumOfBytesWritten,
  846. NULL
  847. );
  848. }
  849. else
  850. {
  851. MessagePrint (szText, IdsTitle.GetString ());
  852. }
  853. }
  854. bRecordedError = TRUE;
  855. hr = S_OK;
  856. }
  857. else if(FAILED(hr))
  858. {
  859. goto ExitHere;
  860. }
  861. hr = pCurLine->GetNextLine (&pNextLine);
  862. if (FAILED(hr))
  863. {
  864. goto ExitHere;
  865. }
  866. delete pCurLine;
  867. pCurLine = pNextLine;
  868. }
  869. hr = pCurUser->GetNextUser (&pNextUser);
  870. if (FAILED(hr))
  871. {
  872. goto ExitHere;
  873. }
  874. delete pCurUser;
  875. pCurUser = pNextUser;
  876. }
  877. // If error happend, we aready exited, reset warnings
  878. hr = S_OK;
  879. // We are done if we are asked to do validating only
  880. if (bRecordedError)
  881. {
  882. MessagePrintIds (IDS_HASERROR);
  883. }
  884. else if (cmd.FValidateOnly())
  885. {
  886. MessagePrintIds (IDS_VALIDSUCCESS);
  887. }
  888. else
  889. {
  890. MessagePrintIds (IDS_FINSUCCESS);
  891. }
  892. ExitHere:
  893. //
  894. // Report error if any here
  895. //
  896. if(FAILED(hr))
  897. {
  898. ReportError (NULL, hr);
  899. }
  900. if (hwndDump)
  901. {
  902. DestroyWindow (hwndDump);
  903. }
  904. if (hLogFile != INVALID_HANDLE_VALUE)
  905. {
  906. CloseHandle (hLogFile);
  907. }
  908. if (pCurLine)
  909. {
  910. delete pCurLine;
  911. }
  912. if (pCurUser)
  913. {
  914. delete pCurUser;
  915. }
  916. if (pMmc)
  917. {
  918. delete pMmc;
  919. }
  920. parser.Release();
  921. if (bUninit)
  922. {
  923. CoUninitialize ();
  924. }
  925. return 0;
  926. }
  927. void ReportError (
  928. HANDLE hFile,
  929. HRESULT hr
  930. )
  931. {
  932. TCHAR szTitle[128];
  933. TCHAR szBuf[512];
  934. HINSTANCE hModule = GetModuleHandle (NULL);
  935. if (LoadString (
  936. hModule,
  937. IDS_PRODUCTNAME,
  938. szTitle,
  939. sizeof(szTitle)/sizeof(TCHAR)
  940. ) == 0)
  941. {
  942. goto ExitHere;
  943. }
  944. // Is this our own error
  945. if (HRESULT_FACILITY(hr) == FACILITY_TSEC_CODE)
  946. {
  947. if (FormatMessage (
  948. FORMAT_MESSAGE_FROM_HMODULE,
  949. hModule,
  950. HRESULT_CODE(hr),
  951. 0,
  952. szBuf,
  953. sizeof(szBuf)/sizeof(TCHAR),
  954. NULL
  955. ) == 0)
  956. {
  957. goto ExitHere;
  958. }
  959. }
  960. // Is this TAPI error?
  961. else if ((hr < 0 && hr > -100) || HRESULT_FACILITY(hr) == 0)
  962. {
  963. hModule = LoadLibrary (TEXT("TAPIUI.DLL"));
  964. if (hModule == NULL)
  965. {
  966. goto ExitHere;
  967. }
  968. if (FormatMessage (
  969. FORMAT_MESSAGE_FROM_HMODULE,
  970. hModule,
  971. TAPIERROR_FORMATMESSAGE(hr),
  972. 0,
  973. szBuf,
  974. sizeof(szBuf)/sizeof(TCHAR),
  975. NULL
  976. ) == 0)
  977. {
  978. FreeLibrary (hModule);
  979. goto ExitHere;
  980. }
  981. FreeLibrary (hModule);
  982. }
  983. // Assume system error
  984. else
  985. {
  986. if (FormatMessage (
  987. FORMAT_MESSAGE_FROM_SYSTEM,
  988. NULL,
  989. HRESULT_CODE(hr),
  990. 0,
  991. szBuf,
  992. sizeof(szBuf)/sizeof(TCHAR),
  993. NULL
  994. ) == 0)
  995. {
  996. goto ExitHere;
  997. }
  998. }
  999. if (hFile == NULL || hFile == INVALID_HANDLE_VALUE)
  1000. {
  1001. MessagePrint (szBuf, szTitle);
  1002. }
  1003. else
  1004. {
  1005. char szAnsiBuf[1024];
  1006. DWORD dwNumOfBytesWritten;
  1007. WideCharToMultiByte (
  1008. CP_ACP,
  1009. 0,
  1010. szBuf,
  1011. -1,
  1012. szAnsiBuf,
  1013. sizeof(szAnsiBuf),
  1014. NULL,
  1015. NULL
  1016. );
  1017. lstrcatA (szAnsiBuf, "\n");
  1018. WriteFile (
  1019. hFile,
  1020. szAnsiBuf,
  1021. lstrlenA (szAnsiBuf),
  1022. &dwNumOfBytesWritten,
  1023. NULL
  1024. );
  1025. }
  1026. ExitHere:
  1027. return;
  1028. }