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.

1039 lines
25 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // Copyright (c) 1997-1999 Microsoft Corporation
  4. // All rights reserved.
  5. //
  6. // File Name:
  7. // pathsup.c
  8. //
  9. // Description:
  10. // Some path support routines.
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "pch.h"
  14. static TCHAR g_szSetupMgrFileExtensions[MAX_PATH + 1] = _T("");
  15. //---------------------------------------------------------------------------
  16. //
  17. // Function: CleanTrailingSlashes
  18. //
  19. // Purpose: Cleans up trailing slashes off pathnames. This is a support
  20. // routine for ConcatenatePaths().
  21. //
  22. // Arguments:
  23. // LPTSTR lpBuffer - MAX_PATH buffer
  24. //
  25. // Returns: VOID
  26. //
  27. //---------------------------------------------------------------------------
  28. static VOID CleanTrailingSlashes(LPTSTR lpBuffer)
  29. {
  30. TCHAR *p = lpBuffer + lstrlen(lpBuffer) - 1;
  31. while ( p >= lpBuffer && *p == _T('\\') )
  32. *p-- = _T('\0');
  33. }
  34. //---------------------------------------------------------------------------
  35. //
  36. // Function: CleanLeadingSlashes
  37. //
  38. // Purpose: Removes leading slashes from the given string.
  39. //
  40. // Arguments:
  41. // LPTSTR lpStr - str to clean
  42. //
  43. // Returns:
  44. // A pointer to the character after the run of back-slashes.
  45. //
  46. //---------------------------------------------------------------------------
  47. static LPTSTR CleanLeadingSlashes(LPTSTR lpStr)
  48. {
  49. TCHAR *p=lpStr;
  50. while ( *p && *p == TEXT('\\') )
  51. p++;
  52. return p;
  53. }
  54. //---------------------------------------------------------------------------
  55. //
  56. // Function: ConcatenatePaths
  57. //
  58. // Purpose: This function cats path components together. It makes sure
  59. // that there are not multiple slashes separating each item, and
  60. // that there isn't a trailing back-slash.
  61. //
  62. // The last string passed must be NULL.
  63. //
  64. // Arguments:
  65. // LPTSTR lpBuffer - MAX_PATH buffer
  66. // ...
  67. //
  68. // Returns:
  69. // TRUE if all is ok
  70. // FALSE if resultant string is >= MAX_PATH chars
  71. //
  72. //---------------------------------------------------------------------------
  73. BOOL __cdecl ConcatenatePaths(LPTSTR lpBuffer, ...)
  74. {
  75. LPTSTR lpString;
  76. va_list arglist;
  77. HRESULT hrCat;
  78. va_start(arglist, lpBuffer);
  79. lpString = va_arg(arglist, LPTSTR);
  80. while ( lpString != NULL ) {
  81. if ( lstrlen(lpBuffer) + lstrlen(lpString) >= MAX_PATH )
  82. return FALSE;
  83. lpString = CleanLeadingSlashes(lpString);
  84. CleanTrailingSlashes(lpString);
  85. CleanTrailingSlashes(lpBuffer);
  86. if ( lpBuffer[0] ) {
  87. hrCat=StringCchCat(lpBuffer, MAX_PATH, _T("\\"));
  88. hrCat=StringCchCat(lpBuffer, MAX_PATH, lpString);
  89. } else {
  90. lstrcpyn(lpBuffer, lpString, MAX_PATH);
  91. }
  92. lpString = va_arg(arglist, LPTSTR);
  93. }
  94. va_end(arglist);
  95. return TRUE;
  96. }
  97. //---------------------------------------------------------------------------
  98. //
  99. // Function: ParseDriveLetterOrUnc
  100. //
  101. // Purpose: Will parse past the \\srv\share\ or D:\ and return a pointer
  102. // to the character after that mess.
  103. //
  104. // Returns: Pointer to the pathname 1 char past the volume descriptor,
  105. // NULL if errors. GetLastError() will be valid when NULL
  106. // is returned.
  107. //
  108. // Notes:
  109. // - Only pass in fully qualified pathnames. Use MyGetFullPath().
  110. //
  111. //---------------------------------------------------------------------------
  112. LPTSTR ParseDriveLetterOrUnc(LPTSTR lpFileName)
  113. {
  114. TCHAR *p=NULL;
  115. //
  116. // If path is of form \\srv\share\, get a pointer past the whole mess.
  117. //
  118. // Note we start at lpFileName+3 because "srv" (in this example) must
  119. // be at least 1 character.
  120. //
  121. if ( lpFileName[0] == _T('\\') && lpFileName[1] == _T('\\') ) {
  122. //
  123. // Move past the computer name
  124. //
  125. p = lpFileName + 2;
  126. while( *p != _T('\\') )
  127. {
  128. if( *p == _T('\0') )
  129. {
  130. SetLastError( ERROR_BAD_PATHNAME );
  131. return( NULL );
  132. }
  133. p++;
  134. }
  135. p++;
  136. //
  137. // Scan past the share name
  138. //
  139. while( *p != _T('\\') )
  140. {
  141. if( *p == _T('\0') )
  142. {
  143. SetLastError( ERROR_BAD_PATHNAME );
  144. return( NULL );
  145. }
  146. p++;
  147. }
  148. p++;
  149. }
  150. //
  151. // Get past the D:\ if path is of that form
  152. //
  153. if ( towupper(lpFileName[0]) >= _T('A') &&
  154. towupper(lpFileName[0]) <= _T('Z') &&
  155. lpFileName[1] == _T(':') &&
  156. lpFileName[2] == _T('\\') ) {
  157. p = lpFileName + 3;
  158. }
  159. //
  160. // If we never set *p, then the path is not in a valid form.
  161. //
  162. if ( p == NULL ) {
  163. SetLastError(ERROR_BAD_PATHNAME);
  164. return NULL;
  165. }
  166. return p;
  167. }
  168. //---------------------------------------------------------------------------
  169. //
  170. // Function: GetComputerNameFromUnc
  171. //
  172. // Purpose: To strip out the computer name from a full UNC path.
  173. //
  174. // Example: \\computername\sharename\dir1\dir2 would return
  175. // \\computername
  176. //
  177. // Arguments:
  178. //
  179. // szComputerName is assumed to be MAX_PATH length
  180. //
  181. // Returns: VOID
  182. //
  183. // Notes:
  184. // - Only pass in fully qualified pathnames. Use MyGetFullPath().
  185. //
  186. //---------------------------------------------------------------------------
  187. VOID
  188. GetComputerNameFromUnc( IN TCHAR *szFullUncPath,
  189. OUT TCHAR *szComputerName,
  190. IN DWORD cbSize) {
  191. TCHAR *pString;
  192. AssertMsg( szFullUncPath[0] == _T('\\') && szFullUncPath[1] == _T('\\'),
  193. "szFullUncPath is not a well formed net path" );
  194. lstrcpyn( szComputerName, szFullUncPath, cbSize );
  195. pString = &(szComputerName[2]);
  196. //
  197. // Scan past the computer name
  198. //
  199. while( *pString != _T('\\') )
  200. {
  201. if( *pString == _T('\0') )
  202. {
  203. AssertMsg( FALSE,
  204. "Bad UNC path");
  205. return;
  206. }
  207. pString++;
  208. }
  209. *pString = _T('\0');
  210. }
  211. //---------------------------------------------------------------------------
  212. //
  213. // Function: GetComputerAndShareNameFromUnc
  214. //
  215. // Purpose: To strip out the computer and share name from a full UNC path.
  216. //
  217. // Example: \\computername\sharename\dir1\dir2 would return
  218. // \\computername\sharename
  219. //
  220. // Arguments:
  221. //
  222. // szComputerAndShareName is assumed to be MAX_PATH length
  223. //
  224. // Returns: VOID
  225. //
  226. // Notes:
  227. // - Only pass in fully qualified pathnames. Use MyGetFullPath().
  228. //
  229. //---------------------------------------------------------------------------
  230. VOID
  231. GetComputerAndShareNameFromUnc( IN TCHAR *szFullUncPath,
  232. OUT TCHAR *szComputerAndShareName,
  233. IN DWORD cbSize) {
  234. TCHAR *pString;
  235. AssertMsg( szFullUncPath[0] == _T('\\') && szFullUncPath[1] == _T('\\'),
  236. "szFullUncPath is not a well formed net path");
  237. lstrcpyn( szComputerAndShareName, szFullUncPath, cbSize );
  238. pString = &(szComputerAndShareName[2]);
  239. //
  240. // Scan past the computer name
  241. //
  242. while( *pString != _T('\\') )
  243. {
  244. if( *pString == _T('\0') )
  245. {
  246. AssertMsg( FALSE,
  247. "Bad UNC path");
  248. return;
  249. }
  250. pString++;
  251. }
  252. pString++;
  253. //
  254. // Scan past the share name
  255. //
  256. while( *pString != _T('\\') )
  257. {
  258. if( *pString == _T('\0') )
  259. {
  260. //
  261. // already just the computer and share name so just return
  262. //
  263. return;
  264. }
  265. pString++;
  266. }
  267. *pString = _T('\0');
  268. }
  269. //---------------------------------------------------------------------------
  270. //
  271. // Function: MyGetFullPath
  272. //
  273. // Purpose: Small wrapper on GetFullPathName(). It assumes the buffer
  274. // is MAX_PATH.
  275. //
  276. // Returns:
  277. // Pointer to filename part in the buffer, NULL if errors. The
  278. // Win32 error code will be valid if fails.
  279. //
  280. // Notes:
  281. // - This function should be called whenever obtaining a pathname
  282. // from the user. Some of the other routines in this file
  283. // require a fully qualified and cleaned up pathname (i.e. no
  284. // trailing space and such).
  285. //
  286. //---------------------------------------------------------------------------
  287. LPTSTR MyGetFullPath(LPTSTR lpFileName)
  288. {
  289. TCHAR Buffer[MAX_PATH], *lpFilePart;
  290. lstrcpyn(Buffer, lpFileName, AS(Buffer));
  291. if ( ! GetFullPathName(Buffer,
  292. MAX_PATH,
  293. lpFileName,
  294. &lpFilePart) ) {
  295. lpFilePart = NULL;
  296. return NULL;
  297. }
  298. return lpFilePart;
  299. }
  300. //---------------------------------------------------------------------------
  301. //
  302. // Function: GetPathFromPathAndFilename
  303. //
  304. // Purpose: To obtain the just the path from a string that contains a path
  305. // and a filename.
  306. //
  307. // Arguments: LPTSTR lpPathAndFileName - the full path and filename
  308. // TCHAR *szPath - buffer the path is to be returned in, it is
  309. // assumed to be of MAX_PATH length
  310. //
  311. // Returns:
  312. // Inside szBuffer is just the path from the input of the path and file
  313. // name
  314. // BOOL - TRUE on success, FALSE on failure
  315. //
  316. //
  317. // Examples:
  318. // lpPathAndFileName szBuffer
  319. //
  320. // c:\foo\bar.exe returns c:\foo
  321. // c:\bar.exe c:\
  322. //
  323. //---------------------------------------------------------------------------
  324. BOOL
  325. GetPathFromPathAndFilename( IN LPTSTR lpPathAndFileName, OUT TCHAR *szPath, IN DWORD cbSize )
  326. {
  327. INT iFileNameLength;
  328. INT iPathLength;
  329. INT iPathAndFileNameLength;
  330. TCHAR Buffer[MAX_PATH];
  331. TCHAR *lpFilePart;
  332. lstrcpyn(Buffer, lpPathAndFileName, AS(Buffer));
  333. if ( ! GetFullPathName(Buffer,
  334. MAX_PATH,
  335. lpPathAndFileName,
  336. &lpFilePart) ) {
  337. return( FALSE );
  338. }
  339. iFileNameLength = lstrlen( lpFilePart );
  340. iPathAndFileNameLength = lstrlen( lpPathAndFileName );
  341. lstrcpyn( szPath, lpPathAndFileName, cbSize );
  342. szPath[iPathAndFileNameLength - iFileNameLength] = _T('\0');
  343. //
  344. // At this point szPath looks like either c:\foo\ or c:\
  345. // So trim the last back slash unless at the root
  346. //
  347. iPathLength = lstrlen( szPath );
  348. if( iPathLength > 3 )
  349. {
  350. szPath[iPathLength-1] = _T('\0');
  351. }
  352. return( TRUE );
  353. }
  354. //---------------------------------------------------------------------------
  355. //
  356. // Function: MyGetDiskFreeSpace
  357. //
  358. // Purpose: Gets the free space in bytes on the given drive and returns
  359. // a LONGLONG (int64).
  360. //
  361. // The Win32 apis won't return an int64. Also, the Win32 apis
  362. // require d:\. But this function will accept any fully
  363. // qualified path.
  364. //
  365. // Arguments:
  366. // LPTSTR - any fully qualified path
  367. //
  368. // Returns:
  369. // LONGLONG - free space
  370. //
  371. //---------------------------------------------------------------------------
  372. LONGLONG
  373. MyGetDiskFreeSpace(LPTSTR Drive)
  374. {
  375. BOOL bRet;
  376. DWORD nSectorsPerCluster,
  377. nBytesPerSector,
  378. nFreeClusters,
  379. nTotalClusters;
  380. TCHAR DriveBuffer[MAX_PATH];
  381. LONGLONG FreeBytes;
  382. HRESULT hrCat;
  383. if( _istalpha( Drive[0] ) )
  384. {
  385. lstrcpyn(DriveBuffer, Drive, 4);
  386. DriveBuffer[3] = _T('\0');
  387. }
  388. else if( Drive[0] == _T('\\') )
  389. {
  390. GetComputerNameFromUnc( Drive, DriveBuffer, AS(DriveBuffer) );
  391. hrCat=StringCchCat( DriveBuffer, AS(DriveBuffer), _T("\\") );
  392. hrCat=StringCchCat( DriveBuffer, AS(DriveBuffer), WizGlobals.DistShareName );
  393. hrCat=StringCchCat( DriveBuffer, AS(DriveBuffer), _T("\\") );
  394. }
  395. else
  396. {
  397. AssertMsg(FALSE,
  398. "MyGetDiskFreeSpace failed, programming error, bad Drive parameter");
  399. }
  400. bRet = GetDiskFreeSpace( DriveBuffer,
  401. &nSectorsPerCluster,
  402. &nBytesPerSector,
  403. &nFreeClusters,
  404. &nTotalClusters );
  405. if( bRet == FALSE )
  406. {
  407. ReportErrorId( NULL,
  408. MSGTYPE_ERR | MSGTYPE_WIN32,
  409. IDS_ERR_UNABLE_TO_DETERMINE_FREE_SPACE,
  410. DriveBuffer );
  411. return( 0 );
  412. }
  413. FreeBytes = (LONGLONG) nFreeClusters *
  414. (LONGLONG) nBytesPerSector *
  415. (LONGLONG) nSectorsPerCluster;
  416. return( FreeBytes );
  417. }
  418. //---------------------------------------------------------------------------
  419. //
  420. // Function: MySetupQuerySpaceRequiredOnDrive
  421. //
  422. // Purpose: Uses setupapi disk-space-list and returns the LONGLONG
  423. // of how many bytes are needed.
  424. //
  425. // Arguments:
  426. // LPTSTR - any fully qualified path
  427. //
  428. // Returns:
  429. // LONGLONG - free space
  430. //
  431. //---------------------------------------------------------------------------
  432. LONGLONG
  433. MySetupQuerySpaceRequiredOnDrive(HDSKSPC hDiskSpace, LPTSTR Drive)
  434. {
  435. BOOL bRet;
  436. LONGLONG llRequiredSpace;
  437. TCHAR DriveBuffer[MAX_PATH];
  438. if( _istalpha( Drive[0] ) )
  439. {
  440. lstrcpyn(DriveBuffer, Drive, 3);
  441. DriveBuffer[2] = _T('\0');
  442. }
  443. else if( Drive[0] == _T('\\') )
  444. {
  445. GetComputerAndShareNameFromUnc( Drive, DriveBuffer, AS(DriveBuffer) );
  446. }
  447. else
  448. {
  449. AssertMsg(FALSE,
  450. "SetupQuerySpaceRequiredOnDrive failed, programming error, bad Drive parameter");
  451. }
  452. bRet = SetupQuerySpaceRequiredOnDrive(
  453. hDiskSpace,
  454. DriveBuffer,
  455. &llRequiredSpace,
  456. NULL, 0);
  457. AssertMsg(bRet,
  458. "SetupQuerySpaceRequiredOnDrive failed, programming error");
  459. return llRequiredSpace;
  460. }
  461. //---------------------------------------------------------------------------
  462. //
  463. // Function: IsPathOnLocalDiskDrive
  464. //
  465. // Purpose: Determines if the path is on a local disk drive or not.
  466. //
  467. // Arguments:
  468. // LPTSTR lpPath - fully qualified path
  469. //
  470. // Returns: BOOL
  471. //
  472. //---------------------------------------------------------------------------
  473. BOOL
  474. IsPathOnLocalDiskDrive(LPCTSTR lpPath)
  475. {
  476. UINT nDriveType;
  477. TCHAR szDrivePath[MAX_PATH + 1];
  478. //
  479. // Use GetDriveType to determine if the path is a local or a network path
  480. //
  481. lstrcpyn( szDrivePath, lpPath, AS(szDrivePath) );
  482. if( szDrivePath[0] != _T('\\') )
  483. {
  484. //
  485. // Truncate the path to the root dir
  486. //
  487. szDrivePath[3] = _T('\0');
  488. }
  489. nDriveType = GetDriveType( szDrivePath );
  490. if( nDriveType == DRIVE_REMOTE )
  491. {
  492. return( FALSE );
  493. }
  494. else
  495. {
  496. return( TRUE );
  497. }
  498. }
  499. //---------------------------------------------------------------------------
  500. //
  501. // Function: EnsureDirExists
  502. //
  503. // Purpose: Function that will iteratively create the given directory
  504. // by creating each piece of the pathname if necessary.
  505. //
  506. // Arguments:
  507. // LPTSTR lpDirName - dir name
  508. //
  509. // Returns: BOOL
  510. //
  511. // Notes:
  512. // - This function requires a fully qualified pathname. Translate
  513. // pathnames using MyGetFullPath() first.
  514. //
  515. // - The Win32 error code will be valid upon failure.
  516. //
  517. //---------------------------------------------------------------------------
  518. BOOL EnsureDirExists(LPTSTR lpDirName)
  519. {
  520. BOOL bRestoreSlash;
  521. DWORD dwAttribs;
  522. TCHAR *p;
  523. //
  524. // Parse off the D:\ or \\srv\shr\. The lasterror will already
  525. // be set by ParseDriveLetterOrUnc() if any errors occured.
  526. //
  527. if ( (p = ParseDriveLetterOrUnc(lpDirName)) == NULL )
  528. return FALSE;
  529. //
  530. // Now parse off each piece of the pathname and make sure dir exists
  531. //
  532. while ( *p ) {
  533. // find next \ or end // of pathname
  534. while ( *p && *p != _T('\\') )
  535. p++;
  536. bRestoreSlash = FALSE;
  537. if ( *p == _T('\\') ) {
  538. *p = _T('\0');
  539. bRestoreSlash = TRUE;
  540. }
  541. // see if a file with that name already exists
  542. dwAttribs = GetFileAttributes(lpDirName);
  543. if ( dwAttribs != (DWORD) -1 &&
  544. !(dwAttribs & FILE_ATTRIBUTE_DIRECTORY) ) {
  545. if ( bRestoreSlash )
  546. *p = _T('\\');
  547. SetLastError(ERROR_ALREADY_EXISTS);
  548. return FALSE;
  549. }
  550. // create the dir and allow a failure if the dir already exists
  551. if ( !CreateDirectory(lpDirName, NULL) &&
  552. GetLastError() != ERROR_ALREADY_EXISTS ) {
  553. if ( bRestoreSlash )
  554. *p = _T('\\');
  555. return FALSE;
  556. }
  557. if ( bRestoreSlash )
  558. *p = _T('\\');
  559. // advance to next piece of the pathname
  560. p++;
  561. }
  562. return TRUE;
  563. }
  564. //---------------------------------------------------------------------------
  565. //
  566. // Function: DoesFolderExist
  567. //
  568. // Purpose: Checks if the given folder exists or not.
  569. //
  570. // Arguments:
  571. // LPTSTR lpDirName - dir name
  572. //
  573. // Returns: BOOL
  574. //
  575. //---------------------------------------------------------------------------
  576. BOOL DoesFolderExist(LPTSTR lpDirName)
  577. {
  578. DWORD dwAttribs = GetFileAttributes(lpDirName);
  579. if ( dwAttribs == (DWORD) -1 )
  580. return FALSE;
  581. if ( !(dwAttribs & FILE_ATTRIBUTE_DIRECTORY) )
  582. return FALSE;
  583. return TRUE;
  584. }
  585. //---------------------------------------------------------------------------
  586. //
  587. // Function: DoesFileExist
  588. //
  589. // Purpose: Checks if the given file exists or not.
  590. //
  591. // Arguments:
  592. // LPTSTR lpFileName - file name
  593. //
  594. // Returns: BOOL
  595. //
  596. //---------------------------------------------------------------------------
  597. BOOL DoesFileExist(LPTSTR lpFileName)
  598. {
  599. DWORD dwAttribs = GetFileAttributes(lpFileName);
  600. if ( dwAttribs == (DWORD) -1 )
  601. return FALSE;
  602. if ( dwAttribs & FILE_ATTRIBUTE_DIRECTORY )
  603. return FALSE;
  604. return TRUE;
  605. }
  606. //---------------------------------------------------------------------------
  607. //
  608. // Function: DoesPathExist
  609. //
  610. // Purpose: Checks if the given path exists or not. It does not pay
  611. // attention to whether it is a file or directory.
  612. //
  613. // Arguments:
  614. // LPTSTR lpPathName - path name
  615. //
  616. // Returns: BOOL
  617. //
  618. //---------------------------------------------------------------------------
  619. BOOL DoesPathExist(LPTSTR lpPathName)
  620. {
  621. DWORD dwAttribs = GetFileAttributes(lpPathName);
  622. if ( dwAttribs == (DWORD) -1 )
  623. return FALSE;
  624. return TRUE;
  625. }
  626. //---------------------------------------------------------------------------
  627. //
  628. // Function: ILFreePriv
  629. //
  630. // Purpose: Frees an ID list that some shell apis allocate with it's own
  631. // special allocator.
  632. //
  633. // Arguments:
  634. // LPITEMIDLIST pidl - pointer to shell specially alloced mem
  635. //
  636. // Returns: VOID
  637. //
  638. //---------------------------------------------------------------------------
  639. VOID ILFreePriv(LPITEMIDLIST pidl)
  640. {
  641. LPMALLOC pMalloc;
  642. if (pidl)
  643. {
  644. if ( NOERROR == SHGetMalloc(&pMalloc) )
  645. {
  646. pMalloc->lpVtbl->Free(pMalloc, pidl);
  647. pMalloc->lpVtbl->Release(pMalloc);
  648. }
  649. }
  650. }
  651. //
  652. // Constants used for GetOpenFileName() and GetSaveFileName() calls that
  653. // allow user to browse for an answer file.
  654. //
  655. //#define TEXT_FILE_FILTER _T("Text Files (*.txt)\0*.txt\0Remote Boot Files (*.sif)\0*.sif\0Sysprep Inf Files (*.inf)\0*.inf\0All Files (*.*)\0*.*\0")
  656. #define TEXT_EXTENSION _T("txt")
  657. //----------------------------------------------------------------------------
  658. //
  659. // Function: GetAnswerFileName
  660. //
  661. // Purpose: Function for the 'Browse' button on the SaveScript page and
  662. // the NewOrEdit page.
  663. //
  664. // Arguments:
  665. // HWND hwnd - calling window
  666. // LPTSTR buffer - output, pass in a MAX_PATH buffer
  667. //
  668. // Returns:
  669. // BOOL - success
  670. //
  671. //----------------------------------------------------------------------------
  672. BOOL GetAnswerFileName(HWND hwnd,
  673. LPTSTR lpFileName,
  674. BOOL bSavingFile)
  675. {
  676. OPENFILENAME ofn;
  677. DWORD dwFlags;
  678. TCHAR PathBuffer[MAX_PATH];
  679. INT iRet;
  680. HRESULT hrPrintf;
  681. //
  682. // If we haven't already loaded the resource strings, then load them now.
  683. //
  684. if( g_szSetupMgrFileExtensions[0] == _T('\0') )
  685. {
  686. TCHAR *StrTextFiles;
  687. TCHAR *StrRemoteBootFiles;
  688. TCHAR *StrSysprepFiles;
  689. TCHAR *StrAllFiles;
  690. //
  691. // Load the resource strings
  692. //
  693. StrTextFiles = AllocateString(NULL, IDS_TEXT_FILES);
  694. StrRemoteBootFiles = AllocateString(NULL, IDS_REMOTE_BOOT_FILES);
  695. StrSysprepFiles = AllocateString(NULL, IDS_SYSPREP_FILES);
  696. StrAllFiles = AllocateString(NULL, IDS_ALL_FILES);
  697. //
  698. // Build the text file filter string
  699. //
  700. //
  701. // The question marks (?) are just placehoders for where the NULL char
  702. // will be inserted.
  703. //
  704. hrPrintf=StringCchPrintf( g_szSetupMgrFileExtensions,AS(g_szSetupMgrFileExtensions),
  705. _T("%s (*.txt)?*.txt?%s (*.sif)?*.sif?%s (*.inf)?*.inf?%s (*.*)?*.*?"),
  706. StrTextFiles,
  707. StrRemoteBootFiles,
  708. StrSysprepFiles,
  709. StrAllFiles );
  710. FREE(StrTextFiles);
  711. FREE(StrRemoteBootFiles);
  712. FREE(StrSysprepFiles);
  713. FREE(StrAllFiles);
  714. ConvertQuestionsToNull( g_szSetupMgrFileExtensions );
  715. }
  716. if ( bSavingFile )
  717. dwFlags = OFN_HIDEREADONLY |
  718. OFN_PATHMUSTEXIST;
  719. else
  720. dwFlags = OFN_HIDEREADONLY |
  721. OFN_FILEMUSTEXIST;
  722. GetCurrentDirectory(MAX_PATH, PathBuffer);
  723. ofn.lStructSize = sizeof(OPENFILENAME);
  724. ofn.hwndOwner = hwnd;
  725. ofn.hInstance = NULL;
  726. ofn.lpstrFilter = g_szSetupMgrFileExtensions;
  727. ofn.lpstrCustomFilter = NULL;
  728. ofn.nMaxCustFilter = 0L;
  729. ofn.nFilterIndex = 1;
  730. ofn.lpstrFile = lpFileName;
  731. ofn.nMaxFile = MAX_PATH;
  732. ofn.lpstrFileTitle = NULL;
  733. ofn.nMaxFileTitle = 0;
  734. ofn.lpstrInitialDir = PathBuffer;
  735. ofn.lpstrTitle = NULL;
  736. ofn.Flags = dwFlags;
  737. ofn.nFileOffset = 0;
  738. ofn.nFileExtension = 0;
  739. ofn.lpstrDefExt = TEXT_EXTENSION;
  740. if ( bSavingFile )
  741. iRet = GetSaveFileName(&ofn);
  742. else
  743. iRet = GetOpenFileName(&ofn);
  744. if ( ! iRet )
  745. return FALSE;
  746. MyGetFullPath(lpFileName);
  747. return TRUE;
  748. }
  749. //----------------------------------------------------------------------------
  750. //
  751. // Function: ShowBrowseFolder
  752. //
  753. // Purpose: Displays a browse folder for the user to select a file from.
  754. // Takes the headache out of making an OPENFILENAME struct and filling
  755. // it up.
  756. //
  757. // Arguments:
  758. // HWND hwnd - handle to the dialog box
  759. // TCHAR *szFileFilter - string to display descriptions and extensions
  760. // on the files
  761. // TCHAR *szFileExtension - string that is the default extension for the file
  762. // DWORD dwFlags - bit flags used to initialize the browse dialog
  763. // TCHAR *szStartingPath - path the browse should start at
  764. // TCHAR *szFileNameAndPath - path and filename the user selected
  765. //
  766. // Returns: Non-Zero - if user specified a file
  767. // Zero - if user did not specify a file
  768. //
  769. //----------------------------------------------------------------------------
  770. INT
  771. ShowBrowseFolder( IN HWND hwnd,
  772. IN TCHAR *szFileFilter,
  773. IN TCHAR *szFileExtension,
  774. IN DWORD dwFlags,
  775. IN TCHAR *szStartingPath,
  776. IN OUT TCHAR *szFileNameAndPath ) {
  777. OPENFILENAME ofn;
  778. ofn.lStructSize = sizeof(OPENFILENAME);
  779. ofn.hwndOwner = hwnd;
  780. ofn.hInstance = NULL;
  781. ofn.lpstrFilter = szFileFilter;
  782. ofn.lpstrCustomFilter = NULL;
  783. ofn.nMaxCustFilter = 0L;
  784. ofn.nFilterIndex = 1;
  785. ofn.lpstrFile = szFileNameAndPath;
  786. ofn.nMaxFile = MAX_PATH;
  787. ofn.lpstrFileTitle = NULL;
  788. ofn.nMaxFileTitle = 0;
  789. ofn.lpstrInitialDir = szStartingPath;
  790. ofn.lpstrTitle = NULL;
  791. ofn.Flags = dwFlags;
  792. ofn.nFileOffset = 0;
  793. ofn.nFileExtension = 0;
  794. ofn.lpstrDefExt = szFileExtension;
  795. return( GetOpenFileName( &ofn ) );
  796. }
  797. //----------------------------------------------------------------------------
  798. //
  799. // Function: GetPlatform
  800. //
  801. // Purpose:
  802. //
  803. // Arguments: OUT TCHAR *pBuffer - buffer to copy the platform string to,
  804. // assumed to be able to hold MAX_PATH chars
  805. //
  806. // Returns: VOID
  807. //
  808. //----------------------------------------------------------------------------
  809. VOID
  810. GetPlatform( OUT TCHAR *pBuffer )
  811. {
  812. SYSTEM_INFO SystemInfo;
  813. GetSystemInfo( &SystemInfo );
  814. switch( SystemInfo.wProcessorArchitecture )
  815. {
  816. case PROCESSOR_ARCHITECTURE_INTEL:
  817. lstrcpyn( pBuffer, _T("i386"), MAX_PATH );
  818. break;
  819. case PROCESSOR_ARCHITECTURE_AMD64:
  820. lstrcpyn( pBuffer, _T("amd64"), MAX_PATH );
  821. break;
  822. default:
  823. lstrcpyn( pBuffer, _T("i386"), MAX_PATH );
  824. AssertMsg( FALSE,
  825. "Unknown Processor. Can't set sysprep language files path." );
  826. }
  827. }