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.

845 lines
30 KiB

  1. /****************************************************************************\
  2. NEWFILES.C / OPK Wizard (OPKWIZ.EXE)
  3. Microsoft Confidential
  4. Copyright (c) Microsoft Corporation 1998
  5. All rights reserved
  6. 3/99 - Jason Cohen (JCOHEN)
  7. Added this new source file for the OPK Wizard as part of the OOBE
  8. update.
  9. 09/2000 - Stephen Lodwick (STELO)
  10. Ported OPK Wizard to Whistler
  11. \****************************************************************************/
  12. //
  13. // Include file(s):
  14. //
  15. #include "pch.h"
  16. #include "newfiles.h"
  17. #include "resource.h"
  18. //
  19. // Internal Defined Value(s):
  20. //
  21. #define DIR_CONFIG_OOBE _T("$OEM$")
  22. #define INF_SECT_SOURCEDISK _T("SourcedisksFiles")
  23. #define INF_SECT_DESTDIRS _T("DestinationDirs")
  24. #define INF_SECT_OOBE _T("RegisterOOBE")
  25. #define INF_LINE_COPYFILES _T("CopyFiles")
  26. #define INF_PREFIX _T("X")
  27. #define SOURCENUM_OPTIONS_CAB _T("782")
  28. #define DESTLDID_OOBE _T("11")
  29. #define STR_SEARCH _T("*")
  30. #define STR_PADDING _T("\r\n\r\n")
  31. #define MAX_BUFFER 16384 // 32768
  32. #ifndef CSTR_EQUAL
  33. #define CSTR_EQUAL 2
  34. #endif // CSTR_EQUAL
  35. //
  36. // Internal Structure(s):
  37. //
  38. typedef struct _FILELIST
  39. {
  40. LPTSTR lpFileName;
  41. LPTSTR lpDirectory;
  42. struct _FILELIST * lpNext;
  43. } FILELIST, *PFILELIST, *LPFILELIST;
  44. //
  45. // Internal Function Prototype(s):
  46. //
  47. static void DelFiles(LPTSTR, LPTSTR, DWORD, LPTSTR, LPTSTR);
  48. static LPFILELIST AllocFileList(HWND, LPTSTR, LPTSTR);
  49. static BOOL CompareFiles(LPTSTR, LPTSTR);
  50. //
  51. // External Function(s):
  52. //
  53. //////////////////////////////////////////////////////////////////////////////
  54. // AddFiles - lpSourceDir = location of files to copy to OOBE directory.
  55. // Destination = location of the system directory where installed to
  56. // LDID.
  57. // lpConfigDir = location of oemaudit.inf, and config files.
  58. // lpSourceDir -> OOBE -> lpDestDir
  59. //
  60. void AddFiles(HWND hwndParent, LPTSTR lpSourceDir, LPTSTR lpDestLdid,
  61. LPTSTR lpDestDir, LPTSTR lpDestName, LPTSTR lpConfigDir)
  62. {
  63. LPTSTR lpFilePart,
  64. lpFile,
  65. lpFileName,
  66. lpSectEnd,
  67. lpSearch,
  68. lpTarget,
  69. lpNext;
  70. TCHAR szBuffer[MAX_PATH + 32] = NULLSTR,
  71. szCurDir[MAX_PATH] = NULLSTR,
  72. szSourceDir[MAX_PATH] = NULLSTR,
  73. szCopyDir[MAX_PATH],
  74. szWinbom[MAX_PATH],
  75. szCopyFiles[MAX_PATH + 32];
  76. LPFILELIST lpflHead = NULL,
  77. lpflCur,
  78. lpflBuf;
  79. BOOL bFound;
  80. DWORD dwNum;
  81. int iFilePartLen;
  82. HRESULT hrCat;
  83. HRESULT hrPrintf;
  84. //
  85. // First thing we do is setup the directories and strings
  86. // that we need to do all the work.
  87. //
  88. // We need the path to the config directory. Copydir is where
  89. // the files are going to be copied to from the SourceDir
  90. // so it needs to be cleaned out before we do the CopyFile.
  91. // CopyDir will be created if not exists.
  92. //
  93. lstrcpyn(szCopyDir, lpConfigDir, AS(szCopyDir));
  94. AddPathN(szCopyDir, DIR_CONFIG_OOBE,AS(szCopyDir));
  95. AddPathN(szCopyDir, _T("\\"),AS(szCopyDir));
  96. lpFilePart = szCopyDir + lstrlen(szCopyDir);
  97. iFilePartLen= AS(szCopyDir)-lstrlen(szCopyDir);
  98. // Need a full path to the oemaudit inf.
  99. //
  100. lstrcpyn(szWinbom, lpConfigDir,AS(szWinbom));
  101. AddPathN(szWinbom, FILE_WINBOM_INI,AS(szWinbom));
  102. // We need to construct the prefix to the copy
  103. // files section name.
  104. //
  105. lstrcpyn(szCopyFiles, INF_PREFIX,AS(szCopyFiles));
  106. hrCat=StringCchCat(szCopyFiles, AS(szCopyFiles), lpDestLdid ? lpDestLdid : DESTLDID_OOBE);
  107. if ( lpDestDir && *lpDestDir )
  108. hrCat=StringCchCat(szCopyFiles, AS(szCopyFiles), lpDestDir);
  109. StrRem(szCopyFiles, CHR_BACKSLASH);
  110. lpSectEnd = szCopyFiles + lstrlen(szCopyFiles);
  111. //
  112. // Now that we have that info, we need to get rid of any files that
  113. // may have already been put in the inf and the destination directory.
  114. //
  115. // Cleaned out of the inf and destination directory only if we are
  116. // passed in NULL for the source.
  117. //
  118. if ( !(lpSourceDir && *lpSourceDir) )
  119. DelFiles(szCopyDir, lpFilePart, iFilePartLen, szWinbom, szCopyFiles);
  120. //
  121. // Now we make a list of all the files we are going to add to the
  122. // inf and destination directory.
  123. //
  124. // If the source isn't a valid dir, we must have just wanted to clean up.
  125. //
  126. if ( ( lpSourceDir && *lpSourceDir ) &&
  127. ( GetFullPathName(lpSourceDir, sizeof(szSourceDir) / sizeof(TCHAR), szSourceDir, &lpFile) && szSourceDir[0] ) &&
  128. ( (dwNum = GetFileAttributes(szSourceDir)) != 0xFFFFFFFF ) )
  129. {
  130. // Check to see if we were passed a file or a directory.
  131. //
  132. if ( ( dwNum & FILE_ATTRIBUTE_DIRECTORY ) ||
  133. ( lpFile <= szSourceDir ) )
  134. {
  135. // We are search for all the files in the diretory.
  136. //
  137. lpFile = STR_SEARCH;
  138. }
  139. else
  140. {
  141. // We are only doing one file. We need to separate
  142. // the file from the directory.
  143. //
  144. *(lpFile - 1) = NULLCHR;
  145. }
  146. // Set the staring point for our file search.
  147. //
  148. GetCurrentDirectory(sizeof(szCurDir) / sizeof(TCHAR), szCurDir);
  149. SetCurrentDirectory(szSourceDir);
  150. // Get the file list.
  151. //
  152. lpflHead = AllocFileList(hwndParent, szBuffer, lpFile);
  153. // Make sure the destination dir exits.
  154. //
  155. *lpFilePart = NULLCHR;
  156. CreatePath(szCopyDir);
  157. //
  158. // Now that we have the file list, go through each one processing
  159. // it separately and then free the memory allocated for it.
  160. //
  161. // Loop through all the files in our linked list.
  162. //
  163. for ( lpflCur = lpflHead; lpflCur; lpflCur = lpflBuf )
  164. {
  165. //
  166. // First copy the file into the flat directory.
  167. //
  168. // Setup the relative path from the currect directory
  169. // to the file we want to copy.
  170. //
  171. if ( lpflCur->lpDirectory && *lpflCur->lpDirectory )
  172. lstrcpyn(szBuffer, lpflCur->lpDirectory,AS(szBuffer));
  173. else
  174. szBuffer[0] = NULLCHR;
  175. AddPathN(szBuffer, lpflCur->lpFileName,AS(szBuffer));
  176. // Support for a different file name for the destination.
  177. //
  178. lpFileName = lpDestName ? lpDestName : lpflCur->lpFileName;
  179. // Setup the destination file name.
  180. //
  181. lstrcpyn(lpFilePart, lpFileName, iFilePartLen);
  182. // Copy the file to the Options\Cabs directory and display
  183. // an error if the copy failed. Probably means that this
  184. // is a duplicate file.
  185. //
  186. if ( !CopyFile(szBuffer, szCopyDir, TRUE) )
  187. {
  188. // Save the CopyFile error and then check to see if the file
  189. // is actaully different then the one tried to copy over.
  190. //
  191. dwNum = GetLastError();
  192. if ( ( !CompareFiles(szBuffer, szCopyDir) ) &&
  193. ( lpTarget = (LPTSTR) MALLOC(256 * sizeof(TCHAR)) ) )
  194. {
  195. //
  196. // I hate doing UI in backend type code. Because of time I don't have
  197. // much choice, but in the future, this UI code should be replaced
  198. // with a call back mechanism so the caller can do the UI.
  199. //
  200. // This is the first of only two places where UI is used in here.
  201. //
  202. // Allocate another buffer to hold the message with the file name.
  203. //
  204. if ( ( LoadString(NULL, dwNum == ERROR_FILE_EXISTS ? IDS_ERR_DUPFILE : IDS_ERR_COPY, lpTarget, 256 * sizeof(TCHAR)) ) &&
  205. ( lpNext = (LPTSTR) MALLOC((lstrlen(lpFileName) + lstrlen(lpTarget) + 1) * sizeof(TCHAR)) ) )
  206. {
  207. // Add the file name to the message, get the title for the message
  208. // box and display the error.
  209. //
  210. hrPrintf=StringCchPrintf(lpNext, (lstrlen(lpFileName) + lstrlen(lpTarget) + 1), lpTarget, lpFileName);
  211. *lpTarget = NULLCHR;
  212. LoadString(NULL, IDS_APPNAME, lpTarget, 256 * sizeof(TCHAR));
  213. MessageBox(hwndParent, lpNext, lpTarget, MB_OK | MB_ICONWARNING | MB_APPLMODAL);
  214. FREE(lpNext);
  215. }
  216. FREE(lpTarget);
  217. }
  218. }
  219. //
  220. // Now add the file to the [SourceDiskFiles] section.
  221. //
  222. // We just use WritePrivateProfileString() to write
  223. // FILENAME=781 to the [SourceDiskFiles] section.
  224. //
  225. WritePrivateProfileString(INF_SECT_SOURCEDISK, lpFileName, SOURCENUM_OPTIONS_CAB, szWinbom);
  226. //
  227. // This code figures out what the copy files section will be
  228. // called. This is based on the path where the files will
  229. // be copied.
  230. //
  231. // Create the name of the copy files section the file will be in.
  232. //
  233. *lpSectEnd = NULLCHR;
  234. if ( lpflCur->lpDirectory && *lpflCur->lpDirectory )
  235. lstrcpyn(lpSectEnd, lpflCur->lpDirectory, AS(szCopyFiles)-(int)(lpSectEnd - szCopyFiles) );
  236. StrRem(lpSectEnd, CHR_BACKSLASH);
  237. //
  238. // Now add the file path to the [DestinationDirs] section.
  239. //
  240. // Create the LDID and dir combo to write to the dest dir section.
  241. //
  242. lstrcpyn(szBuffer, lpDestLdid ? lpDestLdid : DESTLDID_OOBE,AS(szBuffer));
  243. if ( ( lpDestDir && *lpDestDir ) ||
  244. ( lpflCur->lpDirectory && *lpflCur->lpDirectory ) )
  245. {
  246. hrCat=StringCchCat(szBuffer,AS(szBuffer), _T(",\""));
  247. if ( lpDestDir && *lpDestDir )
  248. {
  249. hrCat=StringCchCat(szBuffer, AS(szBuffer),lpDestDir);
  250. if ( lpflCur->lpDirectory && *lpflCur->lpDirectory )
  251. AddPathN(szBuffer, lpflCur->lpDirectory,AS(szBuffer));
  252. }
  253. else
  254. hrCat=StringCchCat(szBuffer, AS(szBuffer), lpflCur->lpDirectory);
  255. hrCat=StringCchCat(szBuffer, AS(szBuffer), _T("\""));
  256. }
  257. // We just use WritePrivateProfileString() to write
  258. // COPYFILES=11,"OOBE\\DIR" to the [DestinationDirs] section.
  259. //
  260. WritePrivateProfileString(INF_SECT_DESTDIRS, szCopyFiles, szBuffer, szWinbom);
  261. //
  262. // Now add the copy files section to the CopyFiles line.
  263. //
  264. // First get current CopyFiles line.
  265. //
  266. szBuffer[0] = NULLCHR;
  267. GetPrivateProfileString(INF_SECT_OOBE, INF_LINE_COPYFILES, NULLSTR, szBuffer, sizeof(szBuffer) / sizeof(TCHAR), szWinbom);
  268. // Search each section listed in the CopyFiles line to see
  269. // if we need to add this one. The sections are divided by
  270. // commas.
  271. //
  272. // ISSUE-2002/02/28-stelo- May want to take qutoes into account, but I don't think so.
  273. //
  274. bFound = FALSE;
  275. for ( lpTarget = szBuffer; !bFound && lpTarget && *lpTarget; lpTarget = lpNext )
  276. {
  277. // Get rid of proceeding spaces.
  278. //
  279. while ( *lpTarget == CHR_SPACE )
  280. lpTarget = CharNext(lpTarget);
  281. // NULL terminate at the ',' and setup
  282. // the lpNext pointer.
  283. //
  284. if ( lpNext = StrChr(lpTarget, _T(',')) )
  285. *lpNext = NULLCHR;
  286. // Make sure there are no trailing spaces.
  287. //
  288. if ( lpSearch = StrChr(lpTarget, CHR_SPACE) )
  289. *lpSearch = NULLCHR;
  290. // Check if this section is the same as the one
  291. // we are going to add.
  292. //
  293. if ( CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, lpTarget, -1, szCopyFiles, -1) == CSTR_EQUAL )
  294. bFound = TRUE;
  295. // Need to restore the characters we may have stomped on.
  296. //
  297. if ( lpNext )
  298. *lpNext++ = _T(',');
  299. if ( lpSearch )
  300. *lpSearch = CHR_SPACE;
  301. }
  302. // Now see if we need to add the line.
  303. //
  304. if ( !bFound )
  305. {
  306. // Append our copy files section.
  307. //
  308. if ( szBuffer[0] )
  309. hrCat=StringCchCat(szBuffer,AS(szBuffer), _T(", "));
  310. hrCat=StringCchCat(szBuffer, AS(szBuffer), szCopyFiles);
  311. // We just use WritePrivateProfileString() to write
  312. // the CopyFiles line back to the [RegisterOOBE] section
  313. // with our added copy files section on it.
  314. //
  315. WritePrivateProfileString(INF_SECT_OOBE, INF_LINE_COPYFILES, szBuffer, szWinbom);
  316. }
  317. //
  318. // Now write the file name to it's copy files section.
  319. //
  320. // First get the entire copy files section.
  321. //
  322. GetPrivateProfileSection(szCopyFiles, szBuffer, sizeof(szBuffer) / sizeof(TCHAR), szWinbom);
  323. // Loop throught the strings to see if the file is already there.
  324. //
  325. bFound = FALSE;
  326. for ( lpTarget = szBuffer; !bFound && *lpTarget; lpTarget += (lstrlen(lpTarget) + 1) )
  327. {
  328. // Get rid of proceeding spaces.
  329. //
  330. while ( *lpTarget == CHR_SPACE )
  331. lpTarget = CharNext(lpTarget);
  332. // Make sure there are no trailing spaces.
  333. //
  334. if ( lpSearch = StrChr(lpTarget, CHR_SPACE) )
  335. *lpSearch = NULLCHR;
  336. // Check if this section is the same as the one
  337. // we are going to add.
  338. //
  339. if ( CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, lpTarget, -1, lpFileName, -1) == CSTR_EQUAL )
  340. bFound = TRUE;
  341. // Need to restore the character we may have stomped on.
  342. //
  343. if ( lpSearch )
  344. *lpSearch = CHR_SPACE;
  345. }
  346. // Now write back the section if we need to.
  347. //
  348. if ( !bFound )
  349. {
  350. // Need to a pointer to the end of the sub strings.
  351. //
  352. for ( lpSearch = szBuffer; *lpSearch; lpSearch += (lstrlen(lpSearch) + 1) );
  353. // Copy the string to the end and add an extra NULL.
  354. //
  355. lstrcpyn(lpSearch, lpFileName, ((MAX_PATH+32)-(int)(lpSearch-szBuffer)) );
  356. lpSearch += (lstrlen(lpSearch) + 1);
  357. *lpSearch = NULLCHR;
  358. // We need to call WritePrivateProfileSection() with NULL
  359. // to remove the section. We shouldn't have to do this,
  360. // but the Win32 docs are not correct.
  361. //
  362. WritePrivateProfileSection(szCopyFiles, NULL, szWinbom);
  363. // We just use WritePrivateProfileSection() to write the
  364. // copy files section back with our added file in it.
  365. //
  366. WritePrivateProfileSection(szCopyFiles, szBuffer, szWinbom);
  367. }
  368. //
  369. // Now free the structure and the data within it.
  370. //
  371. // Save the next pointer before we free the structure.
  372. //
  373. lpflBuf = lpflCur->lpNext;
  374. // Free the file buffers and the structure.
  375. //
  376. FREE(lpflCur->lpFileName);
  377. FREE(lpflCur->lpDirectory);
  378. FREE(lpflCur);
  379. }
  380. //
  381. // All done, now just clean up.
  382. //
  383. // Put the current directory back to where it should be.
  384. //
  385. if ( szCurDir[0] )
  386. SetCurrentDirectory(szCurDir);
  387. }
  388. // Make sure the changes to the inf are flushed to disk
  389. //
  390. WritePrivateProfileString(NULL, NULL, NULL, szWinbom);
  391. }
  392. //
  393. // Internal Function(s):
  394. //
  395. static void DelFiles(LPTSTR lpszCopyDir, LPTSTR lpszFilePart, DWORD cbFilePart, LPTSTR lpszWinbom, LPTSTR lpszCopyFiles)
  396. {
  397. LPTSTR lpSearch,
  398. lpSection,
  399. lpFileName,
  400. lpTarget,
  401. lpNext;
  402. LPTSTR lpszSections = NULL,
  403. lpszFileNames = NULL,
  404. lpszBuffer = NULL;
  405. BOOL bFound;
  406. //
  407. // Allocate buffers...
  408. //
  409. lpszSections = MALLOC(MAX_BUFFER * sizeof(TCHAR));
  410. lpszFileNames = MALLOC(MAX_BUFFER * sizeof(TCHAR));
  411. lpszBuffer = MALLOC(MAX_BUFFER * sizeof(TCHAR));
  412. if ( !lpszSections || !lpszFileNames || !lpszBuffer )
  413. {
  414. // Free the buffers... Note: FREE macro checks for NULL
  415. //
  416. FREE( lpszSections );
  417. FREE( lpszFileNames );
  418. FREE( lpszBuffer );
  419. return;
  420. }
  421. // We need all the section names.
  422. //
  423. GetPrivateProfileSectionNames(lpszSections, MAX_BUFFER, lpszWinbom);
  424. // Loop throught the section to see if there is any that match our search criteria.
  425. //
  426. for ( lpSection = lpszSections; lpSection && *lpSection; lpSection += (lstrlen(lpSection) + 1) )
  427. {
  428. // Get rid of proceeding spaces.
  429. //
  430. while ( *lpSection == CHR_SPACE )
  431. lpSection = CharNext(lpSection);
  432. // Make sure there are no trailing spaces.
  433. //
  434. if ( lpSearch = StrChr(lpSection, CHR_SPACE) )
  435. *lpSearch = NULLCHR;
  436. // Check if this section is the same as the one
  437. // we are going to add.
  438. //
  439. if ( CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, lpSection, lstrlen(lpszCopyFiles), lpszCopyFiles, lstrlen(lpszCopyFiles)) == CSTR_EQUAL )
  440. {
  441. // We need all the files in the section.
  442. //
  443. GetPrivateProfileSection(lpSection, lpszFileNames, MAX_BUFFER, lpszWinbom);
  444. // Loop throught the section to see if there is any that match our search criteria.
  445. //
  446. for ( lpFileName = lpszFileNames; *lpFileName; lpFileName += (lstrlen(lpFileName) + 1) )
  447. {
  448. // Get rid of proceeding spaces.
  449. //
  450. while ( *lpFileName == CHR_SPACE )
  451. lpFileName = CharNext(lpFileName);
  452. // Make sure there are no trailing spaces.
  453. //
  454. if ( lpSearch = StrChr(lpFileName, CHR_SPACE) )
  455. *lpSearch = NULLCHR;
  456. // Delete the file from the destination directory.
  457. //
  458. lstrcpyn(lpszFilePart, lpFileName, cbFilePart);
  459. DeleteFile(lpszCopyDir);
  460. // Remove the line from the source disk section.
  461. //
  462. WritePrivateProfileString(INF_SECT_SOURCEDISK, lpFileName, NULL, lpszWinbom);
  463. }
  464. // Search each section listed in the CopyFiles and remove
  465. // this one. The sections are divided by commas.
  466. //
  467. bFound = FALSE;
  468. GetPrivateProfileString(INF_SECT_OOBE, INF_LINE_COPYFILES, NULLSTR, lpszBuffer, MAX_BUFFER, lpszWinbom);
  469. for ( lpTarget = lpszBuffer; !bFound && lpTarget && *lpTarget; lpTarget = lpNext )
  470. {
  471. // Get rid of proceeding spaces.
  472. //
  473. while ( *lpTarget == CHR_SPACE )
  474. lpTarget = CharNext(lpTarget);
  475. // NULL terminate at the ',' and setup
  476. // the lpNext pointer.
  477. //
  478. if ( lpNext = StrChr(lpTarget, _T(',')) )
  479. *lpNext = NULLCHR;
  480. // Make sure there are no trailing spaces.
  481. //
  482. if ( lpSearch = StrChr(lpTarget, CHR_SPACE) )
  483. *lpSearch = NULLCHR;
  484. // Check if this section is the same as the one
  485. // we are going to remove.
  486. //
  487. if ( CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, lpTarget, -1, lpSection, -1) == CSTR_EQUAL )
  488. bFound = TRUE;
  489. // Need to restore the characters we may have stomped on.
  490. //
  491. if ( lpNext )
  492. *lpNext++ = _T(',');
  493. if ( lpSearch )
  494. *lpSearch = CHR_SPACE;
  495. if ( bFound )
  496. {
  497. // Go back to the ',' or the beginning of the buffer.
  498. //
  499. while ( ( lpTarget > lpszBuffer) && ( *lpTarget != _T(',') ) )
  500. lpTarget = CharPrev(lpszBuffer, lpTarget);
  501. // Now overwrite the string we took out.
  502. //
  503. if ( lpNext )
  504. lstrcpyn(lpTarget, lpNext - 1, (MAX_BUFFER-(int)(lpTarget-lpszBuffer)));
  505. else
  506. *lpTarget = NULLCHR;
  507. }
  508. }
  509. if ( bFound )
  510. {
  511. // We should eat any preceeding spaces and/or commas just
  512. // for good measure.
  513. //
  514. for ( lpTarget = lpszBuffer; ( *lpTarget == CHR_SPACE ) || ( *lpTarget == _T(',') ); lpTarget = CharNext(lpTarget) );
  515. // Now write the buffer back to the inf file.
  516. //
  517. WritePrivateProfileString(INF_SECT_OOBE, INF_LINE_COPYFILES, *lpTarget ? lpTarget : NULL, lpszWinbom);
  518. }
  519. // Remove the line from the destination dirs section.
  520. //
  521. WritePrivateProfileString(INF_SECT_DESTDIRS, lpSection, NULL, lpszWinbom);
  522. // Remove this section entirely.
  523. //
  524. WritePrivateProfileSection(lpSection, NULL, lpszWinbom);
  525. }
  526. }
  527. // Free the buffers... Note: FREE macro checks for NULL
  528. //
  529. FREE( lpszSections );
  530. FREE( lpszFileNames );
  531. FREE( lpszBuffer );
  532. }
  533. static LPFILELIST AllocFileList(HWND hwndParent, LPTSTR lpDirectory, LPTSTR lpSearch)
  534. {
  535. WIN32_FIND_DATA FileFound;
  536. HANDLE hFile;
  537. LPTSTR lpEnd,
  538. lpFileName;
  539. LPFILELIST lpflHead = NULL;
  540. LPFILELIST* lplpflNext = &lpflHead;
  541. HRESULT hrPrintf;
  542. // Process all the files and directories.
  543. //
  544. if ( (hFile = FindFirstFile(lpSearch, &FileFound)) != INVALID_HANDLE_VALUE )
  545. {
  546. do
  547. {
  548. // Display an error if the short and long file names don't match.
  549. // Means that it is a LFN, which INFs don't like.
  550. //
  551. if ( ( FileFound.cAlternateFileName[0] ) &&
  552. ( CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, FileFound.cAlternateFileName, -1, FileFound.cFileName, -1) != CSTR_EQUAL ) &&
  553. ( lpEnd = (LPTSTR) MALLOC(256 * sizeof(TCHAR)) ) )
  554. {
  555. //
  556. // I hate doing UI in backend type code. Because of time I don't have
  557. // much choice, but in the future, this UI code should be replaced
  558. // with a call back mechanism so the caller can do the UI.
  559. //
  560. // This is the second of only two places where UI is used in here.
  561. //
  562. // Allocate another buffer to hold the message with the file name.
  563. //
  564. if ( ( LoadString(NULL, IDS_ERR_LFN, lpEnd, 256) ) &&
  565. ( lpFileName = (LPTSTR) MALLOC((lstrlen(FileFound.cFileName) + lstrlen(lpEnd) + 1) * sizeof(TCHAR)) ) )
  566. {
  567. // Add the file name to the message, get the title for the message
  568. // box and display the error.
  569. //
  570. hrPrintf=StringCchPrintf(lpFileName, (lstrlen(FileFound.cFileName) + lstrlen(lpEnd) + 1), lpEnd, FileFound.cFileName);
  571. *lpEnd = NULLCHR;
  572. LoadString(NULL, IDS_APPNAME, lpEnd, 256 * sizeof(TCHAR));
  573. MessageBox(hwndParent, lpFileName, lpEnd, MB_OK | MB_ICONWARNING | MB_APPLMODAL);
  574. FREE(lpFileName);
  575. }
  576. FREE(lpEnd);
  577. }
  578. // Get a pointer to the file name, the short one if possible.
  579. //
  580. if ( FileFound.cAlternateFileName[0] )
  581. lpFileName = FileFound.cAlternateFileName;
  582. else
  583. lpFileName = FileFound.cFileName;
  584. // First check to see if this is a files (not a directory).
  585. //
  586. if ( !( FileFound.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) )
  587. {
  588. // Allocate the next item in the structure.
  589. //
  590. if ( *lplpflNext = (LPFILELIST) MALLOC(sizeof(FILELIST)) )
  591. {
  592. // Allocate the buffer for the file name and path and
  593. // make sure that none of the allocations fail.
  594. //
  595. if ( ( (*lplpflNext)->lpFileName = (LPTSTR) MALLOC((lstrlen(lpFileName) + 1) * sizeof(TCHAR)) ) &&
  596. ( (*lplpflNext)->lpDirectory = (LPTSTR) MALLOC((lstrlen(lpDirectory) + 1) * sizeof(TCHAR)) ) )
  597. {
  598. // Copy the file name and path into the buffers.
  599. //
  600. lstrcpyn((*lplpflNext)->lpFileName, lpFileName, (lstrlen(lpFileName) + 1));
  601. lstrcpyn((*lplpflNext)->lpDirectory, lpDirectory, (lstrlen(lpDirectory) + 1));
  602. // Null the next pointer so we know this is the last item.
  603. //
  604. (*lplpflNext)->lpNext = NULL;
  605. // Set the next pointer to point to the address of
  606. // the next member of this new structure.
  607. //
  608. lplpflNext = &((*lplpflNext)->lpNext);
  609. }
  610. else
  611. {
  612. // Don't worry, the FREE() macro checks for NULL
  613. // before it frees the memory.
  614. //
  615. FREE((*lplpflNext)->lpFileName);
  616. FREE(*lplpflNext);
  617. }
  618. }
  619. }
  620. // Otherwise, make sure the directory is not "." or "..".
  621. //
  622. else if ( ( lstrcmp(lpFileName, _T(".")) ) &&
  623. ( lstrcmp(lpFileName, _T("..")) ) )
  624. {
  625. // Tack on this directory name to the current path saving
  626. // the end pointer so that it is easy to get rid of this
  627. // directory name when we return back.
  628. //
  629. lpEnd = lpDirectory + lstrlen(lpDirectory);
  630. AddPath(lpDirectory, lpFileName);
  631. // Go into the next directory, get all the files, and
  632. // the set the current directory back to the original
  633. // directory.
  634. //
  635. SetCurrentDirectory(lpFileName);
  636. *lplpflNext = AllocFileList(hwndParent, lpDirectory, lpSearch);
  637. SetCurrentDirectory(_T(".."));
  638. // Get rid of the directory name off our path buffer.
  639. //
  640. *lpEnd = NULLCHR;
  641. // Need to setup our next pointer to the end of the list
  642. // returned to us.
  643. //
  644. while ( *lplpflNext )
  645. lplpflNext = &((*lplpflNext)->lpNext);
  646. }
  647. }
  648. while ( FindNextFile(hFile, &FileFound) );
  649. FindClose(hFile);
  650. }
  651. return lpflHead;
  652. }
  653. static BOOL CompareFiles(LPTSTR lpFile1, LPTSTR lpFile2)
  654. {
  655. BOOL bCompare,
  656. bRead1,
  657. bRead2;
  658. HANDLE hFile1,
  659. hFile2;
  660. BYTE baBuffer1[4096],
  661. baBuffer2[4096];
  662. DWORD dwBytes1,
  663. dwBytes2,
  664. dwCount;
  665. // Open the files.
  666. //
  667. hFile1 = CreateFile(lpFile1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  668. hFile2 = CreateFile(lpFile2, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  669. // Make sure the files were opened.
  670. //
  671. if ( ( hFile1 != INVALID_HANDLE_VALUE ) &&
  672. ( hFile2 != INVALID_HANDLE_VALUE ) )
  673. {
  674. // Read all the data from the files.
  675. //
  676. do
  677. {
  678. // Read in the max buffer from each file.
  679. //
  680. bRead1 = ReadFile(hFile1, baBuffer1, sizeof(baBuffer1), &dwBytes1, NULL);
  681. bRead2 = ReadFile(hFile2, baBuffer2, sizeof(baBuffer2), &dwBytes2, NULL);
  682. // Make sure the reads didn't fail.
  683. //
  684. if ( bRead1 && bRead2 )
  685. {
  686. // Check to make sure the sizes are the same.
  687. //
  688. if ( bCompare = ( dwBytes1 == dwBytes2 ) )
  689. {
  690. // Make sure the buffers are identical.
  691. //
  692. for ( dwCount = 0; bCompare && ( dwCount < dwBytes1 ); dwCount++ )
  693. bCompare = ( baBuffer1[dwCount] == baBuffer2[dwCount] );
  694. }
  695. }
  696. else
  697. // If both the reads failed, we will return true.
  698. //
  699. bCompare = ( !bRead1 && !bRead2 );
  700. }
  701. while ( bCompare && bRead1 && bRead2 && dwBytes1 && dwBytes2 );
  702. }
  703. else
  704. // If both the files does not exist, then we will
  705. // return false.
  706. //
  707. bCompare = ( ( hFile1 != INVALID_HANDLE_VALUE ) && ( hFile2 != INVALID_HANDLE_VALUE ) );
  708. // Close the files.
  709. //
  710. if ( hFile1 == INVALID_HANDLE_VALUE )
  711. CloseHandle(hFile1);
  712. if ( hFile2 == INVALID_HANDLE_VALUE )
  713. CloseHandle(hFile2);
  714. return bCompare;
  715. }