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.

794 lines
19 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. util.c
  5. Abstract:
  6. This file implements utility functions.
  7. Environment:
  8. WIN32 User Mode
  9. Author:
  10. Wesley Witt (wesw) 17-Feb-1996
  11. --*/
  12. #include "wizard.h"
  13. #pragma hdrstop
  14. PLATFORM_INFO Platforms[] =
  15. {
  16. { TEXT("Windows NT x86"), TEXT("i386"), 0, FAX_INSTALLED_PLATFORM_X86, NULL, FALSE },
  17. { TEXT("Windows NT Alpha_AXP"), TEXT("alpha"), 0, FAX_INSTALLED_PLATFORM_ALPHA, NULL, FALSE },
  18. };
  19. DWORD CountPlatforms = (sizeof(Platforms)/sizeof(PLATFORM_INFO));
  20. // Sequentially enumerate platforms
  21. WORD EnumPlatforms[4];
  22. typedef struct _STRING_TABLE {
  23. DWORD ResourceId;
  24. BOOL UseTitle;
  25. LPTSTR String;
  26. } STRING_TABLE, *PSTRING_TABLE;
  27. static STRING_TABLE StringTable[] =
  28. {
  29. { IDS_TITLE_WKS, FALSE, NULL },
  30. { IDS_TITLE_SRV, FALSE, NULL },
  31. { IDS_TITLE_PP, FALSE, NULL },
  32. { IDS_TITLE_RA, FALSE, NULL },
  33. { IDS_COPYING, FALSE, NULL },
  34. { IDS_COPY_WAITMSG, TRUE, NULL },
  35. { IDS_COULD_NOT_DELETE_FAX_PRINTER, FALSE, NULL },
  36. { IDS_COULD_NOT_DELETE_FILES, FALSE, NULL },
  37. { IDS_CREATING_FAXPRT, FALSE, NULL },
  38. { IDS_CREATING_GROUPS, FALSE, NULL },
  39. { IDS_DEFAULT_PRINTER, FALSE, NULL },
  40. { IDS_DEFAULT_SHARE, FALSE, NULL },
  41. { IDS_DELETE_WAITMSG, TRUE, NULL },
  42. { IDS_DELETING, FALSE, NULL },
  43. { IDS_DELETING_FAX_PRINTERS, FALSE, NULL },
  44. { IDS_DELETING_FAX_SERVICE, FALSE, NULL },
  45. { IDS_DELETING_GROUPS, FALSE, NULL },
  46. { IDS_DELETING_REGISTRY, FALSE, NULL },
  47. { IDS_DEVICEINIT_LABEL01, TRUE, NULL },
  48. { IDS_ERR_TITLE, TRUE, NULL },
  49. { IDS_FAXCLIENT_SETUP, FALSE, NULL },
  50. { IDS_FAX_PRINTER_PENDING_DELETION, FALSE, NULL },
  51. { IDS_FAX_SHARE_COMMENT, FALSE, NULL },
  52. { IDS_INBOUND_DIR, FALSE, NULL },
  53. { IDS_INIT_TAPI, FALSE, NULL },
  54. { IDS_INSTALLING_FAXSVC, FALSE, NULL },
  55. { IDS_INVALID_DIRECTORY, FALSE, NULL },
  56. { IDS_INVALID_LOCAL_PRINTER_NAME, FALSE, NULL },
  57. { IDS_LABEL01_LAST, TRUE, NULL },
  58. { IDS_LABEL02_LAST, TRUE, NULL },
  59. { IDS_LABEL_PRINTERNAME, FALSE, NULL },
  60. { IDS_LASTUNINSTALL_LABEL01, TRUE, NULL },
  61. { IDS_NO_MODEM, FALSE, NULL },
  62. { IDS_QUERY_CANCEL, FALSE, NULL },
  63. { IDS_QUERY_UNINSTALL, TRUE, NULL },
  64. { IDS_SETTING_REGISTRY, FALSE, NULL },
  65. { IDS_SHARE_FAX_PRINTER, FALSE, NULL },
  66. { IDS_STARTING_FAXSVC, FALSE, NULL },
  67. { IDS_TITLE, TRUE, NULL },
  68. { IDS_WELCOME_LABEL01, TRUE, NULL },
  69. { IDS_WELCOME_LABEL02, TRUE, NULL },
  70. { IDS_WRN_SPOOLER, FALSE, NULL },
  71. { IDS_WRN_TITLE, TRUE, NULL },
  72. { IDS_PRINTER_NAME, FALSE, NULL },
  73. { IDS_CSID, FALSE, NULL },
  74. { IDS_TSID, FALSE, NULL },
  75. { IDS_DEST_DIR, FALSE, NULL },
  76. { IDS_PROFILE, FALSE, NULL },
  77. { IDS_ACCOUNTNAME, FALSE, NULL },
  78. { IDS_PASSWORD, FALSE, NULL },
  79. { IDS_NO_TAPI_DEVICES, FALSE, NULL },
  80. { IDS_USER_MUST_BE_ADMIN, TRUE, NULL },
  81. { IDS_COULD_NOT_INSTALL_FAX_SERVICE, FALSE, NULL },
  82. { IDS_COULD_NOT_START_FAX_SERVICE, FALSE, NULL },
  83. { IDS_COULD_NOT_CREATE_PRINTER, FALSE, NULL },
  84. { IDS_PERMISSION_CREATE_PRINTER, FALSE, NULL },
  85. { IDS_COULD_SET_REG_DATA, FALSE, NULL },
  86. { IDS_INVALID_USER, FALSE, NULL },
  87. { IDS_INVALID_USER_NAME, FALSE, NULL },
  88. { IDS_INVALID_AREA_CODE, FALSE, NULL },
  89. { IDS_INVALID_PHONE_NUMBER, FALSE, NULL },
  90. { IDS_ROUTING_REQUIRED, FALSE, NULL },
  91. { IDS_COULD_NOT_COPY_FILES, FALSE, NULL },
  92. { IDS_CANT_USE_FAX_PRINTER, FALSE, NULL },
  93. { IDS_CANT_SET_SERVICE_ACCOUNT, FALSE, NULL },
  94. { IDS_EXCHANGE_IS_RUNNING, FALSE, NULL },
  95. { IDS_DEFAULT_PRINTER_NAME, FALSE, NULL },
  96. { IDS_INSTALLING_EXCHANGE, FALSE, NULL },
  97. { IDS_351_MODEM, FALSE, NULL },
  98. { IDS_LARGEFONTNAME, FALSE, NULL },
  99. { IDS_LARGEFONTSIZE, FALSE, NULL },
  100. { IDS_NO_CLASS1, TRUE, NULL },
  101. { IDS_UAA_MODE, FALSE, NULL },
  102. { IDS_UAA_PRINTER_NAME, FALSE, NULL },
  103. { IDS_UAA_FAX_PHONE, FALSE, NULL },
  104. { IDS_UAA_DEST_PROFILENAME, FALSE, NULL },
  105. { IDS_UAA_ROUTE_PROFILENAME, FALSE, NULL },
  106. { IDS_UAA_PLATFORM_LIST, FALSE, NULL },
  107. { IDS_UAA_DEST_PRINTERLIST, FALSE, NULL },
  108. { IDS_UAA_ACCOUNT_NAME, FALSE, NULL },
  109. { IDS_UAA_PASSWORD, FALSE, NULL },
  110. { IDS_UAA_DEST_DIRPATH, FALSE, NULL },
  111. { IDS_UAA_SERVER_NAME, FALSE, NULL },
  112. { IDS_UAA_SENDER_NAME, FALSE, NULL },
  113. { IDS_UAA_SENDER_FAX_AREA_CODE, FALSE, NULL },
  114. { IDS_UAA_SENDER_FAX_NUMBER, FALSE, NULL }
  115. };
  116. #define CountStringTable (sizeof(StringTable)/sizeof(STRING_TABLE))
  117. VOID
  118. SetTitlesInStringTable(
  119. VOID
  120. )
  121. {
  122. DWORD i;
  123. TCHAR Buffer[1024];
  124. DWORD Index = 0;
  125. for (i=0; i<CountStringTable; i++) {
  126. if (StringTable[i].UseTitle) {
  127. if (LoadString(
  128. FaxWizModuleHandle,
  129. StringTable[i].ResourceId,
  130. Buffer,
  131. sizeof(Buffer)
  132. ))
  133. {
  134. if (StringTable[i].String) {
  135. MemFree( StringTable[i].String );
  136. }
  137. StringTable[i].String = (LPTSTR) MemAlloc( StringSize( Buffer ) + 256 );
  138. if (StringTable[i].String) {
  139. switch (RequestedSetupType) {
  140. case SETUP_TYPE_SERVER:
  141. Index = 1;
  142. break;
  143. case SETUP_TYPE_WORKSTATION:
  144. Index = 0;
  145. break;
  146. case SETUP_TYPE_CLIENT:
  147. Index = 2;
  148. break;
  149. case SETUP_TYPE_POINT_PRINT:
  150. Index = 2;
  151. break;
  152. case SETUP_TYPE_REMOTE_ADMIN:
  153. Index = 3;
  154. break;
  155. }
  156. _stprintf( StringTable[i].String, Buffer, StringTable[Index].String );
  157. }
  158. }
  159. }
  160. }
  161. }
  162. VOID
  163. InitializeStringTable(
  164. VOID
  165. )
  166. {
  167. DWORD i;
  168. TCHAR Buffer[512];
  169. SYSTEM_INFO SystemInfo;
  170. GetSystemInfo( &SystemInfo );
  171. switch (SystemInfo.wProcessorArchitecture) {
  172. case PROCESSOR_ARCHITECTURE_INTEL:
  173. _stprintf(ThisPlatformName, TEXT("i386") );
  174. break;
  175. case PROCESSOR_ARCHITECTURE_ALPHA:
  176. _stprintf(ThisPlatformName, TEXT("alpha") );
  177. break;
  178. case PROCESSOR_ARCHITECTURE_MIPS:
  179. _stprintf(ThisPlatformName, TEXT("mips") );
  180. break;
  181. case PROCESSOR_ARCHITECTURE_PPC:
  182. _stprintf(ThisPlatformName, TEXT("ppc") );
  183. break;
  184. default:
  185. DebugPrint(( TEXT("Unsupported platform!") ));
  186. break;
  187. }
  188. for (i=0; i<CountStringTable; i++) {
  189. if (LoadString(
  190. FaxWizModuleHandle,
  191. StringTable[i].ResourceId,
  192. Buffer,
  193. sizeof(Buffer)
  194. )) {
  195. StringTable[i].String = (LPTSTR) MemAlloc( StringSize( Buffer ) + 256 );
  196. if (!StringTable[i].String) {
  197. StringTable[i].String = TEXT("");
  198. } else {
  199. _tcscpy( StringTable[i].String, Buffer );
  200. }
  201. } else {
  202. StringTable[i].String = TEXT("");
  203. }
  204. }
  205. SetTitlesInStringTable();
  206. }
  207. LPTSTR
  208. GetString(
  209. DWORD ResourceId
  210. )
  211. {
  212. DWORD i;
  213. for (i=0; i<CountStringTable; i++) {
  214. if (StringTable[i].ResourceId == ResourceId) {
  215. return StringTable[i].String;
  216. }
  217. }
  218. return NULL;
  219. }
  220. int
  221. PopUpMsg(
  222. HWND hwnd,
  223. DWORD ResourceId,
  224. BOOL Error,
  225. DWORD Type
  226. )
  227. {
  228. return MessageBox(
  229. hwnd,
  230. GetString( ResourceId ),
  231. GetString( Error ? IDS_ERR_TITLE : IDS_WRN_TITLE ),
  232. MB_SETFOREGROUND | (Error ? MB_ICONEXCLAMATION : MB_ICONINFORMATION) | (Type == 0 ? MB_OK : Type)
  233. );
  234. }
  235. int
  236. PopUpMsgFmt(
  237. HWND hwnd,
  238. DWORD ResourceId,
  239. BOOL Error,
  240. DWORD Type,
  241. ...
  242. )
  243. {
  244. TCHAR buf[1024];
  245. va_list arg_ptr;
  246. va_start(arg_ptr, Type);
  247. _vsntprintf( buf, sizeof(buf), GetString( ResourceId ), arg_ptr );
  248. return MessageBox(
  249. hwnd,
  250. buf,
  251. GetString( Error ? IDS_ERR_TITLE : IDS_WRN_TITLE ),
  252. MB_SETFOREGROUND | (Error ? MB_ICONEXCLAMATION : MB_ICONINFORMATION) | (Type == 0 ? MB_OK : Type)
  253. );
  254. }
  255. LPTSTR
  256. GetProductName(
  257. VOID
  258. )
  259. {
  260. DWORD Index;
  261. switch (RequestedSetupType) {
  262. case SETUP_TYPE_SERVER:
  263. Index = 1;
  264. break;
  265. case SETUP_TYPE_WORKSTATION:
  266. Index = 0;
  267. break;
  268. case SETUP_TYPE_CLIENT:
  269. Index = 2;
  270. break;
  271. case SETUP_TYPE_POINT_PRINT:
  272. Index = 2;
  273. break;
  274. case SETUP_TYPE_REMOTE_ADMIN:
  275. Index = 3;
  276. break;
  277. }
  278. return StringTable[Index].String;
  279. }
  280. VOID
  281. SetWizPageTitle(
  282. HWND hWnd
  283. )
  284. {
  285. PropSheet_SetTitle( hWnd, 0, GetProductName() );
  286. }
  287. LPTSTR
  288. RemoveLastNode(
  289. LPTSTR Path
  290. )
  291. {
  292. DWORD i;
  293. if (Path == NULL || Path[0] == 0) {
  294. return Path;
  295. }
  296. i = _tcslen(Path)-1;
  297. if (Path[i] == TEXT('\\')) {
  298. Path[i] = 0;
  299. i -= 1;
  300. }
  301. for (; i>0; i--) {
  302. if (Path[i] == TEXT('\\')) {
  303. Path[i+1] = 0;
  304. break;
  305. }
  306. }
  307. return Path;
  308. }
  309. DWORD
  310. ExtraChars(
  311. HWND hwnd,
  312. LPTSTR TextBuffer
  313. )
  314. {
  315. RECT Rect;
  316. SIZE Size;
  317. HDC hdc;
  318. DWORD len;
  319. HFONT hFont;
  320. INT Fit;
  321. hdc = GetDC( hwnd );
  322. GetWindowRect( hwnd, &Rect );
  323. hFont = (HFONT)SendMessage( hwnd, WM_GETFONT, 0, 0 );
  324. if (hFont != NULL) {
  325. SelectObject( hdc, hFont );
  326. }
  327. len = _tcslen( TextBuffer );
  328. if (!GetTextExtentExPoint(
  329. hdc,
  330. TextBuffer,
  331. len,
  332. Rect.right - Rect.left,
  333. &Fit,
  334. NULL,
  335. &Size
  336. )) {
  337. //
  338. // can't determine the text extents so we return zero
  339. //
  340. Fit = len;
  341. }
  342. ReleaseDC( hwnd, hdc );
  343. if (Fit < (INT)len) {
  344. return len - Fit;
  345. }
  346. return 0;
  347. }
  348. LPTSTR
  349. CompactFileName(
  350. LPCTSTR FileNameIn,
  351. DWORD CharsToRemove
  352. )
  353. {
  354. LPTSTR start;
  355. LPTSTR FileName;
  356. DWORD FileNameLen;
  357. LPTSTR lastPart;
  358. DWORD lastPartLen;
  359. DWORD lastPartPos;
  360. LPTSTR midPart;
  361. DWORD midPartPos;
  362. if (! FileNameIn) {
  363. return NULL;
  364. }
  365. FileName = MemAlloc( (_tcslen( FileNameIn ) + 16) * sizeof(TCHAR) );
  366. if (! FileName) {
  367. return NULL;
  368. }
  369. _tcscpy( FileName, FileNameIn );
  370. FileNameLen = _tcslen(FileName);
  371. if (FileNameLen < CharsToRemove + 3) {
  372. // nothing to remove
  373. return FileName;
  374. }
  375. lastPart = _tcsrchr(FileName, TEXT('\\') );
  376. if (! lastPart) {
  377. // nothing to remove
  378. return FileName;
  379. }
  380. lastPartLen = _tcslen(lastPart);
  381. // temporary null-terminate FileName
  382. lastPartPos = lastPart - FileName;
  383. FileName[lastPartPos] = TEXT('\0');
  384. midPart = _tcsrchr(FileName, TEXT('\\') );
  385. // restore
  386. FileName[lastPartPos] = TEXT('\\');
  387. if (!midPart) {
  388. // nothing to remove
  389. return FileName;
  390. }
  391. midPartPos = midPart - FileName;
  392. if ( ((DWORD) (lastPart - midPart) ) >= (CharsToRemove + 3) ) {
  393. // found
  394. start = midPart+1;
  395. start[0] = start[1] = start[2] = TEXT('.');
  396. start += 3;
  397. _tcscpy(start, lastPart);
  398. start[lastPartLen] = TEXT('\0');
  399. return FileName;
  400. }
  401. do {
  402. FileName[midPartPos] = TEXT('\0');
  403. midPart = _tcsrchr(FileName, TEXT('\\') );
  404. // restore
  405. FileName[midPartPos] = TEXT('\\');
  406. if (!midPart) {
  407. // nothing to remove
  408. return FileName;
  409. }
  410. midPartPos = midPart - FileName;
  411. if ( (DWORD) ((lastPart - midPart) ) >= (CharsToRemove + 3) ) {
  412. // found
  413. start = midPart+1;
  414. start[0] = start[1] = start[2] = TEXT('.');
  415. start += 3;
  416. _tcscpy(start, lastPart);
  417. start[lastPartLen] = TEXT('\0');
  418. return FileName;
  419. }
  420. } while ( 1 );
  421. }
  422. VOID
  423. DoExchangeInstall(
  424. HWND hwnd
  425. )
  426. {
  427. //
  428. // always update the mapi service inf
  429. // so that the user can add the fax
  430. // service to their profile even if they
  431. // choose not to do so now.
  432. //
  433. AddFaxAbToMapiSvcInf();
  434. AddFaxXpToMapiSvcInf();
  435. InstallExchangeClientExtension(
  436. EXCHANGE_CLIENT_EXT_NAME,
  437. EXCHANGE_CLIENT_EXT_FILE,
  438. EXCHANGE_CONTEXT_MASK
  439. );
  440. if ((InstallMode & INSTALL_NEW) && WizData.UseExchange) {
  441. if (!MapiAvail) {
  442. //
  443. // the user wants to use exchange, but it has not
  444. // been installed yet. so lets install it!
  445. //
  446. WCHAR InstallCommand[256];
  447. STARTUPINFO si;
  448. PROCESS_INFORMATION pi;
  449. GetExchangeInstallCommand( InstallCommand );
  450. GetStartupInfo( &si );
  451. if (CreateProcessW( NULL, InstallCommand, NULL, NULL,
  452. FALSE, 0, NULL, NULL, &si, &pi )) {
  453. //
  454. // wait for the exchange install to finish
  455. //
  456. WaitForSingleObject( pi.hProcess, INFINITE );
  457. InitializeMapi();
  458. //
  459. // create a profile and add the fax address book
  460. //
  461. CreateDefaultMapiProfile( WizData.MapiProfile );
  462. InstallFaxAddressBook( hwnd, WizData.MapiProfile );
  463. InstallFaxTransport( WizData.MapiProfile );
  464. }
  465. } else {
  466. CreateDefaultMapiProfile( WizData.MapiProfile );
  467. if (!IsMapiServiceInstalled( WizData.MapiProfile, FAXAB_SERVICE_NAME )) {
  468. InstallFaxAddressBook( hwnd, WizData.MapiProfile );
  469. }
  470. if (!IsMapiServiceInstalled( WizData.MapiProfile, FAXXP_SERVICE_NAME )) {
  471. InstallFaxTransport( WizData.MapiProfile );
  472. }
  473. }
  474. //
  475. // check to see if exchange is running,
  476. // if is is then give the user a warning to restart it
  477. //
  478. if (IsExchangeRunning()) {
  479. PopUpMsg( hwnd, IDS_EXCHANGE_IS_RUNNING, FALSE, 0 );
  480. }
  481. }
  482. }
  483. BOOL
  484. CreateNetworkShare(
  485. LPTSTR Path,
  486. LPTSTR ShareName,
  487. LPTSTR Comment
  488. )
  489. {
  490. SHARE_INFO_2 ShareInfo;
  491. NET_API_STATUS rVal;
  492. TCHAR ExpandedPath[MAX_PATH*2];
  493. ExpandEnvironmentStrings( Path, ExpandedPath, sizeof(ExpandedPath) );
  494. ShareInfo.shi2_netname = ShareName;
  495. ShareInfo.shi2_type = STYPE_DISKTREE;
  496. ShareInfo.shi2_remark = Comment;
  497. ShareInfo.shi2_permissions = ACCESS_ALL;
  498. ShareInfo.shi2_max_uses = (DWORD) -1,
  499. ShareInfo.shi2_current_uses = (DWORD) -1;
  500. ShareInfo.shi2_path = ExpandedPath;
  501. ShareInfo.shi2_passwd = NULL;
  502. rVal = NetShareAdd(
  503. NULL,
  504. 2,
  505. (LPBYTE) &ShareInfo,
  506. NULL
  507. );
  508. return rVal == 0;
  509. }
  510. BOOL
  511. DeleteNetworkShare(
  512. LPTSTR ShareName
  513. )
  514. {
  515. NET_API_STATUS rVal;
  516. rVal = NetShareDel(
  517. NULL,
  518. ShareName,
  519. 0
  520. );
  521. return rVal == 0;
  522. }
  523. BOOL
  524. DeleteDirectoryTree(
  525. LPWSTR Root
  526. )
  527. {
  528. WCHAR FileName[MAX_PATH*2];
  529. WIN32_FIND_DATA FindData;
  530. HANDLE hFind;
  531. swprintf( FileName, L"%s\\*", Root );
  532. hFind = FindFirstFile( FileName, &FindData );
  533. if (hFind == INVALID_HANDLE_VALUE) {
  534. return FALSE;
  535. }
  536. do {
  537. if (FindData.cFileName[0] == L'.') {
  538. continue;
  539. }
  540. if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  541. DeleteDirectoryTree( FindData.cFileName );
  542. } else {
  543. MyDeleteFile( FindData.cFileName );
  544. }
  545. } while (FindNextFile( hFind, &FindData ));
  546. FindClose( hFind );
  547. RemoveDirectory( Root );
  548. return TRUE;
  549. }
  550. BOOL
  551. MyDeleteFile(
  552. LPWSTR FileName
  553. )
  554. {
  555. if (GetFileAttributes( FileName ) == 0xffffffff) {
  556. //
  557. // the file does not exists
  558. //
  559. return TRUE;
  560. }
  561. if (!DeleteFile( FileName )) {
  562. if (MoveFileEx( FileName, NULL, MOVEFILE_DELAY_UNTIL_REBOOT )) {
  563. RebootRequired = TRUE;
  564. return TRUE;
  565. } else {
  566. return FALSE;
  567. }
  568. } else {
  569. return TRUE;
  570. }
  571. }
  572. //
  573. // RafaelL: 4/3/97
  574. // this is a work-around for Setupapi!SetupSetPlatformPathOverride bug.
  575. // but this also can be useful for custom cross-platform layout.
  576. //
  577. BOOL
  578. PlatformOverride(
  579. LPTSTR ThisPlatformName, // "i386"
  580. LPTSTR Override, // "alpha"
  581. LPTSTR SourceRoot, // "foo\...\bar\i386\"
  582. LPTSTR Result // "foo\...\bar\alpha\"
  583. )
  584. {
  585. DWORD Len;
  586. DWORD Pos;
  587. LPTSTR LastPart;
  588. LPTSTR PlatformPart;
  589. BOOL IsBackSlashAtEnd = 0;
  590. if ( (!ThisPlatformName) || (!Override) || (!SourceRoot) || (!Result) ) {
  591. // don't do anything: don't break anybody.
  592. return TRUE;
  593. }
  594. _tcscpy( Result, SourceRoot );
  595. Len = _tcslen(Result);
  596. LastPart = _tcsrchr(Result, TEXT('\\') );
  597. if (!LastPart) {
  598. return FALSE;
  599. }
  600. Pos = LastPart - Result;
  601. if ( Pos == (Len - 1) ) {
  602. IsBackSlashAtEnd = 1;
  603. *LastPart = TEXT('\0');
  604. PlatformPart = _tcsrchr(Result, TEXT('\\') );
  605. if (!PlatformPart) {
  606. return FALSE;
  607. }
  608. }
  609. else {
  610. PlatformPart = LastPart;
  611. }
  612. PlatformPart++;
  613. if ( _tcsicmp( PlatformPart, ThisPlatformName) != 0 ) {
  614. return FALSE;
  615. }
  616. _tcscpy (PlatformPart, Override);
  617. Len = _tcslen(Result);
  618. if (IsBackSlashAtEnd) {
  619. Result[Len] = TEXT ('\\');
  620. Result[Len+1] = TEXT ('\0');
  621. }
  622. else {
  623. Result[Len] = TEXT ('\0');
  624. }
  625. return TRUE;
  626. }