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

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